[llvm] [llvm-objcopy] Add llvm-objcopy option --set-visibility-sym (PR #80872)
Ilia Kuklin via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 6 11:21:19 PST 2024
https://github.com/kuilpd updated https://github.com/llvm/llvm-project/pull/80872
>From af5f188a7c4d16f1c9d7c2d8d4785d5a24e9ef00 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Tue, 6 Feb 2024 20:59:40 +0500
Subject: [PATCH 1/2] Add llvm-objcopy option --set-visibility-sym
---
llvm/include/llvm/ObjCopy/ELF/ELFConfig.h | 4 +
llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp | 3 +
.../llvm-objcopy/ELF/set-visibility.test | 139 ++++++++++++++++++
llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 43 ++++++
llvm/tools/llvm-objcopy/ObjcopyOpts.td | 11 ++
5 files changed, 200 insertions(+)
create mode 100644 llvm/test/tools/llvm-objcopy/ELF/set-visibility.test
diff --git a/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h b/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h
index d77cb69b159db..b3efa3205e376 100644
--- a/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h
+++ b/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h
@@ -9,6 +9,7 @@
#ifndef LLVM_OBJCOPY_ELF_ELFCONFIG_H
#define LLVM_OBJCOPY_ELF_ELFCONFIG_H
+#include "llvm/ObjCopy/CommonConfig.h"
#include "llvm/Object/ELFTypes.h"
namespace llvm {
@@ -18,6 +19,9 @@ namespace objcopy {
struct ELFConfig {
uint8_t NewSymbolVisibility = (uint8_t)ELF::STV_DEFAULT;
+ NameMatcher SymbolsToSetVisibility;
+ uint8_t SetVisibilityType = ELF::STV_DEFAULT;
+
// ELF entry point address expression. The input parameter is an entry point
// address in the input ELF file. The entry address in the output file is
// calculated with EntryExpr(input_address), when either --set-start or
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index b6d77d17bae36..b768b7c5d05d7 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -290,6 +290,9 @@ static Error updateAndRemoveSymbols(const CommonConfig &Config,
return Error::success();
Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
+ if (ELFConfig.SymbolsToSetVisibility.matches(Sym.Name) &&
+ Sym.getShndx() != SHN_UNDEF)
+ Sym.Visibility = ELFConfig.SetVisibilityType;
// Common and undefined symbols don't make sense as local symbols, and can
// even cause crashes if we localize those, so skip them.
if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF &&
diff --git a/llvm/test/tools/llvm-objcopy/ELF/set-visibility.test b/llvm/test/tools/llvm-objcopy/ELF/set-visibility.test
new file mode 100644
index 0000000000000..bc1c92021c4fe
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/set-visibility.test
@@ -0,0 +1,139 @@
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo '.*' > %t.symbols.regex
+
+# RUN: cp %t.o %t0.o
+# RUN: llvm-objcopy %t0.o --set-visibility-syms=%t.symbols.regex=default --regex
+# RUN: llvm-readelf -s %t0.o | FileCheck %s --check-prefix=DEF
+# DEF-DAG: LOCAL DEFAULT 1 default_local
+# DEF-DAG: LOCAL DEFAULT 1 internal_local
+# DEF-DAG: LOCAL DEFAULT 1 hidden_local
+# DEF-DAG: LOCAL DEFAULT 1 protected_local
+# DEF-DAG: GLOBAL DEFAULT 1 default_global
+# DEF-DAG: WEAK DEFAULT 1 default_weak
+# DEF-DAG: GLOBAL DEFAULT 1 internal_global
+# DEF-DAG: WEAK DEFAULT 1 internal_weak
+# DEF-DAG: GLOBAL DEFAULT 1 hidden_global
+# DEF-DAG: WEAK DEFAULT 1 hidden_weak
+# DEF-DAG: GLOBAL DEFAULT 1 protected_global
+# DEF-DAG: WEAK DEFAULT 1 protected_weak
+
+# RUN: cp %t.o %t0.o
+# RUN: llvm-objcopy %t0.o --set-visibility-syms=%t.symbols.regex=hidden --regex
+# RUN: llvm-readelf -s %t0.o | FileCheck %s --check-prefix=HID
+# HID-DAG: LOCAL HIDDEN 1 default_local
+# HID-DAG: LOCAL HIDDEN 1 internal_local
+# HID-DAG: LOCAL HIDDEN 1 hidden_local
+# HID-DAG: LOCAL HIDDEN 1 protected_local
+# HID-DAG: GLOBAL HIDDEN 1 default_global
+# HID-DAG: WEAK HIDDEN 1 default_weak
+# HID-DAG: GLOBAL HIDDEN 1 internal_global
+# HID-DAG: WEAK HIDDEN 1 internal_weak
+# HID-DAG: GLOBAL HIDDEN 1 hidden_global
+# HID-DAG: WEAK HIDDEN 1 hidden_weak
+# HID-DAG: GLOBAL HIDDEN 1 protected_global
+# HID-DAG: WEAK HIDDEN 1 protected_weak
+
+# RUN: cp %t.o %t0.o
+# RUN: llvm-objcopy %t0.o --set-visibility-syms=%t.symbols.regex=protected --regex
+# RUN: llvm-readelf -s %t0.o | FileCheck %s --check-prefix=PRO
+# PRO-DAG: LOCAL PROTECTED 1 default_local
+# PRO-DAG: LOCAL PROTECTED 1 internal_local
+# PRO-DAG: LOCAL PROTECTED 1 hidden_local
+# PRO-DAG: LOCAL PROTECTED 1 protected_local
+# PRO-DAG: GLOBAL PROTECTED 1 default_global
+# PRO-DAG: WEAK PROTECTED 1 default_weak
+# PRO-DAG: GLOBAL PROTECTED 1 internal_global
+# PRO-DAG: WEAK PROTECTED 1 internal_weak
+# PRO-DAG: GLOBAL PROTECTED 1 hidden_global
+# PRO-DAG: WEAK PROTECTED 1 hidden_weak
+# PRO-DAG: GLOBAL PROTECTED 1 protected_global
+# PRO-DAG: WEAK PROTECTED 1 protected_weak
+
+# RUN: cp %t.o %t0.o
+# RUN: llvm-objcopy %t0.o --set-visibility-syms=%t.symbols.regex=internal --regex
+# RUN: llvm-readelf -s %t0.o | FileCheck %s --check-prefix=INT
+# INT-DAG: LOCAL INTERNAL 1 default_local
+# INT-DAG: LOCAL INTERNAL 1 internal_local
+# INT-DAG: LOCAL INTERNAL 1 hidden_local
+# INT-DAG: LOCAL INTERNAL 1 protected_local
+# INT-DAG: GLOBAL INTERNAL 1 default_global
+# INT-DAG: WEAK INTERNAL 1 default_weak
+# INT-DAG: GLOBAL INTERNAL 1 internal_global
+# INT-DAG: WEAK INTERNAL 1 internal_weak
+# INT-DAG: GLOBAL INTERNAL 1 hidden_global
+# INT-DAG: WEAK INTERNAL 1 hidden_weak
+# INT-DAG: GLOBAL INTERNAL 1 protected_global
+# INT-DAG: WEAK INTERNAL 1 protected_weak
+
+# RUN: cp %t.o %t0.o
+# RUN: llvm-objcopy %t0.o --set-visibility-sym=hidden_global=default
+# RUN: llvm-objcopy %t0.o --set-visibility-sym=default_global=hidden
+# RUN: llvm-objcopy %t0.o --set-visibility-sym=default_local=protected
+# RUN: llvm-objcopy %t0.o --set-visibility-sym=protected_global=internal
+# RUN: llvm-readelf -s %t0.o | FileCheck %s --check-prefix=SYM
+# SYM-DAG: LOCAL PROTECTED 1 default_local
+# SYM-DAG: GLOBAL HIDDEN 1 default_global
+# SYM-DAG: GLOBAL DEFAULT 1 hidden_global
+# SYM-DAG: GLOBAL INTERNAL 1 protected_global
+
+!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:
+ - Name: default_local
+ Section: .text
+ Binding: STB_LOCAL
+ - Name: default_global
+ Section: .text
+ Binding: STB_GLOBAL
+ - Name: default_weak
+ Section: .text
+ Binding: STB_WEAK
+ - Name: internal_local
+ Section: .text
+ Binding: STB_LOCAL
+ Other: [ STV_INTERNAL ]
+ - Name: internal_global
+ Section: .text
+ Binding: STB_GLOBAL
+ Other: [ STV_INTERNAL ]
+ - Name: internal_weak
+ Section: .text
+ Binding: STB_WEAK
+ Other: [ STV_INTERNAL ]
+ - Name: hidden_local
+ Section: .text
+ Binding: STB_LOCAL
+ Other: [ STV_HIDDEN ]
+ - Name: hidden_global
+ Section: .text
+ Binding: STB_GLOBAL
+ Other: [ STV_HIDDEN ]
+ - Name: hidden_weak
+ Section: .text
+ Binding: STB_WEAK
+ Other: [ STV_HIDDEN ]
+ - Name: protected_local
+ Section: .text
+ Binding: STB_LOCAL
+ Other: [ STV_PROTECTED ]
+ - Name: protected_global
+ Section: .text
+ Binding: STB_GLOBAL
+ Other: [ STV_PROTECTED ]
+ - Name: protected_weak
+ Section: .text
+ Binding: STB_WEAK
+ Other: [ STV_PROTECTED ]
+ - Name: ignored_name
+ Section: .text
+ Binding: STB_GLOBAL
+ Other: [ STV_INTERNAL ]
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index f15307181fad6..9fb7d3997039e 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -254,6 +254,21 @@ parseSetSectionFlagValue(StringRef FlagValue) {
return SFU;
}
+static Expected<uint8_t> parseVisibilityType(StringRef VisType) {
+ const uint8_t Invalid = 0xff;
+ uint8_t type = StringSwitch<uint8_t>(VisType)
+ .Case("default", ELF::STV_DEFAULT)
+ .Case("hidden", ELF::STV_HIDDEN)
+ .Case("internal", ELF::STV_INTERNAL)
+ .Case("protected", ELF::STV_PROTECTED)
+ .Default(Invalid);
+ if (type == Invalid)
+ return createStringError(errc::invalid_argument,
+ "'%s' is not a valid symbol visibility",
+ VisType.str().c_str());
+ return type;
+}
+
namespace {
struct TargetInfo {
FileFormat Format;
@@ -962,6 +977,34 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
Config.SymbolsToAdd.push_back(*SymInfo);
}
+ for (auto *Arg : InputArgs.filtered(OBJCOPY_set_visibility_sym)) {
+ if (!StringRef(Arg->getValue()).contains('='))
+ return createStringError(errc::invalid_argument,
+ "bad format for --set-visibility-sym");
+ auto SymAndVis = StringRef(Arg->getValue()).split('=');
+ Expected<uint8_t> Type = parseVisibilityType(SymAndVis.second);
+ if (!Type)
+ return Type.takeError();
+ ELFConfig.SetVisibilityType = Type.get();
+ if (Error E =
+ ELFConfig.SymbolsToSetVisibility.addMatcher(NameOrPattern::create(
+ SymAndVis.first, SymbolMatchStyle, ErrorCallback)))
+ return std::move(E);
+ }
+ for (auto *Arg : InputArgs.filtered(OBJCOPY_set_visibility_syms)) {
+ if (!StringRef(Arg->getValue()).contains('='))
+ return createStringError(errc::invalid_argument,
+ "bad format for --set-visibility-syms");
+ auto FileAndVis = StringRef(Arg->getValue()).split('=');
+ Expected<uint8_t> Type = parseVisibilityType(FileAndVis.second);
+ if (!Type)
+ return Type.takeError();
+ ELFConfig.SetVisibilityType = Type.get();
+ if (Error E = addSymbolsFromFile(ELFConfig.SymbolsToSetVisibility, DC.Alloc,
+ FileAndVis.first, SymbolMatchStyle,
+ ErrorCallback))
+ return std::move(E);
+ }
ELFConfig.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links);
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
index ead8cd28d3877..d872316df5190 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -93,6 +93,17 @@ defm set_section_type
"Set the type of section <section> to the integer <type>">,
MetaVarName<"section=type">;
+defm set_visibility_sym
+ : Eq<"set-visibility-sym",
+ "Change the visibility of a symbol to the specified type">,
+ MetaVarName<"symbol=visibility_type">;
+defm set_visibility_syms
+ : Eq<"set-visibility-syms",
+ "Reads a list of symbols from <filename> and changes their "
+ "visibility to the specified type. Visibility types: default, "
+ "internal, hidden, protected">,
+ MetaVarName<"filename=visibility_type">;
+
def S : Flag<["-"], "S">,
Alias<strip_all>,
HelpText<"Alias for --strip-all">;
>From cc05728dd3d0b05cffdcc2e1e194b9898d30666f Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Wed, 7 Feb 2024 00:19:24 +0500
Subject: [PATCH 2/2] Change --set-visibility-sym test check order and variable
---
llvm/test/tools/llvm-objcopy/ELF/set-visibility.test | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/test/tools/llvm-objcopy/ELF/set-visibility.test b/llvm/test/tools/llvm-objcopy/ELF/set-visibility.test
index bc1c92021c4fe..008981b0e06c7 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/set-visibility.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/set-visibility.test
@@ -69,12 +69,12 @@
# RUN: cp %t.o %t0.o
# RUN: llvm-objcopy %t0.o --set-visibility-sym=hidden_global=default
# RUN: llvm-objcopy %t0.o --set-visibility-sym=default_global=hidden
-# RUN: llvm-objcopy %t0.o --set-visibility-sym=default_local=protected
+# RUN: llvm-objcopy %t0.o --set-visibility-sym=internal_global=protected
# RUN: llvm-objcopy %t0.o --set-visibility-sym=protected_global=internal
# RUN: llvm-readelf -s %t0.o | FileCheck %s --check-prefix=SYM
-# SYM-DAG: LOCAL PROTECTED 1 default_local
-# SYM-DAG: GLOBAL HIDDEN 1 default_global
# SYM-DAG: GLOBAL DEFAULT 1 hidden_global
+# SYM-DAG: GLOBAL HIDDEN 1 default_global
+# SYM-DAG: GLOBAL PROTECTED 1 internal_global
# SYM-DAG: GLOBAL INTERNAL 1 protected_global
!ELF
More information about the llvm-commits
mailing list