[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

llvm-svn: 249297
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 7e7ad49..c9a353b 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -170,13 +170,14 @@
 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 @@
     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 @@
   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);
 }