diff options
author | Alexander Shaposhnikov <shal1t712@gmail.com> | 2018-10-24 22:49:06 +0000 |
---|---|---|
committer | Alexander Shaposhnikov <shal1t712@gmail.com> | 2018-10-24 22:49:06 +0000 |
commit | 654d3a9577d9782b03edaff7be369fa13e9ba14b (patch) | |
tree | 9e0b9e3c233edfc475172a2dc626f8820ade353e /llvm/tools/llvm-objcopy/llvm-objcopy.cpp | |
parent | ad4d018202d7f967c56b6adcfc283f7273b9d356 (diff) | |
download | llvm-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.cpp | 88 |
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); } |