From 4f7a5c3bb429c945ff4e456478b5532f828d1143 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Mon, 22 Aug 2016 18:44:04 +0000 Subject: [PATCH] [ELF] Define __ehdr_start symbol This symbol can be used by the program to examine its own headers. Differential Revision: https://reviews.llvm.org/D23750 llvm-svn: 279452 --- lld/ELF/Symbols.h | 4 ++++ lld/ELF/Writer.cpp | 6 ++++++ lld/test/ELF/ehdr_start.s | 11 +++++++++++ lld/test/ELF/linkerscript/linkerscript-ehdr_start.s | 11 +++++++++++ 4 files changed, 32 insertions(+) create mode 100644 lld/test/ELF/ehdr_start.s create mode 100644 lld/test/ELF/linkerscript/linkerscript-ehdr_start.s diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index a1170f4febc5..dfdcbe4b466b 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -366,6 +366,9 @@ public: // Some linker-generated symbols need to be created as // DefinedRegular symbols. template struct ElfSym { + // The content for __ehdr_start symbol. + static DefinedRegular *EhdrStart; + // The content for _etext and etext symbols. static DefinedRegular *Etext; static DefinedRegular *Etext2; @@ -382,6 +385,7 @@ template struct ElfSym { static SymbolBody *MipsGpDisp; }; +template DefinedRegular *ElfSym::EhdrStart; template DefinedRegular *ElfSym::Etext; template DefinedRegular *ElfSym::Etext2; template DefinedRegular *ElfSym::Edata; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 3b20bbe49b16..a8c6f8241985 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -598,6 +598,8 @@ template void Writer::addReservedSymbols() { if (ScriptConfig->HasContents) return; + ElfSym::EhdrStart = Symtab::X->addIgnored("__ehdr_start"); + auto Define = [this](StringRef S, DefinedRegular *&Sym1, DefinedRegular *&Sym2) { Sym1 = Symtab::X->addIgnored(S, STV_DEFAULT); @@ -1180,6 +1182,10 @@ static uint16_t getELFType() { // to each section. This function fixes some predefined absolute // symbol values that depend on section address and size. template void Writer::fixAbsoluteSymbols() { + // __ehdr_start is the location of program headers. + if (ElfSym::EhdrStart) + ElfSym::EhdrStart->Value = Out::ProgramHeaders->getVA(); + auto Set = [](DefinedRegular *S1, DefinedRegular *S2, uintX_t V) { if (S1) S1->Value = V; diff --git a/lld/test/ELF/ehdr_start.s b/lld/test/ELF/ehdr_start.s new file mode 100644 index 000000000000..e605df59af10 --- /dev/null +++ b/lld/test/ELF/ehdr_start.s @@ -0,0 +1,11 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-objdump -t %t | FileCheck %s +# CHECK: 0000000000010040 *ABS* 00000000 .hidden __ehdr_start + +.text +.global _start, __ehdr_start +_start: + .quad __ehdr_start diff --git a/lld/test/ELF/linkerscript/linkerscript-ehdr_start.s b/lld/test/ELF/linkerscript/linkerscript-ehdr_start.s new file mode 100644 index 000000000000..ef3dc597cb88 --- /dev/null +++ b/lld/test/ELF/linkerscript/linkerscript-ehdr_start.s @@ -0,0 +1,11 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { }" > %t.script +# RUN: not ld.lld %t.o -script %t.script -o %t 2>&1 | FileCheck %s +# CHECK: undefined symbol: __ehdr_start + +.text +.global _start, __ehdr_start +_start: + .quad __ehdr_start