[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
This commit is contained in:
parent
e4320f5e6a
commit
ce1af1a201
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue