Index: lld/trunk/ELF/InputSection.cpp =================================================================== --- lld/trunk/ELF/InputSection.cpp +++ lld/trunk/ELF/InputSection.cpp @@ -123,6 +123,14 @@ } template +static typename llvm::object::ELFFile::uintX_t +getSymSize(SymbolBody &Body) { + if (auto *SS = dyn_cast>(&Body)) + return SS->Sym.st_size; + return 0; +} + +template template void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd, RelIteratorRange Rels) { @@ -153,7 +161,7 @@ const Elf_Shdr *SymTab = File->getSymbolTable(); if (SymIndex < SymTab->sh_info) { uintX_t SymVA = getLocalRelTarget(*File, RI); - Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA, + Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA, 0, findMipsPairedReloc(Buf, Type, NextRelocs)); continue; } @@ -191,11 +199,13 @@ } else if (!Target->relocNeedsCopy(Type, Body) && isa>(Body)) { continue; - } else if (Target->isTlsDynReloc(Type)) { + } else if (Target->isTlsDynReloc(Type) || + Target->isSizeDynReloc(Type, Body)) { continue; } - Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, - SymVA + getAddend(RI), + uintX_t A = getAddend(RI); + uintX_t Size = getSymSize(Body); + Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA + A, Size + A, findMipsPairedReloc(Buf, Type, NextRelocs)); } } Index: lld/trunk/ELF/Target.h =================================================================== --- lld/trunk/ELF/Target.h +++ lld/trunk/ELF/Target.h @@ -53,11 +53,12 @@ uint64_t GotEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const = 0; virtual bool isRelRelative(uint32_t Type) const; + virtual bool isSizeDynReloc(uint32_t Type, const SymbolBody &S) const; virtual bool relocNeedsCopy(uint32_t Type, const SymbolBody &S) const; virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0; virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const = 0; virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, - uint64_t P, uint64_t SA, + uint64_t P, uint64_t SA, uint64_t ZA = 0, uint8_t *PairedLoc = nullptr) const = 0; virtual bool isTlsOptimized(unsigned Type, const SymbolBody *S) const; virtual unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, Index: lld/trunk/ELF/Target.cpp =================================================================== --- lld/trunk/ELF/Target.cpp +++ lld/trunk/ELF/Target.cpp @@ -87,7 +87,8 @@ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, - uint64_t SA, uint8_t *PairedLoc = nullptr) const override; + uint64_t SA, uint64_t ZA = 0, + uint8_t *PairedLoc = nullptr) const override; bool isTlsOptimized(unsigned Type, const SymbolBody *S) const override; unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, @@ -120,9 +121,11 @@ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, - uint64_t SA, uint8_t *PairedLoc = nullptr) const override; + uint64_t SA, uint64_t ZA = 0, + uint8_t *PairedLoc = nullptr) const override; bool isRelRelative(uint32_t Type) const override; bool isTlsOptimized(unsigned Type, const SymbolBody *S) const override; + bool isSizeDynReloc(uint32_t Type, const SymbolBody &S) const override; unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, const SymbolBody &S) const override; @@ -150,7 +153,8 @@ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, - uint64_t SA, uint8_t *PairedLoc = nullptr) const override; + uint64_t SA, uint64_t ZA = 0, + uint8_t *PairedLoc = nullptr) const override; bool isRelRelative(uint32_t Type) const override; }; @@ -169,7 +173,8 @@ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, - uint64_t SA, uint8_t *PairedLoc = nullptr) const override; + uint64_t SA, uint64_t ZA = 0, + uint8_t *PairedLoc = nullptr) const override; }; template class MipsTargetInfo final : public TargetInfo { @@ -185,7 +190,8 @@ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, - uint64_t SA, uint8_t *PairedLoc = nullptr) const override; + uint64_t SA, uint64_t ZA = 0, + uint8_t *PairedLoc = nullptr) const override; }; } // anonymous namespace @@ -228,6 +234,10 @@ bool TargetInfo::isRelRelative(uint32_t Type) const { return true; } +bool TargetInfo::isSizeDynReloc(uint32_t Type, const SymbolBody &S) const { + return false; +} + unsigned TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, const SymbolBody &S) const { @@ -338,7 +348,7 @@ } void X86TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, - uint64_t P, uint64_t SA, + uint64_t P, uint64_t SA, uint64_t ZA, uint8_t *PairedLoc) const { switch (Type) { case R_386_32: @@ -623,10 +633,18 @@ case R_X86_64_PC32: case R_X86_64_PC64: case R_X86_64_PLT32: + case R_X86_64_SIZE32: + case R_X86_64_SIZE64: return true; } } +bool X86_64TargetInfo::isSizeDynReloc(uint32_t Type, + const SymbolBody &S) const { + return (Type == R_X86_64_SIZE32 || Type == R_X86_64_SIZE64) && + canBePreempted(&S, false); +} + bool X86_64TargetInfo::isTlsOptimized(unsigned Type, const SymbolBody *S) const { if (Config->Shared || (S && !S->isTLS())) @@ -767,7 +785,7 @@ } void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, - uint64_t P, uint64_t SA, + uint64_t P, uint64_t SA, uint64_t ZA, uint8_t *PairedLoc) const { switch (Type) { case R_X86_64_32: @@ -794,6 +812,12 @@ case R_X86_64_TLSLD: write32le(Loc, SA - P); break; + case R_X86_64_SIZE32: + write32le(Loc, ZA); + break; + case R_X86_64_SIZE64: + write64le(Loc, ZA); + break; case R_X86_64_TPOFF32: { uint64_t Val = SA - Out::TlsPhdr->p_memsz; checkInt<32>(Val, Type); @@ -915,7 +939,7 @@ } void PPC64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, - uint64_t P, uint64_t SA, + uint64_t P, uint64_t SA, uint64_t ZA, uint8_t *PairedLoc) const { uint64_t TB = getPPC64TocBase(); @@ -1153,7 +1177,7 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, - uint8_t *PairedLoc) const { + uint64_t ZA, uint8_t *PairedLoc) const { switch (Type) { case R_AARCH64_ABS16: checkIntUInt<16>(SA, Type); @@ -1266,7 +1290,7 @@ template void MipsTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, - uint8_t *PairedLoc) const { + uint64_t ZA, uint8_t *PairedLoc) const { const endianness E = ELFT::TargetEndianness; switch (Type) { case R_MIPS_32: Index: lld/trunk/test/ELF/Inputs/relocation-size-shared.s =================================================================== --- lld/trunk/test/ELF/Inputs/relocation-size-shared.s +++ lld/trunk/test/ELF/Inputs/relocation-size-shared.s @@ -0,0 +1,6 @@ +.data +.global fooshared +.type fooshared,%object +.size fooshared,26 +fooshared: +.zero 26 Index: lld/trunk/test/ELF/relocation-size-shared.s =================================================================== --- lld/trunk/test/ELF/relocation-size-shared.s +++ lld/trunk/test/ELF/relocation-size-shared.s @@ -0,0 +1,78 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocation-size-shared.s -o %tso.o +// RUN: ld.lld -shared %tso.o -o %tso +// RUN: ld.lld %t.o %tso -o %t1 +// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=RELOCSHARED %s +// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s + +// RELOCSHARED: Relocations [ +// RELOCSHARED-NEXT: Section ({{.*}}) .rela.dyn { +// RELOCSHARED-NEXT: 0x11018 R_X86_64_SIZE64 fooshared 0xFFFFFFFFFFFFFFFF +// RELOCSHARED-NEXT: 0x11020 R_X86_64_SIZE64 fooshared 0x0 +// RELOCSHARED-NEXT: 0x11028 R_X86_64_SIZE64 fooshared 0x1 +// RELOCSHARED-NEXT: 0x11048 R_X86_64_SIZE32 fooshared 0xFFFFFFFFFFFFFFFF +// RELOCSHARED-NEXT: 0x1104F R_X86_64_SIZE32 fooshared 0x0 +// RELOCSHARED-NEXT: 0x11056 R_X86_64_SIZE32 fooshared 0x1 +// RELOCSHARED-NEXT: } +// RELOCSHARED-NEXT:] + +// DISASM: Disassembly of section .text: +// DISASM: _data: +// DISASM-NEXT: 11000: 19 00 +// DISASM-NEXT: 11002: 00 00 +// DISASM-NEXT: 11004: 00 00 +// DISASM-NEXT: 11006: 00 00 +// DISASM-NEXT: 11008: 1a 00 +// DISASM-NEXT: 1100a: 00 00 +// DISASM-NEXT: 1100c: 00 00 +// DISASM-NEXT: 1100e: 00 00 +// DISASM-NEXT: 11010: 1b 00 +// DISASM-NEXT: 11012: 00 00 +// DISASM-NEXT: 11014: 00 00 +// DISASM-NEXT: 11016: 00 00 +// DISASM-NEXT: 11018: 00 00 +// DISASM-NEXT: 1101a: 00 00 +// DISASM-NEXT: 1101c: 00 00 +// DISASM-NEXT: 1101e: 00 00 +// DISASM-NEXT: 11020: 00 00 +// DISASM-NEXT: 11022: 00 00 +// DISASM-NEXT: 11024: 00 00 +// DISASM-NEXT: 11026: 00 00 +// DISASM-NEXT: 11028: 00 00 +// DISASM-NEXT: 1102a: 00 00 +// DISASM-NEXT: 1102c: 00 00 +// DISASM-NEXT: 1102e: 00 00 +// DISASM: _start: +// DISASM-NEXT: 11030: 8b 04 25 19 00 00 00 movl 25, %eax +// DISASM-NEXT: 11037: 8b 04 25 1a 00 00 00 movl 26, %eax +// DISASM-NEXT: 1103e: 8b 04 25 1b 00 00 00 movl 27, %eax +// DISASM-NEXT: 11045: 8b 04 25 00 00 00 00 movl 0, %eax +// DISASM-NEXT: 1104c: 8b 04 25 00 00 00 00 movl 0, %eax +// DISASM-NEXT: 11053: 8b 04 25 00 00 00 00 movl 0, %eax + +.data +.global foo +.type foo,%object +.size foo,26 +foo: +.zero 26 + +.text +_data: + // R_X86_64_SIZE64: + .quad foo@SIZE-1 + .quad foo@SIZE + .quad foo@SIZE+1 + .quad fooshared@SIZE-1 + .quad fooshared@SIZE + .quad fooshared@SIZE+1 + +.globl _start +_start: + // R_X86_64_SIZE32: + movl foo@SIZE-1,%eax + movl foo@SIZE,%eax + movl foo@SIZE+1,%eax + movl fooshared@SIZE-1,%eax + movl fooshared@SIZE,%eax + movl fooshared@SIZE+1,%eax Index: lld/trunk/test/ELF/relocation-size.s =================================================================== --- lld/trunk/test/ELF/relocation-size.s +++ lld/trunk/test/ELF/relocation-size.s @@ -0,0 +1,123 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +// RUN: ld.lld %t.o -o %t1 +// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=NORELOC %s +// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s +// RUN: ld.lld -shared %t.o -o %t1 +// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=RELOCSHARED %s +// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASMSHARED %s + +// NORELOC: Relocations [ +// NORELOC-NEXT: ] + +// DISASM: Disassembly of section .text: +// DISASM-NEXT: _data: +// DISASM-NEXT: 11000: 19 00 +// DISASM-NEXT: 11002: 00 00 +// DISASM-NEXT: 11004: 00 00 +// DISASM-NEXT: 11006: 00 00 +// DISASM-NEXT: 11008: 1a 00 +// DISASM-NEXT: 1100a: 00 00 +// DISASM-NEXT: 1100c: 00 00 +// DISASM-NEXT: 1100e: 00 00 +// DISASM-NEXT: 11010: 1b 00 +// DISASM-NEXT: 11012: 00 00 +// DISASM-NEXT: 11014: 00 00 +// DISASM-NEXT: 11016: 00 00 +// DISASM-NEXT: 11018: 19 00 +// DISASM-NEXT: 1101a: 00 00 +// DISASM-NEXT: 1101c: 00 00 +// DISASM-NEXT: 1101e: 00 00 +// DISASM-NEXT: 11020: 1a 00 +// DISASM-NEXT: 11022: 00 00 +// DISASM-NEXT: 11024: 00 00 +// DISASM-NEXT: 11026: 00 00 +// DISASM-NEXT: 11028: 1b 00 +// DISASM-NEXT: 1102a: 00 00 +// DISASM-NEXT: 1102c: 00 00 +// DISASM-NEXT: 1102e: 00 00 +// DISASM: _start: +// DISASM-NEXT: 11030: 8b 04 25 19 00 00 00 movl 25, %eax +// DISASM-NEXT: 11037: 8b 04 25 1a 00 00 00 movl 26, %eax +// DISASM-NEXT: 1103e: 8b 04 25 1b 00 00 00 movl 27, %eax +// DISASM-NEXT: 11045: 8b 04 25 19 00 00 00 movl 25, %eax +// DISASM-NEXT: 1104c: 8b 04 25 1a 00 00 00 movl 26, %eax +// DISASM-NEXT: 11053: 8b 04 25 1b 00 00 00 movl 27, %eax + +// RELOCSHARED: Relocations [ +// RELOCSHARED-NEXT: Section ({{.*}}) .rela.dyn { +// RELOCSHARED-NEXT: 0x1000 R_X86_64_SIZE64 foo 0xFFFFFFFFFFFFFFFF +// RELOCSHARED-NEXT: 0x1008 R_X86_64_SIZE64 foo 0x0 +// RELOCSHARED-NEXT: 0x1010 R_X86_64_SIZE64 foo 0x1 +// RELOCSHARED-NEXT: 0x1033 R_X86_64_SIZE32 foo 0xFFFFFFFFFFFFFFFF +// RELOCSHARED-NEXT: 0x103A R_X86_64_SIZE32 foo 0x0 +// RELOCSHARED-NEXT: 0x1041 R_X86_64_SIZE32 foo 0x1 +// RELOCSHARED-NEXT: } +// RELOCSHARED-NEXT: ] + +// DISASMSHARED: Disassembly of section .text: +// DISASMSHARED-NEXT: _data: +// DISASMSHARED-NEXT: 1000: 00 00 +// DISASMSHARED-NEXT: 1002: 00 00 +// DISASMSHARED-NEXT: 1004: 00 00 +// DISASMSHARED-NEXT: 1006: 00 00 +// DISASMSHARED-NEXT: 1008: 00 00 +// DISASMSHARED-NEXT: 100a: 00 00 +// DISASMSHARED-NEXT: 100c: 00 00 +// DISASMSHARED-NEXT: 100e: 00 00 +// DISASMSHARED-NEXT: 1010: 00 00 +// DISASMSHARED-NEXT: 1012: 00 00 +// DISASMSHARED-NEXT: 1014: 00 00 +// DISASMSHARED-NEXT: 1016: 00 00 +// DISASMSHARED-NEXT: 1018: 19 00 +// DISASMSHARED-NEXT: 101a: 00 00 +// DISASMSHARED-NEXT: 101c: 00 00 +// DISASMSHARED-NEXT: 101e: 00 00 +// DISASMSHARED-NEXT: 1020: 1a 00 +// DISASMSHARED-NEXT: 1022: 00 00 +// DISASMSHARED-NEXT: 1024: 00 00 +// DISASMSHARED-NEXT: 1026: 00 00 +// DISASMSHARED-NEXT: 1028: 1b 00 +// DISASMSHARED-NEXT: 102a: 00 00 +// DISASMSHARED-NEXT: 102c: 00 00 +// DISASMSHARED-NEXT: 102e: 00 00 +// DISASMSHARED: _start: +// DISASMSHARED-NEXT: 1030: 8b 04 25 00 00 00 00 movl 0, %eax +// DISASMSHARED-NEXT: 1037: 8b 04 25 00 00 00 00 movl 0, %eax +// DISASMSHARED-NEXT: 103e: 8b 04 25 00 00 00 00 movl 0, %eax +// DISASMSHARED-NEXT: 1045: 8b 04 25 19 00 00 00 movl 25, %eax +// DISASMSHARED-NEXT: 104c: 8b 04 25 1a 00 00 00 movl 26, %eax +// DISASMSHARED-NEXT: 1053: 8b 04 25 1b 00 00 00 movl 27, %eax + +.data +.global foo +.type foo,%object +.size foo,26 +foo: +.zero 26 + +.data +.global foohidden +.hidden foohidden +.type foohidden,%object +.size foohidden,26 +foohidden: +.zero 26 + +.text +_data: + // R_X86_64_SIZE64: + .quad foo@SIZE-1 + .quad foo@SIZE + .quad foo@SIZE+1 + .quad foohidden@SIZE-1 + .quad foohidden@SIZE + .quad foohidden@SIZE+1 +.globl _start +_start: + // R_X86_64_SIZE32: + movl foo@SIZE-1,%eax + movl foo@SIZE,%eax + movl foo@SIZE+1,%eax + movl foohidden@SIZE-1,%eax + movl foohidden@SIZE,%eax + movl foohidden@SIZE+1,%eax