LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/Orc - OrcABISupport.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 39 134 29.1 %
Date: 2017-09-14 15:23:50 Functions: 3 10 30.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===------------- OrcABISupport.cpp - ABI specific support code ----------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
      11             : #include "llvm/ADT/Triple.h"
      12             : #include "llvm/Support/Process.h"
      13             : 
      14             : namespace llvm {
      15             : namespace orc {
      16             : 
      17           0 : void OrcAArch64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn,
      18             :                                    void *CallbackMgr) {
      19             : 
      20           0 :   const uint32_t ResolverCode[] = {
      21             :     // resolver_entry:
      22             :     0xa9bf47fd,        // 0x000:  stp  x29, x17, [sp, #-16]!
      23             :     0x910003fd,        // 0x004:  mov  x29, sp
      24             :     0xa9bf73fb,        // 0x008:  stp  x27, x28, [sp, #-16]!
      25             :     0xa9bf6bf9,        // 0x00c:  stp  x25, x26, [sp, #-16]!
      26             :     0xa9bf63f7,        // 0x010:  stp  x23, x24, [sp, #-16]!
      27             :     0xa9bf5bf5,        // 0x014:  stp  x21, x22, [sp, #-16]!
      28             :     0xa9bf53f3,        // 0x018:  stp  x19, x20, [sp, #-16]!
      29             :     0xa9bf3fee,        // 0x01c:  stp  x14, x15, [sp, #-16]!
      30             :     0xa9bf37ec,        // 0x020:  stp  x12, x13, [sp, #-16]!
      31             :     0xa9bf2fea,        // 0x024:  stp  x10, x11, [sp, #-16]!
      32             :     0xa9bf27e8,        // 0x028:  stp   x8,  x9, [sp, #-16]!
      33             :     0xa9bf1fe6,        // 0x02c:  stp   x6,  x7, [sp, #-16]!
      34             :     0xa9bf17e4,        // 0x030:  stp   x4,  x5, [sp, #-16]!
      35             :     0xa9bf0fe2,        // 0x034:  stp   x2,  x3, [sp, #-16]!
      36             :     0xa9bf07e0,        // 0x038:  stp   x0,  x1, [sp, #-16]!
      37             :     0xadbf7ffe,        // 0x03c:  stp  q30, q31, [sp, #-32]!
      38             :     0xadbf77fc,        // 0x040:  stp  q28, q29, [sp, #-32]!
      39             :     0xadbf6ffa,        // 0x044:  stp  q26, q27, [sp, #-32]!
      40             :     0xadbf67f8,        // 0x048:  stp  q24, q25, [sp, #-32]!
      41             :     0xadbf5ff6,        // 0x04c:  stp  q22, q23, [sp, #-32]!
      42             :     0xadbf57f4,        // 0x050:  stp  q20, q21, [sp, #-32]!
      43             :     0xadbf4ff2,        // 0x054:  stp  q18, q19, [sp, #-32]!
      44             :     0xadbf47f0,        // 0x058:  stp  q16, q17, [sp, #-32]!
      45             :     0xadbf3fee,        // 0x05c:  stp  q14, q15, [sp, #-32]!
      46             :     0xadbf37ec,        // 0x060:  stp  q12, q13, [sp, #-32]!
      47             :     0xadbf2fea,        // 0x064:  stp  q10, q11, [sp, #-32]!
      48             :     0xadbf27e8,        // 0x068:  stp   q8,  q9, [sp, #-32]!
      49             :     0xadbf1fe6,        // 0x06c:  stp   q6,  q7, [sp, #-32]!
      50             :     0xadbf17e4,        // 0x070:  stp   q4,  q5, [sp, #-32]!
      51             :     0xadbf0fe2,        // 0x074:  stp   q2,  q3, [sp, #-32]!
      52             :     0xadbf07e0,        // 0x078:  stp   q0,  q1, [sp, #-32]!
      53             :     0x580004e0,        // 0x07c:  ldr   x0, Lcallbackmgr
      54             :     0xaa1e03e1,        // 0x080:  mov   x1, x30
      55             :     0xd1003021,        // 0x084:  sub   x1,  x1, #12
      56             :     0x58000442,        // 0x088:  ldr   x2, Lreentry_fn_ptr
      57             :     0xd63f0040,        // 0x08c:  blr   x2
      58             :     0xaa0003f1,        // 0x090:  mov   x17, x0
      59             :     0xacc107e0,        // 0x094:  ldp   q0,  q1, [sp], #32
      60             :     0xacc10fe2,        // 0x098:  ldp   q2,  q3, [sp], #32
      61             :     0xacc117e4,        // 0x09c:  ldp   q4,  q5, [sp], #32
      62             :     0xacc11fe6,        // 0x0a0:  ldp   q6,  q7, [sp], #32
      63             :     0xacc127e8,        // 0x0a4:  ldp   q8,  q9, [sp], #32
      64             :     0xacc12fea,        // 0x0a8:  ldp  q10, q11, [sp], #32
      65             :     0xacc137ec,        // 0x0ac:  ldp  q12, q13, [sp], #32
      66             :     0xacc13fee,        // 0x0b0:  ldp  q14, q15, [sp], #32
      67             :     0xacc147f0,        // 0x0b4:  ldp  q16, q17, [sp], #32
      68             :     0xacc14ff2,        // 0x0b8:  ldp  q18, q19, [sp], #32
      69             :     0xacc157f4,        // 0x0bc:  ldp  q20, q21, [sp], #32
      70             :     0xacc15ff6,        // 0x0c0:  ldp  q22, q23, [sp], #32
      71             :     0xacc167f8,        // 0x0c4:  ldp  q24, q25, [sp], #32
      72             :     0xacc16ffa,        // 0x0c8:  ldp  q26, q27, [sp], #32
      73             :     0xacc177fc,        // 0x0cc:  ldp  q28, q29, [sp], #32
      74             :     0xacc17ffe,        // 0x0d0:  ldp  q30, q31, [sp], #32
      75             :     0xa8c107e0,        // 0x0d4:  ldp   x0,  x1, [sp], #16
      76             :     0xa8c10fe2,        // 0x0d8:  ldp   x2,  x3, [sp], #16
      77             :     0xa8c117e4,        // 0x0dc:  ldp   x4,  x5, [sp], #16
      78             :     0xa8c11fe6,        // 0x0e0:  ldp   x6,  x7, [sp], #16
      79             :     0xa8c127e8,        // 0x0e4:  ldp   x8,  x9, [sp], #16
      80             :     0xa8c12fea,        // 0x0e8:  ldp  x10, x11, [sp], #16
      81             :     0xa8c137ec,        // 0x0ec:  ldp  x12, x13, [sp], #16
      82             :     0xa8c13fee,        // 0x0f0:  ldp  x14, x15, [sp], #16
      83             :     0xa8c153f3,        // 0x0f4:  ldp  x19, x20, [sp], #16
      84             :     0xa8c15bf5,        // 0x0f8:  ldp  x21, x22, [sp], #16
      85             :     0xa8c163f7,        // 0x0fc:  ldp  x23, x24, [sp], #16
      86             :     0xa8c16bf9,        // 0x100:  ldp  x25, x26, [sp], #16
      87             :     0xa8c173fb,        // 0x104:  ldp  x27, x28, [sp], #16
      88             :     0xa8c17bfd,        // 0x108:  ldp  x29, x30, [sp], #16
      89             :     0xd65f0220,        // 0x10c:  ret  x17
      90             :     0x01234567,        // 0x110:  Lreentry_fn_ptr:
      91             :     0xdeadbeef,        // 0x114:      .quad 0
      92             :     0x98765432,        // 0x118:  Lcallbackmgr:
      93             :     0xcafef00d         // 0x11c:      .quad 0
      94             :   };
      95             : 
      96           0 :   const unsigned ReentryFnAddrOffset = 0x110;
      97           0 :   const unsigned CallbackMgrAddrOffset = 0x118;
      98             : 
      99           0 :   memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode));
     100           0 :   memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn));
     101           0 :   memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr,
     102             :          sizeof(CallbackMgr));
     103           0 : }
     104             : 
     105           0 : void OrcAArch64::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
     106             :                                   unsigned NumTrampolines) {
     107             : 
     108           0 :   unsigned OffsetToPtr = alignTo(NumTrampolines * TrampolineSize, 8);
     109             : 
     110           0 :   memcpy(TrampolineMem + OffsetToPtr, &ResolverAddr, sizeof(void *));
     111             : 
     112             :   // OffsetToPtr is actually the offset from the PC for the 2nd instruction, so
     113             :   // subtract 32-bits.
     114           0 :   OffsetToPtr -= 4;
     115             : 
     116           0 :   uint32_t *Trampolines = reinterpret_cast<uint32_t *>(TrampolineMem);
     117             : 
     118           0 :   for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) {
     119           0 :     Trampolines[3 * I + 0] = 0xaa1e03f1;                      // mov x17, x30
     120           0 :     Trampolines[3 * I + 1] = 0x58000010 | (OffsetToPtr << 3); // mov x16, Lptr
     121           0 :     Trampolines[3 * I + 2] = 0xd63f0200;                      // blr x16
     122             :   }
     123             : 
     124           0 : }
     125             : 
     126           0 : Error OrcAArch64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
     127             :                                          unsigned MinStubs,
     128             :                                          void *InitialPtrVal) {
     129             :   // Stub format is:
     130             :   //
     131             :   // .section __orc_stubs
     132             :   // stub1:
     133             :   //                 ldr     x0, ptr1       ; PC-rel load of ptr1
     134             :   //                 br      x0             ; Jump to resolver
     135             :   // stub2:
     136             :   //                 ldr     x0, ptr2       ; PC-rel load of ptr2
     137             :   //                 br      x0             ; Jump to resolver
     138             :   //
     139             :   // ...
     140             :   //
     141             :   // .section __orc_ptrs
     142             :   // ptr1:
     143             :   //                 .quad 0x0
     144             :   // ptr2:
     145             :   //                 .quad 0x0
     146             :   //
     147             :   // ...
     148             : 
     149           0 :   const unsigned StubSize = IndirectStubsInfo::StubSize;
     150             : 
     151             :   // Emit at least MinStubs, rounded up to fill the pages allocated.
     152           0 :   unsigned PageSize = sys::Process::getPageSize();
     153           0 :   unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
     154           0 :   unsigned NumStubs = (NumPages * PageSize) / StubSize;
     155             : 
     156             :   // Allocate memory for stubs and pointers in one call.
     157           0 :   std::error_code EC;
     158             :   auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
     159           0 :       2 * NumPages * PageSize, nullptr,
     160           0 :       sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
     161             : 
     162           0 :   if (EC)
     163           0 :     return errorCodeToError(EC);
     164             : 
     165             :   // Create separate MemoryBlocks representing the stubs and pointers.
     166           0 :   sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize);
     167           0 :   sys::MemoryBlock PtrsBlock(static_cast<char *>(StubsMem.base()) +
     168             :                                  NumPages * PageSize,
     169           0 :                              NumPages * PageSize);
     170             : 
     171             :   // Populate the stubs page stubs and mark it executable.
     172           0 :   uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlock.base());
     173           0 :   uint64_t PtrOffsetField = static_cast<uint64_t>(NumPages * PageSize)
     174             :                             << 3;
     175             : 
     176           0 :   for (unsigned I = 0; I < NumStubs; ++I)
     177           0 :     Stub[I] = 0xd61f020058000010 | PtrOffsetField;
     178             : 
     179           0 :   if (auto EC = sys::Memory::protectMappedMemory(
     180           0 :           StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC))
     181           0 :     return errorCodeToError(EC);
     182             : 
     183             :   // Initialize all pointers to point at FailureAddress.
     184           0 :   void **Ptr = reinterpret_cast<void **>(PtrsBlock.base());
     185           0 :   for (unsigned I = 0; I < NumStubs; ++I)
     186           0 :     Ptr[I] = InitialPtrVal;
     187             : 
     188           0 :   StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem));
     189             : 
     190           0 :   return Error::success();
     191             : }
     192             : 
     193           9 : void OrcX86_64_Base::writeTrampolines(uint8_t *TrampolineMem,
     194             :                                       void *ResolverAddr,
     195             :                                       unsigned NumTrampolines) {
     196             : 
     197           9 :   unsigned OffsetToPtr = NumTrampolines * TrampolineSize;
     198             : 
     199           9 :   memcpy(TrampolineMem + OffsetToPtr, &ResolverAddr, sizeof(void *));
     200             : 
     201           9 :   uint64_t *Trampolines = reinterpret_cast<uint64_t *>(TrampolineMem);
     202           9 :   uint64_t CallIndirPCRel = 0xf1c40000000015ff;
     203             : 
     204        4608 :   for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize)
     205        4599 :     Trampolines[I] = CallIndirPCRel | ((OffsetToPtr - 6) << 16);
     206           9 : }
     207             : 
     208           9 : Error OrcX86_64_Base::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
     209             :                                              unsigned MinStubs,
     210             :                                              void *InitialPtrVal) {
     211             :   // Stub format is:
     212             :   //
     213             :   // .section __orc_stubs
     214             :   // stub1:
     215             :   //                 jmpq    *ptr1(%rip)
     216             :   //                 .byte   0xC4         ; <- Invalid opcode padding.
     217             :   //                 .byte   0xF1
     218             :   // stub2:
     219             :   //                 jmpq    *ptr2(%rip)
     220             :   //
     221             :   // ...
     222             :   //
     223             :   // .section __orc_ptrs
     224             :   // ptr1:
     225             :   //                 .quad 0x0
     226             :   // ptr2:
     227             :   //                 .quad 0x0
     228             :   //
     229             :   // ...
     230             : 
     231           9 :   const unsigned StubSize = IndirectStubsInfo::StubSize;
     232             : 
     233             :   // Emit at least MinStubs, rounded up to fill the pages allocated.
     234           9 :   unsigned PageSize = sys::Process::getPageSize();
     235           9 :   unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
     236           9 :   unsigned NumStubs = (NumPages * PageSize) / StubSize;
     237             : 
     238             :   // Allocate memory for stubs and pointers in one call.
     239           9 :   std::error_code EC;
     240             :   auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
     241           9 :       2 * NumPages * PageSize, nullptr,
     242          27 :       sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
     243             : 
     244           9 :   if (EC)
     245           0 :     return errorCodeToError(EC);
     246             : 
     247             :   // Create separate MemoryBlocks representing the stubs and pointers.
     248          27 :   sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize);
     249           9 :   sys::MemoryBlock PtrsBlock(static_cast<char *>(StubsMem.base()) +
     250             :                                  NumPages * PageSize,
     251          27 :                              NumPages * PageSize);
     252             : 
     253             :   // Populate the stubs page stubs and mark it executable.
     254           9 :   uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlock.base());
     255           9 :   uint64_t PtrOffsetField = static_cast<uint64_t>(NumPages * PageSize - 6)
     256             :                             << 16;
     257        4617 :   for (unsigned I = 0; I < NumStubs; ++I)
     258        4608 :     Stub[I] = 0xF1C40000000025ff | PtrOffsetField;
     259             : 
     260           9 :   if (auto EC = sys::Memory::protectMappedMemory(
     261           9 :           StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC))
     262           0 :     return errorCodeToError(EC);
     263             : 
     264             :   // Initialize all pointers to point at FailureAddress.
     265           9 :   void **Ptr = reinterpret_cast<void **>(PtrsBlock.base());
     266        4617 :   for (unsigned I = 0; I < NumStubs; ++I)
     267        4608 :     Ptr[I] = InitialPtrVal;
     268             : 
     269          54 :   StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem));
     270             : 
     271          27 :   return Error::success();
     272             : }
     273             : 
     274          10 : void OrcX86_64_SysV::writeResolverCode(uint8_t *ResolverMem,
     275             :                                        JITReentryFn ReentryFn,
     276             :                                        void *CallbackMgr) {
     277             : 
     278          10 :   const uint8_t ResolverCode[] = {
     279             :       // resolver_entry:
     280             :       0x55,                                     // 0x00: pushq     %rbp
     281             :       0x48, 0x89, 0xe5,                         // 0x01: movq      %rsp, %rbp
     282             :       0x50,                                     // 0x04: pushq     %rax
     283             :       0x53,                                     // 0x05: pushq     %rbx
     284             :       0x51,                                     // 0x06: pushq     %rcx
     285             :       0x52,                                     // 0x07: pushq     %rdx
     286             :       0x56,                                     // 0x08: pushq     %rsi
     287             :       0x57,                                     // 0x09: pushq     %rdi
     288             :       0x41, 0x50,                               // 0x0a: pushq     %r8
     289             :       0x41, 0x51,                               // 0x0c: pushq     %r9
     290             :       0x41, 0x52,                               // 0x0e: pushq     %r10
     291             :       0x41, 0x53,                               // 0x10: pushq     %r11
     292             :       0x41, 0x54,                               // 0x12: pushq     %r12
     293             :       0x41, 0x55,                               // 0x14: pushq     %r13
     294             :       0x41, 0x56,                               // 0x16: pushq     %r14
     295             :       0x41, 0x57,                               // 0x18: pushq     %r15
     296             :       0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00, // 0x1a: subq      0x208, %rsp
     297             :       0x48, 0x0f, 0xae, 0x04, 0x24,             // 0x21: fxsave64  (%rsp)
     298             :       0x48, 0xbf,                               // 0x26: movabsq   <CBMgr>, %rdi
     299             : 
     300             :       // 0x28: Callback manager addr.
     301             :       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     302             : 
     303             :       0x48, 0x8b, 0x75, 0x08,                   // 0x30: movq      8(%rbp), %rsi
     304             :       0x48, 0x83, 0xee, 0x06,                   // 0x34: subq      $6, %rsi
     305             :       0x48, 0xb8,                               // 0x38: movabsq   <REntry>, %rax
     306             : 
     307             :       // 0x3a: JIT re-entry fn addr:
     308             :       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     309             : 
     310             :       0xff, 0xd0,                               // 0x42: callq     *%rax
     311             :       0x48, 0x89, 0x45, 0x08,                   // 0x44: movq      %rax, 8(%rbp)
     312             :       0x48, 0x0f, 0xae, 0x0c, 0x24,             // 0x48: fxrstor64 (%rsp)
     313             :       0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00, // 0x4d: addq      0x208, %rsp
     314             :       0x41, 0x5f,                               // 0x54: popq      %r15
     315             :       0x41, 0x5e,                               // 0x56: popq      %r14
     316             :       0x41, 0x5d,                               // 0x58: popq      %r13
     317             :       0x41, 0x5c,                               // 0x5a: popq      %r12
     318             :       0x41, 0x5b,                               // 0x5c: popq      %r11
     319             :       0x41, 0x5a,                               // 0x5e: popq      %r10
     320             :       0x41, 0x59,                               // 0x60: popq      %r9
     321             :       0x41, 0x58,                               // 0x62: popq      %r8
     322             :       0x5f,                                     // 0x64: popq      %rdi
     323             :       0x5e,                                     // 0x65: popq      %rsi
     324             :       0x5a,                                     // 0x66: popq      %rdx
     325             :       0x59,                                     // 0x67: popq      %rcx
     326             :       0x5b,                                     // 0x68: popq      %rbx
     327             :       0x58,                                     // 0x69: popq      %rax
     328             :       0x5d,                                     // 0x6a: popq      %rbp
     329             :       0xc3,                                     // 0x6b: retq
     330             :   };
     331             : 
     332          10 :   const unsigned ReentryFnAddrOffset = 0x3a;
     333          10 :   const unsigned CallbackMgrAddrOffset = 0x28;
     334             : 
     335          10 :   memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode));
     336          10 :   memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn));
     337          10 :   memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr,
     338             :          sizeof(CallbackMgr));
     339          10 : }
     340             : 
     341           0 : void OrcX86_64_Win32::writeResolverCode(uint8_t *ResolverMem,
     342             :                                         JITReentryFn ReentryFn,
     343             :                                         void *CallbackMgr) {
     344             : 
     345             :   // resolverCode is similar to OrcX86_64 with differences specific to windows x64 calling convention:
     346             :   // arguments go into rcx, rdx and come in reverse order, shadow space allocation on stack
     347           0 :   const uint8_t ResolverCode[] = {
     348             :       // resolver_entry:
     349             :       0x55,                                      // 0x00: pushq     %rbp
     350             :       0x48, 0x89, 0xe5,                          // 0x01: movq      %rsp, %rbp
     351             :       0x50,                                      // 0x04: pushq     %rax
     352             :       0x53,                                      // 0x05: pushq     %rbx
     353             :       0x51,                                      // 0x06: pushq     %rcx
     354             :       0x52,                                      // 0x07: pushq     %rdx
     355             :       0x56,                                      // 0x08: pushq     %rsi
     356             :       0x57,                                      // 0x09: pushq     %rdi
     357             :       0x41, 0x50,                                // 0x0a: pushq     %r8
     358             :       0x41, 0x51,                                // 0x0c: pushq     %r9
     359             :       0x41, 0x52,                                // 0x0e: pushq     %r10
     360             :       0x41, 0x53,                                // 0x10: pushq     %r11
     361             :       0x41, 0x54,                                // 0x12: pushq     %r12
     362             :       0x41, 0x55,                                // 0x14: pushq     %r13
     363             :       0x41, 0x56,                                // 0x16: pushq     %r14
     364             :       0x41, 0x57,                                // 0x18: pushq     %r15
     365             :       0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00,  // 0x1a: subq      0x208, %rsp
     366             :       0x48, 0x0f, 0xae, 0x04, 0x24,              // 0x21: fxsave64  (%rsp)
     367             : 
     368             :       0x48, 0xb9,                                // 0x26: movabsq   <CBMgr>, %rcx
     369             :       // 0x28: Callback manager addr.
     370             :       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     371             : 
     372             :       0x48, 0x8B, 0x55, 0x08,                    // 0x30: mov       rdx, [rbp+0x8]
     373             :       0x48, 0x83, 0xea, 0x06,                    // 0x34: sub       rdx, 0x6
     374             : 
     375             :       0x48, 0xb8,                                // 0x38: movabsq   <REntry>, %rax
     376             :       // 0x3a: JIT re-entry fn addr:
     377             :       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     378             : 
     379             :       // 0x42: sub       rsp, 0x20 (Allocate shadow space)
     380             :       0x48, 0x83, 0xEC, 0x20,
     381             :       0xff, 0xd0,                                // 0x46: callq     *%rax
     382             : 
     383             :       // 0x48: add       rsp, 0x20 (Free shadow space)
     384             :       0x48, 0x83, 0xC4, 0x20,
     385             : 
     386             :       0x48, 0x89, 0x45, 0x08,                    // 0x4C: movq      %rax, 8(%rbp)
     387             :       0x48, 0x0f, 0xae, 0x0c, 0x24,              // 0x50: fxrstor64 (%rsp)
     388             :       0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00,  // 0x55: addq      0x208, %rsp
     389             :       0x41, 0x5f,                                // 0x5C: popq      %r15
     390             :       0x41, 0x5e,                                // 0x5E: popq      %r14
     391             :       0x41, 0x5d,                                // 0x60: popq      %r13
     392             :       0x41, 0x5c,                                // 0x62: popq      %r12
     393             :       0x41, 0x5b,                                // 0x64: popq      %r11
     394             :       0x41, 0x5a,                                // 0x66: popq      %r10
     395             :       0x41, 0x59,                                // 0x68: popq      %r9
     396             :       0x41, 0x58,                                // 0x6a: popq      %r8
     397             :       0x5f,                                      // 0x6c: popq      %rdi
     398             :       0x5e,                                      // 0x6d: popq      %rsi
     399             :       0x5a,                                      // 0x6e: popq      %rdx
     400             :       0x59,                                      // 0x6f: popq      %rcx
     401             :       0x5b,                                      // 0x70: popq      %rbx
     402             :       0x58,                                      // 0x71: popq      %rax
     403             :       0x5d,                                      // 0x72: popq      %rbp
     404             :       0xc3,                                      // 0x73: retq
     405             :   };
     406             : 
     407             : 
     408           0 :   const unsigned ReentryFnAddrOffset = 0x3a;
     409           0 :   const unsigned CallbackMgrAddrOffset = 0x28;
     410             : 
     411           0 :   memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode));
     412           0 :   memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn));
     413           0 :   memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr,
     414             :          sizeof(CallbackMgr));
     415           0 : }
     416             : 
     417           0 : void OrcI386::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn,
     418             :                                 void *CallbackMgr) {
     419             : 
     420           0 :   const uint8_t ResolverCode[] = {
     421             :       // resolver_entry:
     422             :       0x55,                               // 0x00: pushl    %ebp
     423             :       0x89, 0xe5,                         // 0x01: movl     %esp, %ebp
     424             :       0x54,                               // 0x03: pushl    %esp
     425             :       0x83, 0xe4, 0xf0,                   // 0x04: andl     $-0x10, %esp
     426             :       0x50,                               // 0x07: pushl    %eax
     427             :       0x53,                               // 0x08: pushl    %ebx
     428             :       0x51,                               // 0x09: pushl    %ecx
     429             :       0x52,                               // 0x0a: pushl    %edx
     430             :       0x56,                               // 0x0b: pushl    %esi
     431             :       0x57,                               // 0x0c: pushl    %edi
     432             :       0x81, 0xec, 0x18, 0x02, 0x00, 0x00, // 0x0d: subl     $0x218, %esp
     433             :       0x0f, 0xae, 0x44, 0x24, 0x10,       // 0x13: fxsave   0x10(%esp)
     434             :       0x8b, 0x75, 0x04,                   // 0x18: movl     0x4(%ebp), %esi
     435             :       0x83, 0xee, 0x05,                   // 0x1b: subl     $0x5, %esi
     436             :       0x89, 0x74, 0x24, 0x04,             // 0x1e: movl     %esi, 0x4(%esp)
     437             :       0xc7, 0x04, 0x24, 0x00, 0x00, 0x00,
     438             :       0x00,                               // 0x22: movl     <cbmgr>, (%esp)
     439             :       0xb8, 0x00, 0x00, 0x00, 0x00,       // 0x29: movl     <reentry>, %eax
     440             :       0xff, 0xd0,                         // 0x2e: calll    *%eax
     441             :       0x89, 0x45, 0x04,                   // 0x30: movl     %eax, 0x4(%ebp)
     442             :       0x0f, 0xae, 0x4c, 0x24, 0x10,       // 0x33: fxrstor  0x10(%esp)
     443             :       0x81, 0xc4, 0x18, 0x02, 0x00, 0x00, // 0x38: addl     $0x218, %esp
     444             :       0x5f,                               // 0x3e: popl     %edi
     445             :       0x5e,                               // 0x3f: popl     %esi
     446             :       0x5a,                               // 0x40: popl     %edx
     447             :       0x59,                               // 0x41: popl     %ecx
     448             :       0x5b,                               // 0x42: popl     %ebx
     449             :       0x58,                               // 0x43: popl     %eax
     450             :       0x8b, 0x65, 0xfc,                   // 0x44: movl     -0x4(%ebp), %esp
     451             :       0x5d,                               // 0x48: popl     %ebp
     452             :       0xc3                                // 0x49: retl
     453             :   };
     454             : 
     455           0 :   const unsigned ReentryFnAddrOffset = 0x2a;
     456           0 :   const unsigned CallbackMgrAddrOffset = 0x25;
     457             : 
     458           0 :   memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode));
     459           0 :   memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn));
     460           0 :   memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr,
     461             :          sizeof(CallbackMgr));
     462           0 : }
     463             : 
     464           0 : void OrcI386::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
     465             :                                unsigned NumTrampolines) {
     466             : 
     467           0 :   uint64_t CallRelImm = 0xF1C4C400000000e8;
     468           0 :   uint64_t Resolver = reinterpret_cast<uint64_t>(ResolverAddr);
     469           0 :   uint64_t ResolverRel =
     470           0 :       Resolver - reinterpret_cast<uint64_t>(TrampolineMem) - 5;
     471             : 
     472           0 :   uint64_t *Trampolines = reinterpret_cast<uint64_t *>(TrampolineMem);
     473           0 :   for (unsigned I = 0; I < NumTrampolines; ++I, ResolverRel -= TrampolineSize)
     474           0 :     Trampolines[I] = CallRelImm | (ResolverRel << 8);
     475           0 : }
     476             : 
     477           0 : Error OrcI386::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
     478             :                                       unsigned MinStubs, void *InitialPtrVal) {
     479             :   // Stub format is:
     480             :   //
     481             :   // .section __orc_stubs
     482             :   // stub1:
     483             :   //                 jmpq    *ptr1
     484             :   //                 .byte   0xC4         ; <- Invalid opcode padding.
     485             :   //                 .byte   0xF1
     486             :   // stub2:
     487             :   //                 jmpq    *ptr2
     488             :   //
     489             :   // ...
     490             :   //
     491             :   // .section __orc_ptrs
     492             :   // ptr1:
     493             :   //                 .quad 0x0
     494             :   // ptr2:
     495             :   //                 .quad 0x0
     496             :   //
     497             :   // ...
     498             : 
     499           0 :   const unsigned StubSize = IndirectStubsInfo::StubSize;
     500             : 
     501             :   // Emit at least MinStubs, rounded up to fill the pages allocated.
     502           0 :   unsigned PageSize = sys::Process::getPageSize();
     503           0 :   unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
     504           0 :   unsigned NumStubs = (NumPages * PageSize) / StubSize;
     505             : 
     506             :   // Allocate memory for stubs and pointers in one call.
     507           0 :   std::error_code EC;
     508             :   auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
     509           0 :       2 * NumPages * PageSize, nullptr,
     510           0 :       sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
     511             : 
     512           0 :   if (EC)
     513           0 :     return errorCodeToError(EC);
     514             : 
     515             :   // Create separate MemoryBlocks representing the stubs and pointers.
     516           0 :   sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize);
     517           0 :   sys::MemoryBlock PtrsBlock(static_cast<char *>(StubsMem.base()) +
     518             :                                  NumPages * PageSize,
     519           0 :                              NumPages * PageSize);
     520             : 
     521             :   // Populate the stubs page stubs and mark it executable.
     522           0 :   uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlock.base());
     523           0 :   uint64_t PtrAddr = reinterpret_cast<uint64_t>(PtrsBlock.base());
     524           0 :   for (unsigned I = 0; I < NumStubs; ++I, PtrAddr += 4)
     525           0 :     Stub[I] = 0xF1C40000000025ff | (PtrAddr << 16);
     526             : 
     527           0 :   if (auto EC = sys::Memory::protectMappedMemory(
     528           0 :           StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC))
     529           0 :     return errorCodeToError(EC);
     530             : 
     531             :   // Initialize all pointers to point at FailureAddress.
     532           0 :   void **Ptr = reinterpret_cast<void **>(PtrsBlock.base());
     533           0 :   for (unsigned I = 0; I < NumStubs; ++I)
     534           0 :     Ptr[I] = InitialPtrVal;
     535             : 
     536           0 :   StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem));
     537             : 
     538           0 :   return Error::success();
     539             : }
     540             : 
     541             : } // End namespace orc.
     542             : } // End namespace llvm.

Generated by: LCOV version 1.13