Skip to content

Commit 428cf71

Browse files
committed
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 fc5f51c with a fix for the MSan failure (it was not caused by this change, but it was revealed by the new tests).
1 parent a25b662 commit 428cf71

File tree

3 files changed

+162
-4
lines changed

3 files changed

+162
-4
lines changed

llvm/lib/Object/WasmObjectFile.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,7 @@ Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
13511351
break;
13521352
case wasm::WASM_EXTERNAL_TABLE:
13531353
Info.Kind = wasm::WASM_SYMBOL_TYPE_TABLE;
1354+
Info.ElementIndex = Ex.Index;
13541355
break;
13551356
default:
13561357
return make_error<GenericBinaryError>("unexpected export kind",
@@ -1667,10 +1668,18 @@ Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
16671668
Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
16681669
auto &Sym = getWasmSymbol(Symb);
16691670
if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1670-
isDefinedFunctionIndex(Sym.Info.ElementIndex))
1671-
return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset;
1672-
else
1673-
return getSymbolValue(Symb);
1671+
isDefinedFunctionIndex(Sym.Info.ElementIndex)) {
1672+
// For object files, use the section offset. The linker relies on this.
1673+
// For linked files, use the file offset. This behavior matches the way
1674+
// browsers print stack traces and is useful for binary size analysis.
1675+
// (see https://webassembly.github.io/spec/web-api/index.html#conventions)
1676+
uint32_t Adjustment = isRelocatableObject() || isSharedObject()
1677+
? 0
1678+
: Sections[CodeSection].Offset;
1679+
return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +
1680+
Adjustment;
1681+
}
1682+
return getSymbolValue(Symb);
16741683
}
16751684

16761685
uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# RUN: yaml2obj %s -o %t.wasm
2+
# RUN: llvm-nm %t.wasm | FileCheck %s
3+
4+
# CHECK: 0000009f T my_func_export
5+
# CHECK-NEXT: 0000002a D my_global_export
6+
# CHECK-NEXT: 00000000 D my_table_export
7+
8+
--- !WASM
9+
FileHeader:
10+
Version: 0x1
11+
Sections:
12+
- Type: TYPE
13+
Signatures:
14+
- Index: 0
15+
ParamTypes: []
16+
ReturnTypes: []
17+
- Type: IMPORT
18+
Imports:
19+
- Module: env
20+
Field: foo
21+
Kind: FUNCTION
22+
SigIndex: 0
23+
- Module: env
24+
Field: bar
25+
Kind: GLOBAL
26+
GlobalType: I32
27+
GlobalMutable: true
28+
- Module: env
29+
Field: memory
30+
Kind: MEMORY
31+
Memory:
32+
Minimum: 0x1
33+
- Type: FUNCTION
34+
FunctionTypes: [ 0 ]
35+
- Type: TABLE
36+
Tables:
37+
- Index: 0
38+
ElemType: FUNCREF
39+
Limits:
40+
Flags: [ HAS_MAX ]
41+
Minimum: 0x1
42+
Maximum: 0x1
43+
- Type: GLOBAL
44+
Globals:
45+
- Index: 1
46+
Mutable: false
47+
Type: I32
48+
InitExpr:
49+
Opcode: I32_CONST
50+
Value: 42
51+
- Type: EXPORT
52+
Exports:
53+
- Name: my_func_export
54+
Kind: FUNCTION
55+
Index: 1
56+
- Name: my_global_export
57+
Kind: GLOBAL
58+
Index: 1
59+
- Name: my_table_export
60+
Kind: TABLE
61+
Index: 0
62+
- Type: CODE
63+
Functions:
64+
- Index: 1
65+
Locals:
66+
Body: 00
67+
- Type: DATA
68+
Segments:
69+
- SectionOffset: 0
70+
InitFlags: 0
71+
Offset:
72+
Opcode: I32_CONST
73+
Value: 0
74+
Content: ''
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# RUN: yaml2obj %s -o %t.wasm
2+
# RUN: llvm-objdump -t %t.wasm | FileCheck %s
3+
#
4+
# CHECK: SYMBOL TABLE:
5+
# CHECK-NEXT: 0000009f g F CODE my_func_export
6+
# CHECK-NEXT: 0000002a g O DATA my_global_export
7+
# CHECK-NEXT: 00000000 g TABLE my_table_export
8+
9+
--- !WASM
10+
FileHeader:
11+
Version: 0x1
12+
Sections:
13+
- Type: TYPE
14+
Signatures:
15+
- Index: 0
16+
ParamTypes: []
17+
ReturnTypes: []
18+
- Type: IMPORT
19+
Imports:
20+
- Module: env
21+
Field: foo
22+
Kind: FUNCTION
23+
SigIndex: 0
24+
- Module: env
25+
Field: bar
26+
Kind: GLOBAL
27+
GlobalType: I32
28+
GlobalMutable: true
29+
- Module: env
30+
Field: memory
31+
Kind: MEMORY
32+
Memory:
33+
Minimum: 0x1
34+
- Type: FUNCTION
35+
FunctionTypes: [ 0 ]
36+
- Type: TABLE
37+
Tables:
38+
- Index: 0
39+
ElemType: FUNCREF
40+
Limits:
41+
Flags: [ HAS_MAX ]
42+
Minimum: 0x1
43+
Maximum: 0x1
44+
- Type: GLOBAL
45+
Globals:
46+
- Index: 1
47+
Mutable: false
48+
Type: I32
49+
InitExpr:
50+
Opcode: I32_CONST
51+
Value: 42
52+
- Type: EXPORT
53+
Exports:
54+
- Name: my_func_export
55+
Kind: FUNCTION
56+
Index: 1
57+
- Name: my_global_export
58+
Kind: GLOBAL
59+
Index: 1
60+
- Name: my_table_export
61+
Kind: TABLE
62+
Index: 0
63+
- Type: CODE
64+
Functions:
65+
- Index: 1
66+
Locals:
67+
Body: 00
68+
- Type: DATA
69+
Segments:
70+
- SectionOffset: 0
71+
InitFlags: 0
72+
Offset:
73+
Opcode: I32_CONST
74+
Value: 0
75+
Content: ''

0 commit comments

Comments
 (0)