summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp12
-rw-r--r--lld/ELF/Options.td3
-rw-r--r--lld/ELF/Writer.cpp67
-rw-r--r--lld/test/ELF/oformat-binary.s28
5 files changed, 92 insertions, 19 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 3f9b776f414..b2c107ce485 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 a85f30fe7a3..451b2e49eab 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 7245ddfb6d1..0d4738d3df8 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<"<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">,
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index d927ee3a376..4469944792b 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -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>::run() {
fixSectionAlignments();
assignAddresses();
}
- assignFileOffsets();
+
+ if (!Config->OFormatBinary)
+ assignFileOffsets();
+ else
+ assignFileOffsetsBinary();
+
setPhdrs();
fixAbsoluteSymbols();
}
@@ -276,8 +283,12 @@ template <class ELFT> void Writer<ELFT>::run() {
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>::fixHeaders() {
// 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 Off, OutputSectionBase<ELFT> *Sec) {
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>::openFile() {
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();
diff --git a/lld/test/ELF/oformat-binary.s b/lld/test/ELF/oformat-binary.s
new file mode 100644
index 00000000000..49db7cdb2c1
--- /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
OpenPOWER on IntegriCloud