summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2020-08-03 14:32:30 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2020-08-03 14:32:30 +0000
commit8f8ec7ff389bebdde7d14b98698aa753205f9def (patch)
tree721fb9bae592799d3f5322785fd9372706a3fccb
parent44230f891eeb122003744afd25bc38f749bf8483 (diff)
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom tested by plenty
-rw-r--r--gnu/llvm/lld/ELF/Arch/X86_64.cpp479
1 files changed, 45 insertions, 434 deletions
diff --git a/gnu/llvm/lld/ELF/Arch/X86_64.cpp b/gnu/llvm/lld/ELF/Arch/X86_64.cpp
index 514ddc5ec8b..74b72eb9129 100644
--- a/gnu/llvm/lld/ELF/Arch/X86_64.cpp
+++ b/gnu/llvm/lld/ELF/Arch/X86_64.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "InputFiles.h"
-#include "OutputSections.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
@@ -19,8 +18,9 @@ using namespace llvm;
using namespace llvm::object;
using namespace llvm::support::endian;
using namespace llvm::ELF;
-using namespace lld;
-using namespace lld::elf;
+
+namespace lld {
+namespace elf {
namespace {
class X86_64 : public TargetInfo {
@@ -32,49 +32,23 @@ public:
RelType getDynRel(RelType type) const override;
void writeGotPltHeader(uint8_t *buf) 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, const Symbol &sym,
uint64_t pltEntryAddr) const override;
- void relocate(uint8_t *loc, const Relocation &rel,
- uint64_t val) const override;
- int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
- void applyJumpInstrMod(uint8_t *loc, JumpModType type,
- unsigned size) const override;
-
- RelExpr adjustGotPcExpr(RelType type, int64_t addend,
- const uint8_t *loc) const override;
- void relaxGot(uint8_t *loc, const Relocation &rel,
- uint64_t val) const override;
- void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
- uint64_t val) const override;
- void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
- uint64_t val) const override;
- void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
- uint64_t val) const override;
- void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
- uint64_t val) 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 relaxGot(uint8_t *loc, RelType type, uint64_t val) 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;
bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
uint8_t stOther) const override;
- bool deleteFallThruJmpInsn(InputSection &is, InputFile *file,
- InputSection *nextIS) const override;
};
} // namespace
-// This is vector of NOP instructions of sizes from 1 to 8 bytes. The
-// appropriately sized instructions are used to fill the gaps between sections
-// which are executed during fall through.
-static const std::vector<std::vector<uint8_t>> nopInstructions = {
- {0x90},
- {0x66, 0x90},
- {0x0f, 0x1f, 0x00},
- {0x0f, 0x1f, 0x40, 0x00},
- {0x0f, 0x1f, 0x44, 0x00, 0x00},
- {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
- {0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
- {0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}};
-
X86_64::X86_64() {
copyRel = R_X86_64_COPY;
gotRel = R_X86_64_GLOB_DAT;
@@ -87,12 +61,10 @@ X86_64::X86_64() {
tlsGotRel = R_X86_64_TPOFF64;
tlsModuleIndexRel = R_X86_64_DTPMOD64;
tlsOffsetRel = R_X86_64_DTPOFF64;
- gotEntrySize = 8;
pltHeaderSize = 16;
pltEntrySize = 16;
ipltEntrySize = 16;
trapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3
- nopInstrs = nopInstructions;
// Align to the large page size (known as a superpage or huge page).
// FreeBSD automatically promotes large, superpage-aligned allocations.
@@ -101,216 +73,6 @@ X86_64::X86_64() {
int X86_64::getTlsGdRelaxSkip(RelType type) const { return 2; }
-// Opcodes for the different X86_64 jmp instructions.
-enum JmpInsnOpcode : uint32_t {
- J_JMP_32,
- J_JNE_32,
- J_JE_32,
- J_JG_32,
- J_JGE_32,
- J_JB_32,
- J_JBE_32,
- J_JL_32,
- J_JLE_32,
- J_JA_32,
- J_JAE_32,
- J_UNKNOWN,
-};
-
-// Given the first (optional) and second byte of the insn's opcode, this
-// returns the corresponding enum value.
-static JmpInsnOpcode getJmpInsnType(const uint8_t *first,
- const uint8_t *second) {
- if (*second == 0xe9)
- return J_JMP_32;
-
- if (first == nullptr)
- return J_UNKNOWN;
-
- if (*first == 0x0f) {
- switch (*second) {
- case 0x84:
- return J_JE_32;
- case 0x85:
- return J_JNE_32;
- case 0x8f:
- return J_JG_32;
- case 0x8d:
- return J_JGE_32;
- case 0x82:
- return J_JB_32;
- case 0x86:
- return J_JBE_32;
- case 0x8c:
- return J_JL_32;
- case 0x8e:
- return J_JLE_32;
- case 0x87:
- return J_JA_32;
- case 0x83:
- return J_JAE_32;
- }
- }
- return J_UNKNOWN;
-}
-
-// Return the relocation index for input section IS with a specific Offset.
-// Returns the maximum size of the vector if no such relocation is found.
-static unsigned getRelocationWithOffset(const InputSection &is,
- uint64_t offset) {
- unsigned size = is.relocations.size();
- for (unsigned i = size - 1; i + 1 > 0; --i) {
- if (is.relocations[i].offset == offset && is.relocations[i].expr != R_NONE)
- return i;
- }
- return size;
-}
-
-// Returns true if R corresponds to a relocation used for a jump instruction.
-// TODO: Once special relocations for relaxable jump instructions are available,
-// this should be modified to use those relocations.
-static bool isRelocationForJmpInsn(Relocation &R) {
- return R.type == R_X86_64_PLT32 || R.type == R_X86_64_PC32 ||
- R.type == R_X86_64_PC8;
-}
-
-// Return true if Relocation R points to the first instruction in the
-// next section.
-// TODO: Delete this once psABI reserves a new relocation type for fall thru
-// jumps.
-static bool isFallThruRelocation(InputSection &is, InputFile *file,
- InputSection *nextIS, Relocation &r) {
- if (!isRelocationForJmpInsn(r))
- return false;
-
- uint64_t addrLoc = is.getOutputSection()->addr + is.outSecOff + r.offset;
- uint64_t targetOffset = InputSectionBase::getRelocTargetVA(
- file, r.type, r.addend, addrLoc, *r.sym, r.expr);
-
- // If this jmp is a fall thru, the target offset is the beginning of the
- // next section.
- uint64_t nextSectionOffset =
- nextIS->getOutputSection()->addr + nextIS->outSecOff;
- return (addrLoc + 4 + targetOffset) == nextSectionOffset;
-}
-
-// Return the jmp instruction opcode that is the inverse of the given
-// opcode. For example, JE inverted is JNE.
-static JmpInsnOpcode invertJmpOpcode(const JmpInsnOpcode opcode) {
- switch (opcode) {
- case J_JE_32:
- return J_JNE_32;
- case J_JNE_32:
- return J_JE_32;
- case J_JG_32:
- return J_JLE_32;
- case J_JGE_32:
- return J_JL_32;
- case J_JB_32:
- return J_JAE_32;
- case J_JBE_32:
- return J_JA_32;
- case J_JL_32:
- return J_JGE_32;
- case J_JLE_32:
- return J_JG_32;
- case J_JA_32:
- return J_JBE_32;
- case J_JAE_32:
- return J_JB_32;
- default:
- return J_UNKNOWN;
- }
-}
-
-// Deletes direct jump instruction in input sections that jumps to the
-// following section as it is not required. If there are two consecutive jump
-// instructions, it checks if they can be flipped and one can be deleted.
-// For example:
-// .section .text
-// a.BB.foo:
-// ...
-// 10: jne aa.BB.foo
-// 16: jmp bar
-// aa.BB.foo:
-// ...
-//
-// can be converted to:
-// a.BB.foo:
-// ...
-// 10: je bar #jne flipped to je and the jmp is deleted.
-// aa.BB.foo:
-// ...
-bool X86_64::deleteFallThruJmpInsn(InputSection &is, InputFile *file,
- InputSection *nextIS) const {
- const unsigned sizeOfDirectJmpInsn = 5;
-
- if (nextIS == nullptr)
- return false;
-
- if (is.getSize() < sizeOfDirectJmpInsn)
- return false;
-
- // If this jmp insn can be removed, it is the last insn and the
- // relocation is 4 bytes before the end.
- unsigned rIndex = getRelocationWithOffset(is, is.getSize() - 4);
- if (rIndex == is.relocations.size())
- return false;
-
- Relocation &r = is.relocations[rIndex];
-
- // Check if the relocation corresponds to a direct jmp.
- const uint8_t *secContents = is.data().data();
- // If it is not a direct jmp instruction, there is nothing to do here.
- if (*(secContents + r.offset - 1) != 0xe9)
- return false;
-
- if (isFallThruRelocation(is, file, nextIS, r)) {
- // This is a fall thru and can be deleted.
- r.expr = R_NONE;
- r.offset = 0;
- is.drop_back(sizeOfDirectJmpInsn);
- is.nopFiller = true;
- return true;
- }
-
- // Now, check if flip and delete is possible.
- const unsigned sizeOfJmpCCInsn = 6;
- // To flip, there must be atleast one JmpCC and one direct jmp.
- if (is.getSize() < sizeOfDirectJmpInsn + sizeOfJmpCCInsn)
- return 0;
-
- unsigned rbIndex =
- getRelocationWithOffset(is, (is.getSize() - sizeOfDirectJmpInsn - 4));
- if (rbIndex == is.relocations.size())
- return 0;
-
- Relocation &rB = is.relocations[rbIndex];
-
- const uint8_t *jmpInsnB = secContents + rB.offset - 1;
- JmpInsnOpcode jmpOpcodeB = getJmpInsnType(jmpInsnB - 1, jmpInsnB);
- if (jmpOpcodeB == J_UNKNOWN)
- return false;
-
- if (!isFallThruRelocation(is, file, nextIS, rB))
- return false;
-
- // jmpCC jumps to the fall thru block, the branch can be flipped and the
- // jmp can be deleted.
- JmpInsnOpcode jInvert = invertJmpOpcode(jmpOpcodeB);
- if (jInvert == J_UNKNOWN)
- return false;
- is.jumpInstrMods.push_back({jInvert, (rB.offset - 1), 4});
- // Move R's values to rB except the offset.
- rB = {r.expr, r.type, rB.offset, r.addend, r.sym};
- // Cancel R
- r.expr = R_NONE;
- r.offset = 0;
- is.drop_back(sizeOfDirectJmpInsn);
- is.nopFiller = true;
- return true;
-}
-
RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
const uint8_t *loc) const {
if (type == R_X86_64_GOTTPOFF)
@@ -327,7 +89,7 @@ RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
case R_X86_64_DTPOFF64:
return R_DTPREL;
case R_X86_64_TPOFF32:
- return R_TPREL;
+ return R_TLS;
case R_X86_64_TLSDESC_CALL:
return R_TLSDESC_CALL;
case R_X86_64_TLSLD:
@@ -381,12 +143,6 @@ void X86_64::writeGotPlt(uint8_t *buf, const Symbol &s) const {
write64le(buf, s.getPltVA() + 6);
}
-void X86_64::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
- // An x86 entry is the address of the ifunc resolver function (for -z rel).
- if (config->writeAddends)
- write64le(buf, s.getVA());
-}
-
void X86_64::writePltHeader(uint8_t *buf) const {
const uint8_t pltData[] = {
0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip)
@@ -421,9 +177,8 @@ RelType X86_64::getDynRel(RelType type) const {
return R_X86_64_NONE;
}
-void X86_64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
- uint64_t val) const {
- if (rel.type == R_X86_64_TLSGD) {
+void X86_64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
+ if (type == R_X86_64_TLSGD) {
// Convert
// .byte 0x66
// leaq x@tlsgd(%rip), %rdi
@@ -446,7 +201,7 @@ void X86_64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
// lea x@tlsgd(%rip), %rax
// call *(%rax)
// to the following two instructions.
- assert(rel.type == R_X86_64_GOTPC32_TLSDESC);
+ assert(type == R_X86_64_GOTPC32_TLSDESC);
if (memcmp(loc - 3, "\x48\x8d\x05", 3)) {
error(getErrorLocation(loc - 3) + "R_X86_64_GOTPC32_TLSDESC must be used "
"in callq *x@tlsdesc(%rip), %rax");
@@ -462,9 +217,8 @@ void X86_64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
}
}
-void X86_64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
- uint64_t val) const {
- if (rel.type == R_X86_64_TLSGD) {
+void X86_64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
+ if (type == R_X86_64_TLSGD) {
// Convert
// .byte 0x66
// leaq x@tlsgd(%rip), %rdi
@@ -487,7 +241,7 @@ void X86_64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
// lea x@tlsgd(%rip), %rax
// call *(%rax)
// to the following two instructions.
- assert(rel.type == R_X86_64_GOTPC32_TLSDESC);
+ assert(type == R_X86_64_GOTPC32_TLSDESC);
if (memcmp(loc - 3, "\x48\x8d\x05", 3)) {
error(getErrorLocation(loc - 3) + "R_X86_64_GOTPC32_TLSDESC must be used "
"in callq *x@tlsdesc(%rip), %rax");
@@ -504,8 +258,7 @@ void X86_64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
// In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to
// R_X86_64_TPOFF32 so that it does not use GOT.
-void X86_64::relaxTlsIeToLe(uint8_t *loc, const Relocation &,
- uint64_t val) const {
+void X86_64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
uint8_t *inst = loc - 3;
uint8_t reg = loc[-1] >> 3;
uint8_t *regSlot = loc - 1;
@@ -546,13 +299,12 @@ void X86_64::relaxTlsIeToLe(uint8_t *loc, const Relocation &,
write32le(loc, val + 4);
}
-void X86_64::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
- uint64_t val) const {
- if (rel.type == R_X86_64_DTPOFF64) {
+void X86_64::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const {
+ if (type == R_X86_64_DTPOFF64) {
write64le(loc, val);
return;
}
- if (rel.type == R_X86_64_DTPOFF32) {
+ if (type == R_X86_64_DTPOFF32) {
write32le(loc, val);
return;
}
@@ -595,163 +347,26 @@ void X86_64::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
"expected R_X86_64_PLT32 or R_X86_64_GOTPCRELX after R_X86_64_TLSLD");
}
-// A JumpInstrMod at a specific offset indicates that the jump instruction
-// opcode at that offset must be modified. This is specifically used to relax
-// jump instructions with basic block sections. This function looks at the
-// JumpMod and effects the change.
-void X86_64::applyJumpInstrMod(uint8_t *loc, JumpModType type,
- unsigned size) const {
- switch (type) {
- case J_JMP_32:
- if (size == 4)
- *loc = 0xe9;
- else
- *loc = 0xeb;
- break;
- case J_JE_32:
- if (size == 4) {
- loc[-1] = 0x0f;
- *loc = 0x84;
- } else
- *loc = 0x74;
- break;
- case J_JNE_32:
- if (size == 4) {
- loc[-1] = 0x0f;
- *loc = 0x85;
- } else
- *loc = 0x75;
- break;
- case J_JG_32:
- if (size == 4) {
- loc[-1] = 0x0f;
- *loc = 0x8f;
- } else
- *loc = 0x7f;
- break;
- case J_JGE_32:
- if (size == 4) {
- loc[-1] = 0x0f;
- *loc = 0x8d;
- } else
- *loc = 0x7d;
- break;
- case J_JB_32:
- if (size == 4) {
- loc[-1] = 0x0f;
- *loc = 0x82;
- } else
- *loc = 0x72;
- break;
- case J_JBE_32:
- if (size == 4) {
- loc[-1] = 0x0f;
- *loc = 0x86;
- } else
- *loc = 0x76;
- break;
- case J_JL_32:
- if (size == 4) {
- loc[-1] = 0x0f;
- *loc = 0x8c;
- } else
- *loc = 0x7c;
- break;
- case J_JLE_32:
- if (size == 4) {
- loc[-1] = 0x0f;
- *loc = 0x8e;
- } else
- *loc = 0x7e;
- break;
- case J_JA_32:
- if (size == 4) {
- loc[-1] = 0x0f;
- *loc = 0x87;
- } else
- *loc = 0x77;
- break;
- case J_JAE_32:
- if (size == 4) {
- loc[-1] = 0x0f;
- *loc = 0x83;
- } else
- *loc = 0x73;
- break;
- case J_UNKNOWN:
- llvm_unreachable("Unknown Jump Relocation");
- }
-}
-
-int64_t X86_64::getImplicitAddend(const uint8_t *buf, RelType type) const {
+void X86_64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
switch (type) {
case R_X86_64_8:
- case R_X86_64_PC8:
- return SignExtend64<8>(*buf);
- case R_X86_64_16:
- case R_X86_64_PC16:
- return SignExtend64<16>(read16le(buf));
- case R_X86_64_32:
- case R_X86_64_32S:
- case R_X86_64_TPOFF32:
- case R_X86_64_GOT32:
- case R_X86_64_GOTPC32:
- case R_X86_64_GOTPC32_TLSDESC:
- case R_X86_64_GOTPCREL:
- case R_X86_64_GOTPCRELX:
- case R_X86_64_REX_GOTPCRELX:
- case R_X86_64_PC32:
- case R_X86_64_GOTTPOFF:
- case R_X86_64_PLT32:
- case R_X86_64_TLSGD:
- case R_X86_64_TLSLD:
- case R_X86_64_DTPOFF32:
- case R_X86_64_SIZE32:
- return SignExtend64<32>(read32le(buf));
- case R_X86_64_64:
- case R_X86_64_TPOFF64:
- case R_X86_64_DTPOFF64:
- case R_X86_64_DTPMOD64:
- case R_X86_64_PC64:
- case R_X86_64_SIZE64:
- case R_X86_64_GLOB_DAT:
- case R_X86_64_GOT64:
- case R_X86_64_GOTOFF64:
- case R_X86_64_GOTPC64:
- case R_X86_64_IRELATIVE:
- case R_X86_64_RELATIVE:
- return read64le(buf);
- case R_X86_64_JUMP_SLOT:
- case R_X86_64_NONE:
- // These relocations are defined as not having an implicit addend.
- return 0;
- default:
- internalLinkerError(getErrorLocation(buf),
- "cannot read addend for relocation " + toString(type));
- return 0;
- }
-}
-
-void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
- switch (rel.type) {
- case R_X86_64_8:
- checkIntUInt(loc, val, 8, rel);
+ checkIntUInt(loc, val, 8, type);
*loc = val;
break;
case R_X86_64_PC8:
- checkInt(loc, val, 8, rel);
+ checkInt(loc, val, 8, type);
*loc = val;
break;
case R_X86_64_16:
- checkIntUInt(loc, val, 16, rel);
+ checkIntUInt(loc, val, 16, type);
write16le(loc, val);
break;
case R_X86_64_PC16:
- checkInt(loc, val, 16, rel);
+ checkInt(loc, val, 16, type);
write16le(loc, val);
break;
case R_X86_64_32:
- checkUInt(loc, val, 32, rel);
+ checkUInt(loc, val, 32, type);
write32le(loc, val);
break;
case R_X86_64_32S:
@@ -769,7 +384,7 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
case R_X86_64_TLSLD:
case R_X86_64_DTPOFF32:
case R_X86_64_SIZE32:
- checkInt(loc, val, 32, rel);
+ checkInt(loc, val, 32, type);
write32le(loc, val);
break;
case R_X86_64_64:
@@ -786,17 +401,12 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
}
-RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
- const uint8_t *loc) const {
- // Only R_X86_64_[REX_]GOTPCRELX can be relaxed. GNU as may emit GOTPCRELX
- // with addend != -4. Such an instruction does not load the full GOT entry, so
- // we cannot relax the relocation. E.g. movl x@GOTPCREL+4(%rip), %rax
- // (addend=0) loads the high 32 bits of the GOT entry.
- if ((type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX) ||
- addend != -4)
- return R_GOT_PC;
- const uint8_t op = loc[-2];
- const uint8_t modRm = loc[-1];
+RelExpr X86_64::adjustRelaxExpr(RelType type, const uint8_t *data,
+ RelExpr relExpr) const {
+ if (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX)
+ return relExpr;
+ const uint8_t op = data[-2];
+ const uint8_t modRm = data[-1];
// FIXME: When PIC is disabled and foo is defined locally in the
// lower 32 bit address space, memory operand in mov can be converted into
@@ -809,13 +419,12 @@ RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
if (op == 0xff && (modRm == 0x15 || modRm == 0x25))
return R_RELAX_GOT_PC;
- // We don't support test/binop instructions without a REX prefix.
- if (type == R_X86_64_GOTPCRELX)
- return R_GOT_PC;
-
// Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor.
// If PIC then no relaxation is available.
- return config->isPic ? R_GOT_PC : R_RELAX_GOT_PC_NOPIC;
+ // We also don't relax test/binop instructions without REX byte,
+ // they are 32bit operations and not common to have.
+ assert(type == R_X86_64_REX_GOTPCRELX);
+ return config->isPic ? relExpr : R_RELAX_GOT_PC_NOPIC;
}
// A subset of relaxations can only be applied for no-PIC. This method
@@ -886,8 +495,7 @@ static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
write32le(loc, val);
}
-void X86_64::relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const {
- checkInt(loc, val, 32, rel);
+void X86_64::relaxGot(uint8_t *loc, RelType type, uint64_t val) const {
const uint8_t op = loc[-2];
const uint8_t modRm = loc[-1];
@@ -1150,4 +758,7 @@ static TargetInfo *getTargetInfo() {
return &t;
}
-TargetInfo *elf::getX86_64TargetInfo() { return getTargetInfo(); }
+TargetInfo *getX86_64TargetInfo() { return getTargetInfo(); }
+
+} // namespace elf
+} // namespace lld