You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// Extension Methods (implemented in terms of other APIs)
39
+
boolIsFunclet(CodeBlockHandlecodeInfoHandle);
30
40
```
31
41
32
42
## Version 1
@@ -59,14 +69,18 @@ Data descriptors used:
59
69
|`RealCodeHeader`|`MethodDesc`| Pointer to the corresponding `MethodDesc`|
60
70
|`RealCodeHeader`|`NumUnwindInfos`| Number of Unwind Infos |
61
71
|`RealCodeHeader`|`UnwindInfos`| Start address of Unwind Infos |
72
+
|`RealCodeHeader`|`GCInfo`| Pointer to the GCInfo encoding |
62
73
|`Module`|`ReadyToRunInfo`| Pointer to the `ReadyToRunInfo` for the module |
74
+
|`ReadyToRunInfo`|`ReadyToRunHeader`| Pointer to the ReadyToRunHeader |
63
75
|`ReadyToRunInfo`|`CompositeInfo`| Pointer to composite R2R info - or itself for non-composite |
64
76
|`ReadyToRunInfo`|`NumRuntimeFunctions`| Number of `RuntimeFunctions`|
65
77
|`ReadyToRunInfo`|`RuntimeFunctions`| Pointer to an array of `RuntimeFunctions` - [see R2R format](../coreclr/botr/readytorun-format.md#readytorunsectiontyperuntimefunctions)|
66
78
|`ReadyToRunInfo`|`NumHotColdMap`| Number of entries in the `HotColdMap`|
67
79
|`ReadyToRunInfo`|`HotColdMap`| Pointer to an array of 32-bit integers - [see R2R format](../coreclr/botr/readytorun-format.md#readytorunsectiontypehotcoldmap-v80)|
68
80
|`ReadyToRunInfo`|`DelayLoadMethodCallThunks`| Pointer to an `ImageDataDirectory` for the delay load method call thunks |
69
81
|`ReadyToRunInfo`|`EntryPointToMethodDescMap`|`HashMap` of entry point addresses to `MethodDesc` pointers |
82
+
|`ReadyToRunHeader`|`MajorVersion`| ReadyToRun major version |
83
+
|`ReadyToRunHeader`|`MinorVersion`| ReadyToRun minor version |
70
84
|`ImageDataDirectory`|`VirtualAddress`| Virtual address of the image data directory |
71
85
|`ImageDataDirectory`|`Size`| Size of the data |
72
86
|`RuntimeFunction`|`BeginAddress`| Begin address of the function |
@@ -85,6 +99,7 @@ Global variables used:
85
99
|`HashMapSlotsPerBucket`| uint32 | Number of slots in each bucket of a `HashMap`|
86
100
|`HashMapValueMask`| uint64 | Bitmask used when storing values in a `HashMap`|
87
101
|`FeatureEHFunclets`| uint8 | 1 if EH funclets are enabled, 0 otherwise |
102
+
|`GCInfoVersion`| uint32 | JITted code GCInfo version |
88
103
89
104
Contracts used:
90
105
| Contract Name |
@@ -220,7 +235,7 @@ class CodeBlock
220
235
}
221
236
```
222
237
223
-
The `GetMethodDesc`and `GetStartAddress` APIs extract fields of the `CodeBlock`:
238
+
The `GetMethodDesc`, `GetStartAddress`, and `GetRelativeOffset` APIs extract fields of the `CodeBlock`:
/* find CodeBlock info for codeInfoHandle.Address*/
256
+
returninfo.RelativeOffset;
257
+
}
237
258
```
238
259
239
-
`GetUnwindInfo` gets the Windows style unwind data in the form of `RUNTIME_FUNCTION` which has a platform dependent implementation. The ExecutionManager delegates to the JitManager implementations as the unwind infos (`RUNTIME_FUNCTION`) are stored differently on jitted and R2R code.
260
+
`IExecutionManager.GetUnwindInfo` gets the Windows style unwind data in the form of `RUNTIME_FUNCTION` which has a platform dependent implementation. The ExecutionManager delegates to the JitManager implementations as the unwind infos (`RUNTIME_FUNCTION`) are stored differently on jitted and R2R code.
240
261
241
262
* For jitted code (`EEJitManager`) a list of sorted `RUNTIME_FUNCTION` are stored on the `RealCodeHeader` which is accessed in the same was as `GetMethodInfo` described above. The correct `RUNTIME_FUNCTION` is found by binary searching the list based on IP.
242
263
@@ -245,6 +266,19 @@ The `GetMethodDesc` and `GetStartAddress` APIs extract fields of the `CodeBlock`
245
266
Unwind info (`RUNTIME_FUNCTION`) use relative addressing. For managed code, these values are relative to the start of the code's containing range in the RangeSectionMap (described below). This could be the beginning of a `CodeHeap` for jitted code or the base address of the loaded image for ReadyToRun code.
246
267
`GetUnwindInfoBaseAddress` finds this base address for a given `CodeBlockHandle`.
247
268
269
+
`IExecutionManager.GetGCInfo` gets a pointer to the relevant GCInfo for a `CodeBlockHandle`. The ExecutionManager delegates to the JitManager implementations as the GCInfo is stored differently on jitted and R2R code.
270
+
271
+
* For jitted code (`EEJitManager`) a pointer to the `GCInfo` is stored on the `RealCodeHeader` which is accessed in the same was as `GetMethodInfo` described above. This can simply be returned as is. The `GCInfoVersion` is defined by the runtime global `GCInfoVersion`.
272
+
273
+
* For R2R code (`ReadyToRunJitManager`), the `GCInfo` is stored directly after the `UnwindData`. This in turn is found by looking up the `UnwindInfo` (`RUNTIME_FUNCTION`) and reading the `UnwindData` offset. We find the `UnwindInfo` as described above in `IExecutionManager.GetUnwindInfo`. Once we have the relevant unwind data, we calculate the size of the unwind data and return a pointer to the following byte (first byte of the GCInfo). The size of the unwind data is a platform specific. Currently only X86 is supported with a constant unwind data size of 32-bits.
274
+
* The `GCInfoVersion` of R2R code is mapped from the R2R MajorVersion and MinorVersion which is read from the ReadyToRunHeader which itself is read from the ReadyToRunInfo (can be found as in GetMethodInfo). The current GCInfoVersion mapping is:
275
+
* MajorVersion >= 11 and MajorVersion < 15 => 4
276
+
277
+
278
+
`IExecutionManager.GetFuncletStartAddress` finds the start of the code blocks funclet. This will be different than the methods start address `GetStartAddress` if the current code block is inside of a funclet. To find the funclet start address, we get the unwind info corresponding to the code block using `IExecutionManager.GetUnwindInfo`. We then parse the unwind info to find the begin address (relative to the unwind info base address) and return the unwind info base address + unwind info begin address.
279
+
280
+
`IsFunclet` is implemented in terms of `IExecutionManager.GetStartAddress` and `IExecutionManager.GetFuncletStartAddress`. If the values are the same, the code block handle is not a funclet. If they are different, it is a funclet.
281
+
248
282
### RangeSectionMap
249
283
250
284
The range section map logically partitions the entire 32-bit or 64-bit addressable space into chunks.
The x86 platform has some major differences to other platforms. In general this stems from the platform being older and not having a defined unwinding codes. Instead, to unwind managed frames, we rely on GCInfo associated with JITted code. For the unwind, we do not defer to a 'Windows like' native unwinder, instead the custom unwinder implementation was ported to managed code.
334
+
335
+
#### GCInfo Parsing
336
+
The GCInfo structure is encoded using a variety of formats to optimize for speed of decoding and size on disk. For information on decoding and parsing refer to [GC Information Encoding for x86](../coreclr/jit/jit-gc-info-x86.md).
337
+
338
+
#### Unwinding Algorithm
339
+
340
+
The x86 architecture uses a custom unwinding algorithm defined in `gc_unwind_x86.inl`. The cDAC uses a copy of this algorithm ported to managed code in `X86Unwinder.cs`.
341
+
342
+
Currently there isn't great documentation on the algorithm, beyond inspecting the implementations.
Copy file name to clipboardExpand all lines: src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IExecutionManager.cs
+5-1Lines changed: 5 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -18,8 +18,12 @@ public interface IExecutionManager : IContract
Copy file name to clipboardExpand all lines: src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.EEJitManager.cs
+24Lines changed: 24 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -85,6 +85,30 @@ public override TargetPointer GetUnwindInfo(RangeSection rangeSection, TargetCod
0 commit comments