[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:         ReturnTypes:
 | 
			
		||||
; 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:     FunctionTypes:   [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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:     Memories:
 | 
			
		||||
; RELOC-NEXT:       - Initial:         0x1
 | 
			
		||||
| 
						 | 
				
			
			@ -412,7 +414,7 @@
 | 
			
		|||
; RELOC-NEXT:       - Index:           8
 | 
			
		||||
; RELOC-NEXT:         Kind:            TABLE
 | 
			
		||||
; RELOC-NEXT:         Name:            __indirect_function_table
 | 
			
		||||
; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
 | 
			
		||||
; RELOC-NEXT:         Flags:           [ UNDEFINED, NO_STRIP ]
 | 
			
		||||
; RELOC-NEXT:         Table:           0
 | 
			
		||||
; RELOC-NEXT:       - Index:           9
 | 
			
		||||
; 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: llc -filetype=obj %s -o %t.o
 | 
			
		||||
; RUN: wasm-ld -r -o %t.wasm %t.hello.o %t.o
 | 
			
		||||
; RUN: obj2yaml %t.wasm | FileCheck %s
 | 
			
		||||
; RUN: wasm-ld -r -o %t2.o %t.hello.o %t.o
 | 
			
		||||
; 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"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +35,11 @@ entry:
 | 
			
		|||
; 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"
 | 
			
		||||
 | 
			
		||||
define void @_start() {
 | 
			
		||||
  ret void
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
; CHECK:      --- !WASM
 | 
			
		||||
; CHECK-NEXT: FileHeader:
 | 
			
		||||
; CHECK-NEXT:   Version:         0x1
 | 
			
		||||
| 
						 | 
				
			
			@ -63,16 +71,16 @@ entry:
 | 
			
		|||
; CHECK-NEXT:         Field:           bar_import
 | 
			
		||||
; CHECK-NEXT:         Kind:            FUNCTION
 | 
			
		||||
; CHECK-NEXT:         SigIndex:        1
 | 
			
		||||
; CHECK-NEXT:       - Module:          env
 | 
			
		||||
; CHECK-NEXT:         Field:           __indirect_function_table
 | 
			
		||||
; CHECK-NEXT:         Kind:            TABLE
 | 
			
		||||
; CHECK-NEXT:         Table:
 | 
			
		||||
; CHECK-NEXT:           Index:           0
 | 
			
		||||
; CHECK-NEXT:           ElemType:        FUNCREF
 | 
			
		||||
; CHECK-NEXT:           Limits:
 | 
			
		||||
; CHECK-NEXT:             Initial:         0x3
 | 
			
		||||
; CHECK-NEXT:   - Type:            FUNCTION
 | 
			
		||||
; CHECK-NEXT:     FunctionTypes:   [ 2, 1, 1 ]
 | 
			
		||||
; CHECK-NEXT:   - Type:            TABLE
 | 
			
		||||
; CHECK-NEXT:     Tables:
 | 
			
		||||
; CHECK-NEXT:       - Index:           0
 | 
			
		||||
; CHECK-NEXT:         ElemType:        FUNCREF
 | 
			
		||||
; CHECK-NEXT:         Limits:
 | 
			
		||||
; CHECK-NEXT:           Flags:           [ HAS_MAX ]
 | 
			
		||||
; CHECK-NEXT:           Initial:         0x4
 | 
			
		||||
; CHECK-NEXT:           Maximum:         0x4
 | 
			
		||||
; CHECK-NEXT:     FunctionTypes:   [ 2, 1, 1, 2 ]
 | 
			
		||||
; CHECK-NEXT:   - Type:            MEMORY
 | 
			
		||||
; CHECK-NEXT:     Memories:
 | 
			
		||||
; CHECK-NEXT:      - Initial:         0x1
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ declare i32 @ret32(i32, i64, i32) local_unnamed_addr
 | 
			
		|||
; RELOC-NEXT:       - Index:           3
 | 
			
		||||
; RELOC-NEXT:         Kind:            TABLE
 | 
			
		||||
; RELOC-NEXT:         Name:            __indirect_function_table
 | 
			
		||||
; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
 | 
			
		||||
; RELOC-NEXT:         Flags:           [ UNDEFINED, NO_STRIP ]
 | 
			
		||||
; RELOC-NEXT:         Table:           0
 | 
			
		||||
; RELOC-NEXT:       - Index:           4
 | 
			
		||||
; RELOC-NEXT:         Kind:            FUNCTION
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -149,16 +149,16 @@ entry:
 | 
			
		|||
; RELOC-NEXT:         Kind:            GLOBAL
 | 
			
		||||
; RELOC-NEXT:         GlobalType:      I32
 | 
			
		||||
; RELOC-NEXT:         GlobalMutable:   true
 | 
			
		||||
; 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:         0x1
 | 
			
		||||
; RELOC-NEXT:   - Type:            FUNCTION
 | 
			
		||||
; RELOC-NEXT:     FunctionTypes:   [ 0, 1, 1, 1, 1, 1 ]
 | 
			
		||||
; 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:         0x2
 | 
			
		||||
; RELOC-NEXT:           Maximum:         0x2
 | 
			
		||||
; RELOC-NEXT:   - Type:            MEMORY
 | 
			
		||||
; RELOC-NEXT:     Memories:
 | 
			
		||||
; RELOC-NEXT:       - Initial:         0x0
 | 
			
		||||
| 
						 | 
				
			
			@ -279,7 +279,7 @@ entry:
 | 
			
		|||
; RELOC-NEXT:       - Index:           8
 | 
			
		||||
; RELOC-NEXT:         Kind:            TABLE
 | 
			
		||||
; RELOC-NEXT:         Name:            __indirect_function_table
 | 
			
		||||
; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
 | 
			
		||||
; RELOC-NEXT:         Flags:           [ UNDEFINED, NO_STRIP ]
 | 
			
		||||
; RELOC-NEXT:         Table:           0
 | 
			
		||||
; RELOC-NEXT:   - Type:            CUSTOM
 | 
			
		||||
; RELOC-NEXT:     Name:            name
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -817,22 +817,31 @@ static TableSymbol *createUndefinedIndirectFunctionTable(StringRef name) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static TableSymbol *resolveIndirectFunctionTable() {
 | 
			
		||||
  // Even though we may not need a table, if the user explicitly specified
 | 
			
		||||
  // --import-table or --export-table, ensure a table is residualized.
 | 
			
		||||
  if (config->importTable)
 | 
			
		||||
    return createUndefinedIndirectFunctionTable(functionTableName);
 | 
			
		||||
  if (config->exportTable)
 | 
			
		||||
    return createDefinedIndirectFunctionTable(functionTableName);
 | 
			
		||||
 | 
			
		||||
  // Otherwise, check to the symtab to find the indirect function table.
 | 
			
		||||
  if (Symbol *sym = symtab->find(functionTableName)) {
 | 
			
		||||
    if (sym->isLive()) {
 | 
			
		||||
      if (auto *t = dyn_cast<TableSymbol>(sym)) {
 | 
			
		||||
        return t->isDefined()
 | 
			
		||||
                   ? t
 | 
			
		||||
                   : createDefinedIndirectFunctionTable(functionTableName);
 | 
			
		||||
      }
 | 
			
		||||
  Symbol *existingTable = symtab->find(functionTableName);
 | 
			
		||||
  if (existingTable) {
 | 
			
		||||
    if (!isa<TableSymbol>(existingTable)) {
 | 
			
		||||
      error(Twine("reserved symbol must be of type table: `") +
 | 
			
		||||
            functionTableName + "`");
 | 
			
		||||
      return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    if (existingTable->isDefined()) {
 | 
			
		||||
      error(Twine("reserved symbol must not be defined in input files: `") +
 | 
			
		||||
            functionTableName + "`");
 | 
			
		||||
      return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (config->importTable) {
 | 
			
		||||
    if (existingTable)
 | 
			
		||||
      return cast<TableSymbol>(existingTable);
 | 
			
		||||
    else
 | 
			
		||||
      return createUndefinedIndirectFunctionTable(functionTableName);
 | 
			
		||||
  } else if ((existingTable && existingTable->isLive()) ||
 | 
			
		||||
             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
 | 
			
		||||
| 
						 | 
				
			
			@ -1029,11 +1038,13 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
 | 
			
		|||
  // Do size optimizations: garbage collection
 | 
			
		||||
  markLive();
 | 
			
		||||
 | 
			
		||||
  // Provide the indirect funciton table if needed.
 | 
			
		||||
  WasmSym::indirectFunctionTable = resolveIndirectFunctionTable();
 | 
			
		||||
  if (!config->relocatable) {
 | 
			
		||||
    // Provide the indirect funciton table if needed.
 | 
			
		||||
    WasmSym::indirectFunctionTable = resolveIndirectFunctionTable();
 | 
			
		||||
 | 
			
		||||
  if (errorCount())
 | 
			
		||||
    return;
 | 
			
		||||
    if (errorCount())
 | 
			
		||||
      return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Write the result to the file.
 | 
			
		||||
  writeResult();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue