[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Object / WasmObjectFile.cpp
bloba08c648358c032e7f1e8b3e640c65ba155e7e91d
1 //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/ArrayRef.h"
10 #include "llvm/ADT/DenseSet.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SmallSet.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/ADT/StringSet.h"
15 #include "llvm/ADT/StringSwitch.h"
16 #include "llvm/ADT/Triple.h"
17 #include "llvm/BinaryFormat/Wasm.h"
18 #include "llvm/MC/SubtargetFeature.h"
19 #include "llvm/Object/Binary.h"
20 #include "llvm/Object/Error.h"
21 #include "llvm/Object/ObjectFile.h"
22 #include "llvm/Object/SymbolicFile.h"
23 #include "llvm/Object/Wasm.h"
24 #include "llvm/Support/Endian.h"
25 #include "llvm/Support/Error.h"
26 #include "llvm/Support/ErrorHandling.h"
27 #include "llvm/Support/LEB128.h"
28 #include "llvm/Support/ScopedPrinter.h"
29 #include <algorithm>
30 #include <cassert>
31 #include <cstdint>
32 #include <cstring>
33 #include <system_error>
35 #define DEBUG_TYPE "wasm-object"
37 using namespace llvm;
38 using namespace object;
40 void WasmSymbol::print(raw_ostream &Out) const {
41 Out << "Name=" << Info.Name
42 << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"
43 << Twine::utohexstr(Info.Flags);
44 if (!isTypeData()) {
45 Out << ", ElemIndex=" << Info.ElementIndex;
46 } else if (isDefined()) {
47 Out << ", Segment=" << Info.DataRef.Segment;
48 Out << ", Offset=" << Info.DataRef.Offset;
49 Out << ", Size=" << Info.DataRef.Size;
53 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
54 LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
55 #endif
57 Expected<std::unique_ptr<WasmObjectFile>>
58 ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
59 Error Err = Error::success();
60 auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
61 if (Err)
62 return std::move(Err);
64 return std::move(ObjectFile);
67 #define VARINT7_MAX ((1 << 7) - 1)
68 #define VARINT7_MIN (-(1 << 7))
69 #define VARUINT7_MAX (1 << 7)
70 #define VARUINT1_MAX (1)
72 static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
73 if (Ctx.Ptr == Ctx.End)
74 report_fatal_error("EOF while reading uint8");
75 return *Ctx.Ptr++;
78 static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
79 if (Ctx.Ptr + 4 > Ctx.End)
80 report_fatal_error("EOF while reading uint32");
81 uint32_t Result = support::endian::read32le(Ctx.Ptr);
82 Ctx.Ptr += 4;
83 return Result;
86 static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
87 if (Ctx.Ptr + 4 > Ctx.End)
88 report_fatal_error("EOF while reading float64");
89 int32_t Result = 0;
90 memcpy(&Result, Ctx.Ptr, sizeof(Result));
91 Ctx.Ptr += sizeof(Result);
92 return Result;
95 static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
96 if (Ctx.Ptr + 8 > Ctx.End)
97 report_fatal_error("EOF while reading float64");
98 int64_t Result = 0;
99 memcpy(&Result, Ctx.Ptr, sizeof(Result));
100 Ctx.Ptr += sizeof(Result);
101 return Result;
104 static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
105 unsigned Count;
106 const char *Error = nullptr;
107 uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
108 if (Error)
109 report_fatal_error(Error);
110 Ctx.Ptr += Count;
111 return Result;
114 static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
115 uint32_t StringLen = readULEB128(Ctx);
116 if (Ctx.Ptr + StringLen > Ctx.End)
117 report_fatal_error("EOF while reading string");
118 StringRef Return =
119 StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
120 Ctx.Ptr += StringLen;
121 return Return;
124 static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
125 unsigned Count;
126 const char *Error = nullptr;
127 uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
128 if (Error)
129 report_fatal_error(Error);
130 Ctx.Ptr += Count;
131 return Result;
134 static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
135 int64_t Result = readLEB128(Ctx);
136 if (Result > VARUINT1_MAX || Result < 0)
137 report_fatal_error("LEB is outside Varuint1 range");
138 return Result;
141 static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
142 int64_t Result = readLEB128(Ctx);
143 if (Result > INT32_MAX || Result < INT32_MIN)
144 report_fatal_error("LEB is outside Varint32 range");
145 return Result;
148 static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
149 uint64_t Result = readULEB128(Ctx);
150 if (Result > UINT32_MAX)
151 report_fatal_error("LEB is outside Varuint32 range");
152 return Result;
155 static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
156 return readLEB128(Ctx);
159 static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) {
160 return readULEB128(Ctx);
163 static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
164 return readUint8(Ctx);
167 static Error readInitExpr(wasm::WasmInitExpr &Expr,
168 WasmObjectFile::ReadContext &Ctx) {
169 Expr.Opcode = readOpcode(Ctx);
171 switch (Expr.Opcode) {
172 case wasm::WASM_OPCODE_I32_CONST:
173 Expr.Value.Int32 = readVarint32(Ctx);
174 break;
175 case wasm::WASM_OPCODE_I64_CONST:
176 Expr.Value.Int64 = readVarint64(Ctx);
177 break;
178 case wasm::WASM_OPCODE_F32_CONST:
179 Expr.Value.Float32 = readFloat32(Ctx);
180 break;
181 case wasm::WASM_OPCODE_F64_CONST:
182 Expr.Value.Float64 = readFloat64(Ctx);
183 break;
184 case wasm::WASM_OPCODE_GLOBAL_GET:
185 Expr.Value.Global = readULEB128(Ctx);
186 break;
187 case wasm::WASM_OPCODE_REF_NULL: {
188 wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx));
189 if (Ty != wasm::ValType::EXTERNREF) {
190 return make_error<GenericBinaryError>("invalid type for ref.null",
191 object_error::parse_failed);
193 break;
195 default:
196 return make_error<GenericBinaryError>("invalid opcode in init_expr",
197 object_error::parse_failed);
200 uint8_t EndOpcode = readOpcode(Ctx);
201 if (EndOpcode != wasm::WASM_OPCODE_END) {
202 return make_error<GenericBinaryError>("invalid init_expr",
203 object_error::parse_failed);
205 return Error::success();
208 static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
209 wasm::WasmLimits Result;
210 Result.Flags = readVaruint32(Ctx);
211 Result.Minimum = readVaruint64(Ctx);
212 if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
213 Result.Maximum = readVaruint64(Ctx);
214 return Result;
217 static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) {
218 wasm::WasmTableType TableType;
219 TableType.ElemType = readUint8(Ctx);
220 TableType.Limits = readLimits(Ctx);
221 return TableType;
224 static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
225 WasmSectionOrderChecker &Checker) {
226 Section.Offset = Ctx.Ptr - Ctx.Start;
227 Section.Type = readUint8(Ctx);
228 LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
229 uint32_t Size = readVaruint32(Ctx);
230 if (Size == 0)
231 return make_error<StringError>("zero length section",
232 object_error::parse_failed);
233 if (Ctx.Ptr + Size > Ctx.End)
234 return make_error<StringError>("section too large",
235 object_error::parse_failed);
236 if (Section.Type == wasm::WASM_SEC_CUSTOM) {
237 WasmObjectFile::ReadContext SectionCtx;
238 SectionCtx.Start = Ctx.Ptr;
239 SectionCtx.Ptr = Ctx.Ptr;
240 SectionCtx.End = Ctx.Ptr + Size;
242 Section.Name = readString(SectionCtx);
244 uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
245 Ctx.Ptr += SectionNameSize;
246 Size -= SectionNameSize;
249 if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
250 return make_error<StringError>("out of order section type: " +
251 llvm::to_string(Section.Type),
252 object_error::parse_failed);
255 Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
256 Ctx.Ptr += Size;
257 return Error::success();
260 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
261 : ObjectFile(Binary::ID_Wasm, Buffer) {
262 ErrorAsOutParameter ErrAsOutParam(&Err);
263 Header.Magic = getData().substr(0, 4);
264 if (Header.Magic != StringRef("\0asm", 4)) {
265 Err = make_error<StringError>("invalid magic number",
266 object_error::parse_failed);
267 return;
270 ReadContext Ctx;
271 Ctx.Start = getData().bytes_begin();
272 Ctx.Ptr = Ctx.Start + 4;
273 Ctx.End = Ctx.Start + getData().size();
275 if (Ctx.Ptr + 4 > Ctx.End) {
276 Err = make_error<StringError>("missing version number",
277 object_error::parse_failed);
278 return;
281 Header.Version = readUint32(Ctx);
282 if (Header.Version != wasm::WasmVersion) {
283 Err = make_error<StringError>("invalid version number: " +
284 Twine(Header.Version),
285 object_error::parse_failed);
286 return;
289 WasmSection Sec;
290 WasmSectionOrderChecker Checker;
291 while (Ctx.Ptr < Ctx.End) {
292 if ((Err = readSection(Sec, Ctx, Checker)))
293 return;
294 if ((Err = parseSection(Sec)))
295 return;
297 Sections.push_back(Sec);
301 Error WasmObjectFile::parseSection(WasmSection &Sec) {
302 ReadContext Ctx;
303 Ctx.Start = Sec.Content.data();
304 Ctx.End = Ctx.Start + Sec.Content.size();
305 Ctx.Ptr = Ctx.Start;
306 switch (Sec.Type) {
307 case wasm::WASM_SEC_CUSTOM:
308 return parseCustomSection(Sec, Ctx);
309 case wasm::WASM_SEC_TYPE:
310 return parseTypeSection(Ctx);
311 case wasm::WASM_SEC_IMPORT:
312 return parseImportSection(Ctx);
313 case wasm::WASM_SEC_FUNCTION:
314 return parseFunctionSection(Ctx);
315 case wasm::WASM_SEC_TABLE:
316 return parseTableSection(Ctx);
317 case wasm::WASM_SEC_MEMORY:
318 return parseMemorySection(Ctx);
319 case wasm::WASM_SEC_TAG:
320 return parseTagSection(Ctx);
321 case wasm::WASM_SEC_GLOBAL:
322 return parseGlobalSection(Ctx);
323 case wasm::WASM_SEC_EXPORT:
324 return parseExportSection(Ctx);
325 case wasm::WASM_SEC_START:
326 return parseStartSection(Ctx);
327 case wasm::WASM_SEC_ELEM:
328 return parseElemSection(Ctx);
329 case wasm::WASM_SEC_CODE:
330 return parseCodeSection(Ctx);
331 case wasm::WASM_SEC_DATA:
332 return parseDataSection(Ctx);
333 case wasm::WASM_SEC_DATACOUNT:
334 return parseDataCountSection(Ctx);
335 default:
336 return make_error<GenericBinaryError>(
337 "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
341 Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
342 // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
343 HasDylinkSection = true;
344 DylinkInfo.MemorySize = readVaruint32(Ctx);
345 DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
346 DylinkInfo.TableSize = readVaruint32(Ctx);
347 DylinkInfo.TableAlignment = readVaruint32(Ctx);
348 uint32_t Count = readVaruint32(Ctx);
349 while (Count--) {
350 DylinkInfo.Needed.push_back(readString(Ctx));
352 if (Ctx.Ptr != Ctx.End)
353 return make_error<GenericBinaryError>("dylink section ended prematurely",
354 object_error::parse_failed);
355 return Error::success();
358 Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
359 llvm::DenseSet<uint64_t> SeenFunctions;
360 llvm::DenseSet<uint64_t> SeenGlobals;
361 llvm::DenseSet<uint64_t> SeenSegments;
362 if (FunctionTypes.size() && !SeenCodeSection) {
363 return make_error<GenericBinaryError>("names must come after code section",
364 object_error::parse_failed);
367 while (Ctx.Ptr < Ctx.End) {
368 uint8_t Type = readUint8(Ctx);
369 uint32_t Size = readVaruint32(Ctx);
370 const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
371 switch (Type) {
372 case wasm::WASM_NAMES_FUNCTION:
373 case wasm::WASM_NAMES_GLOBAL:
374 case wasm::WASM_NAMES_DATA_SEGMENT: {
375 uint32_t Count = readVaruint32(Ctx);
376 while (Count--) {
377 uint32_t Index = readVaruint32(Ctx);
378 StringRef Name = readString(Ctx);
379 wasm::NameType nameType = wasm::NameType::FUNCTION;
380 if (Type == wasm::WASM_NAMES_FUNCTION) {
381 if (!SeenFunctions.insert(Index).second)
382 return make_error<GenericBinaryError>(
383 "function named more than once", object_error::parse_failed);
384 if (!isValidFunctionIndex(Index) || Name.empty())
385 return make_error<GenericBinaryError>("invalid name entry",
386 object_error::parse_failed);
388 if (isDefinedFunctionIndex(Index))
389 getDefinedFunction(Index).DebugName = Name;
390 } else if (Type == wasm::WASM_NAMES_GLOBAL) {
391 nameType = wasm::NameType::GLOBAL;
392 if (!SeenGlobals.insert(Index).second)
393 return make_error<GenericBinaryError>("global named more than once",
394 object_error::parse_failed);
395 if (!isValidGlobalIndex(Index) || Name.empty())
396 return make_error<GenericBinaryError>("invalid name entry",
397 object_error::parse_failed);
398 } else {
399 nameType = wasm::NameType::DATA_SEGMENT;
400 if (!SeenSegments.insert(Index).second)
401 return make_error<GenericBinaryError>(
402 "segment named more than once", object_error::parse_failed);
403 if (Index > DataSegments.size())
404 return make_error<GenericBinaryError>("invalid named data segment",
405 object_error::parse_failed);
407 DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
409 break;
411 // Ignore local names for now
412 case wasm::WASM_NAMES_LOCAL:
413 default:
414 Ctx.Ptr += Size;
415 break;
417 if (Ctx.Ptr != SubSectionEnd)
418 return make_error<GenericBinaryError>(
419 "name sub-section ended prematurely", object_error::parse_failed);
422 if (Ctx.Ptr != Ctx.End)
423 return make_error<GenericBinaryError>("name section ended prematurely",
424 object_error::parse_failed);
425 return Error::success();
428 Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
429 HasLinkingSection = true;
430 if (FunctionTypes.size() && !SeenCodeSection) {
431 return make_error<GenericBinaryError>(
432 "linking data must come after code section",
433 object_error::parse_failed);
436 LinkingData.Version = readVaruint32(Ctx);
437 if (LinkingData.Version != wasm::WasmMetadataVersion) {
438 return make_error<GenericBinaryError>(
439 "unexpected metadata version: " + Twine(LinkingData.Version) +
440 " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
441 object_error::parse_failed);
444 const uint8_t *OrigEnd = Ctx.End;
445 while (Ctx.Ptr < OrigEnd) {
446 Ctx.End = OrigEnd;
447 uint8_t Type = readUint8(Ctx);
448 uint32_t Size = readVaruint32(Ctx);
449 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
450 << "\n");
451 Ctx.End = Ctx.Ptr + Size;
452 switch (Type) {
453 case wasm::WASM_SYMBOL_TABLE:
454 if (Error Err = parseLinkingSectionSymtab(Ctx))
455 return Err;
456 break;
457 case wasm::WASM_SEGMENT_INFO: {
458 uint32_t Count = readVaruint32(Ctx);
459 if (Count > DataSegments.size())
460 return make_error<GenericBinaryError>("too many segment names",
461 object_error::parse_failed);
462 for (uint32_t I = 0; I < Count; I++) {
463 DataSegments[I].Data.Name = readString(Ctx);
464 DataSegments[I].Data.Alignment = readVaruint32(Ctx);
465 DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);
467 break;
469 case wasm::WASM_INIT_FUNCS: {
470 uint32_t Count = readVaruint32(Ctx);
471 LinkingData.InitFunctions.reserve(Count);
472 for (uint32_t I = 0; I < Count; I++) {
473 wasm::WasmInitFunc Init;
474 Init.Priority = readVaruint32(Ctx);
475 Init.Symbol = readVaruint32(Ctx);
476 if (!isValidFunctionSymbol(Init.Symbol))
477 return make_error<GenericBinaryError>("invalid function symbol: " +
478 Twine(Init.Symbol),
479 object_error::parse_failed);
480 LinkingData.InitFunctions.emplace_back(Init);
482 break;
484 case wasm::WASM_COMDAT_INFO:
485 if (Error Err = parseLinkingSectionComdat(Ctx))
486 return Err;
487 break;
488 default:
489 Ctx.Ptr += Size;
490 break;
492 if (Ctx.Ptr != Ctx.End)
493 return make_error<GenericBinaryError>(
494 "linking sub-section ended prematurely", object_error::parse_failed);
496 if (Ctx.Ptr != OrigEnd)
497 return make_error<GenericBinaryError>("linking section ended prematurely",
498 object_error::parse_failed);
499 return Error::success();
502 Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
503 uint32_t Count = readVaruint32(Ctx);
504 LinkingData.SymbolTable.reserve(Count);
505 Symbols.reserve(Count);
506 StringSet<> SymbolNames;
508 std::vector<wasm::WasmImport *> ImportedGlobals;
509 std::vector<wasm::WasmImport *> ImportedFunctions;
510 std::vector<wasm::WasmImport *> ImportedTags;
511 std::vector<wasm::WasmImport *> ImportedTables;
512 ImportedGlobals.reserve(Imports.size());
513 ImportedFunctions.reserve(Imports.size());
514 ImportedTags.reserve(Imports.size());
515 ImportedTables.reserve(Imports.size());
516 for (auto &I : Imports) {
517 if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
518 ImportedFunctions.emplace_back(&I);
519 else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
520 ImportedGlobals.emplace_back(&I);
521 else if (I.Kind == wasm::WASM_EXTERNAL_TAG)
522 ImportedTags.emplace_back(&I);
523 else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
524 ImportedTables.emplace_back(&I);
527 while (Count--) {
528 wasm::WasmSymbolInfo Info;
529 const wasm::WasmSignature *Signature = nullptr;
530 const wasm::WasmGlobalType *GlobalType = nullptr;
531 const wasm::WasmTableType *TableType = nullptr;
532 const wasm::WasmTagType *TagType = nullptr;
534 Info.Kind = readUint8(Ctx);
535 Info.Flags = readVaruint32(Ctx);
536 bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
538 switch (Info.Kind) {
539 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
540 Info.ElementIndex = readVaruint32(Ctx);
541 if (!isValidFunctionIndex(Info.ElementIndex) ||
542 IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
543 return make_error<GenericBinaryError>("invalid function symbol index",
544 object_error::parse_failed);
545 if (IsDefined) {
546 Info.Name = readString(Ctx);
547 unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
548 Signature = &Signatures[FunctionTypes[FuncIndex]];
549 wasm::WasmFunction &Function = Functions[FuncIndex];
550 if (Function.SymbolName.empty())
551 Function.SymbolName = Info.Name;
552 } else {
553 wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
554 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
555 Info.Name = readString(Ctx);
556 Info.ImportName = Import.Field;
557 } else {
558 Info.Name = Import.Field;
560 Signature = &Signatures[Import.SigIndex];
561 if (!Import.Module.empty()) {
562 Info.ImportModule = Import.Module;
565 break;
567 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
568 Info.ElementIndex = readVaruint32(Ctx);
569 if (!isValidGlobalIndex(Info.ElementIndex) ||
570 IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
571 return make_error<GenericBinaryError>("invalid global symbol index",
572 object_error::parse_failed);
573 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
574 wasm::WASM_SYMBOL_BINDING_WEAK)
575 return make_error<GenericBinaryError>("undefined weak global symbol",
576 object_error::parse_failed);
577 if (IsDefined) {
578 Info.Name = readString(Ctx);
579 unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
580 wasm::WasmGlobal &Global = Globals[GlobalIndex];
581 GlobalType = &Global.Type;
582 if (Global.SymbolName.empty())
583 Global.SymbolName = Info.Name;
584 } else {
585 wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
586 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
587 Info.Name = readString(Ctx);
588 Info.ImportName = Import.Field;
589 } else {
590 Info.Name = Import.Field;
592 GlobalType = &Import.Global;
593 if (!Import.Module.empty()) {
594 Info.ImportModule = Import.Module;
597 break;
599 case wasm::WASM_SYMBOL_TYPE_TABLE:
600 Info.ElementIndex = readVaruint32(Ctx);
601 if (!isValidTableNumber(Info.ElementIndex) ||
602 IsDefined != isDefinedTableNumber(Info.ElementIndex))
603 return make_error<GenericBinaryError>("invalid table symbol index",
604 object_error::parse_failed);
605 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
606 wasm::WASM_SYMBOL_BINDING_WEAK)
607 return make_error<GenericBinaryError>("undefined weak table symbol",
608 object_error::parse_failed);
609 if (IsDefined) {
610 Info.Name = readString(Ctx);
611 unsigned TableNumber = Info.ElementIndex - NumImportedTables;
612 wasm::WasmTable &Table = Tables[TableNumber];
613 TableType = &Table.Type;
614 if (Table.SymbolName.empty())
615 Table.SymbolName = Info.Name;
616 } else {
617 wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
618 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
619 Info.Name = readString(Ctx);
620 Info.ImportName = Import.Field;
621 } else {
622 Info.Name = Import.Field;
624 TableType = &Import.Table;
625 if (!Import.Module.empty()) {
626 Info.ImportModule = Import.Module;
629 break;
631 case wasm::WASM_SYMBOL_TYPE_DATA:
632 Info.Name = readString(Ctx);
633 if (IsDefined) {
634 auto Index = readVaruint32(Ctx);
635 if (Index >= DataSegments.size())
636 return make_error<GenericBinaryError>("invalid data symbol index",
637 object_error::parse_failed);
638 auto Offset = readVaruint64(Ctx);
639 auto Size = readVaruint64(Ctx);
640 size_t SegmentSize = DataSegments[Index].Data.Content.size();
641 if (Offset > SegmentSize)
642 return make_error<GenericBinaryError>(
643 "invalid data symbol offset: `" + Info.Name + "` (offset: " +
644 Twine(Offset) + " segment size: " + Twine(SegmentSize) + ")",
645 object_error::parse_failed);
646 Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
648 break;
650 case wasm::WASM_SYMBOL_TYPE_SECTION: {
651 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
652 wasm::WASM_SYMBOL_BINDING_LOCAL)
653 return make_error<GenericBinaryError>(
654 "section symbols must have local binding",
655 object_error::parse_failed);
656 Info.ElementIndex = readVaruint32(Ctx);
657 // Use somewhat unique section name as symbol name.
658 StringRef SectionName = Sections[Info.ElementIndex].Name;
659 Info.Name = SectionName;
660 break;
663 case wasm::WASM_SYMBOL_TYPE_TAG: {
664 Info.ElementIndex = readVaruint32(Ctx);
665 if (!isValidTagIndex(Info.ElementIndex) ||
666 IsDefined != isDefinedTagIndex(Info.ElementIndex))
667 return make_error<GenericBinaryError>("invalid tag symbol index",
668 object_error::parse_failed);
669 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
670 wasm::WASM_SYMBOL_BINDING_WEAK)
671 return make_error<GenericBinaryError>("undefined weak global symbol",
672 object_error::parse_failed);
673 if (IsDefined) {
674 Info.Name = readString(Ctx);
675 unsigned TagIndex = Info.ElementIndex - NumImportedTags;
676 wasm::WasmTag &Tag = Tags[TagIndex];
677 Signature = &Signatures[Tag.Type.SigIndex];
678 TagType = &Tag.Type;
679 if (Tag.SymbolName.empty())
680 Tag.SymbolName = Info.Name;
682 } else {
683 wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex];
684 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
685 Info.Name = readString(Ctx);
686 Info.ImportName = Import.Field;
687 } else {
688 Info.Name = Import.Field;
690 TagType = &Import.Tag;
691 Signature = &Signatures[TagType->SigIndex];
692 if (!Import.Module.empty()) {
693 Info.ImportModule = Import.Module;
696 break;
699 default:
700 return make_error<GenericBinaryError>("invalid symbol type: " +
701 Twine(unsigned(Info.Kind)),
702 object_error::parse_failed);
705 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
706 wasm::WASM_SYMBOL_BINDING_LOCAL &&
707 !SymbolNames.insert(Info.Name).second)
708 return make_error<GenericBinaryError>("duplicate symbol name " +
709 Twine(Info.Name),
710 object_error::parse_failed);
711 LinkingData.SymbolTable.emplace_back(Info);
712 Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType,
713 TagType, Signature);
714 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
717 return Error::success();
720 Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
721 uint32_t ComdatCount = readVaruint32(Ctx);
722 StringSet<> ComdatSet;
723 for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
724 StringRef Name = readString(Ctx);
725 if (Name.empty() || !ComdatSet.insert(Name).second)
726 return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
727 Twine(Name),
728 object_error::parse_failed);
729 LinkingData.Comdats.emplace_back(Name);
730 uint32_t Flags = readVaruint32(Ctx);
731 if (Flags != 0)
732 return make_error<GenericBinaryError>("unsupported COMDAT flags",
733 object_error::parse_failed);
735 uint32_t EntryCount = readVaruint32(Ctx);
736 while (EntryCount--) {
737 unsigned Kind = readVaruint32(Ctx);
738 unsigned Index = readVaruint32(Ctx);
739 switch (Kind) {
740 default:
741 return make_error<GenericBinaryError>("invalid COMDAT entry type",
742 object_error::parse_failed);
743 case wasm::WASM_COMDAT_DATA:
744 if (Index >= DataSegments.size())
745 return make_error<GenericBinaryError>(
746 "COMDAT data index out of range", object_error::parse_failed);
747 if (DataSegments[Index].Data.Comdat != UINT32_MAX)
748 return make_error<GenericBinaryError>("data segment in two COMDATs",
749 object_error::parse_failed);
750 DataSegments[Index].Data.Comdat = ComdatIndex;
751 break;
752 case wasm::WASM_COMDAT_FUNCTION:
753 if (!isDefinedFunctionIndex(Index))
754 return make_error<GenericBinaryError>(
755 "COMDAT function index out of range", object_error::parse_failed);
756 if (getDefinedFunction(Index).Comdat != UINT32_MAX)
757 return make_error<GenericBinaryError>("function in two COMDATs",
758 object_error::parse_failed);
759 getDefinedFunction(Index).Comdat = ComdatIndex;
760 break;
761 case wasm::WASM_COMDAT_SECTION:
762 if (Index >= Sections.size())
763 return make_error<GenericBinaryError>(
764 "COMDAT section index out of range", object_error::parse_failed);
765 if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
766 return make_error<GenericBinaryError>(
767 "non-custom section in a COMDAT", object_error::parse_failed);
768 Sections[Index].Comdat = ComdatIndex;
769 break;
773 return Error::success();
776 Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
777 llvm::SmallSet<StringRef, 3> FieldsSeen;
778 uint32_t Fields = readVaruint32(Ctx);
779 for (size_t I = 0; I < Fields; ++I) {
780 StringRef FieldName = readString(Ctx);
781 if (!FieldsSeen.insert(FieldName).second)
782 return make_error<GenericBinaryError>(
783 "producers section does not have unique fields",
784 object_error::parse_failed);
785 std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
786 if (FieldName == "language") {
787 ProducerVec = &ProducerInfo.Languages;
788 } else if (FieldName == "processed-by") {
789 ProducerVec = &ProducerInfo.Tools;
790 } else if (FieldName == "sdk") {
791 ProducerVec = &ProducerInfo.SDKs;
792 } else {
793 return make_error<GenericBinaryError>(
794 "producers section field is not named one of language, processed-by, "
795 "or sdk",
796 object_error::parse_failed);
798 uint32_t ValueCount = readVaruint32(Ctx);
799 llvm::SmallSet<StringRef, 8> ProducersSeen;
800 for (size_t J = 0; J < ValueCount; ++J) {
801 StringRef Name = readString(Ctx);
802 StringRef Version = readString(Ctx);
803 if (!ProducersSeen.insert(Name).second) {
804 return make_error<GenericBinaryError>(
805 "producers section contains repeated producer",
806 object_error::parse_failed);
808 ProducerVec->emplace_back(std::string(Name), std::string(Version));
811 if (Ctx.Ptr != Ctx.End)
812 return make_error<GenericBinaryError>("producers section ended prematurely",
813 object_error::parse_failed);
814 return Error::success();
817 Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
818 llvm::SmallSet<std::string, 8> FeaturesSeen;
819 uint32_t FeatureCount = readVaruint32(Ctx);
820 for (size_t I = 0; I < FeatureCount; ++I) {
821 wasm::WasmFeatureEntry Feature;
822 Feature.Prefix = readUint8(Ctx);
823 switch (Feature.Prefix) {
824 case wasm::WASM_FEATURE_PREFIX_USED:
825 case wasm::WASM_FEATURE_PREFIX_REQUIRED:
826 case wasm::WASM_FEATURE_PREFIX_DISALLOWED:
827 break;
828 default:
829 return make_error<GenericBinaryError>("unknown feature policy prefix",
830 object_error::parse_failed);
832 Feature.Name = std::string(readString(Ctx));
833 if (!FeaturesSeen.insert(Feature.Name).second)
834 return make_error<GenericBinaryError>(
835 "target features section contains repeated feature \"" +
836 Feature.Name + "\"",
837 object_error::parse_failed);
838 TargetFeatures.push_back(Feature);
840 if (Ctx.Ptr != Ctx.End)
841 return make_error<GenericBinaryError>(
842 "target features section ended prematurely",
843 object_error::parse_failed);
844 return Error::success();
847 Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
848 uint32_t SectionIndex = readVaruint32(Ctx);
849 if (SectionIndex >= Sections.size())
850 return make_error<GenericBinaryError>("invalid section index",
851 object_error::parse_failed);
852 WasmSection &Section = Sections[SectionIndex];
853 uint32_t RelocCount = readVaruint32(Ctx);
854 uint32_t EndOffset = Section.Content.size();
855 uint32_t PreviousOffset = 0;
856 while (RelocCount--) {
857 wasm::WasmRelocation Reloc = {};
858 uint32_t type = readVaruint32(Ctx);
859 Reloc.Type = type;
860 Reloc.Offset = readVaruint32(Ctx);
861 if (Reloc.Offset < PreviousOffset)
862 return make_error<GenericBinaryError>("relocations not in offset order",
863 object_error::parse_failed);
864 PreviousOffset = Reloc.Offset;
865 Reloc.Index = readVaruint32(Ctx);
866 switch (type) {
867 case wasm::R_WASM_FUNCTION_INDEX_LEB:
868 case wasm::R_WASM_TABLE_INDEX_SLEB:
869 case wasm::R_WASM_TABLE_INDEX_SLEB64:
870 case wasm::R_WASM_TABLE_INDEX_I32:
871 case wasm::R_WASM_TABLE_INDEX_I64:
872 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
873 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
874 if (!isValidFunctionSymbol(Reloc.Index))
875 return make_error<GenericBinaryError>(
876 "invalid relocation function index", object_error::parse_failed);
877 break;
878 case wasm::R_WASM_TABLE_NUMBER_LEB:
879 if (!isValidTableSymbol(Reloc.Index))
880 return make_error<GenericBinaryError>("invalid relocation table index",
881 object_error::parse_failed);
882 break;
883 case wasm::R_WASM_TYPE_INDEX_LEB:
884 if (Reloc.Index >= Signatures.size())
885 return make_error<GenericBinaryError>("invalid relocation type index",
886 object_error::parse_failed);
887 break;
888 case wasm::R_WASM_GLOBAL_INDEX_LEB:
889 // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
890 // symbols to refer to their GOT entries.
891 if (!isValidGlobalSymbol(Reloc.Index) &&
892 !isValidDataSymbol(Reloc.Index) &&
893 !isValidFunctionSymbol(Reloc.Index))
894 return make_error<GenericBinaryError>("invalid relocation global index",
895 object_error::parse_failed);
896 break;
897 case wasm::R_WASM_GLOBAL_INDEX_I32:
898 if (!isValidGlobalSymbol(Reloc.Index))
899 return make_error<GenericBinaryError>("invalid relocation global index",
900 object_error::parse_failed);
901 break;
902 case wasm::R_WASM_TAG_INDEX_LEB:
903 if (!isValidTagSymbol(Reloc.Index))
904 return make_error<GenericBinaryError>("invalid relocation tag index",
905 object_error::parse_failed);
906 break;
907 case wasm::R_WASM_MEMORY_ADDR_LEB:
908 case wasm::R_WASM_MEMORY_ADDR_SLEB:
909 case wasm::R_WASM_MEMORY_ADDR_I32:
910 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
911 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
912 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
913 if (!isValidDataSymbol(Reloc.Index))
914 return make_error<GenericBinaryError>("invalid relocation data index",
915 object_error::parse_failed);
916 Reloc.Addend = readVarint32(Ctx);
917 break;
918 case wasm::R_WASM_MEMORY_ADDR_LEB64:
919 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
920 case wasm::R_WASM_MEMORY_ADDR_I64:
921 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
922 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
923 if (!isValidDataSymbol(Reloc.Index))
924 return make_error<GenericBinaryError>("invalid relocation data index",
925 object_error::parse_failed);
926 Reloc.Addend = readVarint64(Ctx);
927 break;
928 case wasm::R_WASM_FUNCTION_OFFSET_I32:
929 if (!isValidFunctionSymbol(Reloc.Index))
930 return make_error<GenericBinaryError>(
931 "invalid relocation function index", object_error::parse_failed);
932 Reloc.Addend = readVarint32(Ctx);
933 break;
934 case wasm::R_WASM_FUNCTION_OFFSET_I64:
935 if (!isValidFunctionSymbol(Reloc.Index))
936 return make_error<GenericBinaryError>(
937 "invalid relocation function index", object_error::parse_failed);
938 Reloc.Addend = readVarint64(Ctx);
939 break;
940 case wasm::R_WASM_SECTION_OFFSET_I32:
941 if (!isValidSectionSymbol(Reloc.Index))
942 return make_error<GenericBinaryError>(
943 "invalid relocation section index", object_error::parse_failed);
944 Reloc.Addend = readVarint32(Ctx);
945 break;
946 default:
947 return make_error<GenericBinaryError>("invalid relocation type: " +
948 Twine(type),
949 object_error::parse_failed);
952 // Relocations must fit inside the section, and must appear in order. They
953 // also shouldn't overlap a function/element boundary, but we don't bother
954 // to check that.
955 uint64_t Size = 5;
956 if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
957 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
958 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
959 Size = 10;
960 if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
961 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
962 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
963 Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
964 Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
965 Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
966 Size = 4;
967 if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
968 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
969 Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
970 Size = 8;
971 if (Reloc.Offset + Size > EndOffset)
972 return make_error<GenericBinaryError>("invalid relocation offset",
973 object_error::parse_failed);
975 Section.Relocations.push_back(Reloc);
977 if (Ctx.Ptr != Ctx.End)
978 return make_error<GenericBinaryError>("reloc section ended prematurely",
979 object_error::parse_failed);
980 return Error::success();
983 Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
984 if (Sec.Name == "dylink") {
985 if (Error Err = parseDylinkSection(Ctx))
986 return Err;
987 } else if (Sec.Name == "name") {
988 if (Error Err = parseNameSection(Ctx))
989 return Err;
990 } else if (Sec.Name == "linking") {
991 if (Error Err = parseLinkingSection(Ctx))
992 return Err;
993 } else if (Sec.Name == "producers") {
994 if (Error Err = parseProducersSection(Ctx))
995 return Err;
996 } else if (Sec.Name == "target_features") {
997 if (Error Err = parseTargetFeaturesSection(Ctx))
998 return Err;
999 } else if (Sec.Name.startswith("reloc.")) {
1000 if (Error Err = parseRelocSection(Sec.Name, Ctx))
1001 return Err;
1003 return Error::success();
1006 Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1007 uint32_t Count = readVaruint32(Ctx);
1008 Signatures.reserve(Count);
1009 while (Count--) {
1010 wasm::WasmSignature Sig;
1011 uint8_t Form = readUint8(Ctx);
1012 if (Form != wasm::WASM_TYPE_FUNC) {
1013 return make_error<GenericBinaryError>("invalid signature type",
1014 object_error::parse_failed);
1016 uint32_t ParamCount = readVaruint32(Ctx);
1017 Sig.Params.reserve(ParamCount);
1018 while (ParamCount--) {
1019 uint32_t ParamType = readUint8(Ctx);
1020 Sig.Params.push_back(wasm::ValType(ParamType));
1022 uint32_t ReturnCount = readVaruint32(Ctx);
1023 while (ReturnCount--) {
1024 uint32_t ReturnType = readUint8(Ctx);
1025 Sig.Returns.push_back(wasm::ValType(ReturnType));
1027 Signatures.push_back(std::move(Sig));
1029 if (Ctx.Ptr != Ctx.End)
1030 return make_error<GenericBinaryError>("type section ended prematurely",
1031 object_error::parse_failed);
1032 return Error::success();
1035 Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1036 uint32_t Count = readVaruint32(Ctx);
1037 Imports.reserve(Count);
1038 for (uint32_t I = 0; I < Count; I++) {
1039 wasm::WasmImport Im;
1040 Im.Module = readString(Ctx);
1041 Im.Field = readString(Ctx);
1042 Im.Kind = readUint8(Ctx);
1043 switch (Im.Kind) {
1044 case wasm::WASM_EXTERNAL_FUNCTION:
1045 NumImportedFunctions++;
1046 Im.SigIndex = readVaruint32(Ctx);
1047 break;
1048 case wasm::WASM_EXTERNAL_GLOBAL:
1049 NumImportedGlobals++;
1050 Im.Global.Type = readUint8(Ctx);
1051 Im.Global.Mutable = readVaruint1(Ctx);
1052 break;
1053 case wasm::WASM_EXTERNAL_MEMORY:
1054 Im.Memory = readLimits(Ctx);
1055 if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1056 HasMemory64 = true;
1057 break;
1058 case wasm::WASM_EXTERNAL_TABLE: {
1059 Im.Table = readTableType(Ctx);
1060 NumImportedTables++;
1061 auto ElemType = Im.Table.ElemType;
1062 if (ElemType != wasm::WASM_TYPE_FUNCREF &&
1063 ElemType != wasm::WASM_TYPE_EXTERNREF)
1064 return make_error<GenericBinaryError>("invalid table element type",
1065 object_error::parse_failed);
1066 break;
1068 case wasm::WASM_EXTERNAL_TAG:
1069 NumImportedTags++;
1070 Im.Tag.Attribute = readUint8(Ctx);
1071 Im.Tag.SigIndex = readVarint32(Ctx);
1072 break;
1073 default:
1074 return make_error<GenericBinaryError>("unexpected import kind",
1075 object_error::parse_failed);
1077 Imports.push_back(Im);
1079 if (Ctx.Ptr != Ctx.End)
1080 return make_error<GenericBinaryError>("import section ended prematurely",
1081 object_error::parse_failed);
1082 return Error::success();
1085 Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1086 uint32_t Count = readVaruint32(Ctx);
1087 FunctionTypes.reserve(Count);
1088 Functions.resize(Count);
1089 uint32_t NumTypes = Signatures.size();
1090 while (Count--) {
1091 uint32_t Type = readVaruint32(Ctx);
1092 if (Type >= NumTypes)
1093 return make_error<GenericBinaryError>("invalid function type",
1094 object_error::parse_failed);
1095 FunctionTypes.push_back(Type);
1097 if (Ctx.Ptr != Ctx.End)
1098 return make_error<GenericBinaryError>("function section ended prematurely",
1099 object_error::parse_failed);
1100 return Error::success();
1103 Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1104 TableSection = Sections.size();
1105 uint32_t Count = readVaruint32(Ctx);
1106 Tables.reserve(Count);
1107 while (Count--) {
1108 wasm::WasmTable T;
1109 T.Type = readTableType(Ctx);
1110 T.Index = NumImportedTables + Tables.size();
1111 Tables.push_back(T);
1112 auto ElemType = Tables.back().Type.ElemType;
1113 if (ElemType != wasm::WASM_TYPE_FUNCREF &&
1114 ElemType != wasm::WASM_TYPE_EXTERNREF) {
1115 return make_error<GenericBinaryError>("invalid table element type",
1116 object_error::parse_failed);
1119 if (Ctx.Ptr != Ctx.End)
1120 return make_error<GenericBinaryError>("table section ended prematurely",
1121 object_error::parse_failed);
1122 return Error::success();
1125 Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1126 uint32_t Count = readVaruint32(Ctx);
1127 Memories.reserve(Count);
1128 while (Count--) {
1129 auto Limits = readLimits(Ctx);
1130 if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1131 HasMemory64 = true;
1132 Memories.push_back(Limits);
1134 if (Ctx.Ptr != Ctx.End)
1135 return make_error<GenericBinaryError>("memory section ended prematurely",
1136 object_error::parse_failed);
1137 return Error::success();
1140 Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1141 TagSection = Sections.size();
1142 uint32_t Count = readVaruint32(Ctx);
1143 Tags.reserve(Count);
1144 while (Count--) {
1145 wasm::WasmTag Tag;
1146 Tag.Index = NumImportedTags + Tags.size();
1147 Tag.Type.Attribute = readUint8(Ctx);
1148 Tag.Type.SigIndex = readVaruint32(Ctx);
1149 Tags.push_back(Tag);
1152 if (Ctx.Ptr != Ctx.End)
1153 return make_error<GenericBinaryError>("tag section ended prematurely",
1154 object_error::parse_failed);
1155 return Error::success();
1158 Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1159 GlobalSection = Sections.size();
1160 uint32_t Count = readVaruint32(Ctx);
1161 Globals.reserve(Count);
1162 while (Count--) {
1163 wasm::WasmGlobal Global;
1164 Global.Index = NumImportedGlobals + Globals.size();
1165 Global.Type.Type = readUint8(Ctx);
1166 Global.Type.Mutable = readVaruint1(Ctx);
1167 if (Error Err = readInitExpr(Global.InitExpr, Ctx))
1168 return Err;
1169 Globals.push_back(Global);
1171 if (Ctx.Ptr != Ctx.End)
1172 return make_error<GenericBinaryError>("global section ended prematurely",
1173 object_error::parse_failed);
1174 return Error::success();
1177 Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1178 uint32_t Count = readVaruint32(Ctx);
1179 Exports.reserve(Count);
1180 for (uint32_t I = 0; I < Count; I++) {
1181 wasm::WasmExport Ex;
1182 Ex.Name = readString(Ctx);
1183 Ex.Kind = readUint8(Ctx);
1184 Ex.Index = readVaruint32(Ctx);
1185 switch (Ex.Kind) {
1186 case wasm::WASM_EXTERNAL_FUNCTION:
1188 if (!isDefinedFunctionIndex(Ex.Index))
1189 return make_error<GenericBinaryError>("invalid function export",
1190 object_error::parse_failed);
1191 getDefinedFunction(Ex.Index).ExportName = Ex.Name;
1192 break;
1193 case wasm::WASM_EXTERNAL_GLOBAL:
1194 if (!isValidGlobalIndex(Ex.Index))
1195 return make_error<GenericBinaryError>("invalid global export",
1196 object_error::parse_failed);
1197 break;
1198 case wasm::WASM_EXTERNAL_TAG:
1199 if (!isValidTagIndex(Ex.Index))
1200 return make_error<GenericBinaryError>("invalid tag export",
1201 object_error::parse_failed);
1202 break;
1203 case wasm::WASM_EXTERNAL_MEMORY:
1204 case wasm::WASM_EXTERNAL_TABLE:
1205 break;
1206 default:
1207 return make_error<GenericBinaryError>("unexpected export kind",
1208 object_error::parse_failed);
1210 Exports.push_back(Ex);
1212 if (Ctx.Ptr != Ctx.End)
1213 return make_error<GenericBinaryError>("export section ended prematurely",
1214 object_error::parse_failed);
1215 return Error::success();
1218 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1219 return Index < NumImportedFunctions + FunctionTypes.size();
1222 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
1223 return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1226 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
1227 return Index < NumImportedGlobals + Globals.size();
1230 bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
1231 return Index < NumImportedTables + Tables.size();
1234 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
1235 return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1238 bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
1239 return Index >= NumImportedTables && isValidTableNumber(Index);
1242 bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
1243 return Index < NumImportedTags + Tags.size();
1246 bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
1247 return Index >= NumImportedTags && isValidTagIndex(Index);
1250 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1251 return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1254 bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
1255 return Index < Symbols.size() && Symbols[Index].isTypeTable();
1258 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1259 return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1262 bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
1263 return Index < Symbols.size() && Symbols[Index].isTypeTag();
1266 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1267 return Index < Symbols.size() && Symbols[Index].isTypeData();
1270 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1271 return Index < Symbols.size() && Symbols[Index].isTypeSection();
1274 wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1275 assert(isDefinedFunctionIndex(Index));
1276 return Functions[Index - NumImportedFunctions];
1279 const wasm::WasmFunction &
1280 WasmObjectFile::getDefinedFunction(uint32_t Index) const {
1281 assert(isDefinedFunctionIndex(Index));
1282 return Functions[Index - NumImportedFunctions];
1285 wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
1286 assert(isDefinedGlobalIndex(Index));
1287 return Globals[Index - NumImportedGlobals];
1290 wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1291 assert(isDefinedTagIndex(Index));
1292 return Tags[Index - NumImportedTags];
1295 Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1296 StartFunction = readVaruint32(Ctx);
1297 if (!isValidFunctionIndex(StartFunction))
1298 return make_error<GenericBinaryError>("invalid start function",
1299 object_error::parse_failed);
1300 return Error::success();
1303 Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1304 SeenCodeSection = true;
1305 CodeSection = Sections.size();
1306 uint32_t FunctionCount = readVaruint32(Ctx);
1307 if (FunctionCount != FunctionTypes.size()) {
1308 return make_error<GenericBinaryError>("invalid function count",
1309 object_error::parse_failed);
1312 for (uint32_t i = 0; i < FunctionCount; i++) {
1313 wasm::WasmFunction& Function = Functions[i];
1314 const uint8_t *FunctionStart = Ctx.Ptr;
1315 uint32_t Size = readVaruint32(Ctx);
1316 const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1318 Function.CodeOffset = Ctx.Ptr - FunctionStart;
1319 Function.Index = NumImportedFunctions + i;
1320 Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1321 Function.Size = FunctionEnd - FunctionStart;
1323 uint32_t NumLocalDecls = readVaruint32(Ctx);
1324 Function.Locals.reserve(NumLocalDecls);
1325 while (NumLocalDecls--) {
1326 wasm::WasmLocalDecl Decl;
1327 Decl.Count = readVaruint32(Ctx);
1328 Decl.Type = readUint8(Ctx);
1329 Function.Locals.push_back(Decl);
1332 uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1333 Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1334 // This will be set later when reading in the linking metadata section.
1335 Function.Comdat = UINT32_MAX;
1336 Ctx.Ptr += BodySize;
1337 assert(Ctx.Ptr == FunctionEnd);
1339 if (Ctx.Ptr != Ctx.End)
1340 return make_error<GenericBinaryError>("code section ended prematurely",
1341 object_error::parse_failed);
1342 return Error::success();
1345 Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1346 uint32_t Count = readVaruint32(Ctx);
1347 ElemSegments.reserve(Count);
1348 while (Count--) {
1349 wasm::WasmElemSegment Segment;
1350 Segment.Flags = readVaruint32(Ctx);
1352 uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER |
1353 wasm::WASM_ELEM_SEGMENT_IS_PASSIVE |
1354 wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS;
1355 if (Segment.Flags & ~SupportedFlags)
1356 return make_error<GenericBinaryError>(
1357 "Unsupported flags for element segment", object_error::parse_failed);
1359 if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
1360 Segment.TableNumber = readVaruint32(Ctx);
1361 else
1362 Segment.TableNumber = 0;
1363 if (!isValidTableNumber(Segment.TableNumber))
1364 return make_error<GenericBinaryError>("invalid TableNumber",
1365 object_error::parse_failed);
1367 if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) {
1368 Segment.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST;
1369 Segment.Offset.Value.Int32 = 0;
1370 } else {
1371 if (Error Err = readInitExpr(Segment.Offset, Ctx))
1372 return Err;
1375 if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
1376 Segment.ElemKind = readUint8(Ctx);
1377 if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {
1378 if (Segment.ElemKind != uint8_t(wasm::ValType::FUNCREF) &&
1379 Segment.ElemKind != uint8_t(wasm::ValType::EXTERNREF)) {
1380 return make_error<GenericBinaryError>("invalid reference type",
1381 object_error::parse_failed);
1383 } else {
1384 if (Segment.ElemKind != 0)
1385 return make_error<GenericBinaryError>("invalid elemtype",
1386 object_error::parse_failed);
1387 Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1389 } else {
1390 Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1393 if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS)
1394 return make_error<GenericBinaryError>(
1395 "elem segment init expressions not yet implemented",
1396 object_error::parse_failed);
1398 uint32_t NumElems = readVaruint32(Ctx);
1399 while (NumElems--) {
1400 Segment.Functions.push_back(readVaruint32(Ctx));
1402 ElemSegments.push_back(Segment);
1404 if (Ctx.Ptr != Ctx.End)
1405 return make_error<GenericBinaryError>("elem section ended prematurely",
1406 object_error::parse_failed);
1407 return Error::success();
1410 Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1411 DataSection = Sections.size();
1412 uint32_t Count = readVaruint32(Ctx);
1413 if (DataCount && Count != DataCount.getValue())
1414 return make_error<GenericBinaryError>(
1415 "number of data segments does not match DataCount section");
1416 DataSegments.reserve(Count);
1417 while (Count--) {
1418 WasmSegment Segment;
1419 Segment.Data.InitFlags = readVaruint32(Ctx);
1420 Segment.Data.MemoryIndex =
1421 (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
1422 ? readVaruint32(Ctx)
1423 : 0;
1424 if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1425 if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1426 return Err;
1427 } else {
1428 Segment.Data.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST;
1429 Segment.Data.Offset.Value.Int32 = 0;
1431 uint32_t Size = readVaruint32(Ctx);
1432 if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1433 return make_error<GenericBinaryError>("invalid segment size",
1434 object_error::parse_failed);
1435 Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1436 // The rest of these Data fields are set later, when reading in the linking
1437 // metadata section.
1438 Segment.Data.Alignment = 0;
1439 Segment.Data.LinkingFlags = 0;
1440 Segment.Data.Comdat = UINT32_MAX;
1441 Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1442 Ctx.Ptr += Size;
1443 DataSegments.push_back(Segment);
1445 if (Ctx.Ptr != Ctx.End)
1446 return make_error<GenericBinaryError>("data section ended prematurely",
1447 object_error::parse_failed);
1448 return Error::success();
1451 Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1452 DataCount = readVaruint32(Ctx);
1453 return Error::success();
1456 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1457 return Header;
1460 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
1462 Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
1463 uint32_t Result = SymbolRef::SF_None;
1464 const WasmSymbol &Sym = getWasmSymbol(Symb);
1466 LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1467 if (Sym.isBindingWeak())
1468 Result |= SymbolRef::SF_Weak;
1469 if (!Sym.isBindingLocal())
1470 Result |= SymbolRef::SF_Global;
1471 if (Sym.isHidden())
1472 Result |= SymbolRef::SF_Hidden;
1473 if (!Sym.isDefined())
1474 Result |= SymbolRef::SF_Undefined;
1475 if (Sym.isTypeFunction())
1476 Result |= SymbolRef::SF_Executable;
1477 return Result;
1480 basic_symbol_iterator WasmObjectFile::symbol_begin() const {
1481 DataRefImpl Ref;
1482 Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1483 Ref.d.b = 0; // Symbol index
1484 return BasicSymbolRef(Ref, this);
1487 basic_symbol_iterator WasmObjectFile::symbol_end() const {
1488 DataRefImpl Ref;
1489 Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1490 Ref.d.b = Symbols.size(); // Symbol index
1491 return BasicSymbolRef(Ref, this);
1494 const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
1495 return Symbols[Symb.d.b];
1498 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1499 return getWasmSymbol(Symb.getRawDataRefImpl());
1502 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
1503 return getWasmSymbol(Symb).Info.Name;
1506 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
1507 auto &Sym = getWasmSymbol(Symb);
1508 if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1509 isDefinedFunctionIndex(Sym.Info.ElementIndex))
1510 return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset;
1511 else
1512 return getSymbolValue(Symb);
1515 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
1516 switch (Sym.Info.Kind) {
1517 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1518 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1519 case wasm::WASM_SYMBOL_TYPE_TAG:
1520 case wasm::WASM_SYMBOL_TYPE_TABLE:
1521 return Sym.Info.ElementIndex;
1522 case wasm::WASM_SYMBOL_TYPE_DATA: {
1523 // The value of a data symbol is the segment offset, plus the symbol
1524 // offset within the segment.
1525 uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1526 const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1527 if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1528 return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
1529 } else if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1530 return Segment.Offset.Value.Int64 + Sym.Info.DataRef.Offset;
1531 } else {
1532 llvm_unreachable("unknown init expr opcode");
1535 case wasm::WASM_SYMBOL_TYPE_SECTION:
1536 return 0;
1538 llvm_unreachable("invalid symbol type");
1541 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1542 return getWasmSymbolValue(getWasmSymbol(Symb));
1545 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1546 llvm_unreachable("not yet implemented");
1547 return 0;
1550 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1551 llvm_unreachable("not yet implemented");
1552 return 0;
1555 Expected<SymbolRef::Type>
1556 WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
1557 const WasmSymbol &Sym = getWasmSymbol(Symb);
1559 switch (Sym.Info.Kind) {
1560 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1561 return SymbolRef::ST_Function;
1562 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1563 return SymbolRef::ST_Other;
1564 case wasm::WASM_SYMBOL_TYPE_DATA:
1565 return SymbolRef::ST_Data;
1566 case wasm::WASM_SYMBOL_TYPE_SECTION:
1567 return SymbolRef::ST_Debug;
1568 case wasm::WASM_SYMBOL_TYPE_TAG:
1569 return SymbolRef::ST_Other;
1570 case wasm::WASM_SYMBOL_TYPE_TABLE:
1571 return SymbolRef::ST_Other;
1574 llvm_unreachable("unknown WasmSymbol::SymbolType");
1575 return SymbolRef::ST_Other;
1578 Expected<section_iterator>
1579 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1580 const WasmSymbol &Sym = getWasmSymbol(Symb);
1581 if (Sym.isUndefined())
1582 return section_end();
1584 DataRefImpl Ref;
1585 Ref.d.a = getSymbolSectionIdImpl(Sym);
1586 return section_iterator(SectionRef(Ref, this));
1589 uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const {
1590 const WasmSymbol &Sym = getWasmSymbol(Symb);
1591 return getSymbolSectionIdImpl(Sym);
1594 uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
1595 switch (Sym.Info.Kind) {
1596 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1597 return CodeSection;
1598 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1599 return GlobalSection;
1600 case wasm::WASM_SYMBOL_TYPE_DATA:
1601 return DataSection;
1602 case wasm::WASM_SYMBOL_TYPE_SECTION:
1603 return Sym.Info.ElementIndex;
1604 case wasm::WASM_SYMBOL_TYPE_TAG:
1605 return TagSection;
1606 case wasm::WASM_SYMBOL_TYPE_TABLE:
1607 return TableSection;
1608 default:
1609 llvm_unreachable("unknown WasmSymbol::SymbolType");
1613 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1615 Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
1616 const WasmSection &S = Sections[Sec.d.a];
1617 #define ECase(X) \
1618 case wasm::WASM_SEC_##X: \
1619 return #X;
1620 switch (S.Type) {
1621 ECase(TYPE);
1622 ECase(IMPORT);
1623 ECase(FUNCTION);
1624 ECase(TABLE);
1625 ECase(MEMORY);
1626 ECase(GLOBAL);
1627 ECase(TAG);
1628 ECase(EXPORT);
1629 ECase(START);
1630 ECase(ELEM);
1631 ECase(CODE);
1632 ECase(DATA);
1633 ECase(DATACOUNT);
1634 case wasm::WASM_SEC_CUSTOM:
1635 return S.Name;
1636 default:
1637 return createStringError(object_error::invalid_section_index, "");
1639 #undef ECase
1642 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1644 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1645 return Sec.d.a;
1648 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1649 const WasmSection &S = Sections[Sec.d.a];
1650 return S.Content.size();
1653 Expected<ArrayRef<uint8_t>>
1654 WasmObjectFile::getSectionContents(DataRefImpl Sec) const {
1655 const WasmSection &S = Sections[Sec.d.a];
1656 // This will never fail since wasm sections can never be empty (user-sections
1657 // must have a name and non-user sections each have a defined structure).
1658 return S.Content;
1661 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1662 return 1;
1665 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1666 return false;
1669 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
1670 return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1673 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
1674 return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1677 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1679 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1681 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1682 DataRefImpl RelocRef;
1683 RelocRef.d.a = Ref.d.a;
1684 RelocRef.d.b = 0;
1685 return relocation_iterator(RelocationRef(RelocRef, this));
1688 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1689 const WasmSection &Sec = getWasmSection(Ref);
1690 DataRefImpl RelocRef;
1691 RelocRef.d.a = Ref.d.a;
1692 RelocRef.d.b = Sec.Relocations.size();
1693 return relocation_iterator(RelocationRef(RelocRef, this));
1696 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
1698 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1699 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1700 return Rel.Offset;
1703 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
1704 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1705 if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
1706 return symbol_end();
1707 DataRefImpl Sym;
1708 Sym.d.a = 1;
1709 Sym.d.b = Rel.Index;
1710 return symbol_iterator(SymbolRef(Sym, this));
1713 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1714 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1715 return Rel.Type;
1718 void WasmObjectFile::getRelocationTypeName(
1719 DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1720 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1721 StringRef Res = "Unknown";
1723 #define WASM_RELOC(name, value) \
1724 case wasm::name: \
1725 Res = #name; \
1726 break;
1728 switch (Rel.Type) {
1729 #include "llvm/BinaryFormat/WasmRelocs.def"
1732 #undef WASM_RELOC
1734 Result.append(Res.begin(), Res.end());
1737 section_iterator WasmObjectFile::section_begin() const {
1738 DataRefImpl Ref;
1739 Ref.d.a = 0;
1740 return section_iterator(SectionRef(Ref, this));
1743 section_iterator WasmObjectFile::section_end() const {
1744 DataRefImpl Ref;
1745 Ref.d.a = Sections.size();
1746 return section_iterator(SectionRef(Ref, this));
1749 uint8_t WasmObjectFile::getBytesInAddress() const {
1750 return HasMemory64 ? 8 : 4;
1753 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1755 Triple::ArchType WasmObjectFile::getArch() const {
1756 return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
1759 SubtargetFeatures WasmObjectFile::getFeatures() const {
1760 return SubtargetFeatures();
1763 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1765 bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
1767 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
1768 assert(Ref.d.a < Sections.size());
1769 return Sections[Ref.d.a];
1772 const WasmSection &
1773 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
1774 return getWasmSection(Section.getRawDataRefImpl());
1777 const wasm::WasmRelocation &
1778 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1779 return getWasmRelocation(Ref.getRawDataRefImpl());
1782 const wasm::WasmRelocation &
1783 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
1784 assert(Ref.d.a < Sections.size());
1785 const WasmSection &Sec = Sections[Ref.d.a];
1786 assert(Ref.d.b < Sec.Relocations.size());
1787 return Sec.Relocations[Ref.d.b];
1790 int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1791 StringRef CustomSectionName) {
1792 switch (ID) {
1793 case wasm::WASM_SEC_CUSTOM:
1794 return StringSwitch<unsigned>(CustomSectionName)
1795 .Case("dylink", WASM_SEC_ORDER_DYLINK)
1796 .Case("linking", WASM_SEC_ORDER_LINKING)
1797 .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
1798 .Case("name", WASM_SEC_ORDER_NAME)
1799 .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1800 .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
1801 .Default(WASM_SEC_ORDER_NONE);
1802 case wasm::WASM_SEC_TYPE:
1803 return WASM_SEC_ORDER_TYPE;
1804 case wasm::WASM_SEC_IMPORT:
1805 return WASM_SEC_ORDER_IMPORT;
1806 case wasm::WASM_SEC_FUNCTION:
1807 return WASM_SEC_ORDER_FUNCTION;
1808 case wasm::WASM_SEC_TABLE:
1809 return WASM_SEC_ORDER_TABLE;
1810 case wasm::WASM_SEC_MEMORY:
1811 return WASM_SEC_ORDER_MEMORY;
1812 case wasm::WASM_SEC_GLOBAL:
1813 return WASM_SEC_ORDER_GLOBAL;
1814 case wasm::WASM_SEC_EXPORT:
1815 return WASM_SEC_ORDER_EXPORT;
1816 case wasm::WASM_SEC_START:
1817 return WASM_SEC_ORDER_START;
1818 case wasm::WASM_SEC_ELEM:
1819 return WASM_SEC_ORDER_ELEM;
1820 case wasm::WASM_SEC_CODE:
1821 return WASM_SEC_ORDER_CODE;
1822 case wasm::WASM_SEC_DATA:
1823 return WASM_SEC_ORDER_DATA;
1824 case wasm::WASM_SEC_DATACOUNT:
1825 return WASM_SEC_ORDER_DATACOUNT;
1826 case wasm::WASM_SEC_TAG:
1827 return WASM_SEC_ORDER_TAG;
1828 default:
1829 return WASM_SEC_ORDER_NONE;
1833 // Represents the edges in a directed graph where any node B reachable from node
1834 // A is not allowed to appear before A in the section ordering, but may appear
1835 // afterward.
1836 int WasmSectionOrderChecker::DisallowedPredecessors
1837 [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
1838 // WASM_SEC_ORDER_NONE
1840 // WASM_SEC_ORDER_TYPE
1841 {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
1842 // WASM_SEC_ORDER_IMPORT
1843 {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
1844 // WASM_SEC_ORDER_FUNCTION
1845 {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
1846 // WASM_SEC_ORDER_TABLE
1847 {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
1848 // WASM_SEC_ORDER_MEMORY
1849 {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
1850 // WASM_SEC_ORDER_TAG
1851 {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
1852 // WASM_SEC_ORDER_GLOBAL
1853 {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
1854 // WASM_SEC_ORDER_EXPORT
1855 {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
1856 // WASM_SEC_ORDER_START
1857 {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
1858 // WASM_SEC_ORDER_ELEM
1859 {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
1860 // WASM_SEC_ORDER_DATACOUNT
1861 {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
1862 // WASM_SEC_ORDER_CODE
1863 {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
1864 // WASM_SEC_ORDER_DATA
1865 {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
1867 // Custom Sections
1868 // WASM_SEC_ORDER_DYLINK
1869 {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
1870 // WASM_SEC_ORDER_LINKING
1871 {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
1872 // WASM_SEC_ORDER_RELOC (can be repeated)
1874 // WASM_SEC_ORDER_NAME
1875 {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
1876 // WASM_SEC_ORDER_PRODUCERS
1877 {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
1878 // WASM_SEC_ORDER_TARGET_FEATURES
1879 {WASM_SEC_ORDER_TARGET_FEATURES}};
1881 bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
1882 StringRef CustomSectionName) {
1883 int Order = getSectionOrder(ID, CustomSectionName);
1884 if (Order == WASM_SEC_ORDER_NONE)
1885 return true;
1887 // Disallowed predecessors we need to check for
1888 SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
1890 // Keep track of completed checks to avoid repeating work
1891 bool Checked[WASM_NUM_SEC_ORDERS] = {};
1893 int Curr = Order;
1894 while (true) {
1895 // Add new disallowed predecessors to work list
1896 for (size_t I = 0;; ++I) {
1897 int Next = DisallowedPredecessors[Curr][I];
1898 if (Next == WASM_SEC_ORDER_NONE)
1899 break;
1900 if (Checked[Next])
1901 continue;
1902 WorkList.push_back(Next);
1903 Checked[Next] = true;
1906 if (WorkList.empty())
1907 break;
1909 // Consider next disallowed predecessor
1910 Curr = WorkList.pop_back_val();
1911 if (Seen[Curr])
1912 return false;
1915 // Have not seen any disallowed predecessors
1916 Seen[Order] = true;
1917 return true;