Skip to content

Commit

Permalink
[ELF] Shared libraries should have entry point
Browse files Browse the repository at this point in the history
Shared libraries should have entry set following the same rules as for
regular binaries. The only difference is that in case the default entry
point (_start or __start) isn't found (unless it was set explicitly), we
shouldn't give a warning as in case of regular binaries.

Differential Revision: https://reviews.llvm.org/D27497

llvm-svn: 288878
  • Loading branch information
petrhosek committed Dec 7, 2016
1 parent 668bebe commit 2f50fef
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 6 deletions.
1 change: 1 addition & 0 deletions lld/ELF/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ struct Configuration {
bool GcSections;
bool GdbIndex;
bool GnuHash = false;
bool HasEntry = false;
bool ICF;
bool Mips64EL = false;
bool MipsN32Abi = false;
Expand Down
4 changes: 2 additions & 2 deletions lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Config->EnableNewDtags = !Args.hasArg(OPT_disable_new_dtags);
Config->ExportDynamic = Args.hasArg(OPT_export_dynamic);
Config->FatalWarnings = Args.hasArg(OPT_fatal_warnings);
Config->HasEntry = Args.hasArg(OPT_entry);
Config->GcSections = getArg(Args, OPT_gc_sections, OPT_no_gc_sections, false);
Config->GdbIndex = Args.hasArg(OPT_gdb_index);
Config->ICF = Args.hasArg(OPT_icf);
Expand Down Expand Up @@ -786,8 +787,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
// It is either "-e <addr>" or "-e <symbol>".
if (!Config->Entry.getAsInteger(0, Config->EntryAddr))
Config->Entry = "";
} else if (!Config->Shared && !Config->Relocatable &&
Config->EMachine != EM_AMDGPU) {
} else if (!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";
Expand Down
10 changes: 6 additions & 4 deletions lld/ELF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1410,14 +1410,16 @@ template <class ELFT> typename ELFT::uint Writer<ELFT>::getEntryAddr() {

// Case 4
if (OutputSectionBase *Sec = findSection(".text")) {
warn("cannot find entry symbol " + Config->Entry + "; defaulting to 0x" +
utohexstr(Sec->Addr));
if (!Config->Shared || Config->HasEntry)
warn("cannot find entry symbol " + Config->Entry + "; defaulting to 0x" +
utohexstr(Sec->Addr));
return Sec->Addr;
}

// Case 5
warn("cannot find entry symbol " + Config->Entry +
"; not setting start address");
if (!Config->Shared || Config->HasEntry)
warn("cannot find entry symbol " + Config->Entry +
"; not setting start address");
return 0;
}

Expand Down
29 changes: 29 additions & 0 deletions lld/test/ELF/gc-sections-keep-shared-start.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t

# RUN: ld.lld -shared --gc-sections -o %t1 %t
# RUN: llvm-readobj --elf-output-style=GNU --file-headers --symbols %t1
# | FileCheck %s
# CHECK: Entry point address: 0x1000
# CHECK: 0000000000001000 0 FUNC LOCAL HIDDEN 4 _start
# CHECK: 0000000000001006 0 FUNC LOCAL HIDDEN 4 internal
# CHECK: 0000000000001005 0 FUNC GLOBAL DEFAULT 4 foobar

.section .text.start,"ax"
.globl _start
.type _start,%function
.hidden _start
_start:
jmp internal

.section .text.foobar,"ax"
.globl foobar
.type foobar,%function
foobar:
ret

.section .text.internal,"ax"
.globl internal
.hidden internal
.type internal,%function
internal:
ret

0 comments on commit 2f50fef

Please sign in to comment.