[llvm] [objcopy] Implement --weaken, --weaken-symbol(s) flags for MachO Object Files (PR #70560)
Dan Zimmerman via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 28 10:48:25 PDT 2023
https://github.com/danzimm created https://github.com/llvm/llvm-project/pull/70560
In a recent legacy codebase I found an invocation of GNU `objconv used to weaken symbols of MachO object files. I tried to replace `objconv` with the corresponding invocation of `llvm-objcopy` and found `--weaken` (and friends) weren't implemented for MachO.
This PR implements those weakening flags for MachO file types.
>From 125fdd42a557f88b561ae1b4592175ebacc38f25 Mon Sep 17 00:00:00 2001
From: danz <dan.zimmerman at adyen.com>
Date: Sat, 28 Oct 2023 11:46:45 -0500
Subject: [PATCH] [objcopy] Implement --weaken, --weaken-symbol(s) flags for
MachO Object Files
---
llvm/lib/ObjCopy/ConfigManager.cpp | 4 +-
llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp | 8 ++
.../tools/llvm-objcopy/MachO/weaken-all.s | 36 ++++++++
llvm/test/tools/llvm-objcopy/MachO/weaken.s | 89 +++++++++++++++++++
4 files changed, 135 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/tools/llvm-objcopy/MachO/weaken-all.s
create mode 100644 llvm/test/tools/llvm-objcopy/MachO/weaken.s
diff --git a/llvm/lib/ObjCopy/ConfigManager.cpp b/llvm/lib/ObjCopy/ConfigManager.cpp
index 5b8e2f5dc2003af..bccb2903e62aeb4 100644
--- a/llvm/lib/ObjCopy/ConfigManager.cpp
+++ b/llvm/lib/ObjCopy/ConfigManager.cpp
@@ -34,13 +34,13 @@ Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
!Common.AllocSectionsPrefix.empty() || !Common.KeepSection.empty() ||
!Common.SymbolsToGlobalize.empty() || !Common.SymbolsToKeep.empty() ||
- !Common.SymbolsToLocalize.empty() || !Common.SymbolsToWeaken.empty() ||
+ !Common.SymbolsToLocalize.empty() ||
!Common.SymbolsToKeepGlobal.empty() || !Common.SectionsToRename.empty() ||
!Common.UnneededSymbolsToRemove.empty() ||
!Common.SetSectionAlignment.empty() || !Common.SetSectionFlags.empty() ||
!Common.SetSectionType.empty() || Common.ExtractDWO ||
Common.PreserveDates || Common.StripAllGNU || Common.StripDWO ||
- Common.StripNonAlloc || Common.StripSections || Common.Weaken ||
+ Common.StripNonAlloc || Common.StripSections ||
Common.DecompressDebugSections || Common.StripUnneeded ||
Common.DiscardMode == DiscardType::Locals || !Common.SymbolsToAdd.empty())
return createStringError(llvm::errc::invalid_argument,
diff --git a/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp
index 9d55c3d8a1a4868..491ec52c100f32c 100644
--- a/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp
+++ b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp
@@ -94,6 +94,14 @@ static void updateAndRemoveSymbols(const CommonConfig &Config,
const MachOConfig &MachOConfig,
Object &Obj) {
for (SymbolEntry &Sym : Obj.SymTable) {
+ // Weaken first to match ELFObjcopy behavior
+ bool IsExportedAndDefined =
+ Sym.n_type & llvm::MachO::N_EXT &&
+ (Sym.n_type & llvm::MachO::N_TYPE) != llvm::MachO::N_UNDF;
+ if (IsExportedAndDefined &&
+ (Config.Weaken || Config.SymbolsToWeaken.matches(Sym.Name)))
+ Sym.n_desc |= llvm::MachO::N_WEAK_DEF;
+
auto I = Config.SymbolsToRename.find(Sym.Name);
if (I != Config.SymbolsToRename.end())
Sym.Name = std::string(I->getValue());
diff --git a/llvm/test/tools/llvm-objcopy/MachO/weaken-all.s b/llvm/test/tools/llvm-objcopy/MachO/weaken-all.s
new file mode 100644
index 000000000000000..740514f311eb5d5
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/MachO/weaken-all.s
@@ -0,0 +1,36 @@
+# REQUIRES: x86-registered-target
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos %s -o %t
+
+# RUN: llvm-objcopy --weaken %t %t2
+# RUN: llvm-readobj --symbols %t2 | FileCheck %s
+
+# CHECK: Symbol {
+# CHECK-NEXT: Name: _foo (1)
+# CHECK-NEXT: Extern
+# CHECK-NEXT: Type: Section (0xE)
+# CHECK-NEXT: Section: __const (0x2)
+# CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+# CHECK-NEXT: Flags [ (0x80)
+# CHECK-NEXT: WeakDef (0x80)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: _func (6)
+# CHECK-NEXT: Extern
+# CHECK-NEXT: Type: Section (0xE)
+# CHECK-NEXT: Section: __text (0x1)
+# CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+# CHECK-NEXT: Flags [ (0x80)
+# CHECK-NEXT: WeakDef (0x80)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: }
+
+.globl _func
+_func:
+
+.section __TEXT,__const
+.globl _foo
+_foo:
diff --git a/llvm/test/tools/llvm-objcopy/MachO/weaken.s b/llvm/test/tools/llvm-objcopy/MachO/weaken.s
new file mode 100644
index 000000000000000..cb2b8672de33558
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/MachO/weaken.s
@@ -0,0 +1,89 @@
+# REQUIRES: x86-registered-target
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos %s -o %t
+
+# RUN: llvm-objcopy -W _func %t %t2
+# RUN: llvm-readobj --symbols %t2 | FileCheck %s -check-prefix=CHECK-1
+
+# CHECK-1: Symbol {
+# CHECK-1-NEXT: Name: _foo (1)
+# CHECK-1-NEXT: Extern
+# CHECK-1-NEXT: Type: Section (0xE)
+# CHECK-1-NEXT: Section: __const (0x2)
+# CHECK-1-NEXT: RefType: UndefinedNonLazy (0x0)
+# CHECK-1-NEXT: Flags [ (0x0)
+# CHECK-1-NEXT: ]
+# CHECK-1-NEXT: Value: 0x0
+# CHECK-1-NEXT: }
+# CHECK-1-NEXT: Symbol {
+# CHECK-1-NEXT: Name: _func (6)
+# CHECK-1-NEXT: Extern
+# CHECK-1-NEXT: Type: Section (0xE)
+# CHECK-1-NEXT: Section: __text (0x1)
+# CHECK-1-NEXT: RefType: UndefinedNonLazy (0x0)
+# CHECK-1-NEXT: Flags [ (0x80)
+# CHECK-1-NEXT: WeakDef (0x80)
+# CHECK-1-NEXT: ]
+# CHECK-1-NEXT: Value: 0x0
+# CHECK-1-NEXT: }
+
+# RUN: echo _foo > %t.rename.txt
+# RUN: echo _func >> %t.rename.txt
+# RUN: llvm-objcopy --weaken-symbols %t.rename.txt %t %t3
+# RUN: llvm-readobj --symbols %t3 | FileCheck %s -check-prefix=CHECK-2
+
+# CHECK-2: Symbol {
+# CHECK-2-NEXT: Name: _foo (1)
+# CHECK-2-NEXT: Extern
+# CHECK-2-NEXT: Type: Section (0xE)
+# CHECK-2-NEXT: Section: __const (0x2)
+# CHECK-2-NEXT: RefType: UndefinedNonLazy (0x0)
+# CHECK-2-NEXT: Flags [ (0x80)
+# CHECK-2-NEXT: WeakDef (0x80)
+# CHECK-2-NEXT: ]
+# CHECK-2-NEXT: Value: 0x0
+# CHECK-2-NEXT: }
+# CHECK-2-NEXT: Symbol {
+# CHECK-2-NEXT: Name: _func (6)
+# CHECK-2-NEXT: Extern
+# CHECK-2-NEXT: Type: Section (0xE)
+# CHECK-2-NEXT: Section: __text (0x1)
+# CHECK-2-NEXT: RefType: UndefinedNonLazy (0x0)
+# CHECK-2-NEXT: Flags [ (0x80)
+# CHECK-2-NEXT: WeakDef (0x80)
+# CHECK-2-NEXT: ]
+# CHECK-2-NEXT: Value: 0x0
+# CHECK-2-NEXT: }
+
+## Verify --weaken-symbol plays nice with --redefine-sym
+# RUN: llvm-objcopy -W _foo --redefine-sym _foo=_bar %t %t4
+# RUN: llvm-readobj --symbols %t4 | FileCheck %s -check-prefix=CHECK-3
+
+# CHECK-3: Symbol {
+# CHECK-3-NEXT: Name: _bar (1)
+# CHECK-3-NEXT: Extern
+# CHECK-3-NEXT: Type: Section (0xE)
+# CHECK-3-NEXT: Section: __const (0x2)
+# CHECK-3-NEXT: RefType: UndefinedNonLazy (0x0)
+# CHECK-3-NEXT: Flags [ (0x80)
+# CHECK-3-NEXT: WeakDef (0x80)
+# CHECK-3-NEXT: ]
+# CHECK-3-NEXT: Value: 0x0
+# CHECK-3-NEXT: }
+# CHECK-3-NEXT: Symbol {
+# CHECK-3-NEXT: Name: _func (6)
+# CHECK-3-NEXT: Extern
+# CHECK-3-NEXT: Type: Section (0xE)
+# CHECK-3-NEXT: Section: __text (0x1)
+# CHECK-3-NEXT: RefType: UndefinedNonLazy (0x0)
+# CHECK-3-NEXT: Flags [ (0x0)
+# CHECK-3-NEXT: ]
+# CHECK-3-NEXT: Value: 0x0
+# CHECK-3-NEXT: }
+
+.globl _func
+_func:
+
+.section __TEXT,__const
+.globl _foo
+_foo:
More information about the llvm-commits
mailing list