aboutsummaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
authorJez Ng <jezng@fb.com>2020-08-31 20:57:19 -0700
committerJez Ng <jezng@fb.com>2020-09-23 19:26:40 -0700
commitcd7cb0c30305501982ba37b4905bb264b3539ad0 (patch)
treebcc4b79410ce4c208ebb6279b4e112b9d24aa553 /lld
parent63ace77962543f961f1d566dd1243b1fb37129ef (diff)
downloadllvm-cd7cb0c30305501982ba37b4905bb264b3539ad0.zip
llvm-cd7cb0c30305501982ba37b4905bb264b3539ad0.tar.gz
llvm-cd7cb0c30305501982ba37b4905bb264b3539ad0.tar.bz2
[lld-macho] Implement and test resolution of common symbols
Handle the case where there are both common and non-common definitions of the same symbol. Add a bunch of tests to ensure compatibility with ld64. Reviewed By: #lld-macho, gkm Differential Revision: https://reviews.llvm.org/D86910
Diffstat (limited to 'lld')
-rw-r--r--lld/MachO/SymbolTable.cpp5
-rw-r--r--lld/test/MachO/common-symbol-resolution.s113
-rw-r--r--lld/test/MachO/nonweak-definition-override.s18
3 files changed, 134 insertions, 2 deletions
diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp
index 6719981..0aa8828 100644
--- a/lld/MachO/SymbolTable.cpp
+++ b/lld/MachO/SymbolTable.cpp
@@ -84,10 +84,11 @@ Symbol *SymbolTable::addCommon(StringRef name, InputFile *file, uint64_t size,
if (auto *common = dyn_cast<CommonSymbol>(s)) {
if (size < common->size)
return s;
- } else if (!isa<Undefined>(s)) {
- error("TODO: implement common symbol resolution with other symbol kinds");
+ } else if (isa<Defined>(s)) {
return s;
}
+ // Common symbols take priority over all non-Defined symbols, so in case of
+ // a name conflict, we fall through to the replaceSymbol() call below.
}
replaceSymbol<CommonSymbol>(s, name, file, size, align);
diff --git a/lld/test/MachO/common-symbol-resolution.s b/lld/test/MachO/common-symbol-resolution.s
new file mode 100644
index 0000000..6cefe30
--- /dev/null
+++ b/lld/test/MachO/common-symbol-resolution.s
@@ -0,0 +1,113 @@
+# REQUIRES: x86
+# RUN: split-file %s %t
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/common.s -o %t/common.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/weak-common.s -o %t/weak-common.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/defined.s -o %t/defined.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/weak-defined.s -o %t/weak-defined.o
+# 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/calls-foo.s -o %t/calls-foo.o
+
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -order_file %t/order -dylib %t/libfoo.o -o %t/libfoo.dylib
+
+# RUN: rm -f %t/defined.a %t/weak-defined-and-common.a
+# RUN: llvm-ar rcs %t/defined.a %t/defined.o
+# RUN: llvm-ar rcs %t/weak-defined-and-common.a %t/weak-defined.o %t/common.o
+
+## The weak attribute appears to have no effect on common symbols. Given two
+## common symbols of the same name, we always pick the one with the larger size,
+## regardless of whether it is weak. Moreover, the resolved symbol in the output
+## file will always be non-weak, even if the winning input symbol definition was
+## weak.
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -order_file %t/order %t/common.o %t/weak-common.o %t/test.o -o %t/test
+# RUN: llvm-objdump --syms %t/test | FileCheck %s --check-prefix=LARGER-COMMON
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -order_file %t/order %t/weak-common.o %t/common.o %t/test.o -o %t/test
+# RUN: llvm-objdump --syms %t/test | FileCheck %s --check-prefix=LARGER-COMMON
+
+## Defined symbols are the only ones that take precedence over common symbols.
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -order_file %t/order %t/defined.o %t/common.o %t/test.o -o %t/test
+# RUN: llvm-objdump --syms %t/test | FileCheck %s --check-prefix=DEFINED
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -order_file %t/order %t/common.o %t/defined.o %t/test.o -o %t/test
+# RUN: llvm-objdump --syms %t/test | FileCheck %s --check-prefix=DEFINED
+
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -order_file %t/order %t/weak-defined.o %t/common.o %t/test.o -o %t/test
+# RUN: llvm-objdump --syms %t/test | FileCheck %s --check-prefix=WEAK-DEFINED
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -order_file %t/order %t/common.o %t/weak-defined.o %t/test.o -o %t/test
+# RUN: llvm-objdump --syms %t/test | FileCheck %s --check-prefix=WEAK-DEFINED
+
+## Common symbols take precedence over archive symbols.
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -order_file %t/order %t/defined.a %t/weak-common.o %t/test.o -o %t/test
+# RUN: llvm-objdump --syms %t/test | FileCheck %s --check-prefix=LARGER-COMMON
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -order_file %t/order %t/weak-common.o %t/defined.a %t/test.o -o %t/test
+# RUN: llvm-objdump --syms %t/test | FileCheck %s --check-prefix=LARGER-COMMON
+
+## If an archive has both a common and a defined symbol, the defined one should
+## win.
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -order_file %t/order %t/weak-defined-and-common.a %t/calls-foo.o -o %t/calls-foo
+# RUN: llvm-objdump --syms %t/calls-foo | FileCheck %s --check-prefix=WEAK-DEFINED
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -order_file %t/order %t/calls-foo.o %t/weak-defined-and-common.a -o %t/calls-foo
+# RUN: llvm-objdump --syms %t/calls-foo | FileCheck %s --check-prefix=WEAK-DEFINED
+
+## Common symbols take precedence over dylib symbols.
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -order_file %t/order %t/libfoo.dylib %t/weak-common.o %t/test.o -o %t/test
+# RUN: llvm-objdump --syms %t/test | FileCheck %s --check-prefix=LARGER-COMMON
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -order_file %t/order %t/weak-common.o %t/libfoo.dylib %t/test.o -o %t/test
+# RUN: llvm-objdump --syms %t/test | FileCheck %s --check-prefix=LARGER-COMMON
+
+# LARGER-COMMON-LABEL: SYMBOL TABLE:
+# LARGER-COMMON-DAG: [[#%x, FOO_ADDR:]] g O __DATA,__common _foo
+# LARGER-COMMON-DAG: [[#FOO_ADDR + 2]] g O __DATA,__common _foo_end
+
+# DEFINED-LABEL: SYMBOL TABLE:
+# DEFINED: g F __TEXT,__text _foo
+
+# WEAK-DEFINED-LABEL: SYMBOL TABLE:
+# WEAK-DEFINED: w F __TEXT,__text _foo
+
+#--- order
+## %t/order is important as we determine the size of a given symbol via the
+## address of the next symbol.
+_foo
+_foo_end
+
+#--- common.s
+.comm _foo, 1
+
+.globl _bar
+_bar:
+
+#--- weak-common.s
+.weak_definition _foo
+.comm _foo, 2
+
+#--- defined.s
+.globl _foo
+_foo:
+ .quad 0x1234
+
+#--- weak-defined.s
+.globl _foo
+.weak_definition _foo
+_foo:
+ .quad 0x1234
+
+#--- libfoo.s
+.globl _foo
+_foo:
+ .quad 0x1234
+
+#--- test.s
+.comm _foo_end, 1
+
+.globl _main
+_main:
+ ret
+
+#--- calls-foo.s
+.comm _foo_end, 1
+
+.globl _main
+_main:
+ callq _foo
+ ret
diff --git a/lld/test/MachO/nonweak-definition-override.s b/lld/test/MachO/nonweak-definition-override.s
index d5c94d4..c531d2b 100644
--- a/lld/test/MachO/nonweak-definition-override.s
+++ b/lld/test/MachO/nonweak-definition-override.s
@@ -3,6 +3,7 @@
# 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/nonweakdef.s -o %t/nonweakdef.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/weakdef.s -o %t/weakdef.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/common.s -o %t/common.o
# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -dylib %t/libfoo.o -o %t/libfoo.dylib
## Check that non-weak defined symbols override weak dylib symbols.
@@ -30,6 +31,14 @@
# NO-WEAK-OVERRIDE-NEXT: segment section address type addend symbol
# NO-WEAK-OVERRIDE-EMPTY:
+## Check that common symbols take precedence over weak dylib symbols, but do not
+## generate an overridding weak binding.
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -L%t -lfoo %t/common.o -o %t/common -lSystem
+# RUN: llvm-objdump --macho --weak-bind %t/common | FileCheck %s --check-prefix=NO-WEAK-OVERRIDE
+# RUN: llvm-objdump --syms %t/common | FileCheck %s --check-prefix=COMMON
+# COMMON-DAG: g O __DATA,__common _nonweak_in_dylib
+# COMMON-DAG: g O __DATA,__common _weak_in_dylib
+
#--- libfoo.s
.globl _weak_in_dylib, _nonweak_in_dylib
@@ -58,3 +67,12 @@ _nonweak_in_dylib:
_main:
ret
+
+#--- common.s
+
+.globl _main
+.comm _weak_in_dylib, 1
+.comm _nonweak_in_dylib, 1
+
+_main:
+ ret