Skip to content

Commit 22b7b84

Browse files
authored
[lld][WebAssembly] Report undefined symbols in -shared/-pie builds (#75242)
Previously we would ignore all undefined symbols when using `-shared` or `-pie`. All undefined symbols would be treated as imports regardless of whether those symbols we defined in any shared library. With this change we now track symbol in shared libraries and report undefined symbols in the main program by default. The old behavior is still available via the `--unresolved-symbols=import-dynamic` command line flag. This rationale for allowing this type of breaking change is that `-pie` and `-shared` are both still experimental will warn as such, unless `--experimental-pic` is passed. As part of this change the linker now models shared library symbols via new SharedFunctionSymbol and SharedDataSymbol types. I've also added a new `--no-shlib-sigcheck` option that bypassed the checking of functions signature in shared libraries. This is specifically required by emscripten the case where the imports/exports of shared libraries have been modified by via JS type legalization (this is only needed when targeting old JS engines where bigint is not yet available See emscripten-core/emscripten#18198
1 parent ef8207b commit 22b7b84

27 files changed

+356
-75
lines changed

lld/test/wasm/Inputs/ret32.s

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
.hidden ret32
21
.globl ret32
32
ret32:
43
.functype ret32 (f32) -> (i32)

lld/test/wasm/dylink.s

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-emscripten -o %t.o %s
2+
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-emscripten %p/Inputs/ret32.s -o %t.ret32.o
3+
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-emscripten %p/Inputs/libsearch-dyn.s -o %t.dyn.o
4+
# RUN: wasm-ld --experimental-pic -shared %t.ret32.o %t.dyn.o -o %t.lib.so
5+
# RUN: not wasm-ld --experimental-pic -pie -o %t.wasm %t.o 2>&1 | FileCheck --check-prefix=ERROR %s
6+
# RUN: wasm-ld --experimental-pic -pie -o %t.wasm %t.o %t.lib.so
7+
# RUN: obj2yaml %t.wasm | FileCheck %s
8+
9+
# ERROR: error: {{.*}}: undefined symbol: ret32
10+
# ERROR: error: {{.*}}: undefined symbol: _bar
11+
.functype ret32 (f32) -> (i32)
12+
13+
.globl _start
14+
_start:
15+
.functype _start () -> ()
16+
f32.const 0.0
17+
call ret32
18+
drop
19+
i32.const _bar@GOT
20+
drop
21+
end_function
22+
23+
# CHECK: Sections:
24+
# CHECK-NEXT: - Type: CUSTOM
25+
# CHECK-NEXT: Name: dylink.0
26+
# CHECK-NEXT: MemorySize: 0
27+
# CHECK-NEXT: MemoryAlignment: 0
28+
# CHECK-NEXT: TableSize: 0
29+
# CHECK-NEXT: TableAlignment: 0
30+
# CHECK-NEXT: Needed:
31+
# CHECK-NEXT: - {{.*}}.lib.so

lld/test/wasm/emit-relocs.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ foo:
5454
# CHECK-NEXT: - Index: 1
5555
# CHECK-NEXT: Kind: FUNCTION
5656
# CHECK-NEXT: Name: ret32
57-
# CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ]
57+
# CHECK-NEXT: Flags: [ ]
5858
# CHECK-NEXT: Function: 1
5959
# CHECK-NEXT: - Index: 2
6060
# CHECK-NEXT: Kind: DATA

lld/test/wasm/no-shlib-sigcheck.s

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-emscripten -o %t.o %s
2+
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-emscripten %p/Inputs/ret32.s -o %t.ret32.o
3+
# RUN: wasm-ld --experimental-pic -shared %t.ret32.o -o %t.lib.so
4+
5+
## Fails with signature mismatch by default
6+
# RUN: not wasm-ld --experimental-pic -pie -o %t.wasm %t.o %t.lib.so 2>&1 | FileCheck --check-prefix=ERROR %s
7+
## Same again with shared library first.
8+
# RUN: not wasm-ld --experimental-pic -pie -o %t.wasm %t.lib.so %t.o 2>&1 | FileCheck --check-prefix=ERROR %s
9+
10+
## Succeeds with --no-shlib-sigcheck added
11+
# RUN: wasm-ld --experimental-pic -pie -o %t.wasm %t.o %t.lib.so --no-shlib-sigcheck
12+
# RUN: obj2yaml %t.wasm | FileCheck %s
13+
## Same again with shared library first.
14+
# RUN: wasm-ld --experimental-pic -pie -o %t.wasm %t.lib.so %t.o --no-shlib-sigcheck
15+
# RUN: obj2yaml %t.wasm | FileCheck %s
16+
17+
.functype ret32 (f32) -> (i64)
18+
19+
.globl _start
20+
_start:
21+
.functype _start () -> ()
22+
f32.const 0.0
23+
call ret32
24+
drop
25+
end_function
26+
27+
# ERROR: wasm-ld: error: function signature mismatch: ret32
28+
# ERROR: >>> defined as (f32) -> i64 in {{.*}}.o
29+
30+
# CHECK: - Type: TYPE
31+
# CHECK-NEXT: Signatures:
32+
# CHECK-NEXT: - Index: 0
33+
# CHECK-NEXT: ParamTypes:
34+
# CHECK-NEXT: - F32
35+
# CHECK-NEXT: ReturnTypes:
36+
# CHECK-NEXT: - I64
37+
# CHECK-NEXT: - Index: 1
38+
# CHECK-NEXT: ParamTypes: []
39+
# CHECK-NEXT: ReturnTypes: []

lld/test/wasm/pie.s

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-emscripten -o %t.o %s
22
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-emscripten %S/Inputs/internal_func.s -o %t.internal_func.o
3-
# RUN: wasm-ld --no-gc-sections --experimental-pic -pie -o %t.wasm %t.o %t.internal_func.o
3+
# RUN: wasm-ld --no-gc-sections --experimental-pic -pie --unresolved-symbols=import-dynamic -o %t.wasm %t.o %t.internal_func.o
44
# RUN: obj2yaml %t.wasm | FileCheck %s
55
# RUN: llvm-objdump --disassemble-symbols=__wasm_call_ctors,__wasm_apply_data_relocs --no-show-raw-insn --no-leading-addr %t.wasm | FileCheck %s --check-prefixes DISASSEM
66

@@ -150,7 +150,7 @@ _start:
150150
# instruction in the InitExpr. We also, therefore, do not need these globals
151151
# to be mutable.
152152

153-
# RUN: wasm-ld --no-gc-sections --experimental-pic -pie --extra-features=extended-const -o %t.extended.wasm %t.o %t.internal_func.o
153+
# RUN: wasm-ld --no-gc-sections --experimental-pic -pie --unresolved-symbols=import-dynamic --extra-features=extended-const -o %t.extended.wasm %t.o %t.internal_func.o
154154
# RUN: obj2yaml %t.extended.wasm | FileCheck %s --check-prefix=EXTENDED-CONST
155155

156156
# EXTENDED-CONST-NOT: __wasm_apply_global_relocs
@@ -207,7 +207,7 @@ _start:
207207
# to be generated along with __wasm_start as the start
208208
# function.
209209

210-
# RUN: wasm-ld --no-gc-sections --shared-memory --experimental-pic -pie -o %t.shmem.wasm %t.o %t.internal_func.o
210+
# RUN: wasm-ld --no-gc-sections --shared-memory --experimental-pic -pie --unresolved-symbols=import-dynamic -o %t.shmem.wasm %t.o %t.internal_func.o
211211
# RUN: obj2yaml %t.shmem.wasm | FileCheck %s --check-prefix=SHMEM
212212
# RUN: llvm-objdump --disassemble-symbols=__wasm_start --no-show-raw-insn --no-leading-addr %t.shmem.wasm | FileCheck %s --check-prefix DISASSEM-SHMEM
213213

lld/test/wasm/shared-needed.s

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
22
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/ret32.s -o %t.ret32.o
33

4-
# RUN: wasm-ld -shared --experimental-pic -o %t1.so %t.o
5-
# RUN: obj2yaml %t1.so | FileCheck %s -check-prefix=SO1
4+
# RUN: wasm-ld -shared --experimental-pic -o %t.ret32.so %t.ret32.o
5+
# RUN: obj2yaml %t.ret32.so | FileCheck %s -check-prefix=SO1
6+
7+
# Without linking against the ret32.so shared object we expect an undefined
8+
# symbol error
9+
10+
# RUN: not wasm-ld -shared --experimental-pic -o %t.so %t.o 2>&1 | FileCheck %s --check-prefix=ERROR
11+
# ERROR: undefined symbol: ret32
12+
13+
# RUN: wasm-ld -shared --experimental-pic -o %t.so %t.o %t.ret32.so
14+
# RUN: obj2yaml %t.so | FileCheck %s -check-prefix=SO2
615

7-
# RUN: wasm-ld -shared --experimental-pic -o %t2.so %t1.so %t.ret32.o
8-
# RUN: obj2yaml %t2.so | FileCheck %s -check-prefix=SO2
916

1017
.globl foo
1118
.globl data
1219

20+
.functype ret32 (f32) -> (i32)
21+
1322
foo:
14-
.functype foo () -> ()
23+
.functype foo (f32) -> (i32)
24+
local.get 0
25+
call ret32
1526
end_function
1627

1728
.section .data,"",@
@@ -24,8 +35,8 @@ data:
2435
# SO1: Sections:
2536
# SO1-NEXT: - Type: CUSTOM
2637
# SO1-NEXT: Name: dylink.0
27-
# SO1-NEXT: MemorySize: 4
28-
# SO1-NEXT: MemoryAlignment: 2
38+
# SO1-NEXT: MemorySize: 0
39+
# SO1-NEXT: MemoryAlignment: 0
2940
# SO1-NEXT: TableSize: 0
3041
# SO1-NEXT: TableAlignment: 0
3142
# SO1-NEXT: Needed: []
@@ -34,10 +45,10 @@ data:
3445
# SO2: Sections:
3546
# SO2-NEXT: - Type: CUSTOM
3647
# SO2-NEXT: Name: dylink.0
37-
# SO2-NEXT: MemorySize: 0
38-
# SO2-NEXT: MemoryAlignment: 0
48+
# SO2-NEXT: MemorySize: 4
49+
# SO2-NEXT: MemoryAlignment: 2
3950
# SO2-NEXT: TableSize: 0
4051
# SO2-NEXT: TableAlignment: 0
4152
# SO2-NEXT: Needed:
42-
# SO2-NEXT: - shared-needed.s.tmp1.so
53+
# SO2-NEXT: - shared-needed.s.tmp.ret32.so
4354
# SO2-NEXT: - Type: TYPE

lld/test/wasm/shared.s

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
2-
# RUN: wasm-ld --experimental-pic -shared -o %t.wasm %t.o
2+
# RUN: wasm-ld --experimental-pic --unresolved-symbols=import-dynamic -shared -o %t.wasm %t.o
33
# RUN: obj2yaml %t.wasm | FileCheck %s
44
# RUN: llvm-objdump --disassemble-symbols=__wasm_call_ctors,__wasm_apply_data_relocs --no-show-raw-insn --no-leading-addr %t.wasm | FileCheck %s --check-prefixes DIS
55

66
.functype func_external () -> ()
77

88
# Linker-synthesized globals
99
.globaltype __stack_pointer, i32
10-
.globaltype __table_base, i32, immutable
11-
.globaltype __memory_base, i32, immutable
10+
.globaltype __table_base, i32, immutable
11+
.globaltype __memory_base, i32, immutable
1212

1313
.section .data.data,"",@
1414
data:

lld/test/wasm/shared64.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# RUN: llvm-mc -filetype=obj -triple=wasm64-unknown-unknown -o %t.o %s
2-
# RUN: wasm-ld -mwasm64 --experimental-pic -shared -o %t.wasm %t.o
2+
# RUN: wasm-ld -mwasm64 --experimental-pic --unresolved-symbols=import-dynamic -shared -o %t.wasm %t.o
33
# RUN: obj2yaml %t.wasm | FileCheck %s
44
# RUN: llvm-objdump --disassemble-symbols=__wasm_call_ctors,__wasm_apply_data_relocs --no-show-raw-insn --no-leading-addr %t.wasm | FileCheck %s --check-prefixes DIS
55

lld/test/wasm/signature-mismatch.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ ret32_address_main:
9393
# RELOC-NEXT: - Index: 1
9494
# RELOC-NEXT: Kind: FUNCTION
9595
# RELOC-NEXT: Name: ret32
96-
# RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
96+
# RELOC-NEXT: Flags: [ ]
9797
# RELOC-NEXT: Function: 2
9898
# RELOC-NEXT: - Index: 2
9999
# RELOC-NEXT: Kind: DATA

lld/test/wasm/tag-section.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
; RUN: llc -filetype=obj -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -relocation-model=pic %p/Inputs/tag-section1.ll -o %t1.o
1212
; RUN: llc -filetype=obj -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -relocation-model=pic %p/Inputs/tag-section2.ll -o %t2.o
1313
; RUN: llc -filetype=obj -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -relocation-model=pic %s -o %t.o
14-
; RUN: wasm-ld --import-undefined --experimental-pic -pie -o %t.wasm %t.o %t1.o %t2.o
14+
; RUN: wasm-ld --import-undefined --experimental-pic --unresolved-symbols=import-dynamic -pie -o %t.wasm %t.o %t1.o %t2.o
1515
; RUN: obj2yaml %t.wasm | FileCheck %s --check-prefix=PIC
1616

1717
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"

0 commit comments

Comments
 (0)