[lld] 4e572db - [lld/mac] Mark private externs with GOT relocs as LOCAL in indirect symbtab

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 15 10:24:53 PDT 2021


Author: Nico Weber
Date: 2021-10-15T13:24:47-04:00
New Revision: 4e572db0c2ec4e96f8ddfade7384e8ee8ad97384

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

LOG: [lld/mac] Mark private externs with GOT relocs as LOCAL in indirect symbtab

prepareSymbolRelocation() in Writer.cpp adds both symbols that need binding and
symbols relocated with a pointer relocation to the got.

Pointer relocations are emitted for non-movq GOTPCREL(%rip) loads.  (movqs
become GOT_LOADs so that the linker knows they can be relaxed to leaqs, while
others, such as addq, become just GOT -- a pointer relocation -- since they
can't be relaxed in that way).

For example, this C file produces a private_extern GOT relocation when
compiled with -O2 with clang:

    extern const char kString[];
    const char* g(int a) { return kString + a; }

Linkers need to put pointer-relocated symbols into the GOT, but ld64 marks them
as LOCAL in the indirect symbol table. This matters, since `strip -x` looks at
the indirect symbol table when deciding what to strip.

The indirect symtab emitting code was assuming that only symbols that need
binding are in the GOT, but pointer relocations where there too. Hence, the
code needs to explicitly check if a symbol is a private extern.

Fixes https://crbug.com/1242638, which has some more information in comments 14
and 15. With this patch, the output of `nm -U` on Chromium Framework after
stripping now contains just two symbols when using lld, just like with ld64.

Differential Revision: https://reviews.llvm.org/D111852

Added: 
    

Modified: 
    lld/MachO/SyntheticSections.cpp
    lld/test/MachO/compact-unwind-both-local-and-dylib-personality.s
    lld/test/MachO/indirect-symtab.s

Removed: 
    


################################################################################
diff  --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
index 61fbf7487cc0d..81f9224a1d2ca 100644
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -1104,8 +1104,12 @@ void IndirectSymtabSection::finalizeContents() {
 }
 
 static uint32_t indirectValue(const Symbol *sym) {
-  return sym->symtabIndex != UINT32_MAX ? sym->symtabIndex
-                                        : INDIRECT_SYMBOL_LOCAL;
+  if (sym->symtabIndex == UINT32_MAX)
+    return INDIRECT_SYMBOL_LOCAL;
+  if (auto *defined = dyn_cast<Defined>(sym))
+    if (defined->privateExtern)
+      return INDIRECT_SYMBOL_LOCAL;
+  return sym->symtabIndex;
 }
 
 void IndirectSymtabSection::writeTo(uint8_t *buf) const {

diff  --git a/lld/test/MachO/compact-unwind-both-local-and-dylib-personality.s b/lld/test/MachO/compact-unwind-both-local-and-dylib-personality.s
index a4ef172d7f7c0..933fcd6939166 100644
--- a/lld/test/MachO/compact-unwind-both-local-and-dylib-personality.s
+++ b/lld/test/MachO/compact-unwind-both-local-and-dylib-personality.s
@@ -33,12 +33,13 @@
 # A:      Indirect symbols for (__DATA_CONST,__got)
 # A-NEXT: address                    index name
 # A-DAG:  0x[[#%x,GXX_PERSONALITY_LO:]] [[#]] ___gxx_personality_v0
-# A-DAG:  0x[[#%x,GXX_PERSONALITY_HI:]] [[#]] ___gxx_personality_v0        
+# A-DAG:  0x[[#%x,GXX_PERSONALITY_HI:]] [[#]] ___gxx_personality_v0
 # A-DAG:  0x[[#%x,PERSONALITY_1:]]  LOCAL
 # A-DAG:  0x[[#%x,PERSONALITY_2:]]  LOCAL
 
 # BC:      Indirect symbols for (__DATA_CONST,__got)
 # BC-NEXT: address                    index name
+# BC-DAG:  0x[[#%x,GXX_PERSONALITY_HI:]] LOCAL
 # BC-DAG:  0x[[#%x,GXX_PERSONALITY_LO:]] LOCAL
 # BC-DAG:  0x[[#%x,PERSONALITY_1:]]  LOCAL
 # BC-DAG:  0x[[#%x,PERSONALITY_2:]]  LOCAL

diff  --git a/lld/test/MachO/indirect-symtab.s b/lld/test/MachO/indirect-symtab.s
index 9c64735e5487e..52849ccb87455 100644
--- a/lld/test/MachO/indirect-symtab.s
+++ b/lld/test/MachO/indirect-symtab.s
@@ -2,8 +2,9 @@
 # RUN: rm -rf %t; split-file %s %t
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/libfoo.s -o %t/libfoo.o
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/bar.s -o %t/bar.o
 # RUN: %lld -dylib %t/libfoo.o -o %t/libfoo.dylib -lSystem
-# RUN: %lld %t/test.o %t/libfoo.dylib -o %t/test -lSystem
+# RUN: %lld %t/test.o %t/bar.o %t/libfoo.dylib -o %t/test -lSystem
 # RUN: llvm-objdump --macho -d --no-show-raw-insn --indirect-symbols %t/test | FileCheck %s
 # RUN: llvm-otool -l %t/test | FileCheck --check-prefix=DYSYMTAB %s
 
@@ -11,6 +12,8 @@
 # CHECK-NEXT: _main:
 # CHECK-NEXT: movq  {{.*}}(%rip), %rax ## literal pool symbol address: _foo
 # CHECK-NEXT: movq  {{.*}}(%rip), %rax ## literal pool symbol address: _bar
+# CHECK-NEXT: leaq  _baz(%rip), %rax
+# CHECK-NEXT: addq  {{.*}}(%rip), %rax
 # CHECK-NEXT: movq  {{.*}}(%rip), %rax ## literal pool symbol address: _foo_tlv
 # CHECK-NEXT: movq  {{.*}}(%rip), %rax ## literal pool symbol address: _bar_tlv
 # CHECK-NEXT: callq {{.*}} ## symbol stub for: _foo_fn
@@ -21,8 +24,9 @@
 # CHECK-NEXT: address            index name
 # CHECK-NEXT: _bar_fn
 # CHECK-NEXT: _foo_fn
-# CHECK-NEXT: Indirect symbols for (__DATA_CONST,__got) 3 entries
+# CHECK-NEXT: Indirect symbols for (__DATA_CONST,__got) 4 entries
 # CHECK-NEXT: address            index name
+# CHECK-NEXT: LOCAL
 # CHECK-NEXT: _bar
 # CHECK-NEXT: _foo
 # CHECK-NEXT: _stub_binder
@@ -35,7 +39,7 @@
 # CHECK-NEXT: _bar_tlv
 # CHECK-NEXT: _foo_tlv
 
-# DYSYMTAB: nindirectsyms 9
+# DYSYMTAB: nindirectsyms 10
 
 #--- libfoo.s
 
@@ -56,8 +60,19 @@ _bar_tlv:
 _main:
   movq _foo at GOTPCREL(%rip), %rax
   movq _bar at GOTPCREL(%rip), %rax
+  movq _baz at GOTPCREL(%rip), %rax
+  addq _quux at GOTPCREL(%rip), %rax
   mov _foo_tlv at TLVP(%rip), %rax
   mov _bar_tlv at TLVP(%rip), %rax
   callq _foo_fn
   callq _bar_fn
   ret
+
+#--- bar.s
+.data
+.globl _baz,_quux
+.private_extern _baz,_quux
+_baz:
+.asciz "baz"
+_quux:
+.asciz "quux"


        


More information about the llvm-commits mailing list