Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c342e64
Re-enable, with a dmb, and change the stub examination logic to use a…
davidwrighton May 16, 2025
226cc59
Add the new logic for handling the disasm comparison in the DAC to th…
davidwrighton May 17, 2025
5388a3d
Merge branch 'main' of github.com:dotnet/runtime into enable_FEATURE_…
davidwrighton May 19, 2025
36e0ec1
More updates to latest
davidwrighton May 19, 2025
279a458
Add cDAC support
davidwrighton May 20, 2025
eca7820
Merge branch 'main' of github.com:dotnet/runtime into enable_FEATURE_…
davidwrighton May 20, 2025
3233cd5
Adjust to having the stub templates back
davidwrighton May 20, 2025
8557dea
Merge branch 'main' into enable_FEATURE_STUBPRECODE_DYNAMIC_HELPERS_a…
davidwrighton May 21, 2025
6c07b89
Update src/coreclr/vm/precode.h
davidwrighton May 21, 2025
43e29b9
Update docs/design/datacontracts/PrecodeStubs.md
davidwrighton May 21, 2025
721be9e
Apply suggestions from code review
davidwrighton May 21, 2025
fca72ac
Issue issue around code copilot found
davidwrighton May 21, 2025
051e071
Changes to make StubPrecode have the write barrier on the writer side
davidwrighton May 22, 2025
59324fd
Add memory ordering protection for FixupPrecode
davidwrighton May 23, 2025
9f86bc1
Merge branch 'main' of github.com:dotnet/runtime into enable_FEATURE_…
davidwrighton May 23, 2025
870e7cf
Fix build on various platforms, and reduce incorrect assert
davidwrighton May 27, 2025
bc9bb86
Fix assertions
davidwrighton May 27, 2025
07df9b1
Fix build break
davidwrighton May 29, 2025
7421c04
Fix copy/paste thinko
davidwrighton May 29, 2025
f2c941d
Fix WASM build
davidwrighton May 29, 2025
2af00ef
Merge branch 'main' into enable_FEATURE_STUBPRECODE_DYNAMIC_HELPERS_a…
davidwrighton Jun 2, 2025
54b3501
Update src/coreclr/vm/riscv64/thunktemplates.S
davidwrighton Jun 11, 2025
4d59a8e
Merge branch 'main' of https://github.com/dotnet/runtime into enable_…
davidwrighton Jul 1, 2025
563ca30
Merge branch 'main' into enable_FEATURE_STUBPRECODE_DYNAMIC_HELPERS_a…
davidwrighton Jul 1, 2025
3cfe122
Update relative offsets for Loongarch and Riscv
davidwrighton Jul 2, 2025
fda796a
Use alternative barrier approach on Arm64
davidwrighton Jul 2, 2025
306ae1b
Merge branch 'enable_FEATURE_STUBPRECODE_DYNAMIC_HELPERS_again' of ht…
davidwrighton Jul 2, 2025
887c885
Try slight variation
davidwrighton Jul 2, 2025
1a8c6b0
Go back to a simple dmb. Seems to have the same perf as a stlr,ldar p…
davidwrighton Jul 2, 2025
a207c9c
Use FlushInstructionCache to protect stub reads instead of using a ba…
davidwrighton Jul 3, 2025
9c17ab8
Remove hallucinations
davidwrighton Jul 3, 2025
71b3876
Missed removing one dmb
davidwrighton Jul 4, 2025
f614223
Feedback from @janvorli
davidwrighton Jul 7, 2025
854fd3e
Address feedback
davidwrighton Jul 8, 2025
0689a0b
Retrict dynamic helpers to iOS/Catalyst scenarios
davidwrighton Jul 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 84 additions & 8 deletions docs/design/datacontracts/PrecodeStubs.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,32 @@ This contract provides support for examining [precode](../coreclr/botr/method-de
TargetPointer GetMethodDescFromStubAddress(TargetCodePointer entryPoint);
```

## Version 1 and 2
## Version 1, 2, and 3

Data descriptors used:
| Data Descriptor Name | Field | Meaning |
| --- | --- | --- |
| PrecodeMachineDescriptor | OffsetOfPrecodeType | See `ReadPrecodeType` |
| PrecodeMachineDescriptor | ShiftOfPrecodeType | See `ReadPrecodeType` |
| PrecodeMachineDescriptor | ReadWidthOfPrecodeType | See `ReadPrecodeType` |
| PrecodeMachineDescriptor | OffsetOfPrecodeType | See `ReadPrecodeType` (Version 1 and 2 only) |
| PrecodeMachineDescriptor | ShiftOfPrecodeType | See `ReadPrecodeType` (Version 1 and 2 only) |
| PrecodeMachineDescriptor | ReadWidthOfPrecodeType | See `ReadPrecodeType` (Version 1 and 2 only) |
| PrecodeMachineDescriptor | StubCodePageSize | Size of a precode code page (in bytes) |
| PrecodeMachineDescriptor | CodePointerToInstrPointerMask | mask to apply to code pointers to get an address (see arm32 note)
| PrecodeMachineDescriptor | StubPrecodeType | precode sort byte for stub precodes |
| PrecodeMachineDescriptor | HasPInvokeImportPrecode | 1 if platform supports PInvoke precode stubs |
| PrecodeMachineDescriptor | PInvokeImportPrecodeType| precode sort byte for PInvoke precode stubs, if supported |
| PrecodeMachineDescriptor | PInvokeImportPrecodeType | precode sort byte for PInvoke precode stubs, if supported |
| PrecodeMachineDescriptor | HasFixupPrecode | 1 if platform supports fixup precode stubs |
| PrecodeMachineDescriptor | FixupPrecodeType| precode sort byte for fixup precode stubs, if supported |
| PrecodeMachineDescriptor | FixupPrecodeType | precode sort byte for fixup precode stubs, if supported |
| PrecodeMachineDescriptor | ThisPointerRetBufPrecodeType | precode sort byte for this pointer ret buf precodes |
| PrecodeMachineDescriptor | FixupStubPrecodeSize | Byte size of `FixupBytes` and `FixupIgnoredBytes` (Version 3 only) |
| PrecodeMachineDescriptor | FixupBytes | Assembly code of a FixupStub (Version 3 only) |
| PrecodeMachineDescriptor | FixupIgnoredBytes | Bytes to ignore of when comparing `FixupBytes` to an actual block of memory in the target process. (Version 3 only) |
| PrecodeMachineDescriptor | StubPrecodeSize | Byte size of `StubBytes` and `StubIgnoredBytes` (Version 3 only) |
| PrecodeMachineDescriptor | StubBytes | Assembly code of a FixupStub (Version 3 only) |
| PrecodeMachineDescriptor | StubIgnoredBytes | Bytes to ignore of when comparing `StubBytes` to an actual block of memory in the target process. (Version 3 only) |
| PrecodeMachineDescriptor | FixupCodeOffset | Offset of second entrypoint into a `FixupStub` (Present in data for Version 3 and above only.) |
| PrecodeMachineDescriptor | InterpreterPrecodeType | precode sort byte for the entrypoint into the interpreter (Version 3 only) |
| PrecodeMachineDescriptor | UMEntryPrecodeType | precode sort byte for the entrypoint into the interpreter (Version 3 only) |
| PrecodeMachineDescriptor | DynamicHelperPrecodeType | precode sort byte for the entrypoint into a dynamic helper (Version 3 only) |
| StubPrecodeData | MethodDesc | pointer to the MethodDesc associated with this stub precode (Version 1 only) |
| StubPrecodeData | SecretParam | pointer to the MethodDesc associated with this stub precode or a second stub data pointer for other types (Version 2 only) |
| StubPrecodeData | Type | precise sort of stub precode |
Expand All @@ -44,12 +54,75 @@ Contracts used:
| --- |
| `PlatformMetadata` |

### Determining the precode type
### Determining the precode type (Version 3)
``` csharp
private bool ReadBytesAndCompare(TargetPointer instrAddress, byte[] expectedBytePattern, byte[] bytesToIgnore)
{
byte[] localCopy = new byte[expectedBytePattern.Length];
for (int i = 0; i < expectedBytePattern.Length; i++)
{
if (bytesToIgnore[i] == 0)
{
byte targetBytePattern = _target.Read<byte>(instrAddress + i);
if (expectedBytePattern[i] != targetBytePattern)
{
return false;
}
}
}

return true;
}
private KnownPrecodeType? TryGetKnownPrecodeType(TargetPointer instrAddress)
{
KnownPrecodeType? basicPrecodeType = default;
if (ReadBytesAndCompare(instrAddress, MachineDescriptor.StubBytes, MachineDescriptor.StubIgnoredBytes))
{
// get the actual type from the StubPrecodeData
Data.StubPrecodeData stubPrecodeData = GetStubPrecodeData(instrAddress);
byte exactPrecodeType = stubPrecodeData.Type;
if (exactPrecodeType == 0)
return null;

if (exactPrecodeType == MachineDescriptor.StubPrecodeType)
{
return KnownPrecodeType.Stub;
}
else if (MachineDescriptor.PInvokeImportPrecodeType is byte compareByte1 && compareByte1 == exactPrecodeType)
{
return KnownPrecodeType.PInvokeImport;
}
else if (MachineDescriptor.ThisPointerRetBufPrecodeType is byte compareByte2 && compareByte2 == exactPrecodeType)
{
return KnownPrecodeType.ThisPtrRetBuf;
}
else if (MachineDescriptor.UMEntryPrecodeType is byte compareByte3 && compareByte3 == exactPrecodeType)
{
return KnownPrecodeType.UMEntry;
}
else if (MachineDescriptor.InterpreterPrecodeType is byte compareByte4 && compareByte4 == exactPrecodeType)
{
return KnownPrecodeType.Interpreter;
}
else if (MachineDescriptor.DynamicHelperPrecodeType is byte compareByte5 && compareByte5 == exactPrecodeType)
{
return KnownPrecodeType.DynamicHelper;
}
}
else if (ReadBytesAndCompare(instrAddress, MachineDescriptor.FixupBytes, MachineDescriptor.FixupIgnoredBytes))
{
return KnownPrecodeType.Fixup;
}
return null;
}
```

### Determining the precode type (Version 1 and 2)

An initial approximation of the precode type relies on a particular pattern at a known offset from the precode entrypoint.
The precode type is expected to be encoded as an immediate. On some platforms the value is spread over multiple instruction bytes and may need to be right-shifted.

```
```csharp
private byte ReadPrecodeType(TargetPointer instrPointer)
{
if (MachineDescriptor.ReadWidthOfPrecodeType == 1)
Expand Down Expand Up @@ -124,6 +197,9 @@ After the initial precode type is determined, for stub precodes a refined precod
PInvokeImport, // also known as NDirectImport in the runtime
Fixup,
ThisPtrRetBuf,
UMEntry,
DynamicHelper,
Interpreter
}

internal abstract class ValidPrecode
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/clrfeatures.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ if (CLR_CMAKE_TARGET_WIN32)
set(FEATURE_TYPEEQUIVALENCE 1)
endif(CLR_CMAKE_TARGET_WIN32)

if (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64)
set(FEATURE_STUBPRECODE_DYNAMIC_HELPERS 1)
endif()

if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS OR CLR_CMAKE_TARGET_ARCH_WASM)
set(FEATURE_CORECLR_CACHED_INTERFACE_DISPATCH 1)
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/debug/daccess/enummem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <interoplibabi.h>
#endif // FEATURE_COMWRAPPERS

#include "cdacplatformmetadata.hpp"

extern HRESULT GetDacTableAddress(ICorDebugDataTarget* dataTarget, ULONG64 baseAddress, PULONG64 dacTableAddress);

#if defined(DAC_MEASURE_PERF)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/debug/ee/dactable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "../../vm/common.h"
#include "../../vm/gcenv.h"
#include "../../vm/ecall.h"
#include "../../vm/cdacplatformmetadata.hpp"

#ifdef DEBUGGING_SUPPORTED

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/debug/runtimeinfo/contracts.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"Loader": 1,
"Object": 1,
"PlatformMetadata": 1,
"PrecodeStubs": 2,
"PrecodeStubs": 3,
"ReJIT": 1,
"RuntimeInfo": 1,
"RuntimeTypeSystem": 1,
Expand Down
25 changes: 20 additions & 5 deletions src/coreclr/debug/runtimeinfo/datadescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -523,20 +523,35 @@ CDAC_TYPE_END(MethodDescVersioningState)

CDAC_TYPE_BEGIN(PrecodeMachineDescriptor)
CDAC_TYPE_INDETERMINATE(PrecodeMachineDescriptor)
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, ReadWidthOfPrecodeType, offsetof(PrecodeMachineDescriptor, ReadWidthOfPrecodeType))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, ShiftOfPrecodeType, offsetof(PrecodeMachineDescriptor, ShiftOfPrecodeType))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, OffsetOfPrecodeType, offsetof(PrecodeMachineDescriptor, OffsetOfPrecodeType))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, InvalidPrecodeType, offsetof(PrecodeMachineDescriptor, InvalidPrecodeType))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, StubPrecodeType, offsetof(PrecodeMachineDescriptor, StubPrecodeType))
#ifdef HAS_NDIRECT_IMPORT_PRECODE
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, PInvokeImportPrecodeType, offsetof(PrecodeMachineDescriptor, PInvokeImportPrecodeType))
#endif

#ifdef HAS_FIXUP_PRECODE
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, FixupPrecodeType, offsetof(PrecodeMachineDescriptor, FixupPrecodeType))
#endif
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, FixupCodeOffset, offsetof(PrecodeMachineDescriptor, FixupCodeOffset))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, FixupStubPrecodeSize, offsetof(PrecodeMachineDescriptor, FixupStubPrecodeSize))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*byte[]*/, FixupBytes, offsetof(PrecodeMachineDescriptor, FixupBytes))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*byte[]*/, FixupIgnoredBytes, offsetof(PrecodeMachineDescriptor, FixupIgnoredBytes))
#endif // HAS_FIXUP_PRECODE

CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, StubPrecodeSize, offsetof(PrecodeMachineDescriptor, StubPrecodeSize))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, StubPrecodeType, offsetof(PrecodeMachineDescriptor, StubPrecodeType))

CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*byte[]*/, StubBytes, offsetof(PrecodeMachineDescriptor, StubBytes))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*byte[]*/, StubIgnoredBytes, offsetof(PrecodeMachineDescriptor, StubIgnoredBytes))

#ifdef HAS_THISPTR_RETBUF_PRECODE
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, ThisPointerRetBufPrecodeType, offsetof(PrecodeMachineDescriptor, ThisPointerRetBufPrecodeType))
#endif
#ifdef FEATURE_INTERPRETER
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, InterpreterPrecodeType, offsetof(PrecodeMachineDescriptor, InterpreterPrecodeType))
#endif
#ifdef FEATURE_STUBPRECODE_DYNAMIC_HELPERS
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, DynamicHelperPrecodeType, offsetof(PrecodeMachineDescriptor, DynamicHelperPrecodeType))
#endif
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, UMEntryPrecodeType, offsetof(PrecodeMachineDescriptor, UMEntryPrecodeType))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint32*/, StubCodePageSize, offsetof(PrecodeMachineDescriptor, StubCodePageSize))
CDAC_TYPE_END(PrecodeMachineDescriptor)

Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/inc/dacvars.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,5 +236,7 @@ DEFINE_DACVAR(bool, dac__g_metadataUpdatesApplied, ::g_metadataUpdatesApplied)

DEFINE_DACVAR(PTR_WSTR, dac__g_EntryAssemblyPath, ::g_EntryAssemblyPath)

DEFINE_DACVAR(CDacPlatformMetadata, dac__g_cdacPlatformMetadata, ::g_cdacPlatformMetadata)

#undef DEFINE_DACVAR
#undef DEFINE_DACVAR_NO_DUMP
4 changes: 4 additions & 0 deletions src/coreclr/vm/arm64/thunktemplates.S
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,12 @@ LEAF_END_MARKED CallCountingStubCodeTemplate, _TEXT
.irp STUB_PAGE_SIZE, 16384, 32768, 65536

LEAF_ENTRY StubPrecodeCode\STUB_PAGE_SIZE
dmb ishld
ldr x10, DATA_SLOT(StubPrecode, Target)
ldr x12, DATA_SLOT(StubPrecode, SecretParam)
br x10
brk 0xf000 // Stubs need to be 24-byte in size to allow for the data to be 3 pointers
brk 0xf000 // Stubs need to be 24-byte in size to allow for the data to be 3 pointers
LEAF_END_MARKED StubPrecodeCode\STUB_PAGE_SIZE

LEAF_ENTRY FixupPrecodeCode\STUB_PAGE_SIZE
Expand All @@ -135,6 +138,7 @@ LEAF_END_MARKED CallCountingStubCodeTemplate, _TEXT

LEAF_ENTRY CallCountingStubCode\STUB_PAGE_SIZE
LOCAL_LABEL(StubStart\STUB_PAGE_SIZE):
dmb ishld
ldr x9, DATA_SLOT(CallCountingStub, RemainingCallCountCell)
ldrh w10, [x9]
subs w10, w10, #1
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/vm/arm64/thunktemplates.asm
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#define DATA_SLOT(stub, field) (stub##Code + STUB_PAGE_SIZE + stub##Data__##field)

LEAF_ENTRY StubPrecodeCode
dmb ishld
ldr x10, DATA_SLOT(StubPrecode, Target)
ldr x12, DATA_SLOT(StubPrecode, SecretParam)
br x10
Expand All @@ -25,6 +26,7 @@
LEAF_END_MARKED FixupPrecodeCode

LEAF_ENTRY CallCountingStubCode
dmb ishld
ldr x9, DATA_SLOT(CallCountingStub, RemainingCallCountCell)
ldrh w10, [x9]
subs w10, w10, #1
Expand Down
16 changes: 10 additions & 6 deletions src/coreclr/vm/cdacplatformmetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@

#include "cdacplatformmetadata.hpp"

#ifndef DACCESS_COMPILE
CDacPlatformMetadata g_cdacPlatformMetadata;
GVAL_IMPL(CDacPlatformMetadata, g_cdacPlatformMetadata);

#ifndef DACCESS_COMPILE
void CDacPlatformMetadata::Init()
{
PrecodeMachineDescriptor::Init(&g_cdacPlatformMetadata.precode);
#if defined(TARGET_ARM)
g_cdacPlatformMetadata.codePointerFlags = CDacCodePointerFlags::HasArm32ThumbBit;
(&g_cdacPlatformMetadata)->codePointerFlags = CDacCodePointerFlags::HasArm32ThumbBit;
#elif defined(TARGET_ARM64) && defined(TARGET_APPLE)
// TODO set HasArm64PtrAuth if arm64e
g_cdacPlatformMetadata.codePointerFlags = CDacCodePointerFlags::None;
(&g_cdacPlatformMetadata)->codePointerFlags = CDacCodePointerFlags::None;
#else
g_cdacPlatformMetadata.codePointerFlags = CDacCodePointerFlags::None;
(&g_cdacPlatformMetadata)->codePointerFlags = CDacCodePointerFlags::None;
#endif
}

void CDacPlatformMetadata::InitPrecodes()
{
PrecodeMachineDescriptor::Init(&(&g_cdacPlatformMetadata)->precode);
}

#endif // !DACCESS_COMPILE
5 changes: 2 additions & 3 deletions src/coreclr/vm/cdacplatformmetadata.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include "precode.h"

// Cross-cutting metadata for cDAC
#ifndef DACCESS_COMPILE
enum class CDacCodePointerFlags : uint8_t
{
None = 0,
Expand All @@ -24,10 +23,10 @@ struct CDacPlatformMetadata
CDacPlatformMetadata(const CDacPlatformMetadata&) = delete;
CDacPlatformMetadata& operator=(const CDacPlatformMetadata&) = delete;
static void Init();
static void InitPrecodes();
};

extern CDacPlatformMetadata g_cdacPlatformMetadata;
#endif // DACCESS_COMPILE
GVAL_DECL(CDacPlatformMetadata, g_cdacPlatformMetadata);


#endif// CDACPLATFORMMETADATA_HPP__
1 change: 1 addition & 0 deletions src/coreclr/vm/ceemain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,7 @@ void EEStartupHelper()
StubLinkerCPU::Init();
StubPrecode::StaticInitialize();
FixupPrecode::StaticInitialize();
CDacPlatformMetadata::InitPrecodes();

InitializeGarbageCollector();

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/loaderallocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ class LoaderAllocator
}

#if defined(FEATURE_READYTORUN) && defined(FEATURE_STUBPRECODE_DYNAMIC_HELPERS)
PTR_LoaderHeap GetDynamicHelpersStubHeap()
PTR_InterleavedLoaderHeap GetDynamicHelpersStubHeap()
{
LIMITED_METHOD_CONTRACT;
return m_pDynamicHelpersStubHeap;
Expand Down
Loading
Loading