[lld] r252857 - [ELF2] Add mandatory .dynamic section entries on MIPS.

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 11 20:39:50 PST 2015


Author: ikudrin
Date: Wed Nov 11 22:39:49 2015
New Revision: 252857

URL: http://llvm.org/viewvc/llvm-project?rev=252857&view=rev
Log:
[ELF2] Add mandatory .dynamic section entries on MIPS.

The MIPS target requires specific dynamic section entries to be defined.

 * DT_MIPS_RLD_VERSION and DT_MIPS_FLAGS store predefined values.
 * DT_MIPS_BASE_ADDRESS holds base VA.
 * DT_MIPS_LOCAL_GOTNO holds the number of local GOT entries.
 * DT_MIPS_SYMTABNO holds the number of .dynsym entries.
 * DT_MIPS_GOTSYM holds the index of the .dynsym entry
   which corresponds to the first entry of the global part of GOT.
 * DT_MIPS_RLD_MAP holds the address of the reserved space in the data segment.
 * DT_MIPS_PLTGOT points to the .got.plt section if it exists.
 * DT_PLTGOT holds the address of the GOT section.

See "Dynamic Section" in Chapter 5 in the following document for detailed
description: ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf

Differential revision: http://reviews.llvm.org/D14450

Added:
    lld/trunk/test/elf2/Inputs/mips-dynamic.s
    lld/trunk/test/elf2/mips-dynamic.s
Modified:
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/elf2/mips-got-relocs.s

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=252857&r1=252856&r2=252857&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Wed Nov 11 22:39:49 2015
@@ -94,6 +94,17 @@ GotSection<ELFT>::getEntryAddr(const Sym
   return this->getVA() + B.GotIndex * sizeof(uintX_t);
 }
 
+template <class ELFT>
+const SymbolBody *GotSection<ELFT>::getMipsFirstGlobalEntry() const {
+  return Entries.empty() ? nullptr : Entries.front();
+}
+
+template <class ELFT>
+unsigned GotSection<ELFT>::getMipsLocalEntriesNum() const {
+  // TODO: Update when the suppoort of GOT entries for local symbols is added.
+  return Target->getGotHeaderEntriesNum();
+}
+
 template <class ELFT> void GotSection<ELFT>::finalize() {
   this->Header.sh_size =
       (Target->getGotHeaderEntriesNum() + Entries.size()) * sizeof(uintX_t);
@@ -477,6 +488,12 @@ DynamicSection<ELFT>::DynamicSection(Sym
   Elf_Shdr &Header = this->Header;
   Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
   Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;
+
+  // .dynamic section is not writable on MIPS.
+  // See "Special Section" in Chapter 4 in the following document:
+  // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+  if (Config->EMachine == EM_MIPS)
+    Header.sh_flags = llvm::ELF::SHF_ALLOC;
 }
 
 template <class ELFT> void DynamicSection<ELFT>::finalize() {
@@ -495,7 +512,7 @@ template <class ELFT> void DynamicSectio
   if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
     ++NumEntries; // DT_JMPREL
     ++NumEntries; // DT_PLTRELSZ
-    ++NumEntries; // DT_PLTGOT
+    ++NumEntries; // DT_PLTGOT / DT_MIPS_PLTGOT
     ++NumEntries; // DT_PLTREL
   }
 
@@ -558,6 +575,19 @@ template <class ELFT> void DynamicSectio
     ++NumEntries; // DT_FLAGS
   if (DtFlags1)
     ++NumEntries; // DT_FLAGS_1
+
+  if (Config->EMachine == EM_MIPS) {
+    ++NumEntries; // DT_MIPS_RLD_VERSION
+    ++NumEntries; // DT_MIPS_FLAGS
+    ++NumEntries; // DT_MIPS_BASE_ADDRESS
+    ++NumEntries; // DT_MIPS_SYMTABNO
+    ++NumEntries; // DT_MIPS_LOCAL_GOTNO
+    ++NumEntries; // DT_MIPS_GOTSYM;
+    ++NumEntries; // DT_PLTGOT
+    if (Out<ELFT>::MipsRldMap)
+      ++NumEntries; // DT_MIPS_RLD_MAP
+  }
+
   ++NumEntries; // DT_NULL
 
   Header.sh_size = NumEntries * Header.sh_entsize;
@@ -588,7 +618,12 @@ template <class ELFT> void DynamicSectio
   if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
     WritePtr(DT_JMPREL, Out<ELFT>::RelaPlt->getVA());
     WriteVal(DT_PLTRELSZ, Out<ELFT>::RelaPlt->getSize());
-    WritePtr(DT_PLTGOT, Out<ELFT>::GotPlt->getVA());
+    // On MIPS, the address of the .got.plt section is stored in
+    // the DT_MIPS_PLTGOT entry because the DT_PLTGOT entry points to
+    // the .got section. See "Dynamic Section" in the following document:
+    // https://sourceware.org/ml/binutils/2008-07/txt00000.txt
+    WritePtr((Config->EMachine == EM_MIPS) ? DT_MIPS_PLTGOT : DT_PLTGOT,
+             Out<ELFT>::GotPlt->getVA());
     WriteVal(DT_PLTREL, Out<ELFT>::RelaPlt->isRela() ? DT_RELA : DT_REL);
   }
 
@@ -640,6 +675,25 @@ template <class ELFT> void DynamicSectio
     WriteVal(DT_FLAGS, DtFlags);
   if (DtFlags1)
     WriteVal(DT_FLAGS_1, DtFlags1);
+
+  // See "Dynamic Section" in Chapter 5 in the following document
+  // for detailed description:
+  // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+  if (Config->EMachine == EM_MIPS) {
+    WriteVal(DT_MIPS_RLD_VERSION, 1);
+    WriteVal(DT_MIPS_FLAGS, RHF_NOTPOT);
+    WritePtr(DT_MIPS_BASE_ADDRESS, Target->getVAStart());
+    WriteVal(DT_MIPS_SYMTABNO, Out<ELFT>::DynSymTab->getNumSymbols());
+    WriteVal(DT_MIPS_LOCAL_GOTNO, Out<ELFT>::Got->getMipsLocalEntriesNum());
+    if (const SymbolBody *B = Out<ELFT>::Got->getMipsFirstGlobalEntry())
+      WriteVal(DT_MIPS_GOTSYM, B->getDynamicSymbolTableIndex());
+    else
+      WriteVal(DT_MIPS_GOTSYM, Out<ELFT>::DynSymTab->getNumSymbols());
+    WritePtr(DT_PLTGOT, Out<ELFT>::Got->getVA());
+    if (Out<ELFT>::MipsRldMap)
+      WritePtr(DT_MIPS_RLD_MAP, Out<ELFT>::MipsRldMap->getVA());
+  }
+
   WriteVal(DT_NULL, 0);
 }
 

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=252857&r1=252856&r2=252857&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Wed Nov 11 22:39:49 2015
@@ -122,6 +122,16 @@ public:
   bool empty() const { return Entries.empty(); }
   uintX_t getEntryAddr(const SymbolBody &B) const;
 
+  // Returns the symbol which corresponds to the first entry of the global part
+  // of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic
+  // table properties.
+  // Returns nullptr if the global part is empty.
+  const SymbolBody *getMipsFirstGlobalEntry() const;
+
+  // Returns the number of entries in the local part of GOT including
+  // the number of reserved entries. This method is MIPS-specific.
+  unsigned getMipsLocalEntriesNum() const;
+
 private:
   std::vector<const SymbolBody *> Entries;
 };
@@ -403,6 +413,7 @@ template <class ELFT> struct Out {
   static HashTableSection<ELFT> *HashTab;
   static InterpSection<ELFT> *Interp;
   static OutputSection<ELFT> *Bss;
+  static OutputSection<ELFT> *MipsRldMap;
   static OutputSectionBase<ELFT> *Opd;
   static uint8_t *OpdBuf;
   static PltSection<ELFT> *Plt;
@@ -424,6 +435,7 @@ template <class ELFT> GotSection<ELFT> *
 template <class ELFT> HashTableSection<ELFT> *Out<ELFT>::HashTab;
 template <class ELFT> InterpSection<ELFT> *Out<ELFT>::Interp;
 template <class ELFT> OutputSection<ELFT> *Out<ELFT>::Bss;
+template <class ELFT> OutputSection<ELFT> *Out<ELFT>::MipsRldMap;
 template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::Opd;
 template <class ELFT> uint8_t *Out<ELFT>::OpdBuf;
 template <class ELFT> PltSection<ELFT> *Out<ELFT>::Plt;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=252857&r1=252856&r2=252857&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Nov 11 22:39:49 2015
@@ -632,8 +632,23 @@ template <class ELFT> void Writer<ELFT>:
       OutputSections.push_back(Out<ELFT>::RelaDyn);
     if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs())
       OutputSections.push_back(Out<ELFT>::RelaPlt);
+    // This is a MIPS specific section to hold a space within the data segment
+    // of executable file which is pointed to by the DT_MIPS_RLD_MAP entry.
+    // See "Dynamic section" in Chapter 5 in the following document:
+    // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+    if (Config->EMachine == EM_MIPS && !Config->Shared) {
+      Out<ELFT>::MipsRldMap = new (SecAlloc.Allocate())
+          OutputSection<ELFT>(".rld_map", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
+      Out<ELFT>::MipsRldMap->setSize(ELFT::Is64Bits ? 8 : 4);
+      Out<ELFT>::MipsRldMap->updateAlign(ELFT::Is64Bits ? 8 : 4);
+      OutputSections.push_back(Out<ELFT>::MipsRldMap);
+    }
   }
-  if (!Out<ELFT>::Got->empty())
+
+  // We add the .got section to the result for dynamic MIPS target because
+  // its address and properties are mentioned in the .dynamic section.
+  if (!Out<ELFT>::Got->empty() ||
+      (isOutputDynamic() && Config->EMachine == EM_MIPS))
     OutputSections.push_back(Out<ELFT>::Got);
   if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty())
     OutputSections.push_back(Out<ELFT>::GotPlt);

Added: lld/trunk/test/elf2/Inputs/mips-dynamic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/mips-dynamic.s?rev=252857&view=auto
==============================================================================
--- lld/trunk/test/elf2/Inputs/mips-dynamic.s (added)
+++ lld/trunk/test/elf2/Inputs/mips-dynamic.s Wed Nov 11 22:39:49 2015
@@ -0,0 +1,4 @@
+  .text
+  .globl _foo
+_foo:
+  nop

Added: lld/trunk/test/elf2/mips-dynamic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/mips-dynamic.s?rev=252857&view=auto
==============================================================================
--- lld/trunk/test/elf2/mips-dynamic.s (added)
+++ lld/trunk/test/elf2/mips-dynamic.s Wed Nov 11 22:39:49 2015
@@ -0,0 +1,91 @@
+# Check MIPS specific .dynamic section entries.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %p/Inputs/mips-dynamic.s -o %td.o
+# RUN: ld.lld2 -shared %td.o -o %td.so
+
+# RUN: ld.lld2 %t.o %td.so -o %t.exe
+# RUN: llvm-readobj -sections -dynamic-table %t.exe \
+# RUN:   | FileCheck -check-prefix=EXE %s
+
+# RUN: ld.lld2 -shared %t.o %td.so -o %t.so
+# RUN: llvm-readobj -sections -dyn-symbols -dynamic-table %t.so \
+# RUN:   | FileCheck -check-prefix=DSO %s
+
+# REQUIRES: mips
+
+# EXE:      Sections [
+# EXE:          Name: .dynamic
+# EXE-NEXT:     Type: SHT_DYNAMIC
+# EXE-NEXT:     Flags [
+# EXE-NEXT:       SHF_ALLOC
+# EXE-NEXT:     ]
+# EXE:          Name: .rld_map
+# EXE-NEXT:     Type: SHT_PROGBITS
+# EXE-NEXT:     Flags [
+# EXE-NEXT:       SHF_ALLOC
+# EXE-NEXT:       SHF_WRITE
+# EXE-NEXT:     ]
+# EXE-NEXT:     Address: [[RLDMAPADDR:0x[0-9a-f]+]]
+# EXE-NEXT:     Offset:
+# EXE-NEXT:     Size: 4
+# EXE:          Name: .got
+# EXE-NEXT:     Type: SHT_PROGBITS
+# EXE-NEXT:     Flags [ (0x10000003)
+# EXE-NEXT:       SHF_ALLOC
+# EXE-NEXT:       SHF_WRITE
+# EXE-NEXT:     ]
+# EXE-NEXT:     Address: [[GOTADDR:0x[0-9a-f]+]]
+# EXE-NEXT:     Offset:
+# EXE-NEXT:     Size: 8
+# EXE:      ]
+# EXE:      DynamicSection [
+# EXE-NEXT:   Tag        Type                 Name/Value
+# EXE-DAG:    0x00000003 PLTGOT               [[GOTADDR]]
+# EXE-DAG:    0x70000001 MIPS_RLD_VERSION     1
+# EXE-DAG:    0x70000005 MIPS_FLAGS           NOTPOT
+# EXE-DAG:    0x70000006 MIPS_BASE_ADDRESS
+# EXE-DAG:    0x7000000A MIPS_LOCAL_GOTNO     2
+# EXE-DAG:    0x70000011 MIPS_SYMTABNO        1
+# EXE-DAG:    0x70000013 MIPS_GOTSYM          0x1
+# EXE-DAG:    0x70000016 MIPS_RLD_MAP         [[RLDMAPADDR]]
+# EXE:      ]
+
+# DSO:      Sections [
+# DSO:          Name: .dynamic
+# DSO-NEXT:     Type: SHT_DYNAMIC
+# DSO-NEXT:     Flags [
+# DSO-NEXT:       SHF_ALLOC
+# DSO-NEXT:     ]
+# DSO:          Name: .got
+# DSO-NEXT:     Type: SHT_PROGBITS
+# DSO-NEXT:     Flags [ (0x10000003)
+# DSO-NEXT:       SHF_ALLOC
+# DSO-NEXT:       SHF_WRITE
+# DSO-NEXT:     ]
+# DSO-NEXT:     Address: [[GOTADDR:0x[0-9a-f]+]]
+# DSO-NEXT:     Offset:
+# DSO-NEXT:     Size: 8
+# DSO:      ]
+# DSO:      DynamicSymbols [
+# DSO:          Name: @
+# DSO:          Name: _gp@
+# DSO:          Name: __start@
+# DSO:          Name: _foo@
+# DSO:      ]
+# DSO:      DynamicSection [
+# DSO-NEXT:   Tag        Type                 Name/Value
+# DSO-DAG:    0x00000003 PLTGOT               [[GOTADDR]]
+# DSO-DAG:    0x70000001 MIPS_RLD_VERSION     1
+# DSO-DAG:    0x70000005 MIPS_FLAGS           NOTPOT
+# DSO-DAG:    0x70000006 MIPS_BASE_ADDRESS    0x0
+# DSO-DAG:    0x7000000A MIPS_LOCAL_GOTNO     2
+# DSO-DAG:    0x70000011 MIPS_SYMTABNO        4
+# DSO-DAG:    0x70000013 MIPS_GOTSYM          0x4
+# DSO:      ]
+
+  .text
+  .globl  __start,_foo
+  .type _foo, at function
+__start:
+  nop

Modified: lld/trunk/test/elf2/mips-got-relocs.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/mips-got-relocs.s?rev=252857&r1=252856&r2=252857&view=diff
==============================================================================
--- lld/trunk/test/elf2/mips-got-relocs.s (original)
+++ lld/trunk/test/elf2/mips-got-relocs.s Wed Nov 11 22:39:49 2015
@@ -68,25 +68,25 @@ v1:
 # EXE_DIS_EL:  20000:  18 80 02 3c  lui $2, 32792
 
 # DSO_SYM: Sections:
-# DSO_SYM: .got 0000000c 0000000000020034 DATA
+# DSO_SYM: .got 0000000c 0000000000020004 DATA
 # DSO_SYM: SYMBOL TABLE:
-# DSO_SYM: 00028024         *ABS*		 00000000 _gp
+# DSO_SYM: 00027ff4         *ABS*		 00000000 _gp
 #          ^-- .got + GP offset (0x7ff0)
 # DSO_SYM: 00020000 g       .data		 00000004 v1
 
 # DSO_GOT_BE: Contents of section .got:
-# DSO_GOT_BE:  20034 00000000 80000000 00020000
+# DSO_GOT_BE:  20004 00000000 80000000 00020000
 #                    ^        ^        ^-- v1 (0x20000)
 #                    |        +-- Module pointer (0x80000000)
 #                    +-- Lazy resolver (0x0)
 
 # DSO_GOT_EL: Contents of section .got:
-# DSO_GOT_EL:  20034 00000000 00000080 00000200
+# DSO_GOT_EL:  20004 00000000 00000080 00000200
 #                    ^        ^        ^-- v1 (0x20000)
 #                    |        +-- Module pointer (0x80000000)
 #                    +-- Lazy resolver (0x0)
 
-# v1GotAddr (0x2003c) - _gp (0x28024) = -0x7fe8 => 0x8018 = 32792
+# v1GotAddr (0x2000c) - _gp (0x27ff4) = -0x7fe8 => 0x8018 = 32792
 # DSO_DIS_BE:  10000:  3c 02 80 18  lui $2, 32792
 # DSO_DIS_EL:  10000:  18 80 02 3c  lui $2, 32792
 




More information about the llvm-commits mailing list