Skip to content

Commit 4e572db

Browse files
committed
[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
1 parent bacddf4 commit 4e572db

File tree

3 files changed

+26
-6
lines changed

3 files changed

+26
-6
lines changed

lld/MachO/SyntheticSections.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,8 +1104,12 @@ void IndirectSymtabSection::finalizeContents() {
11041104
}
11051105

11061106
static uint32_t indirectValue(const Symbol *sym) {
1107-
return sym->symtabIndex != UINT32_MAX ? sym->symtabIndex
1108-
: INDIRECT_SYMBOL_LOCAL;
1107+
if (sym->symtabIndex == UINT32_MAX)
1108+
return INDIRECT_SYMBOL_LOCAL;
1109+
if (auto *defined = dyn_cast<Defined>(sym))
1110+
if (defined->privateExtern)
1111+
return INDIRECT_SYMBOL_LOCAL;
1112+
return sym->symtabIndex;
11091113
}
11101114

11111115
void IndirectSymtabSection::writeTo(uint8_t *buf) const {

lld/test/MachO/compact-unwind-both-local-and-dylib-personality.s

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@
3333
# A: Indirect symbols for (__DATA_CONST,__got)
3434
# A-NEXT: address index name
3535
# A-DAG: 0x[[#%x,GXX_PERSONALITY_LO:]] [[#]] ___gxx_personality_v0
36-
# A-DAG: 0x[[#%x,GXX_PERSONALITY_HI:]] [[#]] ___gxx_personality_v0
36+
# A-DAG: 0x[[#%x,GXX_PERSONALITY_HI:]] [[#]] ___gxx_personality_v0
3737
# A-DAG: 0x[[#%x,PERSONALITY_1:]] LOCAL
3838
# A-DAG: 0x[[#%x,PERSONALITY_2:]] LOCAL
3939

4040
# BC: Indirect symbols for (__DATA_CONST,__got)
4141
# BC-NEXT: address index name
42+
# BC-DAG: 0x[[#%x,GXX_PERSONALITY_HI:]] LOCAL
4243
# BC-DAG: 0x[[#%x,GXX_PERSONALITY_LO:]] LOCAL
4344
# BC-DAG: 0x[[#%x,PERSONALITY_1:]] LOCAL
4445
# BC-DAG: 0x[[#%x,PERSONALITY_2:]] LOCAL

lld/test/MachO/indirect-symtab.s

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22
# RUN: rm -rf %t; split-file %s %t
33
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/libfoo.s -o %t/libfoo.o
44
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
5+
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/bar.s -o %t/bar.o
56
# RUN: %lld -dylib %t/libfoo.o -o %t/libfoo.dylib -lSystem
6-
# RUN: %lld %t/test.o %t/libfoo.dylib -o %t/test -lSystem
7+
# RUN: %lld %t/test.o %t/bar.o %t/libfoo.dylib -o %t/test -lSystem
78
# RUN: llvm-objdump --macho -d --no-show-raw-insn --indirect-symbols %t/test | FileCheck %s
89
# RUN: llvm-otool -l %t/test | FileCheck --check-prefix=DYSYMTAB %s
910

1011
# CHECK: (__TEXT,__text) section
1112
# CHECK-NEXT: _main:
1213
# CHECK-NEXT: movq {{.*}}(%rip), %rax ## literal pool symbol address: _foo
1314
# CHECK-NEXT: movq {{.*}}(%rip), %rax ## literal pool symbol address: _bar
15+
# CHECK-NEXT: leaq _baz(%rip), %rax
16+
# CHECK-NEXT: addq {{.*}}(%rip), %rax
1417
# CHECK-NEXT: movq {{.*}}(%rip), %rax ## literal pool symbol address: _foo_tlv
1518
# CHECK-NEXT: movq {{.*}}(%rip), %rax ## literal pool symbol address: _bar_tlv
1619
# CHECK-NEXT: callq {{.*}} ## symbol stub for: _foo_fn
@@ -21,8 +24,9 @@
2124
# CHECK-NEXT: address index name
2225
# CHECK-NEXT: _bar_fn
2326
# CHECK-NEXT: _foo_fn
24-
# CHECK-NEXT: Indirect symbols for (__DATA_CONST,__got) 3 entries
27+
# CHECK-NEXT: Indirect symbols for (__DATA_CONST,__got) 4 entries
2528
# CHECK-NEXT: address index name
29+
# CHECK-NEXT: LOCAL
2630
# CHECK-NEXT: _bar
2731
# CHECK-NEXT: _foo
2832
# CHECK-NEXT: _stub_binder
@@ -35,7 +39,7 @@
3539
# CHECK-NEXT: _bar_tlv
3640
# CHECK-NEXT: _foo_tlv
3741

38-
# DYSYMTAB: nindirectsyms 9
42+
# DYSYMTAB: nindirectsyms 10
3943

4044
#--- libfoo.s
4145

@@ -56,8 +60,19 @@ _bar_tlv:
5660
_main:
5761
movq _foo@GOTPCREL(%rip), %rax
5862
movq _bar@GOTPCREL(%rip), %rax
63+
movq _baz@GOTPCREL(%rip), %rax
64+
addq _quux@GOTPCREL(%rip), %rax
5965
mov _foo_tlv@TLVP(%rip), %rax
6066
mov _bar_tlv@TLVP(%rip), %rax
6167
callq _foo_fn
6268
callq _bar_fn
6369
ret
70+
71+
#--- bar.s
72+
.data
73+
.globl _baz,_quux
74+
.private_extern _baz,_quux
75+
_baz:
76+
.asciz "baz"
77+
_quux:
78+
.asciz "quux"

0 commit comments

Comments
 (0)