diff options
Diffstat (limited to 'ELF/Arch/X86.cpp')
| -rw-r--r-- | ELF/Arch/X86.cpp | 442 |
1 files changed, 221 insertions, 221 deletions
diff --git a/ELF/Arch/X86.cpp b/ELF/Arch/X86.cpp index e910375d2fc75..e1dd231e8e8d4 100644 --- a/ELF/Arch/X86.cpp +++ b/ELF/Arch/X86.cpp @@ -1,9 +1,8 @@ //===- X86.cpp ------------------------------------------------------------===// // -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -24,63 +23,73 @@ namespace { class X86 : public TargetInfo { public: X86(); - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override; - void writeGotPltHeader(uint8_t *Buf) const override; - RelType getDynRel(RelType Type) const override; - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; - void writeIgotPlt(uint8_t *Buf, const Symbol &S) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; - - RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr Expr) const override; - void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; + int getTlsGdRelaxSkip(RelType type) const override; + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override; + void writeGotPltHeader(uint8_t *buf) const override; + RelType getDynRel(RelType type) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override; + void writeIgotPlt(uint8_t *buf, const Symbol &s) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; + + RelExpr adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr expr) const override; + void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const override; }; } // namespace X86::X86() { - CopyRel = R_386_COPY; - GotRel = R_386_GLOB_DAT; - NoneRel = R_386_NONE; - PltRel = R_386_JUMP_SLOT; - IRelativeRel = R_386_IRELATIVE; - RelativeRel = R_386_RELATIVE; - TlsGotRel = R_386_TLS_TPOFF; - TlsModuleIndexRel = R_386_TLS_DTPMOD32; - TlsOffsetRel = R_386_TLS_DTPOFF32; - GotEntrySize = 4; - GotPltEntrySize = 4; - PltEntrySize = 16; - PltHeaderSize = 16; - TlsGdRelaxSkip = 2; - TrapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3 + copyRel = R_386_COPY; + gotRel = R_386_GLOB_DAT; + noneRel = R_386_NONE; + pltRel = R_386_JUMP_SLOT; + iRelativeRel = R_386_IRELATIVE; + relativeRel = R_386_RELATIVE; + symbolicRel = R_386_32; + tlsGotRel = R_386_TLS_TPOFF; + tlsModuleIndexRel = R_386_TLS_DTPMOD32; + tlsOffsetRel = R_386_TLS_DTPOFF32; + pltEntrySize = 16; + pltHeaderSize = 16; + trapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3 // Align to the non-PAE large page size (known as a superpage or huge page). // FreeBSD automatically promotes large, superpage-aligned allocations. - DefaultImageBase = 0x400000; + defaultImageBase = 0x400000; } -static bool hasBaseReg(uint8_t ModRM) { return (ModRM & 0xc7) != 0x5; } +int X86::getTlsGdRelaxSkip(RelType type) const { + return 2; +} -RelExpr X86::getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const { - switch (Type) { +RelExpr X86::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { + // There are 4 different TLS variable models with varying degrees of + // flexibility and performance. LocalExec and InitialExec models are fast but + // less-flexible models. If they are in use, we set DF_STATIC_TLS flag in the + // dynamic section to let runtime know about that. + if (type == R_386_TLS_LE || type == R_386_TLS_LE_32 || type == R_386_TLS_IE || + type == R_386_TLS_GOTIE) + config->hasStaticTlsModel = true; + + switch (type) { case R_386_8: case R_386_16: case R_386_32: - case R_386_TLS_LDO_32: return R_ABS; + case R_386_TLS_LDO_32: + return R_DTPREL; case R_386_TLS_GD: - return R_TLSGD_GOT_FROM_END; + return R_TLSGD_GOTPLT; case R_386_TLS_LDM: - return R_TLSLD_GOT_FROM_END; + return R_TLSLD_GOTPLT; case R_386_PLT32: return R_PLT_PC; case R_386_PC8: @@ -88,7 +97,7 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S, case R_386_PC32: return R_PC; case R_386_GOTPC: - return R_GOTONLY_PC_FROM_END; + return R_GOTPLTONLY_PC; case R_386_TLS_IE: return R_GOT; case R_386_GOT32: @@ -108,14 +117,14 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S, // load an GOT address to a register, which is usually %ebx. // // So, there are two ways to refer to symbol foo's GOT entry: foo@GOT or - // foo@GOT(%reg). + // foo@GOT(%ebx). // // foo@GOT is not usable in PIC. If we are creating a PIC output and if we // find such relocation, we should report an error. foo@GOT is resolved to // an *absolute* address of foo's GOT entry, because both GOT address and // foo's offset are known. In other words, it's G + A. // - // foo@GOT(%reg) needs to be resolved to a *relative* offset from a GOT to + // foo@GOT(%ebx) needs to be resolved to a *relative* offset from a GOT to // foo's GOT entry in the table, because GOT address is not known but foo's // offset in the table is known. It's G + A - GOT. // @@ -123,16 +132,16 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S, // different use cases. In order to distinguish them, we have to read a // machine instruction. // - // The following code implements it. We assume that Loc[0] is the first - // byte of a displacement or an immediate field of a valid machine + // The following code implements it. We assume that Loc[0] is the first byte + // of a displacement or an immediate field of a valid machine // instruction. That means a ModRM byte is at Loc[-1]. By taking a look at - // the byte, we can determine whether the instruction is register-relative - // (i.e. it was generated for foo@GOT(%reg)) or absolute (i.e. foo@GOT). - return hasBaseReg(Loc[-1]) ? R_GOT_FROM_END : R_GOT; + // the byte, we can determine whether the instruction uses the operand as an + // absolute address (R_GOT) or a register-relative address (R_GOTPLT). + return (loc[-1] & 0xc7) == 0x5 ? R_GOT : R_GOTPLT; case R_386_TLS_GOTIE: - return R_GOT_FROM_END; + return R_GOTPLT; case R_386_GOTOFF: - return R_GOTREL_FROM_END; + return R_GOTPLTREL; case R_386_TLS_LE: return R_TLS; case R_386_TLS_LE_32: @@ -140,105 +149,102 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S, case R_386_NONE: return R_NONE; default: - return R_INVALID; + error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + + ") against symbol " + toString(s)); + return R_NONE; } } -RelExpr X86::adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr Expr) const { - switch (Expr) { +RelExpr X86::adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr expr) const { + switch (expr) { default: - return Expr; + return expr; case R_RELAX_TLS_GD_TO_IE: - return R_RELAX_TLS_GD_TO_IE_END; + return R_RELAX_TLS_GD_TO_IE_GOTPLT; case R_RELAX_TLS_GD_TO_LE: return R_RELAX_TLS_GD_TO_LE_NEG; } } -void X86::writeGotPltHeader(uint8_t *Buf) const { - write32le(Buf, In.Dynamic->getVA()); +void X86::writeGotPltHeader(uint8_t *buf) const { + write32le(buf, mainPart->dynamic->getVA()); } -void X86::writeGotPlt(uint8_t *Buf, const Symbol &S) const { +void X86::writeGotPlt(uint8_t *buf, const Symbol &s) const { // Entries in .got.plt initially points back to the corresponding // PLT entries with a fixed offset to skip the first instruction. - write32le(Buf, S.getPltVA() + 6); + write32le(buf, s.getPltVA() + 6); } -void X86::writeIgotPlt(uint8_t *Buf, const Symbol &S) const { +void X86::writeIgotPlt(uint8_t *buf, const Symbol &s) const { // An x86 entry is the address of the ifunc resolver function. - write32le(Buf, S.getVA()); + write32le(buf, s.getVA()); } -RelType X86::getDynRel(RelType Type) const { - if (Type == R_386_TLS_LE) +RelType X86::getDynRel(RelType type) const { + if (type == R_386_TLS_LE) return R_386_TLS_TPOFF; - if (Type == R_386_TLS_LE_32) + if (type == R_386_TLS_LE_32) return R_386_TLS_TPOFF32; - return Type; + return type; } -void X86::writePltHeader(uint8_t *Buf) const { - if (Config->Pic) { - const uint8_t V[] = { - 0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl GOTPLT+4(%ebx) - 0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *GOTPLT+8(%ebx) +void X86::writePltHeader(uint8_t *buf) const { + if (config->isPic) { + const uint8_t v[] = { + 0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl 4(%ebx) + 0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *8(%ebx) 0x90, 0x90, 0x90, 0x90 // nop }; - memcpy(Buf, V, sizeof(V)); - - uint32_t Ebx = In.Got->getVA() + In.Got->getSize(); - uint32_t GotPlt = In.GotPlt->getVA() - Ebx; - write32le(Buf + 2, GotPlt + 4); - write32le(Buf + 8, GotPlt + 8); + memcpy(buf, v, sizeof(v)); return; } - const uint8_t PltData[] = { + const uint8_t pltData[] = { 0xff, 0x35, 0, 0, 0, 0, // pushl (GOTPLT+4) 0xff, 0x25, 0, 0, 0, 0, // jmp *(GOTPLT+8) 0x90, 0x90, 0x90, 0x90, // nop }; - memcpy(Buf, PltData, sizeof(PltData)); - uint32_t GotPlt = In.GotPlt->getVA(); - write32le(Buf + 2, GotPlt + 4); - write32le(Buf + 8, GotPlt + 8); + memcpy(buf, pltData, sizeof(pltData)); + uint32_t gotPlt = in.gotPlt->getVA(); + write32le(buf + 2, gotPlt + 4); + write32le(buf + 8, gotPlt + 8); } -void X86::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - const uint8_t Inst[] = { - 0xff, 0x00, 0, 0, 0, 0, // jmp *foo_in_GOT or jmp *foo@GOT(%ebx) - 0x68, 0, 0, 0, 0, // pushl $reloc_offset - 0xe9, 0, 0, 0, 0, // jmp .PLT0@PC - }; - memcpy(Buf, Inst, sizeof(Inst)); - - if (Config->Pic) { - // jmp *foo@GOT(%ebx) - uint32_t Ebx = In.Got->getVA() + In.Got->getSize(); - Buf[1] = 0xa3; - write32le(Buf + 2, GotPltEntryAddr - Ebx); +void X86::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + if (config->isPic) { + const uint8_t inst[] = { + 0xff, 0xa3, 0, 0, 0, 0, // jmp *foo@GOT(%ebx) + 0x68, 0, 0, 0, 0, // pushl $reloc_offset + 0xe9, 0, 0, 0, 0, // jmp .PLT0@PC + }; + memcpy(buf, inst, sizeof(inst)); + write32le(buf + 2, gotPltEntryAddr - in.gotPlt->getVA()); } else { - // jmp *foo_in_GOT - Buf[1] = 0x25; - write32le(Buf + 2, GotPltEntryAddr); + const uint8_t inst[] = { + 0xff, 0x25, 0, 0, 0, 0, // jmp *foo@GOT + 0x68, 0, 0, 0, 0, // pushl $reloc_offset + 0xe9, 0, 0, 0, 0, // jmp .PLT0@PC + }; + memcpy(buf, inst, sizeof(inst)); + write32le(buf + 2, gotPltEntryAddr); } - write32le(Buf + 7, RelOff); - write32le(Buf + 12, -getPltEntryOffset(Index) - 16); + write32le(buf + 7, relOff); + write32le(buf + 12, -pltHeaderSize - pltEntrySize * index - 16); } -int64_t X86::getImplicitAddend(const uint8_t *Buf, RelType Type) const { - switch (Type) { +int64_t X86::getImplicitAddend(const uint8_t *buf, RelType type) const { + switch (type) { case R_386_8: case R_386_PC8: - return SignExtend64<8>(*Buf); + return SignExtend64<8>(*buf); case R_386_16: case R_386_PC16: - return SignExtend64<16>(read16le(Buf)); + return SignExtend64<16>(read16le(buf)); case R_386_32: case R_386_GOT32: case R_386_GOT32X: @@ -248,28 +254,28 @@ int64_t X86::getImplicitAddend(const uint8_t *Buf, RelType Type) const { case R_386_PLT32: case R_386_TLS_LDO_32: case R_386_TLS_LE: - return SignExtend64<32>(read32le(Buf)); + return SignExtend64<32>(read32le(buf)); default: return 0; } } -void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void X86::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_386_8: // R_386_{PC,}{8,16} are not part of the i386 psABI, but they are // being used for some 16-bit programs such as boot loaders, so // we want to support them. - checkIntUInt(Loc, Val, 8, Type); - *Loc = Val; + checkIntUInt(loc, val, 8, type); + *loc = val; break; case R_386_PC8: - checkInt(Loc, Val, 8, Type); - *Loc = Val; + checkInt(loc, val, 8, type); + *loc = val; break; case R_386_16: - checkIntUInt(Loc, Val, 16, Type); - write16le(Loc, Val); + checkIntUInt(loc, val, 16, type); + write16le(loc, val); break; case R_386_PC16: // R_386_PC16 is normally used with 16 bit code. In that situation @@ -282,11 +288,10 @@ void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { // current location subtracted from it. // We just check that Val fits in 17 bits. This misses some cases, but // should have no false positives. - checkInt(Loc, Val, 17, Type); - write16le(Loc, Val); + checkInt(loc, val, 17, type); + write16le(loc, val); break; case R_386_32: - case R_386_GLOB_DAT: case R_386_GOT32: case R_386_GOT32X: case R_386_GOTOFF: @@ -305,86 +310,86 @@ void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { case R_386_TLS_LE_32: case R_386_TLS_TPOFF: case R_386_TLS_TPOFF32: - checkInt(Loc, Val, 32, Type); - write32le(Loc, Val); + checkInt(loc, val, 32, type); + write32le(loc, val); break; default: - error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); + llvm_unreachable("unknown relocation"); } } -void X86::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { +void X86::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const { // Convert // leal x@tlsgd(, %ebx, 1), // call __tls_get_addr@plt // to // movl %gs:0,%eax // subl $x@ntpoff,%eax - const uint8_t Inst[] = { + const uint8_t inst[] = { 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax 0x81, 0xe8, 0, 0, 0, 0, // subl Val(%ebx), %eax }; - memcpy(Loc - 3, Inst, sizeof(Inst)); - write32le(Loc + 5, Val); + memcpy(loc - 3, inst, sizeof(inst)); + write32le(loc + 5, val); } -void X86::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const { +void X86::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const { // Convert // leal x@tlsgd(, %ebx, 1), // call __tls_get_addr@plt // to // movl %gs:0, %eax // addl x@gotntpoff(%ebx), %eax - const uint8_t Inst[] = { + const uint8_t inst[] = { 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax 0x03, 0x83, 0, 0, 0, 0, // addl Val(%ebx), %eax }; - memcpy(Loc - 3, Inst, sizeof(Inst)); - write32le(Loc + 5, Val); + memcpy(loc - 3, inst, sizeof(inst)); + write32le(loc + 5, val); } // In some conditions, relocations can be optimized to avoid using GOT. // This function does that for Initial Exec to Local Exec case. -void X86::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { +void X86::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const { // Ulrich's document section 6.2 says that @gotntpoff can // be used with MOVL or ADDL instructions. // @indntpoff is similar to @gotntpoff, but for use in // position dependent code. - uint8_t Reg = (Loc[-1] >> 3) & 7; + uint8_t reg = (loc[-1] >> 3) & 7; - if (Type == R_386_TLS_IE) { - if (Loc[-1] == 0xa1) { + if (type == R_386_TLS_IE) { + if (loc[-1] == 0xa1) { // "movl foo@indntpoff,%eax" -> "movl $foo,%eax" // This case is different from the generic case below because // this is a 5 byte instruction while below is 6 bytes. - Loc[-1] = 0xb8; - } else if (Loc[-2] == 0x8b) { + loc[-1] = 0xb8; + } else if (loc[-2] == 0x8b) { // "movl foo@indntpoff,%reg" -> "movl $foo,%reg" - Loc[-2] = 0xc7; - Loc[-1] = 0xc0 | Reg; + loc[-2] = 0xc7; + loc[-1] = 0xc0 | reg; } else { // "addl foo@indntpoff,%reg" -> "addl $foo,%reg" - Loc[-2] = 0x81; - Loc[-1] = 0xc0 | Reg; + loc[-2] = 0x81; + loc[-1] = 0xc0 | reg; } } else { - assert(Type == R_386_TLS_GOTIE); - if (Loc[-2] == 0x8b) { + assert(type == R_386_TLS_GOTIE); + if (loc[-2] == 0x8b) { // "movl foo@gottpoff(%rip),%reg" -> "movl $foo,%reg" - Loc[-2] = 0xc7; - Loc[-1] = 0xc0 | Reg; + loc[-2] = 0xc7; + loc[-1] = 0xc0 | reg; } else { // "addl foo@gotntpoff(%rip),%reg" -> "leal foo(%reg),%reg" - Loc[-2] = 0x8d; - Loc[-1] = 0x80 | (Reg << 3) | Reg; + loc[-2] = 0x8d; + loc[-1] = 0x80 | (reg << 3) | reg; } } - write32le(Loc, Val); + write32le(loc, val); } -void X86::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { - if (Type == R_386_TLS_LDO_32) { - write32le(Loc, Val); +void X86::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const { + if (type == R_386_TLS_LDO_32) { + write32le(loc, val); return; } @@ -395,48 +400,48 @@ void X86::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { // movl %gs:0,%eax // nop // leal 0(%esi,1),%esi - const uint8_t Inst[] = { + const uint8_t inst[] = { 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax 0x90, // nop 0x8d, 0x74, 0x26, 0x00, // leal 0(%esi,1),%esi }; - memcpy(Loc - 2, Inst, sizeof(Inst)); + memcpy(loc - 2, inst, sizeof(inst)); } namespace { class RetpolinePic : public X86 { public: RetpolinePic(); - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; }; class RetpolineNoPic : public X86 { public: RetpolineNoPic(); - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; }; } // namespace RetpolinePic::RetpolinePic() { - PltHeaderSize = 48; - PltEntrySize = 32; + pltHeaderSize = 48; + pltEntrySize = 32; } -void RetpolinePic::writeGotPlt(uint8_t *Buf, const Symbol &S) const { - write32le(Buf, S.getPltVA() + 17); +void RetpolinePic::writeGotPlt(uint8_t *buf, const Symbol &s) const { + write32le(buf, s.getPltVA() + 17); } -void RetpolinePic::writePltHeader(uint8_t *Buf) const { - const uint8_t Insn[] = { - 0xff, 0xb3, 0, 0, 0, 0, // 0: pushl GOTPLT+4(%ebx) +void RetpolinePic::writePltHeader(uint8_t *buf) const { + const uint8_t insn[] = { + 0xff, 0xb3, 4, 0, 0, 0, // 0: pushl 4(%ebx) 0x50, // 6: pushl %eax - 0x8b, 0x83, 0, 0, 0, 0, // 7: mov GOTPLT+8(%ebx), %eax + 0x8b, 0x83, 8, 0, 0, 0, // 7: mov 8(%ebx), %eax 0xe8, 0x0e, 0x00, 0x00, 0x00, // d: call next 0xf3, 0x90, // 12: loop: pause 0x0f, 0xae, 0xe8, // 14: lfence @@ -450,18 +455,13 @@ void RetpolinePic::writePltHeader(uint8_t *Buf) const { 0xc3, // 2e: ret 0xcc, // 2f: int3; padding }; - memcpy(Buf, Insn, sizeof(Insn)); - - uint32_t Ebx = In.Got->getVA() + In.Got->getSize(); - uint32_t GotPlt = In.GotPlt->getVA() - Ebx; - write32le(Buf + 2, GotPlt + 4); - write32le(Buf + 9, GotPlt + 8); + memcpy(buf, insn, sizeof(insn)); } -void RetpolinePic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - const uint8_t Insn[] = { +void RetpolinePic::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + const uint8_t insn[] = { 0x50, // pushl %eax 0x8b, 0x83, 0, 0, 0, 0, // mov foo@GOT(%ebx), %eax 0xe8, 0, 0, 0, 0, // call plt+0x20 @@ -470,28 +470,28 @@ void RetpolinePic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, 0xe9, 0, 0, 0, 0, // jmp plt+0 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // int3; padding }; - memcpy(Buf, Insn, sizeof(Insn)); - - uint32_t Ebx = In.Got->getVA() + In.Got->getSize(); - unsigned Off = getPltEntryOffset(Index); - write32le(Buf + 3, GotPltEntryAddr - Ebx); - write32le(Buf + 8, -Off - 12 + 32); - write32le(Buf + 13, -Off - 17 + 18); - write32le(Buf + 18, RelOff); - write32le(Buf + 23, -Off - 27); + memcpy(buf, insn, sizeof(insn)); + + uint32_t ebx = in.gotPlt->getVA(); + unsigned off = pltHeaderSize + pltEntrySize * index; + write32le(buf + 3, gotPltEntryAddr - ebx); + write32le(buf + 8, -off - 12 + 32); + write32le(buf + 13, -off - 17 + 18); + write32le(buf + 18, relOff); + write32le(buf + 23, -off - 27); } RetpolineNoPic::RetpolineNoPic() { - PltHeaderSize = 48; - PltEntrySize = 32; + pltHeaderSize = 48; + pltEntrySize = 32; } -void RetpolineNoPic::writeGotPlt(uint8_t *Buf, const Symbol &S) const { - write32le(Buf, S.getPltVA() + 16); +void RetpolineNoPic::writeGotPlt(uint8_t *buf, const Symbol &s) const { + write32le(buf, s.getPltVA() + 16); } -void RetpolineNoPic::writePltHeader(uint8_t *Buf) const { - const uint8_t Insn[] = { +void RetpolineNoPic::writePltHeader(uint8_t *buf) const { + const uint8_t insn[] = { 0xff, 0x35, 0, 0, 0, 0, // 0: pushl GOTPLT+4 0x50, // 6: pushl %eax 0xa1, 0, 0, 0, 0, // 7: mov GOTPLT+8, %eax @@ -509,17 +509,17 @@ void RetpolineNoPic::writePltHeader(uint8_t *Buf) const { 0xc3, // 2e: ret 0xcc, // 2f: int3; padding }; - memcpy(Buf, Insn, sizeof(Insn)); + memcpy(buf, insn, sizeof(insn)); - uint32_t GotPlt = In.GotPlt->getVA(); - write32le(Buf + 2, GotPlt + 4); - write32le(Buf + 8, GotPlt + 8); + uint32_t gotPlt = in.gotPlt->getVA(); + write32le(buf + 2, gotPlt + 4); + write32le(buf + 8, gotPlt + 8); } -void RetpolineNoPic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - const uint8_t Insn[] = { +void RetpolineNoPic::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + const uint8_t insn[] = { 0x50, // 0: pushl %eax 0xa1, 0, 0, 0, 0, // 1: mov foo_in_GOT, %eax 0xe8, 0, 0, 0, 0, // 6: call plt+0x20 @@ -529,26 +529,26 @@ void RetpolineNoPic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a: int3; padding 0xcc, // 1f: int3; padding }; - memcpy(Buf, Insn, sizeof(Insn)); - - unsigned Off = getPltEntryOffset(Index); - write32le(Buf + 2, GotPltEntryAddr); - write32le(Buf + 7, -Off - 11 + 32); - write32le(Buf + 12, -Off - 16 + 17); - write32le(Buf + 17, RelOff); - write32le(Buf + 22, -Off - 26); + memcpy(buf, insn, sizeof(insn)); + + unsigned off = pltHeaderSize + pltEntrySize * index; + write32le(buf + 2, gotPltEntryAddr); + write32le(buf + 7, -off - 11 + 32); + write32le(buf + 12, -off - 16 + 17); + write32le(buf + 17, relOff); + write32le(buf + 22, -off - 26); } TargetInfo *elf::getX86TargetInfo() { - if (Config->ZRetpolineplt) { - if (Config->Pic) { - static RetpolinePic T; - return &T; + if (config->zRetpolineplt) { + if (config->isPic) { + static RetpolinePic t; + return &t; } - static RetpolineNoPic T; - return &T; + static RetpolineNoPic t; + return &t; } - static X86 T; - return &T; + static X86 t; + return &t; } |
