[llvm] r362818 - llvm-objcopy: Implement --extract-partition and --extract-main-partition.
Peter Collingbourne via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 7 10:57:48 PDT 2019
Author: pcc
Date: Fri Jun 7 10:57:48 2019
New Revision: 362818
URL: http://llvm.org/viewvc/llvm-project?rev=362818&view=rev
Log:
llvm-objcopy: Implement --extract-partition and --extract-main-partition.
This implements the functionality described in
https://lld.llvm.org/Partitions.html. It works as follows:
- Reads the section headers using the ELF header at file offset 0;
- If extracting a loadable partition:
- Finds the section containing the required partition ELF header by looking it up in the section table;
- Reads the ELF and program headers from the section.
- If extracting the main partition:
- Reads the ELF and program headers from file offset 0.
- Filters the section table according to which sections are in the program headers that it read:
- If ParentSegment != nullptr or section is not SHF_ALLOC, then it goes in.
- Sections containing partition ELF headers or program headers are excluded as there are no headers for these in ordinary ELF files.
Differential Revision: https://reviews.llvm.org/D62364
Added:
llvm/trunk/test/tools/llvm-objcopy/ELF/Inputs/partitions.elf (with props)
llvm/trunk/test/tools/llvm-objcopy/ELF/Inputs/partitions.elf.test
llvm/trunk/test/tools/llvm-objcopy/ELF/partitions.test
Modified:
llvm/trunk/include/llvm/BinaryFormat/ELF.h
llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp
llvm/trunk/tools/llvm-objcopy/CopyConfig.h
llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp
llvm/trunk/tools/llvm-objcopy/ELF/Object.h
llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td
Modified: llvm/trunk/include/llvm/BinaryFormat/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/ELF.h?rev=362818&r1=362817&r2=362818&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/ELF.h (original)
+++ llvm/trunk/include/llvm/BinaryFormat/ELF.h Fri Jun 7 10:57:48 2019
@@ -843,6 +843,8 @@ enum : unsigned {
// for safe ICF.
SHT_LLVM_DEPENDENT_LIBRARIES = 0x6fff4c04, // LLVM Dependent Library Specifiers.
SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification.
+ SHT_LLVM_PART_EHDR = 0x6fff4c06, // ELF header for loadable partition.
+ SHT_LLVM_PART_PHDR = 0x6fff4c07, // Phdrs for loadable partition.
// Android's experimental support for SHT_RELR sections.
// https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512
SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets.
Added: llvm/trunk/test/tools/llvm-objcopy/ELF/Inputs/partitions.elf
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/ELF/Inputs/partitions.elf?rev=362818&view=auto
==============================================================================
Binary file - no diff available.
Propchange: llvm/trunk/test/tools/llvm-objcopy/ELF/Inputs/partitions.elf
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: llvm/trunk/test/tools/llvm-objcopy/ELF/Inputs/partitions.elf.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/ELF/Inputs/partitions.elf.test?rev=362818&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/ELF/Inputs/partitions.elf.test (added)
+++ llvm/trunk/test/tools/llvm-objcopy/ELF/Inputs/partitions.elf.test Fri Jun 7 10:57:48 2019
@@ -0,0 +1,28 @@
+// partitions.elf was generated by running this test in lld:
+
+// REQUIRES: x86
+// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=x86_64-unknown-linux
+// RUN: ld.lld %t.o -o %t --export-dynamic --gc-sections
+
+.section .llvm_sympart.g1,"", at llvm_sympart
+.asciz "part1"
+.quad g1
+
+.section .llvm_sympart.g2,"", at llvm_sympart
+.asciz "part2"
+.quad g2
+
+.section .text0,"ax", at progbits
+.globl _start
+_start:
+ret
+
+.section .bss1,"aw", at nobits
+.globl g1
+g1:
+.zero 8
+
+.section .bss2,"aw", at nobits
+.globl g2
+g2:
+.zero 16
Added: llvm/trunk/test/tools/llvm-objcopy/ELF/partitions.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/ELF/partitions.test?rev=362818&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/ELF/partitions.test (added)
+++ llvm/trunk/test/tools/llvm-objcopy/ELF/partitions.test Fri Jun 7 10:57:48 2019
@@ -0,0 +1,187 @@
+partitions.elf is a file containing a main partition and two loadable
+partitions "part1" and "part2" (see https://lld.llvm.org/Partitions.html
+for a description of partitions). This file tests that extracting the main
+and loadable partitions produces a file with the correct headers and sections.
+
+RUN: llvm-objcopy --extract-main-partition %p/Inputs/partitions.elf %t1
+RUN: llvm-objcopy --extract-partition=part1 %p/Inputs/partitions.elf %t2
+RUN: llvm-objcopy --extract-partition=part2 %p/Inputs/partitions.elf %t3
+
+RUN: llvm-readelf --headers --sections --symbols %t1 | FileCheck --check-prefix=MAIN %s
+RUN: llvm-readelf --headers --sections --symbols %t2 | FileCheck --check-prefix=PART1 %s
+RUN: llvm-readelf --headers --sections --symbols %t3 | FileCheck --check-prefix=PART2 %s
+
+MAIN: ELF Header:
+MAIN-NEXT: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
+MAIN-NEXT: Class: ELF64
+MAIN-NEXT: Data: 2's complement, little endian
+MAIN-NEXT: Version: 1 (current)
+MAIN-NEXT: OS/ABI: UNIX - System V
+MAIN-NEXT: ABI Version: 0x0
+MAIN-NEXT: Type: EXEC (Executable file)
+MAIN-NEXT: Machine: Advanced Micro Devices X86-64
+MAIN-NEXT: Version: 0x1
+MAIN-NEXT: Entry point address: 0x201000
+MAIN-NEXT: Start of program headers: 64 (bytes into file)
+MAIN-NEXT: Start of section headers: 12488 (bytes into file)
+MAIN-NEXT: Flags: 0x0
+MAIN-NEXT: Size of this header: 64 (bytes)
+MAIN-NEXT: Size of program headers: 56 (bytes)
+MAIN-NEXT: Number of program headers: 8
+MAIN-NEXT: Size of section headers: 64 (bytes)
+MAIN-NEXT: Number of section headers: 13
+MAIN-NEXT: Section header string table index: 11
+
+MAIN: Section Headers:
+MAIN-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
+MAIN-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0
+MAIN-NEXT: [ 1] .dynsym DYNSYM 0000000000200200 000200 000030 18 A 4 1 8
+MAIN-NEXT: [ 2] .gnu.hash GNU_HASH 0000000000200230 000230 000020 00 A 1 0 8
+MAIN-NEXT: [ 3] .hash HASH 0000000000200250 000250 000018 04 A 1 0 4
+MAIN-NEXT: [ 4] .dynstr STRTAB 0000000000200268 000268 000014 00 A 0 0 1
+MAIN-NEXT: [ 5] .rodata PROGBITS 000000000020027c 00027c 000018 00 A 0 0 4
+MAIN-NEXT: [ 6] .text0 PROGBITS 0000000000201000 001000 000001 00 AX 0 0 1
+MAIN-NEXT: [ 7] .dynamic DYNAMIC 0000000000202000 002000 000080 10 WA 4 0 8
+MAIN-NEXT: [ 8] .part.end NOBITS 0000000000209000 003000 001000 00 WA 0 0 1
+MAIN-NEXT: [ 9] .comment PROGBITS 0000000000000000 003000 000008 01 MS 0 0 1
+MAIN-NEXT: [10] .symtab SYMTAB 0000000000000000 003008 000048 18 12 2 8
+MAIN-NEXT: [11] .shstrtab STRTAB 0000000000000000 003050 000060 00 0 0 1
+MAIN-NEXT: [12] .strtab STRTAB 0000000000000000 0030b0 000011 00 0 0 1
+
+MAIN: Symbol table '.dynsym' contains 2 entries:
+MAIN-NEXT: Num: Value Size Type Bind Vis Ndx Name
+MAIN-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+MAIN-NEXT: 1: 0000000000201000 0 NOTYPE GLOBAL DEFAULT 6 _start
+
+MAIN: Symbol table '.symtab' contains 3 entries:
+MAIN-NEXT: Num: Value Size Type Bind Vis Ndx Name
+MAIN-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+MAIN-NEXT: 1: 0000000000202000 0 NOTYPE LOCAL HIDDEN 7 _DYNAMIC
+MAIN-NEXT: 2: 0000000000201000 0 NOTYPE GLOBAL DEFAULT 6 _start
+
+MAIN: Program Headers:
+MAIN-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+MAIN-NEXT: PHDR 0x000040 0x0000000000200040 0x0000000000200040 0x0001c0 0x0001c0 R 0x8
+MAIN-NEXT: LOAD 0x000000 0x0000000000200000 0x0000000000200000 0x000294 0x000294 R 0x1000
+MAIN-NEXT: LOAD 0x001000 0x0000000000201000 0x0000000000201000 0x000001 0x000001 R E 0x1000
+MAIN-NEXT: LOAD 0x002000 0x0000000000202000 0x0000000000202000 0x000080 0x000080 RW 0x1000
+MAIN-NEXT: LOAD 0x003000 0x0000000000209000 0x0000000000209000 0x000000 0x001000 RW 0x1000
+MAIN-NEXT: DYNAMIC 0x002000 0x0000000000202000 0x0000000000202000 0x000080 0x000080 RW 0x8
+MAIN-NEXT: GNU_RELRO 0x002000 0x0000000000202000 0x0000000000202000 0x000080 0x001000 R 0x1
+MAIN-NEXT: GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x0
+
+PART1: ELF Header:
+PART1-NEXT: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
+PART1-NEXT: Class: ELF64
+PART1-NEXT: Data: 2's complement, little endian
+PART1-NEXT: Version: 1 (current)
+PART1-NEXT: OS/ABI: UNIX - System V
+PART1-NEXT: ABI Version: 0x0
+PART1-NEXT: Type: DYN (Shared object file)
+PART1-NEXT: Machine: Advanced Micro Devices X86-64
+PART1-NEXT: Version: 0x1
+PART1-NEXT: Entry point address: 0x0
+PART1-NEXT: Start of program headers: 64 (bytes into file)
+PART1-NEXT: Start of section headers: 8336 (bytes into file)
+PART1-NEXT: Flags: 0x0
+PART1-NEXT: Size of this header: 64 (bytes)
+PART1-NEXT: Size of program headers: 56 (bytes)
+PART1-NEXT: Number of program headers: 7
+PART1-NEXT: Size of section headers: 64 (bytes)
+PART1-NEXT: Number of section headers: 11
+PART1-NEXT: Section header string table index: 9
+
+PART1: Section Headers:
+PART1-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
+PART1-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0
+PART1-NEXT: [ 1] .dynsym DYNSYM 00000000002031c8 0001c8 000030 18 A 4 1 8
+PART1-NEXT: [ 2] .gnu.hash GNU_HASH 00000000002031f8 0001f8 000020 00 A 1 0 8
+PART1-NEXT: [ 3] .hash HASH 0000000000203218 000218 000018 04 A 1 0 4
+PART1-NEXT: [ 4] .dynstr STRTAB 0000000000203230 000230 00000a 00 A 0 0 1
+PART1-NEXT: [ 5] .dynamic DYNAMIC 0000000000204000 001000 000090 10 WA 4 0 8
+PART1-NEXT: [ 6] .bss1 NOBITS 0000000000205000 002000 000008 00 WA 0 0 1
+PART1-NEXT: [ 7] .comment PROGBITS 0000000000000000 002000 000008 01 MS 0 0 1
+PART1-NEXT: [ 8] .symtab SYMTAB 0000000000000000 002008 000030 18 10 1 8
+PART1-NEXT: [ 9] .shstrtab STRTAB 0000000000000000 002038 00004d 00 0 0 1
+PART1-NEXT: [10] .strtab STRTAB 0000000000000000 002085 000004 00 0 0 1
+
+PART1: Symbol table '.dynsym' contains 2 entries:
+PART1-NEXT: Num: Value Size Type Bind Vis Ndx Name
+PART1-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+PART1-NEXT: 1: 0000000000205000 0 NOTYPE GLOBAL DEFAULT 15 g1
+
+PART1: Symbol table '.symtab' contains 2 entries:
+PART1-NEXT: Num: Value Size Type Bind Vis Ndx Name
+PART1-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+PART1-NEXT: 1: 0000000000205000 0 NOTYPE GLOBAL DEFAULT 6 g1
+
+PART1: Program Headers:
+PART1-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+PART1-NEXT: PHDR 0x000040 0x0000000000203040 0x0000000000203040 0x000188 0x000188 R 0x1
+PART1-NEXT: LOAD 0x000000 0x0000000000203000 0x0000000000203000 0x00023a 0x00023a R 0x1000
+PART1-NEXT: LOAD 0x001000 0x0000000000204000 0x0000000000204000 0x000090 0x000090 RW 0x1000
+PART1-NEXT: LOAD 0x002000 0x0000000000205000 0x0000000000205000 0x000000 0x000008 RW 0x1000
+PART1-NEXT: DYNAMIC 0x001000 0x0000000000204000 0x0000000000204000 0x000090 0x000090 RW 0x8
+PART1-NEXT: GNU_RELRO 0x001000 0x0000000000204000 0x0000000000204000 0x000090 0x001000 R 0x1
+PART1-NEXT: GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x0
+
+PART2: ELF Header:
+PART2-NEXT: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
+PART2-NEXT: Class: ELF64
+PART2-NEXT: Data: 2's complement, little endian
+PART2-NEXT: Version: 1 (current)
+PART2-NEXT: OS/ABI: UNIX - System V
+PART2-NEXT: ABI Version: 0x0
+PART2-NEXT: Type: DYN (Shared object file)
+PART2-NEXT: Machine: Advanced Micro Devices X86-64
+PART2-NEXT: Version: 0x1
+PART2-NEXT: Entry point address: 0x0
+PART2-NEXT: Start of program headers: 64 (bytes into file)
+PART2-NEXT: Start of section headers: 8336 (bytes into file)
+PART2-NEXT: Flags: 0x0
+PART2-NEXT: Size of this header: 64 (bytes)
+PART2-NEXT: Size of program headers: 56 (bytes)
+PART2-NEXT: Number of program headers: 7
+PART2-NEXT: Size of section headers: 64 (bytes)
+PART2-NEXT: Number of section headers: 11
+PART2-NEXT: Section header string table index: 9
+
+PART2: Section Headers:
+PART2-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
+PART2-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0
+PART2-NEXT: [ 1] .dynsym DYNSYM 00000000002061c8 0001c8 000030 18 A 4 1 8
+PART2-NEXT: [ 2] .gnu.hash GNU_HASH 00000000002061f8 0001f8 000020 00 A 1 0 8
+PART2-NEXT: [ 3] .hash HASH 0000000000206218 000218 000018 04 A 1 0 4
+PART2-NEXT: [ 4] .dynstr STRTAB 0000000000206230 000230 00000a 00 A 0 0 1
+PART2-NEXT: [ 5] .dynamic DYNAMIC 0000000000207000 001000 000090 10 WA 4 0 8
+PART2-NEXT: [ 6] .bss2 NOBITS 0000000000208000 002000 000010 00 WA 0 0 1
+PART2-NEXT: [ 7] .comment PROGBITS 0000000000000000 002000 000008 01 MS 0 0 1
+PART2-NEXT: [ 8] .symtab SYMTAB 0000000000000000 002008 000030 18 10 1 8
+PART2-NEXT: [ 9] .shstrtab STRTAB 0000000000000000 002038 00004d 00 0 0 1
+PART2-NEXT: [10] .strtab STRTAB 0000000000000000 002085 000004 00 0 0 1
+
+PART2: Symbol table '.dynsym' contains 2 entries:
+PART2-NEXT: Num: Value Size Type Bind Vis Ndx Name
+PART2-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+PART2-NEXT: 1: 0000000000208000 0 NOTYPE GLOBAL DEFAULT 23 g2
+
+PART2: Symbol table '.symtab' contains 2 entries:
+PART2-NEXT: Num: Value Size Type Bind Vis Ndx Name
+PART2-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+PART2-NEXT: 1: 0000000000208000 0 NOTYPE GLOBAL DEFAULT 6 g2
+
+PART2: Program Headers:
+PART2-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+PART2-NEXT: PHDR 0x000040 0x0000000000206040 0x0000000000206040 0x000188 0x000188 R 0x1
+PART2-NEXT: LOAD 0x000000 0x0000000000206000 0x0000000000206000 0x00023a 0x00023a R 0x1000
+PART2-NEXT: LOAD 0x001000 0x0000000000207000 0x0000000000207000 0x000090 0x000090 RW 0x1000
+PART2-NEXT: LOAD 0x002000 0x0000000000208000 0x0000000000208000 0x000000 0x000010 RW 0x1000
+PART2-NEXT: DYNAMIC 0x001000 0x0000000000207000 0x0000000000207000 0x000090 0x000090 RW 0x8
+PART2-NEXT: GNU_RELRO 0x001000 0x0000000000207000 0x0000000000207000 0x000090 0x001000 R 0x1
+PART2-NEXT: GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x0
+
+RUN: not llvm-objcopy --extract-partition=part3 %p/Inputs/partitions.elf %t4 2>&1 | FileCheck --check-prefix=ERROR1 %s
+ERROR1: error: could not find partition named 'part3'
+
+RUN: not llvm-objcopy --extract-main-partition --extract-partition=part2 %p/Inputs/partitions.elf %t4 2>&1 | FileCheck --check-prefix=ERROR2 %s
+ERROR2: error: cannot specify --extract-partition together with --extract-main-partition
Modified: llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp?rev=362818&r1=362817&r2=362818&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp (original)
+++ llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp Fri Jun 7 10:57:48 2019
@@ -519,6 +519,8 @@ Expected<DriverConfig> parseObjcopyOptio
Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols);
Config.AllocSectionsPrefix =
InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections);
+ if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition))
+ Config.ExtractPartition = Arg->getValue();
for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
if (!StringRef(Arg->getValue()).contains('='))
@@ -593,6 +595,8 @@ Expected<DriverConfig> parseObjcopyOptio
Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc);
Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded);
Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo);
+ Config.ExtractMainPartition =
+ InputArgs.hasArg(OBJCOPY_extract_main_partition);
Config.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
if (InputArgs.hasArg(OBJCOPY_discard_all, OBJCOPY_discard_locals))
@@ -697,6 +701,11 @@ Expected<DriverConfig> parseObjcopyOptio
errc::invalid_argument,
"LLVM was not compiled with LLVM_ENABLE_ZLIB: cannot decompress");
+ if (Config.ExtractPartition && Config.ExtractMainPartition)
+ return createStringError(errc::invalid_argument,
+ "cannot specify --extract-partition together with "
+ "--extract-main-partition");
+
DC.CopyConfigs.push_back(std::move(Config));
return std::move(DC);
}
Modified: llvm/trunk/tools/llvm-objcopy/CopyConfig.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/CopyConfig.h?rev=362818&r1=362817&r2=362818&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/CopyConfig.h (original)
+++ llvm/trunk/tools/llvm-objcopy/CopyConfig.h Fri Jun 7 10:57:48 2019
@@ -120,6 +120,7 @@ struct CopyConfig {
StringRef BuildIdLinkDir;
Optional<StringRef> BuildIdLinkInput;
Optional<StringRef> BuildIdLinkOutput;
+ Optional<StringRef> ExtractPartition;
StringRef SplitDWO;
StringRef SymbolsPrefix;
StringRef AllocSectionsPrefix;
@@ -155,6 +156,7 @@ struct CopyConfig {
bool AllowBrokenLinks = false;
bool DeterministicArchives = true;
bool ExtractDWO = false;
+ bool ExtractMainPartition = false;
bool KeepFileSymbols = false;
bool LocalizeHidden = false;
bool OnlyKeepDebug = false;
Modified: llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp?rev=362818&r1=362817&r2=362818&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp (original)
+++ llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp Fri Jun 7 10:57:48 2019
@@ -507,6 +507,16 @@ static Error replaceAndRemoveSections(co
return (Sec.Flags & SHF_ALLOC) == 0;
};
+ if (Config.ExtractPartition || Config.ExtractMainPartition) {
+ RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
+ if (RemovePred(Sec))
+ return true;
+ if (Sec.Type == SHT_LLVM_PART_EHDR || Sec.Type == SHT_LLVM_PART_PHDR)
+ return true;
+ return (Sec.Flags & SHF_ALLOC) != 0 && !Sec.ParentSegment;
+ };
+ }
+
// Explicit copies:
if (!Config.OnlySection.empty()) {
RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) {
@@ -747,7 +757,7 @@ Error executeObjcopyOnRawBinary(const Co
Error executeObjcopyOnBinary(const CopyConfig &Config,
object::ELFObjectFileBase &In, Buffer &Out) {
- ELFReader Reader(&In);
+ ELFReader Reader(&In, Config.ExtractPartition);
std::unique_ptr<Object> Obj = Reader.create();
// Prefer OutputArch (-O<format>) if set, otherwise infer it from the input.
const ElfType OutputElfType =
Modified: llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp?rev=362818&r1=362817&r2=362818&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp (original)
+++ llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp Fri Jun 7 10:57:48 2019
@@ -1101,21 +1101,36 @@ template <class ELFT> void ELFBuilder<EL
}
}
-template <class ELFT> void ELFBuilder<ELFT>::readProgramHeaders() {
+template <class ELFT> void ELFBuilder<ELFT>::findEhdrOffset() {
+ if (!ExtractPartition)
+ return;
+
+ for (const SectionBase &Section : Obj.sections()) {
+ if (Section.Type == SHT_LLVM_PART_EHDR &&
+ Section.Name == *ExtractPartition) {
+ EhdrOffset = Section.Offset;
+ return;
+ }
+ }
+ error("could not find partition named '" + *ExtractPartition + "'");
+}
+
+template <class ELFT>
+void ELFBuilder<ELFT>::readProgramHeaders(const ELFFile<ELFT> &HeadersFile) {
uint32_t Index = 0;
- for (const auto &Phdr : unwrapOrError(ElfFile.program_headers())) {
- if (Phdr.p_offset + Phdr.p_filesz > ElfFile.getBufSize())
+ for (const auto &Phdr : unwrapOrError(HeadersFile.program_headers())) {
+ if (Phdr.p_offset + Phdr.p_filesz > HeadersFile.getBufSize())
error("program header with offset 0x" + Twine::utohexstr(Phdr.p_offset) +
" and file size 0x" + Twine::utohexstr(Phdr.p_filesz) +
" goes past the end of the file");
- ArrayRef<uint8_t> Data{ElfFile.base() + Phdr.p_offset,
+ ArrayRef<uint8_t> Data{HeadersFile.base() + Phdr.p_offset,
(size_t)Phdr.p_filesz};
Segment &Seg = Obj.addSegment(Data);
Seg.Type = Phdr.p_type;
Seg.Flags = Phdr.p_flags;
- Seg.OriginalOffset = Phdr.p_offset;
- Seg.Offset = Phdr.p_offset;
+ Seg.OriginalOffset = Phdr.p_offset + EhdrOffset;
+ Seg.Offset = Phdr.p_offset + EhdrOffset;
Seg.VAddr = Phdr.p_vaddr;
Seg.PAddr = Phdr.p_paddr;
Seg.FileSize = Phdr.p_filesz;
@@ -1135,8 +1150,9 @@ template <class ELFT> void ELFBuilder<EL
auto &ElfHdr = Obj.ElfHdrSegment;
ElfHdr.Index = Index++;
+ ElfHdr.OriginalOffset = ElfHdr.Offset = EhdrOffset;
- const auto &Ehdr = *ElfFile.getHeader();
+ const auto &Ehdr = *HeadersFile.getHeader();
auto &PrHdr = Obj.ProgramHdrSegment;
PrHdr.Type = PT_PHDR;
PrHdr.Flags = 0;
@@ -1144,7 +1160,7 @@ template <class ELFT> void ELFBuilder<EL
// Whereas this works automatically for ElfHdr, here OriginalOffset is
// always non-zero and to ensure the equation we assign the same value to
// VAddr as well.
- PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = Ehdr.e_phoff;
+ PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = EhdrOffset + Ehdr.e_phoff;
PrHdr.PAddr = 0;
PrHdr.FileSize = PrHdr.MemSize = Ehdr.e_phentsize * Ehdr.e_phnum;
// The spec requires us to naturally align all the fields.
@@ -1363,7 +1379,9 @@ template <class ELFT> void ELFBuilder<EL
ArrayRef<uint8_t>(ElfFile.base() + Shdr.sh_offset,
(Shdr.sh_type == SHT_NOBITS) ? 0 : Shdr.sh_size);
}
+}
+template <class ELFT> void ELFBuilder<ELFT>::readSections() {
// If a section index table exists we'll need to initialize it before we
// initialize the symbol table because the symbol table might need to
// reference it.
@@ -1397,11 +1415,34 @@ template <class ELFT> void ELFBuilder<EL
initGroupSection(GroupSec);
}
}
+
+ uint32_t ShstrIndex = ElfFile.getHeader()->e_shstrndx;
+ if (ShstrIndex == SHN_XINDEX)
+ ShstrIndex = unwrapOrError(ElfFile.getSection(0))->sh_link;
+
+ if (ShstrIndex == SHN_UNDEF)
+ Obj.HadShdrs = false;
+ else
+ Obj.SectionNames =
+ Obj.sections().template getSectionOfType<StringTableSection>(
+ ShstrIndex,
+ "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
+ " is invalid",
+ "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
+ " is not a string table");
}
template <class ELFT> void ELFBuilder<ELFT>::build() {
- const auto &Ehdr = *ElfFile.getHeader();
+ readSectionHeaders();
+ findEhdrOffset();
+ // The ELFFile whose ELF headers and program headers are copied into the
+ // output file. Normally the same as ElfFile, but if we're extracting a
+ // loadable partition it will point to the partition's headers.
+ ELFFile<ELFT> HeadersFile = unwrapOrError(ELFFile<ELFT>::create(toStringRef(
+ {ElfFile.base() + EhdrOffset, ElfFile.getBufSize() - EhdrOffset})));
+
+ auto &Ehdr = *HeadersFile.getHeader();
Obj.OSABI = Ehdr.e_ident[EI_OSABI];
Obj.ABIVersion = Ehdr.e_ident[EI_ABIVERSION];
Obj.Type = Ehdr.e_type;
@@ -1410,23 +1451,8 @@ template <class ELFT> void ELFBuilder<EL
Obj.Entry = Ehdr.e_entry;
Obj.Flags = Ehdr.e_flags;
- readSectionHeaders();
- readProgramHeaders();
-
- uint32_t ShstrIndex = Ehdr.e_shstrndx;
- if (ShstrIndex == SHN_XINDEX)
- ShstrIndex = unwrapOrError(ElfFile.getSection(0))->sh_link;
-
- if (ShstrIndex == SHN_UNDEF)
- Obj.HadShdrs = false;
- else
- Obj.SectionNames =
- Obj.sections().template getSectionOfType<StringTableSection>(
- ShstrIndex,
- "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
- " in elf header is invalid",
- "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
- " in elf header is not a string table");
+ readSections();
+ readProgramHeaders(HeadersFile);
}
Writer::~Writer() {}
@@ -1440,19 +1466,19 @@ std::unique_ptr<Object> BinaryReader::cr
std::unique_ptr<Object> ELFReader::create() const {
auto Obj = llvm::make_unique<Object>();
if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(Bin)) {
- ELFBuilder<ELF32LE> Builder(*O, *Obj);
+ ELFBuilder<ELF32LE> Builder(*O, *Obj, ExtractPartition);
Builder.build();
return Obj;
} else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(Bin)) {
- ELFBuilder<ELF64LE> Builder(*O, *Obj);
+ ELFBuilder<ELF64LE> Builder(*O, *Obj, ExtractPartition);
Builder.build();
return Obj;
} else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(Bin)) {
- ELFBuilder<ELF32BE> Builder(*O, *Obj);
+ ELFBuilder<ELF32BE> Builder(*O, *Obj, ExtractPartition);
Builder.build();
return Obj;
} else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Bin)) {
- ELFBuilder<ELF64BE> Builder(*O, *Obj);
+ ELFBuilder<ELF64BE> Builder(*O, *Obj, ExtractPartition);
Builder.build();
return Obj;
}
@@ -1732,7 +1758,6 @@ template <class ELFT> void ELFWriter<ELF
Segment &ElfHdr = Obj.ElfHdrSegment;
ElfHdr.Type = PT_PHDR;
ElfHdr.Flags = 0;
- ElfHdr.OriginalOffset = ElfHdr.Offset = 0;
ElfHdr.VAddr = 0;
ElfHdr.PAddr = 0;
ElfHdr.FileSize = ElfHdr.MemSize = sizeof(Elf_Ehdr);
Modified: llvm/trunk/tools/llvm-objcopy/ELF/Object.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/ELF/Object.h?rev=362818&r1=362817&r2=362818&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/ELF/Object.h (original)
+++ llvm/trunk/tools/llvm-objcopy/ELF/Object.h Fri Jun 7 10:57:48 2019
@@ -889,17 +889,23 @@ private:
const ELFFile<ELFT> &ElfFile;
Object &Obj;
+ uint64_t EhdrOffset = 0;
+ Optional<StringRef> ExtractPartition;
void setParentSegment(Segment &Child);
- void readProgramHeaders();
+ void readProgramHeaders(const ELFFile<ELFT> &HeadersFile);
void initGroupSection(GroupSection *GroupSec);
void initSymbolTable(SymbolTableSection *SymTab);
void readSectionHeaders();
+ void readSections();
+ void findEhdrOffset();
SectionBase &makeSection(const Elf_Shdr &Shdr);
public:
- ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj)
- : ElfFile(*ElfObj.getELFFile()), Obj(Obj) {}
+ ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,
+ Optional<StringRef> ExtractPartition)
+ : ElfFile(*ElfObj.getELFFile()), Obj(Obj),
+ ExtractPartition(ExtractPartition) {}
void build();
};
@@ -916,10 +922,12 @@ public:
class ELFReader : public Reader {
Binary *Bin;
+ Optional<StringRef> ExtractPartition;
public:
std::unique_ptr<Object> create() const override;
- explicit ELFReader(Binary *B) : Bin(B) {}
+ explicit ELFReader(Binary *B, Optional<StringRef> ExtractPartition)
+ : Bin(B), ExtractPartition(ExtractPartition) {}
};
class Object {
Modified: llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td?rev=362818&r1=362817&r2=362818&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td (original)
+++ llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td Fri Jun 7 10:57:48 2019
@@ -145,6 +145,13 @@ def extract_dwo
HelpText<
"Remove all sections that are not DWARF .dwo sections from file">;
+defm extract_partition
+ : Eq<"extract-partition", "Extract named partition from input file">,
+ MetaVarName<"name">;
+def extract_main_partition
+ : Flag<["--"], "extract-main-partition">,
+ HelpText<"Extract main partition from the input file">;
+
def localize_hidden
: Flag<["--"], "localize-hidden">,
HelpText<
More information about the llvm-commits
mailing list