[lld] r249297 - [ELF2] Add DT_INIT and DT_FINI dynamic table entries

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 5 03:29:47 PDT 2015


Author: ikudrin
Date: Mon Oct  5 05:29:46 2015
New Revision: 249297

URL: http://llvm.org/viewvc/llvm-project?rev=249297&view=rev
Log:
[ELF2] Add DT_INIT and DT_FINI dynamic table entries

The entries are added if there are "_init" or "_fini" entries in
the symbol table respectively. According to the behavior of ld,
entries are inserted even for undefined symbols.

Symbol names can be overridden by using -init and -fini command
line switches. If used, these switches neither add new symbol table
entries nor require those symbols to be resolved.

Differential Revision: http://reviews.llvm.org/D13385


Added:
    lld/trunk/test/elf2/init-fini.s
Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=249297&r1=249296&r2=249297&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Mon Oct  5 05:29:46 2015
@@ -20,6 +20,8 @@ namespace elf2 {
 struct Configuration {
   llvm::StringRef DynamicLinker;
   llvm::StringRef Entry;
+  llvm::StringRef Fini = "_fini";
+  llvm::StringRef Init = "_init";
   llvm::StringRef OutputFile = "a.out";
   llvm::StringRef SoName;
   llvm::StringRef Sysroot;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=249297&r1=249296&r2=249297&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Mon Oct  5 05:29:46 2015
@@ -117,6 +117,12 @@ void LinkerDriver::link(ArrayRef<const c
   if (auto *Arg = Args.getLastArg(OPT_entry))
     Config->Entry = Arg->getValue();
 
+  if (auto *Arg = Args.getLastArg(OPT_fini))
+    Config->Fini = Arg->getValue();
+
+  if (auto *Arg = Args.getLastArg(OPT_init))
+    Config->Init = Arg->getValue();
+
   if (auto *Arg = Args.getLastArg(OPT_soname))
     Config->SoName = Arg->getValue();
 

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=249297&r1=249296&r2=249297&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Mon Oct  5 05:29:46 2015
@@ -32,6 +32,12 @@ def entry : Separate<["--", "-"], "entry
 def export_dynamic : Flag<["--", "-"], "export-dynamic">,
   HelpText<"Put symbols in the dynamic symbol table">;
 
+def fini : Separate<["-"], "fini">, MetaVarName<"<symbol>">,
+  HelpText<"Specify a finalizer function">;
+
+def init : Separate<["-"], "init">, MetaVarName<"<symdol>">,
+  HelpText<"Specify an initializer function">;
+
 def l : Joined<["-"], "l">, MetaVarName<"<libName>">,
   HelpText<"Root name of library to use">;
 
@@ -77,6 +83,8 @@ def alias_L__library_path : Joined<["--"
 def alias_discard_all_x: Flag<["-"], "x">, Alias<discard_all>;
 def alias_discard_locals_X: Flag<["-"], "X">, Alias<discard_locals>;
 def alias_entry_e : Separate<["-"], "e">, Alias<entry>;
+def alias_fini_fini : Joined<["-"], "fini=">, Alias<fini>;
+def alias_init_init : Joined<["-"], "init=">, Alias<init>;
 def alias_l__library : Joined<["--"], "library=">, Alias<l>;
 def alias_rpath_rpath : Joined<["-"], "rpath=">, Alias<rpath>;
 def alias_soname_h : Separate<["-"], "h">, Alias<soname>;

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=249297&r1=249296&r2=249297&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Mon Oct  5 05:29:46 2015
@@ -170,13 +170,14 @@ template <class ELFT> void HashTableSect
 template <class ELFT>
 DynamicSection<ELFT>::DynamicSection(SymbolTable &SymTab,
                                      HashTableSection<ELFT> &HashSec,
-                                     RelocationSection<ELFT> &RelaDynSec)
+                                     RelocationSection<ELFT> &RelaDynSec,
+                                     const OutputSection<ELFT> &BssSec)
     : OutputSectionBase<ELFT::Is64Bits>(".dynamic", llvm::ELF::SHT_DYNAMIC,
                                         llvm::ELF::SHF_ALLOC |
                                             llvm::ELF::SHF_WRITE),
       HashSec(HashSec), DynSymSec(HashSec.getDynSymSec()),
       DynStrSec(DynSymSec.getStrTabSec()), RelaDynSec(RelaDynSec),
-      SymTab(SymTab) {
+      BssSec(BssSec), SymTab(SymTab) {
   typename Base::HeaderT &Header = this->Header;
   Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
   Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;
@@ -224,6 +225,16 @@ template <class ELFT> void DynamicSectio
     DynStrSec.add(File->getSoName());
   NumEntries += SharedFiles.size();
 
+  if (Symbol *S = SymTab.getSymbols().lookup(Config->Init))
+    InitSym = dyn_cast<ELFSymbolBody<ELFT>>(S->Body);
+  if (Symbol *S = SymTab.getSymbols().lookup(Config->Fini))
+    FiniSym = dyn_cast<ELFSymbolBody<ELFT>>(S->Body);
+
+  if (InitSym)
+    ++NumEntries; // DT_INIT
+  if (FiniSym)
+    ++NumEntries; // DT_FINI
+
   ++NumEntries; // DT_NULL
 
   Header.sh_size = NumEntries * Header.sh_entsize;
@@ -280,6 +291,11 @@ template <class ELFT> void DynamicSectio
   for (const std::unique_ptr<SharedFileBase> &File : SharedFiles)
     WriteVal(DT_NEEDED, DynStrSec.getFileOff(File->getSoName()));
 
+  if (InitSym)
+    WritePtr(DT_INIT, getSymVA(*InitSym, BssSec));
+  if (FiniSym)
+    WritePtr(DT_FINI, getSymVA(*FiniSym, BssSec));
+
   WriteVal(DT_NULL, 0);
 }
 

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=249297&r1=249296&r2=249297&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Mon Oct  5 05:29:46 2015
@@ -320,7 +320,8 @@ class DynamicSection final : public Outp
 
 public:
   DynamicSection(SymbolTable &SymTab, HashTableSection<ELFT> &HashSec,
-                 RelocationSection<ELFT> &RelaDynSec);
+                 RelocationSection<ELFT> &RelaDynSec,
+                 const OutputSection<ELFT> &BssSec);
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
 
@@ -333,7 +334,10 @@ private:
   SymbolTableSection<ELFT> &DynSymSec;
   StringTableSection<ELFT::Is64Bits> &DynStrSec;
   RelocationSection<ELFT> &RelaDynSec;
+  const OutputSection<ELFT> &BssSec;
   SymbolTable &SymTab;
+  const ELFSymbolBody<ELFT> *InitSym = nullptr;
+  const ELFSymbolBody<ELFT> *FiniSym = nullptr;
 };
 }
 }

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=249297&r1=249296&r2=249297&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Oct  5 05:29:46 2015
@@ -85,7 +85,7 @@ public:
   Writer(SymbolTable *T)
       : SymTabSec(*T, StrTabSec, BssSec), DynSymSec(*T, DynStrSec, BssSec),
         RelaDynSec(DynSymSec, GotSec, T->shouldUseRela()), PltSec(GotSec),
-        HashSec(DynSymSec), DynamicSec(*T, HashSec, RelaDynSec),
+        HashSec(DynSymSec), DynamicSec(*T, HashSec, RelaDynSec, BssSec),
         BssSec(PltSec, GotSec, BssSec, ".bss", SHT_NOBITS,
                SHF_ALLOC | SHF_WRITE) {}
   void run();

Added: lld/trunk/test/elf2/init-fini.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/init-fini.s?rev=249297&view=auto
==============================================================================
--- lld/trunk/test/elf2/init-fini.s (added)
+++ lld/trunk/test/elf2/init-fini.s Mon Oct  5 05:29:46 2015
@@ -0,0 +1,43 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+// Should use "_init" and "_fini" by default when fills dynamic table
+// RUN: lld -flavor gnu2 -shared %t -o %t2
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=BYDEF %s
+// BYDEF: INIT 0x11010
+// BYDEF: FINI 0x11020
+
+// -init and -fini override symbols to use
+// RUN: lld -flavor gnu2 -shared %t -o %t2 -init _foo -fini _bar
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=OVR %s
+// OVR: INIT 0x11030
+// OVR: FINI 0x11040
+
+// Check aliases as well
+// RUN: lld -flavor gnu2 -shared %t -o %t2 -init=_foo -fini=_bar
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=OVR %s
+
+// Should add a dynamic table entry even if a given symbol stay undefined
+// RUN: lld -flavor gnu2 -shared %t -o %t2 -init=_undef -fini=_undef
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=UNDEF %s
+// UNDEF: INIT 0x0
+// UNDEF: FINI 0x0
+
+// Should not add new entries to the symbol table
+// and should not require given symbols to be resolved
+// RUN: lld -flavor gnu2 -shared %t -o %t2 -init=_unknown -fini=_unknown
+// RUN: llvm-readobj -symbols -dynamic-table %t2 | FileCheck --check-prefix=NOENTRY %s
+// NOENTRY: Symbols [
+// NOENTRY-NOT: Name: _unknown
+// NOENTRY: ]
+// NOENTRY: DynamicSection [
+// NOENTRY-NOT: INIT
+// NOENTRY-NOT: FINI
+// NOENTRY: ]
+
+.global _start,_init,_fini,_foo,_bar,_undef;
+_start:
+_init = 0x11010
+_fini = 0x11020
+_foo  = 0x11030
+_bar  = 0x11040




More information about the llvm-commits mailing list