Skip to content

Commit b99147b

Browse files
committed
[lld][WebAssembly] Don't defined indirect function table in relocatable output
Object files (and the output --relocatable) should never define __indirect_function_table. It should always be linker synthesized with the final output executable. Differential Revision: https://reviews.llvm.org/D94993
1 parent da98651 commit b99147b

File tree

5 files changed

+70
-49
lines changed

5 files changed

+70
-49
lines changed

lld/test/wasm/locals-duplicate.test

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -231,17 +231,19 @@
231231
; RELOC-NEXT: ParamTypes: []
232232
; RELOC-NEXT: ReturnTypes:
233233
; RELOC-NEXT: - I32
234+
; RELOC-NEXT: - Type: IMPORT
235+
; RELOC-NEXT: Imports:
236+
; RELOC-NEXT: - Module: env
237+
; RELOC-NEXT: Field: __indirect_function_table
238+
; RELOC-NEXT: Kind: TABLE
239+
; RELOC-NEXT: Table:
240+
; RELOC-NEXT: Index: 0
241+
; RELOC-NEXT: ElemType: FUNCREF
242+
; RELOC-NEXT: Limits:
243+
; RELOC-NEXT: Initial: 0x3
234244
; RELOC-NEXT: - Type: FUNCTION
235245
; RELOC-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
236246
; RELOC-NEXT: 0, 0 ]
237-
; RELOC-NEXT: - Type: TABLE
238-
; RELOC-NEXT: Tables:
239-
; RELOC-NEXT: - Index: 0
240-
; RELOC-NEXT: ElemType: FUNCREF
241-
; RELOC-NEXT: Limits:
242-
; RELOC-NEXT: Flags: [ HAS_MAX ]
243-
; RELOC-NEXT: Initial: 0x7
244-
; RELOC-NEXT: Maximum: 0x7
245247
; RELOC-NEXT: - Type: MEMORY
246248
; RELOC-NEXT: Memories:
247249
; RELOC-NEXT: - Initial: 0x1
@@ -412,7 +414,7 @@
412414
; RELOC-NEXT: - Index: 8
413415
; RELOC-NEXT: Kind: TABLE
414416
; RELOC-NEXT: Name: __indirect_function_table
415-
; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
417+
; RELOC-NEXT: Flags: [ UNDEFINED, NO_STRIP ]
416418
; RELOC-NEXT: Table: 0
417419
; RELOC-NEXT: - Index: 9
418420
; RELOC-NEXT: Kind: FUNCTION

lld/test/wasm/relocatable.ll

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
; RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/hello.s -o %t.hello.o
22
; RUN: llc -filetype=obj %s -o %t.o
3-
; RUN: wasm-ld -r -o %t.wasm %t.hello.o %t.o
4-
; RUN: obj2yaml %t.wasm | FileCheck %s
3+
; RUN: wasm-ld -r -o %t2.o %t.hello.o %t.o
4+
; RUN: obj2yaml %t2.o | FileCheck %s
5+
6+
; Verify the resulting object can be used as linker input
7+
; RUN: wasm-ld --allow-undefined -o %t.wasm %t2.o --export-table
58

69
target triple = "wasm32-unknown-unknown"
710

@@ -32,6 +35,11 @@ entry:
3235
; Test that __attribute__(used) (i.e NO_STRIP) is preserved in the relocated symbol table
3336
@llvm.used = appending global [1 x i8*] [i8* bitcast (i32 ()* @my_func to i8*)], section "llvm.metadata"
3437

38+
define void @_start() {
39+
ret void
40+
}
41+
42+
3543
; CHECK: --- !WASM
3644
; CHECK-NEXT: FileHeader:
3745
; CHECK-NEXT: Version: 0x1
@@ -63,16 +71,16 @@ entry:
6371
; CHECK-NEXT: Field: bar_import
6472
; CHECK-NEXT: Kind: FUNCTION
6573
; CHECK-NEXT: SigIndex: 1
74+
; CHECK-NEXT: - Module: env
75+
; CHECK-NEXT: Field: __indirect_function_table
76+
; CHECK-NEXT: Kind: TABLE
77+
; CHECK-NEXT: Table:
78+
; CHECK-NEXT: Index: 0
79+
; CHECK-NEXT: ElemType: FUNCREF
80+
; CHECK-NEXT: Limits:
81+
; CHECK-NEXT: Initial: 0x3
6682
; CHECK-NEXT: - Type: FUNCTION
67-
; CHECK-NEXT: FunctionTypes: [ 2, 1, 1 ]
68-
; CHECK-NEXT: - Type: TABLE
69-
; CHECK-NEXT: Tables:
70-
; CHECK-NEXT: - Index: 0
71-
; CHECK-NEXT: ElemType: FUNCREF
72-
; CHECK-NEXT: Limits:
73-
; CHECK-NEXT: Flags: [ HAS_MAX ]
74-
; CHECK-NEXT: Initial: 0x4
75-
; CHECK-NEXT: Maximum: 0x4
83+
; CHECK-NEXT: FunctionTypes: [ 2, 1, 1, 2 ]
7684
; CHECK-NEXT: - Type: MEMORY
7785
; CHECK-NEXT: Memories:
7886
; CHECK-NEXT: - Initial: 0x1

lld/test/wasm/signature-mismatch.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ declare i32 @ret32(i32, i64, i32) local_unnamed_addr
8282
; RELOC-NEXT: - Index: 3
8383
; RELOC-NEXT: Kind: TABLE
8484
; RELOC-NEXT: Name: __indirect_function_table
85-
; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
85+
; RELOC-NEXT: Flags: [ UNDEFINED, NO_STRIP ]
8686
; RELOC-NEXT: Table: 0
8787
; RELOC-NEXT: - Index: 4
8888
; RELOC-NEXT: Kind: FUNCTION

lld/test/wasm/weak-alias.ll

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,16 +149,16 @@ entry:
149149
; RELOC-NEXT: Kind: GLOBAL
150150
; RELOC-NEXT: GlobalType: I32
151151
; RELOC-NEXT: GlobalMutable: true
152+
; RELOC-NEXT: - Module: env
153+
; RELOC-NEXT: Field: __indirect_function_table
154+
; RELOC-NEXT: Kind: TABLE
155+
; RELOC-NEXT: Table:
156+
; RELOC-NEXT: Index: 0
157+
; RELOC-NEXT: ElemType: FUNCREF
158+
; RELOC-NEXT: Limits:
159+
; RELOC-NEXT: Initial: 0x1
152160
; RELOC-NEXT: - Type: FUNCTION
153161
; RELOC-NEXT: FunctionTypes: [ 0, 1, 1, 1, 1, 1 ]
154-
; RELOC-NEXT: - Type: TABLE
155-
; RELOC-NEXT: Tables:
156-
; RELOC-NEXT: - Index: 0
157-
; RELOC-NEXT: ElemType: FUNCREF
158-
; RELOC-NEXT: Limits:
159-
; RELOC-NEXT: Flags: [ HAS_MAX ]
160-
; RELOC-NEXT: Initial: 0x2
161-
; RELOC-NEXT: Maximum: 0x2
162162
; RELOC-NEXT: - Type: MEMORY
163163
; RELOC-NEXT: Memories:
164164
; RELOC-NEXT: - Initial: 0x0
@@ -279,7 +279,7 @@ entry:
279279
; RELOC-NEXT: - Index: 8
280280
; RELOC-NEXT: Kind: TABLE
281281
; RELOC-NEXT: Name: __indirect_function_table
282-
; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
282+
; RELOC-NEXT: Flags: [ UNDEFINED, NO_STRIP ]
283283
; RELOC-NEXT: Table: 0
284284
; RELOC-NEXT: - Type: CUSTOM
285285
; RELOC-NEXT: Name: name

lld/wasm/Driver.cpp

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -817,22 +817,31 @@ static TableSymbol *createUndefinedIndirectFunctionTable(StringRef name) {
817817
}
818818

819819
static TableSymbol *resolveIndirectFunctionTable() {
820-
// Even though we may not need a table, if the user explicitly specified
821-
// --import-table or --export-table, ensure a table is residualized.
822-
if (config->importTable)
823-
return createUndefinedIndirectFunctionTable(functionTableName);
824-
if (config->exportTable)
825-
return createDefinedIndirectFunctionTable(functionTableName);
826-
827-
// Otherwise, check to the symtab to find the indirect function table.
828-
if (Symbol *sym = symtab->find(functionTableName)) {
829-
if (sym->isLive()) {
830-
if (auto *t = dyn_cast<TableSymbol>(sym)) {
831-
return t->isDefined()
832-
? t
833-
: createDefinedIndirectFunctionTable(functionTableName);
834-
}
820+
Symbol *existingTable = symtab->find(functionTableName);
821+
if (existingTable) {
822+
if (!isa<TableSymbol>(existingTable)) {
823+
error(Twine("reserved symbol must be of type table: `") +
824+
functionTableName + "`");
825+
return nullptr;
835826
}
827+
if (existingTable->isDefined()) {
828+
error(Twine("reserved symbol must not be defined in input files: `") +
829+
functionTableName + "`");
830+
return nullptr;
831+
}
832+
}
833+
834+
if (config->importTable) {
835+
if (existingTable)
836+
return cast<TableSymbol>(existingTable);
837+
else
838+
return createUndefinedIndirectFunctionTable(functionTableName);
839+
} else if ((existingTable && existingTable->isLive()) ||
840+
config->exportTable) {
841+
// A defined table is required. Either because the user request an exported
842+
// table or because the table symbol is already live. The existing table is
843+
// guaranteed to be undefined due to the check above.
844+
return createDefinedIndirectFunctionTable(functionTableName);
836845
}
837846

838847
// An indirect function table will only be present in the symbol table if
@@ -1029,11 +1038,13 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
10291038
// Do size optimizations: garbage collection
10301039
markLive();
10311040

1032-
// Provide the indirect funciton table if needed.
1033-
WasmSym::indirectFunctionTable = resolveIndirectFunctionTable();
1041+
if (!config->relocatable) {
1042+
// Provide the indirect funciton table if needed.
1043+
WasmSym::indirectFunctionTable = resolveIndirectFunctionTable();
10341044

1035-
if (errorCount())
1036-
return;
1045+
if (errorCount())
1046+
return;
1047+
}
10371048

10381049
// Write the result to the file.
10391050
writeResult();

0 commit comments

Comments
 (0)