Skip to content

Commit b0c2d75

Browse files
authored
[cDAC] Implement IXCLRDataModule APIs SOS uses to read line numbers (#114491)
* Implement cDAC support for the following IXCLRDataModule APIs: GetFlags, StartEnumExtents, EnumExtents, EndEnumExtents, and Request(DACDATAMODULEPRIV_REQUEST_GET_MODULEDATA…)
1 parent 56d8a63 commit b0c2d75

File tree

23 files changed

+642
-11
lines changed

23 files changed

+642
-11
lines changed

docs/design/datacontracts/Loader.md

+84-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ record struct ModuleLookupTables(
3131

3232
``` csharp
3333
ModuleHandle GetModuleHandle(TargetPointer module);
34+
TargetPointer GetRootAssembly();
3435
TargetPointer GetAssembly(ModuleHandle handle);
36+
TargetPointer GetPEAssembly(ModuleHandle handle);
37+
bool TryGetLoadedImageContents(ModuleHandle handle, out TargetPointer baseAddress, out uint size, out uint imageFlags);
38+
bool TryGetSymbolStream(ModuleHandle handle, out TargetPointer buffer, out uint size);
39+
bool IsProbeExtensionResultValid(ModuleHandle handle);
3540
ModuleFlags GetFlags(ModuleHandle handle);
3641
string GetPath(ModuleHandle handle);
3742
string GetFileName(ModuleHandle handle);
@@ -49,12 +54,14 @@ Data descriptors used:
4954
| Data Descriptor Name | Field | Meaning |
5055
| --- | --- | --- |
5156
| `Module` | `Assembly` | Assembly of the Module |
57+
| `Module` | `PEAssembly` | PEAssembly of the Module |
5258
| `Module` | `Base` | Pointer to start of PE file in memory |
5359
| `Module` | `Flags` | Assembly of the Module |
5460
| `Module` | `LoaderAllocator` | LoaderAllocator of the Module |
5561
| `Module` | `ThunkHeap` | Pointer to the thunk heap |
5662
| `Module` | `Path` | Path of the Module (UTF-16, null-terminated) |
5763
| `Module` | `FileName` | File name of the Module (UTF-16, null-terminated) |
64+
| `Module` | `GrowableSymbolStream` | Pointer to the in memory symbol stream |
5865
| `Module` | `FieldDefToDescMap` | Mapping table |
5966
| `Module` | `ManifestModuleReferencesMap` | Mapping table |
6067
| `Module` | `MemberRefToDescMap` | Mapping table |
@@ -64,18 +71,92 @@ Data descriptors used:
6471
| `ModuleLookupMap` | `TableData` | Start of the mapping table's data |
6572
| `ModuleLookupMap` | `SupportedFlagsMask` | Mask for flag bits on lookup map entries |
6673
| `ModuleLookupMap` | `Count` | Number of TargetPointer sized entries in this section of the map |
67-
| `ModuleLookupMap` | `Next` | Pointer to next ModuleLookupMap segment for this map
68-
| `Assembly` | `IsCollectible` | Flag indicating if this is module may be collected
74+
| `ModuleLookupMap` | `Next` | Pointer to next ModuleLookupMap segment for this map |
75+
| `Assembly` | `IsCollectible` | Flag indicating if this is module may be collected |
76+
| `PEAssembly` | `PEImage` | Pointer to the PEAssembly's PEImage |
77+
| `PEImage` | `LoadedImageLayout` | Pointer to the PEImage's loaded PEImageLayout |
78+
| `PEImage` | `ProbeExtensionResult` | PEImage's ProbeExtensionResult |
79+
| `ProbeExtensionResult` | `Type` | Type of ProbeExtensionResult |
80+
| `PEImageLayout` | `Base` | Base address of the image layout |
81+
| `PEImageLayout` | `Size` | Size of the image layout |
82+
| `PEImageLayout` | `Flags` | Flags associated with the PEImageLayout |
83+
| `CGrowableSymbolStream` | `Buffer` | Pointer to the raw symbol stream buffer start |
84+
| `CGrowableSymbolStream` | `Size` | Size of the raw symbol stream buffer |
85+
| `AppDomain` | `RootAssembly` | Pointer to the root assembly |
86+
87+
Global variables used:
88+
| Global Name | Type | Purpose |
89+
| --- | --- | --- |
90+
| `AppDomain` | TargetPointer | Pointer to the global AppDomain |
91+
6992

7093
``` csharp
7194
ModuleHandle GetModuleHandle(TargetPointer modulePointer)
7295
{
7396
return new ModuleHandle(modulePointer);
7497
}
7598

99+
TargetPointer GetRootAssembly()
100+
{
101+
TargetPointer appDomainPointer = _target.ReadGlobalPointer(Constants.Globals.AppDomain);
102+
AppDomain appDomain = // read AppDomain object starting at appDomainPointer
103+
return appDomain.RootAssembly;
104+
}
105+
76106
TargetPointer GetAssembly(ModuleHandle handle)
77107
{
78-
return target.ReadPointer(handle.Address + /* Module::Assrembly offset */);
108+
return target.ReadPointer(handle.Address + /* Module::Assembly offset */);
109+
}
110+
111+
TargetPointer GetPEAssembly(ModuleHandle handle)
112+
{
113+
return target.ReadPointer(handle.Address + /* Module::PEAssembly offset */);
114+
}
115+
116+
bool TryGetLoadedImageContents(ModuleHandle handle, out TargetPointer baseAddress, out uint size, out uint imageFlags)
117+
{
118+
baseAddress = TargetPointer.Null;
119+
size = 0;
120+
imageFlags = 0;
121+
122+
TargetPointer peAssembly = target.ReadPointer(handle.Address + /* Module::PEAssembly offset */);
123+
if (peAssembly == 0) return false; // no loaded PEAssembly
124+
125+
TargetPointer peImage = target.ReadPointer(peAssembly + /* PEAssembly::PEImage offset */);
126+
if(peImage == 0) return false; // no loaded PEImage
127+
128+
TargetPointer peImageLayout = target.ReadPointer(peImage + /* PEImage::LoadedImageLayout offset */);
129+
130+
baseAddress = target.ReadPointer(peImageLayout + /* PEImageLayout::Base offset */);
131+
size = target.Read<uint>(peImageLayout + /* PEImageLayout::Size offset */);
132+
imageFlags = target.Read<uint>(peImageLayout + /* PEImageLayout::Flags offset */);
133+
return true;
134+
}
135+
136+
bool TryGetSymbolStream(ModuleHandle handle, out TargetPointer buffer, out uint size)
137+
{
138+
buffer = TargetPointer.Null;
139+
size = 0;
140+
141+
TargetPointer growableSymbolStream = target.ReadPointer(handle.Address + /* Module::GrowableSymbolStream offset */);
142+
if (growableSymbolStream == 0) return false; // no GrowableSymbolStream found
143+
144+
buffer = target.ReadPointer(growableSymbolStream + /* CGrowableSymbolStream::Buffer offset */);
145+
size = target.Read<uint>(growableSymbolStream + /* CGrowableSymbolStream::Size offset */);
146+
return true;
147+
}
148+
149+
bool IsProbeExtensionResultValid(ModuleHandle handle)
150+
{
151+
TargetPointer peAssembly = target.ReadPointer(handle.Address + /* Module::PEAssembly offset */);
152+
if (peAssembly == 0) return false; // no loaded PEAssembly
153+
154+
TargetPointer peImage = target.ReadPointer(peAssembly + /* PEAssembly::PEImage offset */);
155+
if(peImage == 0) return false; // no loaded PEImage
156+
157+
TargetPointer probeExtensionResult = target.ReadPointer(peImage + /* PEImage::ProbeExtensionResult offset */);
158+
int type = target.Read<int>(probeExtensionResult + /* ProbeExtensionResult::Type offset */);
159+
return type != 0; // 0 is the invalid type. See assemblyprobeextension.h for details
79160
}
80161

81162
ModuleFlags GetFlags(ModuleHandle handle)

src/coreclr/debug/runtimeinfo/datadescriptor.h

+35
Original file line numberDiff line numberDiff line change
@@ -218,13 +218,15 @@ CDAC_TYPE_END(SyncTableEntry)
218218
CDAC_TYPE_BEGIN(Module)
219219
CDAC_TYPE_INDETERMINATE(Module)
220220
CDAC_TYPE_FIELD(Module, /*pointer*/, Assembly, cdac_data<Module>::Assembly)
221+
CDAC_TYPE_FIELD(Module, /*pointer*/, PEAssembly, cdac_data<Module>::PEAssembly)
221222
CDAC_TYPE_FIELD(Module, /*pointer*/, Base, cdac_data<Module>::Base)
222223
CDAC_TYPE_FIELD(Module, /*uint32*/, Flags, cdac_data<Module>::Flags)
223224
CDAC_TYPE_FIELD(Module, /*pointer*/, LoaderAllocator, cdac_data<Module>::LoaderAllocator)
224225
CDAC_TYPE_FIELD(Module, /*pointer*/, DynamicMetadata, cdac_data<Module>::DynamicMetadata)
225226
CDAC_TYPE_FIELD(Module, /*pointer*/, Path, cdac_data<Module>::Path)
226227
CDAC_TYPE_FIELD(Module, /*pointer*/, FileName, cdac_data<Module>::FileName)
227228
CDAC_TYPE_FIELD(Module, /*pointer*/, ReadyToRunInfo, cdac_data<Module>::ReadyToRunInfo)
229+
CDAC_TYPE_FIELD(Module, /*pointer*/, GrowableSymbolStream, cdac_data<Module>::GrowableSymbolStream)
228230

229231
CDAC_TYPE_FIELD(Module, /*pointer*/, FieldDefToDescMap, cdac_data<Module>::FieldDefToDescMap)
230232
CDAC_TYPE_FIELD(Module, /*pointer*/, ManifestModuleReferencesMap, cdac_data<Module>::ManifestModuleReferencesMap)
@@ -249,6 +251,39 @@ CDAC_TYPE_FIELD(Assembly, /*uint8*/, IsCollectible, cdac_data<Assembly>::IsColle
249251
#endif
250252
CDAC_TYPE_END(Assembly)
251253

254+
CDAC_TYPE_BEGIN(PEAssembly)
255+
CDAC_TYPE_INDETERMINATE(PEAssembly)
256+
CDAC_TYPE_FIELD(PEAssembly, /*pointer*/, PEImage, cdac_data<PEAssembly>::PEImage)
257+
CDAC_TYPE_END(PEAssembly)
258+
259+
CDAC_TYPE_BEGIN(PEImage)
260+
CDAC_TYPE_INDETERMINATE(PEImage)
261+
CDAC_TYPE_FIELD(PEImage, /*pointer*/, LoadedImageLayout, cdac_data<PEImage>::LoadedImageLayout)
262+
CDAC_TYPE_FIELD(PEImage, /*ProbeExtensionResult*/, ProbeExtensionResult, cdac_data<PEImage>::ProbeExtensionResult)
263+
CDAC_TYPE_END(PEImage)
264+
265+
CDAC_TYPE_BEGIN(PEImageLayout)
266+
CDAC_TYPE_FIELD(PEImageLayout, /*pointer*/, Base, cdac_data<PEImageLayout>::Base)
267+
CDAC_TYPE_FIELD(PEImageLayout, /*uint32*/, Size, cdac_data<PEImageLayout>::Size)
268+
CDAC_TYPE_FIELD(PEImageLayout, /*uint32*/, Flags, cdac_data<PEImageLayout>::Flags)
269+
CDAC_TYPE_END(PEImageLayout)
270+
271+
CDAC_TYPE_BEGIN(CGrowableSymbolStream)
272+
CDAC_TYPE_INDETERMINATE(CGrowableSymbolStream)
273+
CDAC_TYPE_FIELD(CGrowableSymbolStream, /*pointer*/, Buffer, cdac_data<CGrowableStream>::Buffer)
274+
CDAC_TYPE_FIELD(CGrowableSymbolStream, /*uint32*/, Size, cdac_data<CGrowableStream>::Size)
275+
CDAC_TYPE_END(CGrowableSymbolStream)
276+
277+
CDAC_TYPE_BEGIN(ProbeExtensionResult)
278+
CDAC_TYPE_INDETERMINATE(ProbeExtensionResult)
279+
CDAC_TYPE_FIELD(ProbeExtensionResult, /*int32*/, Type, offsetof(ProbeExtensionResult, Type))
280+
CDAC_TYPE_END(ProbeExtensionResult)
281+
282+
CDAC_TYPE_BEGIN(AppDomain)
283+
CDAC_TYPE_INDETERMINATE(AppDomain)
284+
CDAC_TYPE_FIELD(AppDomain, /*pointer*/, RootAssembly, cdac_data<AppDomain>::RootAssembly)
285+
CDAC_TYPE_END(AppDomain)
286+
252287
// RuntimeTypeSystem
253288

254289
CDAC_TYPE_BEGIN(MethodTable)

src/coreclr/inc/assemblyprobeextension.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
class ProbeExtensionResult
1111
{
1212
public:
13-
enum class Type
13+
enum class Type : int32_t
1414
{
1515
Invalid,
1616
Bundle,

src/coreclr/inc/pedecoder.h

+5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ typedef DPTR(IMAGE_COR20_HEADER) PTR_IMAGE_COR20_HEADER;
5252

5353
class Module;
5454

55+
template<typename T> struct cdac_data;
56+
5557
// --------------------------------------------------------------------------------
5658
// RVA definition
5759
// --------------------------------------------------------------------------------
@@ -405,6 +407,9 @@ class PEDecoder
405407
PTR_IMAGE_NT_HEADERS m_pNTHeaders;
406408
PTR_IMAGE_COR20_HEADER m_pCorHeader;
407409
PTR_READYTORUN_HEADER m_pReadyToRunHeader;
410+
411+
// to allow inherited classes to access, friend to all specializations of cdac_data
412+
template<typename U> friend struct ::cdac_data;
408413
};
409414

410415
//

src/coreclr/inc/stgpool.h

+11
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class StgStringPool;
4949
class StgBlobPool;
5050
class StgCodePool;
5151

52+
template<typename T> struct cdac_data;
53+
5254
// Perform binary search on index table.
5355
//
5456
class RIDBinarySearch : public CBinarySearch<UINT32>
@@ -1500,6 +1502,15 @@ class CGrowableStream : public IStream
15001502
IStream ** ppstm);
15011503

15021504
#endif // DACCESS_COMPILE
1505+
1506+
friend struct cdac_data<CGrowableStream>;
15031507
}; // class CGrowableStream
15041508

1509+
template<>
1510+
struct cdac_data<CGrowableStream>
1511+
{
1512+
static constexpr size_t Buffer = offsetof(CGrowableStream, m_swBuffer);
1513+
static constexpr size_t Size = offsetof(CGrowableStream, m_dwBufferSize);
1514+
};
1515+
15051516
#endif // __StgPool_h__

src/coreclr/vm/appdomain.hpp

+8
Original file line numberDiff line numberDiff line change
@@ -1613,8 +1613,16 @@ class AppDomain final
16131613
TieredCompilationManager m_tieredCompilationManager;
16141614

16151615
#endif
1616+
1617+
friend struct cdac_data<AppDomain>;
16161618
}; // class AppDomain
16171619

1620+
template<>
1621+
struct cdac_data<AppDomain>
1622+
{
1623+
static constexpr size_t RootAssembly = offsetof(AppDomain, m_pRootAssembly);
1624+
};
1625+
16181626
typedef DPTR(class SystemDomain) PTR_SystemDomain;
16191627

16201628
class SystemDomain final

src/coreclr/vm/ceeload.h

+2
Original file line numberDiff line numberDiff line change
@@ -1669,13 +1669,15 @@ template<>
16691669
struct cdac_data<Module>
16701670
{
16711671
static constexpr size_t Assembly = offsetof(Module, m_pAssembly);
1672+
static constexpr size_t PEAssembly = offsetof(Module, m_pPEAssembly);
16721673
static constexpr size_t Base = offsetof(Module, m_baseAddress);
16731674
static constexpr size_t Flags = offsetof(Module, m_dwTransientFlags);
16741675
static constexpr size_t LoaderAllocator = offsetof(Module, m_loaderAllocator);
16751676
static constexpr size_t DynamicMetadata = offsetof(Module, m_pDynamicMetadata);
16761677
static constexpr size_t Path = offsetof(Module, m_path);
16771678
static constexpr size_t FileName = offsetof(Module, m_fileName);
16781679
static constexpr size_t ReadyToRunInfo = offsetof(Module, m_pReadyToRunInfo);
1680+
static constexpr size_t GrowableSymbolStream = offsetof(Module, m_pIStreamSym);
16791681

16801682
// Lookup map pointers
16811683
static constexpr size_t FieldDefToDescMap = offsetof(Module, m_FieldDefToDescMap);

src/coreclr/vm/peassembly.h

+8
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,16 @@ class PEAssembly final
434434
// assembly that created the dynamic assembly. If the creator assembly is dynamic itself, then its fallback
435435
// load context would be propagated to the assembly being dynamically generated.
436436
PTR_AssemblyBinder m_pFallbackBinder;
437+
438+
friend struct cdac_data<PEAssembly>;
437439
}; // class PEAssembly
438440

441+
template<>
442+
struct cdac_data<PEAssembly>
443+
{
444+
static constexpr size_t PEImage = offsetof(PEAssembly, m_PEImage);
445+
};
446+
439447
typedef ReleaseHolder<PEAssembly> PEAssemblyHolder;
440448

441449
#endif // PEASSEMBLY_H_

src/coreclr/vm/peimage.h

+11
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "sstring.h"
2020
#include "holder.h"
2121
#include <assemblyprobeextension.h>
22+
#include "cdacdata.h"
2223

2324
class SimpleRWLock;
2425
// --------------------------------------------------------------------------------
@@ -316,6 +317,16 @@ class PEImage final
316317
SimpleRWLock *m_pLayoutLock;
317318
PTR_PEImageLayout m_pLayouts[IMAGE_COUNT];
318319
IMDInternalImport* m_pMDImport;
320+
321+
friend struct cdac_data<PEImage>;
322+
};
323+
324+
template<>
325+
struct cdac_data<PEImage>
326+
{
327+
// The loaded PEImageLayout is m_pLayouts[IMAGE_LOADED]
328+
static constexpr size_t LoadedImageLayout = offsetof(PEImage, m_pLayouts) + sizeof(PTR_PEImageLayout);
329+
static constexpr size_t ProbeExtensionResult = offsetof(PEImage, m_probeExtensionResult);
319330
};
320331

321332
FORCEINLINE void PEImageRelease(PEImage *i)

src/coreclr/vm/peimagelayout.h

+10
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ class PEImageLayout : public PEDecoder
7272
Volatile<LONG> m_refCount;
7373
public:
7474
PEImage* m_pOwner;
75+
76+
friend struct cdac_data<PEImageLayout>;
77+
};
78+
79+
template<>
80+
struct cdac_data<PEImageLayout>
81+
{
82+
static constexpr size_t Base = offsetof(PEImageLayout, m_base);
83+
static constexpr size_t Size = offsetof(PEImageLayout, m_size);
84+
static constexpr size_t Flags = offsetof(PEImageLayout, m_flags);
7585
};
7686

7787
typedef ReleaseHolder<PEImageLayout> PEImageLayoutHolder;

src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ILoader.cs

+5
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,12 @@ public interface ILoader : IContract
3838

3939
ModuleHandle GetModuleHandle(TargetPointer modulePointer) => throw new NotImplementedException();
4040

41+
TargetPointer GetRootAssembly() => throw new NotImplementedException();
4142
TargetPointer GetAssembly(ModuleHandle handle) => throw new NotImplementedException();
43+
TargetPointer GetPEAssembly(ModuleHandle handle) => throw new NotImplementedException();
44+
bool TryGetLoadedImageContents(ModuleHandle handle, out TargetPointer baseAddress, out uint size, out uint imageFlags) => throw new NotImplementedException();
45+
bool TryGetSymbolStream(ModuleHandle handle, out TargetPointer buffer, out uint size) => throw new NotImplementedException();
46+
bool IsProbeExtensionResultValid(ModuleHandle handle) => throw new NotImplementedException();
4247
ModuleFlags GetFlags(ModuleHandle handle) => throw new NotImplementedException();
4348
string GetPath(ModuleHandle handle) => throw new NotImplementedException();
4449
string GetFileName(ModuleHandle handle) => throw new NotImplementedException();

src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/DataType.cs

+6
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,13 @@ public enum DataType
3030
RuntimeThreadLocals,
3131
Module,
3232
ModuleLookupMap,
33+
AppDomain,
3334
Assembly,
35+
PEAssembly,
36+
PEImage,
37+
PEImageLayout,
38+
CGrowableSymbolStream,
39+
ProbeExtensionResult,
3440
MethodTable,
3541
EEClass,
3642
ArrayClass,

0 commit comments

Comments
 (0)