Ejemplo n.º 1
0
uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) {
  if (Arch == Triple::aarch64) {
    // This stub has to be able to access the full address space,
    // since symbol lookup won't necessarily find a handy, in-range,
    // PLT stub for functions which could be anywhere.
    uint32_t *StubAddr = (uint32_t*)Addr;

    // Stub can use ip0 (== x16) to calculate address
    *StubAddr = 0xd2e00010; // movz ip0, #:abs_g3:<addr>
    StubAddr++;
    *StubAddr = 0xf2c00010; // movk ip0, #:abs_g2_nc:<addr>
    StubAddr++;
    *StubAddr = 0xf2a00010; // movk ip0, #:abs_g1_nc:<addr>
    StubAddr++;
    *StubAddr = 0xf2800010; // movk ip0, #:abs_g0_nc:<addr>
    StubAddr++;
    *StubAddr = 0xd61f0200; // br ip0

    return Addr;
  } else if (Arch == Triple::arm) {
    // TODO: There is only ARM far stub now. We should add the Thumb stub,
    // and stubs for branches Thumb - ARM and ARM - Thumb.
    uint32_t *StubAddr = (uint32_t*)Addr;
    *StubAddr = 0xe51ff004; // ldr pc,<label>
    return (uint8_t*)++StubAddr;
  } else if (Arch == Triple::mipsel || Arch == Triple::mips) {
    uint32_t *StubAddr = (uint32_t*)Addr;
    // 0:   3c190000        lui     t9,%hi(addr).
    // 4:   27390000        addiu   t9,t9,%lo(addr).
    // 8:   03200008        jr      t9.
    // c:   00000000        nop.
    const unsigned LuiT9Instr = 0x3c190000, AdduiT9Instr = 0x27390000;
    const unsigned JrT9Instr = 0x03200008, NopInstr = 0x0;

    *StubAddr = LuiT9Instr;
    StubAddr++;
    *StubAddr = AdduiT9Instr;
    StubAddr++;
    *StubAddr = JrT9Instr;
    StubAddr++;
    *StubAddr = NopInstr;
    return Addr;
  } else if (Arch == Triple::ppc64) {
    // PowerPC64 stub: the address points to a function descriptor
    // instead of the function itself. Load the function address
    // on r11 and sets it to control register. Also loads the function
    // TOC in r2 and environment pointer to r11.
    writeInt32BE(Addr,    0x3D800000); // lis   r12, highest(addr)
    writeInt32BE(Addr+4,  0x618C0000); // ori   r12, higher(addr)
    writeInt32BE(Addr+8,  0x798C07C6); // sldi  r12, r12, 32
    writeInt32BE(Addr+12, 0x658C0000); // oris  r12, r12, h(addr)
    writeInt32BE(Addr+16, 0x618C0000); // ori   r12, r12, l(addr)
    writeInt32BE(Addr+20, 0xF8410028); // std   r2,  40(r1)
    writeInt32BE(Addr+24, 0xE96C0000); // ld    r11, 0(r12)
    writeInt32BE(Addr+28, 0xE84C0008); // ld    r2,  0(r12)
    writeInt32BE(Addr+32, 0x7D6903A6); // mtctr r11
    writeInt32BE(Addr+36, 0xE96C0010); // ld    r11, 16(r2)
    writeInt32BE(Addr+40, 0x4E800420); // bctr

    return Addr;
  } else if (Arch == Triple::systemz) {
    writeInt16BE(Addr,    0xC418);     // lgrl %r1,.+8
    writeInt16BE(Addr+2,  0x0000);
    writeInt16BE(Addr+4,  0x0004);
    writeInt16BE(Addr+6,  0x07F1);     // brc 15,%r1
    // 8-byte address stored at Addr + 8
    return Addr;
  }
  return Addr;
}
Ejemplo n.º 2
0
 //--------------------------------------------------------------
 void
 DataStream::writeUint16BE(u16 n)
 {
     writeInt16BE((i16)n);
 }