[lld] f5f1fd6 - [lld-macho] Print Objective-C stubs in map files (#225302)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 22 22:40:20 PDT 2026


Author: Kyungwoo Lee
Date: 2026-09-23T05:40:13Z
New Revision: f5f1fd6fc00bdd2ace69100fc5c4a78839f53010

URL: https://github.com/llvm/llvm-project/commit/f5f1fd6fc00bdd2ace69100fc5c4a78839f53010
DIFF: https://github.com/llvm/llvm-project/commit/f5f1fd6fc00bdd2ace69100fc5c4a78839f53010.diff

LOG: [lld-macho] Print Objective-C stubs in map files (#225302)

Match ld-prime by listing synthesized Objective-C message-send stubs in
Mach-O map files, including their final addresses and mode-specific sizes.

Added: 
    

Modified: 
    lld/MachO/MapFile.cpp
    lld/MachO/SyntheticSections.h
    lld/test/MachO/arm64-objc-stubs-dead.s
    lld/test/MachO/arm64-objc-stubs.s
    lld/test/MachO/objc-stubs-order-file.s
    lld/test/MachO/x86-64-objc-stubs.s

Removed: 
    


################################################################################
diff  --git a/lld/MachO/MapFile.cpp b/lld/MachO/MapFile.cpp
index 29ebcdcf9a832..8d65f39afe8f1 100644
--- a/lld/MachO/MapFile.cpp
+++ b/lld/MachO/MapFile.cpp
@@ -141,6 +141,14 @@ static void printStubsEntries(
                  sym->getName().str().data());
 }
 
+// For printing the contents of the __objc_stubs section.
+static void printObjCStubsEntries(raw_fd_ostream &os,
+                                  const ObjCStubsSection *osec) {
+  for (const Defined *sym : osec->getSymbols())
+    os << format("0x%08llX\t0x%08llX\t[  0] ", sym->getVA(), sym->size)
+       << sym->getName() << '\n';
+}
+
 static void printNonLazyPointerSection(raw_fd_ostream &os,
                                        NonLazyPointerSectionBase *osec) {
   // ld64 considers stubs to belong to particular files, but considers GOT
@@ -257,6 +265,8 @@ void macho::writeMapFile() {
                      osec->addr, osec->getSize());
       } else if (osec == in.stubs) {
         printStubsEntries(os, readerToFileOrdinal, osec, target->stubSize);
+      } else if (osec == in.objcStubs) {
+        printObjCStubsEntries(os, in.objcStubs);
       } else if (osec == in.lazyPointers) {
         printStubsEntries(os, readerToFileOrdinal, osec, target->wordSize);
       } else if (osec == in.stubHelper) {

diff  --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h
index 9acbd73d277e8..1b5c4e13f8fa9 100644
--- a/lld/MachO/SyntheticSections.h
+++ b/lld/MachO/SyntheticSections.h
@@ -345,6 +345,7 @@ class ObjCStubsSection final : public SyntheticSection {
   static constexpr llvm::StringLiteral symbolPrefix = "_objc_msgSend$";
   static bool isObjCStubSymbol(Symbol *sym);
   static StringRef getMethname(Symbol *sym);
+  ArrayRef<Defined *> getSymbols() const { return symbols; }
 
   /// Stably sort the stubs by \p priorities and reassign their offsets. Must
   /// run before addresses are assigned.

diff  --git a/lld/test/MachO/arm64-objc-stubs-dead.s b/lld/test/MachO/arm64-objc-stubs-dead.s
index 5dcb171c17eac..2639db073d83a 100644
--- a/lld/test/MachO/arm64-objc-stubs-dead.s
+++ b/lld/test/MachO/arm64-objc-stubs-dead.s
@@ -4,24 +4,32 @@
 
 # RUN: %lld -arch arm64 -lSystem -U _objc_msgSend -o %t.out %t.o
 # RUN: llvm-nm %t.out | FileCheck %s
-# RUN: %lld -arch arm64 -lSystem -U _objc_msgSend -dead_strip -o %t.out %t.o
-# RUN: llvm-nm %t.out | FileCheck %s --check-prefix=DEAD
+# RUN: %lld -arch arm64 -lSystem -U _objc_msgSend -dead_strip -o %t.out %t.o -map %t.map
+# RUN: llvm-nm %t.out | FileCheck %s --check-prefix=DEAD \
+# RUN:   --implicit-check-not=_foo --implicit-check-not='_objc_msgSend$deadsel'
+# RUN: FileCheck %s --check-prefix=DEAD-MAP \
+# RUN:   --implicit-check-not='_objc_msgSend$deadsel' < %t.map
 
 # CHECK: _foo
-# CHECK: _objc_msgSend$length
+# CHECK: _objc_msgSend$deadsel
+# CHECK: _objc_msgSend$livesel
 
-# DEAD-NOT: _foo
-# DEAD-NOT: _objc_msgSend$length
+# DEAD: _objc_msgSend$livesel
+
+# DEAD-MAP: 0x[[#%.8X,OBJC_STUBS:]] 0x00000020 __TEXT __objc_stubs
+# DEAD-MAP-LABEL: # Symbols:
+# DEAD-MAP: 0x[[#OBJC_STUBS]] 0x00000020 [  0] _objc_msgSend$livesel
 
 .section __TEXT,__text
 
 .globl _foo
 _foo:
-  bl  _objc_msgSend$length
+  bl  _objc_msgSend$deadsel
   ret
 
 .globl _main
 _main:
+  bl  _objc_msgSend$livesel
   ret
 
 .subsections_via_symbols

diff  --git a/lld/test/MachO/arm64-objc-stubs.s b/lld/test/MachO/arm64-objc-stubs.s
index da25b1292faa6..53cf3ebc119f8 100644
--- a/lld/test/MachO/arm64-objc-stubs.s
+++ b/lld/test/MachO/arm64-objc-stubs.s
@@ -1,16 +1,18 @@
 # REQUIRES: aarch64
 
 # RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %s -o %t.o
-# RUN: %lld -arch arm64 -lSystem -o %t.out %t.o -U _external_func
+# RUN: %lld -arch arm64 -lSystem -o %t.out %t.o -U _external_func -map %t.map
 # RUN: llvm-otool -vs __TEXT __objc_stubs %t.out | FileCheck %s
+# RUN: FileCheck %s --check-prefix=MAP < %t.map
 # RUN: %lld -arch arm64 -lSystem -o %t.out %t.o -dead_strip -U _external_func
 # RUN: llvm-otool -vs __TEXT __objc_stubs %t.out | FileCheck %s
 # RUN: %lld -arch arm64 -lSystem -o %t.out %t.o -objc_stubs_fast -U _external_func
 # RUN: llvm-otool -vs __TEXT __objc_stubs %t.out | FileCheck %s
 # RUN: llvm-otool -l %t.out | FileCheck %s --check-prefix=FASTALIGN
-# RUN: %lld -arch arm64 -lSystem -o %t.out %t.o -objc_stubs_small -U _external_func
+# RUN: %lld -arch arm64 -lSystem -o %t.out %t.o -objc_stubs_small -U _external_func -map %t.small.map
 # RUN: llvm-otool -vs __TEXT __objc_stubs  %t.out | FileCheck %s --check-prefix=SMALL
 # RUN: llvm-otool -l %t.out | FileCheck %s --check-prefix=SMALLALIGN
+# RUN: FileCheck %s --check-prefix=SMALLMAP < %t.small.map
 # RUN: llvm-objdump --section-headers %t.out | FileCheck %s --check-prefix=SECTIONS
 
 # CHECK: Contents of (__TEXT,__objc_stubs) section
@@ -37,6 +39,16 @@
 
 # CHECK-EMPTY:
 
+# MAP: 0x[[#%.8X,OBJC_STUBS:]] 0x00000040 __TEXT __objc_stubs
+# MAP: # Symbols:
+# MAP-DAG: 0x[[#OBJC_STUBS]] 0x00000020 [  0] _objc_msgSend$foo
+# MAP-DAG: 0x[[#OBJC_STUBS+0x20]] 0x00000020 [  0] _objc_msgSend$length
+
+# SMALLMAP: 0x[[#%.8X,OBJC_STUBS:]] 0x00000018 __TEXT __objc_stubs
+# SMALLMAP: # Symbols:
+# SMALLMAP-DAG: 0x[[#OBJC_STUBS]] 0x0000000C [  0] _objc_msgSend$foo
+# SMALLMAP-DAG: 0x[[#OBJC_STUBS+0xC]] 0x0000000C [  0] _objc_msgSend$length
+
 # FASTALIGN:       sectname __objc_stubs
 # FASTALIGN-NEXT:   segname __TEXT
 # FASTALIGN-NEXT:      addr

diff  --git a/lld/test/MachO/objc-stubs-order-file.s b/lld/test/MachO/objc-stubs-order-file.s
index 66fbaaaf4ea8a..6881bb44b282e 100644
--- a/lld/test/MachO/objc-stubs-order-file.s
+++ b/lld/test/MachO/objc-stubs-order-file.s
@@ -16,9 +16,10 @@
 ## _hot is ordered first, so the stub it calls moves ahead of the others, which
 ## keep their relative order.
 # RUN: %lld -arch arm64 -e _main -U _objc_msgSend -o %t/ordered.out %t/a.o \
-# RUN:   -objc_stubs_small -order_file %t/order
+# RUN:   -objc_stubs_small -order_file %t/order -map %t/ordered.map
 # RUN: llvm-objdump --no-show-raw-insn --section=__TEXT,__objc_stubs --macho \
 # RUN:   %t/ordered.out | FileCheck %s --check-prefix=ORDERED
+# RUN: FileCheck %s --check-prefix=MAP < %t/ordered.map
 
 # RUN: %lld -arch arm64 -e _main -U _objc_msgSend -o %t/fast.out %t/a.o \
 # RUN:   -objc_stubs_fast -order_file %t/order
@@ -47,6 +48,12 @@
 # ORDERED:      _objc_msgSend$cold:
 # ORDERED:      _objc_msgSend$mild:
 
+# MAP: 0x[[#%.8X,OBJC_STUBS:]] 0x00000024 __TEXT __objc_stubs
+# MAP-LABEL: # Symbols:
+# MAP: 0x[[#OBJC_STUBS]] 0x0000000C [  0] _objc_msgSend$hot
+# MAP-NEXT: 0x[[#OBJC_STUBS+0xC]] 0x0000000C [  0] _objc_msgSend$cold
+# MAP-NEXT: 0x[[#OBJC_STUBS+0x18]] 0x0000000C [  0] _objc_msgSend$mild
+
 #--- a.s
 .text
 .globl _cold

diff  --git a/lld/test/MachO/x86-64-objc-stubs.s b/lld/test/MachO/x86-64-objc-stubs.s
index a8bf5de9fe03d..49a1164247f1d 100644
--- a/lld/test/MachO/x86-64-objc-stubs.s
+++ b/lld/test/MachO/x86-64-objc-stubs.s
@@ -1,11 +1,12 @@
 # REQUIRES: x86
 
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
-# RUN: %lld -arch x86_64 -lSystem -o %t.out %t.o
+# RUN: %lld -arch x86_64 -lSystem -o %t.out %t.o -map %t.map
 # RUN: llvm-objdump --macho --section-headers %t.out > %t.txt
 # RUN: llvm-otool -vs __DATA __objc_selrefs %t.out >> %t.txt
 # RUN: llvm-otool -vs __TEXT __objc_stubs %t.out >> %t.txt
 # RUN: FileCheck %s < %t.txt
+# RUN: FileCheck %s --check-prefix=MAP < %t.map
 # RUN: %no-fatal-warnings-lld -arch x86_64 -lSystem -o %t.out %t.o -objc_stubs_small 2>&1 | FileCheck %s --check-prefix=WARNING
 
 # WARNING: warning: -objc_stubs_small is not yet implemented, defaulting to -objc_stubs_fast
@@ -49,6 +50,11 @@
 
 # CHECK-EMPTY:
 
+# MAP: 0x[[#%.8X,OBJC_STUBS:]] 0x0000001A __TEXT __objc_stubs
+# MAP-LABEL: # Symbols:
+# MAP: 0x[[#OBJC_STUBS]] 0x0000000D [  0] _objc_msgSend$foo
+# MAP-NEXT: 0x[[#OBJC_STUBS+0xD]] 0x0000000D [  0] _objc_msgSend$length
+
 .section  __TEXT,__objc_methname,cstring_literals
 lselref1:
   .asciz  "foo"


        


More information about the llvm-commits mailing list