aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/WasmObjectFile.cpp
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2017-09-06 22:05:41 +0000
committerSam Clegg <sbc@chromium.org>2017-09-06 22:05:41 +0000
commite7a60708ffff6521ba5fad54e9c833457de758a1 (patch)
treee72a840a236137cfa9345d9e79b271d04e5ca292 /llvm/lib/Object/WasmObjectFile.cpp
parentf2f4e033b47b125f857178d367c992859d0e37ae (diff)
downloadllvm-e7a60708ffff6521ba5fad54e9c833457de758a1.zip
llvm-e7a60708ffff6521ba5fad54e9c833457de758a1.tar.gz
llvm-e7a60708ffff6521ba5fad54e9c833457de758a1.tar.bz2
[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
Diffstat (limited to 'llvm/lib/Object/WasmObjectFile.cpp')
-rw-r--r--llvm/lib/Object/WasmObjectFile.cpp100
1 files changed, 67 insertions, 33 deletions
diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index 9309751..bd51fbd 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -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: