Skip to content

Commit e22ee70

Browse files
authored
[cDAC] Change pointer data to be compile-time constant (#118543)
* Make cDAC pointer data initialize at compile-time * update StressLog to remove non-compile-time global
1 parent 5688eab commit e22ee70

File tree

10 files changed

+67
-35
lines changed

10 files changed

+67
-35
lines changed

docs/design/datacontracts/StressLog.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ Data descriptors used:
5353
| StressLog | TickFrequency | Number of ticks per second for stresslog timestamps |
5454
| StressLog | StartTimestamp | Timestamp when the stress log was started |
5555
| StressLog | ModuleOffset | Offset of the module in the stress log |
56+
| StressLog | Modules | Offset of the stress log's module table (if StressLogHasModuleTable is `1`) |
5657
| StressLog | Logs | Pointer to the thread-specific logs |
5758
| StressLogModuleDesc | BaseAddress | Base address of the module |
5859
| StressLogModuleDesc | Size | Size of the module |
@@ -80,7 +81,6 @@ Global variables used:
8081
| StressLogChunkSize | uint | Size of a stress log chunk |
8182
| StressLogMaxMessageSize | ulong | Maximum size of a stress log message |
8283
| StressLogHasModuleTable | byte | Whether the stress log module table is present |
83-
| StressLogModuleTable | pointer | Pointer to the stress log's module table (if StressLogHasModuleTable is `1`) |
8484

8585
```csharp
8686
bool HasStressLog()
@@ -216,12 +216,21 @@ protected TargetPointer GetFormatPointer(ulong formatOffset)
216216
return new TargetPointer(stressLog.ModuleOffset + formatOffset);
217217
}
218218

219-
TargetPointer moduleTable = target.ReadGlobalPointer(Constants.Globals.StressLogModuleTable);
219+
TargetPointer? moduleTable;
220+
if (!target.TryReadGlobalPointer(Constants.Globals.StressLogModuleTable, out moduleTable))
221+
{
222+
if (!target.TryReadGlobalPointer(Constants.Globals.StressLog, out TargetPointer? pStressLog))
223+
{
224+
throw new InvalidOperationException("StressLogModuleTable is not set and StressLog is not available, but StressLogHasModuleTable is set to 1.");
225+
}
226+
Data.StressLog stressLog = target.ProcessedData.GetOrAdd<Data.StressLog>(pStressLog.Value);
227+
moduleTable = stressLog.Modules ?? throw new InvalidOperationException("StressLogModuleTable is not set and StressLog does not contain a ModuleTable offset, but StressLogHasModuleTable is set to 1.");
228+
}
220229
uint moduleEntrySize = target.GetTypeInfo(DataType.StressLogModuleDesc).Size!.Value;
221230
uint maxModules = target.ReadGlobal<uint>(Constants.Globals.StressLogMaxModules);
222231
for (uint i = 0; i < maxModules; ++i)
223232
{
224-
StressLogModuleDesc module = new(Target, moduleTable + i * moduleEntrySize);
233+
StressLogModuleDesc module = new(Target, moduleTable.Value + i * moduleEntrySize);
225234
ulong relativeOffset = formatOffset - cumulativeOffset;
226235
if (relativeOffset < module.Size.Value)
227236
{

src/coreclr/clrdatadescriptors.cmake

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,13 @@ function(generate_data_descriptors)
7878

7979
# inherit definitions, include directories, and dependencies from the INTERFACE target
8080
target_link_libraries(${LIBRARY} PRIVATE ${DATA_DESCRIPTORS_INTERFACE_TARGET})
81+
82+
if(MSVC)
83+
# /Zc:externConstexpr is required to export constexpr variables
84+
# from the object file, otherwise the linker will not export them.
85+
# See https://learn.microsoft.com/en-us/cpp/build/reference/zc-externconstexpr
86+
# for more details.
87+
target_compile_options(${LIBRARY} PRIVATE /Zc:externConstexpr)
88+
endif(MSVC)
8189
endif()
8290
endfunction(generate_data_descriptors)

src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ struct ContractDescriptor
1818
const char *descriptor;
1919
const uint32_t pointer_data_count;
2020
uint32_t pad0;
21-
const uintptr_t *pointer_data;
21+
const void** pointer_data;
2222
};
2323

2424
// POINTER_DATA_NAME and CONTRACT_NAME are macros provided by
2525
// contractconfiguration.h which is configured by CMake
26-
extern const uintptr_t POINTER_DATA_NAME[];
26+
extern const void* POINTER_DATA_NAME[];
2727

2828
#if EXPORT_CONTRACT
2929
DLLEXPORT

src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ struct ContractDescriptor
1818
const char *descriptor;
1919
const uint32_t pointer_data_count;
2020
uint32_t pad0;
21-
const uintptr_t *pointer_data;
21+
const void** pointer_data;
2222
};
2323

2424
// POINTER_DATA_NAME and CONTRACT_NAME are macros provided by
2525
// contractconfiguration.h which is configured by CMake
26-
extern const uintptr_t POINTER_DATA_NAME[];
26+
extern const void* POINTER_DATA_NAME[];
2727

2828
// just the placeholder pointer
29-
const uintptr_t POINTER_DATA_NAME[] = { (uintptr_t)0 };
29+
const void* POINTER_DATA_NAME[] = { (void*)0 };
3030

3131
DLLEXPORT struct ContractDescriptor CONTRACT_NAME;
3232

src/coreclr/debug/datadescriptor-shared/contractpointerdata.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66

77
extern "C"
88
{
9-
// without an extern declaration, clang does not emit this global into the object file
10-
extern const uintptr_t POINTER_DATA_NAME[];
11-
12-
const uintptr_t POINTER_DATA_NAME[] = {
13-
(uintptr_t)0, // placeholder
14-
#define CDAC_GLOBAL_POINTER(name,value) (uintptr_t)(value),
15-
#define CDAC_GLOBAL_SUB_DESCRIPTOR(name,value) (uintptr_t)(value),
16-
#include "wrappeddatadescriptor.inc"
9+
// without an extern declaration, clang does not emit this global into the object file
10+
extern constexpr const void* POINTER_DATA_NAME[] = {
11+
(void*)0, // placeholder
12+
#define CDAC_GLOBAL_POINTER(name,value) (void*)(value),
13+
#define CDAC_GLOBAL_SUB_DESCRIPTOR(name,value) (void*)(value),
14+
#include "wrappeddatadescriptor.inc"
15+
};
1716
};
18-
}
17+

src/coreclr/inc/stresslog.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -396,23 +396,24 @@ inline BOOL StressLog::LogOn(unsigned facility, unsigned level)
396396
template<>
397397
struct cdac_offsets<StressLog>
398398
{
399-
static const size_t facilitiesToLog = offsetof(StressLog, facilitiesToLog);
400-
static const size_t levelToLog = offsetof(StressLog, levelToLog);
401-
static const size_t MaxSizePerThread = offsetof(StressLog, MaxSizePerThread);
402-
static const size_t MaxSizeTotal = offsetof(StressLog, MaxSizeTotal);
403-
static const size_t totalChunk = offsetof(StressLog, totalChunk);
404-
static const size_t logs = offsetof(StressLog, logs);
405-
static const size_t tickFrequency = offsetof(StressLog, tickFrequency);
406-
static const size_t startTimeStamp = offsetof(StressLog, startTimeStamp);
407-
static const size_t startTime = offsetof(StressLog, startTime);
408-
static const size_t moduleOffset = offsetof(StressLog, moduleOffset);
409-
static constexpr uint64_t MAX_MODULES = StressLog::MAX_MODULES;
399+
static constexpr size_t facilitiesToLog = offsetof(StressLog, facilitiesToLog);
400+
static constexpr size_t levelToLog = offsetof(StressLog, levelToLog);
401+
static constexpr size_t MaxSizePerThread = offsetof(StressLog, MaxSizePerThread);
402+
static constexpr size_t MaxSizeTotal = offsetof(StressLog, MaxSizeTotal);
403+
static constexpr size_t totalChunk = offsetof(StressLog, totalChunk);
404+
static constexpr size_t logs = offsetof(StressLog, logs);
405+
static constexpr size_t tickFrequency = offsetof(StressLog, tickFrequency);
406+
static constexpr size_t startTimeStamp = offsetof(StressLog, startTimeStamp);
407+
static constexpr size_t startTime = offsetof(StressLog, startTime);
408+
static constexpr size_t moduleOffset = offsetof(StressLog, moduleOffset);
409+
static constexpr size_t MAX_MODULES = StressLog::MAX_MODULES;
410+
static constexpr size_t modules = offsetof(StressLog, modules);
410411

411412
struct ModuleDesc
412413
{
413414
static constexpr size_t type_size = sizeof(StressLog::ModuleDesc);
414-
static const size_t baseAddress = offsetof(StressLog::ModuleDesc, baseAddress);
415-
static const size_t size = offsetof(StressLog::ModuleDesc, size);
415+
static constexpr size_t baseAddress = offsetof(StressLog::ModuleDesc, baseAddress);
416+
static constexpr size_t size = offsetof(StressLog::ModuleDesc, size);
416417
};
417418
};
418419

src/coreclr/vm/datadescriptor/datadescriptor.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ CDAC_TYPE_FIELD(StressLog, /* pointer */, Logs, cdac_offsets<StressLog>::logs)
317317
CDAC_TYPE_FIELD(StressLog, /* uint64 */, TickFrequency, cdac_offsets<StressLog>::tickFrequency)
318318
CDAC_TYPE_FIELD(StressLog, /* uint64 */, StartTimestamp, cdac_offsets<StressLog>::startTimeStamp)
319319
CDAC_TYPE_FIELD(StressLog, /* nuint */, ModuleOffset, cdac_offsets<StressLog>::moduleOffset)
320+
CDAC_TYPE_FIELD(StressLog, /* StressLogModuleDesc[] */, Modules, cdac_offsets<StressLog>::modules)
320321
CDAC_TYPE_END(StressLog)
321322

322323
CDAC_TYPE_BEGIN(StressLogModuleDesc)
@@ -908,7 +909,6 @@ CDAC_GLOBAL_POINTER(TlsIndexBase, &::_tls_index)
908909
CDAC_GLOBAL(StressLogEnabled, uint8, 1)
909910
CDAC_GLOBAL_POINTER(StressLog, &g_pStressLog)
910911
CDAC_GLOBAL(StressLogHasModuleTable, uint8, 1)
911-
CDAC_GLOBAL_POINTER(StressLogModuleTable, &g_pStressLog->modules)
912912
CDAC_GLOBAL(StressLogMaxModules, uint64, cdac_offsets<StressLog>::MAX_MODULES)
913913
CDAC_GLOBAL(StressLogChunkSize, uint32, STRESSLOG_CHUNK_SIZE)
914914
CDAC_GLOBAL(StressLogValidChunkSig, uint32, StressLogChunk::ValidChunkSig)

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StressLog.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,22 @@ private TargetPointer GetFormatPointer(ulong formatOffset)
112112
return new TargetPointer(stressLog.ModuleOffset.Value + formatOffset);
113113
}
114114

115-
TargetPointer moduleTable = target.ReadGlobalPointer(Constants.Globals.StressLogModuleTable);
115+
TargetPointer? moduleTable;
116+
if (!target.TryReadGlobalPointer(Constants.Globals.StressLogModuleTable, out moduleTable))
117+
{
118+
if (!target.TryReadGlobalPointer(Constants.Globals.StressLog, out TargetPointer? pStressLog))
119+
{
120+
throw new InvalidOperationException("StressLogModuleTable is not set and StressLog is not available, but StressLogHasModuleTable is set to 1.");
121+
}
122+
Data.StressLog stressLog = target.ProcessedData.GetOrAdd<Data.StressLog>(pStressLog.Value);
123+
moduleTable = stressLog.Modules ?? throw new InvalidOperationException("StressLogModuleTable is not set and StressLog does not contain a ModuleTable offset, but StressLogHasModuleTable is set to 1.");
124+
}
116125
uint moduleEntrySize = target.GetTypeInfo(DataType.StressLogModuleDesc).Size!.Value;
117126
uint maxModules = target.ReadGlobal<uint>(Constants.Globals.StressLogMaxModules);
118127
ulong cumulativeOffset = 0;
119128
for (uint i = 0; i < maxModules; ++i)
120129
{
121-
Data.StressLogModuleDesc module = target.ProcessedData.GetOrAdd<Data.StressLogModuleDesc>(moduleTable + i * moduleEntrySize);
130+
Data.StressLogModuleDesc module = target.ProcessedData.GetOrAdd<Data.StressLogModuleDesc>(moduleTable.Value + i * moduleEntrySize);
122131
ulong relativeOffset = formatOffset - cumulativeOffset;
123132
if (relativeOffset < module.Size.Value)
124133
{

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/StressLog.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ public StressLog(Target target, TargetPointer address)
2323
StartTimestamp = target.Read<ulong>(address + (ulong)type.Fields[nameof(StartTimestamp)].Offset);
2424
ModuleOffset = target.ReadNUInt(address + (ulong)type.Fields[nameof(ModuleOffset)].Offset);
2525

26+
if (type.Fields.ContainsKey(nameof(Modules)))
27+
Modules = target.ReadPointer(address + (ulong)type.Fields[nameof(Modules)].Offset);
28+
2629
Logs = target.ReadPointer(address + (ulong)type.Fields[nameof(Logs)].Offset);
2730
}
2831

@@ -42,5 +45,7 @@ public StressLog(Target target, TargetPointer address)
4245

4346
public TargetNUInt ModuleOffset { get; init; }
4447

48+
public TargetPointer? Modules { get; init; }
49+
4550
public TargetPointer Logs { get; init; }
4651
}

src/tools/StressLogAnalyzer/src/Program.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ private static ContractDescriptorParser.ContractDescriptor GetDescriptor(int str
520520
{
521521
Baseline = BaseContractDescriptor.Baseline,
522522
Version = BaseContractDescriptor.Version,
523-
Contracts = new(){ { "StressLog", stressLogVersion } },
523+
Contracts = new() { { "StressLog", stressLogVersion } },
524524
Types = BaseContractDescriptor.Types,
525525
Globals = BaseContractDescriptor.Globals,
526526
};
@@ -542,7 +542,8 @@ private static ContractDescriptorParser.ContractDescriptor GetDescriptor(int str
542542
"Logs": 24,
543543
"TickFrequency": 48,
544544
"StartTimestamp": 56,
545-
"ModuleOffset": 72
545+
"ModuleOffset": 72,
546+
"Modules": 80
546547
},
547548
"StressLogModuleDesc": {
548549
"!": 16,

0 commit comments

Comments
 (0)