From 86ce267a4ace2ec170653611099786324808d68e Mon Sep 17 00:00:00 2001 From: George Rimar Date: Thu, 25 Aug 2016 09:05:47 +0000 Subject: [PATCH] [ELF] - Implemented --oformat binary option. -oformat output-format `-oformat' option can be used to specify the binary format for the output object file. Patch implements binary format output type. Differential revision: https://reviews.llvm.org/D23769 llvm-svn: 279726 --- lld/ELF/Config.h | 1 + lld/ELF/Driver.cpp | 12 ++++++++ lld/ELF/Options.td | 3 ++ lld/ELF/Writer.cpp | 67 +++++++++++++++++++++++++++++++------------ lld/test/ELF/oformat-binary.s | 28 ++++++++++++++++++ 5 files changed, 92 insertions(+), 19 deletions(-) create mode 100644 lld/test/ELF/oformat-binary.s diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 3f9b776f..b2c107c 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -92,6 +92,7 @@ struct Configuration { bool Mips64EL = false; bool NoGnuUnique; bool NoUndefinedVersion; + bool OFormatBinary; bool Pic; bool Pie; bool PrintGcSections; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index a85f30f..451b2e49ea 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -334,6 +334,16 @@ static UnresolvedPolicy getUnresolvedSymbolOption(opt::InputArgList &Args) { return UnresolvedPolicy::Error; } +static bool isOutputFormatBinary(opt::InputArgList &Args) { + if (auto *Arg = Args.getLastArg(OPT_oformat)) { + StringRef S = Arg->getValue(); + if (S == "binary") + return true; + error("unknown --oformat value: " + S); + } + return false; +} + // Initializes Config members by the command line options. void LinkerDriver::readConfigs(opt::InputArgList &Args) { for (auto *Arg : Args.filtered(OPT_L)) @@ -450,6 +460,8 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { } } + Config->OFormatBinary = isOutputFormatBinary(Args); + for (auto *Arg : Args.filtered(OPT_undefined)) Config->Undefined.push_back(Arg->getValue()); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 7245ddf..0d4738d 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -119,6 +119,9 @@ def no_undefined_version: F<"no-undefined-version">, def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"">, HelpText<"Path to file to write output">; +def oformat: Separate<["--"], "oformat">, MetaVarName<"">, + HelpText<"Specify the binary format for the output object file">; + def pie: F<"pie">, HelpText<"Create a position independent executable">; def print_gc_sections: F<"print-gc-sections">, diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index d927ee3..4469944 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -58,6 +58,7 @@ private: std::vector createPhdrs(); void assignAddresses(); void assignFileOffsets(); + void assignFileOffsetsBinary(); void setPhdrs(); void fixHeaders(); void fixSectionAlignments(); @@ -65,6 +66,7 @@ private: void openFile(); void writeHeader(); void writeSections(); + void writeSectionsBinary(); void writeBuildId(); std::unique_ptr Buffer; @@ -268,7 +270,12 @@ template void Writer::run() { fixSectionAlignments(); assignAddresses(); } - assignFileOffsets(); + + if (!Config->OFormatBinary) + assignFileOffsets(); + else + assignFileOffsetsBinary(); + setPhdrs(); fixAbsoluteSymbols(); } @@ -276,8 +283,12 @@ template void Writer::run() { openFile(); if (HasError) return; - writeHeader(); - writeSections(); + if (!Config->OFormatBinary) { + writeHeader(); + writeSections(); + } else { + writeSectionsBinary(); + } writeBuildId(); if (HasError) return; @@ -1056,8 +1067,10 @@ template void Writer::fixHeaders() { // Assign VAs (addresses at run-time) to output sections. template void Writer::assignAddresses() { - uintX_t VA = Config->ImageBase + Out::ElfHeader->getSize() + - Out::ProgramHeaders->getSize(); + uintX_t VA = Config->ImageBase; + if (!Config->OFormatBinary) + VA += + Out::ElfHeader->getSize() + Out::ProgramHeaders->getSize(); uintX_t ThreadBssOffset = 0; for (OutputSectionBase *Sec : OutputSections) { @@ -1097,25 +1110,34 @@ static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase *Sec) { return alignTo(Off, Target->PageSize, Sec->getVA()); } +template +void setOffset(OutputSectionBase *Sec, uintX_t &Off) { + if (Sec->getType() == SHT_NOBITS) { + Sec->setFileOffset(Off); + return; + } + + Off = getFileAlignment(Off, Sec); + Sec->setFileOffset(Off); + Off += Sec->getSize(); +} + +template void Writer::assignFileOffsetsBinary() { + uintX_t Off = 0; + for (OutputSectionBase *Sec : OutputSections) + if (Sec->getFlags() & SHF_ALLOC) + setOffset(Sec, Off); + FileSize = alignTo(Off, sizeof(uintX_t)); +} + // Assign file offsets to output sections. template void Writer::assignFileOffsets() { uintX_t Off = 0; + setOffset(Out::ElfHeader, Off); + setOffset(Out::ProgramHeaders, Off); - auto Set = [&](OutputSectionBase *Sec) { - if (Sec->getType() == SHT_NOBITS) { - Sec->setFileOffset(Off); - return; - } - - Off = getFileAlignment(Off, Sec); - Sec->setFileOffset(Off); - Off += Sec->getSize(); - }; - - Set(Out::ElfHeader); - Set(Out::ProgramHeaders); for (OutputSectionBase *Sec : OutputSections) - Set(Sec); + setOffset(Sec, Off); SectionHeaderOff = alignTo(Off, sizeof(uintX_t)); FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr); @@ -1262,6 +1284,13 @@ template void Writer::openFile() { Buffer = std::move(*BufferOrErr); } +template void Writer::writeSectionsBinary() { + uint8_t *Buf = Buffer->getBufferStart(); + for (OutputSectionBase *Sec : OutputSections) + if (Sec->getFlags() & SHF_ALLOC) + Sec->writeTo(Buf + Sec->getFileOff()); +} + // Write section contents to a mmap'ed file. template void Writer::writeSections() { uint8_t *Buf = Buffer->getBufferStart(); diff --git a/lld/test/ELF/oformat-binary.s b/lld/test/ELF/oformat-binary.s new file mode 100644 index 0000000..49db7cd --- /dev/null +++ b/lld/test/ELF/oformat-binary.s @@ -0,0 +1,28 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: ld.lld -o %t.out %t --oformat binary +# RUN: hexdump -C %t.out | FileCheck %s +# CHECK: 00000000 90 11 22 00 00 00 00 00 +# CHECK-NOT: 00000010 + +## Check case when linkerscript is used. +# RUN: echo "SECTIONS { . = 0x1000; }" > %t.script +# RUN: ld.lld -o %t2.out --script %t.script %t --oformat binary +# RUN: hexdump -C %t2.out | FileCheck %s + +# RUN: not ld.lld -o %t3.out %t --oformat foo 2>&1 \ +# RUN: | FileCheck %s --check-prefix ERR +# ERR: unknown --oformat value: foo + +.text +.align 4 +.globl _start +_start: + nop + +.section .mysec.1,"ax" +.byte 0x11 + +.section .mysec.2,"ax" +.byte 0x22 -- 2.7.4