Skip to content

Commit 7c62f67

Browse files
author
Max Charlamb
committed
Merge branch 'cdac-strings' into cdac-new-entrypoint
2 parents 32c7655 + 799e5d4 commit 7c62f67

File tree

18 files changed

+626
-373
lines changed

18 files changed

+626
-373
lines changed

docs/design/datacontracts/contract-descriptor.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ a JSON integer constant.
8383
"globals":
8484
{
8585
"FEATURE_COMINTEROP": 0,
86-
"s_pThreadStore": [ 0 ] // indirect from pointer data offset 0
86+
"s_pThreadStore": [ 0 ], // indirect from pointer data offset 0
87+
"RuntimeID": "windows-x64" // string value
8788
},
8889
"contracts": {"Thread": 1, "GCHandle": 1, "ThreadStore": 1}
8990
}

docs/design/datacontracts/data_descriptor.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,11 @@ The global values will be in an array, with each value described by a dictionary
212212

213213
* `"name": "global value name"` the name of the global value
214214
* `"type": "type name"` the type of the global value
215-
* optional `"value": VALUE | [ int ] | "unknown"` the value of the global value, or an offset in an auxiliary array containing the value or "unknown".
215+
* optional `"value": VALUE | [ int ] ` the value of the global value, or an offset in an auxiliary array containing the value.
216+
217+
The `VALUE` may be either a number of string. JSON numeric constants are always parsed as numbers. JSON strings are always parsed as strings and may additionally parse as a hex (with prefix `0x` or `0X`) or decimal number.
218+
Numeric constants must be within the range of the type of the global value.
216219

217-
The `VALUE` may be a JSON numeric constant integer or a string containing a signed or unsigned
218-
decimal or hex (with prefix `0x` or `0X`) integer constant. The constant must be within the range
219-
of the type of the global value.
220220

221221
**Compact format**:
222222

@@ -225,7 +225,8 @@ The global values will be in a dictionary, with each key being the name of a glo
225225
* `[VALUE | [int], "type name"]` the type and value of a global
226226
* `VALUE | [int]` just the value of a global
227227

228-
As in the regular format, `VALUE` is a numeric constant or a string containing an integer constant.
228+
`VALUE` may be either a number of string. JSON numeric constants are always parsed as numbers. JSON strings are always parsed as strings and may additionally parse as a hex (with prefix `0x` or `0X`) or decimal number.
229+
Numeric constants must be within the range of the type of the global value.
229230

230231
Note that a two element array is unambiguously "type and value", whereas a one-element array is
231232
unambiguously "indirect value".
@@ -288,7 +289,7 @@ The baseline is given in the "regular" format.
288289
],
289290
"globals": [
290291
{ "name": "FEATURE_EH_FUNCLETS", "type": "uint8", "value": "0" }, // baseline defaults value to 0
291-
{ "name": "FEATURE_COMINTEROP", "type", "uint8", "value": "1"},
292+
{ "name": "FEATURE_COMINTEROP", "type": "uint8", "value": "1"},
292293
{ "name": "s_pThreadStore", "type": "pointer" } // no baseline value
293294
]
294295
}
@@ -308,7 +309,8 @@ The following is an example of an in-memory descriptor that references the above
308309
"globals":
309310
{
310311
"FEATURE_COMINTEROP": 0,
311-
"s_pThreadStore": [ 0 ] // indirect from aux data offset 0
312+
"s_pThreadStore": [ 0 ], // indirect from aux data offset 0
313+
"RuntimeID": "windows-x64"
312314
}
313315
}
314316
```
@@ -332,6 +334,7 @@ And the globals will be:
332334
| FEATURE_COMINTEROP | uint8 | 0 |
333335
| FEATURE_EH_FUNCLETS | uint8 | 0 |
334336
| s_pThreadStore | pointer | 0x0100ffe0 |
337+
| RuntimeID | string |"windows-x64"|
335338

336339
The `FEATURE_EH_FUNCLETS` global's value comes from the baseline - not the in-memory data
337340
descriptor. By contrast, `FEATURE_COMINTEROP` comes from the in-memory data descriptor - with the

src/coreclr/debug/runtimeinfo/datadescriptor.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ struct GlobalPointerSpec
5353
uint32_t PointerDataIndex;
5454
};
5555

56+
struct GlobalStringSpec
57+
{
58+
uint32_t Name;
59+
uint32_t StringValue;
60+
};
61+
5662
#define CONCAT(token1,token2) token1 ## token2
5763
#define CONCAT4(token1, token2, token3, token4) token1 ## token2 ## token3 ## token4
5864

@@ -61,6 +67,7 @@ struct GlobalPointerSpec
6167
#define MAKE_FIELDTYPELEN_NAME(tyname,membername) CONCAT4(cdac_string_pool_membertypename__, tyname, __, membername)
6268
#define MAKE_GLOBALLEN_NAME(globalname) CONCAT(cdac_string_pool_globalname__, globalname)
6369
#define MAKE_GLOBALTYPELEN_NAME(globalname) CONCAT(cdac_string_pool_globaltypename__, globalname)
70+
#define MAKE_GLOBALVALUELEN_NAME(globalname) CONCAT(cdac_string_pool_globalvalue__, globalname)
6471

6572
// used to stringify the result of a macros expansion
6673
#define STRINGIFY(x) #x
@@ -76,6 +83,8 @@ struct CDacStringPoolSizes
7683
#define CDAC_TYPE_BEGIN(name) DECL_LEN(MAKE_TYPELEN_NAME(name), sizeof(#name))
7784
#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) DECL_LEN(MAKE_FIELDLEN_NAME(tyname,membername), sizeof(#membername)) \
7885
DECL_LEN(MAKE_FIELDTYPELEN_NAME(tyname,membername), sizeof(#membertyname))
86+
#define CDAC_GLOBAL_STRING(name, stringval) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) \
87+
DECL_LEN(MAKE_GLOBALVALUELEN_NAME(name), sizeof(#stringval))
7988
#define CDAC_GLOBAL_POINTER(name,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name))
8089
#define CDAC_GLOBAL(name,tyname,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) \
8190
DECL_LEN(MAKE_GLOBALTYPELEN_NAME(name), sizeof(#tyname))
@@ -89,6 +98,7 @@ struct CDacStringPoolSizes
8998
#define GET_FIELDTYPE_NAME(tyname,membername) offsetof(struct CDacStringPoolSizes, MAKE_FIELDTYPELEN_NAME(tyname,membername))
9099
#define GET_GLOBAL_NAME(globalname) offsetof(struct CDacStringPoolSizes, MAKE_GLOBALLEN_NAME(globalname))
91100
#define GET_GLOBALTYPE_NAME(globalname) offsetof(struct CDacStringPoolSizes, MAKE_GLOBALTYPELEN_NAME(globalname))
101+
#define GET_GLOBALSTRING_VALUE(globalname) offsetof(struct CDacStringPoolSizes, MAKE_GLOBALVALUELEN_NAME(globalname))
92102

93103
// count the types
94104
enum
@@ -128,6 +138,15 @@ enum
128138
#include "datadescriptor.h"
129139
};
130140

141+
// count the global strings
142+
enum
143+
{
144+
CDacBlobGlobalStringsCount =
145+
#define CDAC_GLOBALS_BEGIN() 0
146+
#define CDAC_GLOBAL_STRING(name,value) + 1
147+
#include "datadescriptor.h"
148+
};
149+
131150

132151
#define MAKE_TYPEFIELDS_TYNAME(tyname) CONCAT(CDacFieldsPoolTypeStart__, tyname)
133152

@@ -202,27 +221,31 @@ struct BinaryBlobDataDescriptor
202221
uint32_t GlobalLiteralValuesStart;
203222

204223
uint32_t GlobalPointersStart;
224+
uint32_t GlobalStringValuesStart;
205225
uint32_t NamesPoolStart;
206226

207227
uint32_t TypeCount;
208228
uint32_t FieldsPoolCount;
209229

210230
uint32_t GlobalLiteralValuesCount;
211231
uint32_t GlobalPointerValuesCount;
232+
uint32_t GlobalStringValuesCount;
212233

213234
uint32_t NamesPoolCount;
214235

215236
uint8_t TypeSpecSize;
216237
uint8_t FieldSpecSize;
217238
uint8_t GlobalLiteralSpecSize;
218239
uint8_t GlobalPointerSpecSize;
240+
uint8_t GlobalStringSpecSize;
219241
} Directory;
220242
uint32_t PlatformFlags;
221243
uint32_t BaselineName;
222244
struct TypeSpec Types[CDacBlobTypesCount];
223245
struct FieldSpec FieldsPool[CDacBlobFieldsPoolCount];
224246
struct GlobalLiteralSpec GlobalLiteralValues[CDacBlobGlobalLiteralsCount];
225247
struct GlobalPointerSpec GlobalPointerValues[CDacBlobGlobalPointersCount];
248+
struct GlobalStringSpec GlobalStringValues[CDacBlobGlobalStringsCount];
226249
uint8_t NamesPool[sizeof(struct CDacStringPoolSizes)];
227250
uint8_t EndMagic[4];
228251
};
@@ -247,16 +270,19 @@ struct MagicAndBlob BlobDataDescriptor = {
247270
/* .FieldsPoolStart = */ offsetof(struct BinaryBlobDataDescriptor, FieldsPool),
248271
/* .GlobalLiteralValuesStart = */ offsetof(struct BinaryBlobDataDescriptor, GlobalLiteralValues),
249272
/* .GlobalPointersStart = */ offsetof(struct BinaryBlobDataDescriptor, GlobalPointerValues),
273+
/* .GlobalStringValuesStart = */ offsetof(struct BinaryBlobDataDescriptor, GlobalStringValues),
250274
/* .NamesPoolStart = */ offsetof(struct BinaryBlobDataDescriptor, NamesPool),
251275
/* .TypeCount = */ CDacBlobTypesCount,
252276
/* .FieldsPoolCount = */ CDacBlobFieldsPoolCount,
253277
/* .GlobalLiteralValuesCount = */ CDacBlobGlobalLiteralsCount,
254278
/* .GlobalPointerValuesCount = */ CDacBlobGlobalPointersCount,
279+
/* .GlobalStringValuesCount = */ CDacBlobGlobalStringsCount,
255280
/* .NamesPoolCount = */ sizeof(struct CDacStringPoolSizes),
256281
/* .TypeSpecSize = */ sizeof(struct TypeSpec),
257282
/* .FieldSpecSize = */ sizeof(struct FieldSpec),
258283
/* .GlobalLiteralSpecSize = */ sizeof(struct GlobalLiteralSpec),
259284
/* .GlobalPointerSpecSize = */ sizeof(struct GlobalPointerSpec),
285+
/* .GlobalStringSpecSize = */ sizeof(struct GlobalStringSpec)
260286
},
261287
/* .PlatformFlags = */ (sizeof(void*) == 4 ? 0x02 : 0) | 0x01,
262288
/* .BaselineName = */ offsetof(struct CDacStringPoolSizes, cdac_string_pool_baseline_),
@@ -292,10 +318,16 @@ struct MagicAndBlob BlobDataDescriptor = {
292318
#include "datadescriptor.h"
293319
},
294320

321+
/* .GlobalStringValues = */ {
322+
#define CDAC_GLOBAL_STRING(name,value) { /* .Name = */ GET_GLOBAL_NAME(name), /* .Value = */ GET_GLOBALSTRING_VALUE(name) },
323+
#include "datadescriptor.h"
324+
},
325+
295326
/* .NamesPool = */ ("\0" // starts with a nul
296327
#define CDAC_BASELINE(name) name "\0"
297328
#define CDAC_TYPE_BEGIN(name) #name "\0"
298329
#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) #membername "\0" #membertyname "\0"
330+
#define CDAC_GLOBAL_STRING(name,value) #name "\0" #value "\0"
299331
#define CDAC_GLOBAL_POINTER(name,value) #name "\0"
300332
#define CDAC_GLOBAL(name,tyname,value) #name "\0" #tyname "\0"
301333
#include "datadescriptor.h"

src/coreclr/debug/runtimeinfo/datadescriptor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@
9898
#ifndef CDAC_GLOBAL_POINTER
9999
#define CDAC_GLOBAL_POINTER(globalname,addr)
100100
#endif
101+
#ifndef CDAC_GLOBAL_STRING
102+
#define CDAC_GLOBAL_STRING(globalname,stringval)
103+
#endif
101104
#ifndef CDAC_GLOBALS_END
102105
#define CDAC_GLOBALS_END()
103106
#endif
@@ -858,4 +861,5 @@ CDAC_GLOBALS_END()
858861
#undef CDAC_GLOBALS_BEGIN
859862
#undef CDAC_GLOBAL
860863
#undef CDAC_GLOBAL_POINTER
864+
#undef CDAC_GLOBAL_STRING
861865
#undef CDAC_GLOBALS_END

src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class DataDescriptorModel
2424
public uint PlatformFlags { get; }
2525
// The number of indirect globals plus 1 for the placeholder at index 0
2626
[JsonIgnore]
27-
public int PointerDataCount => 1 + Globals.Values.Count(g => g.Value.Indirect);
27+
public int PointerDataCount => 1 + Globals.Values.Count(g => g.Value.Kind == GlobalValue.KindEnum.Indirect);
2828

2929
private DataDescriptorModel(string baseline, IReadOnlyDictionary<string, TypeModel> types, IReadOnlyDictionary<string, GlobalModel> globals, IReadOnlyDictionary<string, int> contracts, uint platformFlags)
3030
{
@@ -36,6 +36,7 @@ private DataDescriptorModel(string baseline, IReadOnlyDictionary<string, TypeMod
3636
}
3737

3838
public const string PointerTypeName = "pointer";
39+
public const string StringTypeName = "string";
3940

4041
internal void DumpModel()
4142
{
@@ -274,6 +275,7 @@ public GlobalValue? Value
274275
}
275276
}
276277
}
278+
277279
internal sealed class FieldBuilder
278280
{
279281
private string _type = string.Empty;
@@ -331,19 +333,38 @@ public readonly struct TypeModel
331333
[JsonConverter(typeof(GlobalValueJsonConverter))]
332334
public readonly struct GlobalValue : IEquatable<GlobalValue>
333335
{
334-
public bool Indirect { get; private init; }
335-
public ulong Value { get; }
336-
public static GlobalValue MakeDirect(ulong value) => new GlobalValue(value);
337-
public static GlobalValue MakeIndirect(uint auxDataIdx) => new GlobalValue((ulong)auxDataIdx) { Indirect = true };
338-
private GlobalValue(ulong value) { Value = value; }
336+
public enum KindEnum
337+
{
338+
Direct,
339+
Indirect,
340+
String
341+
}
342+
343+
public KindEnum Kind { get; private init; }
344+
public ulong NumericValue { get; }
345+
public string StringValue { get; }
346+
public static GlobalValue MakeDirect(ulong value) => new GlobalValue(value) { Kind = KindEnum.Direct };
347+
public static GlobalValue MakeIndirect(uint auxDataIdx) => new GlobalValue((ulong)auxDataIdx) { Kind = KindEnum.Indirect };
348+
public static GlobalValue MakeString(string value) => new GlobalValue(value) { Kind = KindEnum.String };
349+
private GlobalValue(ulong value) { NumericValue = value; StringValue = string.Empty;}
350+
private GlobalValue(string value) { StringValue = value; }
339351

340-
public static bool operator ==(GlobalValue left, GlobalValue right) => left.Value == right.Value && left.Indirect == right.Indirect;
352+
public static bool operator ==(GlobalValue left, GlobalValue right) => left.Equals(right);
341353
public static bool operator !=(GlobalValue left, GlobalValue right) => !(left == right);
342354

343-
public bool Equals(GlobalValue other) => this == other;
344-
public override bool Equals(object? obj) => obj is GlobalValue value && this == value;
345-
public override int GetHashCode() => HashCode.Combine(Value, Indirect);
346-
public override string ToString() => Indirect ? $"Indirect({Value})" : $"0x{Value:x}";
355+
public bool Equals(GlobalValue other) => other.Kind == Kind && other.NumericValue == NumericValue && other.StringValue == StringValue;
356+
public override bool Equals(object? obj) => obj is GlobalValue value && Equals(value);
357+
public override int GetHashCode() => HashCode.Combine(Kind, NumericValue, StringValue);
358+
public override string ToString()
359+
{
360+
return Kind switch
361+
{
362+
KindEnum.Direct => $"0x{NumericValue:x}",
363+
KindEnum.Indirect => $"Indirect({NumericValue})",
364+
KindEnum.String => $"'{StringValue}'",
365+
_ => throw new InvalidOperationException("Unknown GlobalValue type")
366+
};
367+
}
347368
}
348369

349370
[JsonConverter(typeof(GlobalModelJsonConverter))]

src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalValueJsonConverter.cs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,25 @@ public override DataDescriptorModel.GlobalValue Read(ref Utf8JsonReader reader,
1515

1616
public override void Write(Utf8JsonWriter writer, DataDescriptorModel.GlobalValue value, JsonSerializerOptions options)
1717
{
18-
if (!value.Indirect)
18+
switch (value.Kind)
1919
{
20-
// no type: just write value as a number.
21-
// we always write as a string containing a hex number
22-
writer.WriteStringValue($"0x{value.Value:x}");
23-
}
24-
else
25-
{
26-
// pointer data index. write as a 1-element array containing a decimal number
27-
writer.WriteStartArray();
28-
writer.WriteNumberValue(value.Value);
29-
writer.WriteEndArray();
20+
case DataDescriptorModel.GlobalValue.KindEnum.Direct:
21+
// no type: just write value as a number.
22+
// we always write as a string containing a hex number
23+
writer.WriteStringValue($"0x{value.NumericValue:x}");
24+
break;
25+
case DataDescriptorModel.GlobalValue.KindEnum.Indirect:
26+
// pointer data index. write as a 1-element array containing a decimal number
27+
writer.WriteStartArray();
28+
writer.WriteNumberValue(value.NumericValue);
29+
writer.WriteEndArray();
30+
break;
31+
case DataDescriptorModel.GlobalValue.KindEnum.String:
32+
// string data. write as a JSON string value
33+
writer.WriteStringValue(value.StringValue);
34+
break;
35+
default:
36+
throw new InvalidOperationException("Unknown GlobalValue type");
3037
}
3138
}
3239
}

0 commit comments

Comments
 (0)