[llvm] [MachO] Refine alias n_desc flag ownership (name flags from alias, not aliasee) (PR #212001)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 25 02:39:47 PDT 2026


https://github.com/syhhyl updated https://github.com/llvm/llvm-project/pull/212001

>From 7fb418a0f38ce623f95110cc2a844b5644bb996a Mon Sep 17 00:00:00 2001
From: syhhyl <syhhyl926 at 126.com>
Date: Sat, 25 Jul 2026 16:43:28 +0800
Subject: [PATCH] [MachO] Refine alias n_desc flag ownership
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

For alias symbols, n_desc mixes name attributes (N_WEAK_DEF,
N_WEAK_REF, N_ALT_ENTRY, N_NO_DEAD_STRIP — from the alias)
and location attributes (N_ARM_THUMB_DEF, N_COLD_FUNC,
N_SYMBOL_RESOLVER — from the aliasee).

The original fix in #198148 used a full OR of flags, which
preserves the alias weak def but incorrectly propagates the
aliasee weak def to strong aliases in the reverse direction.

Replace the OR with a NameMask that takes name flags from
the alias and location flags from the aliasee.

Assisted-by: opencode
---
 llvm/lib/MC/MachObjectWriter.cpp              | 15 ++--
 llvm/test/CodeGen/AArch64/macho-weak-alias.ll | 73 ++++++++++++++++++-
 2 files changed, 79 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp
index 657f6f40fd9e9..edf4bc3f740e4 100644
--- a/llvm/lib/MC/MachObjectWriter.cpp
+++ b/llvm/lib/MC/MachObjectWriter.cpp
@@ -443,11 +443,16 @@ void MachObjectWriter::writeNlist(MachSymbolData &MSD, const MCAssembler &Asm) {
   // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
   // value.
   bool EncodeAsAltEntry = IsAlias && OrigSymbol.isAltEntry();
-  uint16_t Flags = Symbol->getEncodedFlags(EncodeAsAltEntry);
-  // Preserve the aliasee's flags while adding alias-specific flags,
-  // such as N_WEAK_DEF emitted by .weak_definition.
-  if (IsAlias)
-    Flags |= OrigSymbol.getEncodedFlags(EncodeAsAltEntry);
+  uint16_t Flags;
+  if (!IsAlias) {
+    Flags = Symbol->getEncodedFlags(EncodeAsAltEntry);
+  } else {
+    uint16_t AliaseeFlags = Symbol->getEncodedFlags(false);
+    uint16_t AliasFlags = OrigSymbol.getEncodedFlags(EncodeAsAltEntry);
+    constexpr uint16_t NameMask = MachO::N_WEAK_DEF | MachO::N_WEAK_REF |
+                                  MachO::N_ALT_ENTRY | MachO::N_NO_DEAD_STRIP;
+    Flags = (AliaseeFlags & ~NameMask) | (AliasFlags & NameMask);
+  }
   W.write<uint16_t>(Flags);
   if (is64Bit())
     W.write<uint64_t>(Address);
diff --git a/llvm/test/CodeGen/AArch64/macho-weak-alias.ll b/llvm/test/CodeGen/AArch64/macho-weak-alias.ll
index a936cea618b38..48adcdaf154a0 100644
--- a/llvm/test/CodeGen/AArch64/macho-weak-alias.ll
+++ b/llvm/test/CodeGen/AArch64/macho-weak-alias.ll
@@ -1,17 +1,82 @@
 ; RUN: llc -mtriple=aarch64-apple-macosx13.0.0 -filetype=obj %s -o %t.o
-; RUN: llvm-nm -m %t.o | FileCheck %s
+; RUN: llvm-nm -m %t.o | FileCheck --check-prefix=NM %s
+; RUN: llvm-readobj --symbols %t.o | FileCheck --check-prefix=SYMBOL %s
+
+; llvm.used gives foo_internal N_NO_DEAD_STRIP.
+; Under the name-flag rule, aliases must NOT inherit it.
+ at llvm.used = appending global [1 x ptr] [ptr @foo_internal], section "llvm.metadata"
 
 define internal void @foo_internal() {
   ret void
 }
 
+; Weak alias to internal target: bar sets N_WEAK_DEF, foo has N_NO_DEAD_STRIP.
+; Result: N_WEAK_DEF only (0x80), no N_NO_DEAD_STRIP.
 @foo_default = weak_odr alias void (), ptr @foo_internal
+
+; Weak hidden alias: bar sets N_WEAK_DEF + hidden.
 @foo_hidden = weak_odr hidden alias void (), ptr @foo_internal
 
+; Baseline: ordinary weak hidden definition.
 define weak_odr hidden void @foo_defined() {
   ret void
 }
 
-; CHECK-DAG: weak external _foo_default
-; CHECK-DAG: weak private external _foo_hidden
-; CHECK-DAG: weak private external _foo_defined
+; Weak aliasee target.
+define weak_odr void @foo_weak_aliasee() {
+  ret void
+}
+
+; Strong alias to weak target: bar has no weak, foo has N_WEAK_DEF.
+; Result: no weak flags (0x0).
+ at foo_strong_alias = alias void (), ptr @foo_weak_aliasee
+
+; Auto-hide weak: linkonce_odr unnamed_addr -> emit .weak_def_can_be_hidden.
+; Result: N_WEAK_DEF | N_WEAK_REF (0xC0).
+ at foo_auto = linkonce_odr unnamed_addr alias void (), ptr @foo_internal
+
+; NM-DAG: weak external _foo_default
+; NM-DAG: weak private external _foo_hidden
+; NM-DAG: weak private external _foo_defined
+; NM-DAG: {{^[0-9a-fA-F]+ \(__TEXT,__text\) external _foo_strong_alias$}}
+; NM-DAG: weak external automatically hidden _foo_auto
+; NM-DAG: non-external [no dead strip] _foo_internal
+
+; _foo_internal: N_NO_DEAD_STRIP from llvm.used (0x20).
+; SYMBOL:      Name: _foo_internal
+; SYMBOL-NEXT: Type: Section (0xE)
+; SYMBOL-NEXT: Section: __text
+; SYMBOL-NEXT: RefType: UndefinedNonLazy (0x0)
+; SYMBOL-NEXT: Flags [ (0x20)
+; SYMBOL-NEXT:   NoDeadStrip (0x20)
+; SYMBOL-NEXT: ]
+
+; _foo_auto: 0xC0 = N_WEAK_DEF | N_WEAK_REF.
+; SYMBOL:      Name: _foo_auto
+; SYMBOL-NEXT: Extern
+; SYMBOL-NEXT: Type: Section (0xE)
+; SYMBOL-NEXT: Section: __text
+; SYMBOL-NEXT: RefType: UndefinedNonLazy (0x0)
+; SYMBOL-NEXT: Flags [ (0xC0)
+; SYMBOL-NEXT:   WeakDef (0x80)
+; SYMBOL-NEXT:   WeakRef (0x40)
+; SYMBOL-NEXT: ]
+
+; _foo_default: 0x80 = N_WEAK_DEF, no N_NO_DEAD_STRIP inherited.
+; SYMBOL:      Name: _foo_default
+; SYMBOL-NEXT: Extern
+; SYMBOL-NEXT: Type: Section (0xE)
+; SYMBOL-NEXT: Section: __text
+; SYMBOL-NEXT: RefType: UndefinedNonLazy (0x0)
+; SYMBOL-NEXT: Flags [ (0x80)
+; SYMBOL-NEXT:   WeakDef (0x80)
+; SYMBOL-NEXT: ]
+
+; _foo_strong_alias: 0x0, no weak inherited from foo.
+; SYMBOL:      Name: _foo_strong_alias
+; SYMBOL-NEXT: Extern
+; SYMBOL-NEXT: Type: Section (0xE)
+; SYMBOL-NEXT: Section: __text
+; SYMBOL-NEXT: RefType: UndefinedNonLazy (0x0)
+; SYMBOL-NEXT: Flags [ (0x0)
+; SYMBOL-NEXT: ]



More information about the llvm-commits mailing list