diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:52:45 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:52:45 +0000 |
commit | d2bd9e70b16db88a7808ee2280b0a107afbfdd3b (patch) | |
tree | 12612d2c593445b297ac656911c9db7cf9065bdd /ELF/Arch | |
parent | f1e1c239e31b467e17f1648b1f524fc9ab5b431a (diff) | |
download | src-vendor/lld.tar.gz src-vendor/lld.zip |
Vendor import of stripped lld trunk r375505, the last commit before thevendor/lld/lld-trunk-r375505vendor/lld
upstream Subversion repository was made read-only, and the LLVM project
migrated to GitHub:
https://llvm.org/svn/llvm-project/lld/trunk@375505
Notes
Notes:
svn path=/vendor/lld/dist/; revision=353950
svn path=/vendor/lld/lld-r375505/; revision=353951; tag=vendor/lld/lld-trunk-r375505
Diffstat (limited to 'ELF/Arch')
-rw-r--r-- | ELF/Arch/AArch64.cpp | 108 | ||||
-rw-r--r-- | ELF/Arch/AMDGPU.cpp | 10 | ||||
-rw-r--r-- | ELF/Arch/ARM.cpp | 10 | ||||
-rw-r--r-- | ELF/Arch/AVR.cpp | 10 | ||||
-rw-r--r-- | ELF/Arch/Hexagon.cpp | 59 | ||||
-rw-r--r-- | ELF/Arch/MSP430.cpp | 10 | ||||
-rw-r--r-- | ELF/Arch/Mips.cpp | 236 | ||||
-rw-r--r-- | ELF/Arch/MipsArchTree.cpp | 56 | ||||
-rw-r--r-- | ELF/Arch/PPC.cpp | 25 | ||||
-rw-r--r-- | ELF/Arch/PPC64.cpp | 48 | ||||
-rw-r--r-- | ELF/Arch/RISCV.cpp | 10 | ||||
-rw-r--r-- | ELF/Arch/SPARCV9.cpp | 10 | ||||
-rw-r--r-- | ELF/Arch/X86.cpp | 10 | ||||
-rw-r--r-- | ELF/Arch/X86_64.cpp | 10 |
14 files changed, 421 insertions, 191 deletions
diff --git a/ELF/Arch/AArch64.cpp b/ELF/Arch/AArch64.cpp index 4d4789702f03..5cf07029fa1d 100644 --- a/ELF/Arch/AArch64.cpp +++ b/ELF/Arch/AArch64.cpp @@ -17,13 +17,14 @@ using namespace llvm; using namespace llvm::support::endian; using namespace llvm::ELF; -using namespace lld; -using namespace lld::elf; + +namespace lld { +namespace elf { // Page(Expr) is the page address of the expression Expr, defined // as (Expr & ~0xFFF). (This applies even if the machine page size // supported by the platform has a different value.) -uint64_t elf::getAArch64Page(uint64_t expr) { +uint64_t getAArch64Page(uint64_t expr) { return expr & ~static_cast<uint64_t>(0xFFF); } @@ -76,6 +77,26 @@ AArch64::AArch64() { RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const { switch (type) { + case R_AARCH64_ABS16: + case R_AARCH64_ABS32: + case R_AARCH64_ABS64: + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LDST128_ABS_LO12_NC: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_MOVW_SABS_G0: + case R_AARCH64_MOVW_SABS_G1: + case R_AARCH64_MOVW_SABS_G2: + case R_AARCH64_MOVW_UABS_G0: + case R_AARCH64_MOVW_UABS_G0_NC: + case R_AARCH64_MOVW_UABS_G1: + case R_AARCH64_MOVW_UABS_G1_NC: + case R_AARCH64_MOVW_UABS_G2: + case R_AARCH64_MOVW_UABS_G2_NC: + case R_AARCH64_MOVW_UABS_G3: + return R_ABS; case R_AARCH64_TLSDESC_ADR_PAGE21: return R_AARCH64_TLSDESC_PAGE; case R_AARCH64_TLSDESC_LD64_LO12: @@ -90,6 +111,11 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, case R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC: case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC: case R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC: + case R_AARCH64_TLSLE_MOVW_TPREL_G0: + case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: + case R_AARCH64_TLSLE_MOVW_TPREL_G1: + case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC: + case R_AARCH64_TLSLE_MOVW_TPREL_G2: return R_TLS; case R_AARCH64_CALL26: case R_AARCH64_CONDBR19: @@ -101,6 +127,13 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, case R_AARCH64_PREL64: case R_AARCH64_ADR_PREL_LO21: case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_MOVW_PREL_G0: + case R_AARCH64_MOVW_PREL_G0_NC: + case R_AARCH64_MOVW_PREL_G1: + case R_AARCH64_MOVW_PREL_G1_NC: + case R_AARCH64_MOVW_PREL_G2: + case R_AARCH64_MOVW_PREL_G2_NC: + case R_AARCH64_MOVW_PREL_G3: return R_PC; case R_AARCH64_ADR_PREL_PG_HI21: case R_AARCH64_ADR_PREL_PG_HI21_NC: @@ -114,7 +147,9 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, case R_AARCH64_NONE: return R_NONE; default: - return R_ABS; + error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + + ") against symbol " + toString(s)); + return R_NONE; } } @@ -247,6 +282,26 @@ static void or32AArch64Imm(uint8_t *l, uint64_t imm) { or32le(l, (imm & 0xFFF) << 10); } +// Update the immediate field in an AArch64 movk, movn or movz instruction +// for a signed relocation, and update the opcode of a movn or movz instruction +// to match the sign of the operand. +static void writeSMovWImm(uint8_t *loc, uint32_t imm) { + uint32_t inst = read32le(loc); + // Opcode field is bits 30, 29, with 10 = movz, 00 = movn and 11 = movk. + if (!(inst & (1 << 29))) { + // movn or movz. + if (imm & 0x10000) { + // Change opcode to movn, which takes an inverted operand. + imm ^= 0xFFFF; + inst &= ~(1 << 30); + } else { + // Change opcode to movz. + inst |= 1 << 30; + } + } + write32le(loc, inst | ((imm & 0xFFFF) << 5)); +} + void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { switch (type) { case R_AARCH64_ABS16: @@ -326,18 +381,56 @@ void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { checkAlignment(loc, val, 16, type); or32AArch64Imm(loc, getBits(val, 4, 11)); break; + case R_AARCH64_MOVW_UABS_G0: + checkUInt(loc, val, 16, type); + LLVM_FALLTHROUGH; case R_AARCH64_MOVW_UABS_G0_NC: or32le(loc, (val & 0xFFFF) << 5); break; + case R_AARCH64_MOVW_UABS_G1: + checkUInt(loc, val, 32, type); + LLVM_FALLTHROUGH; case R_AARCH64_MOVW_UABS_G1_NC: or32le(loc, (val & 0xFFFF0000) >> 11); break; + case R_AARCH64_MOVW_UABS_G2: + checkUInt(loc, val, 48, type); + LLVM_FALLTHROUGH; case R_AARCH64_MOVW_UABS_G2_NC: or32le(loc, (val & 0xFFFF00000000) >> 27); break; case R_AARCH64_MOVW_UABS_G3: or32le(loc, (val & 0xFFFF000000000000) >> 43); break; + case R_AARCH64_MOVW_PREL_G0: + case R_AARCH64_MOVW_SABS_G0: + case R_AARCH64_TLSLE_MOVW_TPREL_G0: + checkInt(loc, val, 17, type); + LLVM_FALLTHROUGH; + case R_AARCH64_MOVW_PREL_G0_NC: + case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: + writeSMovWImm(loc, val); + break; + case R_AARCH64_MOVW_PREL_G1: + case R_AARCH64_MOVW_SABS_G1: + case R_AARCH64_TLSLE_MOVW_TPREL_G1: + checkInt(loc, val, 33, type); + LLVM_FALLTHROUGH; + case R_AARCH64_MOVW_PREL_G1_NC: + case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC: + writeSMovWImm(loc, val >> 16); + break; + case R_AARCH64_MOVW_PREL_G2: + case R_AARCH64_MOVW_SABS_G2: + case R_AARCH64_TLSLE_MOVW_TPREL_G2: + checkInt(loc, val, 49, type); + LLVM_FALLTHROUGH; + case R_AARCH64_MOVW_PREL_G2_NC: + writeSMovWImm(loc, val >> 32); + break; + case R_AARCH64_MOVW_PREL_G3: + writeSMovWImm(loc, val >> 48); + break; case R_AARCH64_TSTBR14: checkInt(loc, val, 16, type); or32le(loc, (val & 0xFFFC) << 3); @@ -351,7 +444,7 @@ void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { or32AArch64Imm(loc, val); break; default: - error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); + llvm_unreachable("unknown relocation"); } } @@ -587,4 +680,7 @@ static TargetInfo *getTargetInfo() { return &t; } -TargetInfo *elf::getAArch64TargetInfo() { return getTargetInfo(); } +TargetInfo *getAArch64TargetInfo() { return getTargetInfo(); } + +} // namespace elf +} // namespace lld diff --git a/ELF/Arch/AMDGPU.cpp b/ELF/Arch/AMDGPU.cpp index f2e32ca0996d..b42ca7746742 100644 --- a/ELF/Arch/AMDGPU.cpp +++ b/ELF/Arch/AMDGPU.cpp @@ -17,8 +17,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 AMDGPU final : public TargetInfo { @@ -107,7 +108,10 @@ RelType AMDGPU::getDynRel(RelType type) const { return R_AMDGPU_NONE; } -TargetInfo *elf::getAMDGPUTargetInfo() { +TargetInfo *getAMDGPUTargetInfo() { static AMDGPU target; return ⌖ } + +} // namespace elf +} // namespace lld diff --git a/ELF/Arch/ARM.cpp b/ELF/Arch/ARM.cpp index 64adc33c07ae..41baea496d36 100644 --- a/ELF/Arch/ARM.cpp +++ b/ELF/Arch/ARM.cpp @@ -18,8 +18,9 @@ using namespace llvm; using namespace llvm::support::endian; using namespace llvm::ELF; -using namespace lld; -using namespace lld::elf; + +namespace lld { +namespace elf { namespace { class ARM final : public TargetInfo { @@ -600,7 +601,10 @@ int64_t ARM::getImplicitAddend(const uint8_t *buf, RelType type) const { } } -TargetInfo *elf::getARMTargetInfo() { +TargetInfo *getARMTargetInfo() { static ARM target; return ⌖ } + +} // namespace elf +} // namespace lld diff --git a/ELF/Arch/AVR.cpp b/ELF/Arch/AVR.cpp index 869f0fe0c525..cb33ff448ba4 100644 --- a/ELF/Arch/AVR.cpp +++ b/ELF/Arch/AVR.cpp @@ -36,8 +36,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 AVR final : public TargetInfo { @@ -70,7 +71,10 @@ void AVR::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { } } -TargetInfo *elf::getAVRTargetInfo() { +TargetInfo *getAVRTargetInfo() { static AVR target; return ⌖ } + +} // namespace elf +} // namespace lld diff --git a/ELF/Arch/Hexagon.cpp b/ELF/Arch/Hexagon.cpp index c497a6df7987..67264a2272dd 100644 --- a/ELF/Arch/Hexagon.cpp +++ b/ELF/Arch/Hexagon.cpp @@ -19,8 +19,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 Hexagon final : public TargetInfo { @@ -29,6 +30,7 @@ public: uint32_t calcEFlags() const override; RelExpr getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const override; + RelType getDynRel(RelType type) const override; void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; void writePltHeader(uint8_t *buf) const override; void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, @@ -86,25 +88,47 @@ static uint32_t applyMask(uint32_t mask, uint32_t data) { RelExpr Hexagon::getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const { switch (type) { + case R_HEX_NONE: + return R_NONE; + case R_HEX_6_X: + case R_HEX_8_X: + case R_HEX_9_X: + case R_HEX_10_X: + case R_HEX_11_X: + case R_HEX_12_X: + case R_HEX_16_X: + case R_HEX_32: + case R_HEX_32_6_X: + case R_HEX_HI16: + case R_HEX_LO16: + return R_ABS; case R_HEX_B9_PCREL: - case R_HEX_B9_PCREL_X: case R_HEX_B13_PCREL: case R_HEX_B15_PCREL: - case R_HEX_B15_PCREL_X: case R_HEX_6_PCREL_X: case R_HEX_32_PCREL: return R_PC; + case R_HEX_B9_PCREL_X: + case R_HEX_B15_PCREL_X: case R_HEX_B22_PCREL: case R_HEX_PLT_B22_PCREL: case R_HEX_B22_PCREL_X: case R_HEX_B32_PCREL_X: return R_PLT_PC; + case R_HEX_GOTREL_11_X: + case R_HEX_GOTREL_16_X: + case R_HEX_GOTREL_32_6_X: + case R_HEX_GOTREL_HI16: + case R_HEX_GOTREL_LO16: + return R_GOTPLTREL; case R_HEX_GOT_11_X: case R_HEX_GOT_16_X: case R_HEX_GOT_32_6_X: - return R_HEXAGON_GOT; + return R_GOTPLT; default: - return R_ABS; + error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + + ") against symbol " + toString(s)); + return R_NONE; } } @@ -197,6 +221,7 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { break; case R_HEX_11_X: case R_HEX_GOT_11_X: + case R_HEX_GOTREL_11_X: or32le(loc, applyMask(findMaskR11(read32le(loc)), val & 0x3f)); break; case R_HEX_12_X: @@ -204,6 +229,7 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { break; case R_HEX_16_X: // These relocs only have 6 effective bits. case R_HEX_GOT_16_X: + case R_HEX_GOTREL_16_X: or32le(loc, applyMask(findMaskR16(read32le(loc)), val & 0x3f)); break; case R_HEX_32: @@ -212,18 +238,22 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { break; case R_HEX_32_6_X: case R_HEX_GOT_32_6_X: + case R_HEX_GOTREL_32_6_X: or32le(loc, applyMask(0x0fff3fff, val >> 6)); break; case R_HEX_B9_PCREL: + checkInt(loc, val, 11, type); or32le(loc, applyMask(0x003000fe, val >> 2)); break; case R_HEX_B9_PCREL_X: or32le(loc, applyMask(0x003000fe, val & 0x3f)); break; case R_HEX_B13_PCREL: + checkInt(loc, val, 15, type); or32le(loc, applyMask(0x00202ffe, val >> 2)); break; case R_HEX_B15_PCREL: + checkInt(loc, val, 17, type); or32le(loc, applyMask(0x00df20fe, val >> 2)); break; case R_HEX_B15_PCREL_X: @@ -231,6 +261,7 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { break; case R_HEX_B22_PCREL: case R_HEX_PLT_B22_PCREL: + checkInt(loc, val, 22, type); or32le(loc, applyMask(0x1ff3ffe, val >> 2)); break; case R_HEX_B22_PCREL_X: @@ -239,15 +270,16 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { case R_HEX_B32_PCREL_X: or32le(loc, applyMask(0x0fff3fff, val >> 6)); break; + case R_HEX_GOTREL_HI16: case R_HEX_HI16: or32le(loc, applyMask(0x00c03fff, val >> 16)); break; + case R_HEX_GOTREL_LO16: case R_HEX_LO16: or32le(loc, applyMask(0x00c03fff, val)); break; default: - error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); - break; + llvm_unreachable("unknown relocation"); } } @@ -285,7 +317,16 @@ void Hexagon::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, relocateOne(buf + 4, R_HEX_6_PCREL_X, gotPltEntryAddr - pltEntryAddr); } -TargetInfo *elf::getHexagonTargetInfo() { +RelType Hexagon::getDynRel(RelType type) const { + if (type == R_HEX_32) + return type; + return R_HEX_NONE; +} + +TargetInfo *getHexagonTargetInfo() { static Hexagon target; return ⌖ } + +} // namespace elf +} // namespace lld diff --git a/ELF/Arch/MSP430.cpp b/ELF/Arch/MSP430.cpp index 90664396c85e..f03e8181923b 100644 --- a/ELF/Arch/MSP430.cpp +++ b/ELF/Arch/MSP430.cpp @@ -26,8 +26,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 MSP430 final : public TargetInfo { @@ -87,7 +88,10 @@ void MSP430::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { } } -TargetInfo *elf::getMSP430TargetInfo() { +TargetInfo *getMSP430TargetInfo() { static MSP430 target; return ⌖ } + +} // namespace elf +} // namespace lld diff --git a/ELF/Arch/Mips.cpp b/ELF/Arch/Mips.cpp index 24b3957acd99..d8fa306a6205 100644 --- a/ELF/Arch/Mips.cpp +++ b/ELF/Arch/Mips.cpp @@ -14,15 +14,13 @@ #include "Thunks.h" #include "lld/Common/ErrorHandler.h" #include "llvm/Object/ELF.h" -#include "llvm/Support/Endian.h" 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 { template <class ELFT> class MIPS final : public TargetInfo { public: @@ -85,8 +83,14 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType type, const Symbol &s, switch (type) { case R_MIPS_JALR: + // If the target symbol is not preemptible and is not microMIPS, + // it might be possible to replace jalr/jr instruction by bal/b. + // It depends on the target symbol's offset. + if (!s.isPreemptible && !(s.getVA() & 0x1)) + return R_PC; + return R_NONE; case R_MICROMIPS_JALR: - return R_HINT; + return R_NONE; case R_MIPS_GPREL16: case R_MIPS_GPREL32: case R_MICROMIPS_GPREL16: @@ -120,15 +124,16 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType type, const Symbol &s, case R_MIPS_TLS_DTPREL_LO16: case R_MIPS_TLS_DTPREL32: case R_MIPS_TLS_DTPREL64: + case R_MICROMIPS_TLS_DTPREL_HI16: + case R_MICROMIPS_TLS_DTPREL_LO16: + return R_ABS; case R_MIPS_TLS_TPREL_HI16: case R_MIPS_TLS_TPREL_LO16: case R_MIPS_TLS_TPREL32: case R_MIPS_TLS_TPREL64: - case R_MICROMIPS_TLS_DTPREL_HI16: - case R_MICROMIPS_TLS_DTPREL_LO16: case R_MICROMIPS_TLS_TPREL_HI16: case R_MICROMIPS_TLS_TPREL_LO16: - return R_ABS; + return R_TLS; case R_MIPS_PC32: case R_MIPS_PC16: case R_MIPS_PC19_S2: @@ -192,7 +197,7 @@ void MIPS<ELFT>::writeGotPlt(uint8_t *buf, const Symbol &) const { uint64_t va = in.plt->getVA(); if (isMicroMips()) va |= 1; - write32<ELFT::TargetEndianness>(buf, va); + write32(buf, va); } template <endianness E> static uint32_t readShuffle(const uint8_t *loc) { @@ -202,19 +207,18 @@ template <endianness E> static uint32_t readShuffle(const uint8_t *loc) { // as early as possible. To do so, little-endian binaries keep 16-bit // words in a big-endian order. That is why we have to swap these // words to get a correct value. - uint32_t v = read32<E>(loc); + uint32_t v = read32(loc); if (E == support::little) return (v << 16) | (v >> 16); return v; } -template <endianness E> static void writeValue(uint8_t *loc, uint64_t v, uint8_t bitsSize, uint8_t shift) { - uint32_t instr = read32<E>(loc); + uint32_t instr = read32(loc); uint32_t mask = 0xffffffff >> (32 - bitsSize); uint32_t data = (instr & ~mask) | ((v >> shift) & mask); - write32<E>(loc, data); + write32(loc, data); } template <endianness E> @@ -225,7 +229,7 @@ static void writeShuffleValue(uint8_t *loc, uint64_t v, uint8_t bitsSize, if (E == support::little) std::swap(words[0], words[1]); - writeValue<E>(loc, v, bitsSize, shift); + writeValue(loc, v, bitsSize, shift); if (E == support::little) std::swap(words[0], words[1]); @@ -234,94 +238,92 @@ static void writeShuffleValue(uint8_t *loc, uint64_t v, uint8_t bitsSize, template <endianness E> static void writeMicroRelocation16(uint8_t *loc, uint64_t v, uint8_t bitsSize, uint8_t shift) { - uint16_t instr = read16<E>(loc); + uint16_t instr = read16(loc); uint16_t mask = 0xffff >> (16 - bitsSize); uint16_t data = (instr & ~mask) | ((v >> shift) & mask); - write16<E>(loc, data); + write16(loc, data); } template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *buf) const { - const endianness e = ELFT::TargetEndianness; if (isMicroMips()) { uint64_t gotPlt = in.gotPlt->getVA(); uint64_t plt = in.plt->getVA(); // Overwrite trap instructions written by Writer::writeTrapInstr. memset(buf, 0, pltHeaderSize); - write16<e>(buf, isMipsR6() ? 0x7860 : 0x7980); // addiupc v1, (GOTPLT) - . - write16<e>(buf + 4, 0xff23); // lw $25, 0($3) - write16<e>(buf + 8, 0x0535); // subu16 $2, $2, $3 - write16<e>(buf + 10, 0x2525); // srl16 $2, $2, 2 - write16<e>(buf + 12, 0x3302); // addiu $24, $2, -2 - write16<e>(buf + 14, 0xfffe); - write16<e>(buf + 16, 0x0dff); // move $15, $31 + write16(buf, isMipsR6() ? 0x7860 : 0x7980); // addiupc v1, (GOTPLT) - . + write16(buf + 4, 0xff23); // lw $25, 0($3) + write16(buf + 8, 0x0535); // subu16 $2, $2, $3 + write16(buf + 10, 0x2525); // srl16 $2, $2, 2 + write16(buf + 12, 0x3302); // addiu $24, $2, -2 + write16(buf + 14, 0xfffe); + write16(buf + 16, 0x0dff); // move $15, $31 if (isMipsR6()) { - write16<e>(buf + 18, 0x0f83); // move $28, $3 - write16<e>(buf + 20, 0x472b); // jalrc $25 - write16<e>(buf + 22, 0x0c00); // nop + write16(buf + 18, 0x0f83); // move $28, $3 + write16(buf + 20, 0x472b); // jalrc $25 + write16(buf + 22, 0x0c00); // nop relocateOne(buf, R_MICROMIPS_PC19_S2, gotPlt - plt); } else { - write16<e>(buf + 18, 0x45f9); // jalrc $25 - write16<e>(buf + 20, 0x0f83); // move $28, $3 - write16<e>(buf + 22, 0x0c00); // nop + write16(buf + 18, 0x45f9); // jalrc $25 + write16(buf + 20, 0x0f83); // move $28, $3 + write16(buf + 22, 0x0c00); // nop relocateOne(buf, R_MICROMIPS_PC23_S2, gotPlt - plt); } return; } if (config->mipsN32Abi) { - write32<e>(buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) - write32<e>(buf + 4, 0x8dd90000); // lw $25, %lo(&GOTPLT[0])($14) - write32<e>(buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) - write32<e>(buf + 12, 0x030ec023); // subu $24, $24, $14 - write32<e>(buf + 16, 0x03e07825); // move $15, $31 - write32<e>(buf + 20, 0x0018c082); // srl $24, $24, 2 + write32(buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) + write32(buf + 4, 0x8dd90000); // lw $25, %lo(&GOTPLT[0])($14) + write32(buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) + write32(buf + 12, 0x030ec023); // subu $24, $24, $14 + write32(buf + 16, 0x03e07825); // move $15, $31 + write32(buf + 20, 0x0018c082); // srl $24, $24, 2 } else if (ELFT::Is64Bits) { - write32<e>(buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) - write32<e>(buf + 4, 0xddd90000); // ld $25, %lo(&GOTPLT[0])($14) - write32<e>(buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) - write32<e>(buf + 12, 0x030ec023); // subu $24, $24, $14 - write32<e>(buf + 16, 0x03e07825); // move $15, $31 - write32<e>(buf + 20, 0x0018c0c2); // srl $24, $24, 3 + write32(buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) + write32(buf + 4, 0xddd90000); // ld $25, %lo(&GOTPLT[0])($14) + write32(buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) + write32(buf + 12, 0x030ec023); // subu $24, $24, $14 + write32(buf + 16, 0x03e07825); // move $15, $31 + write32(buf + 20, 0x0018c0c2); // srl $24, $24, 3 } else { - write32<e>(buf, 0x3c1c0000); // lui $28, %hi(&GOTPLT[0]) - write32<e>(buf + 4, 0x8f990000); // lw $25, %lo(&GOTPLT[0])($28) - write32<e>(buf + 8, 0x279c0000); // addiu $28, $28, %lo(&GOTPLT[0]) - write32<e>(buf + 12, 0x031cc023); // subu $24, $24, $28 - write32<e>(buf + 16, 0x03e07825); // move $15, $31 - write32<e>(buf + 20, 0x0018c082); // srl $24, $24, 2 + write32(buf, 0x3c1c0000); // lui $28, %hi(&GOTPLT[0]) + write32(buf + 4, 0x8f990000); // lw $25, %lo(&GOTPLT[0])($28) + write32(buf + 8, 0x279c0000); // addiu $28, $28, %lo(&GOTPLT[0]) + write32(buf + 12, 0x031cc023); // subu $24, $24, $28 + write32(buf + 16, 0x03e07825); // move $15, $31 + write32(buf + 20, 0x0018c082); // srl $24, $24, 2 } uint32_t jalrInst = config->zHazardplt ? 0x0320fc09 : 0x0320f809; - write32<e>(buf + 24, jalrInst); // jalr.hb $25 or jalr $25 - write32<e>(buf + 28, 0x2718fffe); // subu $24, $24, 2 + write32(buf + 24, jalrInst); // jalr.hb $25 or jalr $25 + write32(buf + 28, 0x2718fffe); // subu $24, $24, 2 uint64_t gotPlt = in.gotPlt->getVA(); - writeValue<e>(buf, gotPlt + 0x8000, 16, 16); - writeValue<e>(buf + 4, gotPlt, 16, 0); - writeValue<e>(buf + 8, gotPlt, 16, 0); + writeValue(buf, gotPlt + 0x8000, 16, 16); + writeValue(buf + 4, gotPlt, 16, 0); + writeValue(buf + 8, gotPlt, 16, 0); } template <class ELFT> void MIPS<ELFT>::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, int32_t index, unsigned relOff) const { - const endianness e = ELFT::TargetEndianness; if (isMicroMips()) { // Overwrite trap instructions written by Writer::writeTrapInstr. memset(buf, 0, pltEntrySize); if (isMipsR6()) { - write16<e>(buf, 0x7840); // addiupc $2, (GOTPLT) - . - write16<e>(buf + 4, 0xff22); // lw $25, 0($2) - write16<e>(buf + 8, 0x0f02); // move $24, $2 - write16<e>(buf + 10, 0x4723); // jrc $25 / jr16 $25 + write16(buf, 0x7840); // addiupc $2, (GOTPLT) - . + write16(buf + 4, 0xff22); // lw $25, 0($2) + write16(buf + 8, 0x0f02); // move $24, $2 + write16(buf + 10, 0x4723); // jrc $25 / jr16 $25 relocateOne(buf, R_MICROMIPS_PC19_S2, gotPltEntryAddr - pltEntryAddr); } else { - write16<e>(buf, 0x7900); // addiupc $2, (GOTPLT) - . - write16<e>(buf + 4, 0xff22); // lw $25, 0($2) - write16<e>(buf + 8, 0x4599); // jrc $25 / jr16 $25 - write16<e>(buf + 10, 0x0f02); // move $24, $2 + write16(buf, 0x7900); // addiupc $2, (GOTPLT) - . + write16(buf + 4, 0xff22); // lw $25, 0($2) + write16(buf + 8, 0x4599); // jrc $25 / jr16 $25 + write16(buf + 10, 0x0f02); // move $24, $2 relocateOne(buf, R_MICROMIPS_PC23_S2, gotPltEntryAddr - pltEntryAddr); } return; @@ -332,13 +334,13 @@ void MIPS<ELFT>::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, : (config->zHazardplt ? 0x03200408 : 0x03200008); uint32_t addInst = ELFT::Is64Bits ? 0x65f80000 : 0x25f80000; - write32<e>(buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry) - write32<e>(buf + 4, loadInst); // l[wd] $25, %lo(.got.plt entry)($15) - write32<e>(buf + 8, jrInst); // jr $25 / jr.hb $25 - write32<e>(buf + 12, addInst); // [d]addiu $24, $15, %lo(.got.plt entry) - writeValue<e>(buf, gotPltEntryAddr + 0x8000, 16, 16); - writeValue<e>(buf + 4, gotPltEntryAddr, 16, 0); - writeValue<e>(buf + 12, gotPltEntryAddr, 16, 0); + write32(buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry) + write32(buf + 4, loadInst); // l[wd] $25, %lo(.got.plt entry)($15) + write32(buf + 8, jrInst); // jr $25 / jr.hb $25 + write32(buf + 12, addInst); // [d]addiu $24, $15, %lo(.got.plt entry) + writeValue(buf, gotPltEntryAddr + 0x8000, 16, 16); + writeValue(buf + 4, gotPltEntryAddr, 16, 0); + writeValue(buf + 12, gotPltEntryAddr, 16, 0); } template <class ELFT> @@ -372,16 +374,16 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *buf, RelType type) const { case R_MIPS_GPREL32: case R_MIPS_TLS_DTPREL32: case R_MIPS_TLS_TPREL32: - return SignExtend64<32>(read32<e>(buf)); + return SignExtend64<32>(read32(buf)); case R_MIPS_26: // FIXME (simon): If the relocation target symbol is not a PLT entry // we should use another expression for calculation: // ((A << 2) | (P & 0xf0000000)) >> 2 - return SignExtend64<28>(read32<e>(buf) << 2); + return SignExtend64<28>(read32(buf) << 2); case R_MIPS_GOT16: case R_MIPS_HI16: case R_MIPS_PCHI16: - return SignExtend64<16>(read32<e>(buf)) << 16; + return SignExtend64<16>(read32(buf)) << 16; case R_MIPS_GPREL16: case R_MIPS_LO16: case R_MIPS_PCLO16: @@ -389,7 +391,7 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *buf, RelType type) const { case R_MIPS_TLS_DTPREL_LO16: case R_MIPS_TLS_TPREL_HI16: case R_MIPS_TLS_TPREL_LO16: - return SignExtend64<16>(read32<e>(buf)); + return SignExtend64<16>(read32(buf)); case R_MICROMIPS_GOT16: case R_MICROMIPS_HI16: return SignExtend64<16>(readShuffle<e>(buf)) << 16; @@ -403,21 +405,21 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *buf, RelType type) const { case R_MICROMIPS_GPREL7_S2: return SignExtend64<9>(readShuffle<e>(buf) << 2); case R_MIPS_PC16: - return SignExtend64<18>(read32<e>(buf) << 2); + return SignExtend64<18>(read32(buf) << 2); case R_MIPS_PC19_S2: - return SignExtend64<21>(read32<e>(buf) << 2); + return SignExtend64<21>(read32(buf) << 2); case R_MIPS_PC21_S2: - return SignExtend64<23>(read32<e>(buf) << 2); + return SignExtend64<23>(read32(buf) << 2); case R_MIPS_PC26_S2: - return SignExtend64<28>(read32<e>(buf) << 2); + return SignExtend64<28>(read32(buf) << 2); case R_MIPS_PC32: - return SignExtend64<32>(read32<e>(buf)); + return SignExtend64<32>(read32(buf)); case R_MICROMIPS_26_S1: return SignExtend64<27>(readShuffle<e>(buf) << 1); case R_MICROMIPS_PC7_S1: - return SignExtend64<8>(read16<e>(buf) << 1); + return SignExtend64<8>(read16(buf) << 1); case R_MICROMIPS_PC10_S1: - return SignExtend64<11>(read16<e>(buf) << 1); + return SignExtend64<11>(read16(buf) << 1); case R_MICROMIPS_PC16_S1: return SignExtend64<17>(readShuffle<e>(buf) << 1); case R_MICROMIPS_PC18_S3: @@ -487,9 +489,9 @@ static uint64_t fixupCrossModeJump(uint8_t *loc, RelType type, uint64_t val) { switch (type) { case R_MIPS_26: { - uint32_t inst = read32<e>(loc) >> 26; + uint32_t inst = read32(loc) >> 26; if (inst == 0x3 || inst == 0x1d) { // JAL or JALX - writeValue<e>(loc, 0x1d << 26, 32, 0); + writeValue(loc, 0x1d << 26, 32, 0); return val; } break; @@ -538,11 +540,6 @@ void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { type == R_MICROMIPS_TLS_DTPREL_HI16 || type == R_MICROMIPS_TLS_DTPREL_LO16) { val -= 0x8000; - } else if (type == R_MIPS_TLS_TPREL_HI16 || type == R_MIPS_TLS_TPREL_LO16 || - type == R_MIPS_TLS_TPREL32 || type == R_MIPS_TLS_TPREL64 || - type == R_MICROMIPS_TLS_TPREL_HI16 || - type == R_MICROMIPS_TLS_TPREL_LO16) { - val -= 0x7000; } switch (type) { @@ -550,25 +547,25 @@ void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { case R_MIPS_GPREL32: case R_MIPS_TLS_DTPREL32: case R_MIPS_TLS_TPREL32: - write32<e>(loc, val); + write32(loc, val); break; case R_MIPS_64: case R_MIPS_TLS_DTPREL64: case R_MIPS_TLS_TPREL64: - write64<e>(loc, val); + write64(loc, val); break; case R_MIPS_26: - writeValue<e>(loc, val, 26, 2); + writeValue(loc, val, 26, 2); break; case R_MIPS_GOT16: // The R_MIPS_GOT16 relocation's value in "relocatable" linking mode // is updated addend (not a GOT index). In that case write high 16 bits // to store a correct addend value. if (config->relocatable) { - writeValue<e>(loc, val + 0x8000, 16, 16); + writeValue(loc, val + 0x8000, 16, 16); } else { checkInt(loc, val, 16, type); - writeValue<e>(loc, val, 16, 0); + writeValue(loc, val, 16, 0); } break; case R_MICROMIPS_GOT16: @@ -595,7 +592,7 @@ void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { case R_MIPS_PCLO16: case R_MIPS_TLS_DTPREL_LO16: case R_MIPS_TLS_TPREL_LO16: - writeValue<e>(loc, val, 16, 0); + writeValue(loc, val, 16, 0); break; case R_MICROMIPS_GPREL16: case R_MICROMIPS_TLS_GD: @@ -621,7 +618,7 @@ void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { case R_MIPS_PCHI16: case R_MIPS_TLS_DTPREL_HI16: case R_MIPS_TLS_TPREL_HI16: - writeValue<e>(loc, val + 0x8000, 16, 16); + writeValue(loc, val + 0x8000, 16, 16); break; case R_MICROMIPS_CALL_HI16: case R_MICROMIPS_GOT_HI16: @@ -631,37 +628,51 @@ void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { writeShuffleValue<e>(loc, val + 0x8000, 16, 16); break; case R_MIPS_HIGHER: - writeValue<e>(loc, val + 0x80008000, 16, 32); + writeValue(loc, val + 0x80008000, 16, 32); break; case R_MIPS_HIGHEST: - writeValue<e>(loc, val + 0x800080008000, 16, 48); + writeValue(loc, val + 0x800080008000, 16, 48); break; case R_MIPS_JALR: + val -= 4; + // Replace jalr/jr instructions by bal/b if the target + // offset fits into the 18-bit range. + if (isInt<18>(val)) { + switch (read32(loc)) { + case 0x0320f809: // jalr $25 => bal sym + write32(loc, 0x04110000 | ((val >> 2) & 0xffff)); + break; + case 0x03200008: // jr $25 => b sym + write32(loc, 0x10000000 | ((val >> 2) & 0xffff)); + break; + } + } + break; case R_MICROMIPS_JALR: // Ignore this optimization relocation for now break; case R_MIPS_PC16: checkAlignment(loc, val, 4, type); checkInt(loc, val, 18, type); - writeValue<e>(loc, val, 16, 2); + writeValue(loc, val, 16, 2); break; case R_MIPS_PC19_S2: checkAlignment(loc, val, 4, type); checkInt(loc, val, 21, type); - writeValue<e>(loc, val, 19, 2); + writeValue(loc, val, 19, 2); break; case R_MIPS_PC21_S2: checkAlignment(loc, val, 4, type); checkInt(loc, val, 23, type); - writeValue<e>(loc, val, 21, 2); + writeValue(loc, val, 21, 2); break; case R_MIPS_PC26_S2: checkAlignment(loc, val, 4, type); checkInt(loc, val, 28, type); - writeValue<e>(loc, val, 26, 2); + writeValue(loc, val, 26, 2); break; case R_MIPS_PC32: - writeValue<e>(loc, val, 32, 0); + writeValue(loc, val, 32, 0); break; case R_MICROMIPS_26_S1: case R_MICROMIPS_PC26_S1: @@ -707,7 +718,7 @@ template <class ELFT> bool MIPS<ELFT>::usesOnlyLowPageBits(RelType type) const { } // Return true if the symbol is a PIC function. -template <class ELFT> bool elf::isMipsPIC(const Defined *sym) { +template <class ELFT> bool isMipsPIC(const Defined *sym) { if (!sym->isFunc()) return false; @@ -725,17 +736,20 @@ template <class ELFT> bool elf::isMipsPIC(const Defined *sym) { return file->getObj().getHeader()->e_flags & EF_MIPS_PIC; } -template <class ELFT> TargetInfo *elf::getMipsTargetInfo() { +template <class ELFT> TargetInfo *getMipsTargetInfo() { static MIPS<ELFT> target; return ⌖ } -template TargetInfo *elf::getMipsTargetInfo<ELF32LE>(); -template TargetInfo *elf::getMipsTargetInfo<ELF32BE>(); -template TargetInfo *elf::getMipsTargetInfo<ELF64LE>(); -template TargetInfo *elf::getMipsTargetInfo<ELF64BE>(); +template TargetInfo *getMipsTargetInfo<ELF32LE>(); +template TargetInfo *getMipsTargetInfo<ELF32BE>(); +template TargetInfo *getMipsTargetInfo<ELF64LE>(); +template TargetInfo *getMipsTargetInfo<ELF64BE>(); + +template bool isMipsPIC<ELF32LE>(const Defined *); +template bool isMipsPIC<ELF32BE>(const Defined *); +template bool isMipsPIC<ELF64LE>(const Defined *); +template bool isMipsPIC<ELF64BE>(const Defined *); -template bool elf::isMipsPIC<ELF32LE>(const Defined *); -template bool elf::isMipsPIC<ELF32BE>(const Defined *); -template bool elf::isMipsPIC<ELF64LE>(const Defined *); -template bool elf::isMipsPIC<ELF64BE>(const Defined *); +} // namespace elf +} // namespace lld diff --git a/ELF/Arch/MipsArchTree.cpp b/ELF/Arch/MipsArchTree.cpp index f64d03756457..923458afae0d 100644 --- a/ELF/Arch/MipsArchTree.cpp +++ b/ELF/Arch/MipsArchTree.cpp @@ -23,8 +23,8 @@ using namespace llvm; using namespace llvm::object; using namespace llvm::ELF; -using namespace lld; -using namespace lld::elf; +namespace lld { +namespace elf { namespace { struct ArchTreeEdge { @@ -166,17 +166,17 @@ static ArchTreeEdge archTree[] = { {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1}, }; -static bool isArchMatched(uint32_t New, uint32_t res) { - if (New == res) +static bool isArchMatched(uint32_t newFlags, uint32_t res) { + if (newFlags == res) return true; - if (New == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, res)) + if (newFlags == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, res)) return true; - if (New == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, res)) + if (newFlags == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, res)) return true; for (const auto &edge : archTree) { if (res == edge.child) { res = edge.parent; - if (res == New) + if (res == newFlags) return true; } } @@ -278,28 +278,34 @@ static uint32_t getArchFlags(ArrayRef<FileFlags> files) { uint32_t ret = files[0].flags & (EF_MIPS_ARCH | EF_MIPS_MACH); for (const FileFlags &f : files.slice(1)) { - uint32_t New = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH); + uint32_t newFlags = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH); // Check ISA compatibility. - if (isArchMatched(New, ret)) + if (isArchMatched(newFlags, ret)) continue; - if (!isArchMatched(ret, New)) { + if (!isArchMatched(ret, newFlags)) { error("incompatible target ISA:\n>>> " + toString(files[0].file) + ": " + getFullArchName(ret) + "\n>>> " + toString(f.file) + ": " + - getFullArchName(New)); + getFullArchName(newFlags)); return 0; } - ret = New; + ret = newFlags; } return ret; } -template <class ELFT> uint32_t elf::calcMipsEFlags() { +template <class ELFT> uint32_t calcMipsEFlags() { std::vector<FileFlags> v; for (InputFile *f : objectFiles) v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader()->e_flags}); - if (v.empty()) - return 0; + if (v.empty()) { + // If we don't have any input files, we'll have to rely on the information + // we can derive from emulation information, since this at least gets us + // ABI. + if (config->emulation.empty() || config->is64) + return 0; + return config->mipsN32Abi ? EF_MIPS_ABI2 : EF_MIPS_ABI_O32; + } checkFlags(v); return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v); } @@ -344,8 +350,7 @@ static StringRef getMipsFpAbiName(uint8_t fpAbi) { } } -uint8_t elf::getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag, - StringRef fileName) { +uint8_t getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag, StringRef fileName) { if (compareMipsFpAbi(newFlag, oldFlag) >= 0) return newFlag; if (compareMipsFpAbi(oldFlag, newFlag) < 0) @@ -361,7 +366,7 @@ template <class ELFT> static bool isN32Abi(const InputFile *f) { return false; } -bool elf::isMipsN32Abi(const InputFile *f) { +bool isMipsN32Abi(const InputFile *f) { switch (config->ekind) { case ELF32LEKind: return isN32Abi<ELF32LE>(f); @@ -376,14 +381,17 @@ bool elf::isMipsN32Abi(const InputFile *f) { } } -bool elf::isMicroMips() { return config->eflags & EF_MIPS_MICROMIPS; } +bool isMicroMips() { return config->eflags & EF_MIPS_MICROMIPS; } -bool elf::isMipsR6() { +bool isMipsR6() { uint32_t arch = config->eflags & EF_MIPS_ARCH; return arch == EF_MIPS_ARCH_32R6 || arch == EF_MIPS_ARCH_64R6; } -template uint32_t elf::calcMipsEFlags<ELF32LE>(); -template uint32_t elf::calcMipsEFlags<ELF32BE>(); -template uint32_t elf::calcMipsEFlags<ELF64LE>(); -template uint32_t elf::calcMipsEFlags<ELF64BE>(); +template uint32_t calcMipsEFlags<ELF32LE>(); +template uint32_t calcMipsEFlags<ELF32BE>(); +template uint32_t calcMipsEFlags<ELF64LE>(); +template uint32_t calcMipsEFlags<ELF64BE>(); + +} // namespace elf +} // namespace lld diff --git a/ELF/Arch/PPC.cpp b/ELF/Arch/PPC.cpp index 46c5891e4f8a..c4eecb9a29c2 100644 --- a/ELF/Arch/PPC.cpp +++ b/ELF/Arch/PPC.cpp @@ -16,8 +16,9 @@ using namespace llvm; using namespace llvm::support::endian; using namespace llvm::ELF; -using namespace lld; -using namespace lld::elf; + +namespace lld { +namespace elf { namespace { class PPC final : public TargetInfo { @@ -61,7 +62,7 @@ static void writeFromHalf16(uint8_t *loc, uint32_t insn) { write32(config->isLE ? loc : loc - 2, insn); } -void elf::writePPC32GlinkSection(uint8_t *buf, size_t numEntries) { +void writePPC32GlinkSection(uint8_t *buf, size_t numEntries) { // On PPC Secure PLT ABI, bl foo@plt jumps to a call stub, which loads an // absolute address from a specific .plt slot (usually called .got.plt on // other targets) and jumps there. @@ -190,6 +191,13 @@ bool PPC::inBranchRange(RelType type, uint64_t src, uint64_t dst) const { RelExpr PPC::getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const { switch (type) { + case R_PPC_NONE: + return R_NONE; + case R_PPC_ADDR16_HA: + case R_PPC_ADDR16_HI: + case R_PPC_ADDR16_LO: + case R_PPC_ADDR32: + return R_ABS; case R_PPC_DTPREL16: case R_PPC_DTPREL16_HA: case R_PPC_DTPREL16_HI: @@ -227,7 +235,9 @@ RelExpr PPC::getRelExpr(RelType type, const Symbol &s, case R_PPC_TPREL16_HI: return R_TLS; default: - return R_ABS; + error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + + ") against symbol " + toString(s)); + return R_NONE; } } @@ -319,7 +329,7 @@ void PPC::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { break; } default: - error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); + llvm_unreachable("unknown relocation"); } } @@ -426,7 +436,10 @@ void PPC::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const { } } -TargetInfo *elf::getPPCTargetInfo() { +TargetInfo *getPPCTargetInfo() { static PPC target; return ⌖ } + +} // namespace elf +} // namespace lld diff --git a/ELF/Arch/PPC64.cpp b/ELF/Arch/PPC64.cpp index 70d284cfad71..905903fa4d66 100644 --- a/ELF/Arch/PPC64.cpp +++ b/ELF/Arch/PPC64.cpp @@ -16,8 +16,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 { static uint64_t ppc64TocOffset = 0x8000; static uint64_t dynamicThreadPointerOffset = 0x8000; @@ -59,7 +60,7 @@ enum DFormOpcd { ADDI = 14 }; -uint64_t elf::getPPC64TocBase() { +uint64_t getPPC64TocBase() { // The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The // TOC starts where the first of these sections starts. We always create a // .got when we see a relocation that uses it, so for us the start is always @@ -73,7 +74,7 @@ uint64_t elf::getPPC64TocBase() { return tocVA + ppc64TocOffset; } -unsigned elf::getPPC64GlobalEntryToLocalEntryOffset(uint8_t stOther) { +unsigned getPPC64GlobalEntryToLocalEntryOffset(uint8_t stOther) { // The offset is encoded into the 3 most significant bits of the st_other // field, with some special values described in section 3.4.1 of the ABI: // 0 --> Zero offset between the GEP and LEP, and the function does NOT use @@ -98,7 +99,7 @@ unsigned elf::getPPC64GlobalEntryToLocalEntryOffset(uint8_t stOther) { return 0; } -bool elf::isPPC64SmallCodeModelTocReloc(RelType type) { +bool isPPC64SmallCodeModelTocReloc(RelType type) { // The only small code model relocations that access the .toc section. return type == R_PPC64_TOC16 || type == R_PPC64_TOC16_DS; } @@ -153,8 +154,8 @@ getRelaTocSymAndAddend(InputSectionBase *tocSec, uint64_t offset) { // ld/lwa 3, 0(3) # load the value from the address // // Returns true if the relaxation is performed. -bool elf::tryRelaxPPC64TocIndirection(RelType type, const Relocation &rel, - uint8_t *bufLoc) { +bool tryRelaxPPC64TocIndirection(RelType type, const Relocation &rel, + uint8_t *bufLoc) { assert(config->tocOptimize); if (rel.addend < 0) return false; @@ -175,6 +176,10 @@ bool elf::tryRelaxPPC64TocIndirection(RelType type, const Relocation &rel, if (!d || d->isPreemptible) return false; + // R_PPC64_ADDR64 should have created a canonical PLT for the non-preemptable + // ifunc and changed its type to STT_FUNC. + assert(!d->isGnuIFunc()); + // Two instructions can materialize a 32-bit signed offset from the toc base. uint64_t tocRelative = d->getVA(addend) - getPPC64TocBase(); if (!isInt<32>(tocRelative)) @@ -454,7 +459,7 @@ void PPC64::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const { } } -unsigned elf::getPPCDFormOp(unsigned secondaryOp) { +unsigned getPPCDFormOp(unsigned secondaryOp) { switch (secondaryOp) { case LBZX: return LBZ; @@ -532,6 +537,21 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const { RelExpr PPC64::getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const { switch (type) { + case R_PPC64_NONE: + return R_NONE; + case R_PPC64_ADDR16: + case R_PPC64_ADDR16_DS: + case R_PPC64_ADDR16_HA: + case R_PPC64_ADDR16_HI: + case R_PPC64_ADDR16_HIGHER: + case R_PPC64_ADDR16_HIGHERA: + case R_PPC64_ADDR16_HIGHEST: + case R_PPC64_ADDR16_HIGHESTA: + case R_PPC64_ADDR16_LO: + case R_PPC64_ADDR16_LO_DS: + case R_PPC64_ADDR32: + case R_PPC64_ADDR64: + return R_ABS; case R_PPC64_GOT16: case R_PPC64_GOT16_DS: case R_PPC64_GOT16_HA: @@ -554,6 +574,7 @@ RelExpr PPC64::getRelExpr(RelType type, const Symbol &s, return R_PPC64_CALL_PLT; case R_PPC64_REL16_LO: case R_PPC64_REL16_HA: + case R_PPC64_REL16_HI: case R_PPC64_REL32: case R_PPC64_REL64: return R_PC; @@ -607,7 +628,9 @@ RelExpr PPC64::getRelExpr(RelType type, const Symbol &s, case R_PPC64_TLS: return R_TLSIE_HINT; default: - return R_ABS; + error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + + ") against symbol " + toString(s)); + return R_NONE; } } @@ -870,7 +893,7 @@ void PPC64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { write64(loc, val - dynamicThreadPointerOffset); break; default: - error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); + llvm_unreachable("unknown relocation"); } } @@ -1071,7 +1094,10 @@ bool PPC64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end, return true; } -TargetInfo *elf::getPPC64TargetInfo() { +TargetInfo *getPPC64TargetInfo() { static PPC64 target; return ⌖ } + +} // namespace elf +} // namespace lld diff --git a/ELF/Arch/RISCV.cpp b/ELF/Arch/RISCV.cpp index 6f16ade57177..e7c0e36e0327 100644 --- a/ELF/Arch/RISCV.cpp +++ b/ELF/Arch/RISCV.cpp @@ -14,8 +14,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 { @@ -436,7 +437,10 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type, } } -TargetInfo *elf::getRISCVTargetInfo() { +TargetInfo *getRISCVTargetInfo() { static RISCV target; return ⌖ } + +} // namespace elf +} // namespace lld diff --git a/ELF/Arch/SPARCV9.cpp b/ELF/Arch/SPARCV9.cpp index 5299206dd919..a0afdff08a63 100644 --- a/ELF/Arch/SPARCV9.cpp +++ b/ELF/Arch/SPARCV9.cpp @@ -16,8 +16,9 @@ using namespace llvm; using namespace llvm::support::endian; using namespace llvm::ELF; -using namespace lld; -using namespace lld::elf; + +namespace lld { +namespace elf { namespace { class SPARCV9 final : public TargetInfo { @@ -143,7 +144,10 @@ void SPARCV9::writePlt(uint8_t *buf, uint64_t gotEntryAddr, relocateOne(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize)); } -TargetInfo *elf::getSPARCV9TargetInfo() { +TargetInfo *getSPARCV9TargetInfo() { static SPARCV9 target; return ⌖ } + +} // namespace elf +} // namespace lld diff --git a/ELF/Arch/X86.cpp b/ELF/Arch/X86.cpp index e1dd231e8e8d..b27a6e302e78 100644 --- a/ELF/Arch/X86.cpp +++ b/ELF/Arch/X86.cpp @@ -16,8 +16,9 @@ using namespace llvm; using namespace llvm::support::endian; using namespace llvm::ELF; -using namespace lld; -using namespace lld::elf; + +namespace lld { +namespace elf { namespace { class X86 : public TargetInfo { @@ -539,7 +540,7 @@ void RetpolineNoPic::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, write32le(buf + 22, -off - 26); } -TargetInfo *elf::getX86TargetInfo() { +TargetInfo *getX86TargetInfo() { if (config->zRetpolineplt) { if (config->isPic) { static RetpolinePic t; @@ -552,3 +553,6 @@ TargetInfo *elf::getX86TargetInfo() { static X86 t; return &t; } + +} // namespace elf +} // namespace lld diff --git a/ELF/Arch/X86_64.cpp b/ELF/Arch/X86_64.cpp index de67aa5c33dc..bb8d92fc61b9 100644 --- a/ELF/Arch/X86_64.cpp +++ b/ELF/Arch/X86_64.cpp @@ -18,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 { @@ -698,4 +699,7 @@ static TargetInfo *getTargetInfo() { return &t; } -TargetInfo *elf::getX86_64TargetInfo() { return getTargetInfo(); } +TargetInfo *getX86_64TargetInfo() { return getTargetInfo(); } + +} // namespace elf +} // namespace lld |