mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-02 15:26:29 +00:00
[llvm-objcopy] Add support for --only-keep/-j and --keep
This change adds support for the --only-keep option and the -j alias as well. A common use case for these being used together is to dump a specific section's data. Additionally the --keep option is added (GNU objcopy doesn't have this) to avoid removing a bunch of things. This allows people to err on the side of stripping aggressively and then to keep the specific bits that they need for their application. Differential Revision: https://reviews.llvm.org/D39021 llvm-svn: 319467
This commit is contained in:
parent
aef1dfc690
commit
ef3b80c57b
19
llvm/test/tools/llvm-objcopy/basic-keep.test
Normal file
19
llvm/test/tools/llvm-objcopy/basic-keep.test
Normal file
@ -0,0 +1,19 @@
|
||||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -strip-non-alloc -keep=.test %t %t2
|
||||
# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .test
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ ]
|
||||
|
||||
# CHECK: SectionHeaderCount: 3
|
||||
|
||||
# CHECK: Name: .test
|
||||
# CHECK: Name: .shstrtab
|
23
llvm/test/tools/llvm-objcopy/basic-only-keep.test
Normal file
23
llvm/test/tools/llvm-objcopy/basic-only-keep.test
Normal file
@ -0,0 +1,23 @@
|
||||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -only-keep=.test %t %t2
|
||||
# RUN: llvm-objcopy -j=.test %t %t3
|
||||
# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s
|
||||
# RUN: diff %t2 %t3
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .test
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ ]
|
||||
|
||||
# CHECK: SectionHeaderCount: 5
|
||||
|
||||
# CHECK: Name: .test
|
||||
# CHECK: Name: .symtab
|
||||
# CHECK: Name: .strtab
|
||||
# CHECK: Name: .shstrtab
|
28
llvm/test/tools/llvm-objcopy/dump-section.test
Normal file
28
llvm/test/tools/llvm-objcopy/dump-section.test
Normal file
@ -0,0 +1,28 @@
|
||||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -O binary -j .text %t %t2
|
||||
# RUN: llvm-objcopy -O binary -only-keep .text %t %t3
|
||||
# RUN: od -t x1 %t2 | FileCheck %s
|
||||
# RUN: wc -c %t2 | FileCheck %s --check-prefix=SIZE
|
||||
# RUN: diff %t2 %t3
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
AddressAlign: 0x0000000000001000
|
||||
Content: "DEADBEEF"
|
||||
ProgramHeaders:
|
||||
- Type: PT_LOAD
|
||||
Flags: [ PF_X, PF_R ]
|
||||
Sections:
|
||||
- Section: .text
|
||||
|
||||
#CHECK: 0000000 de ad be ef
|
||||
|
||||
#SIZE: 4
|
21
llvm/test/tools/llvm-objcopy/explicit-keep-remove.test
Normal file
21
llvm/test/tools/llvm-objcopy/explicit-keep-remove.test
Normal file
@ -0,0 +1,21 @@
|
||||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -R=.test -keep=.test %t %t2
|
||||
# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .test
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ ]
|
||||
|
||||
# CHECK: SectionHeaderCount: 5
|
||||
|
||||
# CHECK: Name: .test
|
||||
# CHECK: Name: .symtab
|
||||
# CHECK: Name: .strtab
|
||||
# CHECK: Name: .shstrtab
|
21
llvm/test/tools/llvm-objcopy/explicit-only-keep-remove.test
Normal file
21
llvm/test/tools/llvm-objcopy/explicit-only-keep-remove.test
Normal file
@ -0,0 +1,21 @@
|
||||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -R=.test -only-keep=.test %t %t2
|
||||
# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .test
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ ]
|
||||
|
||||
# CHECK: SectionHeaderCount: 5
|
||||
|
||||
# CHECK: Name: .test
|
||||
# CHECK: Name: .symtab
|
||||
# CHECK: Name: .strtab
|
||||
# CHECK: Name: .shstrtab
|
27
llvm/test/tools/llvm-objcopy/keep-many.test
Normal file
27
llvm/test/tools/llvm-objcopy/keep-many.test
Normal file
@ -0,0 +1,27 @@
|
||||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -strip-non-alloc -keep=.test -keep=.test3 %t %t2
|
||||
# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .test
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ ]
|
||||
- Name: .test2
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ ]
|
||||
- Name: .test3
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ ]
|
||||
|
||||
|
||||
# CHECK: SectionHeaderCount: 4
|
||||
|
||||
# CHECK: Name: .test
|
||||
# CHECK: Name: .test3
|
||||
# CHECK: Name: .shstrtab
|
27
llvm/test/tools/llvm-objcopy/keep-only-keep.test
Normal file
27
llvm/test/tools/llvm-objcopy/keep-only-keep.test
Normal file
@ -0,0 +1,27 @@
|
||||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -keep=.test2 -only-keep=.test %t %t2
|
||||
# RUN: llvm-objcopy -j=.test -keep=.test2 %t %t3
|
||||
# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s
|
||||
# RUN: diff %t2 %t3
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .test
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .test2
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .test3
|
||||
Type: SHT_PROGBITS
|
||||
|
||||
# CHECK: SectionHeaderCount: 6
|
||||
|
||||
# CHECK: Name: .test
|
||||
# CHECK: Name: .test2
|
||||
# CHECK: Name: .symtab
|
||||
# CHECK: Name: .strtab
|
||||
# CHECK: Name: .shstrtab
|
28
llvm/test/tools/llvm-objcopy/only-keep-many.test
Normal file
28
llvm/test/tools/llvm-objcopy/only-keep-many.test
Normal file
@ -0,0 +1,28 @@
|
||||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -j .test1 -j .test2 %t %t2
|
||||
# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .test1
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ ]
|
||||
- Name: .test2
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ ]
|
||||
- Name: .test3
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ ]
|
||||
|
||||
# CHECK: SectionHeaderCount: 6
|
||||
|
||||
# CHECK: Name: .test1
|
||||
# CHECK: Name: .test2
|
||||
# CHECK: Name: .symtab
|
||||
# CHECK: Name: .strtab
|
||||
# CHECK: Name: .shstrtab
|
21
llvm/test/tools/llvm-objcopy/only-keep-remove-strtab.test
Normal file
21
llvm/test/tools/llvm-objcopy/only-keep-remove-strtab.test
Normal file
@ -0,0 +1,21 @@
|
||||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -R .symtab -R .strtab -only-keep=.test %t %t2
|
||||
# RUN: llvm-objcopy -j=.test -R .strtab -R .symtab %t %t3
|
||||
# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s
|
||||
# RUN: diff %t2 %t3
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .test
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ ]
|
||||
|
||||
# CHECK: SectionHeaderCount: 3
|
||||
|
||||
# CHECK: Name: .test
|
||||
# CHECK: Name: .shstrtab
|
19
llvm/test/tools/llvm-objcopy/only-keep-strip-non-alloc.test
Normal file
19
llvm/test/tools/llvm-objcopy/only-keep-strip-non-alloc.test
Normal file
@ -0,0 +1,19 @@
|
||||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -strip-non-alloc -only-keep=.test %t %t2
|
||||
# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .test
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ ]
|
||||
|
||||
# CHECK: SectionHeaderCount: 3
|
||||
|
||||
# CHECK: Name: .test
|
||||
# CHECK: Name: .shstrtab
|
13
llvm/test/tools/llvm-objcopy/strip-sections-keep.test
Normal file
13
llvm/test/tools/llvm-objcopy/strip-sections-keep.test
Normal file
@ -0,0 +1,13 @@
|
||||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -strip-sections -keep=.shstrtab %t %t2
|
||||
# RUN: od -Ax -t c %t2 | FileCheck %s
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
|
||||
# CHECK: \0 . s h s t r t a b \0
|
20
llvm/test/tools/llvm-objcopy/strip-sections-only-keep.test
Normal file
20
llvm/test/tools/llvm-objcopy/strip-sections-only-keep.test
Normal file
@ -0,0 +1,20 @@
|
||||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -strip-sections -only-keep=.test %t %t2
|
||||
# RUN: od -Ax -t x1 %t2 | FileCheck %s
|
||||
# RUN: od -Ax -t c %t2 | FileCheck %s -check-prefix=TEXT
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .test
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ ]
|
||||
Content: "DEADBEEF"
|
||||
|
||||
# CHECK: de ad be ef
|
||||
|
||||
# TEXT-NOT: t e s t
|
@ -196,6 +196,7 @@ public:
|
||||
SectionBase *DefinedIn, uint64_t Value, uint16_t Shndx,
|
||||
uint64_t Sz);
|
||||
void addSymbolNames();
|
||||
const SectionBase *getStrTab() const { return SymbolNames; }
|
||||
const Symbol *getSymbolByIndex(uint32_t Index) const;
|
||||
void removeSectionReferences(const SectionBase *Sec) override;
|
||||
void initialize(SectionTableRef SecTable) override;
|
||||
@ -368,6 +369,7 @@ public:
|
||||
Object(const object::ELFObjectFile<ELFT> &Obj);
|
||||
virtual ~Object() = default;
|
||||
|
||||
const SymbolTableSection *getSymTab() const { return SymbolTable; }
|
||||
const SectionBase *getSectionHeaderStrTab() const { return SectionNames; }
|
||||
void removeSections(std::function<bool(const SectionBase &)> ToRemove);
|
||||
virtual size_t totalSize() const = 0;
|
||||
|
@ -89,6 +89,13 @@ static cl::opt<bool> StripAll(
|
||||
static cl::opt<bool>
|
||||
StripAllGNU("strip-all-gnu",
|
||||
cl::desc("Removes symbol, relocation, and debug information"));
|
||||
static cl::list<std::string> Keep("keep", cl::desc("Keep <section>"),
|
||||
cl::value_desc("section"));
|
||||
static cl::list<std::string> OnlyKeep("only-keep",
|
||||
cl::desc("Remove all but <section>"),
|
||||
cl::value_desc("section"));
|
||||
static cl::alias OnlyKeepA("j", cl::desc("Alias for only-keep"),
|
||||
cl::aliasopt(OnlyKeep));
|
||||
static cl::opt<bool> StripDebug("strip-debug",
|
||||
cl::desc("Removes all debug information"));
|
||||
static cl::opt<bool> StripSections("strip-sections",
|
||||
@ -150,6 +157,13 @@ void SplitDWOToFile(const ELFObjectFile<ELFT> &ObjFile, StringRef File) {
|
||||
WriteObjectFile(DWOFile, File);
|
||||
}
|
||||
|
||||
// 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"
|
||||
// should keep regardless of a remove. Additionally any removal should respect
|
||||
// any previous removals. Lastly whether or not something is removed shouldn't
|
||||
// depend a) on the order the options occur in or b) on some opaque priority
|
||||
// system. The only priority is that keeps/copies overrule removes.
|
||||
template <class ELFT>
|
||||
void CopyBinary(const ELFObjectFile<ELFT> &ObjFile) {
|
||||
std::unique_ptr<Object<ELFT>> Obj;
|
||||
@ -166,6 +180,8 @@ void CopyBinary(const ELFObjectFile<ELFT> &ObjFile) {
|
||||
|
||||
SectionPred RemovePred = [](const SectionBase &) { return false; };
|
||||
|
||||
// Removes:
|
||||
|
||||
if (!ToRemove.empty()) {
|
||||
RemovePred = [&](const SectionBase &Sec) {
|
||||
return std::find(std::begin(ToRemove), std::end(ToRemove), Sec.Name) !=
|
||||
@ -234,6 +250,43 @@ void CopyBinary(const ELFObjectFile<ELFT> &ObjFile) {
|
||||
return (Sec.Flags & SHF_ALLOC) == 0;
|
||||
};
|
||||
|
||||
// Explicit copies:
|
||||
|
||||
if (!OnlyKeep.empty()) {
|
||||
RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
|
||||
// Explicitly keep these sections regardless of previous removes.
|
||||
if (std::find(std::begin(OnlyKeep), std::end(OnlyKeep), Sec.Name) !=
|
||||
std::end(OnlyKeep))
|
||||
return false;
|
||||
|
||||
// Allow all implicit removes.
|
||||
if (RemovePred(Sec)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Keep special sections.
|
||||
if (Obj->getSectionHeaderStrTab() == &Sec) {
|
||||
return false;
|
||||
}
|
||||
if (Obj->getSymTab() == &Sec || Obj->getSymTab()->getStrTab() == &Sec) {
|
||||
return false;
|
||||
}
|
||||
// Remove everything else.
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
if (!Keep.empty()) {
|
||||
RemovePred = [RemovePred](const SectionBase &Sec) {
|
||||
// Explicitly keep these sections regardless of previous removes.
|
||||
if (std::find(std::begin(Keep), std::end(Keep), Sec.Name) !=
|
||||
std::end(Keep))
|
||||
return false;
|
||||
// Otherwise defer to RemovePred.
|
||||
return RemovePred(Sec);
|
||||
};
|
||||
}
|
||||
|
||||
Obj->removeSections(RemovePred);
|
||||
Obj->finalize();
|
||||
WriteObjectFile(*Obj, OutputFilename.getValue());
|
||||
|
Loading…
x
Reference in New Issue
Block a user