[lld] r279726 - [ELF] - Implemented --oformat binary option.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 25 02:05:47 PDT 2016


Author: grimar
Date: Thu Aug 25 04:05:47 2016
New Revision: 279726

URL: http://llvm.org/viewvc/llvm-project?rev=279726&view=rev
Log:
[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

Added:
    lld/trunk/test/ELF/oformat-binary.s
Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=279726&r1=279725&r2=279726&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Thu Aug 25 04:05:47 2016
@@ -92,6 +92,7 @@ struct Configuration {
   bool Mips64EL = false;
   bool NoGnuUnique;
   bool NoUndefinedVersion;
+  bool OFormatBinary;
   bool Pic;
   bool Pie;
   bool PrintGcSections;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=279726&r1=279725&r2=279726&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Thu Aug 25 04:05:47 2016
@@ -334,6 +334,16 @@ static UnresolvedPolicy getUnresolvedSym
   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::Inpu
     }
   }
 
+  Config->OFormatBinary = isOutputFormatBinary(Args);
+
   for (auto *Arg : Args.filtered(OPT_undefined))
     Config->Undefined.push_back(Arg->getValue());
 

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=279726&r1=279725&r2=279726&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Thu Aug 25 04:05:47 2016
@@ -119,6 +119,9 @@ def no_undefined_version: F<"no-undefine
 def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">,
   HelpText<"Path to file to write output">;
 
+def oformat: Separate<["--"], "oformat">, MetaVarName<"<format>">,
+  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">,

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=279726&r1=279725&r2=279726&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Aug 25 04:05:47 2016
@@ -58,6 +58,7 @@ private:
   std::vector<Phdr> 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<FileOutputBuffer> Buffer;
@@ -268,7 +270,12 @@ template <class ELFT> void Writer<ELFT>:
       fixSectionAlignments();
       assignAddresses();
     }
-    assignFileOffsets();
+
+    if (!Config->OFormatBinary)
+      assignFileOffsets();
+    else
+      assignFileOffsetsBinary();
+
     setPhdrs();
     fixAbsoluteSymbols();
   }
@@ -276,8 +283,12 @@ template <class ELFT> void Writer<ELFT>:
   openFile();
   if (HasError)
     return;
-  writeHeader();
-  writeSections();
+  if (!Config->OFormatBinary) {
+    writeHeader();
+    writeSections();
+  } else {
+    writeSectionsBinary();
+  }
   writeBuildId();
   if (HasError)
     return;
@@ -1056,8 +1067,10 @@ template <class ELFT> void Writer<ELFT>:
 
 // Assign VAs (addresses at run-time) to output sections.
 template <class ELFT> void Writer<ELFT>::assignAddresses() {
-  uintX_t VA = Config->ImageBase + Out<ELFT>::ElfHeader->getSize() +
-               Out<ELFT>::ProgramHeaders->getSize();
+  uintX_t VA = Config->ImageBase;
+  if (!Config->OFormatBinary)
+    VA +=
+        Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
 
   uintX_t ThreadBssOffset = 0;
   for (OutputSectionBase<ELFT> *Sec : OutputSections) {
@@ -1097,25 +1110,34 @@ static uintX_t getFileAlignment(uintX_t
   return alignTo(Off, Target->PageSize, Sec->getVA());
 }
 
+template <class ELFT, class uintX_t>
+void setOffset(OutputSectionBase<ELFT> *Sec, uintX_t &Off) {
+  if (Sec->getType() == SHT_NOBITS) {
+    Sec->setFileOffset(Off);
+    return;
+  }
+
+  Off = getFileAlignment<ELFT>(Off, Sec);
+  Sec->setFileOffset(Off);
+  Off += Sec->getSize();
+}
+
+template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {
+  uintX_t Off = 0;
+  for (OutputSectionBase<ELFT> *Sec : OutputSections)
+    if (Sec->getFlags() & SHF_ALLOC)
+      setOffset(Sec, Off);
+  FileSize = alignTo(Off, sizeof(uintX_t));
+}
+
 // Assign file offsets to output sections.
 template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
   uintX_t Off = 0;
+  setOffset(Out<ELFT>::ElfHeader, Off);
+  setOffset(Out<ELFT>::ProgramHeaders, Off);
 
-  auto Set = [&](OutputSectionBase<ELFT> *Sec) {
-    if (Sec->getType() == SHT_NOBITS) {
-      Sec->setFileOffset(Off);
-      return;
-    }
-
-    Off = getFileAlignment<ELFT>(Off, Sec);
-    Sec->setFileOffset(Off);
-    Off += Sec->getSize();
-  };
-
-  Set(Out<ELFT>::ElfHeader);
-  Set(Out<ELFT>::ProgramHeaders);
   for (OutputSectionBase<ELFT> *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 <class ELFT> void Writer<ELFT>:
     Buffer = std::move(*BufferOrErr);
 }
 
+template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
+  uint8_t *Buf = Buffer->getBufferStart();
+  for (OutputSectionBase<ELFT> *Sec : OutputSections)
+    if (Sec->getFlags() & SHF_ALLOC)
+      Sec->writeTo(Buf + Sec->getFileOff());
+}
+
 // Write section contents to a mmap'ed file.
 template <class ELFT> void Writer<ELFT>::writeSections() {
   uint8_t *Buf = Buffer->getBufferStart();

Added: lld/trunk/test/ELF/oformat-binary.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/oformat-binary.s?rev=279726&view=auto
==============================================================================
--- lld/trunk/test/ELF/oformat-binary.s (added)
+++ lld/trunk/test/ELF/oformat-binary.s Thu Aug 25 04:05:47 2016
@@ -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




More information about the llvm-commits mailing list