Index: test/tools/llvm-objcopy/binary-input-archs.test =================================================================== --- /dev/null +++ test/tools/llvm-objcopy/binary-input-archs.test @@ -0,0 +1,32 @@ +# RUN: printf 0000 > %t + +# RUN: llvm-objcopy -I binary -B i386:x86-64 %t %t2 +# RUN: llvm-readobj -file-headers %t2 | FileCheck %s --check-prefix=ARCH_x86_64 + +# RUN: llvm-objcopy -I binary -B i386 %t %t2 +# RUN: llvm-readobj -file-headers %t2 | FileCheck %s --check-prefix=ARCH_i386 + +# RUN: llvm-objcopy -I binary -B x86-64 %t %t2 +# RUN: llvm-readobj -file-headers %t2 | FileCheck %s --check-prefix=ARCH_x86_64 + +# RUN: llvm-objcopy -I binary -B arm %t %t2 +# RUN: llvm-readobj -file-headers %t2 | FileCheck %s --check-prefix=ARCH_arm32 + +# RUN: llvm-objcopy -I binary -B aarch64 %t %t2 +# RUN: llvm-readobj -file-headers %t2 | FileCheck %s --check-prefix=ARCH_aarch64 + +# ARCH_i386: Class: 32-bit +# ARCH_i386: DataEncoding: LittleEndian +# ARCH_i386: Machine: EM_386 + +# ARCH_x86_64: Class: 64-bit +# ARCH_x86_64: DataEncoding: LittleEndian +# ARCH_x86_64: Machine: EM_X86_64 + +# ARCH_arm32: Class: 32-bit +# ARCH_arm32: DataEncoding: LittleEndian +# ARCH_arm32: Machine: EM_ARM + +# ARCH_aarch64: Class: 64-bit +# ARCH_aarch64: DataEncoding: LittleEndian +# ARCH_aarch64: Machine: EM_AARCH64 Index: test/tools/llvm-objcopy/binary-input-test.bin =================================================================== --- /dev/null +++ test/tools/llvm-objcopy/binary-input-test.bin @@ -0,0 +1 @@ +0000 \ No newline at end of file Index: test/tools/llvm-objcopy/binary-input.test =================================================================== --- /dev/null +++ test/tools/llvm-objcopy/binary-input.test @@ -0,0 +1,138 @@ +# RUN: printf 0000 > %p/binary-input-test.bin +# RUN: llvm-objcopy -I binary -B i386:x86-64 %p/binary-input-test.bin %t2 +# RUN: llvm-readobj -file-headers -sections -symbols %t2 | FileCheck %s + +# CHECK: ElfHeader { +# CHECK-NEXT: Ident { +# CHECK-NEXT: Magic: (7F 45 4C 46) +# CHECK-NEXT: Class: 64-bit (0x2) +# CHECK-NEXT: DataEncoding: LittleEndian (0x1) +# CHECK-NEXT: FileVersion: 1 +# CHECK-NEXT: OS/ABI: SystemV (0x0) +# CHECK-NEXT: ABIVersion: 0 +# CHECK-NEXT: Unused: (00 00 00 00 00 00 00) +# CHECK-NEXT: } +# CHECK-NEXT: Type: Relocatable (0x1) +# CHECK-NEXT: Machine: EM_X86_64 (0x3E) +# CHECK-NEXT: Version: 1 +# CHECK-NEXT: Entry: 0x0 +# CHECK-NEXT: ProgramHeaderOffset: +# CHECK-NEXT: SectionHeaderOffset: +# CHECK-NEXT: Flags [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: HeaderSize: 64 +# CHECK-NEXT: ProgramHeaderEntrySize: +# CHECK-NEXT: ProgramHeaderCount: 0 +# CHECK-NEXT: SectionHeaderEntrySize: 64 +# CHECK-NEXT: SectionHeaderCount: 4 +# CHECK-NEXT: StringTableSectionIndex: 1 +# CHECK-NEXT: } + +# CHECK: Sections [ +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: Name: (0) +# CHECK-NEXT: Type: SHT_NULL (0x0) +# CHECK-NEXT: Flags [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x0 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 0 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 1 +# CHECK-NEXT: Name: .strtab +# CHECK-NEXT: Type: SHT_STRTAB +# CHECK-NEXT: Flags [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x0 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 1 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 2 +# CHECK-NEXT: Name: .symtab +# CHECK-NEXT: Type: SHT_SYMTAB +# CHECK-NEXT: Flags [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x0 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: +# CHECK-NEXT: Link: 1 +# CHECK-NEXT: Info: 2 +# CHECK-NEXT: AddressAlignment: 8 +# CHECK-NEXT: EntrySize: 24 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 3 +# CHECK-NEXT: Name: .data +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x0 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 1 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +#CHECK: Symbols [ +#CHECK-NEXT: Symbol { +#CHECK-NEXT: Name: +#CHECK-NEXT: Value: 0x0 +#CHECK-NEXT: Size: 0 +#CHECK-NEXT: Binding: Local (0x0) +#CHECK-NEXT: Type: None (0x0) +#CHECK-NEXT: Other: 0 +#CHECK-NEXT: Section: Undefined (0x0) +#CHECK-NEXT: } +#CHECK-NEXT: Symbol { +#CHECK-NEXT: Name: +#CHECK-NEXT: Value: 0x0 +#CHECK-NEXT: Size: 0 +#CHECK-NEXT: Binding: Local (0x0) +#CHECK-NEXT: Type: Section (0x3) +#CHECK-NEXT: Other: 0 +#CHECK-NEXT: Section: .data +#CHECK-NEXT: } +#CHECK-NEXT: Symbol { +#CHECK-NEXT: Name: _binary_binary_input_test_start +#CHECK-NEXT: Value: 0x0 +#CHECK-NEXT: Size: 0 +#CHECK-NEXT: Binding: Global (0x1) +#CHECK-NEXT: Type: None (0x0) +#CHECK-NEXT: Other: 0 +#CHECK-NEXT: Section: .data +#CHECK-NEXT: } +#CHECK-NEXT: Symbol { +#CHECK-NEXT: Name: _binary_binary_input_test_end +#CHECK-NEXT: Value: 0x4 +#CHECK-NEXT: Size: 0 +#CHECK-NEXT: Binding: Global (0x1) +#CHECK-NEXT: Type: None (0x0) +#CHECK-NEXT: Other: 0 +#CHECK-NEXT: Section: .data +#CHECK-NEXT: } +#CHECK-NEXT: Symbol { +#CHECK-NEXT: Name: _binary_binary_input_test_size +#CHECK-NEXT: Value: 0x4 +#CHECK-NEXT: Size: 0 +#CHECK-NEXT: Binding: Global (0x1) +#CHECK-NEXT: Type: None (0x0) +#CHECK-NEXT: Other: 0 +#CHECK-NEXT: Section: Absolute (0xFFF1) +#CHECK-NEXT: } +#CHECK-NEXT: ] Index: tools/llvm-objcopy/Object.h =================================================================== --- tools/llvm-objcopy/Object.h +++ tools/llvm-objcopy/Object.h @@ -188,7 +188,7 @@ SectionBase *DefinedIn = nullptr; SymbolShndxType ShndxType; uint32_t Index; - StringRef Name; + std::string Name; uint32_t NameIndex; uint64_t Size; uint8_t Type; @@ -206,10 +206,14 @@ using SymPtr = std::unique_ptr; public: + SymbolTableSection() { + Type = ELF::SHT_SYMTAB; + Align = 8; + } void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; } - void addSymbol(StringRef Name, uint8_t Bind, uint8_t Type, - SectionBase *DefinedIn, uint64_t Value, uint8_t Visibility, - uint16_t Shndx, uint64_t Sz); + void addSymbol(Twine Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn, + uint64_t Value, uint8_t Visibility, uint16_t Shndx, + uint64_t Sz); void addSymbolNames(); const SectionBase *getStrTab() const { return SymbolNames; } const Symbol *getSymbolByIndex(uint32_t Index) const; @@ -225,6 +229,8 @@ // Only writeSection depends on the ELF type so we implement it in a subclass. template class SymbolTableSectionImpl : public SymbolTableSection { +public: + SymbolTableSectionImpl() { EntrySize = sizeof(typename ELFT::Sym); } void writeSection(FileOutputBuffer &Out) const override; }; @@ -354,6 +360,7 @@ using Elf_Ehdr = typename ELFT::Ehdr; using Elf_Phdr = typename ELFT::Phdr; + void initHeader(uint16_t EMachine); void initSymbolTable(const object::ELFFile &ElfFile, SymbolTableSection *SymTab, SectionTableRef SecTable); SecPtr makeSection(const object::ELFFile &ElfFile, @@ -382,13 +389,15 @@ uint32_t Flags; bool WriteSectionHeaders = true; + Object(uint16_t EMachine); Object(const object::ELFObjectFile &Obj); virtual ~Object() = default; - SymbolTableSection *getSymTab() const { return SymbolTable; } + SymbolTableSection *getSymTab() { return SymbolTable; } + const SymbolTableSection *getSymTab() const { return SymbolTable; } const SectionBase *getSectionHeaderStrTab() const { return SectionNames; } void removeSections(std::function ToRemove); - void addSection(StringRef SecName, ArrayRef Data); + SectionBase *addSection(StringRef SecName, ArrayRef Data); virtual size_t totalSize() const = 0; virtual void finalize() = 0; virtual void write(FileOutputBuffer &Out) const = 0; @@ -407,6 +416,7 @@ void assignOffsets(); public: + ELFObject(uint16_t EMachine) : Object(EMachine) {} ELFObject(const object::ELFObjectFile &Obj) : Object(Obj) {} void finalize() override; @@ -422,6 +432,7 @@ uint64_t TotalSize; public: + BinaryObject(uint16_t EMachine) : Object(EMachine) {} BinaryObject(const object::ELFObjectFile &Obj) : Object(Obj) {} void finalize() override; Index: tools/llvm-objcopy/Object.cpp =================================================================== --- tools/llvm-objcopy/Object.cpp +++ tools/llvm-objcopy/Object.cpp @@ -139,12 +139,12 @@ llvm_unreachable("Symbol with invalid ShndxType encountered"); } -void SymbolTableSection::addSymbol(StringRef Name, uint8_t Bind, uint8_t Type, +void SymbolTableSection::addSymbol(Twine Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn, uint64_t Value, uint8_t Visibility, uint16_t Shndx, uint64_t Sz) { Symbol Sym; - Sym.Name = Name; + Sym.Name = Name.str(); Sym.Binding = Bind; Sym.Type = Type; Sym.DefinedIn = DefinedIn; @@ -587,6 +587,46 @@ return SecTable; } +template void SetIdent(uint8_t Ident[16]) { + std::fill(Ident, Ident + 16, 0); + Ident[EI_MAG0] = 0x7f; + Ident[EI_MAG1] = 'E'; + Ident[EI_MAG2] = 'L'; + Ident[EI_MAG3] = 'F'; + Ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; + Ident[EI_DATA] = + ELFT::TargetEndianness == support::big ? ELFDATA2MSB : ELFDATA2LSB; + Ident[EI_VERSION] = EV_CURRENT; + Ident[EI_OSABI] = ELFOSABI_NONE; + Ident[EI_ABIVERSION] = 0; +} + +template void Object::initHeader(uint16_t EMachine) { + SetIdent(Ident); + Flags = 0x0; + Type = ET_REL; + Entry = 0x0; + Machine = EMachine; + Version = 1; +} + +template Object::Object(uint16_t EMachine) { + initHeader(EMachine); + + auto StrTab = llvm::make_unique(); + StrTab->Name = ".strtab"; + SectionNames = StrTab.get(); + Sections.emplace_back(std::move(StrTab)); + + auto SymTab = llvm::make_unique>(); + SymTab->Name = ".symtab"; + SymTab->setStrTab(SectionNames); + // We need to add the null symbol. + SymTab->addSymbol("", 0, 0, nullptr, 0, 0, 0, 0); + SymbolTable = SymTab.get(); + Sections.emplace_back(std::move(SymTab)); +} + template Object::Object(const ELFObjectFile &Obj) { const auto &ElfFile = *Obj.getELFFile(); const auto &Ehdr = *ElfFile.getHeader(); @@ -704,10 +744,13 @@ } template -void Object::addSection(StringRef SecName, ArrayRef Data) { +SectionBase *Object::addSection(StringRef SecName, + ArrayRef Data) { auto Sec = llvm::make_unique(SecName, Data); + auto Out = Sec.get(); Sec->OriginalOffset = ~0ULL; Sections.push_back(std::move(Sec)); + return Out; } template void ELFObject::sortSections() { Index: tools/llvm-objcopy/llvm-objcopy.cpp =================================================================== --- tools/llvm-objcopy/llvm-objcopy.cpp +++ tools/llvm-objcopy/llvm-objcopy.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" @@ -74,6 +75,11 @@ static cl::opt InputFilename(cl::Positional, cl::desc("")); static cl::opt OutputFilename(cl::Positional, cl::desc(""), cl::init("-")); +static cl::opt BinaryArchitecture( + "B", cl::desc("Specify the architecture of a binary input file.")); +static cl::opt + InputFormat("I", cl::desc("Set input format to one of the following:" + "\n\tbinary")); static cl::opt OutputFormat("O", cl::desc("Set output format to one of the following:" "\n\tbinary")); @@ -164,6 +170,18 @@ WriteObjectFile(DWOFile, File); } +template +SectionBase *AddSectionFromFile(Object &Obj, StringRef SecName, + StringRef File) { + auto BufOrErr = MemoryBuffer::getFile(File); + if (!BufOrErr) + reportError(File, BufOrErr.getError()); + auto Buf = std::move(*BufOrErr); + auto BufPtr = reinterpret_cast(Buf->getBufferStart()); + auto BufSize = Buf->getBufferSize(); + return Obj.addSection(SecName, ArrayRef(BufPtr, BufSize)); +} + // This function handles the high level operations of GNU objcopy including // handling command line options. It's important to outline certain properties // we expect to hold of the command line operations. Any operation that "keeps" @@ -171,23 +189,11 @@ // any previous removals. Lastly whether or not something is removed shouldn't // depend a) on the order the options occur in or b) on some opaque priority // system. The only priority is that keeps/copies overrule removes. -template void CopyBinary(const ELFObjectFile &ObjFile) { - std::unique_ptr> Obj; - - if (!OutputFormat.empty() && OutputFormat != "binary") - error("invalid output format '" + OutputFormat + "'"); - if (!OutputFormat.empty() && OutputFormat == "binary") - Obj = llvm::make_unique>(ObjFile); - else - Obj = llvm::make_unique>(ObjFile); - - if (!SplitDWO.empty()) - SplitDWOToFile(ObjFile, SplitDWO.getValue()); - +template void HandleArgs(Object &Obj) { // Localize: if (LocalizeHidden) { - Obj->getSymTab()->localize([](const Symbol &Sym) { + Obj.getSymTab()->localize([](const Symbol &Sym) { return Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL; }); } @@ -210,7 +216,7 @@ if (ExtractDWO) RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { - return OnlyKeepDWOPred(*Obj, Sec) || RemovePred(Sec); + return OnlyKeepDWOPred(Obj, Sec) || RemovePred(Sec); }; if (StripAllGNU) @@ -219,7 +225,7 @@ return true; if ((Sec.Flags & SHF_ALLOC) != 0) return false; - if (&Sec == Obj->getSectionHeaderStrTab()) + if (&Sec == Obj.getSectionHeaderStrTab()) return false; switch (Sec.Type) { case SHT_SYMTAB: @@ -235,7 +241,7 @@ RemovePred = [RemovePred](const SectionBase &Sec) { return RemovePred(Sec) || (Sec.Flags & SHF_ALLOC) == 0; }; - Obj->WriteSectionHeaders = false; + Obj.WriteSectionHeaders = false; } if (StripDebug) { @@ -248,7 +254,7 @@ RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { if (RemovePred(Sec)) return true; - if (&Sec == Obj->getSectionHeaderStrTab()) + if (&Sec == Obj.getSectionHeaderStrTab()) return false; return (Sec.Flags & SHF_ALLOC) == 0; }; @@ -257,7 +263,7 @@ RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { if (RemovePred(Sec)) return true; - if (&Sec == Obj->getSectionHeaderStrTab()) + if (&Sec == Obj.getSectionHeaderStrTab()) return false; if (Sec.Name.startswith(".gnu.warning")) return false; @@ -279,10 +285,10 @@ } // Keep special sections. - if (Obj->getSectionHeaderStrTab() == &Sec) { + if (Obj.getSectionHeaderStrTab() == &Sec) { return false; } - if (Obj->getSymTab() == &Sec || Obj->getSymTab()->getStrTab() == &Sec) { + if (Obj.getSymTab() == &Sec || Obj.getSymTab()->getStrTab() == &Sec) { return false; } // Remove everything else. @@ -301,25 +307,127 @@ }; } - Obj->removeSections(RemovePred); + Obj.removeSections(RemovePred); if (!AddSection.empty()) { for (const auto &Flag : AddSection) { auto SecPair = StringRef(Flag).split("="); auto SecName = SecPair.first; auto File = SecPair.second; - auto BufOrErr = MemoryBuffer::getFile(File); - if (!BufOrErr) - reportError(File, BufOrErr.getError()); - auto Buf = std::move(*BufOrErr); - auto BufPtr = reinterpret_cast(Buf->getBufferStart()); - auto BufSize = Buf->getBufferSize(); - Obj->addSection(SecName, ArrayRef(BufPtr, BufSize)); + AddSectionFromFile(Obj, SecName, File); } } - Obj->finalize(); - WriteObjectFile(*Obj, OutputFilename.getValue()); + Obj.finalize(); + WriteObjectFile(Obj, OutputFilename.getValue()); +} + +// This type keeps track of the machine info for various architectures. This +// lets us map architecture names to ELF types and the e_machine value of the +// ELF file. +struct MachineInfo { + uint16_t EMachine; + bool Is64Bit; + bool IsLittleEndian; +}; + +static const MachineInfo MI_X86_64{EM_X86_64, true, true}; +static const MachineInfo MI_386{EM_386, false, true}; +static const MachineInfo MI_AARCH64{EM_AARCH64, true, true}; +static const MachineInfo MI_ARM{EM_ARM, false, true}; + +static const StringMap ArchMap{{"i386", MI_386}, + {"i386:x86-64", MI_X86_64}, + {"x86-64", MI_X86_64}, + {"arm", MI_ARM}, + {"aarch64", MI_AARCH64}}; + +static MachineInfo GetMachineInfo(StringRef Arch) { + auto Iter = ArchMap.find(Arch); + if (Iter == std::end(ArchMap)) + error("Invalid architecture: " + Arch); + return Iter->getValue(); +} + +template +void InputBinaryFormat(Object &Obj, StringRef BinFile) { + auto DataSec = AddSectionFromFile(Obj, ".data", BinFile); + DataSec->Flags = SHF_ALLOC | SHF_WRITE; + std::string BinFileName = sys::path::stem(BinFile); + std::replace_if(std::begin(BinFileName), std::end(BinFileName), + [](char c) { return !isalnum(c); }, '_'); + auto BaseName = Twine("_binary_") + BinFileName; + auto StartName = BaseName + "_start"; + auto EndName = BaseName + "_end"; + auto SizeName = BaseName + "_size"; + auto SymTab = Obj.getSymTab(); + SymTab->addSymbol("", STB_LOCAL, STT_SECTION, DataSec, 0, STV_DEFAULT, 0, 0); + SymTab->addSymbol(StartName, STB_GLOBAL, STT_NOTYPE, DataSec, 0, STV_DEFAULT, + 0, 0); + SymTab->addSymbol(EndName, STB_GLOBAL, STT_NOTYPE, DataSec, DataSec->Size, + STV_DEFAULT, 0, 0); + SymTab->addSymbol(SizeName, STB_GLOBAL, STT_NOTYPE, nullptr, DataSec->Size, + STV_DEFAULT, SHN_ABS, 0); +} + +template +void HandleBinary(StringRef Input, StringRef OutFmt, MachineInfo MInfo) { + if (OutFmt == "binary") { + BinaryObject Obj(MInfo.EMachine); + InputBinaryFormat(Obj, Input); + HandleArgs(Obj); + } else { + ELFObject Obj(MInfo.EMachine); + InputBinaryFormat(Obj, Input); + HandleArgs(Obj); + } +} + +static void HandleBinaryELFT(StringRef Input, StringRef OutFmt, + StringRef Arch) { + MachineInfo MInfo = GetMachineInfo(Arch); + if (MInfo.Is64Bit) { + if (MInfo.IsLittleEndian) + HandleBinary(Input, OutFmt, MInfo); + else + HandleBinary(Input, OutFmt, MInfo); + } else { + if (MInfo.IsLittleEndian) + HandleBinary(Input, OutFmt, MInfo); + else + HandleBinary(Input, OutFmt, MInfo); + } +} + +template +void HandleELF(const ELFObjectFile &ObjFile, StringRef OutFmt) { + if (!SplitDWO.empty()) + SplitDWOToFile(ObjFile, SplitDWO.getValue()); + + if (OutFmt == "binary") { + BinaryObject Obj(ObjFile); + HandleArgs(Obj); + } else { + ELFObject Obj(ObjFile); + HandleArgs(Obj); + } +} + +static void HandleELFT(StringRef Input, StringRef OutFmt) { + Expected> BinaryOrErr = createBinary(Input); + if (!BinaryOrErr) + reportError(Input, BinaryOrErr.takeError()); + Binary &Binary = *BinaryOrErr.get().getBinary(); + if (auto *o = dyn_cast>(&Binary)) + HandleELF(*o, OutFmt); + else if (auto *o = dyn_cast>(&Binary)) + HandleELF(*o, OutFmt); + else if (auto *o = dyn_cast>(&Binary)) + HandleELF(*o, OutFmt); + else if (auto *o = dyn_cast>(&Binary)) + HandleELF(*o, OutFmt); + else + reportError(Input, object_error::invalid_file_type); } int main(int argc, char **argv) { @@ -333,25 +441,8 @@ cl::PrintHelpMessage(); return 2; } - Expected> BinaryOrErr = createBinary(InputFilename); - if (!BinaryOrErr) - reportError(InputFilename, BinaryOrErr.takeError()); - Binary &Binary = *BinaryOrErr.get().getBinary(); - if (auto *o = dyn_cast>(&Binary)) { - CopyBinary(*o); - return 0; - } - if (auto *o = dyn_cast>(&Binary)) { - CopyBinary(*o); - return 0; - } - if (auto *o = dyn_cast>(&Binary)) { - CopyBinary(*o); - return 0; - } - if (auto *o = dyn_cast>(&Binary)) { - CopyBinary(*o); - return 0; - } - reportError(InputFilename, object_error::invalid_file_type); + if (InputFormat == "binary") + HandleBinaryELFT(InputFilename, OutputFormat, BinaryArchitecture); + else + HandleELFT(InputFilename, OutputFormat); }