[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