Index: llvm/docs/CommandGuide/llvm-objcopy.rst =================================================================== --- llvm/docs/CommandGuide/llvm-objcopy.rst +++ llvm/docs/CommandGuide/llvm-objcopy.rst @@ -318,6 +318,18 @@ 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 Index: llvm/test/tools/llvm-objcopy/ELF/add-symbol-new-symbol-visibility.test =================================================================== --- /dev/null +++ llvm/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 Index: llvm/test/tools/llvm-objcopy/ELF/new-symbol-visibility.test =================================================================== --- /dev/null +++ llvm/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 Index: llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp =================================================================== --- llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp +++ llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp @@ -204,14 +204,14 @@ 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, Index: llvm/tools/llvm-objcopy/CopyConfig.h =================================================================== --- llvm/tools/llvm-objcopy/CopyConfig.h +++ llvm/tools/llvm-objcopy/CopyConfig.h @@ -145,6 +145,7 @@ StringRef SymbolsPrefix; StringRef AllocSectionsPrefix; DiscardType DiscardMode = DiscardType::None; + Optional NewSymbolVisibility; // Repeated options std::vector AddSection; Index: llvm/tools/llvm-objcopy/CopyConfig.cpp =================================================================== --- llvm/tools/llvm-objcopy/CopyConfig.cpp +++ llvm/tools/llvm-objcopy/CopyConfig.cpp @@ -177,7 +177,8 @@ 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 @@ 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 @@ 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 @@ 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); Index: llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp =================================================================== --- llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp @@ -755,7 +755,9 @@ 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 Index: llvm/tools/llvm-objcopy/ELF/Object.h =================================================================== --- llvm/tools/llvm-objcopy/ELF/Object.h +++ llvm/tools/llvm-objcopy/ELF/Object.h @@ -889,11 +889,13 @@ 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 @@ class BinaryReader : public Reader { const MachineInfo &MInfo; MemoryBuffer *MemBuf; + const 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; }; Index: llvm/tools/llvm-objcopy/ELF/Object.cpp =================================================================== --- llvm/tools/llvm-objcopy/ELF/Object.cpp +++ llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -1161,11 +1161,12 @@ 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 @@ 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 { Index: llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp =================================================================== --- llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp +++ llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp @@ -25,10 +25,11 @@ !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 || Index: llvm/tools/llvm-objcopy/ObjcopyOpts.td =================================================================== --- llvm/tools/llvm-objcopy/ObjcopyOpts.td +++ llvm/tools/llvm-objcopy/ObjcopyOpts.td @@ -25,6 +25,11 @@ 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=">,