summaryrefslogtreecommitdiff
path: root/src/vm/arm64/cgencpu.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/arm64/cgencpu.h')
-rw-r--r--src/vm/arm64/cgencpu.h96
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;