forked from OSchip/llvm-project
[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 llvm-svn: 351000
This commit is contained in:
parent
a21e2bd682
commit
f903f782e7
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue