LLVM 17.0.0git
WasmObjectFile.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
8
9#include "llvm/ADT/ArrayRef.h"
10#include "llvm/ADT/DenseSet.h"
11#include "llvm/ADT/SmallSet.h"
12#include "llvm/ADT/StringRef.h"
13#include "llvm/ADT/StringSet.h"
17#include "llvm/Object/Binary.h"
18#include "llvm/Object/Error.h"
21#include "llvm/Object/Wasm.h"
22#include "llvm/Support/Endian.h"
23#include "llvm/Support/Error.h"
25#include "llvm/Support/LEB128.h"
28#include <algorithm>
29#include <cassert>
30#include <cstdint>
31#include <cstring>
32
33#define DEBUG_TYPE "wasm-object"
34
35using namespace llvm;
36using namespace object;
37
39 Out << "Name=" << Info.Name
40 << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"
41 << Twine::utohexstr(Info.Flags) << " [";
42 switch (getBinding()) {
43 case wasm::WASM_SYMBOL_BINDING_GLOBAL: Out << "global"; break;
44 case wasm::WASM_SYMBOL_BINDING_LOCAL: Out << "local"; break;
45 case wasm::WASM_SYMBOL_BINDING_WEAK: Out << "weak"; break;
46 }
47 if (isHidden()) {
48 Out << ", hidden";
49 } else {
50 Out << ", default";
51 }
52 Out << "]";
53 if (!isTypeData()) {
54 Out << ", ElemIndex=" << Info.ElementIndex;
55 } else if (isDefined()) {
56 Out << ", Segment=" << Info.DataRef.Segment;
57 Out << ", Offset=" << Info.DataRef.Offset;
58 Out << ", Size=" << Info.DataRef.Size;
59 }
60}
61
62#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
64#endif
65
68 Error Err = Error::success();
69 auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
70 if (Err)
71 return std::move(Err);
72
73 return std::move(ObjectFile);
74}
75
76#define VARINT7_MAX ((1 << 7) - 1)
77#define VARINT7_MIN (-(1 << 7))
78#define VARUINT7_MAX (1 << 7)
79#define VARUINT1_MAX (1)
80
82 if (Ctx.Ptr == Ctx.End)
83 report_fatal_error("EOF while reading uint8");
84 return *Ctx.Ptr++;
85}
86
88 if (Ctx.Ptr + 4 > Ctx.End)
89 report_fatal_error("EOF while reading uint32");
91 Ctx.Ptr += 4;
92 return Result;
93}
94
96 if (Ctx.Ptr + 4 > Ctx.End)
97 report_fatal_error("EOF while reading float64");
98 int32_t Result = 0;
99 memcpy(&Result, Ctx.Ptr, sizeof(Result));
100 Ctx.Ptr += sizeof(Result);
101 return Result;
102}
103
105 if (Ctx.Ptr + 8 > Ctx.End)
106 report_fatal_error("EOF while reading float64");
107 int64_t Result = 0;
108 memcpy(&Result, Ctx.Ptr, sizeof(Result));
109 Ctx.Ptr += sizeof(Result);
110 return Result;
111}
112
114 unsigned Count;
115 const char *Error = nullptr;
116 uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
117 if (Error)
119 Ctx.Ptr += Count;
120 return Result;
121}
122
124 uint32_t StringLen = readULEB128(Ctx);
125 if (Ctx.Ptr + StringLen > Ctx.End)
126 report_fatal_error("EOF while reading string");
127 StringRef Return =
128 StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
129 Ctx.Ptr += StringLen;
130 return Return;
131}
132
134 unsigned Count;
135 const char *Error = nullptr;
136 uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
137 if (Error)
139 Ctx.Ptr += Count;
140 return Result;
141}
142
144 int64_t Result = readLEB128(Ctx);
145 if (Result > VARUINT1_MAX || Result < 0)
146 report_fatal_error("LEB is outside Varuint1 range");
147 return Result;
148}
149
151 int64_t Result = readLEB128(Ctx);
152 if (Result > INT32_MAX || Result < INT32_MIN)
153 report_fatal_error("LEB is outside Varint32 range");
154 return Result;
155}
156
158 uint64_t Result = readULEB128(Ctx);
159 if (Result > UINT32_MAX)
160 report_fatal_error("LEB is outside Varuint32 range");
161 return Result;
162}
163
165 return readLEB128(Ctx);
166}
167
169 return readULEB128(Ctx);
170}
171
173 return readUint8(Ctx);
174}
175
178 auto Start = Ctx.Ptr;
179
180 Expr.Extended = false;
181 Expr.Inst.Opcode = readOpcode(Ctx);
182 switch (Expr.Inst.Opcode) {
184 Expr.Inst.Value.Int32 = readVarint32(Ctx);
185 break;
187 Expr.Inst.Value.Int64 = readVarint64(Ctx);
188 break;
190 Expr.Inst.Value.Float32 = readFloat32(Ctx);
191 break;
193 Expr.Inst.Value.Float64 = readFloat64(Ctx);
194 break;
196 Expr.Inst.Value.Global = readULEB128(Ctx);
197 break;
199 wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx));
200 if (Ty != wasm::ValType::EXTERNREF) {
201 return make_error<GenericBinaryError>("invalid type for ref.null",
203 }
204 break;
205 }
206 default:
207 Expr.Extended = true;
208 }
209
210 if (!Expr.Extended) {
211 uint8_t EndOpcode = readOpcode(Ctx);
212 if (EndOpcode != wasm::WASM_OPCODE_END)
213 Expr.Extended = true;
214 }
215
216 if (Expr.Extended) {
217 Ctx.Ptr = Start;
218 while (true) {
219 uint8_t Opcode = readOpcode(Ctx);
220 switch (Opcode) {
227 readULEB128(Ctx);
228 break;
235 break;
237 Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start);
238 return Error::success();
239 default:
240 return make_error<GenericBinaryError>(
241 Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode)),
243 }
244 }
245 }
246
247 return Error::success();
248}
249
251 wasm::WasmLimits Result;
252 Result.Flags = readVaruint32(Ctx);
253 Result.Minimum = readVaruint64(Ctx);
254 if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
255 Result.Maximum = readVaruint64(Ctx);
256 return Result;
257}
258
260 wasm::WasmTableType TableType;
261 TableType.ElemType = readUint8(Ctx);
262 TableType.Limits = readLimits(Ctx);
263 return TableType;
264}
265
267 WasmSectionOrderChecker &Checker) {
268 Section.Offset = Ctx.Ptr - Ctx.Start;
269 Section.Type = readUint8(Ctx);
270 LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
272 if (Size == 0)
273 return make_error<StringError>("zero length section",
275 if (Ctx.Ptr + Size > Ctx.End)
276 return make_error<StringError>("section too large",
278 if (Section.Type == wasm::WASM_SEC_CUSTOM) {
280 SectionCtx.Start = Ctx.Ptr;
281 SectionCtx.Ptr = Ctx.Ptr;
282 SectionCtx.End = Ctx.Ptr + Size;
283
284 Section.Name = readString(SectionCtx);
285
286 uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
287 Ctx.Ptr += SectionNameSize;
288 Size -= SectionNameSize;
289 }
290
291 if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
292 return make_error<StringError>("out of order section type: " +
293 llvm::to_string(Section.Type),
295 }
296
297 Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
298 Ctx.Ptr += Size;
299 return Error::success();
300}
301
303 : ObjectFile(Binary::ID_Wasm, Buffer) {
304 ErrorAsOutParameter ErrAsOutParam(&Err);
305 Header.Magic = getData().substr(0, 4);
306 if (Header.Magic != StringRef("\0asm", 4)) {
307 Err = make_error<StringError>("invalid magic number",
309 return;
310 }
311
312 ReadContext Ctx;
313 Ctx.Start = getData().bytes_begin();
314 Ctx.Ptr = Ctx.Start + 4;
315 Ctx.End = Ctx.Start + getData().size();
316
317 if (Ctx.Ptr + 4 > Ctx.End) {
318 Err = make_error<StringError>("missing version number",
320 return;
321 }
322
323 Header.Version = readUint32(Ctx);
324 if (Header.Version != wasm::WasmVersion) {
325 Err = make_error<StringError>("invalid version number: " +
326 Twine(Header.Version),
328 return;
329 }
330
332 while (Ctx.Ptr < Ctx.End) {
333 WasmSection Sec;
334 if ((Err = readSection(Sec, Ctx, Checker)))
335 return;
336 if ((Err = parseSection(Sec)))
337 return;
338
339 Sections.push_back(Sec);
340 }
341}
342
343Error WasmObjectFile::parseSection(WasmSection &Sec) {
344 ReadContext Ctx;
345 Ctx.Start = Sec.Content.data();
346 Ctx.End = Ctx.Start + Sec.Content.size();
347 Ctx.Ptr = Ctx.Start;
348 switch (Sec.Type) {
350 return parseCustomSection(Sec, Ctx);
352 return parseTypeSection(Ctx);
354 return parseImportSection(Ctx);
356 return parseFunctionSection(Ctx);
358 return parseTableSection(Ctx);
360 return parseMemorySection(Ctx);
362 return parseTagSection(Ctx);
364 return parseGlobalSection(Ctx);
366 return parseExportSection(Ctx);
368 return parseStartSection(Ctx);
370 return parseElemSection(Ctx);
372 return parseCodeSection(Ctx);
374 return parseDataSection(Ctx);
376 return parseDataCountSection(Ctx);
377 default:
378 return make_error<GenericBinaryError>(
379 "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
380 }
381}
382
383Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
384 // Legacy "dylink" section support.
385 // See parseDylink0Section for the current "dylink.0" section parsing.
386 HasDylinkSection = true;
387 DylinkInfo.MemorySize = readVaruint32(Ctx);
388 DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
389 DylinkInfo.TableSize = readVaruint32(Ctx);
390 DylinkInfo.TableAlignment = readVaruint32(Ctx);
391 uint32_t Count = readVaruint32(Ctx);
392 while (Count--) {
393 DylinkInfo.Needed.push_back(readString(Ctx));
394 }
395
396 if (Ctx.Ptr != Ctx.End)
397 return make_error<GenericBinaryError>("dylink section ended prematurely",
399 return Error::success();
400}
401
402Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
403 // See
404 // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
405 HasDylinkSection = true;
406
407 const uint8_t *OrigEnd = Ctx.End;
408 while (Ctx.Ptr < OrigEnd) {
409 Ctx.End = OrigEnd;
410 uint8_t Type = readUint8(Ctx);
412 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
413 << "\n");
414 Ctx.End = Ctx.Ptr + Size;
415 uint32_t Count;
416 switch (Type) {
418 DylinkInfo.MemorySize = readVaruint32(Ctx);
419 DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
420 DylinkInfo.TableSize = readVaruint32(Ctx);
421 DylinkInfo.TableAlignment = readVaruint32(Ctx);
422 break;
424 Count = readVaruint32(Ctx);
425 while (Count--) {
426 DylinkInfo.Needed.push_back(readString(Ctx));
427 }
428 break;
430 uint32_t Count = readVaruint32(Ctx);
431 while (Count--) {
432 DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)});
433 }
434 break;
435 }
437 uint32_t Count = readVaruint32(Ctx);
438 while (Count--) {
439 DylinkInfo.ImportInfo.push_back(
440 {readString(Ctx), readString(Ctx), readVaruint32(Ctx)});
441 }
442 break;
443 }
444 default:
445 LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n");
446 Ctx.Ptr += Size;
447 break;
448 }
449 if (Ctx.Ptr != Ctx.End) {
450 return make_error<GenericBinaryError>(
451 "dylink.0 sub-section ended prematurely", object_error::parse_failed);
452 }
453 }
454
455 if (Ctx.Ptr != Ctx.End)
456 return make_error<GenericBinaryError>("dylink.0 section ended prematurely",
458 return Error::success();
459}
460
461Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
462 llvm::DenseSet<uint64_t> SeenFunctions;
463 llvm::DenseSet<uint64_t> SeenGlobals;
464 llvm::DenseSet<uint64_t> SeenSegments;
465
466 while (Ctx.Ptr < Ctx.End) {
467 uint8_t Type = readUint8(Ctx);
469 const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
470 switch (Type) {
474 uint32_t Count = readVaruint32(Ctx);
475 while (Count--) {
480 if (!SeenFunctions.insert(Index).second)
481 return make_error<GenericBinaryError>(
482 "function named more than once", object_error::parse_failed);
483 if (!isValidFunctionIndex(Index) || Name.empty())
484 return make_error<GenericBinaryError>("invalid function name entry",
486
487 if (isDefinedFunctionIndex(Index))
488 getDefinedFunction(Index).DebugName = Name;
489 } else if (Type == wasm::WASM_NAMES_GLOBAL) {
490 nameType = wasm::NameType::GLOBAL;
491 if (!SeenGlobals.insert(Index).second)
492 return make_error<GenericBinaryError>("global named more than once",
494 if (!isValidGlobalIndex(Index) || Name.empty())
495 return make_error<GenericBinaryError>("invalid global name entry",
497 } else {
499 if (!SeenSegments.insert(Index).second)
500 return make_error<GenericBinaryError>(
501 "segment named more than once", object_error::parse_failed);
502 if (Index > DataSegments.size())
503 return make_error<GenericBinaryError>("invalid data segment name entry",
505 }
506 DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
507 }
508 break;
509 }
510 // Ignore local names for now
512 default:
513 Ctx.Ptr += Size;
514 break;
515 }
516 if (Ctx.Ptr != SubSectionEnd)
517 return make_error<GenericBinaryError>(
518 "name sub-section ended prematurely", object_error::parse_failed);
519 }
520
521 if (Ctx.Ptr != Ctx.End)
522 return make_error<GenericBinaryError>("name section ended prematurely",
524 return Error::success();
525}
526
527Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
528 HasLinkingSection = true;
529
530 LinkingData.Version = readVaruint32(Ctx);
531 if (LinkingData.Version != wasm::WasmMetadataVersion) {
532 return make_error<GenericBinaryError>(
533 "unexpected metadata version: " + Twine(LinkingData.Version) +
534 " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
536 }
537
538 const uint8_t *OrigEnd = Ctx.End;
539 while (Ctx.Ptr < OrigEnd) {
540 Ctx.End = OrigEnd;
541 uint8_t Type = readUint8(Ctx);
543 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
544 << "\n");
545 Ctx.End = Ctx.Ptr + Size;
546 switch (Type) {
548 if (Error Err = parseLinkingSectionSymtab(Ctx))
549 return Err;
550 break;
552 uint32_t Count = readVaruint32(Ctx);
553 if (Count > DataSegments.size())
554 return make_error<GenericBinaryError>("too many segment names",
556 for (uint32_t I = 0; I < Count; I++) {
557 DataSegments[I].Data.Name = readString(Ctx);
558 DataSegments[I].Data.Alignment = readVaruint32(Ctx);
559 DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);
560 }
561 break;
562 }
564 uint32_t Count = readVaruint32(Ctx);
565 LinkingData.InitFunctions.reserve(Count);
566 for (uint32_t I = 0; I < Count; I++) {
568 Init.Priority = readVaruint32(Ctx);
569 Init.Symbol = readVaruint32(Ctx);
570 if (!isValidFunctionSymbol(Init.Symbol))
571 return make_error<GenericBinaryError>("invalid function symbol: " +
572 Twine(Init.Symbol),
574 LinkingData.InitFunctions.emplace_back(Init);
575 }
576 break;
577 }
579 if (Error Err = parseLinkingSectionComdat(Ctx))
580 return Err;
581 break;
582 default:
583 Ctx.Ptr += Size;
584 break;
585 }
586 if (Ctx.Ptr != Ctx.End)
587 return make_error<GenericBinaryError>(
588 "linking sub-section ended prematurely", object_error::parse_failed);
589 }
590 if (Ctx.Ptr != OrigEnd)
591 return make_error<GenericBinaryError>("linking section ended prematurely",
593 return Error::success();
594}
595
596Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
597 uint32_t Count = readVaruint32(Ctx);
598 LinkingData.SymbolTable.reserve(Count);
599 Symbols.reserve(Count);
600 StringSet<> SymbolNames;
601
602 std::vector<wasm::WasmImport *> ImportedGlobals;
603 std::vector<wasm::WasmImport *> ImportedFunctions;
604 std::vector<wasm::WasmImport *> ImportedTags;
605 std::vector<wasm::WasmImport *> ImportedTables;
606 ImportedGlobals.reserve(Imports.size());
607 ImportedFunctions.reserve(Imports.size());
608 ImportedTags.reserve(Imports.size());
609 ImportedTables.reserve(Imports.size());
610 for (auto &I : Imports) {
612 ImportedFunctions.emplace_back(&I);
613 else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
614 ImportedGlobals.emplace_back(&I);
615 else if (I.Kind == wasm::WASM_EXTERNAL_TAG)
616 ImportedTags.emplace_back(&I);
617 else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
618 ImportedTables.emplace_back(&I);
619 }
620
621 while (Count--) {
623 const wasm::WasmSignature *Signature = nullptr;
624 const wasm::WasmGlobalType *GlobalType = nullptr;
625 const wasm::WasmTableType *TableType = nullptr;
626
627 Info.Kind = readUint8(Ctx);
628 Info.Flags = readVaruint32(Ctx);
629 bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
630
631 switch (Info.Kind) {
633 Info.ElementIndex = readVaruint32(Ctx);
634 if (!isValidFunctionIndex(Info.ElementIndex) ||
635 IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
636 return make_error<GenericBinaryError>("invalid function symbol index",
638 if (IsDefined) {
639 Info.Name = readString(Ctx);
640 unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
641 wasm::WasmFunction &Function = Functions[FuncIndex];
642 Signature = &Signatures[Function.SigIndex];
643 if (Function.SymbolName.empty())
644 Function.SymbolName = Info.Name;
645 } else {
646 wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
647 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
648 Info.Name = readString(Ctx);
649 Info.ImportName = Import.Field;
650 } else {
651 Info.Name = Import.Field;
652 }
653 Signature = &Signatures[Import.SigIndex];
654 Info.ImportModule = Import.Module;
655 }
656 break;
657
659 Info.ElementIndex = readVaruint32(Ctx);
660 if (!isValidGlobalIndex(Info.ElementIndex) ||
661 IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
662 return make_error<GenericBinaryError>("invalid global symbol index",
664 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
666 return make_error<GenericBinaryError>("undefined weak global symbol",
668 if (IsDefined) {
669 Info.Name = readString(Ctx);
670 unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
671 wasm::WasmGlobal &Global = Globals[GlobalIndex];
672 GlobalType = &Global.Type;
673 if (Global.SymbolName.empty())
674 Global.SymbolName = Info.Name;
675 } else {
676 wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
677 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
678 Info.Name = readString(Ctx);
679 Info.ImportName = Import.Field;
680 } else {
681 Info.Name = Import.Field;
682 }
683 GlobalType = &Import.Global;
684 Info.ImportModule = Import.Module;
685 }
686 break;
687
689 Info.ElementIndex = readVaruint32(Ctx);
690 if (!isValidTableNumber(Info.ElementIndex) ||
691 IsDefined != isDefinedTableNumber(Info.ElementIndex))
692 return make_error<GenericBinaryError>("invalid table symbol index",
694 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
696 return make_error<GenericBinaryError>("undefined weak table symbol",
698 if (IsDefined) {
699 Info.Name = readString(Ctx);
700 unsigned TableNumber = Info.ElementIndex - NumImportedTables;
701 wasm::WasmTable &Table = Tables[TableNumber];
702 TableType = &Table.Type;
703 if (Table.SymbolName.empty())
704 Table.SymbolName = Info.Name;
705 } else {
706 wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
707 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
708 Info.Name = readString(Ctx);
709 Info.ImportName = Import.Field;
710 } else {
711 Info.Name = Import.Field;
712 }
713 TableType = &Import.Table;
714 Info.ImportModule = Import.Module;
715 }
716 break;
717
719 Info.Name = readString(Ctx);
720 if (IsDefined) {
721 auto Index = readVaruint32(Ctx);
722 if (Index >= DataSegments.size())
723 return make_error<GenericBinaryError>("invalid data symbol index",
725 auto Offset = readVaruint64(Ctx);
726 auto Size = readVaruint64(Ctx);
727 size_t SegmentSize = DataSegments[Index].Data.Content.size();
728 if (Offset > SegmentSize)
729 return make_error<GenericBinaryError>(
730 "invalid data symbol offset: `" + Info.Name + "` (offset: " +
731 Twine(Offset) + " segment size: " + Twine(SegmentSize) + ")",
734 }
735 break;
736
738 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
740 return make_error<GenericBinaryError>(
741 "section symbols must have local binding",
743 Info.ElementIndex = readVaruint32(Ctx);
744 // Use somewhat unique section name as symbol name.
745 StringRef SectionName = Sections[Info.ElementIndex].Name;
746 Info.Name = SectionName;
747 break;
748 }
749
751 Info.ElementIndex = readVaruint32(Ctx);
752 if (!isValidTagIndex(Info.ElementIndex) ||
753 IsDefined != isDefinedTagIndex(Info.ElementIndex))
754 return make_error<GenericBinaryError>("invalid tag symbol index",
756 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
758 return make_error<GenericBinaryError>("undefined weak global symbol",
760 if (IsDefined) {
761 Info.Name = readString(Ctx);
762 unsigned TagIndex = Info.ElementIndex - NumImportedTags;
763 wasm::WasmTag &Tag = Tags[TagIndex];
764 Signature = &Signatures[Tag.SigIndex];
765 if (Tag.SymbolName.empty())
766 Tag.SymbolName = Info.Name;
767
768 } else {
769 wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex];
770 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
771 Info.Name = readString(Ctx);
772 Info.ImportName = Import.Field;
773 } else {
774 Info.Name = Import.Field;
775 }
776 Signature = &Signatures[Import.SigIndex];
777 Info.ImportModule = Import.Module;
778 }
779 break;
780 }
781
782 default:
783 return make_error<GenericBinaryError>("invalid symbol type: " +
784 Twine(unsigned(Info.Kind)),
786 }
787
788 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
790 !SymbolNames.insert(Info.Name).second)
791 return make_error<GenericBinaryError>("duplicate symbol name " +
792 Twine(Info.Name),
794 LinkingData.SymbolTable.emplace_back(Info);
795 Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType,
796 Signature);
797 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
798 }
799
800 return Error::success();
801}
802
803Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
804 uint32_t ComdatCount = readVaruint32(Ctx);
805 StringSet<> ComdatSet;
806 for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
808 if (Name.empty() || !ComdatSet.insert(Name).second)
809 return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
810 Twine(Name),
812 LinkingData.Comdats.emplace_back(Name);
814 if (Flags != 0)
815 return make_error<GenericBinaryError>("unsupported COMDAT flags",
817
818 uint32_t EntryCount = readVaruint32(Ctx);
819 while (EntryCount--) {
820 unsigned Kind = readVaruint32(Ctx);
821 unsigned Index = readVaruint32(Ctx);
822 switch (Kind) {
823 default:
824 return make_error<GenericBinaryError>("invalid COMDAT entry type",
827 if (Index >= DataSegments.size())
828 return make_error<GenericBinaryError>(
829 "COMDAT data index out of range", object_error::parse_failed);
830 if (DataSegments[Index].Data.Comdat != UINT32_MAX)
831 return make_error<GenericBinaryError>("data segment in two COMDATs",
833 DataSegments[Index].Data.Comdat = ComdatIndex;
834 break;
836 if (!isDefinedFunctionIndex(Index))
837 return make_error<GenericBinaryError>(
838 "COMDAT function index out of range", object_error::parse_failed);
839 if (getDefinedFunction(Index).Comdat != UINT32_MAX)
840 return make_error<GenericBinaryError>("function in two COMDATs",
842 getDefinedFunction(Index).Comdat = ComdatIndex;
843 break;
845 if (Index >= Sections.size())
846 return make_error<GenericBinaryError>(
847 "COMDAT section index out of range", object_error::parse_failed);
848 if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
849 return make_error<GenericBinaryError>(
850 "non-custom section in a COMDAT", object_error::parse_failed);
851 Sections[Index].Comdat = ComdatIndex;
852 break;
853 }
854 }
855 }
856 return Error::success();
857}
858
859Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
861 uint32_t Fields = readVaruint32(Ctx);
862 for (size_t I = 0; I < Fields; ++I) {
863 StringRef FieldName = readString(Ctx);
864 if (!FieldsSeen.insert(FieldName).second)
865 return make_error<GenericBinaryError>(
866 "producers section does not have unique fields",
868 std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
869 if (FieldName == "language") {
870 ProducerVec = &ProducerInfo.Languages;
871 } else if (FieldName == "processed-by") {
872 ProducerVec = &ProducerInfo.Tools;
873 } else if (FieldName == "sdk") {
874 ProducerVec = &ProducerInfo.SDKs;
875 } else {
876 return make_error<GenericBinaryError>(
877 "producers section field is not named one of language, processed-by, "
878 "or sdk",
880 }
881 uint32_t ValueCount = readVaruint32(Ctx);
882 llvm::SmallSet<StringRef, 8> ProducersSeen;
883 for (size_t J = 0; J < ValueCount; ++J) {
886 if (!ProducersSeen.insert(Name).second) {
887 return make_error<GenericBinaryError>(
888 "producers section contains repeated producer",
890 }
891 ProducerVec->emplace_back(std::string(Name), std::string(Version));
892 }
893 }
894 if (Ctx.Ptr != Ctx.End)
895 return make_error<GenericBinaryError>("producers section ended prematurely",
897 return Error::success();
898}
899
900Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
903 for (size_t I = 0; I < FeatureCount; ++I) {
905 Feature.Prefix = readUint8(Ctx);
906 switch (Feature.Prefix) {
910 break;
911 default:
912 return make_error<GenericBinaryError>("unknown feature policy prefix",
914 }
915 Feature.Name = std::string(readString(Ctx));
916 if (!FeaturesSeen.insert(Feature.Name).second)
917 return make_error<GenericBinaryError>(
918 "target features section contains repeated feature \"" +
919 Feature.Name + "\"",
921 TargetFeatures.push_back(Feature);
922 }
923 if (Ctx.Ptr != Ctx.End)
924 return make_error<GenericBinaryError>(
925 "target features section ended prematurely",
927 return Error::success();
928}
929
930Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
931 uint32_t SectionIndex = readVaruint32(Ctx);
932 if (SectionIndex >= Sections.size())
933 return make_error<GenericBinaryError>("invalid section index",
935 WasmSection &Section = Sections[SectionIndex];
936 uint32_t RelocCount = readVaruint32(Ctx);
937 uint32_t EndOffset = Section.Content.size();
938 uint32_t PreviousOffset = 0;
939 while (RelocCount--) {
940 wasm::WasmRelocation Reloc = {};
941 uint32_t type = readVaruint32(Ctx);
942 Reloc.Type = type;
943 Reloc.Offset = readVaruint32(Ctx);
944 if (Reloc.Offset < PreviousOffset)
945 return make_error<GenericBinaryError>("relocations not in offset order",
947 PreviousOffset = Reloc.Offset;
948 Reloc.Index = readVaruint32(Ctx);
949 switch (type) {
950 case wasm::R_WASM_FUNCTION_INDEX_LEB:
951 case wasm::R_WASM_TABLE_INDEX_SLEB:
952 case wasm::R_WASM_TABLE_INDEX_SLEB64:
953 case wasm::R_WASM_TABLE_INDEX_I32:
954 case wasm::R_WASM_TABLE_INDEX_I64:
955 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
956 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
957 if (!isValidFunctionSymbol(Reloc.Index))
958 return make_error<GenericBinaryError>(
959 "invalid relocation function index", object_error::parse_failed);
960 break;
961 case wasm::R_WASM_TABLE_NUMBER_LEB:
962 if (!isValidTableSymbol(Reloc.Index))
963 return make_error<GenericBinaryError>("invalid relocation table index",
965 break;
966 case wasm::R_WASM_TYPE_INDEX_LEB:
967 if (Reloc.Index >= Signatures.size())
968 return make_error<GenericBinaryError>("invalid relocation type index",
970 break;
971 case wasm::R_WASM_GLOBAL_INDEX_LEB:
972 // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
973 // symbols to refer to their GOT entries.
974 if (!isValidGlobalSymbol(Reloc.Index) &&
975 !isValidDataSymbol(Reloc.Index) &&
976 !isValidFunctionSymbol(Reloc.Index))
977 return make_error<GenericBinaryError>("invalid relocation global index",
979 break;
980 case wasm::R_WASM_GLOBAL_INDEX_I32:
981 if (!isValidGlobalSymbol(Reloc.Index))
982 return make_error<GenericBinaryError>("invalid relocation global index",
984 break;
985 case wasm::R_WASM_TAG_INDEX_LEB:
986 if (!isValidTagSymbol(Reloc.Index))
987 return make_error<GenericBinaryError>("invalid relocation tag index",
989 break;
990 case wasm::R_WASM_MEMORY_ADDR_LEB:
991 case wasm::R_WASM_MEMORY_ADDR_SLEB:
992 case wasm::R_WASM_MEMORY_ADDR_I32:
993 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
994 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
995 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
996 if (!isValidDataSymbol(Reloc.Index))
997 return make_error<GenericBinaryError>("invalid relocation data index",
999 Reloc.Addend = readVarint32(Ctx);
1000 break;
1001 case wasm::R_WASM_MEMORY_ADDR_LEB64:
1002 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1003 case wasm::R_WASM_MEMORY_ADDR_I64:
1004 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1005 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1006 if (!isValidDataSymbol(Reloc.Index))
1007 return make_error<GenericBinaryError>("invalid relocation data index",
1009 Reloc.Addend = readVarint64(Ctx);
1010 break;
1011 case wasm::R_WASM_FUNCTION_OFFSET_I32:
1012 if (!isValidFunctionSymbol(Reloc.Index))
1013 return make_error<GenericBinaryError>(
1014 "invalid relocation function index", object_error::parse_failed);
1015 Reloc.Addend = readVarint32(Ctx);
1016 break;
1017 case wasm::R_WASM_FUNCTION_OFFSET_I64:
1018 if (!isValidFunctionSymbol(Reloc.Index))
1019 return make_error<GenericBinaryError>(
1020 "invalid relocation function index", object_error::parse_failed);
1021 Reloc.Addend = readVarint64(Ctx);
1022 break;
1023 case wasm::R_WASM_SECTION_OFFSET_I32:
1024 if (!isValidSectionSymbol(Reloc.Index))
1025 return make_error<GenericBinaryError>(
1026 "invalid relocation section index", object_error::parse_failed);
1027 Reloc.Addend = readVarint32(Ctx);
1028 break;
1029 default:
1030 return make_error<GenericBinaryError>("invalid relocation type: " +
1031 Twine(type),
1033 }
1034
1035 // Relocations must fit inside the section, and must appear in order. They
1036 // also shouldn't overlap a function/element boundary, but we don't bother
1037 // to check that.
1038 uint64_t Size = 5;
1039 if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1040 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1041 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1042 Size = 10;
1043 if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1044 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1045 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1046 Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1047 Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1048 Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
1049 Size = 4;
1050 if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1051 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1052 Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
1053 Size = 8;
1054 if (Reloc.Offset + Size > EndOffset)
1055 return make_error<GenericBinaryError>("invalid relocation offset",
1057
1058 Section.Relocations.push_back(Reloc);
1059 }
1060 if (Ctx.Ptr != Ctx.End)
1061 return make_error<GenericBinaryError>("reloc section ended prematurely",
1063 return Error::success();
1064}
1065
1066Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
1067 if (Sec.Name == "dylink") {
1068 if (Error Err = parseDylinkSection(Ctx))
1069 return Err;
1070 } else if (Sec.Name == "dylink.0") {
1071 if (Error Err = parseDylink0Section(Ctx))
1072 return Err;
1073 } else if (Sec.Name == "name") {
1074 if (Error Err = parseNameSection(Ctx))
1075 return Err;
1076 } else if (Sec.Name == "linking") {
1077 if (Error Err = parseLinkingSection(Ctx))
1078 return Err;
1079 } else if (Sec.Name == "producers") {
1080 if (Error Err = parseProducersSection(Ctx))
1081 return Err;
1082 } else if (Sec.Name == "target_features") {
1083 if (Error Err = parseTargetFeaturesSection(Ctx))
1084 return Err;
1085 } else if (Sec.Name.startswith("reloc.")) {
1086 if (Error Err = parseRelocSection(Sec.Name, Ctx))
1087 return Err;
1088 }
1089 return Error::success();
1090}
1091
1092Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1093 uint32_t Count = readVaruint32(Ctx);
1094 Signatures.reserve(Count);
1095 while (Count--) {
1097 uint8_t Form = readUint8(Ctx);
1098 if (Form != wasm::WASM_TYPE_FUNC) {
1099 return make_error<GenericBinaryError>("invalid signature type",
1101 }
1102 uint32_t ParamCount = readVaruint32(Ctx);
1103 Sig.Params.reserve(ParamCount);
1104 while (ParamCount--) {
1105 uint32_t ParamType = readUint8(Ctx);
1106 Sig.Params.push_back(wasm::ValType(ParamType));
1107 }
1108 uint32_t ReturnCount = readVaruint32(Ctx);
1109 while (ReturnCount--) {
1111 Sig.Returns.push_back(wasm::ValType(ReturnType));
1112 }
1113 Signatures.push_back(std::move(Sig));
1114 }
1115 if (Ctx.Ptr != Ctx.End)
1116 return make_error<GenericBinaryError>("type section ended prematurely",
1118 return Error::success();
1119}
1120
1121Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1122 uint32_t Count = readVaruint32(Ctx);
1123 uint32_t NumTypes = Signatures.size();
1124 Imports.reserve(Count);
1125 for (uint32_t I = 0; I < Count; I++) {
1127 Im.Module = readString(Ctx);
1128 Im.Field = readString(Ctx);
1129 Im.Kind = readUint8(Ctx);
1130 switch (Im.Kind) {
1132 NumImportedFunctions++;
1133 Im.SigIndex = readVaruint32(Ctx);
1134 if (Im.SigIndex >= NumTypes)
1135 return make_error<GenericBinaryError>("invalid function type",
1137 break;
1139 NumImportedGlobals++;
1140 Im.Global.Type = readUint8(Ctx);
1141 Im.Global.Mutable = readVaruint1(Ctx);
1142 break;
1144 Im.Memory = readLimits(Ctx);
1146 HasMemory64 = true;
1147 break;
1149 Im.Table = readTableType(Ctx);
1150 NumImportedTables++;
1151 auto ElemType = Im.Table.ElemType;
1152 if (ElemType != wasm::WASM_TYPE_FUNCREF &&
1153 ElemType != wasm::WASM_TYPE_EXTERNREF)
1154 return make_error<GenericBinaryError>("invalid table element type",
1156 break;
1157 }
1159 NumImportedTags++;
1160 if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1161 return make_error<GenericBinaryError>("invalid attribute",
1163 Im.SigIndex = readVaruint32(Ctx);
1164 if (Im.SigIndex >= NumTypes)
1165 return make_error<GenericBinaryError>("invalid tag type",
1167 break;
1168 default:
1169 return make_error<GenericBinaryError>("unexpected import kind",
1171 }
1172 Imports.push_back(Im);
1173 }
1174 if (Ctx.Ptr != Ctx.End)
1175 return make_error<GenericBinaryError>("import section ended prematurely",
1177 return Error::success();
1178}
1179
1180Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1181 uint32_t Count = readVaruint32(Ctx);
1182 Functions.reserve(Count);
1183 uint32_t NumTypes = Signatures.size();
1184 while (Count--) {
1186 if (Type >= NumTypes)
1187 return make_error<GenericBinaryError>("invalid function type",
1190 F.SigIndex = Type;
1191 Functions.push_back(F);
1192 }
1193 if (Ctx.Ptr != Ctx.End)
1194 return make_error<GenericBinaryError>("function section ended prematurely",
1196 return Error::success();
1197}
1198
1199Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1200 TableSection = Sections.size();
1201 uint32_t Count = readVaruint32(Ctx);
1202 Tables.reserve(Count);
1203 while (Count--) {
1205 T.Type = readTableType(Ctx);
1206 T.Index = NumImportedTables + Tables.size();
1207 Tables.push_back(T);
1208 auto ElemType = Tables.back().Type.ElemType;
1209 if (ElemType != wasm::WASM_TYPE_FUNCREF &&
1210 ElemType != wasm::WASM_TYPE_EXTERNREF) {
1211 return make_error<GenericBinaryError>("invalid table element type",
1213 }
1214 }
1215 if (Ctx.Ptr != Ctx.End)
1216 return make_error<GenericBinaryError>("table section ended prematurely",
1218 return Error::success();
1219}
1220
1221Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1222 uint32_t Count = readVaruint32(Ctx);
1223 Memories.reserve(Count);
1224 while (Count--) {
1225 auto Limits = readLimits(Ctx);
1226 if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1227 HasMemory64 = true;
1228 Memories.push_back(Limits);
1229 }
1230 if (Ctx.Ptr != Ctx.End)
1231 return make_error<GenericBinaryError>("memory section ended prematurely",
1233 return Error::success();
1234}
1235
1236Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1237 TagSection = Sections.size();
1238 uint32_t Count = readVaruint32(Ctx);
1239 Tags.reserve(Count);
1240 uint32_t NumTypes = Signatures.size();
1241 while (Count--) {
1242 if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1243 return make_error<GenericBinaryError>("invalid attribute",
1246 if (Type >= NumTypes)
1247 return make_error<GenericBinaryError>("invalid tag type",
1250 Tag.Index = NumImportedTags + Tags.size();
1251 Tag.SigIndex = Type;
1252 Tags.push_back(Tag);
1253 }
1254
1255 if (Ctx.Ptr != Ctx.End)
1256 return make_error<GenericBinaryError>("tag section ended prematurely",
1258 return Error::success();
1259}
1260
1261Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1262 GlobalSection = Sections.size();
1263 uint32_t Count = readVaruint32(Ctx);
1264 Globals.reserve(Count);
1265 while (Count--) {
1267 Global.Index = NumImportedGlobals + Globals.size();
1268 Global.Type.Type = readUint8(Ctx);
1269 Global.Type.Mutable = readVaruint1(Ctx);
1270 if (Error Err = readInitExpr(Global.InitExpr, Ctx))
1271 return Err;
1272 Globals.push_back(Global);
1273 }
1274 if (Ctx.Ptr != Ctx.End)
1275 return make_error<GenericBinaryError>("global section ended prematurely",
1277 return Error::success();
1278}
1279
1280Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1281 uint32_t Count = readVaruint32(Ctx);
1282 Exports.reserve(Count);
1283 for (uint32_t I = 0; I < Count; I++) {
1285 Ex.Name = readString(Ctx);
1286 Ex.Kind = readUint8(Ctx);
1287 Ex.Index = readVaruint32(Ctx);
1288 switch (Ex.Kind) {
1290
1291 if (!isDefinedFunctionIndex(Ex.Index))
1292 return make_error<GenericBinaryError>("invalid function export",
1294 getDefinedFunction(Ex.Index).ExportName = Ex.Name;
1295 break;
1297 if (!isValidGlobalIndex(Ex.Index))
1298 return make_error<GenericBinaryError>("invalid global export",
1300 break;
1302 if (!isValidTagIndex(Ex.Index))
1303 return make_error<GenericBinaryError>("invalid tag export",
1305 break;
1308 break;
1309 default:
1310 return make_error<GenericBinaryError>("unexpected export kind",
1312 }
1313 Exports.push_back(Ex);
1314 }
1315 if (Ctx.Ptr != Ctx.End)
1316 return make_error<GenericBinaryError>("export section ended prematurely",
1318 return Error::success();
1319}
1320
1321bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1322 return Index < NumImportedFunctions + Functions.size();
1323}
1324
1325bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
1326 return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1327}
1328
1329bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
1330 return Index < NumImportedGlobals + Globals.size();
1331}
1332
1333bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
1334 return Index < NumImportedTables + Tables.size();
1335}
1336
1337bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
1338 return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1339}
1340
1341bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
1342 return Index >= NumImportedTables && isValidTableNumber(Index);
1343}
1344
1345bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
1346 return Index < NumImportedTags + Tags.size();
1347}
1348
1349bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
1350 return Index >= NumImportedTags && isValidTagIndex(Index);
1351}
1352
1353bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1354 return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1355}
1356
1357bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
1358 return Index < Symbols.size() && Symbols[Index].isTypeTable();
1359}
1360
1361bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1362 return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1363}
1364
1365bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
1366 return Index < Symbols.size() && Symbols[Index].isTypeTag();
1367}
1368
1369bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1370 return Index < Symbols.size() && Symbols[Index].isTypeData();
1371}
1372
1373bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1374 return Index < Symbols.size() && Symbols[Index].isTypeSection();
1375}
1376
1377wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1378 assert(isDefinedFunctionIndex(Index));
1379 return Functions[Index - NumImportedFunctions];
1380}
1381
1382const wasm::WasmFunction &
1383WasmObjectFile::getDefinedFunction(uint32_t Index) const {
1384 assert(isDefinedFunctionIndex(Index));
1385 return Functions[Index - NumImportedFunctions];
1386}
1387
1388wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
1389 assert(isDefinedGlobalIndex(Index));
1390 return Globals[Index - NumImportedGlobals];
1391}
1392
1393wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1394 assert(isDefinedTagIndex(Index));
1395 return Tags[Index - NumImportedTags];
1396}
1397
1398Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1399 StartFunction = readVaruint32(Ctx);
1400 if (!isValidFunctionIndex(StartFunction))
1401 return make_error<GenericBinaryError>("invalid start function",
1403 return Error::success();
1404}
1405
1406Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1407 CodeSection = Sections.size();
1408 uint32_t FunctionCount = readVaruint32(Ctx);
1409 if (FunctionCount != Functions.size()) {
1410 return make_error<GenericBinaryError>("invalid function count",
1412 }
1413
1414 for (uint32_t i = 0; i < FunctionCount; i++) {
1415 wasm::WasmFunction& Function = Functions[i];
1416 const uint8_t *FunctionStart = Ctx.Ptr;
1418 const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1419
1420 Function.CodeOffset = Ctx.Ptr - FunctionStart;
1421 Function.Index = NumImportedFunctions + i;
1422 Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1423 Function.Size = FunctionEnd - FunctionStart;
1424
1425 uint32_t NumLocalDecls = readVaruint32(Ctx);
1426 Function.Locals.reserve(NumLocalDecls);
1427 while (NumLocalDecls--) {
1429 Decl.Count = readVaruint32(Ctx);
1430 Decl.Type = readUint8(Ctx);
1431 Function.Locals.push_back(Decl);
1432 }
1433
1434 uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1435 Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1436 // This will be set later when reading in the linking metadata section.
1437 Function.Comdat = UINT32_MAX;
1438 Ctx.Ptr += BodySize;
1439 assert(Ctx.Ptr == FunctionEnd);
1440 }
1441 if (Ctx.Ptr != Ctx.End)
1442 return make_error<GenericBinaryError>("code section ended prematurely",
1444 return Error::success();
1445}
1446
1447Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1448 uint32_t Count = readVaruint32(Ctx);
1449 ElemSegments.reserve(Count);
1450 while (Count--) {
1451 wasm::WasmElemSegment Segment;
1452 Segment.Flags = readVaruint32(Ctx);
1453
1457 if (Segment.Flags & ~SupportedFlags)
1458 return make_error<GenericBinaryError>(
1459 "Unsupported flags for element segment", object_error::parse_failed);
1460
1462 Segment.TableNumber = readVaruint32(Ctx);
1463 else
1464 Segment.TableNumber = 0;
1465 if (!isValidTableNumber(Segment.TableNumber))
1466 return make_error<GenericBinaryError>("invalid TableNumber",
1468
1470 Segment.Offset.Extended = false;
1472 Segment.Offset.Inst.Value.Int32 = 0;
1473 } else {
1474 if (Error Err = readInitExpr(Segment.Offset, Ctx))
1475 return Err;
1476 }
1477
1479 Segment.ElemKind = readUint8(Ctx);
1481 if (Segment.ElemKind != uint8_t(wasm::ValType::FUNCREF) &&
1482 Segment.ElemKind != uint8_t(wasm::ValType::EXTERNREF)) {
1483 return make_error<GenericBinaryError>("invalid reference type",
1485 }
1486 } else {
1487 if (Segment.ElemKind != 0)
1488 return make_error<GenericBinaryError>("invalid elemtype",
1490 Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1491 }
1492 } else {
1493 Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1494 }
1495
1497 return make_error<GenericBinaryError>(
1498 "elem segment init expressions not yet implemented",
1500
1501 uint32_t NumElems = readVaruint32(Ctx);
1502 while (NumElems--) {
1503 Segment.Functions.push_back(readVaruint32(Ctx));
1504 }
1505 ElemSegments.push_back(Segment);
1506 }
1507 if (Ctx.Ptr != Ctx.End)
1508 return make_error<GenericBinaryError>("elem section ended prematurely",
1510 return Error::success();
1511}
1512
1513Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1514 DataSection = Sections.size();
1515 uint32_t Count = readVaruint32(Ctx);
1516 if (DataCount && Count != *DataCount)
1517 return make_error<GenericBinaryError>(
1518 "number of data segments does not match DataCount section");
1519 DataSegments.reserve(Count);
1520 while (Count--) {
1521 WasmSegment Segment;
1522 Segment.Data.InitFlags = readVaruint32(Ctx);
1523 Segment.Data.MemoryIndex =
1525 ? readVaruint32(Ctx)
1526 : 0;
1527 if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1528 if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1529 return Err;
1530 } else {
1531 Segment.Data.Offset.Extended = false;
1533 Segment.Data.Offset.Inst.Value.Int32 = 0;
1534 }
1536 if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1537 return make_error<GenericBinaryError>("invalid segment size",
1539 Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1540 // The rest of these Data fields are set later, when reading in the linking
1541 // metadata section.
1542 Segment.Data.Alignment = 0;
1543 Segment.Data.LinkingFlags = 0;
1544 Segment.Data.Comdat = UINT32_MAX;
1545 Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1546 Ctx.Ptr += Size;
1547 DataSegments.push_back(Segment);
1548 }
1549 if (Ctx.Ptr != Ctx.End)
1550 return make_error<GenericBinaryError>("data section ended prematurely",
1552 return Error::success();
1553}
1554
1555Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1556 DataCount = readVaruint32(Ctx);
1557 return Error::success();
1558}
1559
1561 return Header;
1562}
1563
1564void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
1565
1568 const WasmSymbol &Sym = getWasmSymbol(Symb);
1569
1570 LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1571 if (Sym.isBindingWeak())
1572 Result |= SymbolRef::SF_Weak;
1573 if (!Sym.isBindingLocal())
1574 Result |= SymbolRef::SF_Global;
1575 if (Sym.isHidden())
1576 Result |= SymbolRef::SF_Hidden;
1577 if (!Sym.isDefined())
1578 Result |= SymbolRef::SF_Undefined;
1579 if (Sym.isTypeFunction())
1580 Result |= SymbolRef::SF_Executable;
1581 return Result;
1582}
1583
1586 Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1587 Ref.d.b = 0; // Symbol index
1588 return BasicSymbolRef(Ref, this);
1589}
1590
1593 Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1594 Ref.d.b = Symbols.size(); // Symbol index
1595 return BasicSymbolRef(Ref, this);
1596}
1597
1599 return Symbols[Symb.d.b];
1600}
1601
1603 return getWasmSymbol(Symb.getRawDataRefImpl());
1604}
1605
1607 return getWasmSymbol(Symb).Info.Name;
1608}
1609
1611 auto &Sym = getWasmSymbol(Symb);
1612 if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1613 isDefinedFunctionIndex(Sym.Info.ElementIndex))
1614 return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset;
1615 else
1616 return getSymbolValue(Symb);
1617}
1618
1620 switch (Sym.Info.Kind) {
1625 return Sym.Info.ElementIndex;
1627 // The value of a data symbol is the segment offset, plus the symbol
1628 // offset within the segment.
1629 uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1630 const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1631 if (Segment.Offset.Extended) {
1632 llvm_unreachable("extended init exprs not supported");
1633 } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1634 return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset;
1635 } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1636 return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset;
1637 } else {
1638 llvm_unreachable("unknown init expr opcode");
1639 }
1640 }
1642 return 0;
1643 }
1644 llvm_unreachable("invalid symbol type");
1645}
1646
1648 return getWasmSymbolValue(getWasmSymbol(Symb));
1649}
1650
1652 llvm_unreachable("not yet implemented");
1653 return 0;
1654}
1655
1657 llvm_unreachable("not yet implemented");
1658 return 0;
1659}
1660
1663 const WasmSymbol &Sym = getWasmSymbol(Symb);
1664
1665 switch (Sym.Info.Kind) {
1669 return SymbolRef::ST_Other;
1671 return SymbolRef::ST_Data;
1673 return SymbolRef::ST_Debug;
1675 return SymbolRef::ST_Other;
1677 return SymbolRef::ST_Other;
1678 }
1679
1680 llvm_unreachable("unknown WasmSymbol::SymbolType");
1681 return SymbolRef::ST_Other;
1682}
1683
1686 const WasmSymbol &Sym = getWasmSymbol(Symb);
1687 if (Sym.isUndefined())
1688 return section_end();
1689
1691 Ref.d.a = getSymbolSectionIdImpl(Sym);
1692 return section_iterator(SectionRef(Ref, this));
1693}
1694
1696 const WasmSymbol &Sym = getWasmSymbol(Symb);
1697 return getSymbolSectionIdImpl(Sym);
1698}
1699
1700uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
1701 switch (Sym.Info.Kind) {
1703 return CodeSection;
1705 return GlobalSection;
1707 return DataSection;
1709 return Sym.Info.ElementIndex;
1711 return TagSection;
1713 return TableSection;
1714 default:
1715 llvm_unreachable("unknown WasmSymbol::SymbolType");
1716 }
1717}
1718
1720
1722 const WasmSection &S = Sections[Sec.d.a];
1723 if (S.Type == wasm::WASM_SEC_CUSTOM)
1724 return S.Name;
1728}
1729
1731
1733 return Sec.d.a;
1734}
1735
1737 const WasmSection &S = Sections[Sec.d.a];
1738 return S.Content.size();
1739}
1740
1743 const WasmSection &S = Sections[Sec.d.a];
1744 // This will never fail since wasm sections can never be empty (user-sections
1745 // must have a name and non-user sections each have a defined structure).
1746 return S.Content;
1747}
1748
1750 return 1;
1751}
1752
1754 return false;
1755}
1756
1759}
1760
1763}
1764
1765bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1766
1767bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1768
1770 DataRefImpl RelocRef;
1771 RelocRef.d.a = Ref.d.a;
1772 RelocRef.d.b = 0;
1773 return relocation_iterator(RelocationRef(RelocRef, this));
1774}
1775
1777 const WasmSection &Sec = getWasmSection(Ref);
1778 DataRefImpl RelocRef;
1779 RelocRef.d.a = Ref.d.a;
1780 RelocRef.d.b = Sec.Relocations.size();
1781 return relocation_iterator(RelocationRef(RelocRef, this));
1782}
1783
1785
1788 return Rel.Offset;
1789}
1790
1793 if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
1794 return symbol_end();
1796 Sym.d.a = 1;
1797 Sym.d.b = Rel.Index;
1798 return symbol_iterator(SymbolRef(Sym, this));
1799}
1800
1803 return Rel.Type;
1804}
1805
1807 DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1809 StringRef Res = "Unknown";
1810
1811#define WASM_RELOC(name, value) \
1812 case wasm::name: \
1813 Res = #name; \
1814 break;
1815
1816 switch (Rel.Type) {
1817#include "llvm/BinaryFormat/WasmRelocs.def"
1818 }
1819
1820#undef WASM_RELOC
1821
1822 Result.append(Res.begin(), Res.end());
1823}
1824
1827 Ref.d.a = 0;
1828 return section_iterator(SectionRef(Ref, this));
1829}
1830
1833 Ref.d.a = Sections.size();
1834 return section_iterator(SectionRef(Ref, this));
1835}
1836
1838 return HasMemory64 ? 8 : 4;
1839}
1840
1842
1844 return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
1845}
1846
1848 return SubtargetFeatures();
1849}
1850
1851bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1852
1853bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
1854
1856 assert(Ref.d.a < Sections.size());
1857 return Sections[Ref.d.a];
1858}
1859
1860const WasmSection &
1862 return getWasmSection(Section.getRawDataRefImpl());
1863}
1864
1867 return getWasmRelocation(Ref.getRawDataRefImpl());
1868}
1869
1872 assert(Ref.d.a < Sections.size());
1873 const WasmSection &Sec = Sections[Ref.d.a];
1874 assert(Ref.d.b < Sec.Relocations.size());
1875 return Sec.Relocations[Ref.d.b];
1876}
1877
1878int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1879 StringRef CustomSectionName) {
1880 switch (ID) {
1882 return StringSwitch<unsigned>(CustomSectionName)
1883 .Case("dylink", WASM_SEC_ORDER_DYLINK)
1884 .Case("dylink.0", WASM_SEC_ORDER_DYLINK)
1885 .Case("linking", WASM_SEC_ORDER_LINKING)
1887 .Case("name", WASM_SEC_ORDER_NAME)
1888 .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1889 .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
1892 return WASM_SEC_ORDER_TYPE;
1894 return WASM_SEC_ORDER_IMPORT;
1898 return WASM_SEC_ORDER_TABLE;
1900 return WASM_SEC_ORDER_MEMORY;
1902 return WASM_SEC_ORDER_GLOBAL;
1904 return WASM_SEC_ORDER_EXPORT;
1906 return WASM_SEC_ORDER_START;
1908 return WASM_SEC_ORDER_ELEM;
1910 return WASM_SEC_ORDER_CODE;
1912 return WASM_SEC_ORDER_DATA;
1915 case wasm::WASM_SEC_TAG:
1916 return WASM_SEC_ORDER_TAG;
1917 default:
1918 return WASM_SEC_ORDER_NONE;
1919 }
1920}
1921
1922// Represents the edges in a directed graph where any node B reachable from node
1923// A is not allowed to appear before A in the section ordering, but may appear
1924// afterward.
1926 [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
1927 // WASM_SEC_ORDER_NONE
1928 {},
1929 // WASM_SEC_ORDER_TYPE
1930 {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
1931 // WASM_SEC_ORDER_IMPORT
1932 {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
1933 // WASM_SEC_ORDER_FUNCTION
1934 {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
1935 // WASM_SEC_ORDER_TABLE
1936 {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
1937 // WASM_SEC_ORDER_MEMORY
1938 {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
1939 // WASM_SEC_ORDER_TAG
1940 {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
1941 // WASM_SEC_ORDER_GLOBAL
1942 {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
1943 // WASM_SEC_ORDER_EXPORT
1944 {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
1945 // WASM_SEC_ORDER_START
1946 {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
1947 // WASM_SEC_ORDER_ELEM
1948 {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
1949 // WASM_SEC_ORDER_DATACOUNT
1950 {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
1951 // WASM_SEC_ORDER_CODE
1952 {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
1953 // WASM_SEC_ORDER_DATA
1954 {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
1955
1956 // Custom Sections
1957 // WASM_SEC_ORDER_DYLINK
1958 {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
1959 // WASM_SEC_ORDER_LINKING
1960 {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
1961 // WASM_SEC_ORDER_RELOC (can be repeated)
1962 {},
1963 // WASM_SEC_ORDER_NAME
1964 {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
1965 // WASM_SEC_ORDER_PRODUCERS
1966 {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
1967 // WASM_SEC_ORDER_TARGET_FEATURES
1968 {WASM_SEC_ORDER_TARGET_FEATURES}};
1969
1971 StringRef CustomSectionName) {
1972 int Order = getSectionOrder(ID, CustomSectionName);
1973 if (Order == WASM_SEC_ORDER_NONE)
1974 return true;
1975
1976 // Disallowed predecessors we need to check for
1978
1979 // Keep track of completed checks to avoid repeating work
1980 bool Checked[WASM_NUM_SEC_ORDERS] = {};
1981
1982 int Curr = Order;
1983 while (true) {
1984 // Add new disallowed predecessors to work list
1985 for (size_t I = 0;; ++I) {
1986 int Next = DisallowedPredecessors[Curr][I];
1987 if (Next == WASM_SEC_ORDER_NONE)
1988 break;
1989 if (Checked[Next])
1990 continue;
1991 WorkList.push_back(Next);
1992 Checked[Next] = true;
1993 }
1994
1995 if (WorkList.empty())
1996 break;
1997
1998 // Consider next disallowed predecessor
1999 Curr = WorkList.pop_back_val();
2000 if (Seen[Curr])
2001 return false;
2002 }
2003
2004 // Have not seen any disallowed predecessors
2005 Seen[Order] = true;
2006 return true;
2007}
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:492
#define LLVM_DEBUG(X)
Definition: Debug.h:101
This file defines the DenseSet and SmallDenseSet classes.
std::string Name
uint64_t Size
Symbol * Sym
Definition: ELF_riscv.cpp:463
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
StringSet - A set-like wrapper for the StringMap.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
@ Flags
Definition: TextStubV5.cpp:93
static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx)
static Error readInitExpr(wasm::WasmInitExpr &Expr, WasmObjectFile::ReadContext &Ctx)
static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx)
static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx)
static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx)
static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx)
static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx, WasmSectionOrderChecker &Checker)
static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx)
static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx)
static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx)
static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx)
static StringRef readString(WasmObjectFile::ReadContext &Ctx)
static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx)
#define VARUINT1_MAX
static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx)
static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx)
static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx)
static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:163
const T * data() const
Definition: ArrayRef.h:160
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
Helper for Errors used as out-parameters.
Definition: Error.h:1104
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
Tagged union holding either a T or a Error.
Definition: Error.h:470
bool empty() const
Definition: Function.h:767
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:135
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition: SmallSet.h:179
bool empty() const
Definition: SmallVector.h:94
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
void reserve(size_type N)
Definition: SmallVector.h:667
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:575
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
iterator begin() const
Definition: StringRef.h:111
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
bool startswith(StringRef Prefix) const
Definition: StringRef.h:261
iterator end() const
Definition: StringRef.h:113
const unsigned char * bytes_begin() const
Definition: StringRef.h:115
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition: StringSet.h:23
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition: StringSet.h:34
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:69
R Default(T Value)
Definition: StringSwitch.h:182
StringSwitch & StartsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:83
Manages the enabling and disabling of subtarget specific features.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
static Twine utohexstr(const uint64_t &Val)
Definition: Twine.h:404
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
This is a value type class that represents a single symbol in the list of symbols in the object file.
Definition: SymbolicFile.h:103
DataRefImpl getRawDataRefImpl() const
Definition: SymbolicFile.h:210
MemoryBufferRef Data
Definition: Binary.h:37
StringRef getData() const
Definition: Binary.cpp:39
This class is the base class for all object file types.
Definition: ObjectFile.h:228
friend class RelocationRef
Definition: ObjectFile.h:286
friend class SymbolRef
Definition: ObjectFile.h:246
friend class SectionRef
Definition: ObjectFile.h:260
static Expected< std::unique_ptr< WasmObjectFile > > createWasmObjectFile(MemoryBufferRef Object)
Expected< uint64_t > getSymbolValue(DataRefImpl Symb) const
Definition: ObjectFile.cpp:56
This is a value type class that represents a single relocation in the list of relocations in the obje...
Definition: ObjectFile.h:51
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:80
This is a value type class that represents a single symbol in the list of symbols in the object file.
Definition: ObjectFile.h:167
basic_symbol_iterator symbol_begin() const override
relocation_iterator section_rel_end(DataRefImpl Sec) const override
void moveSymbolNext(DataRefImpl &Symb) const override
uint64_t getSectionAlignment(DataRefImpl Sec) const override
uint64_t getRelocationOffset(DataRefImpl Rel) const override
Expected< SymbolRef::Type > getSymbolType(DataRefImpl Symb) const override
uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override
bool isSectionText(DataRefImpl Sec) const override
bool isSectionBSS(DataRefImpl Sec) const override
basic_symbol_iterator symbol_end() const override
Expected< uint32_t > getSymbolFlags(DataRefImpl Symb) const override
section_iterator section_begin() const override
bool isRelocatableObject() const override
True if this is a relocatable object (.o/.obj).
void moveRelocationNext(DataRefImpl &Rel) const override
uint32_t getSymbolSectionId(SymbolRef Sym) const
bool isSectionCompressed(DataRefImpl Sec) const override
bool isSectionVirtual(DataRefImpl Sec) const override
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override
void getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl< char > &Result) const override
StringRef getFileFormatName() const override
Expected< StringRef > getSymbolName(DataRefImpl Symb) const override
relocation_iterator section_rel_begin(DataRefImpl Sec) const override
uint8_t getBytesInAddress() const override
The number of bytes used to represent an address in this object file format.
WasmObjectFile(MemoryBufferRef Object, Error &Err)
section_iterator section_end() const override
Expected< ArrayRef< uint8_t > > getSectionContents(DataRefImpl Sec) const override
uint64_t getSectionIndex(DataRefImpl Sec) const override
uint32_t getSymbolAlignment(DataRefImpl Symb) const override
uint64_t getSectionSize(DataRefImpl Sec) const override
Triple::ArchType getArch() const override
uint64_t getRelocationType(DataRefImpl Rel) const override
const WasmSection & getWasmSection(const SectionRef &Section) const
Expected< section_iterator > getSymbolSection(DataRefImpl Symb) const override
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override
Expected< SubtargetFeatures > getFeatures() const override
const wasm::WasmObjectHeader & getHeader() const
void moveSectionNext(DataRefImpl &Sec) const override
const wasm::WasmRelocation & getWasmRelocation(const RelocationRef &Ref) const
const WasmSymbol & getWasmSymbol(const DataRefImpl &Symb) const
uint64_t getSectionAddress(DataRefImpl Sec) const override
Expected< uint64_t > getSymbolAddress(DataRefImpl Symb) const override
bool isSectionData(DataRefImpl Sec) const override
Expected< StringRef > getSectionName(DataRefImpl Sec) const override
bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName="")
static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS]
Definition: Wasm.h:348
unsigned getBinding() const
Definition: Wasm.h:85
LLVM_DUMP_METHOD void dump() const
bool isTypeData() const
Definition: Wasm.h:55
const wasm::WasmSymbolInfo & Info
Definition: Wasm.h:44
bool isHidden() const
Definition: Wasm.h:89
void print(raw_ostream &Out) const
bool isDefined() const
Definition: Wasm.h:67
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const uint64_t Version
Definition: InstrProf.h:1083
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
content_iterator< SectionRef > section_iterator
Definition: ObjectFile.h:47
content_iterator< RelocationRef > relocation_iterator
Definition: ObjectFile.h:76
uint32_t read32le(const void *P)
Definition: Endian.h:381
@ WASM_COMDAT_SECTION
Definition: Wasm.h:378
@ WASM_COMDAT_FUNCTION
Definition: Wasm.h:376
@ WASM_COMDAT_DATA
Definition: Wasm.h:375
@ WASM_SEC_CODE
Definition: Wasm.h:252
@ WASM_SEC_MEMORY
Definition: Wasm.h:247
@ WASM_SEC_IMPORT
Definition: Wasm.h:244
@ WASM_SEC_EXPORT
Definition: Wasm.h:249
@ WASM_SEC_DATACOUNT
Definition: Wasm.h:254
@ WASM_SEC_LAST_KNOWN
Definition: Wasm.h:256
@ WASM_SEC_CUSTOM
Definition: Wasm.h:242
@ WASM_SEC_FUNCTION
Definition: Wasm.h:245
@ WASM_SEC_ELEM
Definition: Wasm.h:251
@ WASM_SEC_START
Definition: Wasm.h:250
@ WASM_SEC_TABLE
Definition: Wasm.h:246
@ WASM_SEC_TYPE
Definition: Wasm.h:243
@ WASM_SEC_TAG
Definition: Wasm.h:255
@ WASM_SEC_GLOBAL
Definition: Wasm.h:248
@ WASM_SEC_DATA
Definition: Wasm.h:253
const unsigned WASM_SYMBOL_UNDEFINED
Definition: Wasm.h:409
@ WASM_INIT_FUNCS
Definition: Wasm.h:360
@ WASM_COMDAT_INFO
Definition: Wasm.h:361
@ WASM_SEGMENT_INFO
Definition: Wasm.h:359
@ WASM_SYMBOL_TABLE
Definition: Wasm.h:362
@ WASM_DATA_SEGMENT_IS_PASSIVE
Definition: Wasm.h:331
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
Definition: Wasm.h:332
@ WASM_LIMITS_FLAG_HAS_MAX
Definition: Wasm.h:325
@ WASM_LIMITS_FLAG_IS_64
Definition: Wasm.h:327
@ WASM_DYLINK_NEEDED
Definition: Wasm.h:368
@ WASM_DYLINK_MEM_INFO
Definition: Wasm.h:367
@ WASM_DYLINK_EXPORT_INFO
Definition: Wasm.h:369
@ WASM_DYLINK_IMPORT_INFO
Definition: Wasm.h:370
const unsigned WASM_SYMBOL_BINDING_GLOBAL
Definition: Wasm.h:404
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
Definition: Wasm.h:340
@ WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
Definition: Wasm.h:338
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
Definition: Wasm.h:337
@ WASM_ELEM_SEGMENT_IS_PASSIVE
Definition: Wasm.h:336
const uint32_t WasmMetadataVersion
Definition: Wasm.h:30
const unsigned WASM_SYMBOL_BINDING_WEAK
Definition: Wasm.h:405
const unsigned WASM_SYMBOL_BINDING_LOCAL
Definition: Wasm.h:406
@ WASM_FEATURE_PREFIX_USED
Definition: Wasm.h:344
@ WASM_FEATURE_PREFIX_REQUIRED
Definition: Wasm.h:345
@ WASM_FEATURE_PREFIX_DISALLOWED
Definition: Wasm.h:346
WasmSymbolType
Definition: Wasm.h:382
@ WASM_SYMBOL_TYPE_GLOBAL
Definition: Wasm.h:385
@ WASM_SYMBOL_TYPE_DATA
Definition: Wasm.h:384
@ WASM_SYMBOL_TYPE_TAG
Definition: Wasm.h:387
@ WASM_SYMBOL_TYPE_TABLE
Definition: Wasm.h:388
@ WASM_SYMBOL_TYPE_SECTION
Definition: Wasm.h:386
@ WASM_SYMBOL_TYPE_FUNCTION
Definition: Wasm.h:383
const uint32_t WasmVersion
Definition: Wasm.h:28
@ WASM_NAMES_LOCAL
Definition: Wasm.h:352
@ WASM_NAMES_DATA_SEGMENT
Definition: Wasm.h:354
@ WASM_NAMES_GLOBAL
Definition: Wasm.h:353
@ WASM_NAMES_FUNCTION
Definition: Wasm.h:351
@ WASM_TYPE_FUNCREF
Definition: Wasm.h:266
@ WASM_TYPE_EXTERNREF
Definition: Wasm.h:267
@ WASM_TYPE_FUNC
Definition: Wasm.h:268
const unsigned WASM_SYMBOL_BINDING_MASK
Definition: Wasm.h:401
NameType
Definition: Wasm.h:222
@ WASM_OPCODE_I64_ADD
Definition: Wasm.h:299
@ WASM_OPCODE_I32_SUB
Definition: Wasm.h:297
@ WASM_OPCODE_F64_CONST
Definition: Wasm.h:295
@ WASM_OPCODE_END
Definition: Wasm.h:283
@ WASM_OPCODE_I64_MUL
Definition: Wasm.h:301
@ WASM_OPCODE_REF_NULL
Definition: Wasm.h:302
@ WASM_OPCODE_F32_CONST
Definition: Wasm.h:294
@ WASM_OPCODE_GLOBAL_GET
Definition: Wasm.h:288
@ WASM_OPCODE_I64_SUB
Definition: Wasm.h:300
@ WASM_OPCODE_I32_MUL
Definition: Wasm.h:298
@ WASM_OPCODE_I32_ADD
Definition: Wasm.h:296
@ WASM_OPCODE_I64_CONST
Definition: Wasm.h:293
@ WASM_OPCODE_I32_CONST
Definition: Wasm.h:292
@ WASM_EXTERNAL_TABLE
Definition: Wasm.h:275
@ WASM_EXTERNAL_FUNCTION
Definition: Wasm.h:274
@ WASM_EXTERNAL_TAG
Definition: Wasm.h:278
@ WASM_EXTERNAL_MEMORY
Definition: Wasm.h:276
@ WASM_EXTERNAL_GLOBAL
Definition: Wasm.h:277
llvm::StringRef sectionTypeToString(uint32_t type)
Definition: Wasm.cpp:41
const unsigned WASM_SYMBOL_EXPLICIT_NAME
Definition: Wasm.h:411
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:440
std::string to_string(const T &Value)
Definition: ScopedPrinter.h:85
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a ULEB128 value.
Definition: LEB128.h:128
@ Import
Import information from summary.
int64_t decodeSLEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a SLEB128 value.
Definition: LEB128.h:161
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1246
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
@ Global
Append to llvm.global_dtors.
@ Ref
The access may reference the value stored in memory.
ArrayRef< uint8_t > Content
Definition: Wasm.h:111
std::vector< wasm::WasmRelocation > Relocations
Definition: Wasm.h:112
wasm::WasmDataSegment Data
Definition: Wasm.h:117
uint32_t SectionOffset
Definition: Wasm.h:116
ArrayRef< uint8_t > Content
Definition: Wasm.h:168
WasmInitExpr Offset
Definition: Wasm.h:166
uint32_t MemoryAlignment
Definition: Wasm.h:52
std::vector< StringRef > Needed
Definition: Wasm.h:55
std::vector< WasmDylinkExportInfo > ExportInfo
Definition: Wasm.h:57
std::vector< WasmDylinkImportInfo > ImportInfo
Definition: Wasm.h:56
uint32_t TableAlignment
Definition: Wasm.h:54
WasmInitExpr Offset
Definition: Wasm.h:179
std::vector< uint32_t > Functions
Definition: Wasm.h:180
StringRef Name
Definition: Wasm.h:72
uint32_t Index
Definition: Wasm.h:74
std::optional< StringRef > ExportName
Definition: Wasm.h:155
uint32_t CodeSectionOffset
Definition: Wasm.h:152
StringRef DebugName
Definition: Wasm.h:157
WasmLimits Memory
Definition: Wasm.h:138
StringRef Field
Definition: Wasm.h:132
WasmGlobalType Global
Definition: Wasm.h:136
StringRef Module
Definition: Wasm.h:131
uint32_t SigIndex
Definition: Wasm.h:135
WasmTableType Table
Definition: Wasm.h:137
union llvm::wasm::WasmInitExprMVP::@176 Value
WasmInitExprMVP Inst
Definition: Wasm.h:108
ArrayRef< uint8_t > Body
Definition: Wasm.h:109
std::vector< WasmSymbolInfo > SymbolTable
Definition: Wasm.h:238
std::vector< WasmInitFunc > InitFunctions
Definition: Wasm.h:236
std::vector< StringRef > Comdats
Definition: Wasm.h:237
std::vector< std::pair< std::string, std::string > > SDKs
Definition: Wasm.h:63
std::vector< std::pair< std::string, std::string > > Languages
Definition: Wasm.h:61
std::vector< std::pair< std::string, std::string > > Tools
Definition: Wasm.h:62
SmallVector< ValType, 1 > Returns
Definition: Wasm.h:435
SmallVector< ValType, 4 > Params
Definition: Wasm.h:436
WasmDataReference DataRef
Definition: Wasm.h:218
WasmLimits Limits
Definition: Wasm.h:85
WasmTableType Type
Definition: Wasm.h:90
StringRef SymbolName
Definition: Wasm.h:91
struct llvm::object::DataRefImpl::@339 d