diff options
Diffstat (limited to 'llvm/tools/llvm-objcopy/llvm-objcopy.cpp')
-rw-r--r-- | llvm/tools/llvm-objcopy/llvm-objcopy.cpp | 136 |
1 files changed, 103 insertions, 33 deletions
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp index ca6609f9a99..7713aa6f42b 100644 --- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp +++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/InitLLVM.h" +#include "llvm/Support/Memory.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/WithColor.h" @@ -128,41 +129,51 @@ struct SectionRename { }; struct CopyConfig { - StringRef OutputFilename; + // Main input/output options StringRef InputFilename; - StringRef OutputFormat; StringRef InputFormat; - StringRef BinaryArch; + StringRef OutputFilename; + StringRef OutputFormat; - StringRef SplitDWO; + // Only applicable for --input-format=Binary + MachineInfo BinaryArch; + + // Advanced options StringRef AddGnuDebugLink; + StringRef SplitDWO; StringRef SymbolsPrefix; - std::vector<StringRef> ToRemove; - std::vector<StringRef> Keep; - std::vector<StringRef> OnlyKeep; + + // Repeated options std::vector<StringRef> AddSection; std::vector<StringRef> DumpSection; - std::vector<StringRef> SymbolsToLocalize; + std::vector<StringRef> Keep; + std::vector<StringRef> OnlyKeep; std::vector<StringRef> SymbolsToGlobalize; - std::vector<StringRef> SymbolsToWeaken; - std::vector<StringRef> SymbolsToRemove; std::vector<StringRef> SymbolsToKeep; + std::vector<StringRef> SymbolsToLocalize; + std::vector<StringRef> SymbolsToRemove; + std::vector<StringRef> SymbolsToWeaken; + std::vector<StringRef> ToRemove; + + // Map options StringMap<SectionRename> SectionsToRename; StringMap<StringRef> SymbolsToRename; + + // Boolean options + bool DiscardAll = false; + bool ExtractDWO = false; + bool KeepFileSymbols = false; + bool LocalizeHidden = false; + bool OnlyKeepDebug = false; + bool PreserveDates = false; bool StripAll = false; bool StripAllGNU = false; + bool StripDWO = false; bool StripDebug = false; - bool StripSections = false; bool StripNonAlloc = false; - bool StripDWO = false; + bool StripSections = false; bool StripUnneeded = false; - bool ExtractDWO = false; - bool LocalizeHidden = false; bool Weaken = false; - bool DiscardAll = false; - bool OnlyKeepDebug = false; - bool KeepFileSymbols = false; - bool PreserveDates = false; }; using SectionPred = std::function<bool(const SectionBase &Sec)>; @@ -295,6 +306,45 @@ static bool onlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) { return !isDWOSection(Sec); } +static const StringMap<MachineInfo> ArchMap{ + // Name, {EMachine, 64bit, LittleEndian} + {"aarch64", {EM_AARCH64, true, true}}, + {"arm", {EM_ARM, false, true}}, + {"i386", {EM_386, false, true}}, + {"i386:x86-64", {EM_X86_64, true, true}}, + {"powerpc:common64", {EM_PPC64, true, true}}, + {"sparc", {EM_SPARC, false, true}}, + {"x86-64", {EM_X86_64, true, true}}, +}; + +static const MachineInfo &getMachineInfo(StringRef Arch) { + auto Iter = ArchMap.find(Arch); + if (Iter == std::end(ArchMap)) + error("Invalid architecture: '" + Arch + "'"); + return Iter->getValue(); +} + +static ElfType getOutputElfType(const Binary &Bin) { + // Infer output ELF type from the input ELF object + if (isa<ELFObjectFile<ELF32LE>>(Bin)) + return ELFT_ELF32LE; + if (isa<ELFObjectFile<ELF64LE>>(Bin)) + return ELFT_ELF64LE; + if (isa<ELFObjectFile<ELF32BE>>(Bin)) + return ELFT_ELF32BE; + if (isa<ELFObjectFile<ELF64BE>>(Bin)) + return ELFT_ELF64BE; + llvm_unreachable("Invalid ELFType"); +} + +static ElfType getOutputElfType(const MachineInfo &MI) { + // Infer output ELF type from the binary arch specified + if (MI.Is64Bit) + return MI.IsLittleEndian ? ELFT_ELF64LE : ELFT_ELF64BE; + else + return MI.IsLittleEndian ? ELFT_ELF32LE : ELFT_ELF32BE; +} + static std::unique_ptr<Writer> createWriter(const CopyConfig &Config, Object &Obj, Buffer &Buf, ElfType OutputElfType) { @@ -603,15 +653,14 @@ static void handleArgs(const CopyConfig &Config, Object &Obj, Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink); } -static void executeElfObjcopyOnBinary(const CopyConfig &Config, Binary &Binary, - Buffer &Out) { - ELFReader Reader(&Binary); +static void executeElfObjcopyOnBinary(const CopyConfig &Config, Reader &Reader, + Buffer &Out, ElfType OutputElfType) { std::unique_ptr<Object> Obj = Reader.create(); - handleArgs(Config, *Obj, Reader, Reader.getElfType()); + handleArgs(Config, *Obj, Reader, OutputElfType); std::unique_ptr<Writer> Writer = - createWriter(Config, *Obj, Out, Reader.getElfType()); + createWriter(Config, *Obj, Out, OutputElfType); Writer->finalize(); Writer->write(); } @@ -653,12 +702,15 @@ static void executeElfObjcopyOnArchive(const CopyConfig &Config, Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary(); if (!ChildOrErr) reportError(Ar.getFileName(), ChildOrErr.takeError()); + Binary *Bin = ChildOrErr->get(); + Expected<StringRef> ChildNameOrErr = Child.getName(); if (!ChildNameOrErr) reportError(Ar.getFileName(), ChildNameOrErr.takeError()); MemBuffer MB(ChildNameOrErr.get()); - executeElfObjcopyOnBinary(Config, **ChildOrErr, MB); + ELFReader Reader(Bin); + executeElfObjcopyOnBinary(Config, Reader, MB, getOutputElfType(*Bin)); Expected<NewArchiveMember> Member = NewArchiveMember::getOldMember(Child, true); @@ -698,16 +750,29 @@ static void executeElfObjcopy(const CopyConfig &Config) { if (auto EC = sys::fs::status(Config.InputFilename, Stat)) reportError(Config.InputFilename, EC); - Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr = - createBinary(Config.InputFilename); - if (!BinaryOrErr) - reportError(Config.InputFilename, BinaryOrErr.takeError()); + if (Config.InputFormat == "binary") { + auto BufOrErr = MemoryBuffer::getFile(Config.InputFilename); + if (!BufOrErr) + reportError(Config.InputFilename, BufOrErr.getError()); - if (Archive *Ar = dyn_cast<Archive>(BinaryOrErr.get().getBinary())) { - executeElfObjcopyOnArchive(Config, *Ar); - } else { FileBuffer FB(Config.OutputFilename); - executeElfObjcopyOnBinary(Config, *BinaryOrErr.get().getBinary(), FB); + BinaryReader Reader(Config.BinaryArch, BufOrErr->get()); + executeElfObjcopyOnBinary(Config, Reader, FB, + getOutputElfType(Config.BinaryArch)); + } else { + Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr = + createBinary(Config.InputFilename); + if (!BinaryOrErr) + reportError(Config.InputFilename, BinaryOrErr.takeError()); + + if (Archive *Ar = dyn_cast<Archive>(BinaryOrErr.get().getBinary())) { + executeElfObjcopyOnArchive(Config, *Ar); + } else { + FileBuffer FB(Config.OutputFilename); + Binary *Bin = BinaryOrErr.get().getBinary(); + ELFReader Reader(Bin); + executeElfObjcopyOnBinary(Config, Reader, FB, getOutputElfType(*Bin)); + } } if (Config.PreserveDates) { @@ -755,7 +820,12 @@ static CopyConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) { Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1]; Config.InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target); Config.OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target); - Config.BinaryArch = InputArgs.getLastArgValue(OBJCOPY_binary_architecture); + if (Config.InputFormat == "binary") { + auto BinaryArch = InputArgs.getLastArgValue(OBJCOPY_binary_architecture); + if (BinaryArch.empty()) + error("Specified binary input without specifiying an architecture"); + Config.BinaryArch = getMachineInfo(BinaryArch); + } Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo); Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink); |