summaryrefslogtreecommitdiff
path: root/src/vm/arm64
diff options
context:
space:
mode:
authorGleb Balykov <g.balykov@samsung.com>2020-09-24 12:33:53 +0300
committerAlexander Soldatov/Platform Lab /SRR/Staff Engineer/Samsung Electronics <soldatov.a@samsung.com>2020-10-05 14:16:35 +0300
commit45574c33d63efde3d02485278e9b33746f2578d0 (patch)
treea829f4f009a9475d99cf844ec34e86af699656b1 /src/vm/arm64
parent66a3b803910b389de38703ce349695a247146f5b (diff)
downloadcoreclr-45574c33d63efde3d02485278e9b33746f2578d0.tar.gz
coreclr-45574c33d63efde3d02485278e9b33746f2578d0.tar.bz2
coreclr-45574c33d63efde3d02485278e9b33746f2578d0.zip
[Tizen] Add RelativeStubPrecode for arm64, which replaces StubPrecode in FNV images
Diffstat (limited to 'src/vm/arm64')
-rw-r--r--src/vm/arm64/cgencpu.h96
-rw-r--r--src/vm/arm64/stubs.cpp59
2 files changed, 152 insertions, 3 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;
diff --git a/src/vm/arm64/stubs.cpp b/src/vm/arm64/stubs.cpp
index b25dc4d531..6061654fdc 100644
--- a/src/vm/arm64/stubs.cpp
+++ b/src/vm/arm64/stubs.cpp
@@ -612,11 +612,33 @@ void StubPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator)
m_pMethodDesc = (TADDR)pMD;
}
+void RelativeStubPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator)
+{
+ WRAPPER_NO_CONTRACT;
+
+ int n = 0;
+
+ m_rgCode[n++] = 0x100000C9; // adr x9, #24
+ m_rgCode[n++] = 0xA940312A; // ldp x10,x12,[x9]
+ m_rgCode[n++] = 0x8B09018C; // add x12,x12,x9
+ m_rgCode[n++] = 0x8B09014A; // add x10,x10,x9
+ m_rgCode[n++] = 0xD61F0140; // br x10
+
+ _ASSERTE(n+1 == _countof(m_rgCode));
+
+ m_pTargetOffset = GetPreStubEntryPoint() - (TADDR)this - RelativeStubPrecode::GetTargetOffset();
+ m_pMethodDescOffset = (TADDR)pMD - (TADDR)this - RelativeStubPrecode::GetTargetOffset();
+}
+
#ifdef FEATURE_NATIVE_IMAGE_GENERATION
void StubPrecode::Fixup(DataImage *image)
{
WRAPPER_NO_CONTRACT;
+#ifdef HAS_RELATIVE_STUB_PRECODE
+ // StubPrecode is not saved to image in this case
+ _ASSERTE(!"StubPrecode is not saved to NGENed image, RelativeStubPrecode is instead");
+#else // HAS_RELATIVE_STUB_PRECODE
image->FixupFieldToNode(this, offsetof(StubPrecode, m_pTarget),
image->GetHelperThunk(CORINFO_HELP_EE_PRESTUB),
0,
@@ -626,6 +648,24 @@ void StubPrecode::Fixup(DataImage *image)
(void*)GetMethodDesc(),
0,
IMAGE_REL_BASED_PTR);
+#endif // HAS_RELATIVE_STUB_PRECODE
+}
+
+void RelativeStubPrecode::Fixup(DataImage *image)
+{
+ WRAPPER_NO_CONTRACT;
+
+ image->FixupFieldToNode(this,
+ offsetof(RelativeStubPrecode, m_pTargetOffset),
+ image->GetHelperThunk(CORINFO_HELP_EE_PRESTUB),
+ offsetof(RelativeStubPrecode, m_pTargetOffset) - RelativeStubPrecode::GetTargetOffset(),
+ IMAGE_REL_BASED_RELPTR);
+
+ image->FixupField(this,
+ offsetof(RelativeStubPrecode, m_pMethodDescOffset),
+ (void*)GetMethodDesc(),
+ offsetof(RelativeStubPrecode, m_pMethodDescOffset) - RelativeStubPrecode::GetTargetOffset(),
+ IMAGE_REL_BASED_RELPTR);
}
#endif // FEATURE_NATIVE_IMAGE_GENERATION
@@ -886,9 +926,7 @@ BOOL DoesSlotCallPrestub(PCODE pCode)
#endif // HAS_RELATIVE_FIXUP_PRECODE
// StubPrecode
- if (pInstr[0] == 0x10000089 && // adr x9, #16
- pInstr[1] == 0xA940312A && // ldp x10,x12,[x9]
- pInstr[2] == 0xD61F0140) // br x10
+ if (StubPrecode::IsStubPrecodeByASM(pCode))
{
PCODE pTarget = dac_cast<PTR_StubPrecode>(pInstr)->m_pTarget;
@@ -900,6 +938,21 @@ BOOL DoesSlotCallPrestub(PCODE pCode)
return pTarget == GetPreStubEntryPoint();
}
+ // RelativeStubPrecode
+#if defined(HAS_RELATIVE_STUB_PRECODE)
+ if (RelativeStubPrecode::IsRelativeStubPrecodeByASM(pCode))
+ {
+ PCODE pTarget = dac_cast<PTR_RelativeStubPrecode>(pInstr)->GetTarget();
+
+ if (isJump(pTarget))
+ {
+ pTarget = decodeJump(pTarget);
+ }
+
+ return pTarget == GetPreStubEntryPoint();
+ }
+#endif // HAS_RELATIVE_STUB_PRECODE
+
return FALSE;
}