From 61fef394df456c2b7dcb9fb9ac97755336aa5bca Mon Sep 17 00:00:00 2001 From: Chris Jackson Date: Fri, 30 Aug 2019 10:17:16 +0000 Subject: [PATCH] [llvm-objcopy] Allow the visibility of symbols created by --binary and --add-symbol to be specified with --new-symbol-visibility git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@370458 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/CommandGuide/llvm-objcopy.rst | 12 ++++++++++ .../ELF/add-symbol-new-symbol-visibility.test | 20 ++++++++++++++++ .../ELF/new-symbol-visibility.test | 22 +++++++++++++++++ tools/llvm-objcopy/COFF/COFFObjcopy.cpp | 16 ++++++------- tools/llvm-objcopy/CopyConfig.cpp | 24 +++++++++++++++++-- tools/llvm-objcopy/CopyConfig.h | 1 + tools/llvm-objcopy/ELF/ELFObjcopy.cpp | 4 +++- tools/llvm-objcopy/ELF/Object.cpp | 9 +++---- tools/llvm-objcopy/ELF/Object.h | 12 ++++++---- tools/llvm-objcopy/MachO/MachOObjcopy.cpp | 9 +++---- tools/llvm-objcopy/ObjcopyOpts.td | 5 ++++ 11 files changed, 111 insertions(+), 23 deletions(-) create mode 100644 test/tools/llvm-objcopy/ELF/add-symbol-new-symbol-visibility.test create mode 100644 test/tools/llvm-objcopy/ELF/new-symbol-visibility.test diff --git a/docs/CommandGuide/llvm-objcopy.rst b/docs/CommandGuide/llvm-objcopy.rst index 044293c7e8a..065811c782b 100644 --- a/docs/CommandGuide/llvm-objcopy.rst +++ b/docs/CommandGuide/llvm-objcopy.rst @@ -318,6 +318,18 @@ them. represents a single symbol, with leading and trailing whitespace ignored, as is anything following a '#'. Can be specified multiple times to read names from multiple files. + +.. option:: --new-symbol-visibility + + Specify the visibility of the symbols automatically created when using binary + input or :option:`--add-symbol`. Valid options are: + + - `default` + - `hidden` + - `internal` + - `protected` + + The default is `default`. .. option:: --output-target , -O diff --git a/test/tools/llvm-objcopy/ELF/add-symbol-new-symbol-visibility.test b/test/tools/llvm-objcopy/ELF/add-symbol-new-symbol-visibility.test new file mode 100644 index 00000000000..9ef5849f991 --- /dev/null +++ b/test/tools/llvm-objcopy/ELF/add-symbol-new-symbol-visibility.test @@ -0,0 +1,20 @@ +## Ensure that the visibility of symbols added with --add-symbol can be +## specified with the --new-symbol-visibility switch. + +# RUN: yaml2obj %s -o %t.obj +# RUN: llvm-objcopy --new-symbol-visibility protected --add-symbol symbol_protected=.text:42 \ +# RUN: --add-symbol symbol_hidden=.text:42,hidden %t.obj %t +# RUN: llvm-readelf -s %t | FileCheck %s + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + +# CHECK: PROTECTED {{.*}} symbol_protected +# CHECK: HIDDEN {{.*}} symbol_hidden diff --git a/test/tools/llvm-objcopy/ELF/new-symbol-visibility.test b/test/tools/llvm-objcopy/ELF/new-symbol-visibility.test new file mode 100644 index 00000000000..143a18c0a7e --- /dev/null +++ b/test/tools/llvm-objcopy/ELF/new-symbol-visibility.test @@ -0,0 +1,22 @@ +## Ensure that the visibility of the start, end and size symbols created when +## using binary input can be specified with the --new-symbol-visibility switch. + +# RUN: llvm-objcopy -I binary -B i386:x86-64 %s %t.unspecified +# RUN: llvm-readelf -s %t.unspecified | FileCheck %s --check-prefix=BINARY -DVISIBILITY=DEFAULT +# RUN: llvm-objcopy --new-symbol-visibility default -I binary -B i386:x86-64 %s %t.default +# RUN: llvm-readelf -s %t.default | FileCheck %s --check-prefix=BINARY -DVISIBILITY=DEFAULT +# RUN: llvm-objcopy --new-symbol-visibility hidden -I binary -B i386:x86-64 %s %t.hidden +# RUN: llvm-readelf -s %t.hidden | FileCheck %s --check-prefix=BINARY -DVISIBILITY=HIDDEN +# RUN: llvm-objcopy --new-symbol-visibility protected -I binary -B i386:x86-64 %s %t.protected +# RUN: llvm-readelf -s %t.protected | FileCheck %s --check-prefix=BINARY -DVISIBILITY=PROTECTED +# RUN: llvm-objcopy --new-symbol-visibility internal -I binary -B i386:x86-64 %s %t.internal +# RUN: llvm-readelf -s %t.internal | FileCheck %s --check-prefix=BINARY -DVISIBILITY=INTERNAL + +# BINARY: [[VISIBILITY]] {{.*}} _binary{{.*}}_start +# BINARY-NEXT: [[VISIBILITY]] {{.*}} _binary{{.*}}_end +# BINARY-NEXT: [[VISIBILITY]] {{.*}} _binary{{.*}}_size + +# RUN: not llvm-objcopy --new-symbol-visibility fluff -I binary -B i386:x86-64 %s %t.error 2>&1 \ +# RUN: | FileCheck %s --check-prefix=ERR + +# ERR: error: 'fluff' is not a valid symbol visibility diff --git a/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/tools/llvm-objcopy/COFF/COFFObjcopy.cpp index 55bf69ce85b..28de0eb6efd 100644 --- a/tools/llvm-objcopy/COFF/COFFObjcopy.cpp +++ b/tools/llvm-objcopy/COFF/COFFObjcopy.cpp @@ -204,14 +204,14 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) { Config.BuildIdLinkInput || Config.BuildIdLinkOutput || !Config.SplitDWO.empty() || !Config.SymbolsPrefix.empty() || !Config.AllocSectionsPrefix.empty() || !Config.DumpSection.empty() || - !Config.KeepSection.empty() || !Config.SymbolsToGlobalize.empty() || - !Config.SymbolsToKeep.empty() || !Config.SymbolsToLocalize.empty() || - !Config.SymbolsToWeaken.empty() || !Config.SymbolsToKeepGlobal.empty() || - !Config.SectionsToRename.empty() || !Config.SetSectionFlags.empty() || - !Config.SymbolsToRename.empty() || Config.ExtractDWO || - Config.KeepFileSymbols || Config.LocalizeHidden || Config.PreserveDates || - Config.StripDWO || Config.StripNonAlloc || Config.StripSections || - Config.Weaken || Config.DecompressDebugSections || + !Config.KeepSection.empty() || Config.NewSymbolVisibility || + !Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() || + !Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() || + !Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() || + !Config.SetSectionFlags.empty() || !Config.SymbolsToRename.empty() || + Config.ExtractDWO || Config.KeepFileSymbols || Config.LocalizeHidden || + Config.PreserveDates || Config.StripDWO || Config.StripNonAlloc || + Config.StripSections || Config.Weaken || Config.DecompressDebugSections || Config.DiscardMode == DiscardType::Locals || !Config.SymbolsToAdd.empty() || Config.EntryExpr) { return createStringError(llvm::errc::invalid_argument, diff --git a/tools/llvm-objcopy/CopyConfig.cpp b/tools/llvm-objcopy/CopyConfig.cpp index 2c1dab98c53..9591e5aeb77 100644 --- a/tools/llvm-objcopy/CopyConfig.cpp +++ b/tools/llvm-objcopy/CopyConfig.cpp @@ -177,7 +177,8 @@ parseSetSectionFlagValue(StringRef FlagValue) { return SFU; } -static Expected parseNewSymbolInfo(StringRef FlagValue) { +static Expected parseNewSymbolInfo(StringRef FlagValue, + uint8_t DefaultVisibility) { // Parse value given with --add-symbol option and create the // new symbol if possible. The value format for --add-symbol is: // @@ -222,6 +223,8 @@ static Expected parseNewSymbolInfo(StringRef FlagValue) { return createStringError(errc::invalid_argument, "bad symbol value: '%s'", Flags[0].str().c_str()); + SI.Visibility = DefaultVisibility; + using Functor = std::function; SmallVector UnsupportedFlags; for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I) @@ -488,6 +491,21 @@ Expected parseObjcopyOptions(ArrayRef ArgsArr) { Config.BinaryArch = *MI; } + if (opt::Arg *A = InputArgs.getLastArg(OBJCOPY_new_symbol_visibility)) { + const uint8_t Invalid = 0xff; + Config.NewSymbolVisibility = StringSwitch(A->getValue()) + .Case("default", ELF::STV_DEFAULT) + .Case("hidden", ELF::STV_HIDDEN) + .Case("internal", ELF::STV_INTERNAL) + .Case("protected", ELF::STV_PROTECTED) + .Default(Invalid); + + if (Config.NewSymbolVisibility == Invalid) + return createStringError( + errc::invalid_argument, "'%s' is not a valid symbol visibility", + InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility).str().c_str()); + } + Config.OutputFormat = StringSwitch(OutputFormat) .Case("binary", FileFormat::Binary) .Case("ihex", FileFormat::IHex) @@ -696,7 +714,9 @@ Expected parseObjcopyOptions(ArrayRef ArgsArr) { Arg->getValue(), UseRegex)) return std::move(E); for (auto Arg : InputArgs.filtered(OBJCOPY_add_symbol)) { - Expected NSI = parseNewSymbolInfo(Arg->getValue()); + Expected NSI = parseNewSymbolInfo( + Arg->getValue(), + Config.NewSymbolVisibility.getValueOr(ELF::STV_DEFAULT)); if (!NSI) return NSI.takeError(); Config.SymbolsToAdd.push_back(*NSI); diff --git a/tools/llvm-objcopy/CopyConfig.h b/tools/llvm-objcopy/CopyConfig.h index f7bb587d8e0..e7f293d7fc2 100644 --- a/tools/llvm-objcopy/CopyConfig.h +++ b/tools/llvm-objcopy/CopyConfig.h @@ -145,6 +145,7 @@ struct CopyConfig { StringRef SymbolsPrefix; StringRef AllocSectionsPrefix; DiscardType DiscardMode = DiscardType::None; + Optional NewSymbolVisibility; // Repeated options std::vector AddSection; diff --git a/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/tools/llvm-objcopy/ELF/ELFObjcopy.cpp index bfc2ecaa2c8..07197769996 100644 --- a/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ b/tools/llvm-objcopy/ELF/ELFObjcopy.cpp @@ -755,7 +755,9 @@ Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In, Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In, Buffer &Out) { - BinaryReader Reader(Config.BinaryArch, &In); + uint8_t NewSymbolVisibility = + Config.NewSymbolVisibility.getValueOr(ELF::STV_DEFAULT); + BinaryReader Reader(Config.BinaryArch, &In, NewSymbolVisibility); std::unique_ptr Obj = Reader.create(); // Prefer OutputArch (-O) if set, otherwise fallback to BinaryArch diff --git a/tools/llvm-objcopy/ELF/Object.cpp b/tools/llvm-objcopy/ELF/Object.cpp index 79245aef026..54cddcdd2cd 100644 --- a/tools/llvm-objcopy/ELF/Object.cpp +++ b/tools/llvm-objcopy/ELF/Object.cpp @@ -1161,11 +1161,12 @@ void BinaryELFBuilder::addData(SymbolTableSection *SymTab) { Twine Prefix = Twine("_binary_") + SanitizedFilename; SymTab->addSymbol(Prefix + "_start", STB_GLOBAL, STT_NOTYPE, &DataSection, - /*Value=*/0, STV_DEFAULT, 0, 0); + /*Value=*/0, NewSymbolVisibility, 0, 0); SymTab->addSymbol(Prefix + "_end", STB_GLOBAL, STT_NOTYPE, &DataSection, - /*Value=*/DataSection.Size, STV_DEFAULT, 0, 0); + /*Value=*/DataSection.Size, NewSymbolVisibility, 0, 0); SymTab->addSymbol(Prefix + "_size", STB_GLOBAL, STT_NOTYPE, nullptr, - /*Value=*/DataSection.Size, STV_DEFAULT, SHN_ABS, 0); + /*Value=*/DataSection.Size, NewSymbolVisibility, SHN_ABS, + 0); } std::unique_ptr BinaryELFBuilder::build() { @@ -1610,7 +1611,7 @@ Writer::~Writer() {} Reader::~Reader() {} std::unique_ptr BinaryReader::create() const { - return BinaryELFBuilder(MInfo.EMachine, MemBuf).build(); + return BinaryELFBuilder(MInfo.EMachine, MemBuf, NewSymbolVisibility).build(); } Expected> IHexReader::parse() const { diff --git a/tools/llvm-objcopy/ELF/Object.h b/tools/llvm-objcopy/ELF/Object.h index 42d254c1b2b..42844dae3b4 100644 --- a/tools/llvm-objcopy/ELF/Object.h +++ b/tools/llvm-objcopy/ELF/Object.h @@ -889,11 +889,13 @@ public: class BinaryELFBuilder : public BasicELFBuilder { MemoryBuffer *MemBuf; + uint8_t NewSymbolVisibility; void addData(SymbolTableSection *SymTab); public: - BinaryELFBuilder(uint16_t EM, MemoryBuffer *MB) - : BasicELFBuilder(EM), MemBuf(MB) {} + BinaryELFBuilder(uint16_t EM, MemoryBuffer *MB, uint8_t NewSymbolVisibility) + : BasicELFBuilder(EM), MemBuf(MB), + NewSymbolVisibility(NewSymbolVisibility) {} std::unique_ptr build(); }; @@ -942,10 +944,12 @@ public: class BinaryReader : public Reader { const MachineInfo &MInfo; MemoryBuffer *MemBuf; + uint8_t NewSymbolVisibility; public: - BinaryReader(const MachineInfo &MI, MemoryBuffer *MB) - : MInfo(MI), MemBuf(MB) {} + BinaryReader(const MachineInfo &MI, MemoryBuffer *MB, + const uint8_t NewSymbolVisibility) + : MInfo(MI), MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {} std::unique_ptr create() const override; }; diff --git a/tools/llvm-objcopy/MachO/MachOObjcopy.cpp b/tools/llvm-objcopy/MachO/MachOObjcopy.cpp index c59fa2bd795..a52931e469f 100644 --- a/tools/llvm-objcopy/MachO/MachOObjcopy.cpp +++ b/tools/llvm-objcopy/MachO/MachOObjcopy.cpp @@ -25,10 +25,11 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) { !Config.SplitDWO.empty() || !Config.SymbolsPrefix.empty() || !Config.AllocSectionsPrefix.empty() || !Config.AddSection.empty() || !Config.DumpSection.empty() || !Config.KeepSection.empty() || - !Config.OnlySection.empty() || !Config.SymbolsToGlobalize.empty() || - !Config.SymbolsToKeep.empty() || !Config.SymbolsToLocalize.empty() || - !Config.SymbolsToWeaken.empty() || !Config.SymbolsToKeepGlobal.empty() || - !Config.SectionsToRename.empty() || !Config.SymbolsToRename.empty() || + Config.NewSymbolVisibility || !Config.OnlySection.empty() || + !Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() || + !Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() || + !Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() || + !Config.SymbolsToRename.empty() || !Config.UnneededSymbolsToRemove.empty() || !Config.SetSectionFlags.empty() || !Config.ToRemove.empty() || Config.ExtractDWO || Config.KeepFileSymbols || Config.LocalizeHidden || diff --git a/tools/llvm-objcopy/ObjcopyOpts.td b/tools/llvm-objcopy/ObjcopyOpts.td index 94a4dc8bfb1..55e26fc881e 100644 --- a/tools/llvm-objcopy/ObjcopyOpts.td +++ b/tools/llvm-objcopy/ObjcopyOpts.td @@ -25,6 +25,11 @@ def O : JoinedOrSeparate<["-"], "O">, Alias, HelpText<"Alias for --output-target">; +defm new_symbol_visibility : Eq<"new-symbol-visibility", "Visibility of " + "symbols generated for binary input or added" + " with --add-symbol unless otherwise" + " specified. The default value is 'default'.">; + def compress_debug_sections : Flag<["--"], "compress-debug-sections">; def compress_debug_sections_eq : Joined<["--"], "compress-debug-sections=">, -- 2.40.0