diff options
author | Simon Atanasyan <simon@atanasyan.com> | 2019-01-12 11:12:04 +0000 |
---|---|---|
committer | Simon Atanasyan <simon@atanasyan.com> | 2019-01-12 11:12:04 +0000 |
commit | 06ac862fa695eeffc3bbc1919476e1b343242687 (patch) | |
tree | 953f06d8c4f925076b1b2068e0ed7065dce6e174 | |
parent | f456055a363dc6aff8f4e3c55ef7711febfd3f66 (diff) |
[ORC][MIPS] Setup t9 register and call function through this register
MIPS ABI states that every function must be called through jalr $t9. In
other words, a function expect that t9 register points to the beginning
of its code. A function uses this register to calculate offset to the
Global Offset Table and save it to the `gp` register.
```
lui $gp, %hi(_gp_disp)
addiu $gp, %lo(_gp_disp)
addu $gp, $gp, $t9
```
If `t9` and as a result `$gp` point to the wrong place the following code
loads incorrect value from GOT and passes control to invalid code.
```
lw $v0,%call16(foo)($gp)
jalr $t9
```
OrcMips32 and OrcMips64 writeResolverCode methods pass control to the
resolved address, but do not setup `$t9` before the call. The `t9` holds
value of the beginning of `resolver` code so any attempts to call
routines via GOT failed.
This change fixes the problem. The `OrcLazy/hidden-visibility.ll` test
starts to pass correctly. Before the change it fails on MIPS because the
`exitOnLazyCallThroughFailure` called from the resolver code could not
call libc routine `exit` via GOT.
Differential Revision: http://reviews.llvm.org/D56058
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351000 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/OrcABISupport.h | 4 | ||||
-rw-r--r-- | lib/ExecutionEngine/Orc/OrcABISupport.cpp | 19 |
2 files changed, 10 insertions, 13 deletions
diff --git a/include/llvm/ExecutionEngine/Orc/OrcABISupport.h b/include/llvm/ExecutionEngine/Orc/OrcABISupport.h index 6b748e58ea0..a70fc373713 100644 --- a/include/llvm/ExecutionEngine/Orc/OrcABISupport.h +++ b/include/llvm/ExecutionEngine/Orc/OrcABISupport.h @@ -245,7 +245,7 @@ class OrcMips32_Base { public: static const unsigned PointerSize = 4; static const unsigned TrampolineSize = 20; - static const unsigned ResolverCodeSize = 0xf8; + static const unsigned ResolverCodeSize = 0xfc; using IndirectStubsInfo = GenericIndirectStubsInfo<16>; using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr, @@ -287,7 +287,7 @@ class OrcMips64 { public: static const unsigned PointerSize = 8; static const unsigned TrampolineSize = 40; - static const unsigned ResolverCodeSize = 0x11C; + static const unsigned ResolverCodeSize = 0x120; using IndirectStubsInfo = GenericIndirectStubsInfo<32>; using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr, diff --git a/lib/ExecutionEngine/Orc/OrcABISupport.cpp b/lib/ExecutionEngine/Orc/OrcABISupport.cpp index 47499243e0c..3f513e42ef0 100644 --- a/lib/ExecutionEngine/Orc/OrcABISupport.cpp +++ b/lib/ExecutionEngine/Orc/OrcABISupport.cpp @@ -610,23 +610,19 @@ void OrcMips32_Base::writeResolverCode(uint8_t *ResolverMem, 0x8fa40008, // 0xe8: lw $a0,8($sp) 0x27bd0068, // 0xec: addiu $sp,$sp,104 0x0300f825, // 0xf0: move $ra, $t8 - 0x00000000 // 0xf4: jr $v0/v1 + 0x00000000, // 0xf4: move $t9, $v0/v1 + 0x03200008 // 0xf8: jr $t9 }; const unsigned ReentryFnAddrOffset = 0x7c; // JIT re-entry fn addr lui const unsigned CallbackMgrAddrOffset = 0x6c; // Callback manager addr lui - const unsigned offsett = 0xf4; + const unsigned Offsett = 0xf4; memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); - //Depending on endian return value will be in v0 or v1. - uint32_t JumpV0 = 0x00400008; - uint32_t JumpV1 = 0x00600008; - - if(isBigEndian == true) - memcpy(ResolverMem + offsett, &JumpV1, sizeof(JumpV1)); - else - memcpy(ResolverMem + offsett, &JumpV0, sizeof(JumpV0)); + // Depending on endian return value will be in v0 or v1. + uint32_t MoveVxT9 = isBigEndian ? 0x0060c825 : 0x0040c825; + memcpy(ResolverMem + Offsett, &MoveVxT9, sizeof(MoveVxT9)); uint64_t CallMgrAddr = reinterpret_cast<uint64_t>(CallbackMgr); uint32_t CallMgrLUi = 0x3c040000 | (((CallMgrAddr + 0x8000) >> 16) & 0xFFFF); @@ -814,7 +810,8 @@ void OrcMips64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, 0xdfa30008, // 0x10c: ld v1, 8(sp) 0x67bd00d0, // 0x110: daddiu $sp,$sp,208 0x0300f825, // 0x114: move $ra, $t8 - 0x00400008 // 0x118: jr $v0 + 0x0040c825, // 0x118: move $t9, $v0 + 0x03200008 // 0x11c: jr $t9 }; const unsigned ReentryFnAddrOffset = 0x8c; // JIT re-entry fn addr lui |