# REQUIRES: x86 # 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/strongref.s -o %t/strongref.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/invalid.s -o %t/invalid.o # RUN: %lld -lSystem -dylib %t/libfoo.o -o %t/libfoo.dylib # RUN: %lld -lSystem %t/test.o %t/libfoo.dylib -o %t/test # RUN: %lld -fixup_chains -lSystem %t/test.o %t/libfoo.dylib -o %t/chained # RUN: llvm-objdump --macho --syms --bind --lazy-bind %t/test | FileCheck %s --check-prefixes=SYMS,BIND # RUN: llvm-objdump --macho --syms --dyld-info %t/chained | FileCheck %s --check-prefixes=CHAINED ## llvm-objdump doesn't print out all the flags info for lazy & weak bindings, ## so we use obj2yaml instead to test them. # RUN: obj2yaml %t/test | FileCheck %s --check-prefix=YAML # RUN: %lld -lSystem %t/libfoo.dylib %t/test.o -o %t/test # RUN: llvm-objdump --macho --syms --bind --lazy-bind %t/test | FileCheck %s --check-prefixes=SYMS,BIND # RUN: obj2yaml %t/test | FileCheck %s --check-prefix=YAML # SYMS: SYMBOL TABLE: # SYMS-DAG: 0000000000000000 w *UND* _foo # SYMS-DAG: 0000000000000000 w *UND* _foo_fn # SYMS-DAG: 0000000000000000 w *UND* _foo_tlv # SYMS-DAG: 0000000000000000 w *UND* _weak_foo # SYMS-DAG: 0000000000000000 w *UND* _weak_foo_fn # BIND: Bind table: # BIND-NEXT: segment section address type addend dylib symbol # BIND-DAG: __DATA __data 0x{{[0-9a-f]+}} pointer 0 libfoo _foo (weak_import) # BIND-DAG: __DATA_CONST __got 0x{{[0-9a-f]+}} pointer 0 libfoo _foo (weak_import) # BIND-DAG: __DATA __thread_ptrs 0x{{[0-9a-f]+}} pointer 0 libfoo _foo_tlv (weak_import) # BIND-DAG: __DATA __data 0x{{[0-9a-f]+}} pointer 0 libfoo _weak_foo (weak_import) # BIND-DAG: __DATA __la_symbol_ptr 0x{{[0-9a-f]+}} pointer 0 libfoo _weak_foo_fn (weak_import) # BIND: Lazy bind table: # BIND-NEXT: segment section address dylib symbol # BIND-DAG: __DATA __la_symbol_ptr 0x{{[0-9a-f]+}} libfoo _foo_fn # CHAINED: dyld information: # CHAINED-NEXT: segment section address pointer type addend dylib symbol/vm address # CHAINED-DAG: __DATA_CONST __got {{.*}} bind 0x0 libfoo _foo (weak import) # CHAINED-DAG: __DATA __data {{.*}} bind 0x0 libfoo _foo (weak import) # CHAINED-DAG: __DATA __thread_ptrs {{.*}} bind 0x0 libfoo _foo_tlv (weak import) # CHAINED-DAG: __DATA_CONST __got {{.*}} bind 0x0 libfoo _foo_fn (weak import) # CHAINED-DAG: __DATA __data {{.*}} bind 0x0 weak _weak_foo (weak import) # CHAINED-DAG: __DATA_CONST __got {{.*}} bind 0x0 weak _weak_foo_fn (weak import) # YAML-LABEL: WeakBindOpcodes: # YAML: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM # YAML-NEXT: Imm: 0 # YAML-NEXT: Symbol: _weak_foo_fn # YAML: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM # YAML-NEXT: Imm: 0 # YAML-NEXT: Symbol: _weak_foo # YAML-LABEL: LazyBindOpcodes: # YAML: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM # YAML-NEXT: Imm: 1 # YAML-NEXT: Symbol: _foo_fn ## Check that if both strong & weak references are present in inputs, the weak ## reference takes priority. NOTE: ld64 actually emits a strong reference if ## the reference is to a function symbol or a TLV. I'm not sure if there's a ## good reason for that, so I'm deviating here for a simpler implementation. # RUN: %lld -lSystem %t/test.o %t/strongref.o %t/libfoo.dylib -o %t/with-strong # RUN: %lld -fixup_chains -lSystem %t/test.o %t/strongref.o %t/libfoo.dylib -o %t/with-strong-chained # RUN: llvm-objdump --macho --bind %t/with-strong | FileCheck %s --check-prefix=STRONG-BIND # RUN: llvm-objdump --macho --dyld-info %t/with-strong-chained | FileCheck %s --check-prefix=STRONG-CHAINED # RUN: obj2yaml %t/with-strong | FileCheck %s --check-prefix=STRONG-YAML # RUN: %lld -lSystem %t/strongref.o %t/test.o %t/libfoo.dylib -o %t/with-strong # RUN: %lld -fixup_chains -lSystem %t/strongref.o %t/test.o %t/libfoo.dylib -o %t/with-strong-chained # RUN: llvm-objdump --macho --bind %t/with-strong | FileCheck %s --check-prefix=STRONG-BIND # RUN: llvm-objdump --macho --dyld-info %t/with-strong-chained | FileCheck %s --check-prefix=STRONG-CHAINED # RUN: obj2yaml %t/with-strong | FileCheck %s --check-prefix=STRONG-YAML # RUN: %lld -lSystem %t/libfoo.dylib %t/strongref.o %t/test.o -o %t/with-strong # RUN: %lld -fixup_chains -lSystem %t/libfoo.dylib %t/strongref.o %t/test.o -o %t/with-strong-chained # RUN: llvm-objdump --macho --bind %t/with-strong | FileCheck %s --check-prefix=STRONG-BIND # RUN: llvm-objdump --macho --dyld-info %t/with-strong-chained | FileCheck %s --check-prefix=STRONG-CHAINED # RUN: obj2yaml %t/with-strong | FileCheck %s --check-prefix=STRONG-YAML # RUN: %lld -lSystem %t/libfoo.dylib %t/test.o %t/strongref.o -o %t/with-strong # RUN: %lld -fixup_chains -lSystem %t/libfoo.dylib %t/test.o %t/strongref.o -o %t/with-strong-chained # RUN: llvm-objdump --macho --bind %t/with-strong | FileCheck %s --check-prefix=STRONG-BIND # RUN: llvm-objdump --macho --dyld-info %t/with-strong-chained | FileCheck %s --check-prefix=STRONG-CHAINED # RUN: obj2yaml %t/with-strong | FileCheck %s --check-prefix=STRONG-YAML # RUN: %lld -lSystem %t/test.o %t/libfoo.dylib %t/strongref.o -o %t/with-strong # RUN: %lld -fixup_chains -lSystem %t/test.o %t/libfoo.dylib %t/strongref.o -o %t/with-strong-chained # RUN: llvm-objdump --macho --bind %t/with-strong | FileCheck %s --check-prefix=STRONG-BIND # RUN: llvm-objdump --macho --dyld-info %t/with-strong-chained | FileCheck %s --check-prefix=STRONG-CHAINED # RUN: obj2yaml %t/with-strong | FileCheck %s --check-prefix=STRONG-YAML # RUN: %lld -lSystem %t/strongref.o %t/libfoo.dylib %t/test.o -o %t/with-strong # RUN: %lld -fixup_chains -lSystem %t/strongref.o %t/libfoo.dylib %t/test.o -o %t/with-strong-chained # RUN: llvm-objdump --macho --bind %t/with-strong | FileCheck %s --check-prefix=STRONG-BIND # RUN: llvm-objdump --macho --dyld-info %t/with-strong-chained | FileCheck %s --check-prefix=STRONG-CHAINED # RUN: obj2yaml %t/with-strong | FileCheck %s --check-prefix=STRONG-YAML # STRONG-BIND: Bind table: # STRONG-BIND-NEXT: segment section address type addend dylib symbol # STRONG-BIND-DAG: __DATA __data 0x{{[0-9a-f]+}} pointer 0 libfoo _foo{{$}} # STRONG-BIND-DAG: __DATA __data 0x{{[0-9a-f]+}} pointer 0 libfoo _foo{{$}} # STRONG-BIND-DAG: __DATA_CONST __got 0x{{[0-9a-f]+}} pointer 0 libfoo _foo{{$}} # STRONG-BIND-DAG: __DATA __thread_ptrs 0x{{[0-9a-f]+}} pointer 0 libfoo _foo_tlv{{$}} # STRONG-BIND-DAG: __DATA __data 0x{{[0-9a-f]+}} pointer 0 libfoo _weak_foo{{$}} # STRONG-BIND-DAG: __DATA __data 0x{{[0-9a-f]+}} pointer 0 libfoo _weak_foo{{$}} # STRONG-BIND-DAG: __DATA __la_symbol_ptr 0x{{[0-9a-f]+}} pointer 0 libfoo _weak_foo_fn{{$}} # STRONG-CHAINED: dyld information: # STRONG-CHAINED-NEXT: segment section address pointer type addend dylib symbol/vm address # STRONG-CHAINED-DAG: __DATA_CONST __got {{.*}} bind 0x0 weak _weak_foo_fn{{$}} # STRONG-CHAINED-DAG: __DATA_CONST __got {{.*}} bind 0x0 libfoo _foo_fn{{$}} # STRONG-CHAINED-DAG: __DATA_CONST __got {{.*}} bind 0x0 libfoo _foo{{$}} # STRONG-CHAINED-DAG: __DATA __data {{.*}} bind 0x0 libfoo _foo{{$}} # STRONG-CHAINED-DAG: __DATA __data {{.*}} bind 0x0 libfoo _foo{{$}} # STRONG-CHAINED-DAG: __DATA __data {{.*}} bind 0x0 weak _weak_foo{{$}} # STRONG-CHAINED-DAG: __DATA __data {{.*}} bind 0x0 weak _weak_foo{{$}} # STRONG-CHAINED-DAG: __DATA __thread_ptrs {{.*}} bind 0x0 libfoo _foo_tlv{{$}} # STRONG-YAML-LABEL: WeakBindOpcodes: # STRONG-YAML: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM # STRONG-YAML-NEXT: Imm: 0 # STRONG-YAML-NEXT: Symbol: _weak_foo_fn # STRONG-YAML: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM # STRONG-YAML-NEXT: Imm: 0 # STRONG-YAML-NEXT: Symbol: _weak_foo # STRONG-YAML-LABEL: LazyBindOpcodes: # STRONG-YAML: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM # STRONG-YAML-NEXT: Imm: 0 # STRONG-YAML-NEXT: Symbol: _foo_fn ## Weak references must still be satisfied at link time. # RUN: not %lld -lSystem %t/invalid.o -o /dev/null 2>&1 | FileCheck %s \ # RUN: --check-prefix=INVALID -DDIR=%t # INVALID: error: undefined symbol: _missing #--- libfoo.s .globl _foo, _foo_fn, _weak_foo, _weak_foo_fn .weak_definition _weak_foo, _weak_foo_fn _foo: _foo_fn: _weak_foo: _weak_foo_fn: .section __DATA,__thread_vars,thread_local_variables .globl _foo_tlv _foo_tlv: #--- test.s .globl _main .weak_reference _foo_fn, _foo, _weak_foo, _weak_foo_fn, _foo_tlv _main: mov _foo@GOTPCREL(%rip), %rax mov _foo_tlv@TLVP(%rip), %rax callq _foo_fn callq _weak_foo_fn ret .data .quad _foo .quad _weak_foo #--- strongref.s .globl _strongref _strongref: mov _foo@GOTPCREL(%rip), %rax mov _foo_tlv@TLVP(%rip), %rax callq _foo_fn callq _weak_foo_fn ret .data .quad _foo .quad _weak_foo #--- invalid.s .globl _main .weak_reference _missing _main: callq _missing ret