1 //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/ADT/ArrayRef.h"
11 #include "llvm/ADT/DenseSet.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/ADT/StringSet.h"
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/BinaryFormat/Wasm.h"
17 #include "llvm/MC/SubtargetFeature.h"
18 #include "llvm/Object/Binary.h"
19 #include "llvm/Object/Error.h"
20 #include "llvm/Object/ObjectFile.h"
21 #include "llvm/Object/SymbolicFile.h"
22 #include "llvm/Object/Wasm.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/Error.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/LEB128.h"
27 #include "llvm/Support/ScopedPrinter.h"
32 #include <system_error>
34 #define DEBUG_TYPE "wasm-object"
37 using namespace object;
39 void WasmSymbol::print(raw_ostream &Out) const {
40 Out << "Name=" << Info.Name
41 << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
42 << ", Flags=" << Info.Flags;
44 Out << ", ElemIndex=" << Info.ElementIndex;
45 } else if (isDefined()) {
46 Out << ", Segment=" << Info.DataRef.Segment;
47 Out << ", Offset=" << Info.DataRef.Offset;
48 Out << ", Size=" << Info.DataRef.Size;
52 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
53 LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
56 Expected<std::unique_ptr<WasmObjectFile>>
57 ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
58 Error Err = Error::success();
59 auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err);
61 return std::move(Err);
63 return std::move(ObjectFile);
66 #define VARINT7_MAX ((1 << 7) - 1)
67 #define VARINT7_MIN (-(1 << 7))
68 #define VARUINT7_MAX (1 << 7)
69 #define VARUINT1_MAX (1)
71 static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
72 if (Ctx.Ptr == Ctx.End)
73 report_fatal_error("EOF while reading uint8");
77 static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
78 if (Ctx.Ptr + 4 > Ctx.End)
79 report_fatal_error("EOF while reading uint32");
80 uint32_t Result = support::endian::read32le(Ctx.Ptr);
85 static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
86 if (Ctx.Ptr + 4 > Ctx.End)
87 report_fatal_error("EOF while reading float64");
89 memcpy(&Result, Ctx.Ptr, sizeof(Result));
90 Ctx.Ptr += sizeof(Result);
94 static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
95 if (Ctx.Ptr + 8 > Ctx.End)
96 report_fatal_error("EOF while reading float64");
98 memcpy(&Result, Ctx.Ptr, sizeof(Result));
99 Ctx.Ptr += sizeof(Result);
103 static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
105 const char *Error = nullptr;
106 uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
108 report_fatal_error(Error);
113 static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
114 uint32_t StringLen = readULEB128(Ctx);
115 if (Ctx.Ptr + StringLen > Ctx.End)
116 report_fatal_error("EOF while reading string");
118 StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
119 Ctx.Ptr += StringLen;
123 static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
125 const char *Error = nullptr;
126 uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
128 report_fatal_error(Error);
133 static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
134 int64_t result = readLEB128(Ctx);
135 if (result > VARUINT1_MAX || result < 0)
136 report_fatal_error("LEB is outside Varuint1 range");
140 static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
141 int64_t result = readLEB128(Ctx);
142 if (result > INT32_MAX || result < INT32_MIN)
143 report_fatal_error("LEB is outside Varint32 range");
147 static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
148 uint64_t result = readULEB128(Ctx);
149 if (result > UINT32_MAX)
150 report_fatal_error("LEB is outside Varuint32 range");
154 static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
155 return readLEB128(Ctx);
158 static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
159 return readUint8(Ctx);
162 static Error readInitExpr(wasm::WasmInitExpr &Expr,
163 WasmObjectFile::ReadContext &Ctx) {
164 Expr.Opcode = readOpcode(Ctx);
166 switch (Expr.Opcode) {
167 case wasm::WASM_OPCODE_I32_CONST:
168 Expr.Value.Int32 = readVarint32(Ctx);
170 case wasm::WASM_OPCODE_I64_CONST:
171 Expr.Value.Int64 = readVarint64(Ctx);
173 case wasm::WASM_OPCODE_F32_CONST:
174 Expr.Value.Float32 = readFloat32(Ctx);
176 case wasm::WASM_OPCODE_F64_CONST:
177 Expr.Value.Float64 = readFloat64(Ctx);
179 case wasm::WASM_OPCODE_GLOBAL_GET:
180 Expr.Value.Global = readULEB128(Ctx);
183 return make_error<GenericBinaryError>("Invalid opcode in init_expr",
184 object_error::parse_failed);
187 uint8_t EndOpcode = readOpcode(Ctx);
188 if (EndOpcode != wasm::WASM_OPCODE_END) {
189 return make_error<GenericBinaryError>("Invalid init_expr",
190 object_error::parse_failed);
192 return Error::success();
195 static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
196 wasm::WasmLimits Result;
197 Result.Flags = readVaruint32(Ctx);
198 Result.Initial = readVaruint32(Ctx);
199 if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
200 Result.Maximum = readVaruint32(Ctx);
204 static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) {
205 wasm::WasmTable Table;
206 Table.ElemType = readUint8(Ctx);
207 Table.Limits = readLimits(Ctx);
211 static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
212 WasmSectionOrderChecker &Checker) {
213 Section.Offset = Ctx.Ptr - Ctx.Start;
214 Section.Type = readUint8(Ctx);
215 LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
216 uint32_t Size = readVaruint32(Ctx);
218 return make_error<StringError>("Zero length section",
219 object_error::parse_failed);
220 if (Ctx.Ptr + Size > Ctx.End)
221 return make_error<StringError>("Section too large",
222 object_error::parse_failed);
223 if (Section.Type == wasm::WASM_SEC_CUSTOM) {
224 WasmObjectFile::ReadContext SectionCtx;
225 SectionCtx.Start = Ctx.Ptr;
226 SectionCtx.Ptr = Ctx.Ptr;
227 SectionCtx.End = Ctx.Ptr + Size;
229 Section.Name = readString(SectionCtx);
231 uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
232 Ctx.Ptr += SectionNameSize;
233 Size -= SectionNameSize;
236 if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
237 return make_error<StringError>("Out of order section type: " +
238 llvm::to_string(Section.Type),
239 object_error::parse_failed);
242 Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
244 return Error::success();
247 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
248 : ObjectFile(Binary::ID_Wasm, Buffer) {
249 ErrorAsOutParameter ErrAsOutParam(&Err);
250 Header.Magic = getData().substr(0, 4);
251 if (Header.Magic != StringRef("\0asm", 4)) {
253 make_error<StringError>("Bad magic number", object_error::parse_failed);
258 Ctx.Start = getPtr(0);
259 Ctx.Ptr = Ctx.Start + 4;
260 Ctx.End = Ctx.Start + getData().size();
262 if (Ctx.Ptr + 4 > Ctx.End) {
263 Err = make_error<StringError>("Missing version number",
264 object_error::parse_failed);
268 Header.Version = readUint32(Ctx);
269 if (Header.Version != wasm::WasmVersion) {
270 Err = make_error<StringError>("Bad version number",
271 object_error::parse_failed);
276 WasmSectionOrderChecker Checker;
277 while (Ctx.Ptr < Ctx.End) {
278 if ((Err = readSection(Sec, Ctx, Checker)))
280 if ((Err = parseSection(Sec)))
283 Sections.push_back(Sec);
287 Error WasmObjectFile::parseSection(WasmSection &Sec) {
289 Ctx.Start = Sec.Content.data();
290 Ctx.End = Ctx.Start + Sec.Content.size();
293 case wasm::WASM_SEC_CUSTOM:
294 return parseCustomSection(Sec, Ctx);
295 case wasm::WASM_SEC_TYPE:
296 return parseTypeSection(Ctx);
297 case wasm::WASM_SEC_IMPORT:
298 return parseImportSection(Ctx);
299 case wasm::WASM_SEC_FUNCTION:
300 return parseFunctionSection(Ctx);
301 case wasm::WASM_SEC_TABLE:
302 return parseTableSection(Ctx);
303 case wasm::WASM_SEC_MEMORY:
304 return parseMemorySection(Ctx);
305 case wasm::WASM_SEC_GLOBAL:
306 return parseGlobalSection(Ctx);
307 case wasm::WASM_SEC_EVENT:
308 return parseEventSection(Ctx);
309 case wasm::WASM_SEC_EXPORT:
310 return parseExportSection(Ctx);
311 case wasm::WASM_SEC_START:
312 return parseStartSection(Ctx);
313 case wasm::WASM_SEC_ELEM:
314 return parseElemSection(Ctx);
315 case wasm::WASM_SEC_CODE:
316 return parseCodeSection(Ctx);
317 case wasm::WASM_SEC_DATA:
318 return parseDataSection(Ctx);
320 return make_error<GenericBinaryError>("Bad section type",
321 object_error::parse_failed);
325 Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
326 // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
327 DylinkInfo.MemorySize = readVaruint32(Ctx);
328 DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
329 DylinkInfo.TableSize = readVaruint32(Ctx);
330 DylinkInfo.TableAlignment = readVaruint32(Ctx);
331 uint32_t Count = readVaruint32(Ctx);
333 DylinkInfo.Needed.push_back(readString(Ctx));
335 if (Ctx.Ptr != Ctx.End)
336 return make_error<GenericBinaryError>("dylink section ended prematurely",
337 object_error::parse_failed);
338 return Error::success();
341 Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
342 llvm::DenseSet<uint64_t> Seen;
343 if (Functions.size() != FunctionTypes.size()) {
344 return make_error<GenericBinaryError>("Names must come after code section",
345 object_error::parse_failed);
348 while (Ctx.Ptr < Ctx.End) {
349 uint8_t Type = readUint8(Ctx);
350 uint32_t Size = readVaruint32(Ctx);
351 const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
353 case wasm::WASM_NAMES_FUNCTION: {
354 uint32_t Count = readVaruint32(Ctx);
356 uint32_t Index = readVaruint32(Ctx);
357 if (!Seen.insert(Index).second)
358 return make_error<GenericBinaryError>("Function named more than once",
359 object_error::parse_failed);
360 StringRef Name = readString(Ctx);
361 if (!isValidFunctionIndex(Index) || Name.empty())
362 return make_error<GenericBinaryError>("Invalid name entry",
363 object_error::parse_failed);
364 DebugNames.push_back(wasm::WasmFunctionName{Index, Name});
365 if (isDefinedFunctionIndex(Index))
366 getDefinedFunction(Index).DebugName = Name;
370 // Ignore local names for now
371 case wasm::WASM_NAMES_LOCAL:
376 if (Ctx.Ptr != SubSectionEnd)
377 return make_error<GenericBinaryError>(
378 "Name sub-section ended prematurely", object_error::parse_failed);
381 if (Ctx.Ptr != Ctx.End)
382 return make_error<GenericBinaryError>("Name section ended prematurely",
383 object_error::parse_failed);
384 return Error::success();
387 Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
388 HasLinkingSection = true;
389 if (Functions.size() != FunctionTypes.size()) {
390 return make_error<GenericBinaryError>(
391 "Linking data must come after code section",
392 object_error::parse_failed);
395 LinkingData.Version = readVaruint32(Ctx);
396 if (LinkingData.Version != wasm::WasmMetadataVersion) {
397 return make_error<GenericBinaryError>(
398 "Unexpected metadata version: " + Twine(LinkingData.Version) +
399 " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
400 object_error::parse_failed);
403 const uint8_t *OrigEnd = Ctx.End;
404 while (Ctx.Ptr < OrigEnd) {
406 uint8_t Type = readUint8(Ctx);
407 uint32_t Size = readVaruint32(Ctx);
408 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
410 Ctx.End = Ctx.Ptr + Size;
412 case wasm::WASM_SYMBOL_TABLE:
413 if (Error Err = parseLinkingSectionSymtab(Ctx))
416 case wasm::WASM_SEGMENT_INFO: {
417 uint32_t Count = readVaruint32(Ctx);
418 if (Count > DataSegments.size())
419 return make_error<GenericBinaryError>("Too many segment names",
420 object_error::parse_failed);
421 for (uint32_t i = 0; i < Count; i++) {
422 DataSegments[i].Data.Name = readString(Ctx);
423 DataSegments[i].Data.Alignment = readVaruint32(Ctx);
424 DataSegments[i].Data.Flags = readVaruint32(Ctx);
428 case wasm::WASM_INIT_FUNCS: {
429 uint32_t Count = readVaruint32(Ctx);
430 LinkingData.InitFunctions.reserve(Count);
431 for (uint32_t i = 0; i < Count; i++) {
432 wasm::WasmInitFunc Init;
433 Init.Priority = readVaruint32(Ctx);
434 Init.Symbol = readVaruint32(Ctx);
435 if (!isValidFunctionSymbol(Init.Symbol))
436 return make_error<GenericBinaryError>("Invalid function symbol: " +
438 object_error::parse_failed);
439 LinkingData.InitFunctions.emplace_back(Init);
443 case wasm::WASM_COMDAT_INFO:
444 if (Error Err = parseLinkingSectionComdat(Ctx))
451 if (Ctx.Ptr != Ctx.End)
452 return make_error<GenericBinaryError>(
453 "Linking sub-section ended prematurely", object_error::parse_failed);
455 if (Ctx.Ptr != OrigEnd)
456 return make_error<GenericBinaryError>("Linking section ended prematurely",
457 object_error::parse_failed);
458 return Error::success();
461 Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
462 uint32_t Count = readVaruint32(Ctx);
463 LinkingData.SymbolTable.reserve(Count);
464 Symbols.reserve(Count);
465 StringSet<> SymbolNames;
467 std::vector<wasm::WasmImport *> ImportedGlobals;
468 std::vector<wasm::WasmImport *> ImportedFunctions;
469 std::vector<wasm::WasmImport *> ImportedEvents;
470 ImportedGlobals.reserve(Imports.size());
471 ImportedFunctions.reserve(Imports.size());
472 ImportedEvents.reserve(Imports.size());
473 for (auto &I : Imports) {
474 if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
475 ImportedFunctions.emplace_back(&I);
476 else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
477 ImportedGlobals.emplace_back(&I);
478 else if (I.Kind == wasm::WASM_EXTERNAL_EVENT)
479 ImportedEvents.emplace_back(&I);
483 wasm::WasmSymbolInfo Info;
484 const wasm::WasmSignature *Signature = nullptr;
485 const wasm::WasmGlobalType *GlobalType = nullptr;
486 const wasm::WasmEventType *EventType = nullptr;
488 Info.Kind = readUint8(Ctx);
489 Info.Flags = readVaruint32(Ctx);
490 bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
493 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
494 Info.ElementIndex = readVaruint32(Ctx);
495 if (!isValidFunctionIndex(Info.ElementIndex) ||
496 IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
497 return make_error<GenericBinaryError>("invalid function symbol index",
498 object_error::parse_failed);
500 Info.Name = readString(Ctx);
501 unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
502 Signature = &Signatures[FunctionTypes[FuncIndex]];
503 wasm::WasmFunction &Function = Functions[FuncIndex];
504 if (Function.SymbolName.empty())
505 Function.SymbolName = Info.Name;
507 wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
508 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
509 Info.Name = readString(Ctx);
511 Info.Name = Import.Field;
512 Signature = &Signatures[Import.SigIndex];
513 Info.ImportName = Import.Field;
514 Info.ImportModule = Import.Module;
518 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
519 Info.ElementIndex = readVaruint32(Ctx);
520 if (!isValidGlobalIndex(Info.ElementIndex) ||
521 IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
522 return make_error<GenericBinaryError>("invalid global symbol index",
523 object_error::parse_failed);
524 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
525 wasm::WASM_SYMBOL_BINDING_WEAK)
526 return make_error<GenericBinaryError>("undefined weak global symbol",
527 object_error::parse_failed);
529 Info.Name = readString(Ctx);
530 unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
531 wasm::WasmGlobal &Global = Globals[GlobalIndex];
532 GlobalType = &Global.Type;
533 if (Global.SymbolName.empty())
534 Global.SymbolName = Info.Name;
536 wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
537 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
538 Info.Name = readString(Ctx);
540 Info.Name = Import.Field;
541 GlobalType = &Import.Global;
542 Info.ImportName = Import.Field;
543 Info.ImportModule = Import.Module;
547 case wasm::WASM_SYMBOL_TYPE_DATA:
548 Info.Name = readString(Ctx);
550 uint32_t Index = readVaruint32(Ctx);
551 if (Index >= DataSegments.size())
552 return make_error<GenericBinaryError>("invalid data symbol index",
553 object_error::parse_failed);
554 uint32_t Offset = readVaruint32(Ctx);
555 uint32_t Size = readVaruint32(Ctx);
556 if (Offset + Size > DataSegments[Index].Data.Content.size())
557 return make_error<GenericBinaryError>("invalid data symbol offset",
558 object_error::parse_failed);
559 Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
563 case wasm::WASM_SYMBOL_TYPE_SECTION: {
564 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
565 wasm::WASM_SYMBOL_BINDING_LOCAL)
566 return make_error<GenericBinaryError>(
567 "Section symbols must have local binding",
568 object_error::parse_failed);
569 Info.ElementIndex = readVaruint32(Ctx);
570 // Use somewhat unique section name as symbol name.
571 StringRef SectionName = Sections[Info.ElementIndex].Name;
572 Info.Name = SectionName;
576 case wasm::WASM_SYMBOL_TYPE_EVENT: {
577 Info.ElementIndex = readVaruint32(Ctx);
578 if (!isValidEventIndex(Info.ElementIndex) ||
579 IsDefined != isDefinedEventIndex(Info.ElementIndex))
580 return make_error<GenericBinaryError>("invalid event symbol index",
581 object_error::parse_failed);
582 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
583 wasm::WASM_SYMBOL_BINDING_WEAK)
584 return make_error<GenericBinaryError>("undefined weak global symbol",
585 object_error::parse_failed);
587 Info.Name = readString(Ctx);
588 unsigned EventIndex = Info.ElementIndex - NumImportedEvents;
589 wasm::WasmEvent &Event = Events[EventIndex];
590 Signature = &Signatures[Event.Type.SigIndex];
591 EventType = &Event.Type;
592 if (Event.SymbolName.empty())
593 Event.SymbolName = Info.Name;
596 wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
597 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
598 Info.Name = readString(Ctx);
600 Info.Name = Import.Field;
601 EventType = &Import.Event;
602 Signature = &Signatures[EventType->SigIndex];
603 Info.ImportName = Import.Field;
604 Info.ImportModule = Import.Module;
610 return make_error<GenericBinaryError>("Invalid symbol type",
611 object_error::parse_failed);
614 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
615 wasm::WASM_SYMBOL_BINDING_LOCAL &&
616 !SymbolNames.insert(Info.Name).second)
617 return make_error<GenericBinaryError>("Duplicate symbol name " +
619 object_error::parse_failed);
620 LinkingData.SymbolTable.emplace_back(Info);
621 Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, EventType,
623 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
626 return Error::success();
629 Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
630 uint32_t ComdatCount = readVaruint32(Ctx);
631 StringSet<> ComdatSet;
632 for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
633 StringRef Name = readString(Ctx);
634 if (Name.empty() || !ComdatSet.insert(Name).second)
635 return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
637 object_error::parse_failed);
638 LinkingData.Comdats.emplace_back(Name);
639 uint32_t Flags = readVaruint32(Ctx);
641 return make_error<GenericBinaryError>("Unsupported COMDAT flags",
642 object_error::parse_failed);
644 uint32_t EntryCount = readVaruint32(Ctx);
645 while (EntryCount--) {
646 unsigned Kind = readVaruint32(Ctx);
647 unsigned Index = readVaruint32(Ctx);
650 return make_error<GenericBinaryError>("Invalid COMDAT entry type",
651 object_error::parse_failed);
652 case wasm::WASM_COMDAT_DATA:
653 if (Index >= DataSegments.size())
654 return make_error<GenericBinaryError>(
655 "COMDAT data index out of range", object_error::parse_failed);
656 if (DataSegments[Index].Data.Comdat != UINT32_MAX)
657 return make_error<GenericBinaryError>("Data segment in two COMDATs",
658 object_error::parse_failed);
659 DataSegments[Index].Data.Comdat = ComdatIndex;
661 case wasm::WASM_COMDAT_FUNCTION:
662 if (!isDefinedFunctionIndex(Index))
663 return make_error<GenericBinaryError>(
664 "COMDAT function index out of range", object_error::parse_failed);
665 if (getDefinedFunction(Index).Comdat != UINT32_MAX)
666 return make_error<GenericBinaryError>("Function in two COMDATs",
667 object_error::parse_failed);
668 getDefinedFunction(Index).Comdat = ComdatIndex;
673 return Error::success();
676 Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
677 uint32_t SectionIndex = readVaruint32(Ctx);
678 if (SectionIndex >= Sections.size())
679 return make_error<GenericBinaryError>("Invalid section index",
680 object_error::parse_failed);
681 WasmSection &Section = Sections[SectionIndex];
682 uint32_t RelocCount = readVaruint32(Ctx);
683 uint32_t EndOffset = Section.Content.size();
684 uint32_t PreviousOffset = 0;
685 while (RelocCount--) {
686 wasm::WasmRelocation Reloc = {};
687 Reloc.Type = readVaruint32(Ctx);
688 Reloc.Offset = readVaruint32(Ctx);
689 if (Reloc.Offset < PreviousOffset)
690 return make_error<GenericBinaryError>("Relocations not in offset order",
691 object_error::parse_failed);
692 PreviousOffset = Reloc.Offset;
693 Reloc.Index = readVaruint32(Ctx);
694 switch (Reloc.Type) {
695 case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
696 case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
697 case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
698 if (!isValidFunctionSymbol(Reloc.Index))
699 return make_error<GenericBinaryError>("Bad relocation function index",
700 object_error::parse_failed);
702 case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
703 if (Reloc.Index >= Signatures.size())
704 return make_error<GenericBinaryError>("Bad relocation type index",
705 object_error::parse_failed);
707 case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
708 if (!isValidGlobalSymbol(Reloc.Index))
709 return make_error<GenericBinaryError>("Bad relocation global index",
710 object_error::parse_failed);
712 case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
713 if (!isValidEventSymbol(Reloc.Index))
714 return make_error<GenericBinaryError>("Bad relocation event index",
715 object_error::parse_failed);
717 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
718 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
719 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
720 if (!isValidDataSymbol(Reloc.Index))
721 return make_error<GenericBinaryError>("Bad relocation data index",
722 object_error::parse_failed);
723 Reloc.Addend = readVarint32(Ctx);
725 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
726 if (!isValidFunctionSymbol(Reloc.Index))
727 return make_error<GenericBinaryError>("Bad relocation function index",
728 object_error::parse_failed);
729 Reloc.Addend = readVarint32(Ctx);
731 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
732 if (!isValidSectionSymbol(Reloc.Index))
733 return make_error<GenericBinaryError>("Bad relocation section index",
734 object_error::parse_failed);
735 Reloc.Addend = readVarint32(Ctx);
738 return make_error<GenericBinaryError>("Bad relocation type: " +
740 object_error::parse_failed);
743 // Relocations must fit inside the section, and must appear in order. They
744 // also shouldn't overlap a function/element boundary, but we don't bother
747 if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 ||
748 Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32 ||
749 Reloc.Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32 ||
750 Reloc.Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32)
752 if (Reloc.Offset + Size > EndOffset)
753 return make_error<GenericBinaryError>("Bad relocation offset",
754 object_error::parse_failed);
756 Section.Relocations.push_back(Reloc);
758 if (Ctx.Ptr != Ctx.End)
759 return make_error<GenericBinaryError>("Reloc section ended prematurely",
760 object_error::parse_failed);
761 return Error::success();
764 Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
765 if (Sec.Name == "dylink") {
766 if (Error Err = parseDylinkSection(Ctx))
768 } else if (Sec.Name == "name") {
769 if (Error Err = parseNameSection(Ctx))
771 } else if (Sec.Name == "linking") {
772 if (Error Err = parseLinkingSection(Ctx))
774 } else if (Sec.Name.startswith("reloc.")) {
775 if (Error Err = parseRelocSection(Sec.Name, Ctx))
778 return Error::success();
781 Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
782 uint32_t Count = readVaruint32(Ctx);
783 Signatures.reserve(Count);
785 wasm::WasmSignature Sig;
786 uint8_t Form = readUint8(Ctx);
787 if (Form != wasm::WASM_TYPE_FUNC) {
788 return make_error<GenericBinaryError>("Invalid signature type",
789 object_error::parse_failed);
791 uint32_t ParamCount = readVaruint32(Ctx);
792 Sig.Params.reserve(ParamCount);
793 while (ParamCount--) {
794 uint32_t ParamType = readUint8(Ctx);
795 Sig.Params.push_back(wasm::ValType(ParamType));
797 uint32_t ReturnCount = readVaruint32(Ctx);
799 if (ReturnCount != 1) {
800 return make_error<GenericBinaryError>(
801 "Multiple return types not supported", object_error::parse_failed);
803 Sig.Returns.push_back(wasm::ValType(readUint8(Ctx)));
805 Signatures.push_back(std::move(Sig));
807 if (Ctx.Ptr != Ctx.End)
808 return make_error<GenericBinaryError>("Type section ended prematurely",
809 object_error::parse_failed);
810 return Error::success();
813 Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
814 uint32_t Count = readVaruint32(Ctx);
815 Imports.reserve(Count);
816 for (uint32_t i = 0; i < Count; i++) {
818 Im.Module = readString(Ctx);
819 Im.Field = readString(Ctx);
820 Im.Kind = readUint8(Ctx);
822 case wasm::WASM_EXTERNAL_FUNCTION:
823 NumImportedFunctions++;
824 Im.SigIndex = readVaruint32(Ctx);
826 case wasm::WASM_EXTERNAL_GLOBAL:
827 NumImportedGlobals++;
828 Im.Global.Type = readUint8(Ctx);
829 Im.Global.Mutable = readVaruint1(Ctx);
831 case wasm::WASM_EXTERNAL_MEMORY:
832 Im.Memory = readLimits(Ctx);
834 case wasm::WASM_EXTERNAL_TABLE:
835 Im.Table = readTable(Ctx);
836 if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF)
837 return make_error<GenericBinaryError>("Invalid table element type",
838 object_error::parse_failed);
840 case wasm::WASM_EXTERNAL_EVENT:
842 Im.Event.Attribute = readVarint32(Ctx);
843 Im.Event.SigIndex = readVarint32(Ctx);
846 return make_error<GenericBinaryError>("Unexpected import kind",
847 object_error::parse_failed);
849 Imports.push_back(Im);
851 if (Ctx.Ptr != Ctx.End)
852 return make_error<GenericBinaryError>("Import section ended prematurely",
853 object_error::parse_failed);
854 return Error::success();
857 Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
858 uint32_t Count = readVaruint32(Ctx);
859 FunctionTypes.reserve(Count);
860 uint32_t NumTypes = Signatures.size();
862 uint32_t Type = readVaruint32(Ctx);
863 if (Type >= NumTypes)
864 return make_error<GenericBinaryError>("Invalid function type",
865 object_error::parse_failed);
866 FunctionTypes.push_back(Type);
868 if (Ctx.Ptr != Ctx.End)
869 return make_error<GenericBinaryError>("Function section ended prematurely",
870 object_error::parse_failed);
871 return Error::success();
874 Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
875 uint32_t Count = readVaruint32(Ctx);
876 Tables.reserve(Count);
878 Tables.push_back(readTable(Ctx));
879 if (Tables.back().ElemType != wasm::WASM_TYPE_FUNCREF) {
880 return make_error<GenericBinaryError>("Invalid table element type",
881 object_error::parse_failed);
884 if (Ctx.Ptr != Ctx.End)
885 return make_error<GenericBinaryError>("Table section ended prematurely",
886 object_error::parse_failed);
887 return Error::success();
890 Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
891 uint32_t Count = readVaruint32(Ctx);
892 Memories.reserve(Count);
894 Memories.push_back(readLimits(Ctx));
896 if (Ctx.Ptr != Ctx.End)
897 return make_error<GenericBinaryError>("Memory section ended prematurely",
898 object_error::parse_failed);
899 return Error::success();
902 Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
903 GlobalSection = Sections.size();
904 uint32_t Count = readVaruint32(Ctx);
905 Globals.reserve(Count);
907 wasm::WasmGlobal Global;
908 Global.Index = NumImportedGlobals + Globals.size();
909 Global.Type.Type = readUint8(Ctx);
910 Global.Type.Mutable = readVaruint1(Ctx);
911 if (Error Err = readInitExpr(Global.InitExpr, Ctx))
913 Globals.push_back(Global);
915 if (Ctx.Ptr != Ctx.End)
916 return make_error<GenericBinaryError>("Global section ended prematurely",
917 object_error::parse_failed);
918 return Error::success();
921 Error WasmObjectFile::parseEventSection(ReadContext &Ctx) {
922 EventSection = Sections.size();
923 uint32_t Count = readVarint32(Ctx);
924 Events.reserve(Count);
926 wasm::WasmEvent Event;
927 Event.Index = NumImportedEvents + Events.size();
928 Event.Type.Attribute = readVaruint32(Ctx);
929 Event.Type.SigIndex = readVarint32(Ctx);
930 Events.push_back(Event);
933 if (Ctx.Ptr != Ctx.End)
934 return make_error<GenericBinaryError>("Event section ended prematurely",
935 object_error::parse_failed);
936 return Error::success();
939 Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
940 uint32_t Count = readVaruint32(Ctx);
941 Exports.reserve(Count);
942 for (uint32_t i = 0; i < Count; i++) {
944 Ex.Name = readString(Ctx);
945 Ex.Kind = readUint8(Ctx);
946 Ex.Index = readVaruint32(Ctx);
948 case wasm::WASM_EXTERNAL_FUNCTION:
949 if (!isValidFunctionIndex(Ex.Index))
950 return make_error<GenericBinaryError>("Invalid function export",
951 object_error::parse_failed);
953 case wasm::WASM_EXTERNAL_GLOBAL:
954 if (!isValidGlobalIndex(Ex.Index))
955 return make_error<GenericBinaryError>("Invalid global export",
956 object_error::parse_failed);
958 case wasm::WASM_EXTERNAL_EVENT:
959 if (!isValidEventIndex(Ex.Index))
960 return make_error<GenericBinaryError>("Invalid event export",
961 object_error::parse_failed);
963 case wasm::WASM_EXTERNAL_MEMORY:
964 case wasm::WASM_EXTERNAL_TABLE:
967 return make_error<GenericBinaryError>("Unexpected export kind",
968 object_error::parse_failed);
970 Exports.push_back(Ex);
972 if (Ctx.Ptr != Ctx.End)
973 return make_error<GenericBinaryError>("Export section ended prematurely",
974 object_error::parse_failed);
975 return Error::success();
978 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
979 return Index < NumImportedFunctions + FunctionTypes.size();
982 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
983 return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
986 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
987 return Index < NumImportedGlobals + Globals.size();
990 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
991 return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
994 bool WasmObjectFile::isValidEventIndex(uint32_t Index) const {
995 return Index < NumImportedEvents + Events.size();
998 bool WasmObjectFile::isDefinedEventIndex(uint32_t Index) const {
999 return Index >= NumImportedEvents && isValidEventIndex(Index);
1002 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1003 return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1006 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1007 return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1010 bool WasmObjectFile::isValidEventSymbol(uint32_t Index) const {
1011 return Index < Symbols.size() && Symbols[Index].isTypeEvent();
1014 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1015 return Index < Symbols.size() && Symbols[Index].isTypeData();
1018 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1019 return Index < Symbols.size() && Symbols[Index].isTypeSection();
1022 wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1023 assert(isDefinedFunctionIndex(Index));
1024 return Functions[Index - NumImportedFunctions];
1027 wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
1028 assert(isDefinedGlobalIndex(Index));
1029 return Globals[Index - NumImportedGlobals];
1032 wasm::WasmEvent &WasmObjectFile::getDefinedEvent(uint32_t Index) {
1033 assert(isDefinedEventIndex(Index));
1034 return Events[Index - NumImportedEvents];
1037 Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1038 StartFunction = readVaruint32(Ctx);
1039 if (!isValidFunctionIndex(StartFunction))
1040 return make_error<GenericBinaryError>("Invalid start function",
1041 object_error::parse_failed);
1042 return Error::success();
1045 Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1046 CodeSection = Sections.size();
1047 uint32_t FunctionCount = readVaruint32(Ctx);
1048 if (FunctionCount != FunctionTypes.size()) {
1049 return make_error<GenericBinaryError>("Invalid function count",
1050 object_error::parse_failed);
1053 while (FunctionCount--) {
1054 wasm::WasmFunction Function;
1055 const uint8_t *FunctionStart = Ctx.Ptr;
1056 uint32_t Size = readVaruint32(Ctx);
1057 const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1059 Function.CodeOffset = Ctx.Ptr - FunctionStart;
1060 Function.Index = NumImportedFunctions + Functions.size();
1061 Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1062 Function.Size = FunctionEnd - FunctionStart;
1064 uint32_t NumLocalDecls = readVaruint32(Ctx);
1065 Function.Locals.reserve(NumLocalDecls);
1066 while (NumLocalDecls--) {
1067 wasm::WasmLocalDecl Decl;
1068 Decl.Count = readVaruint32(Ctx);
1069 Decl.Type = readUint8(Ctx);
1070 Function.Locals.push_back(Decl);
1073 uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1074 Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1075 // This will be set later when reading in the linking metadata section.
1076 Function.Comdat = UINT32_MAX;
1077 Ctx.Ptr += BodySize;
1078 assert(Ctx.Ptr == FunctionEnd);
1079 Functions.push_back(Function);
1081 if (Ctx.Ptr != Ctx.End)
1082 return make_error<GenericBinaryError>("Code section ended prematurely",
1083 object_error::parse_failed);
1084 return Error::success();
1087 Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1088 uint32_t Count = readVaruint32(Ctx);
1089 ElemSegments.reserve(Count);
1091 wasm::WasmElemSegment Segment;
1092 Segment.TableIndex = readVaruint32(Ctx);
1093 if (Segment.TableIndex != 0) {
1094 return make_error<GenericBinaryError>("Invalid TableIndex",
1095 object_error::parse_failed);
1097 if (Error Err = readInitExpr(Segment.Offset, Ctx))
1099 uint32_t NumElems = readVaruint32(Ctx);
1100 while (NumElems--) {
1101 Segment.Functions.push_back(readVaruint32(Ctx));
1103 ElemSegments.push_back(Segment);
1105 if (Ctx.Ptr != Ctx.End)
1106 return make_error<GenericBinaryError>("Elem section ended prematurely",
1107 object_error::parse_failed);
1108 return Error::success();
1111 Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1112 DataSection = Sections.size();
1113 uint32_t Count = readVaruint32(Ctx);
1114 DataSegments.reserve(Count);
1116 WasmSegment Segment;
1117 Segment.Data.MemoryIndex = readVaruint32(Ctx);
1118 if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1120 uint32_t Size = readVaruint32(Ctx);
1121 if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1122 return make_error<GenericBinaryError>("Invalid segment size",
1123 object_error::parse_failed);
1124 Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1125 // The rest of these Data fields are set later, when reading in the linking
1126 // metadata section.
1127 Segment.Data.Alignment = 0;
1128 Segment.Data.Flags = 0;
1129 Segment.Data.Comdat = UINT32_MAX;
1130 Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1132 DataSegments.push_back(Segment);
1134 if (Ctx.Ptr != Ctx.End)
1135 return make_error<GenericBinaryError>("Data section ended prematurely",
1136 object_error::parse_failed);
1137 return Error::success();
1140 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
1141 return reinterpret_cast<const uint8_t *>(getData().data() + Offset);
1144 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1148 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
1150 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
1151 uint32_t Result = SymbolRef::SF_None;
1152 const WasmSymbol &Sym = getWasmSymbol(Symb);
1154 LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1155 if (Sym.isBindingWeak())
1156 Result |= SymbolRef::SF_Weak;
1157 if (!Sym.isBindingLocal())
1158 Result |= SymbolRef::SF_Global;
1160 Result |= SymbolRef::SF_Hidden;
1161 if (!Sym.isDefined())
1162 Result |= SymbolRef::SF_Undefined;
1163 if (Sym.isTypeFunction())
1164 Result |= SymbolRef::SF_Executable;
1168 basic_symbol_iterator WasmObjectFile::symbol_begin() const {
1171 return BasicSymbolRef(Ref, this);
1174 basic_symbol_iterator WasmObjectFile::symbol_end() const {
1176 Ref.d.a = Symbols.size();
1177 return BasicSymbolRef(Ref, this);
1180 const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
1181 return Symbols[Symb.d.a];
1184 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1185 return getWasmSymbol(Symb.getRawDataRefImpl());
1188 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
1189 return getWasmSymbol(Symb).Info.Name;
1192 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
1193 return getSymbolValue(Symb);
1196 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
1197 switch (Sym.Info.Kind) {
1198 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1199 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1200 case wasm::WASM_SYMBOL_TYPE_EVENT:
1201 return Sym.Info.ElementIndex;
1202 case wasm::WASM_SYMBOL_TYPE_DATA: {
1203 // The value of a data symbol is the segment offset, plus the symbol
1204 // offset within the segment.
1205 uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1206 const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1207 assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST);
1208 return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
1210 case wasm::WASM_SYMBOL_TYPE_SECTION:
1213 llvm_unreachable("invalid symbol type");
1216 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1217 return getWasmSymbolValue(getWasmSymbol(Symb));
1220 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1221 llvm_unreachable("not yet implemented");
1225 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1226 llvm_unreachable("not yet implemented");
1230 Expected<SymbolRef::Type>
1231 WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
1232 const WasmSymbol &Sym = getWasmSymbol(Symb);
1234 switch (Sym.Info.Kind) {
1235 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1236 return SymbolRef::ST_Function;
1237 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1238 return SymbolRef::ST_Other;
1239 case wasm::WASM_SYMBOL_TYPE_DATA:
1240 return SymbolRef::ST_Data;
1241 case wasm::WASM_SYMBOL_TYPE_SECTION:
1242 return SymbolRef::ST_Debug;
1243 case wasm::WASM_SYMBOL_TYPE_EVENT:
1244 return SymbolRef::ST_Other;
1247 llvm_unreachable("Unknown WasmSymbol::SymbolType");
1248 return SymbolRef::ST_Other;
1251 Expected<section_iterator>
1252 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1253 const WasmSymbol &Sym = getWasmSymbol(Symb);
1254 if (Sym.isUndefined())
1255 return section_end();
1258 switch (Sym.Info.Kind) {
1259 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1260 Ref.d.a = CodeSection;
1262 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1263 Ref.d.a = GlobalSection;
1265 case wasm::WASM_SYMBOL_TYPE_DATA:
1266 Ref.d.a = DataSection;
1268 case wasm::WASM_SYMBOL_TYPE_SECTION:
1269 Ref.d.a = Sym.Info.ElementIndex;
1271 case wasm::WASM_SYMBOL_TYPE_EVENT:
1272 Ref.d.a = EventSection;
1275 llvm_unreachable("Unknown WasmSymbol::SymbolType");
1277 return section_iterator(SectionRef(Ref, this));
1280 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1282 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
1283 StringRef &Res) const {
1284 const WasmSection &S = Sections[Sec.d.a];
1286 case wasm::WASM_SEC_##X: \
1302 case wasm::WASM_SEC_CUSTOM:
1306 return object_error::invalid_section_index;
1309 return std::error_code();
1312 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1314 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1318 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1319 const WasmSection &S = Sections[Sec.d.a];
1320 return S.Content.size();
1323 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
1324 StringRef &Res) const {
1325 const WasmSection &S = Sections[Sec.d.a];
1326 // This will never fail since wasm sections can never be empty (user-sections
1327 // must have a name and non-user sections each have a defined structure).
1328 Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
1330 return std::error_code();
1333 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1337 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1341 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
1342 return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1345 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
1346 return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1349 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1351 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1353 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
1355 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1356 DataRefImpl RelocRef;
1357 RelocRef.d.a = Ref.d.a;
1359 return relocation_iterator(RelocationRef(RelocRef, this));
1362 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1363 const WasmSection &Sec = getWasmSection(Ref);
1364 DataRefImpl RelocRef;
1365 RelocRef.d.a = Ref.d.a;
1366 RelocRef.d.b = Sec.Relocations.size();
1367 return relocation_iterator(RelocationRef(RelocRef, this));
1370 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
1372 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1373 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1377 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
1378 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1379 if (Rel.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
1380 return symbol_end();
1382 Sym.d.a = Rel.Index;
1384 return symbol_iterator(SymbolRef(Sym, this));
1387 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1388 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1392 void WasmObjectFile::getRelocationTypeName(
1393 DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1394 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1395 StringRef Res = "Unknown";
1397 #define WASM_RELOC(name, value) \
1403 #include "llvm/BinaryFormat/WasmRelocs.def"
1408 Result.append(Res.begin(), Res.end());
1411 section_iterator WasmObjectFile::section_begin() const {
1414 return section_iterator(SectionRef(Ref, this));
1417 section_iterator WasmObjectFile::section_end() const {
1419 Ref.d.a = Sections.size();
1420 return section_iterator(SectionRef(Ref, this));
1423 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1425 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1427 Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
1429 SubtargetFeatures WasmObjectFile::getFeatures() const {
1430 return SubtargetFeatures();
1433 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1435 bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
1437 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
1438 assert(Ref.d.a < Sections.size());
1439 return Sections[Ref.d.a];
1443 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
1444 return getWasmSection(Section.getRawDataRefImpl());
1447 const wasm::WasmRelocation &
1448 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1449 return getWasmRelocation(Ref.getRawDataRefImpl());
1452 const wasm::WasmRelocation &
1453 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
1454 assert(Ref.d.a < Sections.size());
1455 const WasmSection &Sec = Sections[Ref.d.a];
1456 assert(Ref.d.b < Sec.Relocations.size());
1457 return Sec.Relocations[Ref.d.b];
1460 int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1461 StringRef CustomSectionName) {
1463 case wasm::WASM_SEC_CUSTOM:
1464 return StringSwitch<unsigned>(CustomSectionName)
1465 .Case("dylink", WASM_SEC_ORDER_DYLINK)
1466 .Case("linking", WASM_SEC_ORDER_LINKING)
1467 .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
1468 .Case("name", WASM_SEC_ORDER_NAME)
1469 .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1471 case wasm::WASM_SEC_TYPE:
1472 return WASM_SEC_ORDER_TYPE;
1473 case wasm::WASM_SEC_IMPORT:
1474 return WASM_SEC_ORDER_IMPORT;
1475 case wasm::WASM_SEC_FUNCTION:
1476 return WASM_SEC_ORDER_FUNCTION;
1477 case wasm::WASM_SEC_TABLE:
1478 return WASM_SEC_ORDER_TABLE;
1479 case wasm::WASM_SEC_MEMORY:
1480 return WASM_SEC_ORDER_MEMORY;
1481 case wasm::WASM_SEC_GLOBAL:
1482 return WASM_SEC_ORDER_GLOBAL;
1483 case wasm::WASM_SEC_EXPORT:
1484 return WASM_SEC_ORDER_EXPORT;
1485 case wasm::WASM_SEC_START:
1486 return WASM_SEC_ORDER_START;
1487 case wasm::WASM_SEC_ELEM:
1488 return WASM_SEC_ORDER_ELEM;
1489 case wasm::WASM_SEC_CODE:
1490 return WASM_SEC_ORDER_CODE;
1491 case wasm::WASM_SEC_DATA:
1492 return WASM_SEC_ORDER_DATA;
1493 case wasm::WASM_SEC_DATACOUNT:
1494 return WASM_SEC_ORDER_DATACOUNT;
1495 case wasm::WASM_SEC_EVENT:
1496 return WASM_SEC_ORDER_EVENT;
1498 llvm_unreachable("invalid section");
1502 bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
1503 StringRef CustomSectionName) {
1504 int Order = getSectionOrder(ID, CustomSectionName);
1505 if (Order == -1) // Skip unknown sections
1507 // There can be multiple "reloc." sections. Otherwise there shouldn't be any
1508 // duplicate section orders.
1509 bool IsValid = (LastOrder == Order && Order == WASM_SEC_ORDER_RELOC) ||