Index: include/lld/ReaderWriter/ELFLinkingContext.h =================================================================== --- include/lld/ReaderWriter/ELFLinkingContext.h +++ include/lld/ReaderWriter/ELFLinkingContext.h @@ -152,11 +152,14 @@ 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> &) const override; /// \brief Set the dynamic linker path @@ -283,6 +286,7 @@ uint64_t _baseAddress; bool _isStaticExecutable; bool _noInhibitExec; + bool _exportDynamic; bool _mergeCommonStrings; bool _runLayoutPass; bool _useShlibUndefines; Index: lib/Driver/GnuLdDriver.cpp =================================================================== --- lib/Driver/GnuLdDriver.cpp +++ lib/Driver/GnuLdDriver.cpp @@ -372,6 +372,10 @@ ctx->setAllowRemainingUndefines(true); break; + case OPT_export_dynamic: + ctx->setExportDynamic(true); + break; + case OPT_merge_strings: ctx->setMergeCommonStrings(true); break; Index: lib/Driver/GnuLdOptions.td =================================================================== --- lib/Driver/GnuLdOptions.td +++ lib/Driver/GnuLdOptions.td @@ -139,6 +139,12 @@ def rpath_link : Separate<["-"], "rpath-link">, HelpText<"Specifies the first set of directories to search">, Group; +def export_dynamic : Flag<["--"], "export-dynamic">, + HelpText<"Add all symbols to the dynamic symbol table" + " when creating executables">, + Group; +def alias_export_dynamic: Flag<["-"], "E">, + Alias; //===----------------------------------------------------------------------===// /// Dynamic Library Options Index: lib/ReaderWriter/ELF/ExecutableWriter.h =================================================================== --- lib/ReaderWriter/ELF/ExecutableWriter.h +++ lib/ReaderWriter/ELF/ExecutableWriter.h @@ -30,6 +30,7 @@ _runtimeFile(new CRuntimeFile(context)) {} protected: + virtual void buildDynamicSymbolTable(const File &file); virtual void addDefaultAtoms(); virtual bool createImplicitFiles(std::vector > &); virtual void finalizeDefaultAtomValues(); @@ -41,6 +42,25 @@ //===----------------------------------------------------------------------===// // ExecutableWriter //===----------------------------------------------------------------------===// +template +void ExecutableWriter::buildDynamicSymbolTable(const File &file) { + for (auto sec : this->_layout.sections()) + if (auto section = dyn_cast>(sec)) + for (const auto &atom : section->atoms()) { + const DefinedAtom *da = dyn_cast(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::buildDynamicSymbolTable(file); +} /// \brief Add absolute symbols by default. These are linker added /// absolute symbols Index: lib/ReaderWriter/ELF/OutputELFWriter.h =================================================================== --- lib/ReaderWriter/ELF/OutputELFWriter.h +++ lib/ReaderWriter/ELF/OutputELFWriter.h @@ -179,15 +179,6 @@ template void OutputELFWriter::buildDynamicSymbolTable(const File &file) { ScopedTask task(getDefaultDomain(), "buildDynamicSymbolTable"); - for (auto sec : this->_layout.sections()) - if (auto section = dyn_cast>(sec)) - for (const auto &atom : section->atoms()) { - const DefinedAtom *da = dyn_cast(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); Index: test/elf/export-dynamic.test =================================================================== --- /dev/null +++ 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