Index: test/tools/llvm-objcopy/keep-global-symbols.test =================================================================== --- /dev/null +++ test/tools/llvm-objcopy/keep-global-symbols.test @@ -0,0 +1,179 @@ +# RUN: yaml2obj %s > %t.o + +# Tests that only global symbols (via -G/--keep-global-symbols) are kept via +# the several different variants of -G/--keep-global-symbol(s). +# +# Most global symbols are kept as global, only Global5 is downgraded to local. +# Global1/Global2: kept via -G/--keep-global-symbol flag +# Global3/Global4: kept via --keep-global-symbols file +# Files exclude comments and trim whitespace. + +# RUN: echo Global2 > %t-globals1.txt +# RUN: echo " Global3 " > %t-globals2.txt +# RUN: echo "Global4 # Global5" >> %t-globals2.txt +# RUN: echo "Global5 Global6" >> %t-globals2.txt +# RUN: echo "Unknown" >> %t-globals2.txt +# RUN: echo " " >> %t-globals2.txt +# RUN: echo "# File with no symbols" > %t-globals3.txt + +# RUN: llvm-objcopy \ +# RUN: -G Global1 \ +# RUN: --keep-global-symbol Global2 \ +# RUN: --keep-global-symbols %t-globals1.txt \ +# RUN: --keep-global-symbols %t-globals2.txt \ +# RUN: -G Local1 \ +# RUN: --globalize-symbol Local2 \ +# RUN: -G Local2 \ +# RUN: -G Weak1 \ +# RUN: --globalize-symbol Weak2 \ +# RUN: -G Weak2 \ +# RUN: %t.o %t.2.o +# RUN: llvm-readobj -symbols %t.2.o | 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 ] +Symbols: + Local: + - Name: Local1 + Section: .text + - Name: Local2 + Section: .text + Weak: + - Name: Weak1 + Section: .text + - Name: Weak2 + Section: .text + - Name: Weak3 + Section: .text + Global: + - Name: Global1 + Section: .text + - Name: Global2 + Section: .text + - Name: Global3 + Section: .text + - Name: Global4 + Section: .text + - Name: Global5 + Section: .text + - Name: Global6 + Section: .text + +# CHECK: Symbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: Local1 +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: Global5 +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: Global6 +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: Weak3 +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: Local2 +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: Global1 +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: Global2 +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: Global3 +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: Global4 +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: Weak1 +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Weak (0x2) +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: Weak2 +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: +# CHECK-NEXT: } +# CHECK-NEXT: ] Index: tools/llvm-objcopy/ObjcopyOpts.td =================================================================== --- tools/llvm-objcopy/ObjcopyOpts.td +++ tools/llvm-objcopy/ObjcopyOpts.td @@ -75,6 +75,22 @@ defm globalize_symbol : Eq<"globalize-symbol">, MetaVarName<"symbol">, HelpText<"Mark as global">; + +defm keep_global_symbol + : Eq<"keep-global-symbol">, + MetaVarName<"symbol">, + HelpText<"Keep only as global. May be repeated to keep several " + "symbols as global.">; +def G : JoinedOrSeparate<[ "-" ], "G">, Alias; + +defm keep_global_symbols + : Eq<"keep-global-symbols">, + MetaVarName<"filename">, + HelpText< + "Keep only symbols in as global. contains one " + "symbol per line and may contain comments beginning with '#'. May be " + "repeated to keep symbols from many files as global.">; + defm weaken_symbol : Eq<"weaken-symbol">, MetaVarName<"symbol">, HelpText<"Mark as weak">; Index: tools/llvm-objcopy/llvm-objcopy.cpp =================================================================== --- tools/llvm-objcopy/llvm-objcopy.cpp +++ tools/llvm-objcopy/llvm-objcopy.cpp @@ -146,6 +146,7 @@ std::vector SymbolsToWeaken; std::vector SymbolsToRemove; std::vector SymbolsToKeep; + std::vector SymbolsToKeepGlobal; StringMap SectionsToRename; StringMap SymbolsToRename; bool StripAll = false; @@ -376,10 +377,23 @@ is_contained(Config.SymbolsToLocalize, Sym.Name))) Sym.Binding = STB_LOCAL; + // Note: these two globalize flags have very similar names but different + // meanings: + // + // --globalize-symbol: promote a symbol to global + // --keep-global-symbol: *only* these symbols should be kept global + // + // If both --globalize-symbol and --keep-global-symbol are specified for + // a given symbol, that symbol will be global in the output file. Because + // of that, make sure to check --globalize-symbol values first. if (!Config.SymbolsToGlobalize.empty() && is_contained(Config.SymbolsToGlobalize, Sym.Name)) Sym.Binding = STB_GLOBAL; + if (!Config.SymbolsToKeepGlobal.empty() && + !is_contained(Config.SymbolsToKeepGlobal, Sym.Name)) + Sym.Binding = STB_LOCAL; + if (!Config.SymbolsToWeaken.empty() && is_contained(Config.SymbolsToWeaken, Sym.Name) && Sym.Binding == STB_GLOBAL) @@ -688,6 +702,23 @@ ExecuteElfObjcopyOnBinary(Config, *BinaryOrErr.get().getBinary(), FB); } +static void addGlobalSymbolsFromFile(std::vector &Symbols, + StringRef Filename) { + SmallVector Lines; + auto BufOrErr = MemoryBuffer::getFile(Filename); + if (!BufOrErr) + reportError(Filename, BufOrErr.getError()); + + BufOrErr.get()->getBuffer().split(Lines, '\n'); + for (StringRef Line : Lines) { + // Ignore everything after '#', trim whitespace, and only add the symbol if + // it's not empty. + auto TrimmedLine = Line.split('#').first.trim(); + if (!TrimmedLine.empty()) + Symbols.push_back(TrimmedLine.str()); + } +} + // ParseObjcopyOptions returns the config and sets the input arguments. If a // help flag is set then ParseObjcopyOptions will print the help messege and // exit. @@ -771,6 +802,10 @@ Config.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols); for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbol)) Config.SymbolsToLocalize.push_back(Arg->getValue()); + for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol)) + Config.SymbolsToKeepGlobal.push_back(Arg->getValue()); + for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols)) + addGlobalSymbolsFromFile(Config.SymbolsToKeepGlobal, Arg->getValue()); for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbol)) Config.SymbolsToGlobalize.push_back(Arg->getValue()); for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))