diff options
author | Gleb Balykov <g.balykov@samsung.com> | 2020-09-24 12:33:53 +0300 |
---|---|---|
committer | Alexander Soldatov/Platform Lab /SRR/Staff Engineer/Samsung Electronics <soldatov.a@samsung.com> | 2020-10-05 14:16:35 +0300 |
commit | 45574c33d63efde3d02485278e9b33746f2578d0 (patch) | |
tree | a829f4f009a9475d99cf844ec34e86af699656b1 /src/vm/arm64 | |
parent | 66a3b803910b389de38703ce349695a247146f5b (diff) | |
download | coreclr-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.h | 96 | ||||
-rw-r--r-- | src/vm/arm64/stubs.cpp | 59 |
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; } |