[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
This commit is contained in:
parent
da986511fb
commit
b99147b4fa
|
|
@ -231,17 +231,19 @@
|
||||||
; RELOC-NEXT: ParamTypes: []
|
; RELOC-NEXT: ParamTypes: []
|
||||||
; RELOC-NEXT: ReturnTypes:
|
; RELOC-NEXT: ReturnTypes:
|
||||||
; RELOC-NEXT: - I32
|
; RELOC-NEXT: - I32
|
||||||
|
; RELOC-NEXT: - Type: IMPORT
|
||||||
|
; RELOC-NEXT: Imports:
|
||||||
|
; RELOC-NEXT: - Module: env
|
||||||
|
; RELOC-NEXT: Field: __indirect_function_table
|
||||||
|
; RELOC-NEXT: Kind: TABLE
|
||||||
|
; RELOC-NEXT: Table:
|
||||||
|
; RELOC-NEXT: Index: 0
|
||||||
|
; RELOC-NEXT: ElemType: FUNCREF
|
||||||
|
; RELOC-NEXT: Limits:
|
||||||
|
; RELOC-NEXT: Initial: 0x3
|
||||||
; RELOC-NEXT: - Type: FUNCTION
|
; RELOC-NEXT: - Type: FUNCTION
|
||||||
; RELOC-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
; RELOC-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
; RELOC-NEXT: 0, 0 ]
|
; RELOC-NEXT: 0, 0 ]
|
||||||
; RELOC-NEXT: - Type: TABLE
|
|
||||||
; RELOC-NEXT: Tables:
|
|
||||||
; RELOC-NEXT: - Index: 0
|
|
||||||
; RELOC-NEXT: ElemType: FUNCREF
|
|
||||||
; RELOC-NEXT: Limits:
|
|
||||||
; RELOC-NEXT: Flags: [ HAS_MAX ]
|
|
||||||
; RELOC-NEXT: Initial: 0x7
|
|
||||||
; RELOC-NEXT: Maximum: 0x7
|
|
||||||
; RELOC-NEXT: - Type: MEMORY
|
; RELOC-NEXT: - Type: MEMORY
|
||||||
; RELOC-NEXT: Memories:
|
; RELOC-NEXT: Memories:
|
||||||
; RELOC-NEXT: - Initial: 0x1
|
; RELOC-NEXT: - Initial: 0x1
|
||||||
|
|
@ -412,7 +414,7 @@
|
||||||
; RELOC-NEXT: - Index: 8
|
; RELOC-NEXT: - Index: 8
|
||||||
; RELOC-NEXT: Kind: TABLE
|
; RELOC-NEXT: Kind: TABLE
|
||||||
; RELOC-NEXT: Name: __indirect_function_table
|
; RELOC-NEXT: Name: __indirect_function_table
|
||||||
; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
|
; RELOC-NEXT: Flags: [ UNDEFINED, NO_STRIP ]
|
||||||
; RELOC-NEXT: Table: 0
|
; RELOC-NEXT: Table: 0
|
||||||
; RELOC-NEXT: - Index: 9
|
; RELOC-NEXT: - Index: 9
|
||||||
; RELOC-NEXT: Kind: FUNCTION
|
; RELOC-NEXT: Kind: FUNCTION
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
; RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/hello.s -o %t.hello.o
|
; RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/hello.s -o %t.hello.o
|
||||||
; RUN: llc -filetype=obj %s -o %t.o
|
; RUN: llc -filetype=obj %s -o %t.o
|
||||||
; RUN: wasm-ld -r -o %t.wasm %t.hello.o %t.o
|
; RUN: wasm-ld -r -o %t2.o %t.hello.o %t.o
|
||||||
; RUN: obj2yaml %t.wasm | FileCheck %s
|
; RUN: obj2yaml %t2.o | FileCheck %s
|
||||||
|
|
||||||
|
; Verify the resulting object can be used as linker input
|
||||||
|
; RUN: wasm-ld --allow-undefined -o %t.wasm %t2.o --export-table
|
||||||
|
|
||||||
target triple = "wasm32-unknown-unknown"
|
target triple = "wasm32-unknown-unknown"
|
||||||
|
|
||||||
|
|
@ -32,6 +35,11 @@ entry:
|
||||||
; Test that __attribute__(used) (i.e NO_STRIP) is preserved in the relocated symbol table
|
; Test that __attribute__(used) (i.e NO_STRIP) is preserved in the relocated symbol table
|
||||||
@llvm.used = appending global [1 x i8*] [i8* bitcast (i32 ()* @my_func to i8*)], section "llvm.metadata"
|
@llvm.used = appending global [1 x i8*] [i8* bitcast (i32 ()* @my_func to i8*)], section "llvm.metadata"
|
||||||
|
|
||||||
|
define void @_start() {
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
; CHECK: --- !WASM
|
; CHECK: --- !WASM
|
||||||
; CHECK-NEXT: FileHeader:
|
; CHECK-NEXT: FileHeader:
|
||||||
; CHECK-NEXT: Version: 0x1
|
; CHECK-NEXT: Version: 0x1
|
||||||
|
|
@ -63,16 +71,16 @@ entry:
|
||||||
; CHECK-NEXT: Field: bar_import
|
; CHECK-NEXT: Field: bar_import
|
||||||
; CHECK-NEXT: Kind: FUNCTION
|
; CHECK-NEXT: Kind: FUNCTION
|
||||||
; CHECK-NEXT: SigIndex: 1
|
; CHECK-NEXT: SigIndex: 1
|
||||||
; CHECK-NEXT: - Type: FUNCTION
|
; CHECK-NEXT: - Module: env
|
||||||
; CHECK-NEXT: FunctionTypes: [ 2, 1, 1 ]
|
; CHECK-NEXT: Field: __indirect_function_table
|
||||||
; CHECK-NEXT: - Type: TABLE
|
; CHECK-NEXT: Kind: TABLE
|
||||||
; CHECK-NEXT: Tables:
|
; CHECK-NEXT: Table:
|
||||||
; CHECK-NEXT: - Index: 0
|
; CHECK-NEXT: Index: 0
|
||||||
; CHECK-NEXT: ElemType: FUNCREF
|
; CHECK-NEXT: ElemType: FUNCREF
|
||||||
; CHECK-NEXT: Limits:
|
; CHECK-NEXT: Limits:
|
||||||
; CHECK-NEXT: Flags: [ HAS_MAX ]
|
; CHECK-NEXT: Initial: 0x3
|
||||||
; CHECK-NEXT: Initial: 0x4
|
; CHECK-NEXT: - Type: FUNCTION
|
||||||
; CHECK-NEXT: Maximum: 0x4
|
; CHECK-NEXT: FunctionTypes: [ 2, 1, 1, 2 ]
|
||||||
; CHECK-NEXT: - Type: MEMORY
|
; CHECK-NEXT: - Type: MEMORY
|
||||||
; CHECK-NEXT: Memories:
|
; CHECK-NEXT: Memories:
|
||||||
; CHECK-NEXT: - Initial: 0x1
|
; CHECK-NEXT: - Initial: 0x1
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ declare i32 @ret32(i32, i64, i32) local_unnamed_addr
|
||||||
; RELOC-NEXT: - Index: 3
|
; RELOC-NEXT: - Index: 3
|
||||||
; RELOC-NEXT: Kind: TABLE
|
; RELOC-NEXT: Kind: TABLE
|
||||||
; RELOC-NEXT: Name: __indirect_function_table
|
; RELOC-NEXT: Name: __indirect_function_table
|
||||||
; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
|
; RELOC-NEXT: Flags: [ UNDEFINED, NO_STRIP ]
|
||||||
; RELOC-NEXT: Table: 0
|
; RELOC-NEXT: Table: 0
|
||||||
; RELOC-NEXT: - Index: 4
|
; RELOC-NEXT: - Index: 4
|
||||||
; RELOC-NEXT: Kind: FUNCTION
|
; RELOC-NEXT: Kind: FUNCTION
|
||||||
|
|
|
||||||
|
|
@ -149,16 +149,16 @@ entry:
|
||||||
; RELOC-NEXT: Kind: GLOBAL
|
; RELOC-NEXT: Kind: GLOBAL
|
||||||
; RELOC-NEXT: GlobalType: I32
|
; RELOC-NEXT: GlobalType: I32
|
||||||
; RELOC-NEXT: GlobalMutable: true
|
; RELOC-NEXT: GlobalMutable: true
|
||||||
; RELOC-NEXT: - Type: FUNCTION
|
; RELOC-NEXT: - Module: env
|
||||||
; RELOC-NEXT: FunctionTypes: [ 0, 1, 1, 1, 1, 1 ]
|
; RELOC-NEXT: Field: __indirect_function_table
|
||||||
; RELOC-NEXT: - Type: TABLE
|
; RELOC-NEXT: Kind: TABLE
|
||||||
; RELOC-NEXT: Tables:
|
; RELOC-NEXT: Table:
|
||||||
; RELOC-NEXT: - Index: 0
|
; RELOC-NEXT: Index: 0
|
||||||
; RELOC-NEXT: ElemType: FUNCREF
|
; RELOC-NEXT: ElemType: FUNCREF
|
||||||
; RELOC-NEXT: Limits:
|
; RELOC-NEXT: Limits:
|
||||||
; RELOC-NEXT: Flags: [ HAS_MAX ]
|
; RELOC-NEXT: Initial: 0x1
|
||||||
; RELOC-NEXT: Initial: 0x2
|
; RELOC-NEXT: - Type: FUNCTION
|
||||||
; RELOC-NEXT: Maximum: 0x2
|
; RELOC-NEXT: FunctionTypes: [ 0, 1, 1, 1, 1, 1 ]
|
||||||
; RELOC-NEXT: - Type: MEMORY
|
; RELOC-NEXT: - Type: MEMORY
|
||||||
; RELOC-NEXT: Memories:
|
; RELOC-NEXT: Memories:
|
||||||
; RELOC-NEXT: - Initial: 0x0
|
; RELOC-NEXT: - Initial: 0x0
|
||||||
|
|
@ -279,7 +279,7 @@ entry:
|
||||||
; RELOC-NEXT: - Index: 8
|
; RELOC-NEXT: - Index: 8
|
||||||
; RELOC-NEXT: Kind: TABLE
|
; RELOC-NEXT: Kind: TABLE
|
||||||
; RELOC-NEXT: Name: __indirect_function_table
|
; RELOC-NEXT: Name: __indirect_function_table
|
||||||
; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
|
; RELOC-NEXT: Flags: [ UNDEFINED, NO_STRIP ]
|
||||||
; RELOC-NEXT: Table: 0
|
; RELOC-NEXT: Table: 0
|
||||||
; RELOC-NEXT: - Type: CUSTOM
|
; RELOC-NEXT: - Type: CUSTOM
|
||||||
; RELOC-NEXT: Name: name
|
; RELOC-NEXT: Name: name
|
||||||
|
|
|
||||||
|
|
@ -817,22 +817,31 @@ static TableSymbol *createUndefinedIndirectFunctionTable(StringRef name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static TableSymbol *resolveIndirectFunctionTable() {
|
static TableSymbol *resolveIndirectFunctionTable() {
|
||||||
// Even though we may not need a table, if the user explicitly specified
|
Symbol *existingTable = symtab->find(functionTableName);
|
||||||
// --import-table or --export-table, ensure a table is residualized.
|
if (existingTable) {
|
||||||
if (config->importTable)
|
if (!isa<TableSymbol>(existingTable)) {
|
||||||
return createUndefinedIndirectFunctionTable(functionTableName);
|
error(Twine("reserved symbol must be of type table: `") +
|
||||||
if (config->exportTable)
|
functionTableName + "`");
|
||||||
return createDefinedIndirectFunctionTable(functionTableName);
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (existingTable->isDefined()) {
|
||||||
|
error(Twine("reserved symbol must not be defined in input files: `") +
|
||||||
|
functionTableName + "`");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Otherwise, check to the symtab to find the indirect function table.
|
if (config->importTable) {
|
||||||
if (Symbol *sym = symtab->find(functionTableName)) {
|
if (existingTable)
|
||||||
if (sym->isLive()) {
|
return cast<TableSymbol>(existingTable);
|
||||||
if (auto *t = dyn_cast<TableSymbol>(sym)) {
|
else
|
||||||
return t->isDefined()
|
return createUndefinedIndirectFunctionTable(functionTableName);
|
||||||
? t
|
} else if ((existingTable && existingTable->isLive()) ||
|
||||||
: createDefinedIndirectFunctionTable(functionTableName);
|
config->exportTable) {
|
||||||
}
|
// A defined table is required. Either because the user request an exported
|
||||||
}
|
// table or because the table symbol is already live. The existing table is
|
||||||
|
// guaranteed to be undefined due to the check above.
|
||||||
|
return createDefinedIndirectFunctionTable(functionTableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// An indirect function table will only be present in the symbol table if
|
// An indirect function table will only be present in the symbol table if
|
||||||
|
|
@ -1029,11 +1038,13 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
|
||||||
// Do size optimizations: garbage collection
|
// Do size optimizations: garbage collection
|
||||||
markLive();
|
markLive();
|
||||||
|
|
||||||
|
if (!config->relocatable) {
|
||||||
// Provide the indirect funciton table if needed.
|
// Provide the indirect funciton table if needed.
|
||||||
WasmSym::indirectFunctionTable = resolveIndirectFunctionTable();
|
WasmSym::indirectFunctionTable = resolveIndirectFunctionTable();
|
||||||
|
|
||||||
if (errorCount())
|
if (errorCount())
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Write the result to the file.
|
// Write the result to the file.
|
||||||
writeResult();
|
writeResult();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue