aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
diff options
context:
space:
mode:
authorJordan Rupprecht <rupprecht@google.com>2018-08-17 18:51:11 +0000
committerJordan Rupprecht <rupprecht@google.com>2018-08-17 18:51:11 +0000
commitcf67633e66de0853ed061dd38960623209aa9dba (patch)
tree94c5ddb942206dd032741ffe052c4e957f85050c /llvm/tools/llvm-objcopy/llvm-objcopy.cpp
parentda5864c73c454441fe1ffdb309d5022eeda3f284 (diff)
downloadllvm-cf67633e66de0853ed061dd38960623209aa9dba.zip
llvm-cf67633e66de0853ed061dd38960623209aa9dba.tar.gz
llvm-cf67633e66de0853ed061dd38960623209aa9dba.tar.bz2
[llvm-objcopy] Add support for -I binary -B <arch>.
Summary: The -I (--input-target) and -B (--binary-architecture) flags exist but are currently silently ignored. This adds support for -I binary for architectures i386, x86-64 (and alias i386:x86-64), arm, aarch64, sparc, and ppc (powerpc:common64). This is largely based on D41687. This is done by implementing an additional subclass of Reader, BinaryReader, which works by interpreting the input file as contents for .data field, sets up a synthetic header, and adds additional sections/symbols (e.g. _binary__tmp_data_txt_start). Reviewers: jakehehrlich, alexshap, jhenderson, javed.absar Reviewed By: jhenderson Subscribers: jyknight, nemanjai, kbarton, fedor.sergeev, jrtc27, kristof.beyls, paulsemel, llvm-commits Differential Revision: https://reviews.llvm.org/D50343 llvm-svn: 340070
Diffstat (limited to 'llvm/tools/llvm-objcopy/llvm-objcopy.cpp')
-rw-r--r--llvm/tools/llvm-objcopy/llvm-objcopy.cpp136
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 ca6609f..7713aa6f 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);