diff options
Diffstat (limited to 'src/vm/arm64/cgencpu.h')
-rw-r--r-- | src/vm/arm64/cgencpu.h | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/vm/arm64/cgencpu.h b/src/vm/arm64/cgencpu.h index 7d01f9d6ff..ea5fe7b4fc 100644 --- a/src/vm/arm64/cgencpu.h +++ b/src/vm/arm64/cgencpu.h @@ -48,6 +48,8 @@ extern PCODE GetPreStubEntryPoint(); #define HAS_RELATIVE_FIXUP_PRECODE 1 #endif +#define HAS_RELATIVE_STUB_PRECODE 1 + // ThisPtrRetBufPrecode one is necessary for closed delegates over static methods with return buffer #define HAS_THISPTR_RETBUF_PRECODE 1 @@ -627,6 +629,15 @@ struct StubPrecode { (LONGLONG*)&m_pTarget, (TADDR)target, (TADDR)expected) == expected; } + static BOOL IsStubPrecodeByASM(PCODE addr) + { + PTR_DWORD pInstr = dac_cast<PTR_DWORD>(PCODEToPINSTR(addr)); + return + (pInstr[0] == 0x10000089) && + (pInstr[1] == 0xA940312A) && + (pInstr[2] == 0xD61F0140); + } + #ifdef FEATURE_PREJIT void Fixup(DataImage *image); #endif @@ -634,6 +645,91 @@ struct StubPrecode { typedef DPTR(StubPrecode) PTR_StubPrecode; +struct RelativeStubPrecode { + + static const int Type = 0xC9; + + // adr x9, #24 + // ldp x10,x12,[x9] ; =m_pTargetOffset,m_pMethodDescOffset + // add x12,x12,x9 + // add x10,x10,x9 + // br x10 + // 4 byte padding for 8 byte allignement + // dcd m_pTargetOffset ; m_pTargetOffset is relative to itself + // dcd m_pMethodDescOffset ; m_pMethodDescOffset is relative to location of m_pTargetOffset + + DWORD m_rgCode[6]; + TADDR m_pTargetOffset; + TADDR m_pMethodDescOffset; + + void Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator); + + static TADDR GetTargetOffset() + { + LIMITED_METHOD_DAC_CONTRACT; + return offsetof(RelativeStubPrecode, m_pTargetOffset); + } + + TADDR GetMethodDesc() + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast<TADDR>(this) + GetTargetOffset() + m_pMethodDescOffset; + } + + PCODE GetTarget() + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast<TADDR>(this) + GetTargetOffset() + m_pTargetOffset; + } + + void ResetTargetInterlocked() + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + EnsureWritableExecutablePages(&m_pTargetOffset); + TADDR addr = (TADDR)GetPreStubEntryPoint() - (TADDR)(this) - GetTargetOffset(); + InterlockedExchange64((LONGLONG*)&m_pTargetOffset, addr); + } + + BOOL SetTargetInterlocked(TADDR target, TADDR expected) + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + EnsureWritableExecutablePages(&m_pTargetOffset); + TADDR addrExpected = expected - (TADDR)(this) - GetTargetOffset(); + TADDR addrTarget = target - (TADDR)(this) - GetTargetOffset(); + return (TADDR)InterlockedCompareExchange64( + (LONGLONG*)&m_pTargetOffset, addrTarget, addrExpected) == addrExpected; + } + + static BOOL IsRelativeStubPrecodeByASM(PCODE addr) + { + PTR_DWORD pInstr = dac_cast<PTR_DWORD>(PCODEToPINSTR(addr)); + return + (pInstr[0] == 0x100000C9) && + (pInstr[1] == 0xA940312A) && + (pInstr[2] == 0x8B09018C) && + (pInstr[3] == 0x8B09014A) && + (pInstr[4] == 0xD61F0140); + } + +#ifdef FEATURE_PREJIT + void Fixup(DataImage *image); +#endif +}; +typedef DPTR(RelativeStubPrecode) PTR_RelativeStubPrecode; + + struct NDirectImportPrecode { static const int Type = 0x8B; |