aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
diff options
context:
space:
mode:
authorAlexander Shaposhnikov <shal1t712@gmail.com>2018-10-24 22:49:06 +0000
committerAlexander Shaposhnikov <shal1t712@gmail.com>2018-10-24 22:49:06 +0000
commit654d3a9577d9782b03edaff7be369fa13e9ba14b (patch)
tree9e0b9e3c233edfc475172a2dc626f8820ade353e /llvm/tools/llvm-objcopy/llvm-objcopy.cpp
parentad4d018202d7f967c56b6adcfc283f7273b9d356 (diff)
downloadllvm-654d3a9577d9782b03edaff7be369fa13e9ba14b.zip
llvm-654d3a9577d9782b03edaff7be369fa13e9ba14b.tar.gz
llvm-654d3a9577d9782b03edaff7be369fa13e9ba14b.tar.bz2
[llvm-objcopy] Introduce dispatch mechanism based on the input
In this diff we introduce dispatch mechanism based on the type of the input (archive, object file, raw binary) and the format (coff, elf, macho). We also move the ELF-specific code into the namespace llvm::objcopy::elf. Test plan: make check-all Differential revision: https://reviews.llvm.org/D53311 llvm-svn: 345217
Diffstat (limited to 'llvm/tools/llvm-objcopy/llvm-objcopy.cpp')
-rw-r--r--llvm/tools/llvm-objcopy/llvm-objcopy.cpp88
1 files changed, 65 insertions, 23 deletions
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
index b7dbf6c..b7e2361 100644
--- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -53,13 +53,6 @@
#include <system_error>
#include <utility>
-using namespace llvm;
-using namespace llvm::objcopy;
-using namespace object;
-using namespace ELF;
-
-using SectionPred = std::function<bool(const SectionBase &Sec)>;
-
namespace llvm {
namespace objcopy {
@@ -92,6 +85,16 @@ LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, Error E) {
} // end namespace objcopy
} // end namespace llvm
+// TODO: move everything enclosed in the namespace llvm::objcopy::elf
+// into separate header+cpp files.
+namespace llvm {
+namespace objcopy {
+namespace elf {
+
+using namespace object;
+using namespace ELF;
+using SectionPred = std::function<bool(const SectionBase &Sec)>;
+
static bool isDebugSection(const SectionBase &Sec) {
return StringRef(Sec.Name).startswith(".debug") ||
StringRef(Sec.Name).startswith(".zdebug") || Sec.Name == ".gdb_index";
@@ -513,18 +516,39 @@ static void handleArgs(const CopyConfig &Config, Object &Obj,
Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink);
}
-static void executeElfObjcopyOnBinary(const CopyConfig &Config, Reader &Reader,
- Buffer &Out, ElfType OutputElfType) {
+void executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
+ Buffer &Out) {
+ BinaryReader Reader(Config.BinaryArch, &In);
std::unique_ptr<Object> Obj = Reader.create();
+ const ElfType OutputElfType = getOutputElfType(Config.BinaryArch);
handleArgs(Config, *Obj, Reader, OutputElfType);
+ std::unique_ptr<Writer> Writer =
+ createWriter(Config, *Obj, Out, OutputElfType);
+ Writer->finalize();
+ Writer->write();
+}
+void executeObjcopyOnBinary(const CopyConfig &Config,
+ object::ELFObjectFileBase &In, Buffer &Out) {
+ ELFReader Reader(&In);
+ std::unique_ptr<Object> Obj = Reader.create();
+ const ElfType OutputElfType = getOutputElfType(In);
+ handleArgs(Config, *Obj, Reader, OutputElfType);
std::unique_ptr<Writer> Writer =
createWriter(Config, *Obj, Out, OutputElfType);
Writer->finalize();
Writer->write();
}
+} // end namespace elf
+} // end namespace objcopy
+} // end namespace llvm
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::objcopy;
+
// For regular archives this function simply calls llvm::writeArchive,
// For thin archives it writes the archive file itself as well as its members.
static Error deepWriteArchive(StringRef ArcName,
@@ -554,8 +578,29 @@ static Error deepWriteArchive(StringRef ArcName,
return Error::success();
}
-static void executeElfObjcopyOnArchive(const CopyConfig &Config,
- const Archive &Ar) {
+/// The function executeObjcopyOnRawBinary does the dispatch based on the format
+/// of the output specified by the command line options.
+static void executeObjcopyOnRawBinary(const CopyConfig &Config,
+ MemoryBuffer &In, Buffer &Out) {
+ // TODO: llvm-objcopy should parse CopyConfig.OutputFormat to recognize
+ // formats other than ELF / "binary" and invoke
+ // elf::executeObjcopyOnRawBinary, macho::executeObjcopyOnRawBinary or
+ // coff::executeObjcopyOnRawBinary accordingly.
+ return elf::executeObjcopyOnRawBinary(Config, In, Out);
+}
+
+/// The function executeObjcopyOnBinary does the dispatch based on the format
+/// of the input binary (ELF, MachO or COFF).
+static void executeObjcopyOnBinary(const CopyConfig &Config, object::Binary &In,
+ Buffer &Out) {
+ if (auto *ELFBinary = dyn_cast<object::ELFObjectFileBase>(&In))
+ return elf::executeObjcopyOnBinary(Config, *ELFBinary, Out);
+ else
+ error("Unsupported object file format");
+}
+
+static void executeObjcopyOnArchive(const CopyConfig &Config,
+ const Archive &Ar) {
std::vector<NewArchiveMember> NewArchiveMembers;
Error Err = Error::success();
for (const Archive::Child &Child : Ar.children(Err)) {
@@ -569,8 +614,7 @@ static void executeElfObjcopyOnArchive(const CopyConfig &Config,
reportError(Ar.getFileName(), ChildNameOrErr.takeError());
MemBuffer MB(ChildNameOrErr.get());
- ELFReader Reader(Bin);
- executeElfObjcopyOnBinary(Config, Reader, MB, getOutputElfType(*Bin));
+ executeObjcopyOnBinary(Config, *Bin, MB);
Expected<NewArchiveMember> Member =
NewArchiveMember::getOldMember(Child, true);
@@ -605,7 +649,10 @@ static void restoreDateOnFile(StringRef Filename,
reportError(Filename, EC);
}
-static void executeElfObjcopy(const CopyConfig &Config) {
+/// The function executeObjcopy does the higher level dispatch based on the type
+/// of input (raw binary, archive or single object file) and takes care of the
+/// format-agnostic modifications, i.e. preserving dates.
+static void executeObjcopy(const CopyConfig &Config) {
sys::fs::file_status Stat;
if (Config.PreserveDates)
if (auto EC = sys::fs::status(Config.InputFilename, Stat))
@@ -615,11 +662,8 @@ static void executeElfObjcopy(const CopyConfig &Config) {
auto BufOrErr = MemoryBuffer::getFile(Config.InputFilename);
if (!BufOrErr)
reportError(Config.InputFilename, BufOrErr.getError());
-
FileBuffer FB(Config.OutputFilename);
- BinaryReader Reader(Config.BinaryArch, BufOrErr->get());
- executeElfObjcopyOnBinary(Config, Reader, FB,
- getOutputElfType(Config.BinaryArch));
+ executeObjcopyOnRawBinary(Config, *BufOrErr->get(), FB);
} else {
Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr =
createBinary(Config.InputFilename);
@@ -627,12 +671,10 @@ static void executeElfObjcopy(const CopyConfig &Config) {
reportError(Config.InputFilename, BinaryOrErr.takeError());
if (Archive *Ar = dyn_cast<Archive>(BinaryOrErr.get().getBinary())) {
- executeElfObjcopyOnArchive(Config, *Ar);
+ executeObjcopyOnArchive(Config, *Ar);
} else {
FileBuffer FB(Config.OutputFilename);
- Binary *Bin = BinaryOrErr.get().getBinary();
- ELFReader Reader(Bin);
- executeElfObjcopyOnBinary(Config, Reader, FB, getOutputElfType(*Bin));
+ executeObjcopyOnBinary(Config, *BinaryOrErr.get().getBinary(), FB);
}
}
@@ -652,5 +694,5 @@ int main(int argc, char **argv) {
else
DriverConfig = parseObjcopyOptions(makeArrayRef(argv + 1, argc));
for (const CopyConfig &CopyConfig : DriverConfig.CopyConfigs)
- executeElfObjcopy(CopyConfig);
+ executeObjcopy(CopyConfig);
}