1 //===------------- OrcABISupport.cpp - ABI specific support code ----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ExecutionEngine/Orc/OrcABISupport.h" 10 #include "llvm/Support/Process.h" 11 12 namespace llvm { 13 namespace orc { 14 15 void OrcAArch64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, 16 void *CallbackMgr) { 17 18 const uint32_t ResolverCode[] = { 19 // resolver_entry: 20 0xa9bf47fd, // 0x000: stp x29, x17, [sp, #-16]! 21 0x910003fd, // 0x004: mov x29, sp 22 0xa9bf73fb, // 0x008: stp x27, x28, [sp, #-16]! 23 0xa9bf6bf9, // 0x00c: stp x25, x26, [sp, #-16]! 24 0xa9bf63f7, // 0x010: stp x23, x24, [sp, #-16]! 25 0xa9bf5bf5, // 0x014: stp x21, x22, [sp, #-16]! 26 0xa9bf53f3, // 0x018: stp x19, x20, [sp, #-16]! 27 0xa9bf3fee, // 0x01c: stp x14, x15, [sp, #-16]! 28 0xa9bf37ec, // 0x020: stp x12, x13, [sp, #-16]! 29 0xa9bf2fea, // 0x024: stp x10, x11, [sp, #-16]! 30 0xa9bf27e8, // 0x028: stp x8, x9, [sp, #-16]! 31 0xa9bf1fe6, // 0x02c: stp x6, x7, [sp, #-16]! 32 0xa9bf17e4, // 0x030: stp x4, x5, [sp, #-16]! 33 0xa9bf0fe2, // 0x034: stp x2, x3, [sp, #-16]! 34 0xa9bf07e0, // 0x038: stp x0, x1, [sp, #-16]! 35 0xadbf7ffe, // 0x03c: stp q30, q31, [sp, #-32]! 36 0xadbf77fc, // 0x040: stp q28, q29, [sp, #-32]! 37 0xadbf6ffa, // 0x044: stp q26, q27, [sp, #-32]! 38 0xadbf67f8, // 0x048: stp q24, q25, [sp, #-32]! 39 0xadbf5ff6, // 0x04c: stp q22, q23, [sp, #-32]! 40 0xadbf57f4, // 0x050: stp q20, q21, [sp, #-32]! 41 0xadbf4ff2, // 0x054: stp q18, q19, [sp, #-32]! 42 0xadbf47f0, // 0x058: stp q16, q17, [sp, #-32]! 43 0xadbf3fee, // 0x05c: stp q14, q15, [sp, #-32]! 44 0xadbf37ec, // 0x060: stp q12, q13, [sp, #-32]! 45 0xadbf2fea, // 0x064: stp q10, q11, [sp, #-32]! 46 0xadbf27e8, // 0x068: stp q8, q9, [sp, #-32]! 47 0xadbf1fe6, // 0x06c: stp q6, q7, [sp, #-32]! 48 0xadbf17e4, // 0x070: stp q4, q5, [sp, #-32]! 49 0xadbf0fe2, // 0x074: stp q2, q3, [sp, #-32]! 50 0xadbf07e0, // 0x078: stp q0, q1, [sp, #-32]! 51 0x580004e0, // 0x07c: ldr x0, Lcallbackmgr 52 0xaa1e03e1, // 0x080: mov x1, x30 53 0xd1003021, // 0x084: sub x1, x1, #12 54 0x58000442, // 0x088: ldr x2, Lreentry_fn_ptr 55 0xd63f0040, // 0x08c: blr x2 56 0xaa0003f1, // 0x090: mov x17, x0 57 0xacc107e0, // 0x094: ldp q0, q1, [sp], #32 58 0xacc10fe2, // 0x098: ldp q2, q3, [sp], #32 59 0xacc117e4, // 0x09c: ldp q4, q5, [sp], #32 60 0xacc11fe6, // 0x0a0: ldp q6, q7, [sp], #32 61 0xacc127e8, // 0x0a4: ldp q8, q9, [sp], #32 62 0xacc12fea, // 0x0a8: ldp q10, q11, [sp], #32 63 0xacc137ec, // 0x0ac: ldp q12, q13, [sp], #32 64 0xacc13fee, // 0x0b0: ldp q14, q15, [sp], #32 65 0xacc147f0, // 0x0b4: ldp q16, q17, [sp], #32 66 0xacc14ff2, // 0x0b8: ldp q18, q19, [sp], #32 67 0xacc157f4, // 0x0bc: ldp q20, q21, [sp], #32 68 0xacc15ff6, // 0x0c0: ldp q22, q23, [sp], #32 69 0xacc167f8, // 0x0c4: ldp q24, q25, [sp], #32 70 0xacc16ffa, // 0x0c8: ldp q26, q27, [sp], #32 71 0xacc177fc, // 0x0cc: ldp q28, q29, [sp], #32 72 0xacc17ffe, // 0x0d0: ldp q30, q31, [sp], #32 73 0xa8c107e0, // 0x0d4: ldp x0, x1, [sp], #16 74 0xa8c10fe2, // 0x0d8: ldp x2, x3, [sp], #16 75 0xa8c117e4, // 0x0dc: ldp x4, x5, [sp], #16 76 0xa8c11fe6, // 0x0e0: ldp x6, x7, [sp], #16 77 0xa8c127e8, // 0x0e4: ldp x8, x9, [sp], #16 78 0xa8c12fea, // 0x0e8: ldp x10, x11, [sp], #16 79 0xa8c137ec, // 0x0ec: ldp x12, x13, [sp], #16 80 0xa8c13fee, // 0x0f0: ldp x14, x15, [sp], #16 81 0xa8c153f3, // 0x0f4: ldp x19, x20, [sp], #16 82 0xa8c15bf5, // 0x0f8: ldp x21, x22, [sp], #16 83 0xa8c163f7, // 0x0fc: ldp x23, x24, [sp], #16 84 0xa8c16bf9, // 0x100: ldp x25, x26, [sp], #16 85 0xa8c173fb, // 0x104: ldp x27, x28, [sp], #16 86 0xa8c17bfd, // 0x108: ldp x29, x30, [sp], #16 87 0xd65f0220, // 0x10c: ret x17 88 0x01234567, // 0x110: Lreentry_fn_ptr: 89 0xdeadbeef, // 0x114: .quad 0 90 0x98765432, // 0x118: Lcallbackmgr: 91 0xcafef00d // 0x11c: .quad 0 92 }; 93 94 const unsigned ReentryFnAddrOffset = 0x110; 95 const unsigned CallbackMgrAddrOffset = 0x118; 96 97 memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); 98 memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); 99 memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, 100 sizeof(CallbackMgr)); 101 } 102 103 void OrcAArch64::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, 104 unsigned NumTrampolines) { 105 106 unsigned OffsetToPtr = alignTo(NumTrampolines * TrampolineSize, 8); 107 108 memcpy(TrampolineMem + OffsetToPtr, &ResolverAddr, sizeof(void *)); 109 110 // OffsetToPtr is actually the offset from the PC for the 2nd instruction, so 111 // subtract 32-bits. 112 OffsetToPtr -= 4; 113 114 uint32_t *Trampolines = reinterpret_cast<uint32_t *>(TrampolineMem); 115 116 for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) { 117 Trampolines[3 * I + 0] = 0xaa1e03f1; // mov x17, x30 118 Trampolines[3 * I + 1] = 0x58000010 | (OffsetToPtr << 3); // adr x16, Lptr 119 Trampolines[3 * I + 2] = 0xd63f0200; // blr x16 120 } 121 122 } 123 124 Error OrcAArch64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, 125 unsigned MinStubs, 126 void *InitialPtrVal) { 127 // Stub format is: 128 // 129 // .section __orc_stubs 130 // stub1: 131 // ldr x0, ptr1 ; PC-rel load of ptr1 132 // br x0 ; Jump to resolver 133 // stub2: 134 // ldr x0, ptr2 ; PC-rel load of ptr2 135 // br x0 ; Jump to resolver 136 // 137 // ... 138 // 139 // .section __orc_ptrs 140 // ptr1: 141 // .quad 0x0 142 // ptr2: 143 // .quad 0x0 144 // 145 // ... 146 147 const unsigned StubSize = IndirectStubsInfo::StubSize; 148 149 // Emit at least MinStubs, rounded up to fill the pages allocated. 150 static const unsigned PageSize = sys::Process::getPageSizeEstimate(); 151 unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; 152 unsigned NumStubs = (NumPages * PageSize) / StubSize; 153 154 // Allocate memory for stubs and pointers in one call. 155 std::error_code EC; 156 auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( 157 2 * NumPages * PageSize, nullptr, 158 sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); 159 160 if (EC) 161 return errorCodeToError(EC); 162 163 // Create separate MemoryBlocks representing the stubs and pointers. 164 sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); 165 sys::MemoryBlock PtrsBlock(static_cast<char *>(StubsMem.base()) + 166 NumPages * PageSize, 167 NumPages * PageSize); 168 169 // Populate the stubs page stubs and mark it executable. 170 uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlock.base()); 171 uint64_t PtrOffsetField = static_cast<uint64_t>(NumPages * PageSize) 172 << 3; 173 174 for (unsigned I = 0; I < NumStubs; ++I) 175 Stub[I] = 0xd61f020058000010 | PtrOffsetField; 176 177 if (auto EC = sys::Memory::protectMappedMemory( 178 StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) 179 return errorCodeToError(EC); 180 181 // Initialize all pointers to point at FailureAddress. 182 void **Ptr = reinterpret_cast<void **>(PtrsBlock.base()); 183 for (unsigned I = 0; I < NumStubs; ++I) 184 Ptr[I] = InitialPtrVal; 185 186 StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem)); 187 188 return Error::success(); 189 } 190 191 void OrcX86_64_Base::writeTrampolines(uint8_t *TrampolineMem, 192 void *ResolverAddr, 193 unsigned NumTrampolines) { 194 195 unsigned OffsetToPtr = NumTrampolines * TrampolineSize; 196 197 memcpy(TrampolineMem + OffsetToPtr, &ResolverAddr, sizeof(void *)); 198 199 uint64_t *Trampolines = reinterpret_cast<uint64_t *>(TrampolineMem); 200 uint64_t CallIndirPCRel = 0xf1c40000000015ff; 201 202 for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) 203 Trampolines[I] = CallIndirPCRel | ((OffsetToPtr - 6) << 16); 204 } 205 206 Error OrcX86_64_Base::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, 207 unsigned MinStubs, 208 void *InitialPtrVal) { 209 // Stub format is: 210 // 211 // .section __orc_stubs 212 // stub1: 213 // jmpq *ptr1(%rip) 214 // .byte 0xC4 ; <- Invalid opcode padding. 215 // .byte 0xF1 216 // stub2: 217 // jmpq *ptr2(%rip) 218 // 219 // ... 220 // 221 // .section __orc_ptrs 222 // ptr1: 223 // .quad 0x0 224 // ptr2: 225 // .quad 0x0 226 // 227 // ... 228 229 const unsigned StubSize = IndirectStubsInfo::StubSize; 230 231 // Emit at least MinStubs, rounded up to fill the pages allocated. 232 static const unsigned PageSize = sys::Process::getPageSizeEstimate(); 233 unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; 234 unsigned NumStubs = (NumPages * PageSize) / StubSize; 235 236 // Allocate memory for stubs and pointers in one call. 237 std::error_code EC; 238 auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( 239 2 * NumPages * PageSize, nullptr, 240 sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); 241 242 if (EC) 243 return errorCodeToError(EC); 244 245 // Create separate MemoryBlocks representing the stubs and pointers. 246 sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); 247 sys::MemoryBlock PtrsBlock(static_cast<char *>(StubsMem.base()) + 248 NumPages * PageSize, 249 NumPages * PageSize); 250 251 // Populate the stubs page stubs and mark it executable. 252 uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlock.base()); 253 uint64_t PtrOffsetField = static_cast<uint64_t>(NumPages * PageSize - 6) 254 << 16; 255 for (unsigned I = 0; I < NumStubs; ++I) 256 Stub[I] = 0xF1C40000000025ff | PtrOffsetField; 257 258 if (auto EC = sys::Memory::protectMappedMemory( 259 StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) 260 return errorCodeToError(EC); 261 262 // Initialize all pointers to point at FailureAddress. 263 void **Ptr = reinterpret_cast<void **>(PtrsBlock.base()); 264 for (unsigned I = 0; I < NumStubs; ++I) 265 Ptr[I] = InitialPtrVal; 266 267 StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem)); 268 269 return Error::success(); 270 } 271 272 void OrcX86_64_SysV::writeResolverCode(uint8_t *ResolverMem, 273 JITReentryFn ReentryFn, 274 void *CallbackMgr) { 275 276 const uint8_t ResolverCode[] = { 277 // resolver_entry: 278 0x55, // 0x00: pushq %rbp 279 0x48, 0x89, 0xe5, // 0x01: movq %rsp, %rbp 280 0x50, // 0x04: pushq %rax 281 0x53, // 0x05: pushq %rbx 282 0x51, // 0x06: pushq %rcx 283 0x52, // 0x07: pushq %rdx 284 0x56, // 0x08: pushq %rsi 285 0x57, // 0x09: pushq %rdi 286 0x41, 0x50, // 0x0a: pushq %r8 287 0x41, 0x51, // 0x0c: pushq %r9 288 0x41, 0x52, // 0x0e: pushq %r10 289 0x41, 0x53, // 0x10: pushq %r11 290 0x41, 0x54, // 0x12: pushq %r12 291 0x41, 0x55, // 0x14: pushq %r13 292 0x41, 0x56, // 0x16: pushq %r14 293 0x41, 0x57, // 0x18: pushq %r15 294 0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00, // 0x1a: subq 0x208, %rsp 295 0x48, 0x0f, 0xae, 0x04, 0x24, // 0x21: fxsave64 (%rsp) 296 0x48, 0xbf, // 0x26: movabsq <CBMgr>, %rdi 297 298 // 0x28: Callback manager addr. 299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 300 301 0x48, 0x8b, 0x75, 0x08, // 0x30: movq 8(%rbp), %rsi 302 0x48, 0x83, 0xee, 0x06, // 0x34: subq $6, %rsi 303 0x48, 0xb8, // 0x38: movabsq <REntry>, %rax 304 305 // 0x3a: JIT re-entry fn addr: 306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 307 308 0xff, 0xd0, // 0x42: callq *%rax 309 0x48, 0x89, 0x45, 0x08, // 0x44: movq %rax, 8(%rbp) 310 0x48, 0x0f, 0xae, 0x0c, 0x24, // 0x48: fxrstor64 (%rsp) 311 0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00, // 0x4d: addq 0x208, %rsp 312 0x41, 0x5f, // 0x54: popq %r15 313 0x41, 0x5e, // 0x56: popq %r14 314 0x41, 0x5d, // 0x58: popq %r13 315 0x41, 0x5c, // 0x5a: popq %r12 316 0x41, 0x5b, // 0x5c: popq %r11 317 0x41, 0x5a, // 0x5e: popq %r10 318 0x41, 0x59, // 0x60: popq %r9 319 0x41, 0x58, // 0x62: popq %r8 320 0x5f, // 0x64: popq %rdi 321 0x5e, // 0x65: popq %rsi 322 0x5a, // 0x66: popq %rdx 323 0x59, // 0x67: popq %rcx 324 0x5b, // 0x68: popq %rbx 325 0x58, // 0x69: popq %rax 326 0x5d, // 0x6a: popq %rbp 327 0xc3, // 0x6b: retq 328 }; 329 330 const unsigned ReentryFnAddrOffset = 0x3a; 331 const unsigned CallbackMgrAddrOffset = 0x28; 332 333 memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); 334 memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); 335 memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, 336 sizeof(CallbackMgr)); 337 } 338 339 void OrcX86_64_Win32::writeResolverCode(uint8_t *ResolverMem, 340 JITReentryFn ReentryFn, 341 void *CallbackMgr) { 342 343 // resolverCode is similar to OrcX86_64 with differences specific to windows x64 calling convention: 344 // arguments go into rcx, rdx and come in reverse order, shadow space allocation on stack 345 const uint8_t ResolverCode[] = { 346 // resolver_entry: 347 0x55, // 0x00: pushq %rbp 348 0x48, 0x89, 0xe5, // 0x01: movq %rsp, %rbp 349 0x50, // 0x04: pushq %rax 350 0x53, // 0x05: pushq %rbx 351 0x51, // 0x06: pushq %rcx 352 0x52, // 0x07: pushq %rdx 353 0x56, // 0x08: pushq %rsi 354 0x57, // 0x09: pushq %rdi 355 0x41, 0x50, // 0x0a: pushq %r8 356 0x41, 0x51, // 0x0c: pushq %r9 357 0x41, 0x52, // 0x0e: pushq %r10 358 0x41, 0x53, // 0x10: pushq %r11 359 0x41, 0x54, // 0x12: pushq %r12 360 0x41, 0x55, // 0x14: pushq %r13 361 0x41, 0x56, // 0x16: pushq %r14 362 0x41, 0x57, // 0x18: pushq %r15 363 0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00, // 0x1a: subq 0x208, %rsp 364 0x48, 0x0f, 0xae, 0x04, 0x24, // 0x21: fxsave64 (%rsp) 365 366 0x48, 0xb9, // 0x26: movabsq <CBMgr>, %rcx 367 // 0x28: Callback manager addr. 368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 369 370 0x48, 0x8B, 0x55, 0x08, // 0x30: mov rdx, [rbp+0x8] 371 0x48, 0x83, 0xea, 0x06, // 0x34: sub rdx, 0x6 372 373 0x48, 0xb8, // 0x38: movabsq <REntry>, %rax 374 // 0x3a: JIT re-entry fn addr: 375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 376 377 // 0x42: sub rsp, 0x20 (Allocate shadow space) 378 0x48, 0x83, 0xEC, 0x20, 379 0xff, 0xd0, // 0x46: callq *%rax 380 381 // 0x48: add rsp, 0x20 (Free shadow space) 382 0x48, 0x83, 0xC4, 0x20, 383 384 0x48, 0x89, 0x45, 0x08, // 0x4C: movq %rax, 8(%rbp) 385 0x48, 0x0f, 0xae, 0x0c, 0x24, // 0x50: fxrstor64 (%rsp) 386 0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00, // 0x55: addq 0x208, %rsp 387 0x41, 0x5f, // 0x5C: popq %r15 388 0x41, 0x5e, // 0x5E: popq %r14 389 0x41, 0x5d, // 0x60: popq %r13 390 0x41, 0x5c, // 0x62: popq %r12 391 0x41, 0x5b, // 0x64: popq %r11 392 0x41, 0x5a, // 0x66: popq %r10 393 0x41, 0x59, // 0x68: popq %r9 394 0x41, 0x58, // 0x6a: popq %r8 395 0x5f, // 0x6c: popq %rdi 396 0x5e, // 0x6d: popq %rsi 397 0x5a, // 0x6e: popq %rdx 398 0x59, // 0x6f: popq %rcx 399 0x5b, // 0x70: popq %rbx 400 0x58, // 0x71: popq %rax 401 0x5d, // 0x72: popq %rbp 402 0xc3, // 0x73: retq 403 }; 404 405 406 const unsigned ReentryFnAddrOffset = 0x3a; 407 const unsigned CallbackMgrAddrOffset = 0x28; 408 409 memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); 410 memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); 411 memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, 412 sizeof(CallbackMgr)); 413 } 414 415 void OrcI386::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, 416 void *CallbackMgr) { 417 418 const uint8_t ResolverCode[] = { 419 // resolver_entry: 420 0x55, // 0x00: pushl %ebp 421 0x89, 0xe5, // 0x01: movl %esp, %ebp 422 0x54, // 0x03: pushl %esp 423 0x83, 0xe4, 0xf0, // 0x04: andl $-0x10, %esp 424 0x50, // 0x07: pushl %eax 425 0x53, // 0x08: pushl %ebx 426 0x51, // 0x09: pushl %ecx 427 0x52, // 0x0a: pushl %edx 428 0x56, // 0x0b: pushl %esi 429 0x57, // 0x0c: pushl %edi 430 0x81, 0xec, 0x18, 0x02, 0x00, 0x00, // 0x0d: subl $0x218, %esp 431 0x0f, 0xae, 0x44, 0x24, 0x10, // 0x13: fxsave 0x10(%esp) 432 0x8b, 0x75, 0x04, // 0x18: movl 0x4(%ebp), %esi 433 0x83, 0xee, 0x05, // 0x1b: subl $0x5, %esi 434 0x89, 0x74, 0x24, 0x04, // 0x1e: movl %esi, 0x4(%esp) 435 0xc7, 0x04, 0x24, 0x00, 0x00, 0x00, 436 0x00, // 0x22: movl <cbmgr>, (%esp) 437 0xb8, 0x00, 0x00, 0x00, 0x00, // 0x29: movl <reentry>, %eax 438 0xff, 0xd0, // 0x2e: calll *%eax 439 0x89, 0x45, 0x04, // 0x30: movl %eax, 0x4(%ebp) 440 0x0f, 0xae, 0x4c, 0x24, 0x10, // 0x33: fxrstor 0x10(%esp) 441 0x81, 0xc4, 0x18, 0x02, 0x00, 0x00, // 0x38: addl $0x218, %esp 442 0x5f, // 0x3e: popl %edi 443 0x5e, // 0x3f: popl %esi 444 0x5a, // 0x40: popl %edx 445 0x59, // 0x41: popl %ecx 446 0x5b, // 0x42: popl %ebx 447 0x58, // 0x43: popl %eax 448 0x8b, 0x65, 0xfc, // 0x44: movl -0x4(%ebp), %esp 449 0x5d, // 0x48: popl %ebp 450 0xc3 // 0x49: retl 451 }; 452 453 const unsigned ReentryFnAddrOffset = 0x2a; 454 const unsigned CallbackMgrAddrOffset = 0x25; 455 456 memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); 457 memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); 458 memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, 459 sizeof(CallbackMgr)); 460 } 461 462 void OrcI386::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, 463 unsigned NumTrampolines) { 464 465 uint64_t CallRelImm = 0xF1C4C400000000e8; 466 uint64_t Resolver = reinterpret_cast<uint64_t>(ResolverAddr); 467 uint64_t ResolverRel = 468 Resolver - reinterpret_cast<uint64_t>(TrampolineMem) - 5; 469 470 uint64_t *Trampolines = reinterpret_cast<uint64_t *>(TrampolineMem); 471 for (unsigned I = 0; I < NumTrampolines; ++I, ResolverRel -= TrampolineSize) 472 Trampolines[I] = CallRelImm | (ResolverRel << 8); 473 } 474 475 Error OrcI386::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, 476 unsigned MinStubs, void *InitialPtrVal) { 477 // Stub format is: 478 // 479 // .section __orc_stubs 480 // stub1: 481 // jmpq *ptr1 482 // .byte 0xC4 ; <- Invalid opcode padding. 483 // .byte 0xF1 484 // stub2: 485 // jmpq *ptr2 486 // 487 // ... 488 // 489 // .section __orc_ptrs 490 // ptr1: 491 // .quad 0x0 492 // ptr2: 493 // .quad 0x0 494 // 495 // ... 496 497 const unsigned StubSize = IndirectStubsInfo::StubSize; 498 499 // Emit at least MinStubs, rounded up to fill the pages allocated. 500 static const unsigned PageSize = sys::Process::getPageSizeEstimate(); 501 unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; 502 unsigned NumStubs = (NumPages * PageSize) / StubSize; 503 504 // Allocate memory for stubs and pointers in one call. 505 std::error_code EC; 506 auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( 507 2 * NumPages * PageSize, nullptr, 508 sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); 509 510 if (EC) 511 return errorCodeToError(EC); 512 513 // Create separate MemoryBlocks representing the stubs and pointers. 514 sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); 515 sys::MemoryBlock PtrsBlock(static_cast<char *>(StubsMem.base()) + 516 NumPages * PageSize, 517 NumPages * PageSize); 518 519 // Populate the stubs page stubs and mark it executable. 520 uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlock.base()); 521 uint64_t PtrAddr = reinterpret_cast<uint64_t>(PtrsBlock.base()); 522 for (unsigned I = 0; I < NumStubs; ++I, PtrAddr += 4) 523 Stub[I] = 0xF1C40000000025ff | (PtrAddr << 16); 524 525 if (auto EC = sys::Memory::protectMappedMemory( 526 StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) 527 return errorCodeToError(EC); 528 529 // Initialize all pointers to point at FailureAddress. 530 void **Ptr = reinterpret_cast<void **>(PtrsBlock.base()); 531 for (unsigned I = 0; I < NumStubs; ++I) 532 Ptr[I] = InitialPtrVal; 533 534 StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem)); 535 536 return Error::success(); 537 } 538 539 void OrcMips32_Base::writeResolverCode(uint8_t *ResolverMem, 540 JITReentryFn ReentryFn, 541 void *CallbackMgr, bool isBigEndian) { 542 543 const uint32_t ResolverCode[] = { 544 // resolver_entry: 545 0x27bdff98, // 0x00: addiu $sp,$sp,-104 546 0xafa20000, // 0x04: sw $v0,0($sp) 547 0xafa30004, // 0x08: sw $v1,4($sp) 548 0xafa40008, // 0x0c: sw $a0,8($sp) 549 0xafa5000c, // 0x10: sw $a1,12($sp) 550 0xafa60010, // 0x14: sw $a2,16($sp) 551 0xafa70014, // 0x18: sw $a3,20($sp) 552 0xafb00018, // 0x1c: sw $s0,24($sp) 553 0xafb1001c, // 0x20: sw $s1,28($sp) 554 0xafb20020, // 0x24: sw $s2,32($sp) 555 0xafb30024, // 0x28: sw $s3,36($sp) 556 0xafb40028, // 0x2c: sw $s4,40($sp) 557 0xafb5002c, // 0x30: sw $s5,44($sp) 558 0xafb60030, // 0x34: sw $s6,48($sp) 559 0xafb70034, // 0x38: sw $s7,52($sp) 560 0xafa80038, // 0x3c: sw $t0,56($sp) 561 0xafa9003c, // 0x40: sw $t1,60($sp) 562 0xafaa0040, // 0x44: sw $t2,64($sp) 563 0xafab0044, // 0x48: sw $t3,68($sp) 564 0xafac0048, // 0x4c: sw $t4,72($sp) 565 0xafad004c, // 0x50: sw $t5,76($sp) 566 0xafae0050, // 0x54: sw $t6,80($sp) 567 0xafaf0054, // 0x58: sw $t7,84($sp) 568 0xafb80058, // 0x5c: sw $t8,88($sp) 569 0xafb9005c, // 0x60: sw $t9,92($sp) 570 0xafbe0060, // 0x64: sw $fp,96($sp) 571 0xafbf0064, // 0x68: sw $ra,100($sp) 572 573 // Callback manager addr. 574 0x00000000, // 0x6c: lui $a0,callbackmgr 575 0x00000000, // 0x70: addiu $a0,$a0,callbackmgr 576 577 0x03e02825, // 0x74: move $a1, $ra 578 0x24a5ffec, // 0x78: addiu $a1,$a1,-20 579 580 // JIT re-entry fn addr: 581 0x00000000, // 0x7c: lui $t9,reentry 582 0x00000000, // 0x80: addiu $t9,$t9,reentry 583 584 0x0320f809, // 0x84: jalr $t9 585 0x00000000, // 0x88: nop 586 0x8fbf0064, // 0x8c: lw $ra,100($sp) 587 0x8fbe0060, // 0x90: lw $fp,96($sp) 588 0x8fb9005c, // 0x94: lw $t9,92($sp) 589 0x8fb80058, // 0x98: lw $t8,88($sp) 590 0x8faf0054, // 0x9c: lw $t7,84($sp) 591 0x8fae0050, // 0xa0: lw $t6,80($sp) 592 0x8fad004c, // 0xa4: lw $t5,76($sp) 593 0x8fac0048, // 0xa8: lw $t4,72($sp) 594 0x8fab0044, // 0xac: lw $t3,68($sp) 595 0x8faa0040, // 0xb0: lw $t2,64($sp) 596 0x8fa9003c, // 0xb4: lw $t1,60($sp) 597 0x8fa80038, // 0xb8: lw $t0,56($sp) 598 0x8fb70034, // 0xbc: lw $s7,52($sp) 599 0x8fb60030, // 0xc0: lw $s6,48($sp) 600 0x8fb5002c, // 0xc4: lw $s5,44($sp) 601 0x8fb40028, // 0xc8: lw $s4,40($sp) 602 0x8fb30024, // 0xcc: lw $s3,36($sp) 603 0x8fb20020, // 0xd0: lw $s2,32($sp) 604 0x8fb1001c, // 0xd4: lw $s1,28($sp) 605 0x8fb00018, // 0xd8: lw $s0,24($sp) 606 0x8fa70014, // 0xdc: lw $a3,20($sp) 607 0x8fa60010, // 0xe0: lw $a2,16($sp) 608 0x8fa5000c, // 0xe4: lw $a1,12($sp) 609 0x8fa40008, // 0xe8: lw $a0,8($sp) 610 0x27bd0068, // 0xec: addiu $sp,$sp,104 611 0x0300f825, // 0xf0: move $ra, $t8 612 0x03200008, // 0xf4: jr $t9 613 0x00000000, // 0xf8: move $t9, $v0/v1 614 }; 615 616 const unsigned ReentryFnAddrOffset = 0x7c; // JIT re-entry fn addr lui 617 const unsigned CallbackMgrAddrOffset = 0x6c; // Callback manager addr lui 618 const unsigned Offsett = 0xf8; 619 620 memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); 621 622 // Depending on endian return value will be in v0 or v1. 623 uint32_t MoveVxT9 = isBigEndian ? 0x0060c825 : 0x0040c825; 624 memcpy(ResolverMem + Offsett, &MoveVxT9, sizeof(MoveVxT9)); 625 626 uint64_t CallMgrAddr = reinterpret_cast<uint64_t>(CallbackMgr); 627 uint32_t CallMgrLUi = 0x3c040000 | (((CallMgrAddr + 0x8000) >> 16) & 0xFFFF); 628 uint32_t CallMgrADDiu = 0x24840000 | ((CallMgrAddr) & 0xFFFF); 629 memcpy(ResolverMem + CallbackMgrAddrOffset, &CallMgrLUi, sizeof(CallMgrLUi)); 630 memcpy(ResolverMem + CallbackMgrAddrOffset + 4, &CallMgrADDiu, 631 sizeof(CallMgrADDiu)); 632 633 uint64_t ReentryAddr = reinterpret_cast<uint64_t>(ReentryFn); 634 uint32_t ReentryLUi = 0x3c190000 | (((ReentryAddr + 0x8000) >> 16) & 0xFFFF); 635 uint32_t ReentryADDiu = 0x27390000 | ((ReentryAddr) & 0xFFFF); 636 memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryLUi, sizeof(ReentryLUi)); 637 memcpy(ResolverMem + ReentryFnAddrOffset + 4, &ReentryADDiu, 638 sizeof(ReentryADDiu)); 639 } 640 641 void OrcMips32_Base::writeTrampolines(uint8_t *TrampolineMem, 642 void *ResolverAddr, 643 unsigned NumTrampolines) { 644 645 uint32_t *Trampolines = reinterpret_cast<uint32_t *>(TrampolineMem); 646 uint64_t ResolveAddr = reinterpret_cast<uint64_t>(ResolverAddr); 647 uint32_t RHiAddr = ((ResolveAddr + 0x8000) >> 16); 648 649 for (unsigned I = 0; I < NumTrampolines; ++I) { 650 Trampolines[5 * I + 0] = 0x03e0c025; // move $t8,$ra 651 Trampolines[5 * I + 1] = 0x3c190000 | (RHiAddr & 0xFFFF); // lui $t9,resolveAddr 652 Trampolines[5 * I + 2] = 0x27390000 | (ResolveAddr & 0xFFFF); // addiu $t9,$t9,resolveAddr 653 Trampolines[5 * I + 3] = 0x0320f809; // jalr $t9 654 Trampolines[5 * I + 4] = 0x00000000; // nop 655 } 656 } 657 658 Error OrcMips32_Base::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, 659 unsigned MinStubs, 660 void *InitialPtrVal) { 661 // Stub format is: 662 // 663 // .section __orc_stubs 664 // stub1: 665 // lui $t9, ptr1 666 // lw $t9, %lo(ptr1)($t9) 667 // jr $t9 668 // stub2: 669 // lui $t9, ptr2 670 // lw $t9,%lo(ptr1)($t9) 671 // jr $t9 672 // 673 // ... 674 // 675 // .section __orc_ptrs 676 // ptr1: 677 // .word 0x0 678 // ptr2: 679 // .word 0x0 680 // 681 // ... 682 683 const unsigned StubSize = IndirectStubsInfo::StubSize; 684 685 // Emit at least MinStubs, rounded up to fill the pages allocated. 686 static const unsigned PageSize = sys::Process::getPageSizeEstimate(); 687 unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; 688 unsigned NumStubs = (NumPages * PageSize) / StubSize; 689 690 // Allocate memory for stubs and pointers in one call. 691 std::error_code EC; 692 auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( 693 2 * NumPages * PageSize, nullptr, 694 sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); 695 696 if (EC) 697 return errorCodeToError(EC); 698 699 // Create separate MemoryBlocks representing the stubs and pointers. 700 sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); 701 sys::MemoryBlock PtrsBlock(static_cast<char *>(StubsMem.base()) + 702 NumPages * PageSize, 703 NumPages * PageSize); 704 705 // Populate the stubs page stubs and mark it executable. 706 uint32_t *Stub = reinterpret_cast<uint32_t *>(StubsBlock.base()); 707 uint64_t PtrAddr = reinterpret_cast<uint64_t>(Stub) + NumPages * PageSize; 708 709 for (unsigned I = 0; I < NumStubs; ++I) { 710 uint32_t HiAddr = ((PtrAddr + 0x8000) >> 16); 711 Stub[4 * I + 0] = 0x3c190000 | (HiAddr & 0xFFFF); // lui $t9,ptr1 712 Stub[4 * I + 1] = 0x8f390000 | (PtrAddr & 0xFFFF); // lw $t9,%lo(ptr1)($t9) 713 Stub[4 * I + 2] = 0x03200008; // jr $t9 714 Stub[4 * I + 3] = 0x00000000; // nop 715 PtrAddr += 4; 716 } 717 718 if (auto EC = sys::Memory::protectMappedMemory( 719 StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) 720 return errorCodeToError(EC); 721 722 // Initialize all pointers to point at FailureAddress. 723 void **Ptr = reinterpret_cast<void **>(PtrsBlock.base()); 724 for (unsigned I = 0; I < NumStubs; ++I) 725 Ptr[I] = InitialPtrVal; 726 727 StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem)); 728 729 return Error::success(); 730 } 731 732 void OrcMips64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, 733 void *CallbackMgr) { 734 735 const uint32_t ResolverCode[] = { 736 //resolver_entry: 737 0x67bdff30, // 0x00: daddiu $sp,$sp,-208 738 0xffa20000, // 0x04: sd v0,0(sp) 739 0xffa30008, // 0x08: sd v1,8(sp) 740 0xffa40010, // 0x0c: sd a0,16(sp) 741 0xffa50018, // 0x10: sd a1,24(sp) 742 0xffa60020, // 0x14: sd a2,32(sp) 743 0xffa70028, // 0x18: sd a3,40(sp) 744 0xffa80030, // 0x1c: sd a4,48(sp) 745 0xffa90038, // 0x20: sd a5,56(sp) 746 0xffaa0040, // 0x24: sd a6,64(sp) 747 0xffab0048, // 0x28: sd a7,72(sp) 748 0xffac0050, // 0x2c: sd t0,80(sp) 749 0xffad0058, // 0x30: sd t1,88(sp) 750 0xffae0060, // 0x34: sd t2,96(sp) 751 0xffaf0068, // 0x38: sd t3,104(sp) 752 0xffb00070, // 0x3c: sd s0,112(sp) 753 0xffb10078, // 0x40: sd s1,120(sp) 754 0xffb20080, // 0x44: sd s2,128(sp) 755 0xffb30088, // 0x48: sd s3,136(sp) 756 0xffb40090, // 0x4c: sd s4,144(sp) 757 0xffb50098, // 0x50: sd s5,152(sp) 758 0xffb600a0, // 0x54: sd s6,160(sp) 759 0xffb700a8, // 0x58: sd s7,168(sp) 760 0xffb800b0, // 0x5c: sd t8,176(sp) 761 0xffb900b8, // 0x60: sd t9,184(sp) 762 0xffbe00c0, // 0x64: sd fp,192(sp) 763 0xffbf00c8, // 0x68: sd ra,200(sp) 764 765 // Callback manager addr. 766 0x00000000, // 0x6c: lui $a0,heighest(callbackmgr) 767 0x00000000, // 0x70: daddiu $a0,$a0,heigher(callbackmgr) 768 0x00000000, // 0x74: dsll $a0,$a0,16 769 0x00000000, // 0x78: daddiu $a0,$a0,hi(callbackmgr) 770 0x00000000, // 0x7c: dsll $a0,$a0,16 771 0x00000000, // 0x80: daddiu $a0,$a0,lo(callbackmgr) 772 773 0x03e02825, // 0x84: move $a1, $ra 774 0x64a5ffdc, // 0x88: daddiu $a1,$a1,-36 775 776 // JIT re-entry fn addr: 777 0x00000000, // 0x8c: lui $t9,reentry 778 0x00000000, // 0x90: daddiu $t9,$t9,reentry 779 0x00000000, // 0x94: dsll $t9,$t9, 780 0x00000000, // 0x98: daddiu $t9,$t9, 781 0x00000000, // 0x9c: dsll $t9,$t9, 782 0x00000000, // 0xa0: daddiu $t9,$t9, 783 0x0320f809, // 0xa4: jalr $t9 784 0x00000000, // 0xa8: nop 785 0xdfbf00c8, // 0xac: ld ra, 200(sp) 786 0xdfbe00c0, // 0xb0: ld fp, 192(sp) 787 0xdfb900b8, // 0xb4: ld t9, 184(sp) 788 0xdfb800b0, // 0xb8: ld t8, 176(sp) 789 0xdfb700a8, // 0xbc: ld s7, 168(sp) 790 0xdfb600a0, // 0xc0: ld s6, 160(sp) 791 0xdfb50098, // 0xc4: ld s5, 152(sp) 792 0xdfb40090, // 0xc8: ld s4, 144(sp) 793 0xdfb30088, // 0xcc: ld s3, 136(sp) 794 0xdfb20080, // 0xd0: ld s2, 128(sp) 795 0xdfb10078, // 0xd4: ld s1, 120(sp) 796 0xdfb00070, // 0xd8: ld s0, 112(sp) 797 0xdfaf0068, // 0xdc: ld t3, 104(sp) 798 0xdfae0060, // 0xe0: ld t2, 96(sp) 799 0xdfad0058, // 0xe4: ld t1, 88(sp) 800 0xdfac0050, // 0xe8: ld t0, 80(sp) 801 0xdfab0048, // 0xec: ld a7, 72(sp) 802 0xdfaa0040, // 0xf0: ld a6, 64(sp) 803 0xdfa90038, // 0xf4: ld a5, 56(sp) 804 0xdfa80030, // 0xf8: ld a4, 48(sp) 805 0xdfa70028, // 0xfc: ld a3, 40(sp) 806 0xdfa60020, // 0x100: ld a2, 32(sp) 807 0xdfa50018, // 0x104: ld a1, 24(sp) 808 0xdfa40010, // 0x108: ld a0, 16(sp) 809 0xdfa30008, // 0x10c: ld v1, 8(sp) 810 0x67bd00d0, // 0x110: daddiu $sp,$sp,208 811 0x0300f825, // 0x114: move $ra, $t8 812 0x03200008, // 0x118: jr $t9 813 0x0040c825, // 0x11c: move $t9, $v0 814 }; 815 816 const unsigned ReentryFnAddrOffset = 0x8c; // JIT re-entry fn addr lui 817 const unsigned CallbackMgrAddrOffset = 0x6c; // Callback manager addr lui 818 819 memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); 820 821 uint64_t CallMgrAddr = reinterpret_cast<uint64_t>(CallbackMgr); 822 823 uint32_t CallMgrLUi = 824 0x3c040000 | (((CallMgrAddr + 0x800080008000) >> 48) & 0xFFFF); 825 uint32_t CallMgrDADDiu = 826 0x64840000 | (((CallMgrAddr + 0x80008000) >> 32) & 0xFFFF); 827 uint32_t CallMgrDSLL = 0x00042438; 828 uint32_t CallMgrDADDiu2 = 829 0x64840000 | ((((CallMgrAddr + 0x8000) >> 16) & 0xFFFF)); 830 uint32_t CallMgrDSLL2 = 0x00042438; 831 uint32_t CallMgrDADDiu3 = 0x64840000 | ((CallMgrAddr)&0xFFFF); 832 833 memcpy(ResolverMem + CallbackMgrAddrOffset, &CallMgrLUi, sizeof(CallMgrLUi)); 834 memcpy(ResolverMem + (CallbackMgrAddrOffset + 4), &CallMgrDADDiu, 835 sizeof(CallMgrDADDiu)); 836 memcpy(ResolverMem + (CallbackMgrAddrOffset + 8), &CallMgrDSLL, 837 sizeof(CallMgrDSLL)); 838 memcpy(ResolverMem + (CallbackMgrAddrOffset + 12), &CallMgrDADDiu2, 839 sizeof(CallMgrDADDiu2)); 840 memcpy(ResolverMem + (CallbackMgrAddrOffset + 16), &CallMgrDSLL2, 841 sizeof(CallMgrDSLL2)); 842 memcpy(ResolverMem + (CallbackMgrAddrOffset + 20), &CallMgrDADDiu3, 843 sizeof(CallMgrDADDiu3)); 844 845 uint64_t ReentryAddr = reinterpret_cast<uint64_t>(ReentryFn); 846 847 uint32_t ReentryLUi = 848 0x3c190000 | (((ReentryAddr + 0x800080008000) >> 48) & 0xFFFF); 849 850 uint32_t ReentryDADDiu = 851 0x67390000 | (((ReentryAddr + 0x80008000) >> 32) & 0xFFFF); 852 853 uint32_t ReentryDSLL = 0x0019cc38; 854 855 uint32_t ReentryDADDiu2 = 856 0x67390000 | (((ReentryAddr + 0x8000) >> 16) & 0xFFFF); 857 858 uint32_t ReentryDSLL2 = 0x0019cc38; 859 860 uint32_t ReentryDADDiu3 = 0x67390000 | ((ReentryAddr)&0xFFFF); 861 862 memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryLUi, sizeof(ReentryLUi)); 863 memcpy(ResolverMem + (ReentryFnAddrOffset + 4), &ReentryDADDiu, 864 sizeof(ReentryDADDiu)); 865 memcpy(ResolverMem + (ReentryFnAddrOffset + 8), &ReentryDSLL, 866 sizeof(ReentryDSLL)); 867 memcpy(ResolverMem + (ReentryFnAddrOffset + 12), &ReentryDADDiu2, 868 sizeof(ReentryDADDiu2)); 869 memcpy(ResolverMem + (ReentryFnAddrOffset + 16), &ReentryDSLL2, 870 sizeof(ReentryDSLL2)); 871 memcpy(ResolverMem + (ReentryFnAddrOffset + 20), &ReentryDADDiu3, 872 sizeof(ReentryDADDiu3)); 873 } 874 875 void OrcMips64::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, 876 unsigned NumTrampolines) { 877 878 uint32_t *Trampolines = reinterpret_cast<uint32_t *>(TrampolineMem); 879 uint64_t ResolveAddr = reinterpret_cast<uint64_t>(ResolverAddr); 880 881 uint64_t HeighestAddr = ((ResolveAddr + 0x800080008000) >> 48); 882 uint64_t HeigherAddr = ((ResolveAddr + 0x80008000) >> 32); 883 uint64_t HiAddr = ((ResolveAddr + 0x8000) >> 16); 884 885 for (unsigned I = 0; I < NumTrampolines; ++I) { 886 Trampolines[10 * I + 0] = 0x03e0c025; // move $t8,$ra 887 Trampolines[10 * I + 1] = 0x3c190000 | (HeighestAddr & 0xFFFF); // lui $t9,resolveAddr 888 Trampolines[10 * I + 2] = 0x67390000 | (HeigherAddr & 0xFFFF); // daddiu $t9,$t9,%higher(resolveAddr) 889 Trampolines[10 * I + 3] = 0x0019cc38; // dsll $t9,$t9,16 890 Trampolines[10 * I + 4] = 0x67390000 | (HiAddr & 0xFFFF); // daddiu $t9,$t9,%hi(ptr) 891 Trampolines[10 * I + 5] = 0x0019cc38; // dsll $t9,$t9,16 892 Trampolines[10 * I + 6] = 0x67390000 | (ResolveAddr & 0xFFFF); // daddiu $t9,$t9,%lo(ptr) 893 Trampolines[10 * I + 7] = 0x0320f809; // jalr $t9 894 Trampolines[10 * I + 8] = 0x00000000; // nop 895 Trampolines[10 * I + 9] = 0x00000000; // nop 896 } 897 } 898 899 Error OrcMips64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, 900 unsigned MinStubs, 901 void *InitialPtrVal) { 902 // Stub format is: 903 // 904 // .section __orc_stubs 905 // stub1: 906 // lui $t9,ptr1 907 // dsll $t9,$t9,16 908 // daddiu $t9,$t9,%hi(ptr) 909 // dsll $t9,$t9,16 910 // ld $t9,%lo(ptr) 911 // jr $t9 912 // stub2: 913 // lui $t9,ptr1 914 // dsll $t9,$t9,16 915 // daddiu $t9,$t9,%hi(ptr) 916 // dsll $t9,$t9,16 917 // ld $t9,%lo(ptr) 918 // jr $t9 919 // 920 // ... 921 // 922 // .section __orc_ptrs 923 // ptr1: 924 // .dword 0x0 925 // ptr2: 926 // .dword 0x0 927 // 928 // ... 929 const unsigned StubSize = IndirectStubsInfo::StubSize; 930 931 // Emit at least MinStubs, rounded up to fill the pages allocated. 932 static const unsigned PageSize = sys::Process::getPageSizeEstimate(); 933 unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; 934 unsigned NumStubs = (NumPages * PageSize) / StubSize; 935 936 // Allocate memory for stubs and pointers in one call. 937 std::error_code EC; 938 auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( 939 2 * NumPages * PageSize, nullptr, 940 sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); 941 942 if (EC) 943 return errorCodeToError(EC); 944 945 // Create separate MemoryBlocks representing the stubs and pointers. 946 sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); 947 sys::MemoryBlock PtrsBlock(static_cast<char *>(StubsMem.base()) + 948 NumPages * PageSize, 949 NumPages * PageSize); 950 951 // Populate the stubs page stubs and mark it executable. 952 uint32_t *Stub = reinterpret_cast<uint32_t *>(StubsBlock.base()); 953 uint64_t PtrAddr = reinterpret_cast<uint64_t>(PtrsBlock.base()); 954 955 for (unsigned I = 0; I < NumStubs; ++I, PtrAddr += 8) { 956 uint64_t HeighestAddr = ((PtrAddr + 0x800080008000) >> 48); 957 uint64_t HeigherAddr = ((PtrAddr + 0x80008000) >> 32); 958 uint64_t HiAddr = ((PtrAddr + 0x8000) >> 16); 959 Stub[8 * I + 0] = 0x3c190000 | (HeighestAddr & 0xFFFF); // lui $t9,ptr1 960 Stub[8 * I + 1] = 0x67390000 | (HeigherAddr & 0xFFFF); // daddiu $t9,$t9,%higher(ptr) 961 Stub[8 * I + 2] = 0x0019cc38; // dsll $t9,$t9,16 962 Stub[8 * I + 3] = 0x67390000 | (HiAddr & 0xFFFF); // daddiu $t9,$t9,%hi(ptr) 963 Stub[8 * I + 4] = 0x0019cc38; // dsll $t9,$t9,16 964 Stub[8 * I + 5] = 0xdf390000 | (PtrAddr & 0xFFFF); // ld $t9,%lo(ptr) 965 Stub[8 * I + 6] = 0x03200008; // jr $t9 966 Stub[8 * I + 7] = 0x00000000; // nop 967 } 968 969 if (auto EC = sys::Memory::protectMappedMemory( 970 StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) 971 return errorCodeToError(EC); 972 973 // Initialize all pointers to point at FailureAddress. 974 void **Ptr = reinterpret_cast<void **>(PtrsBlock.base()); 975 for (unsigned I = 0; I < NumStubs; ++I) 976 Ptr[I] = InitialPtrVal; 977 978 StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem)); 979 980 return Error::success(); 981 } 982 } // End namespace orc. 983 } // End namespace llvm. 984