Allow linker-script-defined entry symbols.

Previously, we were checking the existence of an entry symbol
too early. It was done before the linker script processor creates
symbols defined in scripts. Fixes bug 30743.

llvm-svn: 284676
This commit is contained in:
Rui Ueyama 2016-10-20 00:07:36 +00:00
parent 40379746c8
commit 8da7aa0894
5 changed files with 22 additions and 14 deletions

View File

@ -69,7 +69,6 @@ struct VersionDefinition {
// and such fields have the same name as the corresponding options.
// Most fields are initialized by the driver.
struct Configuration {
Symbol *EntrySym = nullptr;
InputFile *FirstElf = nullptr;
llvm::StringMap<uint64_t> SectionStartMap;
llvm::StringRef DynamicLinker;

View File

@ -695,22 +695,21 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
// Add the start symbol.
// It initializes either Config->Entry or Config->EntryAddr.
// Note that AMDGPU binaries have no entries.
bool HasEntryAddr = false;
if (!Config->Entry.empty()) {
// It is either "-e <addr>" or "-e <symbol>".
HasEntryAddr = !Config->Entry.getAsInteger(0, Config->EntryAddr);
if (!Config->Entry.getAsInteger(0, Config->EntryAddr))
Config->Entry = "";
} else if (!Config->Shared && !Config->Relocatable &&
Config->EMachine != EM_AMDGPU) {
// -e was not specified. Use the default start symbol name
// if it is resolvable.
Config->Entry = (Config->EMachine == EM_MIPS) ? "__start" : "_start";
}
if (!HasEntryAddr && !Config->Entry.empty()) {
if (Symtab.find(Config->Entry))
Config->EntrySym = Symtab.addUndefined(Config->Entry);
else
warn("entry symbol " + Config->Entry + " not found, assuming 0");
}
// If an object file defining the entry symbol is in an archive file,
// extract the file now.
if (Symtab.find(Config->Entry))
Symtab.addUndefined(Config->Entry);
if (HasError)
return; // There were duplicate symbols or incompatible files

View File

@ -225,8 +225,7 @@ template <class ELFT> void elf::markLive() {
};
// Add GC root symbols.
if (Config->EntrySym)
MarkSymbol(Config->EntrySym->body());
MarkSymbol(Symtab<ELFT>::X->find(Config->Entry));
MarkSymbol(Symtab<ELFT>::X->find(Config->Init));
MarkSymbol(Symtab<ELFT>::X->find(Config->Fini));
for (StringRef S : Config->Undefined)

View File

@ -1278,9 +1278,12 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() {
}
template <class ELFT> static typename ELFT::uint getEntryAddr() {
if (Symbol *S = Config->EntrySym)
return S->body()->getVA<ELFT>();
return Config->EntryAddr;
if (Config->Entry.empty())
return Config->EntryAddr;
if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Entry))
return B->getVA<ELFT>();
warn("entry symbol " + Config->Entry + " not found, assuming 0");
return 0;
}
template <class ELFT> static uint8_t getELFEncoding() {

View File

@ -75,6 +75,14 @@
# ENTRY-OVERLOAD: Name: _start
# ENTRY-OVERLOAD-NEXT: Value: [[ENTRY]]
# The entry symbol can be a linker-script-defined symbol.
# RUN: echo "ENTRY(foo); foo = 1;" > %t.script
# RUN: ld.lld -o %t2 %t.script %t
# RUN: llvm-readobj -file-headers -symbols %t2 | \
# RUN: FileCheck -check-prefix=ENTRY-SCRIPT %s
# ENTRY-SCRIPT: Entry: 0x1
# RUN: echo "OUTPUT_FORMAT(elf64-x86-64) /*/*/ GROUP(\"%t\" )" > %t.script
# RUN: ld.lld -o %t2 %t.script
# RUN: llvm-readobj %t2 > /dev/null