Index: lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h +++ lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h @@ -37,6 +37,14 @@ return std::error_code(); } + bool isDynSymEntryRequired(const SharedLibraryAtom *sla) const override { + return _writeHelper.isDynSymEntryRequired(sla); + } + + bool isNeededTagRequired(const SharedLibraryAtom *sla) const override { + return _writeHelper.isNeededTagRequired(sla); + } + LLD_UNIQUE_BUMP_PTR(DynamicTable) createDynamicTable(); LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable) createDynamicSymbolTable(); Index: lib/ReaderWriter/ELF/Mips/MipsELFWriters.h =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsELFWriters.h +++ lib/ReaderWriter/ELF/Mips/MipsELFWriters.h @@ -70,6 +70,15 @@ return file; } + bool isDynSymEntryRequired(const SharedLibraryAtom *sla) const { + return _targetLayout.isReferencedByDefinedAtom(sla); + } + + bool isNeededTagRequired(const SharedLibraryAtom *sla) const { + return _targetLayout.isReferencedByDefinedAtom(sla) || + _targetLayout.isCopied(sla); + } + private: MipsLinkingContext &_context; MipsTargetLayout &_targetLayout; Index: lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h +++ lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h @@ -39,6 +39,14 @@ return std::error_code(); } + bool isDynSymEntryRequired(const SharedLibraryAtom *sla) const override { + return _writeHelper.isDynSymEntryRequired(sla); + } + + bool isNeededTagRequired(const SharedLibraryAtom *sla) const override { + return _writeHelper.isNeededTagRequired(sla); + } + LLD_UNIQUE_BUMP_PTR(DynamicTable) createDynamicTable(); LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable) createDynamicSymbolTable(); Index: lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h +++ lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h @@ -16,6 +16,8 @@ #include "MipsSectionChunks.h" #include "TargetLayout.h" +#include "llvm/ADT/DenseSet.h" + namespace lld { namespace elf { @@ -60,6 +62,33 @@ } } + ErrorOr addAtom(const Atom *atom) override { + // Maintain: + // 1. Set of shared library atoms referenced by regular defined atoms. + // 2. Set of shared library atoms have corresponding R_MIPS_COPY copies. + if (const auto *da = dyn_cast(atom)) + for (const auto *ref : *da) { + if (const auto *sla = dyn_cast(ref->target())) + _referencedDynAtoms.insert(sla); + + if (ref->kindNamespace() == lld::Reference::KindNamespace::ELF) { + assert(ref->kindArch() == Reference::KindArch::Mips); + if (ref->kindValue() == llvm::ELF::R_MIPS_COPY) + _copiedDynSymNames.insert(atom->name()); + } + } + + return TargetLayout::addAtom(atom); + } + + bool isReferencedByDefinedAtom(const SharedLibraryAtom *sla) const { + return _referencedDynAtoms.count(sla); + } + + bool isCopied(const SharedLibraryAtom *sla) const { + return _copiedDynSymNames.count(sla->name()); + } + /// \brief GP offset relative to .got section. uint64_t getGPOffset() const { return 0x7FF0; } @@ -87,6 +116,8 @@ MipsPLTSection *_pltSection; llvm::Optional _gpAtom; llvm::Optional _gpDispAtom; + llvm::DenseSet _referencedDynAtoms; + llvm::StringSet<> _copiedDynSymNames; }; /// \brief Mips Runtime file. Index: lib/ReaderWriter/ELF/OutputELFWriter.h =================================================================== --- lib/ReaderWriter/ELF/OutputELFWriter.h +++ lib/ReaderWriter/ELF/OutputELFWriter.h @@ -108,6 +108,16 @@ virtual LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable) createDynamicSymbolTable(); + /// \brief Create entry in the dynamic symbols table for this atom. + virtual bool isDynSymEntryRequired(const SharedLibraryAtom *sla) const { + return true; + } + + /// \brief Create DT_NEEDED dynamic tage for the shared library. + virtual bool isNeededTagRequired(const SharedLibraryAtom *sla) const { + return true; + } + llvm::BumpPtrAllocator _alloc; const ELFLinkingContext &_context; @@ -177,8 +187,10 @@ atom->_virtualAddr, atom); } for (const auto &sla : file.sharedLibrary()) { - _dynamicSymbolTable->addSymbol(sla, ELF::SHN_UNDEF); - _soNeeded.insert(sla->loadName()); + if (isDynSymEntryRequired(sla)) + _dynamicSymbolTable->addSymbol(sla, ELF::SHN_UNDEF); + if (isNeededTagRequired(sla)) + _soNeeded.insert(sla->loadName()); } for (const auto &loadName : _soNeeded) { Elf_Dyn dyn; Index: test/elf/Mips/dynsym-table-1.test =================================================================== --- /dev/null +++ test/elf/Mips/dynsym-table-1.test @@ -0,0 +1,121 @@ +# Check that LLD does not populate an executable file dynamic symbol table +# by unnecessary symbols. +# 1. bar.so defines T2 +# 2. foo.so defines T1 and references T2 +# 3. main.o reference T1 +# 4. a.out dynamic table should contain T1 entry only + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-bar.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-foo.o +# RUN: yaml2obj -format=elf -docnum 3 %s > %t-main.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t-bar.so %t-bar.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t-foo.so %t-foo.o %t-bar.so +# RUN: lld -flavor gnu -target mipsel -e T0 -o %t.exe \ +# RUN: %t-main.o %t-foo.so %t-bar.so +# RUN: llvm-readobj -dt -dynamic-table %t.exe | FileCheck %s + +# CHECK: DynamicSymbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: @ (0) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: T1@ ({{.*}}) +# CHECK-NEXT: Value: {{.*}} +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Function (0x2) +# CHECK-NEXT: Other: 8 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: ] + +# CHECK: 0x00000003 PLTGOT 0x401000 +# CHECK-NEXT: 0x00000001 NEEDED SharedLibrary (dynsym-table-1.test.tmp-foo.so) +# CHECK-NEXT: 0x00000000 NULL 0x0 + +# bar.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x04 + Size: 0x08 +Symbols: + Global: + - Name: T2 + Type: STT_FUNC + Section: .text + Size: 0x08 + +# foo.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x04 + Size: 0x08 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x08 + Info: .text + Relocations: + - Offset: 0 + Symbol: T2 + Type: R_MIPS_CALL16 +Symbols: + Global: + - Name: T1 + Type: STT_FUNC + Section: .text + Size: 0x08 + - Name: T2 + +# main.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x04 + Size: 0x08 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x08 + Info: .text + Relocations: + - Offset: 0 + Symbol: T1 + Type: R_MIPS_32 +Symbols: + Global: + - Name: T0 + Type: STT_FUNC + Section: .text + Size: 0x08 + - Name: T1 +... Index: test/elf/Mips/dynsym-table-2.test =================================================================== --- /dev/null +++ test/elf/Mips/dynsym-table-2.test @@ -0,0 +1,101 @@ +# Check that LLD does not populate a shared library dynamic symbol table +# by unnecessary symbols. +# 1. bar.so defines T2 and T3 +# 2. foo.so defines T1 and references T2 +# 4. foo.so dynamic table should contain T1 and T2 entries only + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-bar.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-foo.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t-bar.so %t-bar.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t-foo.so %t-foo.o %t-bar.so +# RUN: llvm-readobj -dt -dynamic-table %t-foo.so | FileCheck %s + +# CHECK: DynamicSymbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: @ (0) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: T1@ ({{.*}}) +# CHECK-NEXT: Value: {{.*}} +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Function (0x2) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .text (0x4) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: T2@ ({{.*}}) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Function (0x2) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: ] + +# CHECK: 0x00000003 PLTGOT 0x1000 +# CHECK-NEXT: 0x00000001 NEEDED SharedLibrary (dynsym-table-2.test.tmp-bar.so) +# CHECK-NEXT: 0x00000000 NULL 0x0 + +# bar.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x04 + Size: 0x08 +Symbols: + Global: + - Name: T2 + Type: STT_FUNC + Section: .text + Size: 0x04 + - Name: T3 + Type: STT_FUNC + Section: .text + Value: 0x04 + Size: 0x04 + +# foo.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x04 + Size: 0x08 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x08 + Info: .text + Relocations: + - Offset: 0 + Symbol: T2 + Type: R_MIPS_CALL16 +Symbols: + Global: + - Name: T1 + Type: STT_FUNC + Section: .text + Size: 0x08 + - Name: T2 +... Index: test/elf/Mips/rel-copy.test =================================================================== --- test/elf/Mips/rel-copy.test +++ test/elf/Mips/rel-copy.test @@ -1,16 +1,19 @@ # Check R_MIPS_COPY relocation emitting # when linking non-shared executable file. # -# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o -# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t-so.o -# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o -# RUN: lld -flavor gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so -# RUN: llvm-readobj -dyn-symbols -relocations %t.exe | FileCheck %s +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so1.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t1.so %t-so1.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-so2.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t2.so %t-so2.o +# RUN: yaml2obj -format=elf -docnum 3 %s > %t-o.o +# RUN: lld -flavor gnu -target mipsel -e T0 -o %t.exe %t-o.o %t1.so %t2.so +# RUN: llvm-readobj -dt -r -dynamic-table %t.exe | FileCheck %s # CHECK: Relocations [ # CHECK-NEXT: Section (5) .rel.dyn { # CHECK-NEXT: 0x402004 R_MIPS_REL32 D2 0x0 -# CHECK-NEXT: 0x402008 R_MIPS_COPY D1 0x0 +# CHECK-NEXT: 0x402010 R_MIPS_COPY D1 0x0 +# CHECK-NEXT: 0x402018 R_MIPS_COPY D3 0x0 # CHECK-NEXT: } # CHECK-NEXT: ] @@ -26,7 +29,7 @@ # CHECK-NEXT: } # CHECK-NEXT: Symbol { # CHECK-NEXT: Name: D1@ (1) -# CHECK-NEXT: Value: 0x402008 +# CHECK-NEXT: Value: 0x402010 # CHECK-NEXT: Size: 4 # CHECK-NEXT: Binding: Global (0x1) # CHECK-NEXT: Type: Object (0x1) @@ -34,16 +37,16 @@ # CHECK-NEXT: Section: .bss (0xA) # CHECK-NEXT: } # CHECK-NEXT: Symbol { -# CHECK-NEXT: Name: D1@ (1) -# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Name: D3@ (4) +# CHECK-NEXT: Value: 0x402018 # CHECK-NEXT: Size: 4 # CHECK-NEXT: Binding: Global (0x1) # CHECK-NEXT: Type: Object (0x1) # CHECK-NEXT: Other: 0 -# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: Section: .bss (0xA) # CHECK-NEXT: } # CHECK-NEXT: Symbol { -# CHECK-NEXT: Name: D2@ (4) +# CHECK-NEXT: Name: D2@ (7) # CHECK-NEXT: Value: 0x0 # CHECK-NEXT: Size: 4 # CHECK-NEXT: Binding: Global (0x1) @@ -53,7 +56,13 @@ # CHECK-NEXT: } # CHECK-NEXT: ] -# so.o +# CHECK: DynamicSection [ ({{.*}} entries) +# CHECK: 0x00000001 NEEDED SharedLibrary (rel-copy.test.tmp1.so) +# CHECK: 0x00000001 NEEDED SharedLibrary (rel-copy.test.tmp2.so) +# CHECK-NEXT: 0x00000000 NULL 0x0 +# CHECK-NEXT: ] + +# so1.o --- FileHeader: Class: ELFCLASS32 @@ -82,6 +91,30 @@ Value: 0x4 Size: 4 +# so2.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_PIC, EF_MIPS_CPIC] + +Sections: +- Name: .data + Type: SHT_PROGBITS + Size: 0x04 + AddressAlign: 16 + Flags: [SHF_WRITE, SHF_ALLOC] + +Symbols: + Global: + - Name: D3 + Section: .data + Type: STT_OBJECT + Value: 0x0 + Size: 4 + # o.o --- FileHeader: @@ -100,7 +133,7 @@ - Name: .data Type: SHT_PROGBITS - Size: 0x08 + Size: 0x0C AddressAlign: 16 Flags: [SHF_WRITE, SHF_ALLOC] @@ -118,6 +151,12 @@ - Offset: 0x04 Symbol: D2 Type: R_MIPS_32 + - Offset: 0x08 + Symbol: D3 + Type: R_MIPS_HI16 + - Offset: 0x08 + Symbol: D3 + Type: R_MIPS_LO16 Symbols: Global: @@ -134,4 +173,5 @@ - Name: D1 Type: STT_OBJECT - Name: D2 + - Name: D3 ... Index: test/elf/Mips/rel-dynamic-01.test =================================================================== --- test/elf/Mips/rel-dynamic-01.test +++ test/elf/Mips/rel-dynamic-01.test @@ -18,24 +18,24 @@ # PLT: Disassembly of section .plt: # PLT-NEXT: .plt: -# PLT-NEXT: 400210: 40 00 1c 3c lui $gp, 64 -# PLT-NEXT: 400214: 00 20 99 8f lw $25, 8192($gp) -# PLT-NEXT: 400218: 00 20 9c 27 addiu $gp, $gp, 8192 -# PLT-NEXT: 40021c: 23 c0 1c 03 subu $24, $24, $gp -# PLT-NEXT: 400220: 21 78 e0 03 move $15, $ra -# PLT-NEXT: 400224: 82 c0 18 00 srl $24, $24, 2 -# PLT-NEXT: 400228: 09 f8 20 03 jalr $25 -# PLT-NEXT: 40022c: fe ff 18 27 addiu $24, $24, -2 +# PLT-NEXT: 4001f0: 40 00 1c 3c lui $gp, 64 +# PLT-NEXT: 4001f4: 00 20 99 8f lw $25, 8192($gp) +# PLT-NEXT: 4001f8: 00 20 9c 27 addiu $gp, $gp, 8192 +# PLT-NEXT: 4001fc: 23 c0 1c 03 subu $24, $24, $gp +# PLT-NEXT: 400200: 21 78 e0 03 move $15, $ra +# PLT-NEXT: 400204: 82 c0 18 00 srl $24, $24, 2 +# PLT-NEXT: 400208: 09 f8 20 03 jalr $25 +# PLT-NEXT: 40020c: fe ff 18 27 addiu $24, $24, -2 # -# PLT-NEXT: 400230: 40 00 0f 3c lui $15, 64 -# PLT-NEXT: 400234: 08 20 f9 8d lw $25, 8200($15) -# PLT-NEXT: 400238: 08 00 20 03 jr $25 -# PLT-NEXT: 40023c: 08 20 f8 25 addiu $24, $15, 8200 +# PLT-NEXT: 400210: 40 00 0f 3c lui $15, 64 +# PLT-NEXT: 400214: 08 20 f9 8d lw $25, 8200($15) +# PLT-NEXT: 400218: 08 00 20 03 jr $25 +# PLT-NEXT: 40021c: 08 20 f8 25 addiu $24, $15, 8200 # -# PLT-NEXT: 400240: 40 00 0f 3c lui $15, 64 -# PLT-NEXT: 400244: 0c 20 f9 8d lw $25, 8204($15) -# PLT-NEXT: 400248: 08 00 20 03 jr $25 -# PLT-NEXT: 40024c: 0c 20 f8 25 addiu $24, $15, 8204 +# PLT-NEXT: 400220: 40 00 0f 3c lui $15, 64 +# PLT-NEXT: 400224: 0c 20 f9 8d lw $25, 8204($15) +# PLT-NEXT: 400228: 08 00 20 03 jr $25 +# PLT-NEXT: 40022c: 0c 20 f8 25 addiu $24, $15, 8204 # PLT-SYM: Relocations [ # PLT-SYM-NEXT: Section (5) .rel.dyn { @@ -79,7 +79,7 @@ # PLT-SYM-NEXT: } # PLT-SYM-NEXT: Symbol { # PLT-SYM-NEXT: Name: T1@ (7) -# PLT-SYM-NEXT: Value: 0x400240 +# PLT-SYM-NEXT: Value: 0x400220 # PLT-SYM-NEXT: Size: 0 # PLT-SYM-NEXT: Binding: Global (0x1) # PLT-SYM-NEXT: Type: Function (0x2) @@ -87,15 +87,6 @@ # PLT-SYM-NEXT: Section: Undefined (0x0) # PLT-SYM-NEXT: } # PLT-SYM-NEXT: Symbol { -# PLT-SYM-NEXT: Name: D1@ (1) -# PLT-SYM-NEXT: Value: 0x0 -# PLT-SYM-NEXT: Size: 4 -# PLT-SYM-NEXT: Binding: Global (0x1) -# PLT-SYM-NEXT: Type: Object (0x1) -# PLT-SYM-NEXT: Other: 0 -# PLT-SYM-NEXT: Section: Undefined (0x0) -# PLT-SYM-NEXT: } -# PLT-SYM-NEXT: Symbol { # PLT-SYM-NEXT: Name: T2@ (10) # PLT-SYM-NEXT: Value: 0x0 # PLT-SYM-NEXT: Size: 0