diff options
| author | Rafael Auler <rafaelauler@gmail.com> | 2014-10-08 18:54:26 +0000 |
|---|---|---|
| committer | Rafael Auler <rafaelauler@gmail.com> | 2014-10-08 18:54:26 +0000 |
| commit | ce1af1a201c8dc05c05fd1f36a731e0a0fc5b43d (patch) | |
| tree | 521b42d4afcee5557cc967700a372e40df2cdecd /lld | |
| parent | e4320f5e6a1b4cd0f41bd58afb1f96849901333f (diff) | |
| download | bcm5719-llvm-ce1af1a201c8dc05c05fd1f36a731e0a0fc5b43d.tar.gz bcm5719-llvm-ce1af1a201c8dc05c05fd1f36a731e0a0fc5b43d.zip | |
[ELF] Implement --export-dynamic/-E
When creating a dynamic executable and receiving the -E flag, the linker should
export all globally visible symbols in its dynamic symbol table.
This commit also moves the logic that exports symbols in the dynamic symbol
table from OutputELFWriter to the ExecutableWriter class. It is not correct to
leave this at OutputELFWriter because DynamicLibraryWriter, another subclass of
OutputELFWriter, already exports all symbols, meaning we can potentially end up
with duplicated symbols in the dynamic symbol table when creating shared libs.
Reviewers: shankarke
http://reviews.llvm.org/D5585
llvm-svn: 219334
Diffstat (limited to 'lld')
| -rw-r--r-- | lld/include/lld/ReaderWriter/ELFLinkingContext.h | 4 | ||||
| -rw-r--r-- | lld/lib/Driver/GnuLdDriver.cpp | 4 | ||||
| -rw-r--r-- | lld/lib/Driver/GnuLdOptions.td | 6 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ExecutableWriter.h | 20 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/OutputELFWriter.h | 9 | ||||
| -rw-r--r-- | lld/test/elf/export-dynamic.test | 99 |
6 files changed, 133 insertions, 9 deletions
diff --git a/lld/include/lld/ReaderWriter/ELFLinkingContext.h b/lld/include/lld/ReaderWriter/ELFLinkingContext.h index 4c350775675..1ace8b93a07 100644 --- a/lld/include/lld/ReaderWriter/ELFLinkingContext.h +++ b/lld/include/lld/ReaderWriter/ELFLinkingContext.h @@ -152,11 +152,14 @@ public: void setTriple(llvm::Triple trip) { _triple = trip; } void setNoInhibitExec(bool v) { _noInhibitExec = v; } + void setExportDynamic(bool v) { _exportDynamic = v; } void setIsStaticExecutable(bool v) { _isStaticExecutable = v; } void setMergeCommonStrings(bool v) { _mergeCommonStrings = v; } void setUseShlibUndefines(bool use) { _useShlibUndefines = use; } void setOutputELFType(uint32_t type) { _outputELFType = type; } + bool shouldExportDynamic() const { return _exportDynamic; } + void createInternalFiles(std::vector<std::unique_ptr<File>> &) const override; /// \brief Set the dynamic linker path @@ -283,6 +286,7 @@ protected: uint64_t _baseAddress; bool _isStaticExecutable; bool _noInhibitExec; + bool _exportDynamic; bool _mergeCommonStrings; bool _runLayoutPass; bool _useShlibUndefines; diff --git a/lld/lib/Driver/GnuLdDriver.cpp b/lld/lib/Driver/GnuLdDriver.cpp index 683bf318ef5..ded0b70e0cd 100644 --- a/lld/lib/Driver/GnuLdDriver.cpp +++ b/lld/lib/Driver/GnuLdDriver.cpp @@ -372,6 +372,10 @@ bool GnuLdDriver::parse(int argc, const char *argv[], ctx->setAllowRemainingUndefines(true); break; + case OPT_export_dynamic: + ctx->setExportDynamic(true); + break; + case OPT_merge_strings: ctx->setMergeCommonStrings(true); break; diff --git a/lld/lib/Driver/GnuLdOptions.td b/lld/lib/Driver/GnuLdOptions.td index 08adcc4b6ab..590ce9509aa 100644 --- a/lld/lib/Driver/GnuLdOptions.td +++ b/lld/lib/Driver/GnuLdOptions.td @@ -139,6 +139,12 @@ defm rpath : dashEq<"rpath", "rpath", def rpath_link : Separate<["-"], "rpath-link">, HelpText<"Specifies the first set of directories to search">, Group<grp_dynlibexec>; +def export_dynamic : Flag<["--"], "export-dynamic">, + HelpText<"Add all symbols to the dynamic symbol table" + " when creating executables">, + Group<grp_main>; +def alias_export_dynamic: Flag<["-"], "E">, + Alias<export_dynamic>; //===----------------------------------------------------------------------===// /// Dynamic Library Options diff --git a/lld/lib/ReaderWriter/ELF/ExecutableWriter.h b/lld/lib/ReaderWriter/ELF/ExecutableWriter.h index af780b687e0..a65e8f58729 100644 --- a/lld/lib/ReaderWriter/ELF/ExecutableWriter.h +++ b/lld/lib/ReaderWriter/ELF/ExecutableWriter.h @@ -30,6 +30,7 @@ public: _runtimeFile(new CRuntimeFile<ELFT>(context)) {} protected: + virtual void buildDynamicSymbolTable(const File &file); virtual void addDefaultAtoms(); virtual bool createImplicitFiles(std::vector<std::unique_ptr<File> > &); virtual void finalizeDefaultAtomValues(); @@ -41,6 +42,25 @@ protected: //===----------------------------------------------------------------------===// // ExecutableWriter //===----------------------------------------------------------------------===// +template<class ELFT> +void ExecutableWriter<ELFT>::buildDynamicSymbolTable(const File &file) { + for (auto sec : this->_layout.sections()) + if (auto section = dyn_cast<AtomSection<ELFT>>(sec)) + for (const auto &atom : section->atoms()) { + const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom->_atom); + if (!da) + continue; + if (da->dynamicExport() != DefinedAtom::dynamicExportAlways && + !this->_context.isDynamicallyExportedSymbol(da->name()) && + !(this->_context.shouldExportDynamic() && + da->scope() == Atom::Scope::scopeGlobal)) + continue; + this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(), + atom->_virtualAddr, atom); + } + + OutputELFWriter<ELFT>::buildDynamicSymbolTable(file); +} /// \brief Add absolute symbols by default. These are linker added /// absolute symbols diff --git a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h index e7a81cc9180..30b1e573a66 100644 --- a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h +++ b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h @@ -179,15 +179,6 @@ void OutputELFWriter<ELFT>::buildStaticSymbolTable(const File &file) { template <class ELFT> void OutputELFWriter<ELFT>::buildDynamicSymbolTable(const File &file) { ScopedTask task(getDefaultDomain(), "buildDynamicSymbolTable"); - for (auto sec : this->_layout.sections()) - if (auto section = dyn_cast<AtomSection<ELFT>>(sec)) - for (const auto &atom : section->atoms()) { - const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom->_atom); - if (da && (da->dynamicExport() == DefinedAtom::dynamicExportAlways || - _context.isDynamicallyExportedSymbol(da->name()))) - _dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(), - atom->_virtualAddr, atom); - } for (const auto &sla : file.sharedLibrary()) { if (isDynSymEntryRequired(sla)) _dynamicSymbolTable->addSymbol(sla, ELF::SHN_UNDEF); diff --git a/lld/test/elf/export-dynamic.test b/lld/test/elf/export-dynamic.test new file mode 100644 index 00000000000..6456668dd25 --- /dev/null +++ b/lld/test/elf/export-dynamic.test @@ -0,0 +1,99 @@ +# Tests the --export-dynamic (-E) flag. When creating a dynamic executable and +# receiving this flag, the linker should export all globally visible symbols in +# its dynamic symbol table. + +#RUN: yaml2obj -format=elf %s -o=%t.o +#RUN: lld -flavor gnu -target x86_64 -E %t.o -e=main -o %t1 +#RUN: llvm-readobj -dt %t1 | FileCheck -check-prefix CHECKSYMS %s + +#CHECKSYMS: myfunc1@ +#CHECKSYMS: main@ +#CHECKSYMS: myvar1@ + +# The object file below was generated with the following code: +# +# (command line clang -c prog.c -o prog.o) +# +# int myvar1 = 22; +# +# static int mysecretvar = 11; +# +# int myfunc1() { +# return 23; +# } +# +# static int mysecretfunc() { +# return 42; +# } +# +# int main() { +# return mysecretfunc() + mysecretvar; +# } +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + OSABI: ELFOSABI_GNU + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000010 + Content: 554889E5B8170000005DC30F1F440000554889E54883EC10C745FC00000000E81C000000030425000000004883C4105DC36666666666662E0F1F840000000000554889E5B82A0000005DC3 + - Name: .rela.text + Type: SHT_RELA + Link: .symtab + AddressAlign: 0x0000000000000008 + Info: .text + Relocations: + - Offset: 0x0000000000000027 + Symbol: .data + Type: R_X86_64_32S + Addend: 4 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: 160000000B000000 + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: '' +Symbols: + Local: + - Name: mysecretfunc + Type: STT_FUNC + Section: .text + Value: 0x0000000000000040 + Size: 0x000000000000000B + - Name: mysecretvar + Type: STT_OBJECT + Section: .data + Value: 0x0000000000000004 + Size: 0x0000000000000004 + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + Global: + - Name: main + Type: STT_FUNC + Section: .text + Value: 0x0000000000000010 + Size: 0x0000000000000021 + - Name: myfunc1 + Type: STT_FUNC + Section: .text + Size: 0x000000000000000B + - Name: myvar1 + Type: STT_OBJECT + Section: .data + Size: 0x0000000000000004 |

