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))
}
}
+ Config->OFormatBinary = isOutputFormatBinary(Args);
+
for (auto *Arg : Args.filtered(OPT_undefined))
Config->Undefined.push_back(Arg->getValue());
std::vector<Phdr> createPhdrs();
void assignAddresses();
void assignFileOffsets();
+ void assignFileOffsetsBinary();
void setPhdrs();
void fixHeaders();
void fixSectionAlignments();
void openFile();
void writeHeader();
void writeSections();
+ void writeSectionsBinary();
void writeBuildId();
std::unique_ptr<FileOutputBuffer> Buffer;
fixSectionAlignments();
assignAddresses();
}
- assignFileOffsets();
+
+ if (!Config->OFormatBinary)
+ assignFileOffsets();
+ else
+ assignFileOffsetsBinary();
+
setPhdrs();
fixAbsoluteSymbols();
}
openFile();
if (HasError)
return;
- writeHeader();
- writeSections();
+ if (!Config->OFormatBinary) {
+ writeHeader();
+ writeSections();
+ } else {
+ writeSectionsBinary();
+ }
writeBuildId();
if (HasError)
return;
// 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) {
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);
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();
--- /dev/null
+# 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