aboutsummaryrefslogtreecommitdiff
path: root/lib/Object/WasmObjectFile.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
commit044eb2f6afba375a914ac9d8024f8f5142bb912e (patch)
tree1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /lib/Object/WasmObjectFile.cpp
parenteb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff)
downloadsrc-044eb2f6afba375a914ac9d8024f8f5142bb912e.tar.gz
src-044eb2f6afba375a914ac9d8024f8f5142bb912e.zip
Vendor import of llvm trunk r321017:vendor/llvm/llvm-trunk-r321017
Notes
Notes: svn path=/vendor/llvm/dist/; revision=326938 svn path=/vendor/llvm/llvm-trunk-r321017/; revision=326939; tag=vendor/llvm/llvm-trunk-r321017
Diffstat (limited to 'lib/Object/WasmObjectFile.cpp')
-rw-r--r--lib/Object/WasmObjectFile.cpp202
1 files changed, 143 insertions, 59 deletions
diff --git a/lib/Object/WasmObjectFile.cpp b/lib/Object/WasmObjectFile.cpp
index 7f80bf0b83a0..7a0c05ed8a15 100644
--- a/lib/Object/WasmObjectFile.cpp
+++ b/lib/Object/WasmObjectFile.cpp
@@ -178,14 +178,16 @@ static wasm::WasmTable readTable(const uint8_t *&Ptr) {
}
static Error readSection(WasmSection &Section, const uint8_t *&Ptr,
- const uint8_t *Start) {
- // TODO(sbc): Avoid reading past EOF in the case of malformed files.
+ const uint8_t *Start, const uint8_t *Eof) {
Section.Offset = Ptr - Start;
Section.Type = readVaruint7(Ptr);
uint32_t Size = readVaruint32(Ptr);
if (Size == 0)
return make_error<StringError>("Zero length section",
object_error::parse_failed);
+ if (Ptr + Size > Eof)
+ return make_error<StringError>("Section too large",
+ object_error::parse_failed);
Section.Content = ArrayRef<uint8_t>(Ptr, Size);
Ptr += Size;
return Error::success();
@@ -193,7 +195,6 @@ static Error readSection(WasmSection &Section, const uint8_t *&Ptr,
WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
: ObjectFile(Binary::ID_Wasm, Buffer) {
- LinkingData.DataAlignment = 0;
LinkingData.DataSize = 0;
ErrorAsOutParameter ErrAsOutParam(&Err);
@@ -203,7 +204,16 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
object_error::parse_failed);
return;
}
+
+ const uint8_t *Eof = getPtr(getData().size());
const uint8_t *Ptr = getPtr(4);
+
+ if (Ptr + 4 > Eof) {
+ Err = make_error<StringError>("Missing version number",
+ object_error::parse_failed);
+ return;
+ }
+
Header.Version = readUint32(Ptr);
if (Header.Version != wasm::WasmVersion) {
Err = make_error<StringError>("Bad version number",
@@ -211,10 +221,9 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
return;
}
- const uint8_t *Eof = getPtr(getData().size());
WasmSection Sec;
while (Ptr < Eof) {
- if ((Err = readSection(Sec, Ptr, getPtr(0))))
+ if ((Err = readSection(Sec, Ptr, getPtr(0), Eof)))
return;
if ((Err = parseSection(Sec)))
return;
@@ -292,9 +301,61 @@ 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;
+ size_t GlobalIndex = 0;
+ size_t FunctionIndex = 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, GlobalIndex++, 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, FunctionIndex++, ImportIndex);
+ DEBUG(dbgs() << "Adding import: " << Symbols.back()
+ << " sym index:" << Symbols.size() << "\n");
+ break;
+ default:
+ break;
+ }
+ ImportIndex++;
+ }
+
+ // Add exports to symbol table
+ 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;
+ SymbolMap.try_emplace(Export.Name, Symbols.size());
+ Symbols.emplace_back(Export.Name, ExportType,
+ ExportSection, Export.Index);
+ DEBUG(dbgs() << "Adding export: " << Symbols.back()
+ << " sym index:" << Symbols.size() << "\n");
+ }
+ }
+}
+
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);
@@ -317,7 +378,7 @@ Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
Symbols[SymIndex].Flags = Flags;
DEBUG(dbgs() << "Set symbol flags index:"
<< SymIndex << " name:"
- << Symbols[SymIndex].Name << " exptected:"
+ << Symbols[SymIndex].Name << " expected:"
<< Symbol << " flags: " << Flags << "\n");
}
break;
@@ -325,10 +386,33 @@ Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
case wasm::WASM_DATA_SIZE:
LinkingData.DataSize = readVaruint32(Ptr);
break;
- case wasm::WASM_DATA_ALIGNMENT:
- LinkingData.DataAlignment = readVaruint32(Ptr);
+ case wasm::WASM_SEGMENT_INFO: {
+ uint32_t Count = readVaruint32(Ptr);
+ if (Count > DataSegments.size())
+ return make_error<GenericBinaryError>("Too many segment names",
+ object_error::parse_failed);
+ for (uint32_t i = 0; i < Count; i++) {
+ DataSegments[i].Data.Name = readString(Ptr);
+ DataSegments[i].Data.Alignment = readVaruint32(Ptr);
+ DataSegments[i].Data.Flags = readVaruint32(Ptr);
+ }
+ break;
+ }
+ case wasm::WASM_INIT_FUNCS: {
+ uint32_t Count = readVaruint32(Ptr);
+ LinkingData.InitFunctions.reserve(Count);
+ for (uint32_t i = 0; i < Count; i++) {
+ wasm::WasmInitFunc Init;
+ Init.Priority = readVaruint32(Ptr);
+ Init.FunctionIndex = readVaruint32(Ptr);
+ if (!isValidFunctionIndex(Init.FunctionIndex))
+ return make_error<GenericBinaryError>("Invalid function index: " +
+ Twine(Init.FunctionIndex),
+ object_error::parse_failed);
+ LinkingData.InitFunctions.emplace_back(Init);
+ }
break;
- case wasm::WASM_STACK_POINTER:
+ }
default:
Ptr += Size;
break;
@@ -387,9 +471,9 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr,
case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
break;
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
Reloc.Addend = readVarint32(Ptr);
break;
default:
@@ -455,6 +539,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++) {
@@ -464,31 +549,22 @@ Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End)
Im.Kind = readUint8(Ptr);
switch (Im.Kind) {
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>(
@@ -560,6 +636,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++) {
@@ -567,17 +644,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;
- MakeSymbol = true;
+ if (Ex.Index >= FunctionTypes.size() + NumImportedFunctions)
+ return make_error<GenericBinaryError>("Invalid function export",
+ object_error::parse_failed);
break;
- case wasm::WASM_EXTERNAL_GLOBAL:
- ExportType = WasmSymbol::SymbolType::GLOBAL_EXPORT;
- MakeSymbol = true;
+ case wasm::WASM_EXTERNAL_GLOBAL: {
+ if (Ex.Index >= Globals.size() + NumImportedGlobals)
+ return make_error<GenericBinaryError>("Invalid global export",
+ object_error::parse_failed);
break;
+ }
case wasm::WASM_EXTERNAL_MEMORY:
case wasm::WASM_EXTERNAL_TABLE:
break;
@@ -585,20 +663,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)
@@ -607,27 +671,34 @@ Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End)
return Error::success();
}
+bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
+ return Index < FunctionTypes.size() + NumImportedFunctions;
+}
+
Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) {
StartFunction = readVaruint32(Ptr);
- if (StartFunction >= FunctionTypes.size())
+ if (!isValidFunctionIndex(StartFunction))
return make_error<GenericBinaryError>("Invalid start function",
object_error::parse_failed);
return Error::success();
}
Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) {
+ const uint8_t *CodeSectionStart = Ptr;
uint32_t FunctionCount = readVaruint32(Ptr);
if (FunctionCount != FunctionTypes.size()) {
return make_error<GenericBinaryError>("Invalid function count",
object_error::parse_failed);
}
- CodeSection = ArrayRef<uint8_t>(Ptr, End - Ptr);
-
while (FunctionCount--) {
wasm::WasmFunction Function;
- uint32_t FunctionSize = readVaruint32(Ptr);
- const uint8_t *FunctionEnd = Ptr + FunctionSize;
+ const uint8_t *FunctionStart = Ptr;
+ uint32_t Size = readVaruint32(Ptr);
+ const uint8_t *FunctionEnd = Ptr + Size;
+
+ Function.CodeSectionOffset = FunctionStart - CodeSectionStart;
+ Function.Size = FunctionEnd - FunctionStart;
uint32_t NumLocalDecls = readVaruint32(Ptr);
Function.Locals.reserve(NumLocalDecls);
@@ -685,6 +756,8 @@ Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) {
return Err;
uint32_t Size = readVaruint32(Ptr);
Segment.Data.Content = ArrayRef<uint8_t>(Ptr, Size);
+ Segment.Data.Alignment = 0;
+ Segment.Data.Flags = 0;
Segment.SectionOffset = Ptr - Start;
Ptr += Size;
DataSegments.push_back(Segment);
@@ -710,15 +783,19 @@ uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
const WasmSymbol &Sym = getWasmSymbol(Symb);
DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
- if (Sym.Flags & wasm::WASM_SYMBOL_FLAG_WEAK)
+ if (Sym.isWeak())
Result |= SymbolRef::SF_Weak;
+ if (!Sym.isLocal())
+ Result |= SymbolRef::SF_Global;
+ if (Sym.isHidden())
+ Result |= SymbolRef::SF_Hidden;
switch (Sym.Type) {
case WasmSymbol::SymbolType::FUNCTION_IMPORT:
Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
break;
case WasmSymbol::SymbolType::FUNCTION_EXPORT:
- Result |= SymbolRef::SF_Global | SymbolRef::SF_Executable;
+ Result |= SymbolRef::SF_Executable;
break;
case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
Result |= SymbolRef::SF_Executable;
@@ -728,7 +805,6 @@ uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
Result |= SymbolRef::SF_Undefined;
break;
case WasmSymbol::SymbolType::GLOBAL_EXPORT:
- Result |= SymbolRef::SF_Global;
break;
}
@@ -763,21 +839,29 @@ Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
return getSymbolValue(Symb);
}
-uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
- const WasmSymbol& Sym = getWasmSymbol(Symb);
+uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const {
switch (Sym.Type) {
case WasmSymbol::SymbolType::FUNCTION_IMPORT:
case WasmSymbol::SymbolType::GLOBAL_IMPORT:
- return 0;
case WasmSymbol::SymbolType::FUNCTION_EXPORT:
- case WasmSymbol::SymbolType::GLOBAL_EXPORT:
- return Exports[Sym.ElementIndex].Index;
case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
return Sym.ElementIndex;
+ case WasmSymbol::SymbolType::GLOBAL_EXPORT: {
+ uint32_t GlobalIndex = Sym.ElementIndex - 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;
+ }
}
llvm_unreachable("invalid symbol type");
}
+uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
+ return getWasmSymbolValue(getWasmSymbol(Symb));
+}
+
uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
llvm_unreachable("not yet implemented");
return 0;
@@ -957,7 +1041,7 @@ uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
-unsigned WasmObjectFile::getArch() const { return Triple::wasm32; }
+Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
SubtargetFeatures WasmObjectFile::getFeatures() const {
return SubtargetFeatures();