Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -120,7 +120,7 @@ void addEntry(SymbolBody *Sym); bool addDynTlsEntry(SymbolBody *Sym); bool addCurrentModuleTlsIndex(); - bool empty() const { return Entries.empty(); } + bool leaveInOutput() const { return Demanded || !Entries.empty(); } uintX_t getEntryAddr(const SymbolBody &B) const; uintX_t getGlobalDynAddr(const SymbolBody &B) const; uintX_t getNumEntries() const { return Entries.size(); } @@ -137,6 +137,7 @@ uint32_t getLocalTlsIndexVA() { return Base::getVA() + LocalTlsIndexOff; } + bool Demanded = false; private: std::vector Entries; uint32_t LocalTlsIndexOff = -1; Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -325,6 +325,13 @@ } bool X86TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { + // This relocation does not require got entry, + // but it is relative to got and needs it to be created. + // Here we request for that. + if (Type == R_386_GOTOFF) { + Out::Got->Demanded = true; + return false; + } if (S.isTLS() && Type == R_386_TLS_GD) return Target->isTlsOptimized(Type, &S) && canBePreempted(&S, true); if (Type == R_386_TLS_GOTIE) @@ -344,6 +351,7 @@ add32le(Loc, SA); break; case R_386_GOT32: + case R_386_GOTOFF: add32le(Loc, SA - Out::Got->getVA()); break; case R_386_GOTPC: Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -743,8 +743,10 @@ // We add the .got section to the result for dynamic MIPS target because // its address and properties are mentioned in the .dynamic section. - if (!Out::Got->empty() || - (isOutputDynamic() && Config->EMachine == EM_MIPS)) + Out::Got->Demanded |= + (isOutputDynamic() && Config->EMachine == EM_MIPS); + + if (Out::Got->leaveInOutput()) OutputSections.push_back(Out::Got); if (Out::GotPlt && !Out::GotPlt->empty()) OutputSections.push_back(Out::GotPlt); Index: test/ELF/got-i386.s =================================================================== --- test/ELF/got-i386.s +++ test/ELF/got-i386.s @@ -0,0 +1,56 @@ +// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o +// RUN: ld.lld %t.o -o %t +// RUN: llvm-readobj -s -r -t %t | FileCheck %s +// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s +// REQUIRES: x86 + +// CHECK: Name: .got +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: SHF_WRITE +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x12000 +// CHECK-NEXT: Offset: +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Link: +// CHECK-NEXT: Info: +// CHECK-NEXT: AddressAlignment: + +// CHECK: Symbol { +// CHECK: Name: bar +// CHECK-NEXT: Value: 0x12000 +// CHECK-NEXT: Size: 10 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: Object +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .bss +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: obj +// CHECK-NEXT: Value: 0x1200A +// CHECK-NEXT: Size: 10 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: Object +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .bss +// CHECK-NEXT: } + +// 0x12000 - 0 = addr(.got) = 0x12000 +// 0x1200A - 10 = addr(.got) = 0x12000 +// 0x1200A + 5 - 15 = addr(.got) = 0x12000 +// DISASM: Disassembly of section .text: +// DISASM-NEXT: _start: +// DISASM-NEXT: 11000: c7 81 00 00 00 00 01 00 00 00 movl $1, (%ecx) +// DISASM-NEXT: 1100a: c7 81 0a 00 00 00 02 00 00 00 movl $2, 10(%ecx) +// DISASM-NEXT: 11014: c7 81 0f 00 00 00 03 00 00 00 movl $3, 15(%ecx) + +.global _start +_start: + movl $1, bar@GOTOFF(%ecx) + movl $2, obj@GOTOFF(%ecx) + movl $3, obj+5@GOTOFF(%ecx) + .type bar, @object + .comm bar, 10 + .type obj, @object + .comm obj, 10