Index: llvm/docs/CommandGuide/llvm-objcopy.rst =================================================================== --- llvm/docs/CommandGuide/llvm-objcopy.rst +++ llvm/docs/CommandGuide/llvm-objcopy.rst @@ -58,6 +58,18 @@ this to a subset of the local symbols. For example, file and section symbols in ELF objects will not be discarded. +.. option:: --dump-section
= + + Dump the contents of section ``
`` into the file ````. Can be + specified multiple times to dump multiple sections to different files. + ```` is unrelated to the input and output files provided to + :program:`llvm-objcopy` and as such the normal copying and editing + operations will still be performed. No operations are performed on the sections + prior to dumping them. + + For MachO objects, ``
`` must be formatted as + ``,
``. + .. option:: --enable-deterministic-archives, -D Enable deterministic mode when copying archives, i.e. use 0 for archive member @@ -274,15 +286,6 @@ Remove local symbols starting with ".L" from the output. -.. option:: --dump-section
= - - Dump the contents of section ``
`` into the file ````. Can be - specified multiple times to dump multiple sections to different files. - ```` is unrelated to the input and output files provided to - :program:`llvm-objcopy` and as such the normal copying and editing - operations will still be performed. No operations are performed on the sections - prior to dumping them. - .. option:: --extract-dwo Remove all sections that are not DWARF .dwo sections from the output. Index: llvm/test/tools/llvm-objcopy/MachO/dump-section.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-objcopy/MachO/dump-section.test @@ -0,0 +1,82 @@ +## Show that llvm-objcopy extracts section contents into files specified by +## --dump-section. + +# RUN: yaml2obj %s -o %t + +## Extract section contents into files. +# RUN: llvm-objcopy --dump-section __TEXT,__text=%t.dump.text \ +# RUN: --dump-section __DATA,__data=%t.dump.data %t +# RUN: od -t x1 %t.dump.text | FileCheck %s --check-prefix=TEXT-CONTENT +# RUN: wc -c %t.dump.text | FileCheck %s --check-prefix=TEXT-SIZE +# RUN: od -t x1 %t.dump.data | FileCheck %s --check-prefix=DATA-CONTENT +# RUN: wc -c %t.dump.data | FileCheck %s --check-prefix=DATA-SIZE + +# TEXT-CONTENT: 0000000 aa bb cc dd +# TEXT-SIZE: 4 +# DATA-CONTENT: 0000000 ee ff ee ff +# DATA-SIZE: 4 + +## Error case: A non-existent section name. +# RUN: not llvm-objcopy --dump-section __TEXT,__foo=%t.no-such-section %t 2>&1 \ +# RUN: | FileCheck %s -DINPUT=%t --check-prefix=NO-SUCH-SECTION +# NO-SUCH-SECTION: error: '[[INPUT]]': section '__TEXT,__foo' not found + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x00000001 + ncmds: 1 + sizeofcmds: 312 + flags: 0x00002000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 312 + segname: '' + vmaddr: 0 + vmsize: 12 + fileoff: 344 + filesize: 12 + maxprot: 7 + initprot: 7 + nsects: 3 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0000000000000000 + content: 'AABBCCDD' + size: 4 + offset: 344 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x00000000 + reserved2: 0x00000000 + - sectname: __data + segname: __DATA + addr: 0x0000000000000004 + content: 'EEFFEEFF' + size: 4 + offset: 348 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + - sectname: __const + segname: __TEXT + addr: 0x0000000000000008 + content: 'EEFFEEFF' + size: 4 + offset: 352 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 Index: llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp =================================================================== --- llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp +++ llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp @@ -84,16 +84,37 @@ return LC; } +static Error dumpSectionToFile(StringRef SecName, StringRef Filename, + Object &Obj) { + for (LoadCommand &LC : Obj.LoadCommands) + for (Section &Sec : LC.Sections) { + if (Sec.CanonicalName == SecName) { + Expected> BufferOrErr = + FileOutputBuffer::create(Filename, Sec.Content.size()); + if (!BufferOrErr) + return BufferOrErr.takeError(); + std::unique_ptr Buf = std::move(*BufferOrErr); + llvm::copy(Sec.Content, Buf->getBufferStart()); + + if (Error E = Buf->commit()) + return E; + return Error::success(); + } + } + + return createStringError(object_error::parse_failed, "section '%s' not found", + SecName.str().c_str()); +} + static Error handleArgs(const CopyConfig &Config, Object &Obj) { if (Config.AllowBrokenLinks || !Config.BuildIdLinkDir.empty() || Config.BuildIdLinkInput || Config.BuildIdLinkOutput || !Config.SplitDWO.empty() || !Config.SymbolsPrefix.empty() || !Config.AllocSectionsPrefix.empty() || !Config.AddSection.empty() || - !Config.DumpSection.empty() || !Config.KeepSection.empty() || - Config.NewSymbolVisibility || !Config.SymbolsToGlobalize.empty() || - !Config.SymbolsToKeep.empty() || !Config.SymbolsToLocalize.empty() || - !Config.SymbolsToWeaken.empty() || !Config.SymbolsToKeepGlobal.empty() || - !Config.SectionsToRename.empty() || + !Config.KeepSection.empty() || Config.NewSymbolVisibility || + !Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() || + !Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() || + !Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() || !Config.UnneededSymbolsToRemove.empty() || !Config.SetSectionAlignment.empty() || !Config.SetSectionFlags.empty() || Config.ExtractDWO || Config.KeepFileSymbols || Config.LocalizeHidden || @@ -119,6 +140,14 @@ for (Section &Sec : LC.Sections) Sec.Relocations.clear(); + for (const StringRef &Flag : Config.DumpSection) { + std::pair SecPair = Flag.split("="); + StringRef SecName = SecPair.first; + StringRef File = SecPair.second; + if (Error E = dumpSectionToFile(SecName, File, Obj)) + return E; + } + for (StringRef RPath : Config.RPathToAdd) { for (LoadCommand &LC : Obj.LoadCommands) { if (LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_RPATH &&