From e32a3598bc942ce9031ffd87b4f25395edaeec3f Mon Sep 17 00:00:00 2001 From: George Rimar Date: Wed, 10 Aug 2016 07:59:34 +0000 Subject: [PATCH] [ELF] - Linkerscript: implement SIZEOF_HEADERS. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SIZEOF_HEADERS - Return the size in bytes of the output file’s headers. It is is a feature used in FreeBsd script, for example. There is a discussion on PR28688 page about it. Differential revision: https://reviews.llvm.org/D23165 llvm-svn: 278204 --- lld/ELF/LinkerScript.cpp | 24 ++++++++++++++++++- lld/ELF/LinkerScript.h | 1 + .../linkerscript/linkerscript-sizeofheaders.s | 18 ++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 lld/test/ELF/linkerscript/linkerscript-sizeofheaders.s diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 8c73e530ba73..2d64af33b03d 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -238,7 +238,7 @@ template void LinkerScript::assignAddresses() { } // Assign addresses as instructed by linker script SECTIONS sub-commands. - Dot = Out::ElfHeader->getSize() + Out::ProgramHeaders->getSize(); + Dot = getSizeOfHeaders(); uintX_t MinVA = std::numeric_limits::max(); uintX_t ThreadBssOffset = 0; @@ -430,6 +430,11 @@ typename ELFT::uint LinkerScript::getOutputSectionSize(StringRef Name) { return 0; } +template +typename ELFT::uint LinkerScript::getSizeOfHeaders() { + return Out::ElfHeader->getSize() + Out::ProgramHeaders->getSize(); +} + // Returns indices of ELF headers containing specific section, identified // by Name. Each index is a zero based number of ELF header listed within // PHDRS {} script block. @@ -915,6 +920,21 @@ static uint64_t getSectionSize(StringRef Name) { } } +static uint64_t getSizeOfHeaders() { + switch (Config->EKind) { + case ELF32LEKind: + return Script::X->getSizeOfHeaders(); + case ELF32BEKind: + return Script::X->getSizeOfHeaders(); + case ELF64LEKind: + return Script::X->getSizeOfHeaders(); + case ELF64BEKind: + return Script::X->getSizeOfHeaders(); + default: + llvm_unreachable("unsupported target"); + } +} + SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { StringRef Op = next(); assert(Op == "=" || Op == "+="); @@ -1063,6 +1083,8 @@ Expr ScriptParser::readPrimary() { expect(")"); return [=](uint64_t Dot) { return getSectionSize(Name); }; } + if (Tok == "SIZEOF_HEADERS") + return [=](uint64_t Dot) { return getSizeOfHeaders(); }; // Parse a symbol name or a number literal. uint64_t V = 0; diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 25034e590ece..324b2702cbd5 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -149,6 +149,7 @@ public: void addScriptedSymbols(); bool hasPhdrsCommands(); uintX_t getOutputSectionSize(StringRef Name); + uintX_t getSizeOfHeaders(); std::vector *> *OutputSections; diff --git a/lld/test/ELF/linkerscript/linkerscript-sizeofheaders.s b/lld/test/ELF/linkerscript/linkerscript-sizeofheaders.s new file mode 100644 index 000000000000..f594b0ea3b70 --- /dev/null +++ b/lld/test/ELF/linkerscript/linkerscript-sizeofheaders.s @@ -0,0 +1,18 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo " SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: _size = SIZEOF_HEADERS; \ +# RUN: .text : {*(.text.*)} \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck %s + +#CHECK: SYMBOL TABLE: +#CHECK-NEXT: 0000000000000000 *UND* 00000000 +#CHECK-NEXT: 0000000000000120 .text 00000000 _start +#CHECK-NEXT: 0000000000000120 *ABS* 00000000 _size + +.global _start +_start: + nop