1 //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
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
7 //===----------------------------------------------------------------------===//
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"
14 #include "llvm/ADT/StringSwitch.h"
15 #include "llvm/BinaryFormat/Wasm.h"
16 #include "llvm/Object/Binary.h"
17 #include "llvm/Object/Error.h"
18 #include "llvm/Object/ObjectFile.h"
19 #include "llvm/Object/SymbolicFile.h"
20 #include "llvm/Object/Wasm.h"
21 #include "llvm/Support/Endian.h"
22 #include "llvm/Support/Error.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/Format.h"
25 #include "llvm/Support/LEB128.h"
26 #include "llvm/Support/ScopedPrinter.h"
27 #include "llvm/TargetParser/SubtargetFeature.h"
28 #include "llvm/TargetParser/Triple.h"
35 #define DEBUG_TYPE "wasm-object"
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 switch (getBinding()) {
45 case wasm::WASM_SYMBOL_BINDING_GLOBAL
: Out
<< "global"; break;
46 case wasm::WASM_SYMBOL_BINDING_LOCAL
: Out
<< "local"; break;
47 case wasm::WASM_SYMBOL_BINDING_WEAK
: Out
<< "weak"; break;
56 Out
<< ", ElemIndex=" << Info
.ElementIndex
;
57 } else if (isDefined()) {
58 Out
<< ", Segment=" << Info
.DataRef
.Segment
;
59 Out
<< ", Offset=" << Info
.DataRef
.Offset
;
60 Out
<< ", Size=" << Info
.DataRef
.Size
;
64 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
65 LLVM_DUMP_METHOD
void WasmSymbol::dump() const { print(dbgs()); }
68 Expected
<std::unique_ptr
<WasmObjectFile
>>
69 ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer
) {
70 Error Err
= Error::success();
71 auto ObjectFile
= std::make_unique
<WasmObjectFile
>(Buffer
, Err
);
73 return std::move(Err
);
75 return std::move(ObjectFile
);
78 #define VARINT7_MAX ((1 << 7) - 1)
79 #define VARINT7_MIN (-(1 << 7))
80 #define VARUINT7_MAX (1 << 7)
81 #define VARUINT1_MAX (1)
83 static uint8_t readUint8(WasmObjectFile::ReadContext
&Ctx
) {
84 if (Ctx
.Ptr
== Ctx
.End
)
85 report_fatal_error("EOF while reading uint8");
89 static uint32_t readUint32(WasmObjectFile::ReadContext
&Ctx
) {
90 if (Ctx
.Ptr
+ 4 > Ctx
.End
)
91 report_fatal_error("EOF while reading uint32");
92 uint32_t Result
= support::endian::read32le(Ctx
.Ptr
);
97 static int32_t readFloat32(WasmObjectFile::ReadContext
&Ctx
) {
98 if (Ctx
.Ptr
+ 4 > Ctx
.End
)
99 report_fatal_error("EOF while reading float64");
101 memcpy(&Result
, Ctx
.Ptr
, sizeof(Result
));
102 Ctx
.Ptr
+= sizeof(Result
);
106 static int64_t readFloat64(WasmObjectFile::ReadContext
&Ctx
) {
107 if (Ctx
.Ptr
+ 8 > Ctx
.End
)
108 report_fatal_error("EOF while reading float64");
110 memcpy(&Result
, Ctx
.Ptr
, sizeof(Result
));
111 Ctx
.Ptr
+= sizeof(Result
);
115 static uint64_t readULEB128(WasmObjectFile::ReadContext
&Ctx
) {
117 const char *Error
= nullptr;
118 uint64_t Result
= decodeULEB128(Ctx
.Ptr
, &Count
, Ctx
.End
, &Error
);
120 report_fatal_error(Error
);
125 static StringRef
readString(WasmObjectFile::ReadContext
&Ctx
) {
126 uint32_t StringLen
= readULEB128(Ctx
);
127 if (Ctx
.Ptr
+ StringLen
> Ctx
.End
)
128 report_fatal_error("EOF while reading string");
130 StringRef(reinterpret_cast<const char *>(Ctx
.Ptr
), StringLen
);
131 Ctx
.Ptr
+= StringLen
;
135 static int64_t readLEB128(WasmObjectFile::ReadContext
&Ctx
) {
137 const char *Error
= nullptr;
138 uint64_t Result
= decodeSLEB128(Ctx
.Ptr
, &Count
, Ctx
.End
, &Error
);
140 report_fatal_error(Error
);
145 static uint8_t readVaruint1(WasmObjectFile::ReadContext
&Ctx
) {
146 int64_t Result
= readLEB128(Ctx
);
147 if (Result
> VARUINT1_MAX
|| Result
< 0)
148 report_fatal_error("LEB is outside Varuint1 range");
152 static int32_t readVarint32(WasmObjectFile::ReadContext
&Ctx
) {
153 int64_t Result
= readLEB128(Ctx
);
154 if (Result
> INT32_MAX
|| Result
< INT32_MIN
)
155 report_fatal_error("LEB is outside Varint32 range");
159 static uint32_t readVaruint32(WasmObjectFile::ReadContext
&Ctx
) {
160 uint64_t Result
= readULEB128(Ctx
);
161 if (Result
> UINT32_MAX
)
162 report_fatal_error("LEB is outside Varuint32 range");
166 static int64_t readVarint64(WasmObjectFile::ReadContext
&Ctx
) {
167 return readLEB128(Ctx
);
170 static uint64_t readVaruint64(WasmObjectFile::ReadContext
&Ctx
) {
171 return readULEB128(Ctx
);
174 static uint8_t readOpcode(WasmObjectFile::ReadContext
&Ctx
) {
175 return readUint8(Ctx
);
178 static wasm::ValType
parseValType(WasmObjectFile::ReadContext
&Ctx
,
180 // only directly encoded FUNCREF/EXTERNREF/EXNREF are supported
181 // (not ref null func, ref null extern, or ref null exn)
183 case wasm::WASM_TYPE_I32
:
184 case wasm::WASM_TYPE_I64
:
185 case wasm::WASM_TYPE_F32
:
186 case wasm::WASM_TYPE_F64
:
187 case wasm::WASM_TYPE_V128
:
188 case wasm::WASM_TYPE_FUNCREF
:
189 case wasm::WASM_TYPE_EXTERNREF
:
190 case wasm::WASM_TYPE_EXNREF
:
191 return wasm::ValType(Code
);
193 if (Code
== wasm::WASM_TYPE_NULLABLE
|| Code
== wasm::WASM_TYPE_NONNULLABLE
) {
194 /* Discard HeapType */ readVarint64(Ctx
);
196 return wasm::ValType(wasm::ValType::OTHERREF
);
199 static Error
readInitExpr(wasm::WasmInitExpr
&Expr
,
200 WasmObjectFile::ReadContext
&Ctx
) {
201 auto Start
= Ctx
.Ptr
;
203 Expr
.Extended
= false;
204 Expr
.Inst
.Opcode
= readOpcode(Ctx
);
205 switch (Expr
.Inst
.Opcode
) {
206 case wasm::WASM_OPCODE_I32_CONST
:
207 Expr
.Inst
.Value
.Int32
= readVarint32(Ctx
);
209 case wasm::WASM_OPCODE_I64_CONST
:
210 Expr
.Inst
.Value
.Int64
= readVarint64(Ctx
);
212 case wasm::WASM_OPCODE_F32_CONST
:
213 Expr
.Inst
.Value
.Float32
= readFloat32(Ctx
);
215 case wasm::WASM_OPCODE_F64_CONST
:
216 Expr
.Inst
.Value
.Float64
= readFloat64(Ctx
);
218 case wasm::WASM_OPCODE_GLOBAL_GET
:
219 Expr
.Inst
.Value
.Global
= readULEB128(Ctx
);
221 case wasm::WASM_OPCODE_REF_NULL
: {
222 /* Discard type */ parseValType(Ctx
, readVaruint32(Ctx
));
226 Expr
.Extended
= true;
229 if (!Expr
.Extended
) {
230 uint8_t EndOpcode
= readOpcode(Ctx
);
231 if (EndOpcode
!= wasm::WASM_OPCODE_END
)
232 Expr
.Extended
= true;
238 uint8_t Opcode
= readOpcode(Ctx
);
240 case wasm::WASM_OPCODE_I32_CONST
:
241 case wasm::WASM_OPCODE_GLOBAL_GET
:
242 case wasm::WASM_OPCODE_REF_NULL
:
243 case wasm::WASM_OPCODE_REF_FUNC
:
244 case wasm::WASM_OPCODE_I64_CONST
:
247 case wasm::WASM_OPCODE_F32_CONST
:
250 case wasm::WASM_OPCODE_F64_CONST
:
253 case wasm::WASM_OPCODE_I32_ADD
:
254 case wasm::WASM_OPCODE_I32_SUB
:
255 case wasm::WASM_OPCODE_I32_MUL
:
256 case wasm::WASM_OPCODE_I64_ADD
:
257 case wasm::WASM_OPCODE_I64_SUB
:
258 case wasm::WASM_OPCODE_I64_MUL
:
260 case wasm::WASM_OPCODE_GC_PREFIX
:
262 // The GC opcodes are in a separate (prefixed space). This flat switch
263 // structure works as long as there is no overlap between the GC and
264 // general opcodes used in init exprs.
265 case wasm::WASM_OPCODE_STRUCT_NEW
:
266 case wasm::WASM_OPCODE_STRUCT_NEW_DEFAULT
:
267 case wasm::WASM_OPCODE_ARRAY_NEW
:
268 case wasm::WASM_OPCODE_ARRAY_NEW_DEFAULT
:
269 readULEB128(Ctx
); // heap type index
271 case wasm::WASM_OPCODE_ARRAY_NEW_FIXED
:
272 readULEB128(Ctx
); // heap type index
273 readULEB128(Ctx
); // array size
275 case wasm::WASM_OPCODE_REF_I31
:
277 case wasm::WASM_OPCODE_END
:
278 Expr
.Body
= ArrayRef
<uint8_t>(Start
, Ctx
.Ptr
- Start
);
279 return Error::success();
281 return make_error
<GenericBinaryError
>(
282 Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode
)),
283 object_error::parse_failed
);
288 return Error::success();
291 static wasm::WasmLimits
readLimits(WasmObjectFile::ReadContext
&Ctx
) {
292 wasm::WasmLimits Result
;
293 Result
.Flags
= readVaruint32(Ctx
);
294 Result
.Minimum
= readVaruint64(Ctx
);
295 if (Result
.Flags
& wasm::WASM_LIMITS_FLAG_HAS_MAX
)
296 Result
.Maximum
= readVaruint64(Ctx
);
300 static wasm::WasmTableType
readTableType(WasmObjectFile::ReadContext
&Ctx
) {
301 wasm::WasmTableType TableType
;
302 auto ElemType
= parseValType(Ctx
, readVaruint32(Ctx
));
303 TableType
.ElemType
= ElemType
;
304 TableType
.Limits
= readLimits(Ctx
);
308 static Error
readSection(WasmSection
&Section
, WasmObjectFile::ReadContext
&Ctx
,
309 WasmSectionOrderChecker
&Checker
) {
310 Section
.Type
= readUint8(Ctx
);
311 LLVM_DEBUG(dbgs() << "readSection type=" << Section
.Type
<< "\n");
312 // When reading the section's size, store the size of the LEB used to encode
313 // it. This allows objcopy/strip to reproduce the binary identically.
314 const uint8_t *PreSizePtr
= Ctx
.Ptr
;
315 uint32_t Size
= readVaruint32(Ctx
);
316 Section
.HeaderSecSizeEncodingLen
= Ctx
.Ptr
- PreSizePtr
;
317 Section
.Offset
= Ctx
.Ptr
- Ctx
.Start
;
319 return make_error
<StringError
>("zero length section",
320 object_error::parse_failed
);
321 if (Ctx
.Ptr
+ Size
> Ctx
.End
)
322 return make_error
<StringError
>("section too large",
323 object_error::parse_failed
);
324 if (Section
.Type
== wasm::WASM_SEC_CUSTOM
) {
325 WasmObjectFile::ReadContext SectionCtx
;
326 SectionCtx
.Start
= Ctx
.Ptr
;
327 SectionCtx
.Ptr
= Ctx
.Ptr
;
328 SectionCtx
.End
= Ctx
.Ptr
+ Size
;
330 Section
.Name
= readString(SectionCtx
);
332 uint32_t SectionNameSize
= SectionCtx
.Ptr
- SectionCtx
.Start
;
333 Ctx
.Ptr
+= SectionNameSize
;
334 Size
-= SectionNameSize
;
337 if (!Checker
.isValidSectionOrder(Section
.Type
, Section
.Name
)) {
338 return make_error
<StringError
>("out of order section type: " +
339 llvm::to_string(Section
.Type
),
340 object_error::parse_failed
);
343 Section
.Content
= ArrayRef
<uint8_t>(Ctx
.Ptr
, Size
);
345 return Error::success();
348 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer
, Error
&Err
)
349 : ObjectFile(Binary::ID_Wasm
, Buffer
) {
350 ErrorAsOutParameter
ErrAsOutParam(&Err
);
351 Header
.Magic
= getData().substr(0, 4);
352 if (Header
.Magic
!= StringRef("\0asm", 4)) {
353 Err
= make_error
<StringError
>("invalid magic number",
354 object_error::parse_failed
);
359 Ctx
.Start
= getData().bytes_begin();
360 Ctx
.Ptr
= Ctx
.Start
+ 4;
361 Ctx
.End
= Ctx
.Start
+ getData().size();
363 if (Ctx
.Ptr
+ 4 > Ctx
.End
) {
364 Err
= make_error
<StringError
>("missing version number",
365 object_error::parse_failed
);
369 Header
.Version
= readUint32(Ctx
);
370 if (Header
.Version
!= wasm::WasmVersion
) {
371 Err
= make_error
<StringError
>("invalid version number: " +
372 Twine(Header
.Version
),
373 object_error::parse_failed
);
377 WasmSectionOrderChecker Checker
;
378 while (Ctx
.Ptr
< Ctx
.End
) {
380 if ((Err
= readSection(Sec
, Ctx
, Checker
)))
382 if ((Err
= parseSection(Sec
)))
385 Sections
.push_back(Sec
);
389 Error
WasmObjectFile::parseSection(WasmSection
&Sec
) {
391 Ctx
.Start
= Sec
.Content
.data();
392 Ctx
.End
= Ctx
.Start
+ Sec
.Content
.size();
395 case wasm::WASM_SEC_CUSTOM
:
396 return parseCustomSection(Sec
, Ctx
);
397 case wasm::WASM_SEC_TYPE
:
398 return parseTypeSection(Ctx
);
399 case wasm::WASM_SEC_IMPORT
:
400 return parseImportSection(Ctx
);
401 case wasm::WASM_SEC_FUNCTION
:
402 return parseFunctionSection(Ctx
);
403 case wasm::WASM_SEC_TABLE
:
404 return parseTableSection(Ctx
);
405 case wasm::WASM_SEC_MEMORY
:
406 return parseMemorySection(Ctx
);
407 case wasm::WASM_SEC_TAG
:
408 return parseTagSection(Ctx
);
409 case wasm::WASM_SEC_GLOBAL
:
410 return parseGlobalSection(Ctx
);
411 case wasm::WASM_SEC_EXPORT
:
412 return parseExportSection(Ctx
);
413 case wasm::WASM_SEC_START
:
414 return parseStartSection(Ctx
);
415 case wasm::WASM_SEC_ELEM
:
416 return parseElemSection(Ctx
);
417 case wasm::WASM_SEC_CODE
:
418 return parseCodeSection(Ctx
);
419 case wasm::WASM_SEC_DATA
:
420 return parseDataSection(Ctx
);
421 case wasm::WASM_SEC_DATACOUNT
:
422 return parseDataCountSection(Ctx
);
424 return make_error
<GenericBinaryError
>(
425 "invalid section type: " + Twine(Sec
.Type
), object_error::parse_failed
);
429 Error
WasmObjectFile::parseDylinkSection(ReadContext
&Ctx
) {
430 // Legacy "dylink" section support.
431 // See parseDylink0Section for the current "dylink.0" section parsing.
432 HasDylinkSection
= true;
433 DylinkInfo
.MemorySize
= readVaruint32(Ctx
);
434 DylinkInfo
.MemoryAlignment
= readVaruint32(Ctx
);
435 DylinkInfo
.TableSize
= readVaruint32(Ctx
);
436 DylinkInfo
.TableAlignment
= readVaruint32(Ctx
);
437 uint32_t Count
= readVaruint32(Ctx
);
439 DylinkInfo
.Needed
.push_back(readString(Ctx
));
442 if (Ctx
.Ptr
!= Ctx
.End
)
443 return make_error
<GenericBinaryError
>("dylink section ended prematurely",
444 object_error::parse_failed
);
445 return Error::success();
448 Error
WasmObjectFile::parseDylink0Section(ReadContext
&Ctx
) {
450 // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
451 HasDylinkSection
= true;
453 const uint8_t *OrigEnd
= Ctx
.End
;
454 while (Ctx
.Ptr
< OrigEnd
) {
456 uint8_t Type
= readUint8(Ctx
);
457 uint32_t Size
= readVaruint32(Ctx
);
458 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type
) << " size=" << Size
460 Ctx
.End
= Ctx
.Ptr
+ Size
;
463 case wasm::WASM_DYLINK_MEM_INFO
:
464 DylinkInfo
.MemorySize
= readVaruint32(Ctx
);
465 DylinkInfo
.MemoryAlignment
= readVaruint32(Ctx
);
466 DylinkInfo
.TableSize
= readVaruint32(Ctx
);
467 DylinkInfo
.TableAlignment
= readVaruint32(Ctx
);
469 case wasm::WASM_DYLINK_NEEDED
:
470 Count
= readVaruint32(Ctx
);
472 DylinkInfo
.Needed
.push_back(readString(Ctx
));
475 case wasm::WASM_DYLINK_EXPORT_INFO
: {
476 uint32_t Count
= readVaruint32(Ctx
);
478 DylinkInfo
.ExportInfo
.push_back({readString(Ctx
), readVaruint32(Ctx
)});
482 case wasm::WASM_DYLINK_IMPORT_INFO
: {
483 uint32_t Count
= readVaruint32(Ctx
);
485 DylinkInfo
.ImportInfo
.push_back(
486 {readString(Ctx
), readString(Ctx
), readVaruint32(Ctx
)});
491 LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type
<< "\n");
495 if (Ctx
.Ptr
!= Ctx
.End
) {
496 return make_error
<GenericBinaryError
>(
497 "dylink.0 sub-section ended prematurely", object_error::parse_failed
);
501 if (Ctx
.Ptr
!= Ctx
.End
)
502 return make_error
<GenericBinaryError
>("dylink.0 section ended prematurely",
503 object_error::parse_failed
);
504 return Error::success();
507 Error
WasmObjectFile::parseNameSection(ReadContext
&Ctx
) {
508 llvm::DenseSet
<uint64_t> SeenFunctions
;
509 llvm::DenseSet
<uint64_t> SeenGlobals
;
510 llvm::DenseSet
<uint64_t> SeenSegments
;
512 // If we have linking section (symbol table) or if we are parsing a DSO
513 // then we don't use the name section for symbol information.
514 bool PopulateSymbolTable
= !HasLinkingSection
&& !HasDylinkSection
;
516 // If we are using the name section for symbol information then it will
517 // supersede any symbols created by the export section.
518 if (PopulateSymbolTable
)
521 while (Ctx
.Ptr
< Ctx
.End
) {
522 uint8_t Type
= readUint8(Ctx
);
523 uint32_t Size
= readVaruint32(Ctx
);
524 const uint8_t *SubSectionEnd
= Ctx
.Ptr
+ Size
;
527 case wasm::WASM_NAMES_FUNCTION
:
528 case wasm::WASM_NAMES_GLOBAL
:
529 case wasm::WASM_NAMES_DATA_SEGMENT
: {
530 uint32_t Count
= readVaruint32(Ctx
);
532 uint32_t Index
= readVaruint32(Ctx
);
533 StringRef Name
= readString(Ctx
);
534 wasm::NameType nameType
= wasm::NameType::FUNCTION
;
535 wasm::WasmSymbolInfo Info
{Name
,
536 /*Kind */ wasm::WASM_SYMBOL_TYPE_FUNCTION
,
538 /* ImportModule */ std::nullopt
,
539 /* ImportName */ std::nullopt
,
540 /* ExportName */ std::nullopt
,
541 {/* ElementIndex */ Index
}};
542 const wasm::WasmSignature
*Signature
= nullptr;
543 const wasm::WasmGlobalType
*GlobalType
= nullptr;
544 const wasm::WasmTableType
*TableType
= nullptr;
545 if (Type
== wasm::WASM_NAMES_FUNCTION
) {
546 if (!SeenFunctions
.insert(Index
).second
)
547 return make_error
<GenericBinaryError
>(
548 "function named more than once", object_error::parse_failed
);
549 if (!isValidFunctionIndex(Index
) || Name
.empty())
550 return make_error
<GenericBinaryError
>("invalid function name entry",
551 object_error::parse_failed
);
553 if (isDefinedFunctionIndex(Index
)) {
554 wasm::WasmFunction
&F
= getDefinedFunction(Index
);
556 Signature
= &Signatures
[F
.SigIndex
];
558 Info
.ExportName
= F
.ExportName
;
559 Info
.Flags
|= wasm::WASM_SYMBOL_BINDING_GLOBAL
;
561 Info
.Flags
|= wasm::WASM_SYMBOL_BINDING_LOCAL
;
564 Info
.Flags
|= wasm::WASM_SYMBOL_UNDEFINED
;
566 } else if (Type
== wasm::WASM_NAMES_GLOBAL
) {
567 if (!SeenGlobals
.insert(Index
).second
)
568 return make_error
<GenericBinaryError
>("global named more than once",
569 object_error::parse_failed
);
570 if (!isValidGlobalIndex(Index
) || Name
.empty())
571 return make_error
<GenericBinaryError
>("invalid global name entry",
572 object_error::parse_failed
);
573 nameType
= wasm::NameType::GLOBAL
;
574 Info
.Kind
= wasm::WASM_SYMBOL_TYPE_GLOBAL
;
575 if (isDefinedGlobalIndex(Index
)) {
576 GlobalType
= &getDefinedGlobal(Index
).Type
;
578 Info
.Flags
|= wasm::WASM_SYMBOL_UNDEFINED
;
581 if (!SeenSegments
.insert(Index
).second
)
582 return make_error
<GenericBinaryError
>(
583 "segment named more than once", object_error::parse_failed
);
584 if (Index
> DataSegments
.size())
585 return make_error
<GenericBinaryError
>("invalid data segment name entry",
586 object_error::parse_failed
);
587 nameType
= wasm::NameType::DATA_SEGMENT
;
588 Info
.Kind
= wasm::WASM_SYMBOL_TYPE_DATA
;
589 Info
.Flags
|= wasm::WASM_SYMBOL_BINDING_LOCAL
;
590 assert(Index
< DataSegments
.size());
591 Info
.DataRef
= wasm::WasmDataReference
{
592 Index
, 0, DataSegments
[Index
].Data
.Content
.size()};
594 DebugNames
.push_back(wasm::WasmDebugName
{nameType
, Index
, Name
});
595 if (PopulateSymbolTable
)
596 Symbols
.emplace_back(Info
, GlobalType
, TableType
, Signature
);
600 // Ignore local names for now
601 case wasm::WASM_NAMES_LOCAL
:
606 if (Ctx
.Ptr
!= SubSectionEnd
)
607 return make_error
<GenericBinaryError
>(
608 "name sub-section ended prematurely", object_error::parse_failed
);
611 if (Ctx
.Ptr
!= Ctx
.End
)
612 return make_error
<GenericBinaryError
>("name section ended prematurely",
613 object_error::parse_failed
);
614 return Error::success();
617 Error
WasmObjectFile::parseLinkingSection(ReadContext
&Ctx
) {
618 HasLinkingSection
= true;
620 LinkingData
.Version
= readVaruint32(Ctx
);
621 if (LinkingData
.Version
!= wasm::WasmMetadataVersion
) {
622 return make_error
<GenericBinaryError
>(
623 "unexpected metadata version: " + Twine(LinkingData
.Version
) +
624 " (Expected: " + Twine(wasm::WasmMetadataVersion
) + ")",
625 object_error::parse_failed
);
628 const uint8_t *OrigEnd
= Ctx
.End
;
629 while (Ctx
.Ptr
< OrigEnd
) {
631 uint8_t Type
= readUint8(Ctx
);
632 uint32_t Size
= readVaruint32(Ctx
);
633 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type
) << " size=" << Size
635 Ctx
.End
= Ctx
.Ptr
+ Size
;
637 case wasm::WASM_SYMBOL_TABLE
:
638 if (Error Err
= parseLinkingSectionSymtab(Ctx
))
641 case wasm::WASM_SEGMENT_INFO
: {
642 uint32_t Count
= readVaruint32(Ctx
);
643 if (Count
> DataSegments
.size())
644 return make_error
<GenericBinaryError
>("too many segment names",
645 object_error::parse_failed
);
646 for (uint32_t I
= 0; I
< Count
; I
++) {
647 DataSegments
[I
].Data
.Name
= readString(Ctx
);
648 DataSegments
[I
].Data
.Alignment
= readVaruint32(Ctx
);
649 DataSegments
[I
].Data
.LinkingFlags
= readVaruint32(Ctx
);
653 case wasm::WASM_INIT_FUNCS
: {
654 uint32_t Count
= readVaruint32(Ctx
);
655 LinkingData
.InitFunctions
.reserve(Count
);
656 for (uint32_t I
= 0; I
< Count
; I
++) {
657 wasm::WasmInitFunc Init
;
658 Init
.Priority
= readVaruint32(Ctx
);
659 Init
.Symbol
= readVaruint32(Ctx
);
660 if (!isValidFunctionSymbol(Init
.Symbol
))
661 return make_error
<GenericBinaryError
>("invalid function symbol: " +
663 object_error::parse_failed
);
664 LinkingData
.InitFunctions
.emplace_back(Init
);
668 case wasm::WASM_COMDAT_INFO
:
669 if (Error Err
= parseLinkingSectionComdat(Ctx
))
676 if (Ctx
.Ptr
!= Ctx
.End
)
677 return make_error
<GenericBinaryError
>(
678 "linking sub-section ended prematurely", object_error::parse_failed
);
680 if (Ctx
.Ptr
!= OrigEnd
)
681 return make_error
<GenericBinaryError
>("linking section ended prematurely",
682 object_error::parse_failed
);
683 return Error::success();
686 Error
WasmObjectFile::parseLinkingSectionSymtab(ReadContext
&Ctx
) {
687 uint32_t Count
= readVaruint32(Ctx
);
688 // Clear out any symbol information that was derived from the exports
691 Symbols
.reserve(Count
);
692 StringSet
<> SymbolNames
;
694 std::vector
<wasm::WasmImport
*> ImportedGlobals
;
695 std::vector
<wasm::WasmImport
*> ImportedFunctions
;
696 std::vector
<wasm::WasmImport
*> ImportedTags
;
697 std::vector
<wasm::WasmImport
*> ImportedTables
;
698 ImportedGlobals
.reserve(Imports
.size());
699 ImportedFunctions
.reserve(Imports
.size());
700 ImportedTags
.reserve(Imports
.size());
701 ImportedTables
.reserve(Imports
.size());
702 for (auto &I
: Imports
) {
703 if (I
.Kind
== wasm::WASM_EXTERNAL_FUNCTION
)
704 ImportedFunctions
.emplace_back(&I
);
705 else if (I
.Kind
== wasm::WASM_EXTERNAL_GLOBAL
)
706 ImportedGlobals
.emplace_back(&I
);
707 else if (I
.Kind
== wasm::WASM_EXTERNAL_TAG
)
708 ImportedTags
.emplace_back(&I
);
709 else if (I
.Kind
== wasm::WASM_EXTERNAL_TABLE
)
710 ImportedTables
.emplace_back(&I
);
714 wasm::WasmSymbolInfo Info
;
715 const wasm::WasmSignature
*Signature
= nullptr;
716 const wasm::WasmGlobalType
*GlobalType
= nullptr;
717 const wasm::WasmTableType
*TableType
= nullptr;
719 Info
.Kind
= readUint8(Ctx
);
720 Info
.Flags
= readVaruint32(Ctx
);
721 bool IsDefined
= (Info
.Flags
& wasm::WASM_SYMBOL_UNDEFINED
) == 0;
724 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
725 Info
.ElementIndex
= readVaruint32(Ctx
);
726 if (!isValidFunctionIndex(Info
.ElementIndex
) ||
727 IsDefined
!= isDefinedFunctionIndex(Info
.ElementIndex
))
728 return make_error
<GenericBinaryError
>("invalid function symbol index",
729 object_error::parse_failed
);
731 Info
.Name
= readString(Ctx
);
732 unsigned FuncIndex
= Info
.ElementIndex
- NumImportedFunctions
;
733 wasm::WasmFunction
&Function
= Functions
[FuncIndex
];
734 Signature
= &Signatures
[Function
.SigIndex
];
735 if (Function
.SymbolName
.empty())
736 Function
.SymbolName
= Info
.Name
;
738 wasm::WasmImport
&Import
= *ImportedFunctions
[Info
.ElementIndex
];
739 if ((Info
.Flags
& wasm::WASM_SYMBOL_EXPLICIT_NAME
) != 0) {
740 Info
.Name
= readString(Ctx
);
741 Info
.ImportName
= Import
.Field
;
743 Info
.Name
= Import
.Field
;
745 Signature
= &Signatures
[Import
.SigIndex
];
746 Info
.ImportModule
= Import
.Module
;
750 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
751 Info
.ElementIndex
= readVaruint32(Ctx
);
752 if (!isValidGlobalIndex(Info
.ElementIndex
) ||
753 IsDefined
!= isDefinedGlobalIndex(Info
.ElementIndex
))
754 return make_error
<GenericBinaryError
>("invalid global symbol index",
755 object_error::parse_failed
);
756 if (!IsDefined
&& (Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) ==
757 wasm::WASM_SYMBOL_BINDING_WEAK
)
758 return make_error
<GenericBinaryError
>("undefined weak global symbol",
759 object_error::parse_failed
);
761 Info
.Name
= readString(Ctx
);
762 unsigned GlobalIndex
= Info
.ElementIndex
- NumImportedGlobals
;
763 wasm::WasmGlobal
&Global
= Globals
[GlobalIndex
];
764 GlobalType
= &Global
.Type
;
765 if (Global
.SymbolName
.empty())
766 Global
.SymbolName
= Info
.Name
;
768 wasm::WasmImport
&Import
= *ImportedGlobals
[Info
.ElementIndex
];
769 if ((Info
.Flags
& wasm::WASM_SYMBOL_EXPLICIT_NAME
) != 0) {
770 Info
.Name
= readString(Ctx
);
771 Info
.ImportName
= Import
.Field
;
773 Info
.Name
= Import
.Field
;
775 GlobalType
= &Import
.Global
;
776 Info
.ImportModule
= Import
.Module
;
780 case wasm::WASM_SYMBOL_TYPE_TABLE
:
781 Info
.ElementIndex
= readVaruint32(Ctx
);
782 if (!isValidTableNumber(Info
.ElementIndex
) ||
783 IsDefined
!= isDefinedTableNumber(Info
.ElementIndex
))
784 return make_error
<GenericBinaryError
>("invalid table symbol index",
785 object_error::parse_failed
);
786 if (!IsDefined
&& (Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) ==
787 wasm::WASM_SYMBOL_BINDING_WEAK
)
788 return make_error
<GenericBinaryError
>("undefined weak table symbol",
789 object_error::parse_failed
);
791 Info
.Name
= readString(Ctx
);
792 unsigned TableNumber
= Info
.ElementIndex
- NumImportedTables
;
793 wasm::WasmTable
&Table
= Tables
[TableNumber
];
794 TableType
= &Table
.Type
;
795 if (Table
.SymbolName
.empty())
796 Table
.SymbolName
= Info
.Name
;
798 wasm::WasmImport
&Import
= *ImportedTables
[Info
.ElementIndex
];
799 if ((Info
.Flags
& wasm::WASM_SYMBOL_EXPLICIT_NAME
) != 0) {
800 Info
.Name
= readString(Ctx
);
801 Info
.ImportName
= Import
.Field
;
803 Info
.Name
= Import
.Field
;
805 TableType
= &Import
.Table
;
806 Info
.ImportModule
= Import
.Module
;
810 case wasm::WASM_SYMBOL_TYPE_DATA
:
811 Info
.Name
= readString(Ctx
);
813 auto Index
= readVaruint32(Ctx
);
814 auto Offset
= readVaruint64(Ctx
);
815 auto Size
= readVaruint64(Ctx
);
816 if (!(Info
.Flags
& wasm::WASM_SYMBOL_ABSOLUTE
)) {
817 if (static_cast<size_t>(Index
) >= DataSegments
.size())
818 return make_error
<GenericBinaryError
>(
819 "invalid data segment index: " + Twine(Index
),
820 object_error::parse_failed
);
821 size_t SegmentSize
= DataSegments
[Index
].Data
.Content
.size();
822 if (Offset
> SegmentSize
)
823 return make_error
<GenericBinaryError
>(
824 "invalid data symbol offset: `" + Info
.Name
+
825 "` (offset: " + Twine(Offset
) +
826 " segment size: " + Twine(SegmentSize
) + ")",
827 object_error::parse_failed
);
829 Info
.DataRef
= wasm::WasmDataReference
{Index
, Offset
, Size
};
833 case wasm::WASM_SYMBOL_TYPE_SECTION
: {
834 if ((Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) !=
835 wasm::WASM_SYMBOL_BINDING_LOCAL
)
836 return make_error
<GenericBinaryError
>(
837 "section symbols must have local binding",
838 object_error::parse_failed
);
839 Info
.ElementIndex
= readVaruint32(Ctx
);
840 // Use somewhat unique section name as symbol name.
841 StringRef SectionName
= Sections
[Info
.ElementIndex
].Name
;
842 Info
.Name
= SectionName
;
846 case wasm::WASM_SYMBOL_TYPE_TAG
: {
847 Info
.ElementIndex
= readVaruint32(Ctx
);
848 if (!isValidTagIndex(Info
.ElementIndex
) ||
849 IsDefined
!= isDefinedTagIndex(Info
.ElementIndex
))
850 return make_error
<GenericBinaryError
>("invalid tag symbol index",
851 object_error::parse_failed
);
852 if (!IsDefined
&& (Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) ==
853 wasm::WASM_SYMBOL_BINDING_WEAK
)
854 return make_error
<GenericBinaryError
>("undefined weak global symbol",
855 object_error::parse_failed
);
857 Info
.Name
= readString(Ctx
);
858 unsigned TagIndex
= Info
.ElementIndex
- NumImportedTags
;
859 wasm::WasmTag
&Tag
= Tags
[TagIndex
];
860 Signature
= &Signatures
[Tag
.SigIndex
];
861 if (Tag
.SymbolName
.empty())
862 Tag
.SymbolName
= Info
.Name
;
865 wasm::WasmImport
&Import
= *ImportedTags
[Info
.ElementIndex
];
866 if ((Info
.Flags
& wasm::WASM_SYMBOL_EXPLICIT_NAME
) != 0) {
867 Info
.Name
= readString(Ctx
);
868 Info
.ImportName
= Import
.Field
;
870 Info
.Name
= Import
.Field
;
872 Signature
= &Signatures
[Import
.SigIndex
];
873 Info
.ImportModule
= Import
.Module
;
879 return make_error
<GenericBinaryError
>("invalid symbol type: " +
880 Twine(unsigned(Info
.Kind
)),
881 object_error::parse_failed
);
884 if ((Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) !=
885 wasm::WASM_SYMBOL_BINDING_LOCAL
&&
886 !SymbolNames
.insert(Info
.Name
).second
)
887 return make_error
<GenericBinaryError
>("duplicate symbol name " +
889 object_error::parse_failed
);
890 Symbols
.emplace_back(Info
, GlobalType
, TableType
, Signature
);
891 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols
.back() << "\n");
894 return Error::success();
897 Error
WasmObjectFile::parseLinkingSectionComdat(ReadContext
&Ctx
) {
898 uint32_t ComdatCount
= readVaruint32(Ctx
);
899 StringSet
<> ComdatSet
;
900 for (unsigned ComdatIndex
= 0; ComdatIndex
< ComdatCount
; ++ComdatIndex
) {
901 StringRef Name
= readString(Ctx
);
902 if (Name
.empty() || !ComdatSet
.insert(Name
).second
)
903 return make_error
<GenericBinaryError
>("bad/duplicate COMDAT name " +
905 object_error::parse_failed
);
906 LinkingData
.Comdats
.emplace_back(Name
);
907 uint32_t Flags
= readVaruint32(Ctx
);
909 return make_error
<GenericBinaryError
>("unsupported COMDAT flags",
910 object_error::parse_failed
);
912 uint32_t EntryCount
= readVaruint32(Ctx
);
913 while (EntryCount
--) {
914 unsigned Kind
= readVaruint32(Ctx
);
915 unsigned Index
= readVaruint32(Ctx
);
918 return make_error
<GenericBinaryError
>("invalid COMDAT entry type",
919 object_error::parse_failed
);
920 case wasm::WASM_COMDAT_DATA
:
921 if (Index
>= DataSegments
.size())
922 return make_error
<GenericBinaryError
>(
923 "COMDAT data index out of range", object_error::parse_failed
);
924 if (DataSegments
[Index
].Data
.Comdat
!= UINT32_MAX
)
925 return make_error
<GenericBinaryError
>("data segment in two COMDATs",
926 object_error::parse_failed
);
927 DataSegments
[Index
].Data
.Comdat
= ComdatIndex
;
929 case wasm::WASM_COMDAT_FUNCTION
:
930 if (!isDefinedFunctionIndex(Index
))
931 return make_error
<GenericBinaryError
>(
932 "COMDAT function index out of range", object_error::parse_failed
);
933 if (getDefinedFunction(Index
).Comdat
!= UINT32_MAX
)
934 return make_error
<GenericBinaryError
>("function in two COMDATs",
935 object_error::parse_failed
);
936 getDefinedFunction(Index
).Comdat
= ComdatIndex
;
938 case wasm::WASM_COMDAT_SECTION
:
939 if (Index
>= Sections
.size())
940 return make_error
<GenericBinaryError
>(
941 "COMDAT section index out of range", object_error::parse_failed
);
942 if (Sections
[Index
].Type
!= wasm::WASM_SEC_CUSTOM
)
943 return make_error
<GenericBinaryError
>(
944 "non-custom section in a COMDAT", object_error::parse_failed
);
945 Sections
[Index
].Comdat
= ComdatIndex
;
950 return Error::success();
953 Error
WasmObjectFile::parseProducersSection(ReadContext
&Ctx
) {
954 llvm::SmallSet
<StringRef
, 3> FieldsSeen
;
955 uint32_t Fields
= readVaruint32(Ctx
);
956 for (size_t I
= 0; I
< Fields
; ++I
) {
957 StringRef FieldName
= readString(Ctx
);
958 if (!FieldsSeen
.insert(FieldName
).second
)
959 return make_error
<GenericBinaryError
>(
960 "producers section does not have unique fields",
961 object_error::parse_failed
);
962 std::vector
<std::pair
<std::string
, std::string
>> *ProducerVec
= nullptr;
963 if (FieldName
== "language") {
964 ProducerVec
= &ProducerInfo
.Languages
;
965 } else if (FieldName
== "processed-by") {
966 ProducerVec
= &ProducerInfo
.Tools
;
967 } else if (FieldName
== "sdk") {
968 ProducerVec
= &ProducerInfo
.SDKs
;
970 return make_error
<GenericBinaryError
>(
971 "producers section field is not named one of language, processed-by, "
973 object_error::parse_failed
);
975 uint32_t ValueCount
= readVaruint32(Ctx
);
976 llvm::SmallSet
<StringRef
, 8> ProducersSeen
;
977 for (size_t J
= 0; J
< ValueCount
; ++J
) {
978 StringRef Name
= readString(Ctx
);
979 StringRef Version
= readString(Ctx
);
980 if (!ProducersSeen
.insert(Name
).second
) {
981 return make_error
<GenericBinaryError
>(
982 "producers section contains repeated producer",
983 object_error::parse_failed
);
985 ProducerVec
->emplace_back(std::string(Name
), std::string(Version
));
988 if (Ctx
.Ptr
!= Ctx
.End
)
989 return make_error
<GenericBinaryError
>("producers section ended prematurely",
990 object_error::parse_failed
);
991 return Error::success();
994 Error
WasmObjectFile::parseTargetFeaturesSection(ReadContext
&Ctx
) {
995 llvm::SmallSet
<std::string
, 8> FeaturesSeen
;
996 uint32_t FeatureCount
= readVaruint32(Ctx
);
997 for (size_t I
= 0; I
< FeatureCount
; ++I
) {
998 wasm::WasmFeatureEntry Feature
;
999 Feature
.Prefix
= readUint8(Ctx
);
1000 switch (Feature
.Prefix
) {
1001 case wasm::WASM_FEATURE_PREFIX_USED
:
1002 case wasm::WASM_FEATURE_PREFIX_REQUIRED
:
1003 case wasm::WASM_FEATURE_PREFIX_DISALLOWED
:
1006 return make_error
<GenericBinaryError
>("unknown feature policy prefix",
1007 object_error::parse_failed
);
1009 Feature
.Name
= std::string(readString(Ctx
));
1010 if (!FeaturesSeen
.insert(Feature
.Name
).second
)
1011 return make_error
<GenericBinaryError
>(
1012 "target features section contains repeated feature \"" +
1013 Feature
.Name
+ "\"",
1014 object_error::parse_failed
);
1015 TargetFeatures
.push_back(Feature
);
1017 if (Ctx
.Ptr
!= Ctx
.End
)
1018 return make_error
<GenericBinaryError
>(
1019 "target features section ended prematurely",
1020 object_error::parse_failed
);
1021 return Error::success();
1024 Error
WasmObjectFile::parseRelocSection(StringRef Name
, ReadContext
&Ctx
) {
1025 uint32_t SectionIndex
= readVaruint32(Ctx
);
1026 if (SectionIndex
>= Sections
.size())
1027 return make_error
<GenericBinaryError
>("invalid section index",
1028 object_error::parse_failed
);
1029 WasmSection
&Section
= Sections
[SectionIndex
];
1030 uint32_t RelocCount
= readVaruint32(Ctx
);
1031 uint32_t EndOffset
= Section
.Content
.size();
1032 uint32_t PreviousOffset
= 0;
1033 while (RelocCount
--) {
1034 wasm::WasmRelocation Reloc
= {};
1035 uint32_t type
= readVaruint32(Ctx
);
1037 Reloc
.Offset
= readVaruint32(Ctx
);
1038 if (Reloc
.Offset
< PreviousOffset
)
1039 return make_error
<GenericBinaryError
>("relocations not in offset order",
1040 object_error::parse_failed
);
1042 auto badReloc
= [&](StringRef msg
) {
1043 return make_error
<GenericBinaryError
>(
1044 msg
+ ": " + Twine(Symbols
[Reloc
.Index
].Info
.Name
),
1045 object_error::parse_failed
);
1048 PreviousOffset
= Reloc
.Offset
;
1049 Reloc
.Index
= readVaruint32(Ctx
);
1051 case wasm::R_WASM_FUNCTION_INDEX_LEB
:
1052 case wasm::R_WASM_FUNCTION_INDEX_I32
:
1053 case wasm::R_WASM_TABLE_INDEX_SLEB
:
1054 case wasm::R_WASM_TABLE_INDEX_SLEB64
:
1055 case wasm::R_WASM_TABLE_INDEX_I32
:
1056 case wasm::R_WASM_TABLE_INDEX_I64
:
1057 case wasm::R_WASM_TABLE_INDEX_REL_SLEB
:
1058 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64
:
1059 if (!isValidFunctionSymbol(Reloc
.Index
))
1060 return badReloc("invalid function relocation");
1062 case wasm::R_WASM_TABLE_NUMBER_LEB
:
1063 if (!isValidTableSymbol(Reloc
.Index
))
1064 return badReloc("invalid table relocation");
1066 case wasm::R_WASM_TYPE_INDEX_LEB
:
1067 if (Reloc
.Index
>= Signatures
.size())
1068 return badReloc("invalid relocation type index");
1070 case wasm::R_WASM_GLOBAL_INDEX_LEB
:
1071 // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
1072 // symbols to refer to their GOT entries.
1073 if (!isValidGlobalSymbol(Reloc
.Index
) &&
1074 !isValidDataSymbol(Reloc
.Index
) &&
1075 !isValidFunctionSymbol(Reloc
.Index
))
1076 return badReloc("invalid global relocation");
1078 case wasm::R_WASM_GLOBAL_INDEX_I32
:
1079 if (!isValidGlobalSymbol(Reloc
.Index
))
1080 return badReloc("invalid global relocation");
1082 case wasm::R_WASM_TAG_INDEX_LEB
:
1083 if (!isValidTagSymbol(Reloc
.Index
))
1084 return badReloc("invalid tag relocation");
1086 case wasm::R_WASM_MEMORY_ADDR_LEB
:
1087 case wasm::R_WASM_MEMORY_ADDR_SLEB
:
1088 case wasm::R_WASM_MEMORY_ADDR_I32
:
1089 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB
:
1090 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB
:
1091 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32
:
1092 if (!isValidDataSymbol(Reloc
.Index
))
1093 return badReloc("invalid data relocation");
1094 Reloc
.Addend
= readVarint32(Ctx
);
1096 case wasm::R_WASM_MEMORY_ADDR_LEB64
:
1097 case wasm::R_WASM_MEMORY_ADDR_SLEB64
:
1098 case wasm::R_WASM_MEMORY_ADDR_I64
:
1099 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64
:
1100 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64
:
1101 if (!isValidDataSymbol(Reloc
.Index
))
1102 return badReloc("invalid data relocation");
1103 Reloc
.Addend
= readVarint64(Ctx
);
1105 case wasm::R_WASM_FUNCTION_OFFSET_I32
:
1106 if (!isValidFunctionSymbol(Reloc
.Index
))
1107 return badReloc("invalid function relocation");
1108 Reloc
.Addend
= readVarint32(Ctx
);
1110 case wasm::R_WASM_FUNCTION_OFFSET_I64
:
1111 if (!isValidFunctionSymbol(Reloc
.Index
))
1112 return badReloc("invalid function relocation");
1113 Reloc
.Addend
= readVarint64(Ctx
);
1115 case wasm::R_WASM_SECTION_OFFSET_I32
:
1116 if (!isValidSectionSymbol(Reloc
.Index
))
1117 return badReloc("invalid section relocation");
1118 Reloc
.Addend
= readVarint32(Ctx
);
1121 return make_error
<GenericBinaryError
>("invalid relocation type: " +
1123 object_error::parse_failed
);
1126 // Relocations must fit inside the section, and must appear in order. They
1127 // also shouldn't overlap a function/element boundary, but we don't bother
1130 if (Reloc
.Type
== wasm::R_WASM_MEMORY_ADDR_LEB64
||
1131 Reloc
.Type
== wasm::R_WASM_MEMORY_ADDR_SLEB64
||
1132 Reloc
.Type
== wasm::R_WASM_MEMORY_ADDR_REL_SLEB64
)
1134 if (Reloc
.Type
== wasm::R_WASM_TABLE_INDEX_I32
||
1135 Reloc
.Type
== wasm::R_WASM_MEMORY_ADDR_I32
||
1136 Reloc
.Type
== wasm::R_WASM_MEMORY_ADDR_LOCREL_I32
||
1137 Reloc
.Type
== wasm::R_WASM_SECTION_OFFSET_I32
||
1138 Reloc
.Type
== wasm::R_WASM_FUNCTION_OFFSET_I32
||
1139 Reloc
.Type
== wasm::R_WASM_FUNCTION_INDEX_I32
||
1140 Reloc
.Type
== wasm::R_WASM_GLOBAL_INDEX_I32
)
1142 if (Reloc
.Type
== wasm::R_WASM_TABLE_INDEX_I64
||
1143 Reloc
.Type
== wasm::R_WASM_MEMORY_ADDR_I64
||
1144 Reloc
.Type
== wasm::R_WASM_FUNCTION_OFFSET_I64
)
1146 if (Reloc
.Offset
+ Size
> EndOffset
)
1147 return make_error
<GenericBinaryError
>("invalid relocation offset",
1148 object_error::parse_failed
);
1150 Section
.Relocations
.push_back(Reloc
);
1152 if (Ctx
.Ptr
!= Ctx
.End
)
1153 return make_error
<GenericBinaryError
>("reloc section ended prematurely",
1154 object_error::parse_failed
);
1155 return Error::success();
1158 Error
WasmObjectFile::parseCustomSection(WasmSection
&Sec
, ReadContext
&Ctx
) {
1159 if (Sec
.Name
== "dylink") {
1160 if (Error Err
= parseDylinkSection(Ctx
))
1162 } else if (Sec
.Name
== "dylink.0") {
1163 if (Error Err
= parseDylink0Section(Ctx
))
1165 } else if (Sec
.Name
== "name") {
1166 if (Error Err
= parseNameSection(Ctx
))
1168 } else if (Sec
.Name
== "linking") {
1169 if (Error Err
= parseLinkingSection(Ctx
))
1171 } else if (Sec
.Name
== "producers") {
1172 if (Error Err
= parseProducersSection(Ctx
))
1174 } else if (Sec
.Name
== "target_features") {
1175 if (Error Err
= parseTargetFeaturesSection(Ctx
))
1177 } else if (Sec
.Name
.starts_with("reloc.")) {
1178 if (Error Err
= parseRelocSection(Sec
.Name
, Ctx
))
1181 return Error::success();
1184 Error
WasmObjectFile::parseTypeSection(ReadContext
&Ctx
) {
1185 auto parseFieldDef
= [&]() {
1186 uint32_t TypeCode
= readVaruint32((Ctx
));
1187 /* Discard StorageType */ parseValType(Ctx
, TypeCode
);
1188 /* Discard Mutability */ readVaruint32(Ctx
);
1191 uint32_t Count
= readVaruint32(Ctx
);
1192 Signatures
.reserve(Count
);
1194 wasm::WasmSignature Sig
;
1195 uint8_t Form
= readUint8(Ctx
);
1196 if (Form
== wasm::WASM_TYPE_REC
) {
1197 // Rec groups expand the type index space (beyond what was declared at
1198 // the top of the section, and also consume one element in that space.
1199 uint32_t RecSize
= readVaruint32(Ctx
);
1201 return make_error
<GenericBinaryError
>("Rec group size cannot be 0",
1202 object_error::parse_failed
);
1203 Signatures
.reserve(Signatures
.size() + RecSize
);
1205 Sig
.Kind
= wasm::WasmSignature::Placeholder
;
1206 Signatures
.push_back(std::move(Sig
));
1207 HasUnmodeledTypes
= true;
1210 if (Form
!= wasm::WASM_TYPE_FUNC
) {
1211 // Currently LLVM only models function types, and not other composite
1212 // types. Here we parse the type declarations just enough to skip past
1213 // them in the binary.
1214 if (Form
== wasm::WASM_TYPE_SUB
|| Form
== wasm::WASM_TYPE_SUB_FINAL
) {
1215 uint32_t Supers
= readVaruint32(Ctx
);
1218 return make_error
<GenericBinaryError
>(
1219 "Invalid number of supertypes", object_error::parse_failed
);
1220 /* Discard SuperIndex */ readVaruint32(Ctx
);
1222 Form
= readVaruint32(Ctx
);
1224 if (Form
== wasm::WASM_TYPE_STRUCT
) {
1225 uint32_t FieldCount
= readVaruint32(Ctx
);
1226 while (FieldCount
--) {
1229 } else if (Form
== wasm::WASM_TYPE_ARRAY
) {
1232 return make_error
<GenericBinaryError
>("bad form",
1233 object_error::parse_failed
);
1235 Sig
.Kind
= wasm::WasmSignature::Placeholder
;
1236 Signatures
.push_back(std::move(Sig
));
1237 HasUnmodeledTypes
= true;
1241 uint32_t ParamCount
= readVaruint32(Ctx
);
1242 Sig
.Params
.reserve(ParamCount
);
1243 while (ParamCount
--) {
1244 uint32_t ParamType
= readUint8(Ctx
);
1245 Sig
.Params
.push_back(parseValType(Ctx
, ParamType
));
1248 uint32_t ReturnCount
= readVaruint32(Ctx
);
1249 while (ReturnCount
--) {
1250 uint32_t ReturnType
= readUint8(Ctx
);
1251 Sig
.Returns
.push_back(parseValType(Ctx
, ReturnType
));
1254 Signatures
.push_back(std::move(Sig
));
1256 if (Ctx
.Ptr
!= Ctx
.End
)
1257 return make_error
<GenericBinaryError
>("type section ended prematurely",
1258 object_error::parse_failed
);
1259 return Error::success();
1262 Error
WasmObjectFile::parseImportSection(ReadContext
&Ctx
) {
1263 uint32_t Count
= readVaruint32(Ctx
);
1264 uint32_t NumTypes
= Signatures
.size();
1265 Imports
.reserve(Count
);
1266 for (uint32_t I
= 0; I
< Count
; I
++) {
1267 wasm::WasmImport Im
;
1268 Im
.Module
= readString(Ctx
);
1269 Im
.Field
= readString(Ctx
);
1270 Im
.Kind
= readUint8(Ctx
);
1272 case wasm::WASM_EXTERNAL_FUNCTION
:
1273 NumImportedFunctions
++;
1274 Im
.SigIndex
= readVaruint32(Ctx
);
1275 if (Im
.SigIndex
>= NumTypes
)
1276 return make_error
<GenericBinaryError
>("invalid function type",
1277 object_error::parse_failed
);
1279 case wasm::WASM_EXTERNAL_GLOBAL
:
1280 NumImportedGlobals
++;
1281 Im
.Global
.Type
= readUint8(Ctx
);
1282 Im
.Global
.Mutable
= readVaruint1(Ctx
);
1284 case wasm::WASM_EXTERNAL_MEMORY
:
1285 Im
.Memory
= readLimits(Ctx
);
1286 if (Im
.Memory
.Flags
& wasm::WASM_LIMITS_FLAG_IS_64
)
1289 case wasm::WASM_EXTERNAL_TABLE
: {
1290 Im
.Table
= readTableType(Ctx
);
1291 NumImportedTables
++;
1292 auto ElemType
= Im
.Table
.ElemType
;
1293 if (ElemType
!= wasm::ValType::FUNCREF
&&
1294 ElemType
!= wasm::ValType::EXTERNREF
&&
1295 ElemType
!= wasm::ValType::EXNREF
&&
1296 ElemType
!= wasm::ValType::OTHERREF
)
1297 return make_error
<GenericBinaryError
>("invalid table element type",
1298 object_error::parse_failed
);
1301 case wasm::WASM_EXTERNAL_TAG
:
1303 if (readUint8(Ctx
) != 0) // Reserved 'attribute' field
1304 return make_error
<GenericBinaryError
>("invalid attribute",
1305 object_error::parse_failed
);
1306 Im
.SigIndex
= readVaruint32(Ctx
);
1307 if (Im
.SigIndex
>= NumTypes
)
1308 return make_error
<GenericBinaryError
>("invalid tag type",
1309 object_error::parse_failed
);
1312 return make_error
<GenericBinaryError
>("unexpected import kind",
1313 object_error::parse_failed
);
1315 Imports
.push_back(Im
);
1317 if (Ctx
.Ptr
!= Ctx
.End
)
1318 return make_error
<GenericBinaryError
>("import section ended prematurely",
1319 object_error::parse_failed
);
1320 return Error::success();
1323 Error
WasmObjectFile::parseFunctionSection(ReadContext
&Ctx
) {
1324 uint32_t Count
= readVaruint32(Ctx
);
1325 Functions
.reserve(Count
);
1326 uint32_t NumTypes
= Signatures
.size();
1328 uint32_t Type
= readVaruint32(Ctx
);
1329 if (Type
>= NumTypes
)
1330 return make_error
<GenericBinaryError
>("invalid function type",
1331 object_error::parse_failed
);
1332 wasm::WasmFunction F
;
1334 Functions
.push_back(F
);
1336 if (Ctx
.Ptr
!= Ctx
.End
)
1337 return make_error
<GenericBinaryError
>("function section ended prematurely",
1338 object_error::parse_failed
);
1339 return Error::success();
1342 Error
WasmObjectFile::parseTableSection(ReadContext
&Ctx
) {
1343 TableSection
= Sections
.size();
1344 uint32_t Count
= readVaruint32(Ctx
);
1345 Tables
.reserve(Count
);
1348 T
.Type
= readTableType(Ctx
);
1349 T
.Index
= NumImportedTables
+ Tables
.size();
1350 Tables
.push_back(T
);
1351 auto ElemType
= Tables
.back().Type
.ElemType
;
1352 if (ElemType
!= wasm::ValType::FUNCREF
&&
1353 ElemType
!= wasm::ValType::EXTERNREF
&&
1354 ElemType
!= wasm::ValType::EXNREF
&&
1355 ElemType
!= wasm::ValType::OTHERREF
) {
1356 return make_error
<GenericBinaryError
>("invalid table element type",
1357 object_error::parse_failed
);
1360 if (Ctx
.Ptr
!= Ctx
.End
)
1361 return make_error
<GenericBinaryError
>("table section ended prematurely",
1362 object_error::parse_failed
);
1363 return Error::success();
1366 Error
WasmObjectFile::parseMemorySection(ReadContext
&Ctx
) {
1367 uint32_t Count
= readVaruint32(Ctx
);
1368 Memories
.reserve(Count
);
1370 auto Limits
= readLimits(Ctx
);
1371 if (Limits
.Flags
& wasm::WASM_LIMITS_FLAG_IS_64
)
1373 Memories
.push_back(Limits
);
1375 if (Ctx
.Ptr
!= Ctx
.End
)
1376 return make_error
<GenericBinaryError
>("memory section ended prematurely",
1377 object_error::parse_failed
);
1378 return Error::success();
1381 Error
WasmObjectFile::parseTagSection(ReadContext
&Ctx
) {
1382 TagSection
= Sections
.size();
1383 uint32_t Count
= readVaruint32(Ctx
);
1384 Tags
.reserve(Count
);
1385 uint32_t NumTypes
= Signatures
.size();
1387 if (readUint8(Ctx
) != 0) // Reserved 'attribute' field
1388 return make_error
<GenericBinaryError
>("invalid attribute",
1389 object_error::parse_failed
);
1390 uint32_t Type
= readVaruint32(Ctx
);
1391 if (Type
>= NumTypes
)
1392 return make_error
<GenericBinaryError
>("invalid tag type",
1393 object_error::parse_failed
);
1395 Tag
.Index
= NumImportedTags
+ Tags
.size();
1396 Tag
.SigIndex
= Type
;
1397 Signatures
[Type
].Kind
= wasm::WasmSignature::Tag
;
1398 Tags
.push_back(Tag
);
1401 if (Ctx
.Ptr
!= Ctx
.End
)
1402 return make_error
<GenericBinaryError
>("tag section ended prematurely",
1403 object_error::parse_failed
);
1404 return Error::success();
1407 Error
WasmObjectFile::parseGlobalSection(ReadContext
&Ctx
) {
1408 GlobalSection
= Sections
.size();
1409 const uint8_t *SectionStart
= Ctx
.Ptr
;
1410 uint32_t Count
= readVaruint32(Ctx
);
1411 Globals
.reserve(Count
);
1413 wasm::WasmGlobal Global
;
1414 Global
.Index
= NumImportedGlobals
+ Globals
.size();
1415 const uint8_t *GlobalStart
= Ctx
.Ptr
;
1416 Global
.Offset
= static_cast<uint32_t>(GlobalStart
- SectionStart
);
1417 auto GlobalOpcode
= readVaruint32(Ctx
);
1418 Global
.Type
.Type
= (uint8_t)parseValType(Ctx
, GlobalOpcode
);
1419 Global
.Type
.Mutable
= readVaruint1(Ctx
);
1420 if (Error Err
= readInitExpr(Global
.InitExpr
, Ctx
))
1422 Global
.Size
= static_cast<uint32_t>(Ctx
.Ptr
- GlobalStart
);
1423 Globals
.push_back(Global
);
1425 if (Ctx
.Ptr
!= Ctx
.End
)
1426 return make_error
<GenericBinaryError
>("global section ended prematurely",
1427 object_error::parse_failed
);
1428 return Error::success();
1431 Error
WasmObjectFile::parseExportSection(ReadContext
&Ctx
) {
1432 uint32_t Count
= readVaruint32(Ctx
);
1433 Exports
.reserve(Count
);
1434 Symbols
.reserve(Count
);
1435 for (uint32_t I
= 0; I
< Count
; I
++) {
1436 wasm::WasmExport Ex
;
1437 Ex
.Name
= readString(Ctx
);
1438 Ex
.Kind
= readUint8(Ctx
);
1439 Ex
.Index
= readVaruint32(Ctx
);
1440 const wasm::WasmSignature
*Signature
= nullptr;
1441 const wasm::WasmGlobalType
*GlobalType
= nullptr;
1442 const wasm::WasmTableType
*TableType
= nullptr;
1443 wasm::WasmSymbolInfo Info
;
1444 Info
.Name
= Ex
.Name
;
1447 case wasm::WASM_EXTERNAL_FUNCTION
: {
1448 if (!isDefinedFunctionIndex(Ex
.Index
))
1449 return make_error
<GenericBinaryError
>("invalid function export",
1450 object_error::parse_failed
);
1451 getDefinedFunction(Ex
.Index
).ExportName
= Ex
.Name
;
1452 Info
.Kind
= wasm::WASM_SYMBOL_TYPE_FUNCTION
;
1453 Info
.ElementIndex
= Ex
.Index
;
1454 unsigned FuncIndex
= Info
.ElementIndex
- NumImportedFunctions
;
1455 wasm::WasmFunction
&Function
= Functions
[FuncIndex
];
1456 Signature
= &Signatures
[Function
.SigIndex
];
1459 case wasm::WASM_EXTERNAL_GLOBAL
: {
1460 if (!isValidGlobalIndex(Ex
.Index
))
1461 return make_error
<GenericBinaryError
>("invalid global export",
1462 object_error::parse_failed
);
1463 Info
.Kind
= wasm::WASM_SYMBOL_TYPE_DATA
;
1464 uint64_t Offset
= 0;
1465 if (isDefinedGlobalIndex(Ex
.Index
)) {
1466 auto Global
= getDefinedGlobal(Ex
.Index
);
1467 if (!Global
.InitExpr
.Extended
) {
1468 auto Inst
= Global
.InitExpr
.Inst
;
1469 if (Inst
.Opcode
== wasm::WASM_OPCODE_I32_CONST
) {
1470 Offset
= Inst
.Value
.Int32
;
1471 } else if (Inst
.Opcode
== wasm::WASM_OPCODE_I64_CONST
) {
1472 Offset
= Inst
.Value
.Int64
;
1476 Info
.DataRef
= wasm::WasmDataReference
{0, Offset
, 0};
1479 case wasm::WASM_EXTERNAL_TAG
:
1480 if (!isValidTagIndex(Ex
.Index
))
1481 return make_error
<GenericBinaryError
>("invalid tag export",
1482 object_error::parse_failed
);
1483 Info
.Kind
= wasm::WASM_SYMBOL_TYPE_TAG
;
1484 Info
.ElementIndex
= Ex
.Index
;
1486 case wasm::WASM_EXTERNAL_MEMORY
:
1488 case wasm::WASM_EXTERNAL_TABLE
:
1489 Info
.Kind
= wasm::WASM_SYMBOL_TYPE_TABLE
;
1490 Info
.ElementIndex
= Ex
.Index
;
1493 return make_error
<GenericBinaryError
>("unexpected export kind",
1494 object_error::parse_failed
);
1496 Exports
.push_back(Ex
);
1497 if (Ex
.Kind
!= wasm::WASM_EXTERNAL_MEMORY
) {
1498 Symbols
.emplace_back(Info
, GlobalType
, TableType
, Signature
);
1499 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols
.back() << "\n");
1502 if (Ctx
.Ptr
!= Ctx
.End
)
1503 return make_error
<GenericBinaryError
>("export section ended prematurely",
1504 object_error::parse_failed
);
1505 return Error::success();
1508 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index
) const {
1509 return Index
< NumImportedFunctions
+ Functions
.size();
1512 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index
) const {
1513 return Index
>= NumImportedFunctions
&& isValidFunctionIndex(Index
);
1516 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index
) const {
1517 return Index
< NumImportedGlobals
+ Globals
.size();
1520 bool WasmObjectFile::isValidTableNumber(uint32_t Index
) const {
1521 return Index
< NumImportedTables
+ Tables
.size();
1524 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index
) const {
1525 return Index
>= NumImportedGlobals
&& isValidGlobalIndex(Index
);
1528 bool WasmObjectFile::isDefinedTableNumber(uint32_t Index
) const {
1529 return Index
>= NumImportedTables
&& isValidTableNumber(Index
);
1532 bool WasmObjectFile::isValidTagIndex(uint32_t Index
) const {
1533 return Index
< NumImportedTags
+ Tags
.size();
1536 bool WasmObjectFile::isDefinedTagIndex(uint32_t Index
) const {
1537 return Index
>= NumImportedTags
&& isValidTagIndex(Index
);
1540 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index
) const {
1541 return Index
< Symbols
.size() && Symbols
[Index
].isTypeFunction();
1544 bool WasmObjectFile::isValidTableSymbol(uint32_t Index
) const {
1545 return Index
< Symbols
.size() && Symbols
[Index
].isTypeTable();
1548 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index
) const {
1549 return Index
< Symbols
.size() && Symbols
[Index
].isTypeGlobal();
1552 bool WasmObjectFile::isValidTagSymbol(uint32_t Index
) const {
1553 return Index
< Symbols
.size() && Symbols
[Index
].isTypeTag();
1556 bool WasmObjectFile::isValidDataSymbol(uint32_t Index
) const {
1557 return Index
< Symbols
.size() && Symbols
[Index
].isTypeData();
1560 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index
) const {
1561 return Index
< Symbols
.size() && Symbols
[Index
].isTypeSection();
1564 wasm::WasmFunction
&WasmObjectFile::getDefinedFunction(uint32_t Index
) {
1565 assert(isDefinedFunctionIndex(Index
));
1566 return Functions
[Index
- NumImportedFunctions
];
1569 const wasm::WasmFunction
&
1570 WasmObjectFile::getDefinedFunction(uint32_t Index
) const {
1571 assert(isDefinedFunctionIndex(Index
));
1572 return Functions
[Index
- NumImportedFunctions
];
1575 const wasm::WasmGlobal
&WasmObjectFile::getDefinedGlobal(uint32_t Index
) const {
1576 assert(isDefinedGlobalIndex(Index
));
1577 return Globals
[Index
- NumImportedGlobals
];
1580 wasm::WasmTag
&WasmObjectFile::getDefinedTag(uint32_t Index
) {
1581 assert(isDefinedTagIndex(Index
));
1582 return Tags
[Index
- NumImportedTags
];
1585 Error
WasmObjectFile::parseStartSection(ReadContext
&Ctx
) {
1586 StartFunction
= readVaruint32(Ctx
);
1587 if (!isValidFunctionIndex(StartFunction
))
1588 return make_error
<GenericBinaryError
>("invalid start function",
1589 object_error::parse_failed
);
1590 return Error::success();
1593 Error
WasmObjectFile::parseCodeSection(ReadContext
&Ctx
) {
1594 CodeSection
= Sections
.size();
1595 uint32_t FunctionCount
= readVaruint32(Ctx
);
1596 if (FunctionCount
!= Functions
.size()) {
1597 return make_error
<GenericBinaryError
>("invalid function count",
1598 object_error::parse_failed
);
1601 for (uint32_t i
= 0; i
< FunctionCount
; i
++) {
1602 wasm::WasmFunction
& Function
= Functions
[i
];
1603 const uint8_t *FunctionStart
= Ctx
.Ptr
;
1604 uint32_t Size
= readVaruint32(Ctx
);
1605 const uint8_t *FunctionEnd
= Ctx
.Ptr
+ Size
;
1607 Function
.CodeOffset
= Ctx
.Ptr
- FunctionStart
;
1608 Function
.Index
= NumImportedFunctions
+ i
;
1609 Function
.CodeSectionOffset
= FunctionStart
- Ctx
.Start
;
1610 Function
.Size
= FunctionEnd
- FunctionStart
;
1612 uint32_t NumLocalDecls
= readVaruint32(Ctx
);
1613 Function
.Locals
.reserve(NumLocalDecls
);
1614 while (NumLocalDecls
--) {
1615 wasm::WasmLocalDecl Decl
;
1616 Decl
.Count
= readVaruint32(Ctx
);
1617 Decl
.Type
= readUint8(Ctx
);
1618 Function
.Locals
.push_back(Decl
);
1621 uint32_t BodySize
= FunctionEnd
- Ctx
.Ptr
;
1622 // Ensure that Function is within Ctx's buffer.
1623 if (Ctx
.Ptr
+ BodySize
> Ctx
.End
) {
1624 return make_error
<GenericBinaryError
>("Function extends beyond buffer",
1625 object_error::parse_failed
);
1627 Function
.Body
= ArrayRef
<uint8_t>(Ctx
.Ptr
, BodySize
);
1628 // This will be set later when reading in the linking metadata section.
1629 Function
.Comdat
= UINT32_MAX
;
1630 Ctx
.Ptr
+= BodySize
;
1631 assert(Ctx
.Ptr
== FunctionEnd
);
1633 if (Ctx
.Ptr
!= Ctx
.End
)
1634 return make_error
<GenericBinaryError
>("code section ended prematurely",
1635 object_error::parse_failed
);
1636 return Error::success();
1639 Error
WasmObjectFile::parseElemSection(ReadContext
&Ctx
) {
1640 uint32_t Count
= readVaruint32(Ctx
);
1641 ElemSegments
.reserve(Count
);
1643 wasm::WasmElemSegment Segment
;
1644 Segment
.Flags
= readVaruint32(Ctx
);
1646 uint32_t SupportedFlags
= wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
|
1647 wasm::WASM_ELEM_SEGMENT_IS_PASSIVE
|
1648 wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
;
1649 if (Segment
.Flags
& ~SupportedFlags
)
1650 return make_error
<GenericBinaryError
>(
1651 "Unsupported flags for element segment", object_error::parse_failed
);
1653 bool IsPassive
= (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_IS_PASSIVE
) != 0;
1654 bool IsDeclarative
=
1655 IsPassive
&& (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_IS_DECLARATIVE
);
1656 bool HasTableNumber
=
1658 (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
);
1660 (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
);
1662 (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
) &&
1666 Segment
.TableNumber
= readVaruint32(Ctx
);
1668 Segment
.TableNumber
= 0;
1670 if (!isValidTableNumber(Segment
.TableNumber
))
1671 return make_error
<GenericBinaryError
>("invalid TableNumber",
1672 object_error::parse_failed
);
1674 if (IsPassive
|| IsDeclarative
) {
1675 Segment
.Offset
.Extended
= false;
1676 Segment
.Offset
.Inst
.Opcode
= wasm::WASM_OPCODE_I32_CONST
;
1677 Segment
.Offset
.Inst
.Value
.Int32
= 0;
1679 if (Error Err
= readInitExpr(Segment
.Offset
, Ctx
))
1684 auto ElemKind
= readVaruint32(Ctx
);
1685 if (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
) {
1686 Segment
.ElemKind
= parseValType(Ctx
, ElemKind
);
1687 if (Segment
.ElemKind
!= wasm::ValType::FUNCREF
&&
1688 Segment
.ElemKind
!= wasm::ValType::EXTERNREF
&&
1689 Segment
.ElemKind
!= wasm::ValType::EXNREF
&&
1690 Segment
.ElemKind
!= wasm::ValType::OTHERREF
) {
1691 return make_error
<GenericBinaryError
>("invalid elem type",
1692 object_error::parse_failed
);
1696 return make_error
<GenericBinaryError
>("invalid elem type",
1697 object_error::parse_failed
);
1698 Segment
.ElemKind
= wasm::ValType::FUNCREF
;
1700 } else if (HasInitExprs
) {
1701 auto ElemType
= parseValType(Ctx
, readVaruint32(Ctx
));
1702 Segment
.ElemKind
= ElemType
;
1704 Segment
.ElemKind
= wasm::ValType::FUNCREF
;
1707 uint32_t NumElems
= readVaruint32(Ctx
);
1710 while (NumElems
--) {
1711 wasm::WasmInitExpr Expr
;
1712 if (Error Err
= readInitExpr(Expr
, Ctx
))
1716 while (NumElems
--) {
1717 Segment
.Functions
.push_back(readVaruint32(Ctx
));
1720 ElemSegments
.push_back(Segment
);
1722 if (Ctx
.Ptr
!= Ctx
.End
)
1723 return make_error
<GenericBinaryError
>("elem section ended prematurely",
1724 object_error::parse_failed
);
1725 return Error::success();
1728 Error
WasmObjectFile::parseDataSection(ReadContext
&Ctx
) {
1729 DataSection
= Sections
.size();
1730 uint32_t Count
= readVaruint32(Ctx
);
1731 if (DataCount
&& Count
!= *DataCount
)
1732 return make_error
<GenericBinaryError
>(
1733 "number of data segments does not match DataCount section");
1734 DataSegments
.reserve(Count
);
1736 WasmSegment Segment
;
1737 Segment
.Data
.InitFlags
= readVaruint32(Ctx
);
1738 Segment
.Data
.MemoryIndex
=
1739 (Segment
.Data
.InitFlags
& wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX
)
1740 ? readVaruint32(Ctx
)
1742 if ((Segment
.Data
.InitFlags
& wasm::WASM_DATA_SEGMENT_IS_PASSIVE
) == 0) {
1743 if (Error Err
= readInitExpr(Segment
.Data
.Offset
, Ctx
))
1746 Segment
.Data
.Offset
.Extended
= false;
1747 Segment
.Data
.Offset
.Inst
.Opcode
= wasm::WASM_OPCODE_I32_CONST
;
1748 Segment
.Data
.Offset
.Inst
.Value
.Int32
= 0;
1750 uint32_t Size
= readVaruint32(Ctx
);
1751 if (Size
> (size_t)(Ctx
.End
- Ctx
.Ptr
))
1752 return make_error
<GenericBinaryError
>("invalid segment size",
1753 object_error::parse_failed
);
1754 Segment
.Data
.Content
= ArrayRef
<uint8_t>(Ctx
.Ptr
, Size
);
1755 // The rest of these Data fields are set later, when reading in the linking
1756 // metadata section.
1757 Segment
.Data
.Alignment
= 0;
1758 Segment
.Data
.LinkingFlags
= 0;
1759 Segment
.Data
.Comdat
= UINT32_MAX
;
1760 Segment
.SectionOffset
= Ctx
.Ptr
- Ctx
.Start
;
1762 DataSegments
.push_back(Segment
);
1764 if (Ctx
.Ptr
!= Ctx
.End
)
1765 return make_error
<GenericBinaryError
>("data section ended prematurely",
1766 object_error::parse_failed
);
1767 return Error::success();
1770 Error
WasmObjectFile::parseDataCountSection(ReadContext
&Ctx
) {
1771 DataCount
= readVaruint32(Ctx
);
1772 return Error::success();
1775 const wasm::WasmObjectHeader
&WasmObjectFile::getHeader() const {
1779 void WasmObjectFile::moveSymbolNext(DataRefImpl
&Symb
) const { Symb
.d
.b
++; }
1781 Expected
<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb
) const {
1782 uint32_t Result
= SymbolRef::SF_None
;
1783 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1785 LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym
<< " " << Sym
<< "\n");
1786 if (Sym
.isBindingWeak())
1787 Result
|= SymbolRef::SF_Weak
;
1788 if (!Sym
.isBindingLocal())
1789 Result
|= SymbolRef::SF_Global
;
1791 Result
|= SymbolRef::SF_Hidden
;
1792 if (!Sym
.isDefined())
1793 Result
|= SymbolRef::SF_Undefined
;
1794 if (Sym
.isTypeFunction())
1795 Result
|= SymbolRef::SF_Executable
;
1799 basic_symbol_iterator
WasmObjectFile::symbol_begin() const {
1801 Ref
.d
.a
= 1; // Arbitrary non-zero value so that Ref.p is non-null
1802 Ref
.d
.b
= 0; // Symbol index
1803 return BasicSymbolRef(Ref
, this);
1806 basic_symbol_iterator
WasmObjectFile::symbol_end() const {
1808 Ref
.d
.a
= 1; // Arbitrary non-zero value so that Ref.p is non-null
1809 Ref
.d
.b
= Symbols
.size(); // Symbol index
1810 return BasicSymbolRef(Ref
, this);
1813 const WasmSymbol
&WasmObjectFile::getWasmSymbol(const DataRefImpl
&Symb
) const {
1814 return Symbols
[Symb
.d
.b
];
1817 const WasmSymbol
&WasmObjectFile::getWasmSymbol(const SymbolRef
&Symb
) const {
1818 return getWasmSymbol(Symb
.getRawDataRefImpl());
1821 Expected
<StringRef
> WasmObjectFile::getSymbolName(DataRefImpl Symb
) const {
1822 return getWasmSymbol(Symb
).Info
.Name
;
1825 Expected
<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb
) const {
1826 auto &Sym
= getWasmSymbol(Symb
);
1827 if (!Sym
.isDefined())
1829 Expected
<section_iterator
> Sec
= getSymbolSection(Symb
);
1831 return Sec
.takeError();
1832 uint32_t SectionAddress
= getSectionAddress(Sec
.get()->getRawDataRefImpl());
1833 if (Sym
.Info
.Kind
== wasm::WASM_SYMBOL_TYPE_FUNCTION
&&
1834 isDefinedFunctionIndex(Sym
.Info
.ElementIndex
)) {
1835 return getDefinedFunction(Sym
.Info
.ElementIndex
).CodeSectionOffset
+
1838 if (Sym
.Info
.Kind
== wasm::WASM_SYMBOL_TYPE_GLOBAL
&&
1839 isDefinedGlobalIndex(Sym
.Info
.ElementIndex
)) {
1840 return getDefinedGlobal(Sym
.Info
.ElementIndex
).Offset
+ SectionAddress
;
1843 return getSymbolValue(Symb
);
1846 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol
&Sym
) const {
1847 switch (Sym
.Info
.Kind
) {
1848 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
1849 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
1850 case wasm::WASM_SYMBOL_TYPE_TAG
:
1851 case wasm::WASM_SYMBOL_TYPE_TABLE
:
1852 return Sym
.Info
.ElementIndex
;
1853 case wasm::WASM_SYMBOL_TYPE_DATA
: {
1854 // The value of a data symbol is the segment offset, plus the symbol
1855 // offset within the segment.
1856 uint32_t SegmentIndex
= Sym
.Info
.DataRef
.Segment
;
1857 const wasm::WasmDataSegment
&Segment
= DataSegments
[SegmentIndex
].Data
;
1858 if (Segment
.Offset
.Extended
) {
1859 llvm_unreachable("extended init exprs not supported");
1860 } else if (Segment
.Offset
.Inst
.Opcode
== wasm::WASM_OPCODE_I32_CONST
) {
1861 return Segment
.Offset
.Inst
.Value
.Int32
+ Sym
.Info
.DataRef
.Offset
;
1862 } else if (Segment
.Offset
.Inst
.Opcode
== wasm::WASM_OPCODE_I64_CONST
) {
1863 return Segment
.Offset
.Inst
.Value
.Int64
+ Sym
.Info
.DataRef
.Offset
;
1864 } else if (Segment
.Offset
.Inst
.Opcode
== wasm::WASM_OPCODE_GLOBAL_GET
) {
1865 return Sym
.Info
.DataRef
.Offset
;
1867 llvm_unreachable("unknown init expr opcode");
1870 case wasm::WASM_SYMBOL_TYPE_SECTION
:
1873 llvm_unreachable("invalid symbol type");
1876 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb
) const {
1877 return getWasmSymbolValue(getWasmSymbol(Symb
));
1880 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb
) const {
1881 llvm_unreachable("not yet implemented");
1885 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb
) const {
1886 llvm_unreachable("not yet implemented");
1890 Expected
<SymbolRef::Type
>
1891 WasmObjectFile::getSymbolType(DataRefImpl Symb
) const {
1892 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1894 switch (Sym
.Info
.Kind
) {
1895 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
1896 return SymbolRef::ST_Function
;
1897 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
1898 return SymbolRef::ST_Other
;
1899 case wasm::WASM_SYMBOL_TYPE_DATA
:
1900 return SymbolRef::ST_Data
;
1901 case wasm::WASM_SYMBOL_TYPE_SECTION
:
1902 return SymbolRef::ST_Debug
;
1903 case wasm::WASM_SYMBOL_TYPE_TAG
:
1904 return SymbolRef::ST_Other
;
1905 case wasm::WASM_SYMBOL_TYPE_TABLE
:
1906 return SymbolRef::ST_Other
;
1909 llvm_unreachable("unknown WasmSymbol::SymbolType");
1910 return SymbolRef::ST_Other
;
1913 Expected
<section_iterator
>
1914 WasmObjectFile::getSymbolSection(DataRefImpl Symb
) const {
1915 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1916 if (Sym
.isUndefined())
1917 return section_end();
1920 Ref
.d
.a
= getSymbolSectionIdImpl(Sym
);
1921 return section_iterator(SectionRef(Ref
, this));
1924 uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb
) const {
1925 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1926 return getSymbolSectionIdImpl(Sym
);
1929 uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol
&Sym
) const {
1930 switch (Sym
.Info
.Kind
) {
1931 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
1933 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
1934 return GlobalSection
;
1935 case wasm::WASM_SYMBOL_TYPE_DATA
:
1937 case wasm::WASM_SYMBOL_TYPE_SECTION
:
1938 return Sym
.Info
.ElementIndex
;
1939 case wasm::WASM_SYMBOL_TYPE_TAG
:
1941 case wasm::WASM_SYMBOL_TYPE_TABLE
:
1942 return TableSection
;
1944 llvm_unreachable("unknown WasmSymbol::SymbolType");
1948 uint32_t WasmObjectFile::getSymbolSize(SymbolRef Symb
) const {
1949 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1950 if (!Sym
.isDefined())
1952 if (Sym
.isTypeGlobal())
1953 return getDefinedGlobal(Sym
.Info
.ElementIndex
).Size
;
1954 if (Sym
.isTypeData())
1955 return Sym
.Info
.DataRef
.Size
;
1956 if (Sym
.isTypeFunction())
1957 return functions()[Sym
.Info
.ElementIndex
- getNumImportedFunctions()].Size
;
1958 // Currently symbol size is only tracked for data segments and functions. In
1959 // principle we could also track size (e.g. binary size) for tables, globals
1960 // and element segments etc too.
1964 void WasmObjectFile::moveSectionNext(DataRefImpl
&Sec
) const { Sec
.d
.a
++; }
1966 Expected
<StringRef
> WasmObjectFile::getSectionName(DataRefImpl Sec
) const {
1967 const WasmSection
&S
= Sections
[Sec
.d
.a
];
1968 if (S
.Type
== wasm::WASM_SEC_CUSTOM
)
1970 if (S
.Type
> wasm::WASM_SEC_LAST_KNOWN
)
1971 return createStringError(object_error::invalid_section_index
, "");
1972 return wasm::sectionTypeToString(S
.Type
);
1975 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec
) const {
1976 // For object files, use 0 for section addresses, and section offsets for
1977 // symbol addresses. For linked files, use file offsets.
1978 // See also getSymbolAddress.
1979 return isRelocatableObject() || isSharedObject() ? 0
1980 : Sections
[Sec
.d
.a
].Offset
;
1983 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec
) const {
1987 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec
) const {
1988 const WasmSection
&S
= Sections
[Sec
.d
.a
];
1989 return S
.Content
.size();
1992 Expected
<ArrayRef
<uint8_t>>
1993 WasmObjectFile::getSectionContents(DataRefImpl Sec
) const {
1994 const WasmSection
&S
= Sections
[Sec
.d
.a
];
1995 // This will never fail since wasm sections can never be empty (user-sections
1996 // must have a name and non-user sections each have a defined structure).
2000 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec
) const {
2004 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
2008 bool WasmObjectFile::isSectionText(DataRefImpl Sec
) const {
2009 return getWasmSection(Sec
).Type
== wasm::WASM_SEC_CODE
;
2012 bool WasmObjectFile::isSectionData(DataRefImpl Sec
) const {
2013 return getWasmSection(Sec
).Type
== wasm::WASM_SEC_DATA
;
2016 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec
) const { return false; }
2018 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec
) const { return false; }
2020 relocation_iterator
WasmObjectFile::section_rel_begin(DataRefImpl Ref
) const {
2021 DataRefImpl RelocRef
;
2022 RelocRef
.d
.a
= Ref
.d
.a
;
2024 return relocation_iterator(RelocationRef(RelocRef
, this));
2027 relocation_iterator
WasmObjectFile::section_rel_end(DataRefImpl Ref
) const {
2028 const WasmSection
&Sec
= getWasmSection(Ref
);
2029 DataRefImpl RelocRef
;
2030 RelocRef
.d
.a
= Ref
.d
.a
;
2031 RelocRef
.d
.b
= Sec
.Relocations
.size();
2032 return relocation_iterator(RelocationRef(RelocRef
, this));
2035 void WasmObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const { Rel
.d
.b
++; }
2037 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref
) const {
2038 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
2042 symbol_iterator
WasmObjectFile::getRelocationSymbol(DataRefImpl Ref
) const {
2043 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
2044 if (Rel
.Type
== wasm::R_WASM_TYPE_INDEX_LEB
)
2045 return symbol_end();
2048 Sym
.d
.b
= Rel
.Index
;
2049 return symbol_iterator(SymbolRef(Sym
, this));
2052 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref
) const {
2053 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
2057 void WasmObjectFile::getRelocationTypeName(
2058 DataRefImpl Ref
, SmallVectorImpl
<char> &Result
) const {
2059 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
2060 StringRef Res
= "Unknown";
2062 #define WASM_RELOC(name, value) \
2068 #include "llvm/BinaryFormat/WasmRelocs.def"
2073 Result
.append(Res
.begin(), Res
.end());
2076 section_iterator
WasmObjectFile::section_begin() const {
2079 return section_iterator(SectionRef(Ref
, this));
2082 section_iterator
WasmObjectFile::section_end() const {
2084 Ref
.d
.a
= Sections
.size();
2085 return section_iterator(SectionRef(Ref
, this));
2088 uint8_t WasmObjectFile::getBytesInAddress() const {
2089 return HasMemory64
? 8 : 4;
2092 StringRef
WasmObjectFile::getFileFormatName() const { return "WASM"; }
2094 Triple::ArchType
WasmObjectFile::getArch() const {
2095 return HasMemory64
? Triple::wasm64
: Triple::wasm32
;
2098 Expected
<SubtargetFeatures
> WasmObjectFile::getFeatures() const {
2099 return SubtargetFeatures();
2102 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection
; }
2104 bool WasmObjectFile::isSharedObject() const { return HasDylinkSection
; }
2106 const WasmSection
&WasmObjectFile::getWasmSection(DataRefImpl Ref
) const {
2107 assert(Ref
.d
.a
< Sections
.size());
2108 return Sections
[Ref
.d
.a
];
2112 WasmObjectFile::getWasmSection(const SectionRef
&Section
) const {
2113 return getWasmSection(Section
.getRawDataRefImpl());
2116 const wasm::WasmRelocation
&
2117 WasmObjectFile::getWasmRelocation(const RelocationRef
&Ref
) const {
2118 return getWasmRelocation(Ref
.getRawDataRefImpl());
2121 const wasm::WasmRelocation
&
2122 WasmObjectFile::getWasmRelocation(DataRefImpl Ref
) const {
2123 assert(Ref
.d
.a
< Sections
.size());
2124 const WasmSection
&Sec
= Sections
[Ref
.d
.a
];
2125 assert(Ref
.d
.b
< Sec
.Relocations
.size());
2126 return Sec
.Relocations
[Ref
.d
.b
];
2129 int WasmSectionOrderChecker::getSectionOrder(unsigned ID
,
2130 StringRef CustomSectionName
) {
2132 case wasm::WASM_SEC_CUSTOM
:
2133 return StringSwitch
<unsigned>(CustomSectionName
)
2134 .Case("dylink", WASM_SEC_ORDER_DYLINK
)
2135 .Case("dylink.0", WASM_SEC_ORDER_DYLINK
)
2136 .Case("linking", WASM_SEC_ORDER_LINKING
)
2137 .StartsWith("reloc.", WASM_SEC_ORDER_RELOC
)
2138 .Case("name", WASM_SEC_ORDER_NAME
)
2139 .Case("producers", WASM_SEC_ORDER_PRODUCERS
)
2140 .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES
)
2141 .Default(WASM_SEC_ORDER_NONE
);
2142 case wasm::WASM_SEC_TYPE
:
2143 return WASM_SEC_ORDER_TYPE
;
2144 case wasm::WASM_SEC_IMPORT
:
2145 return WASM_SEC_ORDER_IMPORT
;
2146 case wasm::WASM_SEC_FUNCTION
:
2147 return WASM_SEC_ORDER_FUNCTION
;
2148 case wasm::WASM_SEC_TABLE
:
2149 return WASM_SEC_ORDER_TABLE
;
2150 case wasm::WASM_SEC_MEMORY
:
2151 return WASM_SEC_ORDER_MEMORY
;
2152 case wasm::WASM_SEC_GLOBAL
:
2153 return WASM_SEC_ORDER_GLOBAL
;
2154 case wasm::WASM_SEC_EXPORT
:
2155 return WASM_SEC_ORDER_EXPORT
;
2156 case wasm::WASM_SEC_START
:
2157 return WASM_SEC_ORDER_START
;
2158 case wasm::WASM_SEC_ELEM
:
2159 return WASM_SEC_ORDER_ELEM
;
2160 case wasm::WASM_SEC_CODE
:
2161 return WASM_SEC_ORDER_CODE
;
2162 case wasm::WASM_SEC_DATA
:
2163 return WASM_SEC_ORDER_DATA
;
2164 case wasm::WASM_SEC_DATACOUNT
:
2165 return WASM_SEC_ORDER_DATACOUNT
;
2166 case wasm::WASM_SEC_TAG
:
2167 return WASM_SEC_ORDER_TAG
;
2169 return WASM_SEC_ORDER_NONE
;
2173 // Represents the edges in a directed graph where any node B reachable from node
2174 // A is not allowed to appear before A in the section ordering, but may appear
2176 int WasmSectionOrderChecker::DisallowedPredecessors
2177 [WASM_NUM_SEC_ORDERS
][WASM_NUM_SEC_ORDERS
] = {
2178 // WASM_SEC_ORDER_NONE
2180 // WASM_SEC_ORDER_TYPE
2181 {WASM_SEC_ORDER_TYPE
, WASM_SEC_ORDER_IMPORT
},
2182 // WASM_SEC_ORDER_IMPORT
2183 {WASM_SEC_ORDER_IMPORT
, WASM_SEC_ORDER_FUNCTION
},
2184 // WASM_SEC_ORDER_FUNCTION
2185 {WASM_SEC_ORDER_FUNCTION
, WASM_SEC_ORDER_TABLE
},
2186 // WASM_SEC_ORDER_TABLE
2187 {WASM_SEC_ORDER_TABLE
, WASM_SEC_ORDER_MEMORY
},
2188 // WASM_SEC_ORDER_MEMORY
2189 {WASM_SEC_ORDER_MEMORY
, WASM_SEC_ORDER_TAG
},
2190 // WASM_SEC_ORDER_TAG
2191 {WASM_SEC_ORDER_TAG
, WASM_SEC_ORDER_GLOBAL
},
2192 // WASM_SEC_ORDER_GLOBAL
2193 {WASM_SEC_ORDER_GLOBAL
, WASM_SEC_ORDER_EXPORT
},
2194 // WASM_SEC_ORDER_EXPORT
2195 {WASM_SEC_ORDER_EXPORT
, WASM_SEC_ORDER_START
},
2196 // WASM_SEC_ORDER_START
2197 {WASM_SEC_ORDER_START
, WASM_SEC_ORDER_ELEM
},
2198 // WASM_SEC_ORDER_ELEM
2199 {WASM_SEC_ORDER_ELEM
, WASM_SEC_ORDER_DATACOUNT
},
2200 // WASM_SEC_ORDER_DATACOUNT
2201 {WASM_SEC_ORDER_DATACOUNT
, WASM_SEC_ORDER_CODE
},
2202 // WASM_SEC_ORDER_CODE
2203 {WASM_SEC_ORDER_CODE
, WASM_SEC_ORDER_DATA
},
2204 // WASM_SEC_ORDER_DATA
2205 {WASM_SEC_ORDER_DATA
, WASM_SEC_ORDER_LINKING
},
2208 // WASM_SEC_ORDER_DYLINK
2209 {WASM_SEC_ORDER_DYLINK
, WASM_SEC_ORDER_TYPE
},
2210 // WASM_SEC_ORDER_LINKING
2211 {WASM_SEC_ORDER_LINKING
, WASM_SEC_ORDER_RELOC
, WASM_SEC_ORDER_NAME
},
2212 // WASM_SEC_ORDER_RELOC (can be repeated)
2214 // WASM_SEC_ORDER_NAME
2215 {WASM_SEC_ORDER_NAME
, WASM_SEC_ORDER_PRODUCERS
},
2216 // WASM_SEC_ORDER_PRODUCERS
2217 {WASM_SEC_ORDER_PRODUCERS
, WASM_SEC_ORDER_TARGET_FEATURES
},
2218 // WASM_SEC_ORDER_TARGET_FEATURES
2219 {WASM_SEC_ORDER_TARGET_FEATURES
}};
2221 bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID
,
2222 StringRef CustomSectionName
) {
2223 int Order
= getSectionOrder(ID
, CustomSectionName
);
2224 if (Order
== WASM_SEC_ORDER_NONE
)
2227 // Disallowed predecessors we need to check for
2228 SmallVector
<int, WASM_NUM_SEC_ORDERS
> WorkList
;
2230 // Keep track of completed checks to avoid repeating work
2231 bool Checked
[WASM_NUM_SEC_ORDERS
] = {};
2235 // Add new disallowed predecessors to work list
2236 for (size_t I
= 0;; ++I
) {
2237 int Next
= DisallowedPredecessors
[Curr
][I
];
2238 if (Next
== WASM_SEC_ORDER_NONE
)
2242 WorkList
.push_back(Next
);
2243 Checked
[Next
] = true;
2246 if (WorkList
.empty())
2249 // Consider next disallowed predecessor
2250 Curr
= WorkList
.pop_back_val();
2255 // Have not seen any disallowed predecessors