added support -output-binary; some work might be best taken out though
diff --git a/test/tools/llvm-objcopy/basic-binary-copy.s b/test/tools/llvm-objcopy/basic-binary-copy.s
new file mode 100644
index 0000000..380678a
--- /dev/null
+++ b/test/tools/llvm-objcopy/basic-binary-copy.s
@@ -0,0 +1,16 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objcopy -output-binary %t %t2
+# RUN: od -t x2 -v %t2 | FileCheck %s
+# RUN: wc -c < %t2 | FileCheck %s --check-prefix=SIZE
+
+ .globl main
+ .text
+main:
+ ret
+ ret
+ ret
+ ret
+
+# CHECK: 0000000 c3c3 c3c3
+# SIZE: 4
diff --git a/test/tools/llvm-objcopy/binary-align-copy.s b/test/tools/llvm-objcopy/binary-align-copy.s
new file mode 100644
index 0000000..faf3ee2
--- /dev/null
+++ b/test/tools/llvm-objcopy/binary-align-copy.s
@@ -0,0 +1,22 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objcopy -output-binary %t %t2
+# RUN: od -t x2 %t2 | FileCheck %s
+# RUN: wc -c < %t2 | FileCheck %s --check-prefix=SIZE
+
+ .globl main
+ .text
+main:
+ ret
+ ret
+ ret
+ ret
+
+ .data
+ .byte 50
+
+# CHECK: 0000000 c3c3 c3c3 0000 0000 0000 0000 0000 0000
+# CHECK-NEXT: 0000020 0000 0000 0000 0000 0000 0000 0000 0000
+# CHECK-NEXT: *
+# CHECK-NEXT: 0010000 0032
+# SIZE: 4097
diff --git a/test/tools/llvm-objcopy/interstitial-binary-copy.s b/test/tools/llvm-objcopy/interstitial-binary-copy.s
new file mode 100644
index 0000000..92f09b7
--- /dev/null
+++ b/test/tools/llvm-objcopy/interstitial-binary-copy.s
@@ -0,0 +1,25 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: printf %4092s | dd of=%t bs=1 seek=4100 conv=notrunc
+# RUN: printf "\x00\x10" | dd of=%t bs=1 seek=208 conv=notrunc
+# RUN: printf "\x00\x10" | dd of=%t bs=1 seek=216 conv=notrunc
+# RUN: llvm-objcopy -output-binary %t %t2
+# RUN: od -t x2 %t2 | FileCheck %s
+# RUN: wc -c < %t2 | FileCheck %s --check-prefix=SIZE
+
+ .globl main
+ .text
+main:
+ ret
+ ret
+ ret
+ ret
+
+ .data
+ .byte 50
+
+# CHECK: 0000000 c3c3 c3c3 2020 2020 2020 2020 2020 2020
+# CHECK-NEXT: 0000020 2020 2020 2020 2020 2020 2020 2020 2020
+# CHECK-NEXT: *
+# CHECK-NEXT: 0010000 0032
+# SIZE: 4097
diff --git a/tools/llvm-objcopy/Object.cpp b/tools/llvm-objcopy/Object.cpp
index 6f92aa3..10cd25c 100644
--- a/tools/llvm-objcopy/Object.cpp
+++ b/tools/llvm-objcopy/Object.cpp
@@ -13,9 +13,13 @@
using namespace object;
using namespace ELF;
-template <class ELFT> void Segment::writeHeader(FileOutputBuffer &Out) const {
- uint8_t *Buf = Out.getBufferStart();
- Buf += sizeof(typename ELFT::Ehdr) + Index * sizeof(typename ELFT::Phdr);
+uint64_t align(uint64_t Value, uint64_t Multiple) {
+ if (!Multiple || Value % Multiple == 0)
+ return Value;
+ return Value + Multiple - Value % Multiple;
+}
+
+template <class ELFT> void Segment::writeHeader(uint8_t *Buf) const {
typename ELFT::Phdr &Phdr = *reinterpret_cast<typename ELFT::Phdr *>(Buf);
Phdr.p_type = Type;
Phdr.p_flags = Flags;
@@ -28,24 +32,60 @@
}
void Segment::finalize() {
- auto MinElem =
- std::min_element(std::begin(Sections), std::end(Sections),
- [](const SectionBase *a, const SectionBase *b) -> bool {
- return a->Offset < b->Offset;
- });
- Offset = (**MinElem).Offset;
- FileSize = 0;
- for (auto Section : Sections)
- if (Section->Type != SHT_NOBITS)
- FileSize += Section->Size;
+ auto MinElem = firstSection();
+ if (!MinElem)
+ return;
+ if (Type == PT_LOAD) {
+ auto PrevSection = MinElem;
+ for (auto Sec : Sections) {
+ if (Sec->Addr > PrevSection->Addr + PrevSection->Size) {
+ // Then we have a gap which we can expect file layout to respect. We
+ // need to respect the contents of this gap as well as the user may have
+ // put something meanigful in them like trap instructions in the case
+ // that this segment is executable.
+ ArrayRef<uint8_t> InterstitialData{Contents.data() + PrevSection->Addr -
+ VAddr + PrevSection->Size,
+ Contents.data() + Sec->Addr - VAddr};
+ auto InterstitialSection = new Section(InterstitialData);
+ InterstitialSection->Addr = PrevSection->Addr + PrevSection->Size;
+ InterstitialSections.emplace_back(InterstitialSection);
+ }
+ PrevSection = Sec;
+ }
+ // Lastly there might be an interstitial gap between the last section and
+ // the end of the segment.
+ if (VAddr + MemSize > PrevSection->Addr + PrevSection->Size) {
+ ArrayRef<uint8_t> InterstitialData{Contents.data() + PrevSection->Addr -
+ VAddr + PrevSection->Size,
+ Contents.data() + MemSize};
+ auto InterstitialSection = new Section(InterstitialData);
+ InterstitialSection->Addr = PrevSection->Addr + PrevSection->Size;
+ InterstitialSections.emplace_back(InterstitialSection);
+ }
+ for (auto &InterstitialSection : InterstitialSections)
+ Sections.insert(InterstitialSection.get());
+ }
+
+ // In practice you could have a section that contained no sections. In this
+ // case the file offset is meaingless. Other aspects of it can still hold
+ // meaning however so we want to preserve those things still. So if there is
+ // no MinElem we just leave Offset as it was in the file.
+ if (MinElem)
+ Offset = MinElem->Offset;
+}
+
+void Segment::writeMemSegment(uint8_t *Buf) const {
+ // Because we have filled in all gaps with interstitial sections we can be
+ // sure that we will cover the entire size of MemSize
+ for (auto Section : Sections) {
+ Section->writeSection(Buf);
+ Buf += Section->Size;
+ }
}
void SectionBase::finalize() {}
-template <class ELFT>
-void SectionBase::writeHeader(FileOutputBuffer &Out) const {
- uint8_t *Buf = Out.getBufferStart();
- Buf += HeaderOffset;
+template <class ELFT> void SectionBase::writeHeader(uint8_t *Buf) const {
typename ELFT::Shdr &Shdr = *reinterpret_cast<typename ELFT::Shdr *>(Buf);
Shdr.sh_name = NameIndex;
Shdr.sh_type = Type;
@@ -59,8 +99,7 @@
Shdr.sh_entsize = EntrySize;
}
-void Section::writeSection(FileOutputBuffer &Out) const {
- uint8_t *Buf = Out.getBufferStart() + Offset;
+void Section::writeSection(uint8_t *Buf) const {
std::copy(std::begin(Contents), std::end(Contents), Buf);
}
@@ -93,8 +132,7 @@
}
}
-void StringTableSection::writeSection(FileOutputBuffer &Out) const {
- uint8_t *Buf = Out.getBufferStart() + Offset;
+void StringTableSection::writeSection(uint8_t *Buf) const {
for (const auto &Name : Strings) {
Buf = std::copy(std::begin(Name.getKey()), std::end(Name.getKey()), Buf);
// We need to set the null character and then increment the buffer past it
@@ -156,9 +194,7 @@
}
template <class ELFT>
-void SymbolTableSection<ELFT>::writeSection(llvm::FileOutputBuffer &Out) const {
- uint8_t *Buf = Out.getBufferStart();
- Buf += Offset;
+void SymbolTableSection<ELFT>::writeSection(uint8_t *Buf) const {
typename ELFT::Sym *Sym = reinterpret_cast<typename ELFT::Sym *>(Buf);
for(auto &Symbol : FinalSymbols) {
@@ -176,10 +212,11 @@
}
template <class ELFT>
-void Object<ELFT>::readProgramHeaders(const ELFFile<ELFT> &ElfFile) {
+void ObjectCopyBase<ELFT>::readProgramHeaders(const ELFFile<ELFT> &ElfFile) {
uint32_t Index = 0;
for (const auto &Phdr : unwrapOrError(ElfFile.program_headers())) {
- Segments.emplace_back();
+ ArrayRef<uint8_t> Data{ElfFile.base() + Phdr.p_offset, Phdr.p_filesz};
+ Segments.emplace_back(Data);
Segment &Seg = Segments.back();
Seg.Type = Phdr.p_type;
Seg.Flags = Phdr.p_flags;
@@ -191,17 +228,18 @@
Seg.Index = Index++;
for (auto &Section : Sections) {
if (Seg.Offset <= Section->Offset &&
- Seg.Offset + Seg.FileSize >= Section->Offset + Section->Size) {
- Seg.addSection(&*Section);
+ Seg.Offset + Seg.FileSize >= Section->Offset + Section->Size &&
+ (Section->Flags & SHF_ALLOC)) {
Section->ParrentSegment = &Seg;
+ Seg.addSection(Section.get());
}
}
}
}
template <class ELFT>
-void Object<ELFT>::readSymbolTable(const ELFFile<ELFT> &ElfFile,
- const Elf_Shdr &SymTabShdr) {
+void ObjectCopyBase<ELFT>::readSymbolTable(const ELFFile<ELFT> &ElfFile,
+ const Elf_Shdr &SymTabShdr) {
StringTableSection *StrTab =
dyn_cast<StringTableSection>(Sections[SymTabShdr.sh_link].get());
@@ -238,7 +276,7 @@
}
template <class ELFT>
-void Object<ELFT>::readSectionHeaders(const ELFFile<ELFT> &ElfFile) {
+void ObjectCopyBase<ELFT>::readSectionHeaders(const ELFFile<ELFT> &ElfFile) {
uint32_t Index = 0;
const Elf_Shdr *SymTabShdr = nullptr;
for (const auto &Shdr : unwrapOrError(ElfFile.sections())) {
@@ -277,13 +315,8 @@
readSymbolTable(ElfFile, *SymTabShdr);
}
-template <class ELFT> size_t Object<ELFT>::totalSize() const {
- // We already have the section header offset so we can calculate the total
- // size by just adding up the size of each section header;
- return SHOffset + Sections.size() * sizeof(Elf_Shdr);
-}
-
-template <class ELFT> Object<ELFT>::Object(const ELFObjectFile<ELFT> &Obj) {
+template <class ELFT>
+ObjectCopyBase<ELFT>::ObjectCopyBase(const ELFObjectFile<ELFT> &Obj) {
const auto &ElfFile = *Obj.getELFFile();
const auto &Ehdr = *ElfFile.getHeader();
@@ -304,31 +337,33 @@
readProgramHeaders(ElfFile);
}
-template <class ELFT> void Object<ELFT>::sortSections() {
+template <class ELFT> size_t ObjectCopyELF<ELFT>::totalSize() const {
+ // We already have the section header offset so we can calculate the total
+ // size by just adding up the size of each section header;
+ return this->SHOffset + this->Sections.size() * sizeof(Elf_Shdr);
+}
+
+template <class ELFT> void ObjectCopyELF<ELFT>::sortSections() {
std::sort(
- std::begin(Sections), std::end(Sections),
+ std::begin(this->Sections), std::end(this->Sections),
[](const SecPtr &A, const SecPtr &B) { return A->Index < B->Index; });
}
-uint64_t align(uint64_t Value, uint64_t Multiple) {
- if (!Multiple || Value % Multiple == 0)
- return Value;
- return Value + Multiple - Value % Multiple;
-}
-
-template <class ELFT> void Object<ELFT>::assignOffsets() {
+template <class ELFT> void ObjectCopyELF<ELFT>::assignOffsets() {
// Decide file offsets and indexs
- size_t PhdrSize = Segments.size() * sizeof(Elf_Phdr);
+ size_t PhdrSize = this->Segments.size() * sizeof(Elf_Phdr);
// After the header and the program headers we can put section data.
uint64_t Offset = sizeof(Elf_Ehdr) + PhdrSize;
uint64_t Index = 0;
- for (auto &Section : Sections) {
+ for (auto &Section : this->Sections) {
// The segment can have a different alignment than the section. We need to
// make sure
if (Section->ParrentSegment) {
auto FirstInSeg = Section->ParrentSegment->firstSection();
if (FirstInSeg == Section.get())
Offset = align(Offset, Section->ParrentSegment->Align);
+ // We should respect interstitial gaps of allocated sections
+ Offset = FirstInSeg->Offset + Section->Addr - FirstInSeg->Addr;
}
Offset = align(Offset, Section->Align);
Section->Offset = Offset;
@@ -341,77 +376,119 @@
// section header table offset to be exactly here. This spot might not be
// aligned properlly however so we should align it as needed. This only takes
// a little bit of tweaking to ensure that the sh_name is 4 byte aligned
- Offset = align(Offset, 4);
- SHOffset = Offset;
+ Offset = align(Offset, sizeof(typename ELFT::Word));
+ this->SHOffset = Offset;
}
-template <class ELFT> void Object<ELFT>::finalize() {
+template <class ELFT> void ObjectCopyELF<ELFT>::finalize() {
sortSections();
assignOffsets();
// finalize SectionNames first so that we can assign name indexes.
- SectionNames->finalize();
+ this->SectionNames->finalize();
// Finally now that all offsets and indexes have been set we can finalize any
// reamining issues.
- uint64_t Offset = SHOffset;
- for (auto &Section : Sections) {
- Section->HeaderOffset = Offset;
- Offset += sizeof(Elf_Shdr);
- Section->NameIndex = SectionNames->findIndex(Section->Name);
+ for (auto &Section : this->Sections) {
+ Section->NameIndex = this->SectionNames->findIndex(Section->Name);
Section->finalize();
}
- for (auto &Segment : Segments)
+ for (auto &Segment : this->Segments)
Segment.finalize();
}
template <class ELFT>
-void Object<ELFT>::writeHeader(FileOutputBuffer &Out) const {
+void ObjectCopyELF<ELFT>::writeHeader(FileOutputBuffer &Out) const {
uint8_t *Buf = Out.getBufferStart();
typename ELFT::Ehdr &Ehdr = *reinterpret_cast<typename ELFT::Ehdr *>(Buf);
- std::copy(Ident, Ident + 16, Ehdr.e_ident);
- Ehdr.e_type = Type;
- Ehdr.e_machine = Machine;
- Ehdr.e_version = Version;
- Ehdr.e_entry = Entry;
+ std::copy(this->Ident, this->Ident + 16, Ehdr.e_ident);
+ Ehdr.e_type = this->Type;
+ Ehdr.e_machine = this->Machine;
+ Ehdr.e_version = this->Version;
+ Ehdr.e_entry = this->Entry;
Ehdr.e_phoff = sizeof(Elf_Ehdr);
- Ehdr.e_shoff = SHOffset;
- Ehdr.e_flags = Flags;
+ Ehdr.e_shoff = this->SHOffset;
+ Ehdr.e_flags = this->Flags;
Ehdr.e_ehsize = sizeof(Elf_Ehdr);
Ehdr.e_phentsize = sizeof(Elf_Phdr);
- Ehdr.e_phnum = Segments.size();
+ Ehdr.e_phnum = this->Segments.size();
Ehdr.e_shentsize = sizeof(Elf_Shdr);
- Ehdr.e_shnum = Sections.size();
- Ehdr.e_shstrndx = SectionNames->Index;
+ Ehdr.e_shnum = this->Sections.size();
+ Ehdr.e_shstrndx = this->SectionNames->Index;
}
template <class ELFT>
-void Object<ELFT>::writeProgramHeaders(FileOutputBuffer &Out) const {
- for (auto &Phdr : Segments)
- Phdr.template writeHeader<ELFT>(Out);
+void ObjectCopyELF<ELFT>::writeProgramHeaders(FileOutputBuffer &Out) const {
+ uint8_t *Buf = Out.getBufferStart() + sizeof(Elf_Ehdr);
+ for (auto &Segment : this->Segments) {
+ Segment.template writeHeader<ELFT>(Buf);
+ Buf += sizeof(Elf_Phdr);
+ }
}
template <class ELFT>
-void Object<ELFT>::writeSectionHeaders(FileOutputBuffer &Out) const {
- for (auto &Section : Sections)
- Section->template writeHeader<ELFT>(Out);
+void ObjectCopyELF<ELFT>::writeSectionHeaders(FileOutputBuffer &Out) const {
+ uint8_t *Buf = Out.getBufferStart() + this->SHOffset;
+ for (auto &Section : this->Sections) {
+ Section->template writeHeader<ELFT>(Buf);
+ Buf += sizeof(Elf_Shdr);
+ }
}
template <class ELFT>
-void Object<ELFT>::writeSectionData(FileOutputBuffer &Out) const {
- for (auto &Section : Sections)
- Section->writeSection(Out);
+void ObjectCopyELF<ELFT>::writeSectionData(FileOutputBuffer &Out) const {
+ uint8_t *Buf = Out.getBufferStart();
+ for (auto &Section : this->Sections) {
+ Section->writeSection(Buf + Section->Offset);
+ }
}
-template <class ELFT> void Object<ELFT>::write(FileOutputBuffer &Out) {
+template <class ELFT>
+void ObjectCopyELF<ELFT>::write(FileOutputBuffer &Out) const {
writeHeader(Out);
writeProgramHeaders(Out);
writeSectionData(Out);
writeSectionHeaders(Out);
}
-template class Object<ELF64LE>;
-template class Object<ELF64BE>;
-template class Object<ELF32LE>;
-template class Object<ELF32BE>;
+template <class ELFT> void ObjectCopyBinary<ELFT>::finalize() {
+ for (auto &Segment : this->Segments)
+ Segment.finalize();
+}
+
+template <class ELFT> size_t ObjectCopyBinary<ELFT>::totalSize() const {
+ uint64_t BinSize = 0;
+ for (auto &Segment : this->Segments) {
+ if (Segment.Type == PT_LOAD && Segment.Offset != 0) {
+ BinSize = align(BinSize, Segment.Align);
+ BinSize += Segment.FileSize;
+ }
+ }
+ return BinSize;
+}
+
+template <class ELFT>
+void ObjectCopyBinary<ELFT>::write(FileOutputBuffer &Out) const {
+ // It's worth noting that Segments might be put in very different locations
+ // from each other. They will still be placed
+ uint8_t *Buf = Out.getBufferStart();
+ uint64_t Offset = 0;
+ for (auto &Segment : this->Segments) {
+ if (Segment.Type == PT_LOAD && Segment.Offset != 0) {
+ Offset = align(Offset, Segment.Align);
+ Segment.writeMemSegment(Buf + Offset);
+ Offset += Segment.FileSize;
+ }
+ }
+}
+
+template class ObjectCopyELF<ELF64LE>;
+template class ObjectCopyELF<ELF64BE>;
+template class ObjectCopyELF<ELF32LE>;
+template class ObjectCopyELF<ELF32BE>;
+
+template class ObjectCopyBinary<ELF64LE>;
+template class ObjectCopyBinary<ELF64BE>;
+template class ObjectCopyBinary<ELF32LE>;
+template class ObjectCopyBinary<ELF32BE>;
diff --git a/tools/llvm-objcopy/Object.h b/tools/llvm-objcopy/Object.h
index aba0c26..fcf143a 100644
--- a/tools/llvm-objcopy/Object.h
+++ b/tools/llvm-objcopy/Object.h
@@ -27,8 +27,7 @@
class SectionBase {
public:
llvm::StringRef Name;
- Segment* ParrentSegment;
- uint64_t HeaderOffset;
+ Segment *ParrentSegment = nullptr;
uint32_t Index;
uint64_t Addr = 0;
@@ -44,8 +43,8 @@
virtual ~SectionBase() {}
virtual void finalize();
- template <class ELFT> void writeHeader(llvm::FileOutputBuffer &Out) const;
- virtual void writeSection(llvm::FileOutputBuffer &Out) const = 0;
+ template <class ELFT> void writeHeader(uint8_t *Buf) const;
+ virtual void writeSection(uint8_t *Buf) const = 0;
};
class Segment {
@@ -57,6 +56,8 @@
};
std::set<const SectionBase *, SectionCompare> Sections;
+ std::vector<std::unique_ptr<SectionBase>> InterstitialSections;
+ llvm::ArrayRef<uint8_t> Contents;
public:
uint64_t Align;
@@ -68,6 +69,7 @@
uint64_t Type;
uint64_t VAddr;
+ Segment(llvm::ArrayRef<uint8_t> Data) : Contents(Data) {}
void finalize();
const SectionBase * firstSection() const {
if(Sections.size())
@@ -75,7 +77,8 @@
return nullptr;
}
void addSection(const SectionBase *sec) { Sections.insert(sec); }
- template <class ELFT> void writeHeader(llvm::FileOutputBuffer &Out) const;
+ void writeMemSegment(uint8_t *Buf) const;
+ template <class ELFT> void writeHeader(uint8_t *Buf) const;
};
class Section : public SectionBase {
@@ -83,8 +86,8 @@
llvm::ArrayRef<uint8_t> Contents;
public:
- Section(llvm::ArrayRef<uint8_t> Data) : Contents(Data) {}
- void writeSection(llvm::FileOutputBuffer &Out) const override;
+ Section(llvm::ArrayRef<uint8_t> Data) : Contents(Data) { Size = Data.size(); }
+ void writeSection(uint8_t *Buf) const override;
};
class StringTableSection : public SectionBase {
@@ -100,7 +103,7 @@
void removeString(llvm::StringRef Name);
uint32_t findIndex(llvm::StringRef Name) const;
void finalize() override;
- void writeSection(llvm::FileOutputBuffer &Out) const override;
+ void writeSection(uint8_t *Buf) const override;
static bool classof(const SectionBase *S) {
return S->Type == llvm::ELF::SHT_STRTAB;
}
@@ -136,15 +139,14 @@
SectionBase *DefinedIn, uint64_t Value, uint64_t Sz);
void removeSymbol(llvm::StringRef);
void finalize() override;
- void writeSection(llvm::FileOutputBuffer &) const override;
+ void writeSection(uint8_t *Buf) const override;
static bool classof(const SectionBase *S) {
return S->Type == llvm::ELF::SHT_SYMTAB;
}
};
-template<class ELFT>
-class Object {
-private:
+template <class ELFT> class ObjectCopyBase {
+protected:
typedef std::unique_ptr<SectionBase> SecPtr;
typedef typename ELFT::Shdr Elf_Shdr;
typedef typename ELFT::Ehdr Elf_Ehdr;
@@ -155,16 +157,11 @@
std::vector<SecPtr> Sections;
std::vector<Segment> Segments;
- void sortSections();
- void assignOffsets();
+private:
void readProgramHeaders(const llvm::object::ELFFile<ELFT> &ElfFile);
void readSectionHeaders(const llvm::object::ELFFile<ELFT> &ElfFile);
void readSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile,
const Elf_Shdr &SymTabShdr);
- void writeHeader(llvm::FileOutputBuffer &Out) const;
- void writeProgramHeaders(llvm::FileOutputBuffer &Out) const;
- void writeSectionData(llvm::FileOutputBuffer &Out) const;
- void writeSectionHeaders(llvm::FileOutputBuffer &Out) const;
public:
uint8_t Ident[16];
@@ -175,9 +172,42 @@
uint32_t Version;
uint32_t Flags;
- Object(const llvm::object::ELFObjectFile<ELFT> &Obj);
- size_t totalSize() const;
- void finalize();
- void write(llvm::FileOutputBuffer &Out);
+ ObjectCopyBase(const llvm::object::ELFObjectFile<ELFT> &Obj);
+
+ virtual size_t totalSize() const = 0;
+ virtual void finalize() = 0;
+ virtual void write(llvm::FileOutputBuffer &Out) const = 0;
+ virtual ~ObjectCopyBase() {}
+};
+
+template <class ELFT> class ObjectCopyELF : public ObjectCopyBase<ELFT> {
+private:
+ typedef std::unique_ptr<SectionBase> SecPtr;
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Ehdr Elf_Ehdr;
+ typedef typename ELFT::Phdr Elf_Phdr;
+
+ void sortSections();
+ void assignOffsets();
+ void writeHeader(llvm::FileOutputBuffer &Out) const;
+ void writeProgramHeaders(llvm::FileOutputBuffer &Out) const;
+ void writeSectionData(llvm::FileOutputBuffer &Out) const;
+ void writeSectionHeaders(llvm::FileOutputBuffer &Out) const;
+
+public:
+ ObjectCopyELF(const llvm::object::ELFObjectFile<ELFT> &Obj)
+ : ObjectCopyBase<ELFT>(Obj) {}
+ virtual size_t totalSize() const override;
+ virtual void finalize() override;
+ virtual void write(llvm::FileOutputBuffer &Out) const override;
+};
+
+template <class ELFT> class ObjectCopyBinary : public ObjectCopyBase<ELFT> {
+public:
+ ObjectCopyBinary(const llvm::object::ELFObjectFile<ELFT> &Obj)
+ : ObjectCopyBase<ELFT>(Obj) {}
+ virtual size_t totalSize() const override;
+ virtual void finalize() override;
+ virtual void write(llvm::FileOutputBuffer &Out) const override;
};
#endif
diff --git a/tools/llvm-objcopy/llvm-objcopy.cpp b/tools/llvm-objcopy/llvm-objcopy.cpp
index 6a74a8c..a0006f4 100644
--- a/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -50,12 +50,20 @@
cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input>"));
cl::opt<std::string> OutputFilename(cl::Positional, cl::desc("<output>"),
cl::init("-"));
+cl::opt<bool> OutputBinary("output-binary", cl::desc("output raw binary"));
+
void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) {
std::unique_ptr<FileOutputBuffer> Buffer;
- Object<ELF64LE> Obj{ObjFile};
- Obj.finalize();
+ std::unique_ptr<ObjectCopyBase<ELF64LE>> ObjCopy;
+
+ if (OutputBinary)
+ ObjCopy.reset(new ObjectCopyBinary<ELF64LE>(ObjFile));
+ else
+ ObjCopy.reset(new ObjectCopyELF<ELF64LE>(ObjFile));
+ ObjCopy->finalize();
+
ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
- FileOutputBuffer::create(OutputFilename, Obj.totalSize(),
+ FileOutputBuffer::create(OutputFilename, ObjCopy->totalSize(),
FileOutputBuffer::F_executable);
if (auto EC = BufferOrErr.getError())
error("failed to open " + OutputFilename);
@@ -67,7 +75,8 @@
if (EC)
report_fatal_error(EC.message());
// now if the program fails for any reason the output file will be deleted
- Obj.write(*Buffer);
+ ObjCopy->write(*Buffer);
+
if (auto EC = Buffer->commit())
reportError(OutputFilename, EC);
Out->keep();