diff options
author | Paul Semel <semelpaul@gmail.com> | 2018-08-09 17:05:21 +0000 |
---|---|---|
committer | Paul Semel <semelpaul@gmail.com> | 2018-08-09 17:05:21 +0000 |
commit | 6bbc345f937cf0dd728b197491f393b0d8494899 (patch) | |
tree | 32b7314d705b486444695c0ae697fe5d17cb7bec | |
parent | 5a282e54d073a85f6fca57530343063fc5a74737 (diff) |
[llvm-objcopy] Add --dump-section
Differential Revision: https://reviews.llvm.org/D49979
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@339358 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | test/tools/llvm-objcopy/dump-section.test | 16 | ||||
-rw-r--r-- | tools/llvm-objcopy/ObjcopyOpts.td | 3 | ||||
-rw-r--r-- | tools/llvm-objcopy/Object.cpp | 3 | ||||
-rw-r--r-- | tools/llvm-objcopy/Object.h | 1 | ||||
-rw-r--r-- | tools/llvm-objcopy/llvm-objcopy.cpp | 37 |
5 files changed, 60 insertions, 0 deletions
diff --git a/test/tools/llvm-objcopy/dump-section.test b/test/tools/llvm-objcopy/dump-section.test index 123f4736ca0..cf9accdfd51 100644 --- a/test/tools/llvm-objcopy/dump-section.test +++ b/test/tools/llvm-objcopy/dump-section.test @@ -1,9 +1,14 @@ # 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: llvm-objcopy --dump-section .foo=%t6 %t %t7 +# RUN: not llvm-objcopy --dump-section .bar=%t8 %t %t9 2>&1 | FileCheck %s --check-prefix=NOBITS # RUN: od -t x1 %t2 | FileCheck %s +# RUN: od -t x1 %t6 | FileCheck %s --check-prefix=NON-ALLOC # RUN: wc -c %t2 | FileCheck %s --check-prefix=SIZE # RUN: diff %t2 %t3 +# RUN: diff %t4 %t3 !ELF FileHeader: @@ -17,6 +22,13 @@ Sections: Flags: [ SHF_ALLOC, SHF_EXECINSTR ] AddressAlign: 0x0000000000001000 Content: "DEADBEEF" + - Name: .foo + Type: SHT_PROGBITS + Flags: [ SHF_WRITE ] + Content: "CAFE" + - Name: .bar + Type: SHT_NOBITS + Flags: [ SHF_WRITE ] ProgramHeaders: - Type: PT_LOAD Flags: [ PF_X, PF_R ] @@ -25,4 +37,8 @@ ProgramHeaders: #CHECK: 0000000 de ad be ef +#NON-ALLOC: 0000000 ca fe + #SIZE: 4 + +#NOBITS: Can't dump section ".bar": it has no contents diff --git a/tools/llvm-objcopy/ObjcopyOpts.td b/tools/llvm-objcopy/ObjcopyOpts.td index 8f8a24e8de5..9b872540e91 100644 --- a/tools/llvm-objcopy/ObjcopyOpts.td +++ b/tools/llvm-objcopy/ObjcopyOpts.td @@ -102,3 +102,6 @@ def strip_unneeded : Flag<["-", "--"], "strip-unneeded">, 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 <section> into file <file>">; diff --git a/tools/llvm-objcopy/Object.cpp b/tools/llvm-objcopy/Object.cpp index 0d5dbf759bb..c727c11f91e 100644 --- a/tools/llvm-objcopy/Object.cpp +++ b/tools/llvm-objcopy/Object.cpp @@ -853,6 +853,9 @@ template <class ELFT> void ELFBuilder<ELFT>::readSectionHeaders() { Sec.Align = Shdr.sh_addralign; Sec.EntrySize = Shdr.sh_entsize; Sec.Index = Index++; + Sec.OriginalData = + ArrayRef<uint8_t>(ElfFile.base() + Shdr.sh_offset, + (Shdr.sh_type == SHT_NOBITS) ? 0 : Shdr.sh_size); } // If a section index table exists we'll need to initialize it before we diff --git a/tools/llvm-objcopy/Object.h b/tools/llvm-objcopy/Object.h index 76748d5fc64..ba6aea93505 100644 --- a/tools/llvm-objcopy/Object.h +++ b/tools/llvm-objcopy/Object.h @@ -250,6 +250,7 @@ public: uint64_t Offset = 0; uint64_t Size = 0; uint64_t Type = ELF::SHT_NULL; + ArrayRef<uint8_t> OriginalData; virtual ~SectionBase() = default; diff --git a/tools/llvm-objcopy/llvm-objcopy.cpp b/tools/llvm-objcopy/llvm-objcopy.cpp index edc45ee3611..0c153d521c7 100644 --- a/tools/llvm-objcopy/llvm-objcopy.cpp +++ b/tools/llvm-objcopy/llvm-objcopy.cpp @@ -137,6 +137,7 @@ struct CopyConfig { std::vector<StringRef> Keep; std::vector<StringRef> OnlyKeep; std::vector<StringRef> AddSection; + std::vector<StringRef> DumpSection; std::vector<StringRef> SymbolsToLocalize; std::vector<StringRef> SymbolsToGlobalize; std::vector<StringRef> SymbolsToWeaken; @@ -323,6 +324,30 @@ static void SplitDWOToFile(const CopyConfig &Config, const Reader &Reader, Writer->write(); } +static Error dumpSectionToFile(StringRef SecName, StringRef Filename, + Object &Obj) { + for (auto &Sec : Obj.sections()) { + if (Sec.Name == SecName) { + if (Sec.OriginalData.size() == 0) + return make_error<StringError>("Can't dump section \"" + SecName + + "\": it has no contents", + object_error::parse_failed); + Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr = + FileOutputBuffer::create(Filename, Sec.OriginalData.size()); + if (!BufferOrErr) + return BufferOrErr.takeError(); + std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr); + std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), + Buf->getBufferStart()); + if (Error E = Buf->commit()) + return E; + return Error::success(); + } + } + return make_error<StringError>("Section not found", + 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" @@ -555,6 +580,16 @@ static void HandleArgs(const CopyConfig &Config, Object &Obj, } } + if (!Config.DumpSection.empty()) { + for (const auto &Flag : Config.DumpSection) { + std::pair<StringRef, StringRef> SecPair = Flag.split("="); + StringRef SecName = SecPair.first; + StringRef File = SecPair.second; + if (Error E = dumpSectionToFile(SecName, File, Obj)) + reportError(Config.InputFilename, std::move(E)); + } + } + if (!Config.AddGnuDebugLink.empty()) Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink); } @@ -711,6 +746,8 @@ static CopyConfig ParseObjcopyOptions(ArrayRef<const char *> ArgsArr) { 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); |