1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 04:32:44 +01:00

[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

llvm-svn: 312674
This commit is contained in:
Sam Clegg 2017-09-06 22:05:41 +00:00
parent db8c4e1c9e
commit 610f20a479
9 changed files with 102 additions and 57 deletions

View File

@ -204,6 +204,8 @@ private:
Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
const uint8_t *End);
void populateSymbolTable();
wasm::WasmObjectHeader Header;
std::vector<WasmSection> Sections;
std::vector<wasm::WasmSignature> Signatures;
@ -223,6 +225,8 @@ private:
wasm::WasmLinkingData LinkingData;
uint32_t NumImportedGlobals = 0;
uint32_t NumImportedFunctions = 0;
uint32_t ImportSection = 0;
uint32_t ExportSection = 0;
StringMap<uint32_t> SymbolMap;
};

View File

@ -300,9 +300,69 @@ Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
return Error::success();
}
void WasmObjectFile::populateSymbolTable() {
// Add imports to symbol table
size_t ImportIndex = 0;
for (const wasm::WasmImport& Import : Imports) {
switch (Import.Kind) {
case wasm::WASM_EXTERNAL_GLOBAL:
assert(Import.Global.Type == wasm::WASM_TYPE_I32);
SymbolMap.try_emplace(Import.Field, Symbols.size());
Symbols.emplace_back(Import.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
ImportSection, ImportIndex);
DEBUG(dbgs() << "Adding import: " << Symbols.back()
<< " sym index:" << Symbols.size() << "\n");
break;
case wasm::WASM_EXTERNAL_FUNCTION:
SymbolMap.try_emplace(Import.Field, Symbols.size());
Symbols.emplace_back(Import.Field,
WasmSymbol::SymbolType::FUNCTION_IMPORT,
ImportSection, ImportIndex);
DEBUG(dbgs() << "Adding import: " << Symbols.back()
<< " sym index:" << Symbols.size() << "\n");
break;
default:
break;
}
ImportIndex++;
}
// Add exports to symbol table
size_t ExportIndex = 0;
for (const wasm::WasmExport& Export : Exports) {
if (Export.Kind == wasm::WASM_EXTERNAL_FUNCTION ||
Export.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
WasmSymbol::SymbolType ExportType =
Export.Kind == wasm::WASM_EXTERNAL_FUNCTION
? WasmSymbol::SymbolType::FUNCTION_EXPORT
: WasmSymbol::SymbolType::GLOBAL_EXPORT;
auto Pair = SymbolMap.try_emplace(Export.Name, Symbols.size());
if (Pair.second) {
Symbols.emplace_back(Export.Name, ExportType,
ExportSection, ExportIndex);
DEBUG(dbgs() << "Adding export: " << Symbols.back()
<< " sym index:" << Symbols.size() << "\n");
} else {
uint32_t SymIndex = Pair.first->second;
Symbols[SymIndex] =
WasmSymbol(Export.Name, ExportType, ExportSection, ExportIndex);
DEBUG(dbgs() << "Replacing existing symbol: " << Symbols[SymIndex]
<< " sym index:" << SymIndex << "\n");
}
}
ExportIndex++;
}
}
Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
const uint8_t *End) {
HasLinkingSection = true;
// Only populate the symbol table with imports and exports if the object
// has a linking section (i.e. its a relocatable object file). Otherwise
// the global might not represent symbols at all.
populateSymbolTable();
while (Ptr < End) {
uint8_t Type = readVarint7(Ptr);
uint32_t Size = readVaruint32(Ptr);
@ -463,6 +523,7 @@ Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) {
}
Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) {
ImportSection = Sections.size();
uint32_t Count = readVaruint32(Ptr);
Imports.reserve(Count);
for (uint32_t i = 0; i < Count; i++) {
@ -474,31 +535,20 @@ Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End)
case wasm::WASM_EXTERNAL_FUNCTION:
NumImportedFunctions++;
Im.SigIndex = readVaruint32(Ptr);
SymbolMap.try_emplace(Im.Field, Symbols.size());
Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT,
Sections.size(), i);
DEBUG(dbgs() << "Adding import: " << Symbols.back()
<< " sym index:" << Symbols.size() << "\n");
break;
case wasm::WASM_EXTERNAL_GLOBAL:
NumImportedGlobals++;
Im.Global.Type = readVarint7(Ptr);
Im.Global.Mutable = readVaruint1(Ptr);
SymbolMap.try_emplace(Im.Field, Symbols.size());
Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
Sections.size(), i);
DEBUG(dbgs() << "Adding import: " << Symbols.back()
<< " sym index:" << Symbols.size() << "\n");
break;
case wasm::WASM_EXTERNAL_MEMORY:
Im.Memory = readLimits(Ptr);
break;
case wasm::WASM_EXTERNAL_TABLE:
Im.Table = readTable(Ptr);
if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC) {
if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC)
return make_error<GenericBinaryError>("Invalid table element type",
object_error::parse_failed);
}
break;
default:
return make_error<GenericBinaryError>(
@ -570,6 +620,7 @@ Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End)
}
Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) {
ExportSection = Sections.size();
uint32_t Count = readVaruint32(Ptr);
Exports.reserve(Count);
for (uint32_t i = 0; i < Count; i++) {
@ -577,23 +628,18 @@ Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End)
Ex.Name = readString(Ptr);
Ex.Kind = readUint8(Ptr);
Ex.Index = readVaruint32(Ptr);
WasmSymbol::SymbolType ExportType;
bool MakeSymbol = false;
switch (Ex.Kind) {
case wasm::WASM_EXTERNAL_FUNCTION:
ExportType = WasmSymbol::SymbolType::FUNCTION_EXPORT;
if (Ex.Index >= FunctionTypes.size() + NumImportedFunctions)
return make_error<GenericBinaryError>("Invalid function export",
object_error::parse_failed);
MakeSymbol = true;
break;
case wasm::WASM_EXTERNAL_GLOBAL:
ExportType = WasmSymbol::SymbolType::GLOBAL_EXPORT;
case wasm::WASM_EXTERNAL_GLOBAL: {
if (Ex.Index >= Globals.size() + NumImportedGlobals)
return make_error<GenericBinaryError>("Invalid global export",
object_error::parse_failed);
MakeSymbol = true;
break;
}
case wasm::WASM_EXTERNAL_MEMORY:
case wasm::WASM_EXTERNAL_TABLE:
break;
@ -601,20 +647,6 @@ Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End)
return make_error<GenericBinaryError>(
"Unexpected export kind", object_error::parse_failed);
}
if (MakeSymbol) {
auto Pair = SymbolMap.try_emplace(Ex.Name, Symbols.size());
if (Pair.second) {
Symbols.emplace_back(Ex.Name, ExportType,
Sections.size(), i);
DEBUG(dbgs() << "Adding export: " << Symbols.back()
<< " sym index:" << Symbols.size() << "\n");
} else {
uint32_t SymIndex = Pair.first->second;
Symbols[SymIndex] = WasmSymbol(Ex.Name, ExportType, Sections.size(), i);
DEBUG(dbgs() << "Replacing existing symbol: " << Symbols[SymIndex]
<< " sym index:" << SymIndex << "\n");
}
}
Exports.push_back(Ex);
}
if (Ptr != End)
@ -791,6 +823,8 @@ uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
uint32_t GlobalIndex = Exports[Sym.ElementIndex].Index - NumImportedGlobals;
assert(GlobalIndex < Globals.size());
const wasm::WasmGlobal& Global = Globals[GlobalIndex];
// WasmSymbols correspond only to I32_CONST globals
assert(Global.InitExpr.Opcode == wasm::WASM_OPCODE_I32_CONST);
return Global.InitExpr.Value.Int32;
}
case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:

View File

@ -59,7 +59,7 @@ static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) {
IO.mapRequired("Name", Section.Name);
IO.mapRequired("DataSize", Section.DataSize);
IO.mapRequired("DataAlignment", Section.DataAlignment);
IO.mapRequired("SymbolInfo", Section.SymbolInfos);
IO.mapOptional("SymbolInfo", Section.SymbolInfos);
}
static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {

View File

@ -56,5 +56,4 @@
; CHECK-NEXT: Name: linking
; CHECK-NEXT: DataSize: 28
; CHECK-NEXT: DataAlignment: 8
; CHECK-NEXT: SymbolInfo:
; CHECK-NEXT: ...

View File

@ -24,12 +24,12 @@ Sections:
- Type: I32
Mutable: false
InitExpr:
Opcode: I64_CONST
Opcode: I32_CONST
Value: 64
- Type: I32
Mutable: false
InitExpr:
Opcode: I64_CONST
Opcode: I32_CONST
Value: 1024
- Type: IMPORT
Imports:
@ -50,6 +50,10 @@ Sections:
- Name: bar
Kind: GLOBAL
Index: 0x00000003
- Type: CUSTOM
Name: "linking"
DataSize: 0
DataAlignment: 0
# CHECK: 00000400 D bar
# CHECK-NEXT: U fimport

View File

@ -20,6 +20,10 @@ Sections:
Kind: GLOBAL
GlobalType: I32
GlobalMutable: false
- Type: CUSTOM
Name: "linking"
DataSize: 0
DataAlignment: 0
# CHECK: U bar
# CHECK: U foo

View File

@ -35,12 +35,12 @@ Sections:
- Type: I32
Mutable: false
InitExpr:
Opcode: I64_CONST
Opcode: I32_CONST
Value: 64
- Type: I32
Mutable: false
InitExpr:
Opcode: I64_CONST
Opcode: I32_CONST
Value: 1024
- Type: EXPORT
Exports:

View File

@ -1,11 +1,11 @@
RUN: llvm-objdump -t %p/../Inputs/trivial.obj.wasm | FileCheck %s
CHECK: SYMBOL TABLE:
CHECK-NEXT: 00000000 l F name puts
CHECK-NEXT: 00000001 l F name SomeOtherFunction
CHECK-NEXT: 00000002 l F name main
CHECK-NEXT: 00000000 l F IMPORT puts
CHECK-NEXT: 00000000 l F IMPORT SomeOtherFunction
CHECK-NEXT: 00000002 g F EXPORT main
CHECK-NEXT: 00000010 g EXPORT var
CHECK-NEXT: 00000000 l F name puts
CHECK-NEXT: 00000001 l F name SomeOtherFunction
CHECK-NEXT: 00000002 l F name main

View File

@ -74,6 +74,21 @@ ELF-NEXT: }
WASM: Symbols [
WASM-NEXT: Symbol {
WASM-NEXT: Name: puts
WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4)
WASM-NEXT: Flags: 0x0
WASM-NEXT: }
WASM-NEXT: Symbol {
WASM-NEXT: Name: SomeOtherFunction
WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4)
WASM-NEXT: Flags: 0x0
WASM-NEXT: }
WASM-NEXT: Symbol {
WASM-NEXT: Name: main
WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4)
WASM-NEXT: Flags: 0x0
WASM-NEXT: }
WASM-NEXT: Symbol {
WASM-NEXT: Name: puts
WASM-NEXT: Type: FUNCTION_IMPORT (0x0)
WASM-NEXT: Flags: 0x0
WASM-NEXT: }
@ -87,19 +102,4 @@ WASM-NEXT: Name: main
WASM-NEXT: Type: FUNCTION_EXPORT (0x1)
WASM-NEXT: Flags: 0x0
WASM-NEXT: }
WASM-NEXT: Symbol {
WASM-NEXT: Name: puts
WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4)
WASM-NEXT: Flags: 0x0
WASM-NEXT: }
WASM-NEXT: Symbol {
WASM-NEXT: Name: SomeOtherFunction
WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4)
WASM-NEXT: Flags: 0x0
WASM-NEXT: }
WASM-NEXT: Symbol {
WASM-NEXT: Name: main
WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4)
WASM-NEXT: Flags: 0x0
WASM-NEXT: }
WASM-NEXT: ]