Index: test/tools/llvm-objcopy/dump-section.test =================================================================== --- test/tools/llvm-objcopy/dump-section.test +++ test/tools/llvm-objcopy/dump-section.test @@ -1,9 +1,11 @@ # RUN: yaml2obj %s > %t # RUN: llvm-objcopy -O binary -j .text %t %t2 # RUN: llvm-objcopy -O binary -only-keep .text %t %t3 +# RUN: llvm-objcopy --dump-section .text=%t4 %t %t5 # RUN: od -t x1 %t2 | FileCheck %s # RUN: wc -c %t2 | FileCheck %s --check-prefix=SIZE # RUN: diff %t2 %t3 +# RUN: diff %t4 %t3 !ELF FileHeader: Index: tools/llvm-objcopy/ObjcopyOpts.td =================================================================== --- tools/llvm-objcopy/ObjcopyOpts.td +++ tools/llvm-objcopy/ObjcopyOpts.td @@ -97,3 +97,6 @@ HelpText<"Remove all symbols not needed by relocations">; def keep_file_symbols : Flag<["-", "--"], "keep-file-symbols">, HelpText<"Do not remove file symbols">; +defm dump_section : Eq<"dump-section">, + MetaVarName<"section=file">, + HelpText<"Dump contents of section named
into file ">; Index: tools/llvm-objcopy/Object.h =================================================================== --- tools/llvm-objcopy/Object.h +++ tools/llvm-objcopy/Object.h @@ -612,13 +612,16 @@ void accept(SectionVisitor &Visitor) const override; }; +using object::Binary; + class Reader { public: virtual ~Reader(); virtual std::unique_ptr create() const = 0; + explicit Reader(Binary *B) : Bin(B){}; + Binary *Bin; }; -using object::Binary; using object::ELFFile; using object::ELFObjectFile; using object::OwningBinary; @@ -648,12 +651,11 @@ }; class ELFReader : public Reader { - Binary *Bin; public: ElfType getElfType() const; std::unique_ptr create() const override; - explicit ELFReader(Binary *B) : Bin(B){}; + explicit ELFReader(Binary *B) : Reader(B){}; }; class Object { Index: tools/llvm-objcopy/llvm-objcopy.cpp =================================================================== --- tools/llvm-objcopy/llvm-objcopy.cpp +++ tools/llvm-objcopy/llvm-objcopy.cpp @@ -128,6 +128,7 @@ std::vector Keep; std::vector OnlyKeep; std::vector AddSection; + std::vector DumpSection; std::vector SymbolsToLocalize; std::vector SymbolsToGlobalize; std::vector SymbolsToWeaken; @@ -237,6 +238,42 @@ Writer->write(); } +static Expected getSectionByName(ObjectFile *Obj, + StringRef SecName) { + StringRef SectionName; + for (SectionRef SecRef : Obj->sections()) { + if (std::error_code E = SecRef.getName(SectionName)) + return errorCodeToError(E); + + if (SectionName == SecName) + return SecRef; + } + return createError("section not found"); +} + +static Error dumpSectionToFile(StringRef SecName, StringRef Filename, + Binary *B) { + if (ObjectFile *O = dyn_cast(B)) { + Expected SecRefOrError = getSectionByName(O, SecName); + if (!SecRefOrError) + return SecRefOrError.takeError(); + SectionRef SecRef = *SecRefOrError; + StringRef SecContents; + SecRef.getContents(SecContents); + Expected> BufferOrErr = + FileOutputBuffer::create(Filename, SecContents.size()); + if (!BufferOrErr) + return BufferOrErr.takeError(); + std::unique_ptr Buf = std::move(*BufferOrErr); + std::copy(SecContents.begin(), SecContents.end(), Buf->getBufferStart()); + if (Error E = Buf->commit()) + return E; + return Error::success(); + } + return make_error("File format error", + object_error::parse_failed); +} + // 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" @@ -457,6 +494,16 @@ } } + if (!Config.DumpSection.empty()) { + for (const auto &Flag : Config.DumpSection) { + std::pair SecPair = Flag.split("="); + StringRef SecName = SecPair.first; + StringRef File = SecPair.second; + if (Error E = dumpSectionToFile(SecName, File, Reader.Bin)) + reportError(Config.InputFilename, std::move(E)); + } + } + if (!Config.AddGnuDebugLink.empty()) Obj.addSection(Config.AddGnuDebugLink); } @@ -614,6 +661,8 @@ Config.OnlyKeep.push_back(Arg->getValue()); for (auto Arg : InputArgs.filtered(OBJCOPY_add_section)) Config.AddSection.push_back(Arg->getValue()); + for (auto Arg : InputArgs.filtered(OBJCOPY_dump_section)) + Config.DumpSection.push_back(Arg->getValue()); Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all); Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu); Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug);