Reland "[WebAssembly][Object]Use file offset as function symbol address for linked files (#76198)"

WebAssembly doesn't have a single virtual memory space the way other object
formats or architectures do, so "addresses" mean different things depending
on the context.
Function symbol addresses in object files are offsets from the start of the code
section. This is good for linking and relocation. However when dealing with
linked binaries, offsets from the start of the file/module are more often
used (e.g. for stack traces in browsers), and are more useful for use
cases like binary size attribution. This PR changes Object to use
the file offset instead of the section offset for function symbols, but
only for linked (non-DSO) files.

This is a reland of fc5f51cf with a fix for the MSan failure (it was not caused
by this change, but it was revealed by the new tests).
This commit is contained in:
Derek Schuff
2023-12-21 14:56:03 -08:00
parent a25b66217f
commit 428cf71ffa
3 changed files with 162 additions and 4 deletions

View File

@@ -1351,6 +1351,7 @@ Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
break;
case wasm::WASM_EXTERNAL_TABLE:
Info.Kind = wasm::WASM_SYMBOL_TYPE_TABLE;
Info.ElementIndex = Ex.Index;
break;
default:
return make_error<GenericBinaryError>("unexpected export kind",
@@ -1667,10 +1668,18 @@ Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
auto &Sym = getWasmSymbol(Symb);
if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
isDefinedFunctionIndex(Sym.Info.ElementIndex))
return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset;
else
return getSymbolValue(Symb);
isDefinedFunctionIndex(Sym.Info.ElementIndex)) {
// For object files, use the section offset. The linker relies on this.
// For linked files, use the file offset. This behavior matches the way
// browsers print stack traces and is useful for binary size analysis.
// (see https://webassembly.github.io/spec/web-api/index.html#conventions)
uint32_t Adjustment = isRelocatableObject() || isSharedObject()
? 0
: Sections[CodeSection].Offset;
return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +
Adjustment;
}
return getSymbolValue(Symb);
}
uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {

View File

@@ -0,0 +1,74 @@
# RUN: yaml2obj %s -o %t.wasm
# RUN: llvm-nm %t.wasm | FileCheck %s
# CHECK: 0000009f T my_func_export
# CHECK-NEXT: 0000002a D my_global_export
# CHECK-NEXT: 00000000 D my_table_export
--- !WASM
FileHeader:
Version: 0x1
Sections:
- Type: TYPE
Signatures:
- Index: 0
ParamTypes: []
ReturnTypes: []
- Type: IMPORT
Imports:
- Module: env
Field: foo
Kind: FUNCTION
SigIndex: 0
- Module: env
Field: bar
Kind: GLOBAL
GlobalType: I32
GlobalMutable: true
- Module: env
Field: memory
Kind: MEMORY
Memory:
Minimum: 0x1
- Type: FUNCTION
FunctionTypes: [ 0 ]
- Type: TABLE
Tables:
- Index: 0
ElemType: FUNCREF
Limits:
Flags: [ HAS_MAX ]
Minimum: 0x1
Maximum: 0x1
- Type: GLOBAL
Globals:
- Index: 1
Mutable: false
Type: I32
InitExpr:
Opcode: I32_CONST
Value: 42
- Type: EXPORT
Exports:
- Name: my_func_export
Kind: FUNCTION
Index: 1
- Name: my_global_export
Kind: GLOBAL
Index: 1
- Name: my_table_export
Kind: TABLE
Index: 0
- Type: CODE
Functions:
- Index: 1
Locals:
Body: 00
- Type: DATA
Segments:
- SectionOffset: 0
InitFlags: 0
Offset:
Opcode: I32_CONST
Value: 0
Content: ''

View File

@@ -0,0 +1,75 @@
# RUN: yaml2obj %s -o %t.wasm
# RUN: llvm-objdump -t %t.wasm | FileCheck %s
#
# CHECK: SYMBOL TABLE:
# CHECK-NEXT: 0000009f g F CODE my_func_export
# CHECK-NEXT: 0000002a g O DATA my_global_export
# CHECK-NEXT: 00000000 g TABLE my_table_export
--- !WASM
FileHeader:
Version: 0x1
Sections:
- Type: TYPE
Signatures:
- Index: 0
ParamTypes: []
ReturnTypes: []
- Type: IMPORT
Imports:
- Module: env
Field: foo
Kind: FUNCTION
SigIndex: 0
- Module: env
Field: bar
Kind: GLOBAL
GlobalType: I32
GlobalMutable: true
- Module: env
Field: memory
Kind: MEMORY
Memory:
Minimum: 0x1
- Type: FUNCTION
FunctionTypes: [ 0 ]
- Type: TABLE
Tables:
- Index: 0
ElemType: FUNCREF
Limits:
Flags: [ HAS_MAX ]
Minimum: 0x1
Maximum: 0x1
- Type: GLOBAL
Globals:
- Index: 1
Mutable: false
Type: I32
InitExpr:
Opcode: I32_CONST
Value: 42
- Type: EXPORT
Exports:
- Name: my_func_export
Kind: FUNCTION
Index: 1
- Name: my_global_export
Kind: GLOBAL
Index: 1
- Name: my_table_export
Kind: TABLE
Index: 0
- Type: CODE
Functions:
- Index: 1
Locals:
Body: 00
- Type: DATA
Segments:
- SectionOffset: 0
InitFlags: 0
Offset:
Opcode: I32_CONST
Value: 0
Content: ''