Index: ELF/Arch/AArch64.cpp =================================================================== --- ELF/Arch/AArch64.cpp +++ ELF/Arch/AArch64.cpp @@ -40,7 +40,8 @@ void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const override; bool usesOnlyLowPageBits(uint32_t Type) const override; - void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate = true) const override; RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, RelExpr Expr) const override; void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; @@ -201,16 +202,19 @@ or32le(L, (Imm & 0xFFF) << 10); } -void AArch64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { +void AArch64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate) const { switch (Type) { case R_AARCH64_ABS16: case R_AARCH64_PREL16: - checkIntUInt<16>(Loc, Val, Type); + if (Validate) + checkIntUInt<16>(Loc, Val, Type); write16le(Loc, Val); break; case R_AARCH64_ABS32: case R_AARCH64_PREL32: - checkIntUInt<32>(Loc, Val, Type); + if (Validate) + checkIntUInt<32>(Loc, Val, Type); write32le(Loc, Val); break; case R_AARCH64_ABS64: @@ -225,26 +229,31 @@ case R_AARCH64_ADR_PREL_PG_HI21: case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: case R_AARCH64_TLSDESC_ADR_PAGE21: - checkInt<33>(Loc, Val, Type); + if (Validate) + checkInt<33>(Loc, Val, Type); write32AArch64Addr(Loc, Val >> 12); break; case R_AARCH64_ADR_PREL_LO21: - checkInt<21>(Loc, Val, Type); + if (Validate) + checkInt<21>(Loc, Val, Type); write32AArch64Addr(Loc, Val); break; case R_AARCH64_CALL26: case R_AARCH64_JUMP26: - checkInt<28>(Loc, Val, Type); + if (Validate) + checkInt<28>(Loc, Val, Type); or32le(Loc, (Val & 0x0FFFFFFC) >> 2); break; case R_AARCH64_CONDBR19: - checkInt<21>(Loc, Val, Type); + if (Validate) + checkInt<21>(Loc, Val, Type); or32le(Loc, (Val & 0x1FFFFC) << 3); break; case R_AARCH64_LD64_GOT_LO12_NC: case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case R_AARCH64_TLSDESC_LD64_LO12: - checkAlignment<8>(Loc, Val, Type); + if (Validate) + checkAlignment<8>(Loc, Val, Type); or32le(Loc, (Val & 0xFF8) << 7); break; case R_AARCH64_LDST8_ABS_LO12_NC: @@ -275,11 +284,13 @@ or32le(Loc, (Val & 0xFFFF000000000000) >> 43); break; case R_AARCH64_TSTBR14: - checkInt<16>(Loc, Val, Type); + if (Validate) + checkInt<16>(Loc, Val, Type); or32le(Loc, (Val & 0xFFFC) << 3); break; case R_AARCH64_TLSLE_ADD_TPREL_HI12: - checkInt<24>(Loc, Val, Type); + if (Validate) + checkInt<24>(Loc, Val, Type); or32AArch64Imm(Loc, Val >> 12); break; case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: Index: ELF/Arch/AMDGPU.cpp =================================================================== --- ELF/Arch/AMDGPU.cpp +++ ELF/Arch/AMDGPU.cpp @@ -25,7 +25,8 @@ class AMDGPU final : public TargetInfo { public: AMDGPU(); - void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate = true) const override; RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, const uint8_t *Loc) const override; }; @@ -37,7 +38,8 @@ GotEntrySize = 8; } -void AMDGPU::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { +void AMDGPU::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool /*Validate*/) const { switch (Type) { case R_AMDGPU_ABS32: case R_AMDGPU_GOTPCREL: Index: ELF/Arch/ARM.cpp =================================================================== --- ELF/Arch/ARM.cpp +++ ELF/Arch/ARM.cpp @@ -42,7 +42,8 @@ const SymbolBody &S) const override; bool inBranchRange(uint32_t RelocType, uint64_t Src, uint64_t Dst) const override; - void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate = true) const override; }; } // namespace @@ -263,7 +264,8 @@ return Distance <= Range; } -void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { +void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate) const { switch (Type) { case R_ARM_ABS32: case R_ARM_BASE_PREL: @@ -289,7 +291,8 @@ write32le(Loc, 1); break; case R_ARM_PREL31: - checkInt<31>(Loc, Val, Type); + if (Validate) + checkInt<31>(Loc, Val, Type); write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000)); break; case R_ARM_CALL: @@ -298,7 +301,8 @@ if (Val & 1) { // If bit 0 of Val is 1 the target is Thumb, we must select a BLX. // The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1' - checkInt<26>(Loc, Val, Type); + if (Validate) + checkInt<26>(Loc, Val, Type); write32le(Loc, 0xfa000000 | // opcode ((Val & 2) << 23) | // H ((Val >> 2) & 0x00ffffff)); // imm24 @@ -313,16 +317,19 @@ case R_ARM_JUMP24: case R_ARM_PC24: case R_ARM_PLT32: - checkInt<26>(Loc, Val, Type); + if (Validate) + checkInt<26>(Loc, Val, Type); write32le(Loc, (read32le(Loc) & ~0x00ffffff) | ((Val >> 2) & 0x00ffffff)); break; case R_ARM_THM_JUMP11: - checkInt<12>(Loc, Val, Type); + if (Validate) + checkInt<12>(Loc, Val, Type); write16le(Loc, (read32le(Loc) & 0xf800) | ((Val >> 1) & 0x07ff)); break; case R_ARM_THM_JUMP19: // Encoding T3: Val = S:J2:J1:imm6:imm11:0 - checkInt<21>(Loc, Val, Type); + if (Validate) + checkInt<21>(Loc, Val, Type); write16le(Loc, (read16le(Loc) & 0xfbc0) | // opcode cond ((Val >> 10) & 0x0400) | // S @@ -348,7 +355,8 @@ case R_ARM_THM_JUMP24: // Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0 // FIXME: Use of I1 and I2 require v6T2ops - checkInt<25>(Loc, Val, Type); + if (Validate) + checkInt<25>(Loc, Val, Type); write16le(Loc, 0xf000 | // opcode ((Val >> 14) & 0x0400) | // S @@ -366,14 +374,16 @@ break; case R_ARM_MOVT_ABS: case R_ARM_MOVT_PREL: - checkInt<32>(Loc, Val, Type); + if (Validate) + checkInt<32>(Loc, Val, Type); write32le(Loc, (read32le(Loc) & ~0x000f0fff) | (((Val >> 16) & 0xf000) << 4) | ((Val >> 16) & 0xfff)); break; case R_ARM_THM_MOVT_ABS: case R_ARM_THM_MOVT_PREL: // Encoding T1: A = imm4:i:imm3:imm8 - checkInt<32>(Loc, Val, Type); + if (Validate) + checkInt<32>(Loc, Val, Type); write16le(Loc, 0xf2c0 | // opcode ((Val >> 17) & 0x0400) | // i Index: ELF/Arch/AVR.cpp =================================================================== --- ELF/Arch/AVR.cpp +++ ELF/Arch/AVR.cpp @@ -45,7 +45,8 @@ public: RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, const uint8_t *Loc) const override; - void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate = true) const override; }; } // namespace @@ -60,7 +61,8 @@ } } -void AVR::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { +void AVR::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool /*Validate*/) const { switch (Type) { case R_AVR_CALL: { uint16_t Hi = Val >> 17; Index: ELF/Arch/Mips.cpp =================================================================== --- ELF/Arch/Mips.cpp +++ ELF/Arch/Mips.cpp @@ -39,7 +39,8 @@ int32_t Index, unsigned RelOff) const override; bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, const SymbolBody &S) const override; - void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate = true) const override; bool usesOnlyLowPageBits(uint32_t Type) const override; }; } // namespace @@ -149,12 +150,15 @@ } template -static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t V) { +static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t V, + bool Validate) { uint32_t Mask = 0xffffffff >> (32 - BSIZE); uint32_t Instr = read32(Loc); - if (SHIFT > 0) - checkAlignment<(1 << SHIFT)>(Loc, V, Type); - checkInt(Loc, V, Type); + if (Validate) { + if (SHIFT > 0) + checkAlignment<(1 << SHIFT)>(Loc, V, Type); + checkInt(Loc, V, Type); + } write32(Loc, (Instr & ~Mask) | ((V >> SHIFT) & Mask)); } @@ -314,7 +318,8 @@ } template -void MIPS::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { +void MIPS::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate) const { const endianness E = ELFT::TargetEndianness; // Thread pointer and DRP offsets from the start of TLS data area. // https://www.linux-mips.org/wiki/NPTL @@ -357,7 +362,8 @@ case R_MIPS_GPREL16: case R_MIPS_TLS_GD: case R_MIPS_TLS_LDM: - checkInt<16>(Loc, Val, Type); + if (Validate) + checkInt<16>(Loc, Val, Type); LLVM_FALLTHROUGH; case R_MIPS_CALL16: case R_MIPS_CALL_LO16: @@ -388,19 +394,19 @@ // Ignore this optimization relocation for now break; case R_MIPS_PC16: - applyMipsPcReloc(Loc, Type, Val); + applyMipsPcReloc(Loc, Type, Val, Validate); break; case R_MIPS_PC19_S2: - applyMipsPcReloc(Loc, Type, Val); + applyMipsPcReloc(Loc, Type, Val, Validate); break; case R_MIPS_PC21_S2: - applyMipsPcReloc(Loc, Type, Val); + applyMipsPcReloc(Loc, Type, Val, Validate); break; case R_MIPS_PC26_S2: - applyMipsPcReloc(Loc, Type, Val); + applyMipsPcReloc(Loc, Type, Val, Validate); break; case R_MIPS_PC32: - applyMipsPcReloc(Loc, Type, Val); + applyMipsPcReloc(Loc, Type, Val, Validate); break; default: error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); Index: ELF/Arch/PPC.cpp =================================================================== --- ELF/Arch/PPC.cpp +++ ELF/Arch/PPC.cpp @@ -22,13 +22,15 @@ class PPC final : public TargetInfo { public: PPC() { GotBaseSymOff = 0x8000; } - void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate = true) const override; RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, const uint8_t *Loc) const override; }; } // namespace -void PPC::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { +void PPC::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool /*Validate*/) const { switch (Type) { case R_PPC_ADDR16_HA: write16be(Loc, (Val + 0x8000) >> 16); Index: ELF/Arch/PPC64.cpp =================================================================== --- ELF/Arch/PPC64.cpp +++ ELF/Arch/PPC64.cpp @@ -43,7 +43,8 @@ const uint8_t *Loc) 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, uint32_t Type, uint64_t Val) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate = true) const override; }; } // namespace @@ -142,25 +143,29 @@ } } -void PPC64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { +void PPC64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate) const { // For a TOC-relative relocation, proceed in terms of the corresponding // ADDR16 relocation type. std::tie(Type, Val) = toAddr16Rel(Type, Val); switch (Type) { case R_PPC64_ADDR14: { - checkAlignment<4>(Loc, Val, Type); + if (Validate) + checkAlignment<4>(Loc, Val, Type); // Preserve the AA/LK bits in the branch instruction uint8_t AALK = Loc[3]; write16be(Loc + 2, (AALK & 3) | (Val & 0xfffc)); break; } case R_PPC64_ADDR16: - checkInt<16>(Loc, Val, Type); + if (Validate) + checkInt<16>(Loc, Val, Type); write16be(Loc, Val); break; case R_PPC64_ADDR16_DS: - checkInt<16>(Loc, Val, Type); + if (Validate) + checkInt<16>(Loc, Val, Type); write16be(Loc, (read16be(Loc) & 3) | (Val & ~3)); break; case R_PPC64_ADDR16_HA: @@ -192,7 +197,8 @@ break; case R_PPC64_ADDR32: case R_PPC64_REL32: - checkInt<32>(Loc, Val, Type); + if (Validate) + checkInt<32>(Loc, Val, Type); write32be(Loc, Val); break; case R_PPC64_ADDR64: @@ -202,7 +208,8 @@ break; case R_PPC64_REL24: { uint32_t Mask = 0x03FFFFFC; - checkInt<24>(Loc, Val, Type); + if (Validate) + checkInt<24>(Loc, Val, Type); write32be(Loc, (read32be(Loc) & ~Mask) | (Val & Mask)); break; } Index: ELF/Arch/SPARCV9.cpp =================================================================== --- ELF/Arch/SPARCV9.cpp +++ ELF/Arch/SPARCV9.cpp @@ -28,7 +28,8 @@ const uint8_t *Loc) const override; void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const override; - void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate = true) const override; }; } // namespace @@ -73,28 +74,33 @@ } } -void SPARCV9::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { +void SPARCV9::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate) const { switch (Type) { case R_SPARC_32: case R_SPARC_UA32: // V-word32 - checkUInt<32>(Loc, Val, Type); + if (Validate) + checkUInt<32>(Loc, Val, Type); write32be(Loc, Val); break; case R_SPARC_DISP32: // V-disp32 - checkInt<32>(Loc, Val, Type); + if (Validate) + checkInt<32>(Loc, Val, Type); write32be(Loc, Val); break; case R_SPARC_WDISP30: case R_SPARC_WPLT30: // V-disp30 - checkInt<32>(Loc, Val, Type); + if (Validate) + checkInt<32>(Loc, Val, Type); write32be(Loc, (read32be(Loc) & ~0x3fffffff) | ((Val >> 2) & 0x3fffffff)); break; case R_SPARC_22: // V-imm22 - checkUInt<22>(Loc, Val, Type); + if (Validate) + checkUInt<22>(Loc, Val, Type); write32be(Loc, (read32be(Loc) & ~0x003fffff) | (Val & 0x003fffff)); break; case R_SPARC_GOT22: @@ -104,7 +110,8 @@ break; case R_SPARC_WDISP19: // V-disp19 - checkInt<21>(Loc, Val, Type); + if (Validate) + checkInt<21>(Loc, Val, Type); write32be(Loc, (read32be(Loc) & ~0x0007ffff) | ((Val >> 2) & 0x0007ffff)); break; case R_SPARC_GOT10: Index: ELF/Arch/X86.cpp =================================================================== --- ELF/Arch/X86.cpp +++ ELF/Arch/X86.cpp @@ -34,7 +34,8 @@ 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, uint32_t Type, uint64_t Val) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate = true) const override; RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, RelExpr Expr) const override; @@ -231,21 +232,25 @@ } } -void X86::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { +void X86::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate) const { // 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. switch (Type) { case R_386_8: - checkUInt<8>(Loc, Val, Type); + if (Validate) + checkUInt<8>(Loc, Val, Type); *Loc = Val; break; case R_386_PC8: - checkInt<8>(Loc, Val, Type); + if (Validate) + checkInt<8>(Loc, Val, Type); *Loc = Val; break; case R_386_16: - checkUInt<16>(Loc, Val, Type); + if (Validate) + checkUInt<16>(Loc, Val, Type); write16le(Loc, Val); break; case R_386_PC16: @@ -259,11 +264,13 @@ // 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<17>(Loc, Val, Type); + if (Validate) + checkInt<17>(Loc, Val, Type); write16le(Loc, Val); break; default: - checkInt<32>(Loc, Val, Type); + if (Validate) + checkInt<32>(Loc, Val, Type); write32le(Loc, Val); } } Index: ELF/Arch/X86_64.cpp =================================================================== --- ELF/Arch/X86_64.cpp +++ ELF/Arch/X86_64.cpp @@ -34,7 +34,8 @@ 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, uint32_t Type, uint64_t Val) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate = true) const override; RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, RelExpr Expr) const override; @@ -283,19 +284,22 @@ } template -void X86_64::relocateOne(uint8_t *Loc, uint32_t Type, - uint64_t Val) const { +void X86_64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate) const { switch (Type) { case R_X86_64_8: - checkUInt<8>(Loc, Val, Type); + if (Validate) + checkUInt<8>(Loc, Val, Type); *Loc = Val; break; case R_X86_64_16: - checkUInt<16>(Loc, Val, Type); + if (Validate) + checkUInt<16>(Loc, Val, Type); write16le(Loc, Val); break; case R_X86_64_32: - checkUInt<32>(Loc, Val, Type); + if (Validate) + checkUInt<32>(Loc, Val, Type); write32le(Loc, Val); break; case R_X86_64_32S: @@ -311,7 +315,8 @@ case R_X86_64_TLSLD: case R_X86_64_DTPOFF32: case R_X86_64_SIZE32: - checkInt<32>(Loc, Val, Type); + if (Validate) + checkInt<32>(Loc, Val, Type); write32le(Loc, Val); break; case R_X86_64_64: Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -728,7 +728,9 @@ write32be(BufLoc + 4, 0xe8410028); // ld %r2, 40(%r1) LLVM_FALLTHROUGH; default: - Target->relocateOne(BufLoc, Type, TargetVA); + bool UndefinedWeak = (Rel.Sym->isUndefined() || Rel.Sym->isLazy()) && + !Rel.Sym->isLocal() && Rel.Sym->symbol()->isWeak(); + Target->relocateOne(BufLoc, Type, TargetVA, !UndefinedWeak); break; } } Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -56,7 +56,8 @@ uint64_t Dst) const; virtual RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, const uint8_t *Loc) const = 0; - virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const = 0; + virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val, + bool Validate = true) const = 0; virtual ~TargetInfo(); unsigned TlsGdRelaxSkip = 1; Index: test/ELF/weak-undef-and-large-addr.s =================================================================== --- test/ELF/weak-undef-and-large-addr.s +++ test/ELF/weak-undef-and-large-addr.s @@ -0,0 +1,9 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: ld.lld %t.o -o %t.elf -Ttext=0x200000000 + +.weak foo + +.globl _start +_start: + call foo