From 9280736736d2b1ccfb812b64ccf00bb60548aa6b Mon Sep 17 00:00:00 2001 From: Alexander Shaposhnikov Date: Thu, 26 Apr 2018 18:28:17 +0000 Subject: [PATCH] [llvm-objcopy] Implement --redefine-sym option This diff implements --redefine-sym option for changing the name of a symbol. Test plan: make check-all Differential revision: https://reviews.llvm.org/D46029 llvm-svn: 330973 --- test/tools/llvm-objcopy/redefine-symbol.test | 81 ++++++++++++++++++++ tools/llvm-objcopy/Object.cpp | 12 +-- tools/llvm-objcopy/Object.h | 3 +- tools/llvm-objcopy/Opts.td | 7 +- tools/llvm-objcopy/llvm-objcopy.cpp | 55 ++++++------- 5 files changed, 119 insertions(+), 39 deletions(-) create mode 100644 test/tools/llvm-objcopy/redefine-symbol.test diff --git a/test/tools/llvm-objcopy/redefine-symbol.test b/test/tools/llvm-objcopy/redefine-symbol.test new file mode 100644 index 00000000000..a0600fac83b --- /dev/null +++ b/test/tools/llvm-objcopy/redefine-symbol.test @@ -0,0 +1,81 @@ +# RUN: yaml2obj %s > %t +# RUN: llvm-objcopy --redefine-sym foo=oof --redefine-sym empty= %t %t2 +# RUN: llvm-readobj -symbols %t2 | FileCheck %s +# RUN: not llvm-objcopy --redefine-sym barbar %t %t2 2>&1 | FileCheck %s --check-prefix=BAD-FORMAT +# RUN: not llvm-objcopy --redefine-sym foo=f1 --redefine-sym foo=f2 %t %t2 2>&1 | FileCheck %s --check-prefix=MULTIPLE-REDEFINITION + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x1000 + AddressAlign: 0x0000000000000010 + Content: "0000000000000000" + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x2000 + AddressAlign: 0x0000000000000010 + Content: "0000000000000000" +Symbols: + Global: + - Name: foo + Type: STT_FUNC + Section: .text + Value: 0x1004 + - Name: bar + Type: STT_OBJECT + Section: .data + Value: 0x2000 + Size: 4 + - Name: empty + Type: STT_FUNC + Section: .text + Value: 0x1008 + +#CHECK: Symbols [ +#CHECK-NEXT: Symbol { +#CHECK-NEXT: Name: +#CHECK-NEXT: Value: 0x0 +#CHECK-NEXT: Size: 0 +#CHECK-NEXT: Binding: Local +#CHECK-NEXT: Type: None +#CHECK-NEXT: Other: 0 +#CHECK-NEXT: Section: Undefined +#CHECK-NEXT: } +#CHECK-NEXT: Symbol { +#CHECK-NEXT: Name: oof +#CHECK-NEXT: Value: 0x1004 +#CHECK-NEXT: Size: 0 +#CHECK-NEXT: Binding: Global +#CHECK-NEXT: Type: Function +#CHECK-NEXT: Other: 0 +#CHECK-NEXT: Section: .text +#CHECK-NEXT: } +#CHECK-NEXT: Symbol { +#CHECK-NEXT: Name: bar +#CHECK-NEXT: Value: 0x2000 +#CHECK-NEXT: Size: 4 +#CHECK-NEXT: Binding: Global +#CHECK-NEXT: Type: Object +#CHECK-NEXT: Other: 0 +#CHECK-NEXT: Section: .data +#CHECK-NEXT: } +#CHECK-NEXT: Symbol { +#CHECK-NEXT: Name: +#CHECK-NEXT: Value: 0x1008 +#CHECK-NEXT: Size: 0 +#CHECK-NEXT: Binding: Global +#CHECK-NEXT: Type: Function +#CHECK-NEXT: Other: 0 +#CHECK-NEXT: Section: .text +#CHECK-NEXT: } + +#BAD-FORMAT: Bad format for --redefine-sym +#MULTIPLE-REDEFINITION: Multiple redefinition of symbol foo diff --git a/tools/llvm-objcopy/Object.cpp b/tools/llvm-objcopy/Object.cpp index c7ce2309ffb..07b60367b9e 100644 --- a/tools/llvm-objcopy/Object.cpp +++ b/tools/llvm-objcopy/Object.cpp @@ -202,15 +202,9 @@ void SymbolTableSection::removeSectionReferences(const SectionBase *Sec) { assignIndices(); } -void SymbolTableSection::localize( - std::function ToLocalize) { - for (const auto &Sym : Symbols) { - if (ToLocalize(*Sym)) - Sym->Binding = STB_LOCAL; - } - - // Now that the local symbols aren't grouped at the start we have to reorder - // the symbols to respect this property. +void SymbolTableSection::updateSymbols(function_ref Callable) { + for (auto &Sym : Symbols) + Callable(*Sym); std::stable_partition( std::begin(Symbols), std::end(Symbols), [](const SymPtr &Sym) { return Sym->Binding == STB_LOCAL; }); diff --git a/tools/llvm-objcopy/Object.h b/tools/llvm-objcopy/Object.h index ddc0da16aa4..2598b249a7c 100644 --- a/tools/llvm-objcopy/Object.h +++ b/tools/llvm-objcopy/Object.h @@ -365,8 +365,9 @@ public: void addSymbolNames(); const SectionBase *getStrTab() const { return SymbolNames; } const Symbol *getSymbolByIndex(uint32_t Index) const; + void updateSymbols(function_ref Callable); + void removeSectionReferences(const SectionBase *Sec) override; - void localize(std::function ToLocalize); void initialize(SectionTableRef SecTable) override; void finalize() override; void accept(SectionVisitor &Visitor) const override; diff --git a/tools/llvm-objcopy/Opts.td b/tools/llvm-objcopy/Opts.td index a4d864a7c5b..6e7159559fe 100644 --- a/tools/llvm-objcopy/Opts.td +++ b/tools/llvm-objcopy/Opts.td @@ -27,6 +27,9 @@ defm add_gnu_debuglink : Eq<"add-gnu-debuglink">, defm remove_section : Eq<"remove-section">, MetaVarName<"section">, HelpText<"Remove
">; +defm redefine_symbol : Eq<"redefine-sym">, + MetaVarName<"old=new">, + HelpText<"Change the name of a symbol old to new">; def R : JoinedOrSeparate<["-"], "R">, Alias; defm keep : Eq<"keep">, @@ -57,7 +60,7 @@ def extract_dwo : Flag<["-", "--"], "extract-dwo">, def localize_hidden : Flag<["-", "--"], "localize-hidden">, HelpText<"Mark all symbols that have hidden or internal visibility as local">; defm localize_symbol : Eq<"localize-symbol">, - MetaVarName<"symbol">, - HelpText<"Mark as local">; + MetaVarName<"symbol">, + HelpText<"Mark as local">; def L : JoinedOrSeparate<["-"], "L">, Alias; diff --git a/tools/llvm-objcopy/llvm-objcopy.cpp b/tools/llvm-objcopy/llvm-objcopy.cpp index 7158ceed53f..a4b38cfaf2e 100644 --- a/tools/llvm-objcopy/llvm-objcopy.cpp +++ b/tools/llvm-objcopy/llvm-objcopy.cpp @@ -118,7 +118,8 @@ struct CopyConfig { std::vector Keep; std::vector OnlyKeep; std::vector AddSection; - std::vector LocalizeSymbol; + std::vector SymbolsToLocalize; + StringMap SymbolsToRename; bool StripAll; bool StripAllGNU; bool StripDebug; @@ -130,7 +131,6 @@ struct CopyConfig { }; using SectionPred = std::function; -using SymbolPred = std::function; bool IsDWOSection(const SectionBase &Sec) { return Sec.Name.endswith(".dwo"); } @@ -190,31 +190,9 @@ void HandleArgs(const CopyConfig &Config, Object &Obj, const Reader &Reader, SplitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType); } - SymbolPred LocalizePred = [](const Symbol &) { return false; }; - - // Localize: - - if (Config.LocalizeHidden) { - LocalizePred = [](const Symbol &Sym) { - return Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL; - }; - } - - if (!Config.LocalizeSymbol.empty()) { - LocalizePred = [LocalizePred, &Config](const Symbol &Sym) { - return LocalizePred(Sym) || - std::find(std::begin(Config.LocalizeSymbol), - std::end(Config.LocalizeSymbol), - Sym.Name) != std::end(Config.LocalizeSymbol); - }; - } - - Obj.SymbolTable->localize(LocalizePred); - SectionPred RemovePred = [](const SectionBase &) { return false; }; // Removes: - if (!Config.ToRemove.empty()) { RemovePred = [&Config](const SectionBase &Sec) { return std::find(std::begin(Config.ToRemove), std::end(Config.ToRemove), @@ -283,7 +261,6 @@ void HandleArgs(const CopyConfig &Config, Object &Obj, const Reader &Reader, }; // Explicit copies: - if (!Config.OnlyKeep.empty()) { RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) { // Explicitly keep these sections regardless of previous removes. @@ -335,8 +312,23 @@ void HandleArgs(const CopyConfig &Config, Object &Obj, const Reader &Reader, } } - if (!Config.AddGnuDebugLink.empty()) { + if (!Config.AddGnuDebugLink.empty()) Obj.addSection(Config.AddGnuDebugLink); + + if (Obj.SymbolTable) { + Obj.SymbolTable->updateSymbols([&](Symbol &Sym) { + if ((Config.LocalizeHidden && + (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) || + (!Config.SymbolsToLocalize.empty() && + std::find(std::begin(Config.SymbolsToLocalize), + std::end(Config.SymbolsToLocalize), + Sym.Name) != std::end(Config.SymbolsToLocalize))) + Sym.Binding = STB_LOCAL; + + const auto I = Config.SymbolsToRename.find(Sym.Name); + if (I != Config.SymbolsToRename.end()) + Sym.Name = I->getValue(); + }); } } @@ -397,6 +389,15 @@ CopyConfig ParseObjcopyOptions(ArrayRef ArgsArr) { Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo); Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink); + + for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) { + if (!StringRef(Arg->getValue()).contains('=')) + error("Bad format for --redefine-sym"); + auto Old2New = StringRef(Arg->getValue()).split('='); + if (!Config.SymbolsToRename.insert(Old2New).second) + error("Multiple redefinition of symbol " + Old2New.first); + } + for (auto Arg : InputArgs.filtered(OBJCOPY_remove_section)) Config.ToRemove.push_back(Arg->getValue()); for (auto Arg : InputArgs.filtered(OBJCOPY_keep)) @@ -414,7 +415,7 @@ CopyConfig ParseObjcopyOptions(ArrayRef ArgsArr) { Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo); Config.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden); for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbol)) - Config.LocalizeSymbol.push_back(Arg->getValue()); + Config.SymbolsToLocalize.push_back(Arg->getValue()); return Config; }