llvm.org GIT mirror llvm / 9f8cb47
[WebAssembly] Only treat imports/exports as symbols when reading relocatable object files This change only treats imported and exports functions and globals as symbol table entries the object has a "linking" section (i.e. it is relocatable object file). In this case all globals must be of type I32 and initialized with i32.const. This was previously being assumed but not checked for and was causing a failure on big endian machines due to using the wrong value of then union. See: https://bugs.llvm.org/show_bug.cgi?id=34487 Differential Revision: https://reviews.llvm.org/D37497 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312674 91177308-0d34-0410-b5e6-96231b3b80d8 Sam Clegg 2 years ago
9 changed file(s) with 104 addition(s) and 59 deletion(s). Raw diff Collapse all Expand all
202202 Error parseLinkingSection(const uint8_t *Ptr, const uint8_t *End);
203203 Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
204204 const uint8_t *End);
205
206 void populateSymbolTable();
205207
206208 wasm::WasmObjectHeader Header;
207209 std::vector Sections;
222224 wasm::WasmLinkingData LinkingData;
223225 uint32_t NumImportedGlobals = 0;
224226 uint32_t NumImportedFunctions = 0;
227 uint32_t ImportSection = 0;
228 uint32_t ExportSection = 0;
225229
226230 StringMap SymbolMap;
227231 };
299299 return Error::success();
300300 }
301301
302 void WasmObjectFile::populateSymbolTable() {
303 // Add imports to symbol table
304 size_t ImportIndex = 0;
305 for (const wasm::WasmImport& Import : Imports) {
306 switch (Import.Kind) {
307 case wasm::WASM_EXTERNAL_GLOBAL:
308 assert(Import.Global.Type == wasm::WASM_TYPE_I32);
309 SymbolMap.try_emplace(Import.Field, Symbols.size());
310 Symbols.emplace_back(Import.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
311 ImportSection, ImportIndex);
312 DEBUG(dbgs() << "Adding import: " << Symbols.back()
313 << " sym index:" << Symbols.size() << "\n");
314 break;
315 case wasm::WASM_EXTERNAL_FUNCTION:
316 SymbolMap.try_emplace(Import.Field, Symbols.size());
317 Symbols.emplace_back(Import.Field,
318 WasmSymbol::SymbolType::FUNCTION_IMPORT,
319 ImportSection, ImportIndex);
320 DEBUG(dbgs() << "Adding import: " << Symbols.back()
321 << " sym index:" << Symbols.size() << "\n");
322 break;
323 default:
324 break;
325 }
326 ImportIndex++;
327 }
328
329 // Add exports to symbol table
330 size_t ExportIndex = 0;
331 for (const wasm::WasmExport& Export : Exports) {
332 if (Export.Kind == wasm::WASM_EXTERNAL_FUNCTION ||
333 Export.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
334 WasmSymbol::SymbolType ExportType =
335 Export.Kind == wasm::WASM_EXTERNAL_FUNCTION
336 ? WasmSymbol::SymbolType::FUNCTION_EXPORT
337 : WasmSymbol::SymbolType::GLOBAL_EXPORT;
338 auto Pair = SymbolMap.try_emplace(Export.Name, Symbols.size());
339 if (Pair.second) {
340 Symbols.emplace_back(Export.Name, ExportType,
341 ExportSection, ExportIndex);
342 DEBUG(dbgs() << "Adding export: " << Symbols.back()
343 << " sym index:" << Symbols.size() << "\n");
344 } else {
345 uint32_t SymIndex = Pair.first->second;
346 Symbols[SymIndex] =
347 WasmSymbol(Export.Name, ExportType, ExportSection, ExportIndex);
348 DEBUG(dbgs() << "Replacing existing symbol: " << Symbols[SymIndex]
349 << " sym index:" << SymIndex << "\n");
350 }
351 }
352 ExportIndex++;
353 }
354 }
355
302356 Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
303357 const uint8_t *End) {
304358 HasLinkingSection = true;
359
360 // Only populate the symbol table with imports and exports if the object
361 // has a linking section (i.e. its a relocatable object file). Otherwise
362 // the global might not represent symbols at all.
363 populateSymbolTable();
364
305365 while (Ptr < End) {
306366 uint8_t Type = readVarint7(Ptr);
307367 uint32_t Size = readVaruint32(Ptr);
462522 }
463523
464524 Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) {
525 ImportSection = Sections.size();
465526 uint32_t Count = readVaruint32(Ptr);
466527 Imports.reserve(Count);
467528 for (uint32_t i = 0; i < Count; i++) {
473534 case wasm::WASM_EXTERNAL_FUNCTION:
474535 NumImportedFunctions++;
475536 Im.SigIndex = readVaruint32(Ptr);
476 SymbolMap.try_emplace(Im.Field, Symbols.size());
477 Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT,
478 Sections.size(), i);
479 DEBUG(dbgs() << "Adding import: " << Symbols.back()
480 << " sym index:" << Symbols.size() << "\n");
481537 break;
482538 case wasm::WASM_EXTERNAL_GLOBAL:
483539 NumImportedGlobals++;
484540 Im.Global.Type = readVarint7(Ptr);
485541 Im.Global.Mutable = readVaruint1(Ptr);
486 SymbolMap.try_emplace(Im.Field, Symbols.size());
487 Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
488 Sections.size(), i);
489 DEBUG(dbgs() << "Adding import: " << Symbols.back()
490 << " sym index:" << Symbols.size() << "\n");
491542 break;
492543 case wasm::WASM_EXTERNAL_MEMORY:
493544 Im.Memory = readLimits(Ptr);
494545 break;
495546 case wasm::WASM_EXTERNAL_TABLE:
496547 Im.Table = readTable(Ptr);
497 if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC) {
548 if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC)
498549 return make_error("Invalid table element type",
499550 object_error::parse_failed);
500 }
501551 break;
502552 default:
503553 return make_error(
569619 }
570620
571621 Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) {
622 ExportSection = Sections.size();
572623 uint32_t Count = readVaruint32(Ptr);
573624 Exports.reserve(Count);
574625 for (uint32_t i = 0; i < Count; i++) {
576627 Ex.Name = readString(Ptr);
577628 Ex.Kind = readUint8(Ptr);
578629 Ex.Index = readVaruint32(Ptr);
579 WasmSymbol::SymbolType ExportType;
580 bool MakeSymbol = false;
581630 switch (Ex.Kind) {
582631 case wasm::WASM_EXTERNAL_FUNCTION:
583 ExportType = WasmSymbol::SymbolType::FUNCTION_EXPORT;
584632 if (Ex.Index >= FunctionTypes.size() + NumImportedFunctions)
585633 return make_error("Invalid function export",
586634 object_error::parse_failed);
587 MakeSymbol = true;
588 break;
589 case wasm::WASM_EXTERNAL_GLOBAL:
590 ExportType = WasmSymbol::SymbolType::GLOBAL_EXPORT;
635 break;
636 case wasm::WASM_EXTERNAL_GLOBAL: {
591637 if (Ex.Index >= Globals.size() + NumImportedGlobals)
592638 return make_error("Invalid global export",
593639 object_error::parse_failed);
594 MakeSymbol = true;
595 break;
640 break;
641 }
596642 case wasm::WASM_EXTERNAL_MEMORY:
597643 case wasm::WASM_EXTERNAL_TABLE:
598644 break;
599645 default:
600646 return make_error(
601647 "Unexpected export kind", object_error::parse_failed);
602 }
603 if (MakeSymbol) {
604 auto Pair = SymbolMap.try_emplace(Ex.Name, Symbols.size());
605 if (Pair.second) {
606 Symbols.emplace_back(Ex.Name, ExportType,
607 Sections.size(), i);
608 DEBUG(dbgs() << "Adding export: " << Symbols.back()
609 << " sym index:" << Symbols.size() << "\n");
610 } else {
611 uint32_t SymIndex = Pair.first->second;
612 Symbols[SymIndex] = WasmSymbol(Ex.Name, ExportType, Sections.size(), i);
613 DEBUG(dbgs() << "Replacing existing symbol: " << Symbols[SymIndex]
614 << " sym index:" << SymIndex << "\n");
615 }
616648 }
617649 Exports.push_back(Ex);
618650 }
790822 uint32_t GlobalIndex = Exports[Sym.ElementIndex].Index - NumImportedGlobals;
791823 assert(GlobalIndex < Globals.size());
792824 const wasm::WasmGlobal& Global = Globals[GlobalIndex];
825 // WasmSymbols correspond only to I32_CONST globals
826 assert(Global.InitExpr.Opcode == wasm::WASM_OPCODE_I32_CONST);
793827 return Global.InitExpr.Value.Int32;
794828 }
795829 case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
5858 IO.mapRequired("Name", Section.Name);
5959 IO.mapRequired("DataSize", Section.DataSize);
6060 IO.mapRequired("DataAlignment", Section.DataAlignment);
61 IO.mapRequired("SymbolInfo", Section.SymbolInfos);
61 IO.mapOptional("SymbolInfo", Section.SymbolInfos);
6262 }
6363
6464 static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
5555 ; CHECK-NEXT: Name: linking
5656 ; CHECK-NEXT: DataSize: 28
5757 ; CHECK-NEXT: DataAlignment: 8
58 ; CHECK-NEXT: SymbolInfo:
5958 ; CHECK-NEXT: ...
2323 - Type: I32
2424 Mutable: false
2525 InitExpr:
26 Opcode: I64_CONST
26 Opcode: I32_CONST
2727 Value: 64
2828 - Type: I32
2929 Mutable: false
3030 InitExpr:
31 Opcode: I64_CONST
31 Opcode: I32_CONST
3232 Value: 1024
3333 - Type: IMPORT
3434 Imports:
4949 - Name: bar
5050 Kind: GLOBAL
5151 Index: 0x00000003
52 - Type: CUSTOM
53 Name: "linking"
54 DataSize: 0
55 DataAlignment: 0
5256
5357 # CHECK: 00000400 D bar
5458 # CHECK-NEXT: U fimport
1919 Kind: GLOBAL
2020 GlobalType: I32
2121 GlobalMutable: false
22 - Type: CUSTOM
23 Name: "linking"
24 DataSize: 0
25 DataAlignment: 0
2226
2327 # CHECK: U bar
2428 # CHECK: U foo
3434 - Type: I32
3535 Mutable: false
3636 InitExpr:
37 Opcode: I64_CONST
37 Opcode: I32_CONST
3838 Value: 64
3939 - Type: I32
4040 Mutable: false
4141 InitExpr:
42 Opcode: I64_CONST
42 Opcode: I32_CONST
4343 Value: 1024
4444 - Type: EXPORT
4545 Exports:
0 RUN: llvm-objdump -t %p/../Inputs/trivial.obj.wasm | FileCheck %s
11
22 CHECK: SYMBOL TABLE:
3 CHECK-NEXT: 00000000 l F name puts
4 CHECK-NEXT: 00000001 l F name SomeOtherFunction
5 CHECK-NEXT: 00000002 l F name main
36 CHECK-NEXT: 00000000 l F IMPORT puts
47 CHECK-NEXT: 00000000 l F IMPORT SomeOtherFunction
58 CHECK-NEXT: 00000002 g F EXPORT main
69 CHECK-NEXT: 00000010 g EXPORT var
7 CHECK-NEXT: 00000000 l F name puts
8 CHECK-NEXT: 00000001 l F name SomeOtherFunction
9 CHECK-NEXT: 00000002 l F name main
1010
7373 WASM: Symbols [
7474 WASM-NEXT: Symbol {
7575 WASM-NEXT: Name: puts
76 WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4)
77 WASM-NEXT: Flags: 0x0
78 WASM-NEXT: }
79 WASM-NEXT: Symbol {
80 WASM-NEXT: Name: SomeOtherFunction
81 WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4)
82 WASM-NEXT: Flags: 0x0
83 WASM-NEXT: }
84 WASM-NEXT: Symbol {
85 WASM-NEXT: Name: main
86 WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4)
87 WASM-NEXT: Flags: 0x0
88 WASM-NEXT: }
89 WASM-NEXT: Symbol {
90 WASM-NEXT: Name: puts
7691 WASM-NEXT: Type: FUNCTION_IMPORT (0x0)
7792 WASM-NEXT: Flags: 0x0
7893 WASM-NEXT: }
86101 WASM-NEXT: Type: FUNCTION_EXPORT (0x1)
87102 WASM-NEXT: Flags: 0x0
88103 WASM-NEXT: }
89 WASM-NEXT: Symbol {
90 WASM-NEXT: Name: puts
91 WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4)
92 WASM-NEXT: Flags: 0x0
93 WASM-NEXT: }
94 WASM-NEXT: Symbol {
95 WASM-NEXT: Name: SomeOtherFunction
96 WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4)
97 WASM-NEXT: Flags: 0x0
98 WASM-NEXT: }
99 WASM-NEXT: Symbol {
100 WASM-NEXT: Name: main
101 WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4)
102 WASM-NEXT: Flags: 0x0
103 WASM-NEXT: }
104104 WASM-NEXT: ]