[llvm-objcopy] Fix the behavior of --strip-* and --keep-symbol
If one runs llvm-objcopy --strip-all --keep-symbol foo and the symbol table indeed contains the symbol "foo" then it should not be removed. Test plan: make check-all Differential revision: https://reviews.llvm.org/D47052 llvm-svn: 333008
This commit is contained in:
parent
a6e63f176c
commit
6e7814c484
|
@ -0,0 +1,57 @@
|
|||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy --strip-all --keep-symbol foo %t %t2
|
||||
# RUN: llvm-readobj -sections -symbols %t2 | FileCheck %s
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
Address: 0x1000
|
||||
AddressAlign: 0x0000000000000010
|
||||
Size: 64
|
||||
- Name: .gnu.warning.foo
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .debug_bar
|
||||
Type: SHT_PROGBITS
|
||||
Symbols:
|
||||
Local:
|
||||
- Name: foo
|
||||
Type: STT_FUNC
|
||||
Section: .text
|
||||
Value: 0x1000
|
||||
Size: 8
|
||||
- Name: bar
|
||||
Type: STT_FUNC
|
||||
Section: .text
|
||||
Value: 0x1008
|
||||
Size: 8
|
||||
- Name: baz
|
||||
Type: STT_FUNC
|
||||
Section: .text
|
||||
Value: 0x1010
|
||||
Size: 8
|
||||
|
||||
# CHECK: Name: .text
|
||||
# CHECK: Name: .gnu.warning.foo
|
||||
# CHECK: Name: .symtab
|
||||
# CHECK: Name: .strtab
|
||||
# CHECK: Name: .shstrtab
|
||||
# CHECK-NOT: Name: .debug_bar
|
||||
|
||||
#CHECK: Symbols [
|
||||
#CHECK-NEXT: Symbol {
|
||||
#CHECK-NEXT: Name: foo
|
||||
#CHECK-NEXT: Value: 0x1000
|
||||
#CHECK-NEXT: Size: 8
|
||||
#CHECK-NEXT: Binding: Local
|
||||
#CHECK-NEXT: Type: Function
|
||||
#CHECK-NEXT: Other: 0
|
||||
#CHECK-NEXT: Section: .text
|
||||
#CHECK-NEXT: }
|
||||
#CHECK-NEXT:]
|
|
@ -365,6 +365,7 @@ public:
|
|||
SectionBase *DefinedIn, uint64_t Value, uint8_t Visibility,
|
||||
uint16_t Shndx, uint64_t Sz);
|
||||
void addSymbolNames();
|
||||
bool empty() const { return Symbols.empty(); }
|
||||
const SectionBase *getStrTab() const { return SymbolNames; }
|
||||
const Symbol *getSymbolByIndex(uint32_t Index) const;
|
||||
void updateSymbols(function_ref<void(Symbol &)> Callable);
|
||||
|
|
|
@ -222,6 +222,55 @@ void HandleArgs(const CopyConfig &Config, Object &Obj, const Reader &Reader,
|
|||
if (!Config.SplitDWO.empty()) {
|
||||
SplitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType);
|
||||
}
|
||||
|
||||
// TODO: update or remove symbols only if there is an option that affects them.
|
||||
if (Obj.SymbolTable) {
|
||||
Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
|
||||
if ((Config.LocalizeHidden &&
|
||||
(Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) ||
|
||||
(!Config.SymbolsToLocalize.empty() &&
|
||||
is_contained(Config.SymbolsToLocalize, Sym.Name)))
|
||||
Sym.Binding = STB_LOCAL;
|
||||
|
||||
if (!Config.SymbolsToGlobalize.empty() &&
|
||||
is_contained(Config.SymbolsToGlobalize, Sym.Name))
|
||||
Sym.Binding = STB_GLOBAL;
|
||||
|
||||
if (!Config.SymbolsToWeaken.empty() &&
|
||||
is_contained(Config.SymbolsToWeaken, Sym.Name) &&
|
||||
Sym.Binding == STB_GLOBAL)
|
||||
Sym.Binding = STB_WEAK;
|
||||
|
||||
if (Config.Weaken && Sym.Binding == STB_GLOBAL &&
|
||||
Sym.getShndx() != SHN_UNDEF)
|
||||
Sym.Binding = STB_WEAK;
|
||||
|
||||
const auto I = Config.SymbolsToRename.find(Sym.Name);
|
||||
if (I != Config.SymbolsToRename.end())
|
||||
Sym.Name = I->getValue();
|
||||
});
|
||||
|
||||
Obj.removeSymbols([&](const Symbol &Sym) {
|
||||
if (!Config.SymbolsToKeep.empty() &&
|
||||
is_contained(Config.SymbolsToKeep, Sym.Name))
|
||||
return false;
|
||||
|
||||
if (Config.DiscardAll && Sym.Binding == STB_LOCAL &&
|
||||
Sym.getShndx() != SHN_UNDEF && Sym.Type != STT_FILE &&
|
||||
Sym.Type != STT_SECTION)
|
||||
return true;
|
||||
|
||||
if (Config.StripAll || Config.StripAllGNU)
|
||||
return true;
|
||||
|
||||
if (!Config.SymbolsToRemove.empty() &&
|
||||
is_contained(Config.SymbolsToRemove, Sym.Name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
SectionPred RemovePred = [](const SectionBase &) { return false; };
|
||||
|
||||
|
@ -327,6 +376,19 @@ void HandleArgs(const CopyConfig &Config, Object &Obj, const Reader &Reader,
|
|||
};
|
||||
}
|
||||
|
||||
// This has to be the last predicate assignment.
|
||||
// If the option --keep-symbol has been specified
|
||||
// and at least one of those symbols is present
|
||||
// (equivalently, the updated symbol table is not empty)
|
||||
// the symbol table and the string table should not be removed.
|
||||
if (!Config.SymbolsToKeep.empty() && !Obj.SymbolTable->empty()) {
|
||||
RemovePred = [&Obj, RemovePred](const SectionBase &Sec) {
|
||||
if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab())
|
||||
return false;
|
||||
return RemovePred(Sec);
|
||||
};
|
||||
}
|
||||
|
||||
Obj.removeSections(RemovePred);
|
||||
|
||||
if (!Config.AddSection.empty()) {
|
||||
|
@ -347,51 +409,6 @@ void HandleArgs(const CopyConfig &Config, Object &Obj, const Reader &Reader,
|
|||
|
||||
if (!Config.AddGnuDebugLink.empty())
|
||||
Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink);
|
||||
|
||||
if (Obj.SymbolTable) {
|
||||
Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
|
||||
if ((Config.LocalizeHidden &&
|
||||
(Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) ||
|
||||
(!Config.SymbolsToLocalize.empty() &&
|
||||
is_contained(Config.SymbolsToLocalize, Sym.Name)))
|
||||
Sym.Binding = STB_LOCAL;
|
||||
|
||||
if (!Config.SymbolsToGlobalize.empty() &&
|
||||
is_contained(Config.SymbolsToGlobalize, Sym.Name))
|
||||
Sym.Binding = STB_GLOBAL;
|
||||
|
||||
if (!Config.SymbolsToWeaken.empty() &&
|
||||
is_contained(Config.SymbolsToWeaken, Sym.Name) &&
|
||||
Sym.Binding == STB_GLOBAL)
|
||||
Sym.Binding = STB_WEAK;
|
||||
|
||||
if (Config.Weaken && Sym.Binding == STB_GLOBAL &&
|
||||
Sym.getShndx() != SHN_UNDEF)
|
||||
Sym.Binding = STB_WEAK;
|
||||
|
||||
const auto I = Config.SymbolsToRename.find(Sym.Name);
|
||||
if (I != Config.SymbolsToRename.end())
|
||||
Sym.Name = I->getValue();
|
||||
});
|
||||
|
||||
Obj.removeSymbols([&](const Symbol &Sym) {
|
||||
if (!Config.SymbolsToKeep.empty() &&
|
||||
is_contained(Config.SymbolsToKeep, Sym.Name))
|
||||
return false;
|
||||
|
||||
if (Config.DiscardAll && Sym.Binding == STB_LOCAL &&
|
||||
Sym.getShndx() != SHN_UNDEF && Sym.Type != STT_FILE &&
|
||||
Sym.Type != STT_SECTION)
|
||||
return true;
|
||||
|
||||
if (!Config.SymbolsToRemove.empty() &&
|
||||
is_contained(Config.SymbolsToRemove, Sym.Name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Reader> CreateReader(StringRef InputFilename,
|
||||
|
|
Loading…
Reference in New Issue