Skip to content

Commit 2eaeae7

Browse files
authored
[Object][Wasm] Use offset instead of index for Global address and store size (#81781)
Currently the address reported by binutils for a global is its index; but its offset (in the file or section) is more useful for binary size attribution. This PR treats globals similarly to functions, and tracks their offset and size. It also centralizes the logic differentiating linked from object and dylib files (where section addresses are 0).
1 parent a1d4c69 commit 2eaeae7

File tree

6 files changed

+37
-18
lines changed

6 files changed

+37
-18
lines changed

llvm/include/llvm/BinaryFormat/Wasm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,8 @@ struct WasmGlobal {
350350
WasmGlobalType Type;
351351
WasmInitExpr InitExpr;
352352
StringRef SymbolName; // from the "linking" section
353+
uint32_t Offset; // Offset of the definition in the binary's Global section
354+
uint32_t Size; // Size of the definition in the binary's Global section
353355
};
354356

355357
struct WasmTag {

llvm/include/llvm/Object/Wasm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ class WasmObjectFile : public ObjectFile {
239239
bool isValidSectionSymbol(uint32_t Index) const;
240240
wasm::WasmFunction &getDefinedFunction(uint32_t Index);
241241
const wasm::WasmFunction &getDefinedFunction(uint32_t Index) const;
242-
wasm::WasmGlobal &getDefinedGlobal(uint32_t Index);
242+
const wasm::WasmGlobal &getDefinedGlobal(uint32_t Index) const;
243243
wasm::WasmTag &getDefinedTag(uint32_t Index);
244244

245245
const WasmSection &getWasmSection(DataRefImpl Ref) const;

llvm/lib/Object/WasmObjectFile.cpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,18 +1400,20 @@ Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
14001400

14011401
Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
14021402
GlobalSection = Sections.size();
1403+
const uint8_t *SectionStart = Ctx.Ptr;
14031404
uint32_t Count = readVaruint32(Ctx);
14041405
Globals.reserve(Count);
14051406
while (Count--) {
14061407
wasm::WasmGlobal Global;
14071408
Global.Index = NumImportedGlobals + Globals.size();
1409+
const uint8_t *GlobalStart = Ctx.Ptr;
1410+
Global.Offset = static_cast<uint32_t>(GlobalStart - SectionStart);
14081411
auto GlobalOpcode = readVaruint32(Ctx);
1409-
auto GlobalType = parseValType(Ctx, GlobalOpcode);
1410-
// assert(GlobalType <= std::numeric_limits<wasm::ValType>::max());
1411-
Global.Type.Type = (uint8_t)GlobalType;
1412+
Global.Type.Type = (uint8_t)parseValType(Ctx, GlobalOpcode);
14121413
Global.Type.Mutable = readVaruint1(Ctx);
14131414
if (Error Err = readInitExpr(Global.InitExpr, Ctx))
14141415
return Err;
1416+
Global.Size = static_cast<uint32_t>(Ctx.Ptr - GlobalStart);
14151417
Globals.push_back(Global);
14161418
}
14171419
if (Ctx.Ptr != Ctx.End)
@@ -1564,7 +1566,7 @@ WasmObjectFile::getDefinedFunction(uint32_t Index) const {
15641566
return Functions[Index - NumImportedFunctions];
15651567
}
15661568

1567-
wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
1569+
const wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) const {
15681570
assert(isDefinedGlobalIndex(Index));
15691571
return Globals[Index - NumImportedGlobals];
15701572
}
@@ -1815,18 +1817,22 @@ Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
18151817

18161818
Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
18171819
auto &Sym = getWasmSymbol(Symb);
1820+
if (!Sym.isDefined())
1821+
return 0;
1822+
Expected<section_iterator> Sec = getSymbolSection(Symb);
1823+
if (!Sec)
1824+
return Sec.takeError();
1825+
uint32_t SectionAddress = getSectionAddress(Sec.get()->getRawDataRefImpl());
18181826
if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
18191827
isDefinedFunctionIndex(Sym.Info.ElementIndex)) {
1820-
// For object files, use the section offset. The linker relies on this.
1821-
// For linked files, use the file offset. This behavior matches the way
1822-
// browsers print stack traces and is useful for binary size analysis.
1823-
// (see https://webassembly.github.io/spec/web-api/index.html#conventions)
1824-
uint32_t Adjustment = isRelocatableObject() || isSharedObject()
1825-
? 0
1826-
: Sections[CodeSection].Offset;
18271828
return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +
1828-
Adjustment;
1829+
SectionAddress;
18291830
}
1831+
if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL &&
1832+
isDefinedGlobalIndex(Sym.Info.ElementIndex)) {
1833+
return getDefinedGlobal(Sym.Info.ElementIndex).Offset + SectionAddress;
1834+
}
1835+
18301836
return getSymbolValue(Symb);
18311837
}
18321838

@@ -1936,6 +1942,8 @@ uint32_t WasmObjectFile::getSymbolSize(SymbolRef Symb) const {
19361942
const WasmSymbol &Sym = getWasmSymbol(Symb);
19371943
if (!Sym.isDefined())
19381944
return 0;
1945+
if (Sym.isTypeGlobal())
1946+
return getDefinedGlobal(Sym.Info.ElementIndex).Size;
19391947
if (Sym.isTypeData())
19401948
return Sym.Info.DataRef.Size;
19411949
if (Sym.isTypeFunction())

llvm/test/tools/llvm-nm/wasm/exports.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,4 @@ Sections:
6464

6565
# CHECK: 00000000 D dexport
6666
# CHECK-NEXT: 00000001 T fexport
67-
# CHECK-NEXT: 00000000 D gexport
67+
# CHECK-NEXT: 00000001 D gexport

llvm/test/tools/llvm-nm/wasm/weak-symbols.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,6 @@ Sections:
8080

8181
# CHECK: 00000000 W weak_defined_data
8282
# CHECK-NEXT: 00000001 W weak_defined_func
83-
# CHECK-NEXT: 00000000 W weak_defined_global
83+
# CHECK-NEXT: 00000001 W weak_defined_global
8484
# CHECK-NEXT: w weak_import_data
8585
# CHECK-NEXT: w weak_import_func

llvm/test/tools/llvm-objdump/wasm/linked-symbol-table-namesec.yaml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
#
44
# CHECK: SYMBOL TABLE:
55
# CHECK-NEXT: 00000000 F *UND* 00000000 my_func_import_name
6-
# CHECK-NEXT: 00000083 g F CODE 00000003 my_func_export_name
7-
# CHECK-NEXT: 00000086 l F CODE 00000003 my_func_local_name
6+
# CHECK-NEXT: 0000008c g F CODE 00000003 my_func_export_name
7+
# CHECK-NEXT: 0000008f l F CODE 00000003 my_func_local_name
88
# CHECK-NEXT: 00000000 *UND* 00000000 my_global_import_name
9-
# CHECK-NEXT: 00000001 g GLOBAL 00000000 my_global_export_name
9+
# CHECK-NEXT: 0000004c g GLOBAL 00000005 my_global_export_name
10+
# CHECK-NEXT: 00000051 g GLOBAL 00000009 my_global_local_name
1011
# CHECK-NEXT: 00000000 l O DATA 00000004 my_datasegment_name
1112

1213
--- !WASM
@@ -44,6 +45,12 @@ Sections:
4445
InitExpr:
4546
Opcode: I32_CONST
4647
Value: 42
48+
- Index: 2
49+
Mutable: true
50+
Type: I64
51+
InitExpr:
52+
Opcode: I64_CONST
53+
Value: 5000000000
4754
- Type: EXPORT
4855
Exports:
4956
- Name: my_func_export
@@ -82,6 +89,8 @@ Sections:
8289
Name: my_global_import_name
8390
- Index: 1
8491
Name: my_global_export_name
92+
- Index: 2
93+
Name: my_global_local_name
8594
DataSegmentNames:
8695
- Index: 0
8796
Name: my_datasegment_name

0 commit comments

Comments
 (0)