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/LEB128.h"
25 #include "llvm/Support/ScopedPrinter.h"
26 #include "llvm/TargetParser/SubtargetFeature.h"
27 #include "llvm/TargetParser/Triple.h"
33 #define DEBUG_TYPE "wasm-object"
36 using namespace object
;
38 void WasmSymbol::print(raw_ostream
&Out
) const {
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;
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
;
62 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
63 LLVM_DUMP_METHOD
void WasmSymbol::dump() const { print(dbgs()); }
66 Expected
<std::unique_ptr
<WasmObjectFile
>>
67 ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer
) {
68 Error Err
= Error::success();
69 auto ObjectFile
= std::make_unique
<WasmObjectFile
>(Buffer
, Err
);
71 return std::move(Err
);
73 return std::move(ObjectFile
);
76 #define VARINT7_MAX ((1 << 7) - 1)
77 #define VARINT7_MIN (-(1 << 7))
78 #define VARUINT7_MAX (1 << 7)
79 #define VARUINT1_MAX (1)
81 static uint8_t readUint8(WasmObjectFile::ReadContext
&Ctx
) {
82 if (Ctx
.Ptr
== Ctx
.End
)
83 report_fatal_error("EOF while reading uint8");
87 static uint32_t readUint32(WasmObjectFile::ReadContext
&Ctx
) {
88 if (Ctx
.Ptr
+ 4 > Ctx
.End
)
89 report_fatal_error("EOF while reading uint32");
90 uint32_t Result
= support::endian::read32le(Ctx
.Ptr
);
95 static int32_t readFloat32(WasmObjectFile::ReadContext
&Ctx
) {
96 if (Ctx
.Ptr
+ 4 > Ctx
.End
)
97 report_fatal_error("EOF while reading float64");
99 memcpy(&Result
, Ctx
.Ptr
, sizeof(Result
));
100 Ctx
.Ptr
+= sizeof(Result
);
104 static int64_t readFloat64(WasmObjectFile::ReadContext
&Ctx
) {
105 if (Ctx
.Ptr
+ 8 > Ctx
.End
)
106 report_fatal_error("EOF while reading float64");
108 memcpy(&Result
, Ctx
.Ptr
, sizeof(Result
));
109 Ctx
.Ptr
+= sizeof(Result
);
113 static uint64_t readULEB128(WasmObjectFile::ReadContext
&Ctx
) {
115 const char *Error
= nullptr;
116 uint64_t Result
= decodeULEB128(Ctx
.Ptr
, &Count
, Ctx
.End
, &Error
);
118 report_fatal_error(Error
);
123 static StringRef
readString(WasmObjectFile::ReadContext
&Ctx
) {
124 uint32_t StringLen
= readULEB128(Ctx
);
125 if (Ctx
.Ptr
+ StringLen
> Ctx
.End
)
126 report_fatal_error("EOF while reading string");
128 StringRef(reinterpret_cast<const char *>(Ctx
.Ptr
), StringLen
);
129 Ctx
.Ptr
+= StringLen
;
133 static int64_t readLEB128(WasmObjectFile::ReadContext
&Ctx
) {
135 const char *Error
= nullptr;
136 uint64_t Result
= decodeSLEB128(Ctx
.Ptr
, &Count
, Ctx
.End
, &Error
);
138 report_fatal_error(Error
);
143 static uint8_t readVaruint1(WasmObjectFile::ReadContext
&Ctx
) {
144 int64_t Result
= readLEB128(Ctx
);
145 if (Result
> VARUINT1_MAX
|| Result
< 0)
146 report_fatal_error("LEB is outside Varuint1 range");
150 static int32_t readVarint32(WasmObjectFile::ReadContext
&Ctx
) {
151 int64_t Result
= readLEB128(Ctx
);
152 if (Result
> INT32_MAX
|| Result
< INT32_MIN
)
153 report_fatal_error("LEB is outside Varint32 range");
157 static uint32_t readVaruint32(WasmObjectFile::ReadContext
&Ctx
) {
158 uint64_t Result
= readULEB128(Ctx
);
159 if (Result
> UINT32_MAX
)
160 report_fatal_error("LEB is outside Varuint32 range");
164 static int64_t readVarint64(WasmObjectFile::ReadContext
&Ctx
) {
165 return readLEB128(Ctx
);
168 static uint64_t readVaruint64(WasmObjectFile::ReadContext
&Ctx
) {
169 return readULEB128(Ctx
);
172 static uint8_t readOpcode(WasmObjectFile::ReadContext
&Ctx
) {
173 return readUint8(Ctx
);
176 static Error
readInitExpr(wasm::WasmInitExpr
&Expr
,
177 WasmObjectFile::ReadContext
&Ctx
) {
178 auto Start
= Ctx
.Ptr
;
180 Expr
.Extended
= false;
181 Expr
.Inst
.Opcode
= readOpcode(Ctx
);
182 switch (Expr
.Inst
.Opcode
) {
183 case wasm::WASM_OPCODE_I32_CONST
:
184 Expr
.Inst
.Value
.Int32
= readVarint32(Ctx
);
186 case wasm::WASM_OPCODE_I64_CONST
:
187 Expr
.Inst
.Value
.Int64
= readVarint64(Ctx
);
189 case wasm::WASM_OPCODE_F32_CONST
:
190 Expr
.Inst
.Value
.Float32
= readFloat32(Ctx
);
192 case wasm::WASM_OPCODE_F64_CONST
:
193 Expr
.Inst
.Value
.Float64
= readFloat64(Ctx
);
195 case wasm::WASM_OPCODE_GLOBAL_GET
:
196 Expr
.Inst
.Value
.Global
= readULEB128(Ctx
);
198 case wasm::WASM_OPCODE_REF_NULL
: {
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",
202 object_error::parse_failed
);
207 Expr
.Extended
= true;
210 if (!Expr
.Extended
) {
211 uint8_t EndOpcode
= readOpcode(Ctx
);
212 if (EndOpcode
!= wasm::WASM_OPCODE_END
)
213 Expr
.Extended
= true;
219 uint8_t Opcode
= readOpcode(Ctx
);
221 case wasm::WASM_OPCODE_I32_CONST
:
222 case wasm::WASM_OPCODE_GLOBAL_GET
:
223 case wasm::WASM_OPCODE_REF_NULL
:
224 case wasm::WASM_OPCODE_I64_CONST
:
225 case wasm::WASM_OPCODE_F32_CONST
:
226 case wasm::WASM_OPCODE_F64_CONST
:
229 case wasm::WASM_OPCODE_I32_ADD
:
230 case wasm::WASM_OPCODE_I32_SUB
:
231 case wasm::WASM_OPCODE_I32_MUL
:
232 case wasm::WASM_OPCODE_I64_ADD
:
233 case wasm::WASM_OPCODE_I64_SUB
:
234 case wasm::WASM_OPCODE_I64_MUL
:
236 case wasm::WASM_OPCODE_END
:
237 Expr
.Body
= ArrayRef
<uint8_t>(Start
, Ctx
.Ptr
- Start
);
238 return Error::success();
240 return make_error
<GenericBinaryError
>(
241 Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode
)),
242 object_error::parse_failed
);
247 return Error::success();
250 static wasm::WasmLimits
readLimits(WasmObjectFile::ReadContext
&Ctx
) {
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
);
259 static wasm::WasmTableType
readTableType(WasmObjectFile::ReadContext
&Ctx
) {
260 wasm::WasmTableType TableType
;
261 TableType
.ElemType
= readUint8(Ctx
);
262 TableType
.Limits
= readLimits(Ctx
);
266 static Error
readSection(WasmSection
&Section
, WasmObjectFile::ReadContext
&Ctx
,
267 WasmSectionOrderChecker
&Checker
) {
268 Section
.Offset
= Ctx
.Ptr
- Ctx
.Start
;
269 Section
.Type
= readUint8(Ctx
);
270 LLVM_DEBUG(dbgs() << "readSection type=" << Section
.Type
<< "\n");
271 // When reading the section's size, store the size of the LEB used to encode
272 // it. This allows objcopy/strip to reproduce the binary identically.
273 const uint8_t *PreSizePtr
= Ctx
.Ptr
;
274 uint32_t Size
= readVaruint32(Ctx
);
275 Section
.HeaderSecSizeEncodingLen
= Ctx
.Ptr
- PreSizePtr
;
277 return make_error
<StringError
>("zero length section",
278 object_error::parse_failed
);
279 if (Ctx
.Ptr
+ Size
> Ctx
.End
)
280 return make_error
<StringError
>("section too large",
281 object_error::parse_failed
);
282 if (Section
.Type
== wasm::WASM_SEC_CUSTOM
) {
283 WasmObjectFile::ReadContext SectionCtx
;
284 SectionCtx
.Start
= Ctx
.Ptr
;
285 SectionCtx
.Ptr
= Ctx
.Ptr
;
286 SectionCtx
.End
= Ctx
.Ptr
+ Size
;
288 Section
.Name
= readString(SectionCtx
);
290 uint32_t SectionNameSize
= SectionCtx
.Ptr
- SectionCtx
.Start
;
291 Ctx
.Ptr
+= SectionNameSize
;
292 Size
-= SectionNameSize
;
295 if (!Checker
.isValidSectionOrder(Section
.Type
, Section
.Name
)) {
296 return make_error
<StringError
>("out of order section type: " +
297 llvm::to_string(Section
.Type
),
298 object_error::parse_failed
);
301 Section
.Content
= ArrayRef
<uint8_t>(Ctx
.Ptr
, Size
);
303 return Error::success();
306 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer
, Error
&Err
)
307 : ObjectFile(Binary::ID_Wasm
, Buffer
) {
308 ErrorAsOutParameter
ErrAsOutParam(&Err
);
309 Header
.Magic
= getData().substr(0, 4);
310 if (Header
.Magic
!= StringRef("\0asm", 4)) {
311 Err
= make_error
<StringError
>("invalid magic number",
312 object_error::parse_failed
);
317 Ctx
.Start
= getData().bytes_begin();
318 Ctx
.Ptr
= Ctx
.Start
+ 4;
319 Ctx
.End
= Ctx
.Start
+ getData().size();
321 if (Ctx
.Ptr
+ 4 > Ctx
.End
) {
322 Err
= make_error
<StringError
>("missing version number",
323 object_error::parse_failed
);
327 Header
.Version
= readUint32(Ctx
);
328 if (Header
.Version
!= wasm::WasmVersion
) {
329 Err
= make_error
<StringError
>("invalid version number: " +
330 Twine(Header
.Version
),
331 object_error::parse_failed
);
335 WasmSectionOrderChecker Checker
;
336 while (Ctx
.Ptr
< Ctx
.End
) {
338 if ((Err
= readSection(Sec
, Ctx
, Checker
)))
340 if ((Err
= parseSection(Sec
)))
343 Sections
.push_back(Sec
);
347 Error
WasmObjectFile::parseSection(WasmSection
&Sec
) {
349 Ctx
.Start
= Sec
.Content
.data();
350 Ctx
.End
= Ctx
.Start
+ Sec
.Content
.size();
353 case wasm::WASM_SEC_CUSTOM
:
354 return parseCustomSection(Sec
, Ctx
);
355 case wasm::WASM_SEC_TYPE
:
356 return parseTypeSection(Ctx
);
357 case wasm::WASM_SEC_IMPORT
:
358 return parseImportSection(Ctx
);
359 case wasm::WASM_SEC_FUNCTION
:
360 return parseFunctionSection(Ctx
);
361 case wasm::WASM_SEC_TABLE
:
362 return parseTableSection(Ctx
);
363 case wasm::WASM_SEC_MEMORY
:
364 return parseMemorySection(Ctx
);
365 case wasm::WASM_SEC_TAG
:
366 return parseTagSection(Ctx
);
367 case wasm::WASM_SEC_GLOBAL
:
368 return parseGlobalSection(Ctx
);
369 case wasm::WASM_SEC_EXPORT
:
370 return parseExportSection(Ctx
);
371 case wasm::WASM_SEC_START
:
372 return parseStartSection(Ctx
);
373 case wasm::WASM_SEC_ELEM
:
374 return parseElemSection(Ctx
);
375 case wasm::WASM_SEC_CODE
:
376 return parseCodeSection(Ctx
);
377 case wasm::WASM_SEC_DATA
:
378 return parseDataSection(Ctx
);
379 case wasm::WASM_SEC_DATACOUNT
:
380 return parseDataCountSection(Ctx
);
382 return make_error
<GenericBinaryError
>(
383 "invalid section type: " + Twine(Sec
.Type
), object_error::parse_failed
);
387 Error
WasmObjectFile::parseDylinkSection(ReadContext
&Ctx
) {
388 // Legacy "dylink" section support.
389 // See parseDylink0Section for the current "dylink.0" section parsing.
390 HasDylinkSection
= true;
391 DylinkInfo
.MemorySize
= readVaruint32(Ctx
);
392 DylinkInfo
.MemoryAlignment
= readVaruint32(Ctx
);
393 DylinkInfo
.TableSize
= readVaruint32(Ctx
);
394 DylinkInfo
.TableAlignment
= readVaruint32(Ctx
);
395 uint32_t Count
= readVaruint32(Ctx
);
397 DylinkInfo
.Needed
.push_back(readString(Ctx
));
400 if (Ctx
.Ptr
!= Ctx
.End
)
401 return make_error
<GenericBinaryError
>("dylink section ended prematurely",
402 object_error::parse_failed
);
403 return Error::success();
406 Error
WasmObjectFile::parseDylink0Section(ReadContext
&Ctx
) {
408 // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
409 HasDylinkSection
= true;
411 const uint8_t *OrigEnd
= Ctx
.End
;
412 while (Ctx
.Ptr
< OrigEnd
) {
414 uint8_t Type
= readUint8(Ctx
);
415 uint32_t Size
= readVaruint32(Ctx
);
416 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type
) << " size=" << Size
418 Ctx
.End
= Ctx
.Ptr
+ Size
;
421 case wasm::WASM_DYLINK_MEM_INFO
:
422 DylinkInfo
.MemorySize
= readVaruint32(Ctx
);
423 DylinkInfo
.MemoryAlignment
= readVaruint32(Ctx
);
424 DylinkInfo
.TableSize
= readVaruint32(Ctx
);
425 DylinkInfo
.TableAlignment
= readVaruint32(Ctx
);
427 case wasm::WASM_DYLINK_NEEDED
:
428 Count
= readVaruint32(Ctx
);
430 DylinkInfo
.Needed
.push_back(readString(Ctx
));
433 case wasm::WASM_DYLINK_EXPORT_INFO
: {
434 uint32_t Count
= readVaruint32(Ctx
);
436 DylinkInfo
.ExportInfo
.push_back({readString(Ctx
), readVaruint32(Ctx
)});
440 case wasm::WASM_DYLINK_IMPORT_INFO
: {
441 uint32_t Count
= readVaruint32(Ctx
);
443 DylinkInfo
.ImportInfo
.push_back(
444 {readString(Ctx
), readString(Ctx
), readVaruint32(Ctx
)});
449 LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type
<< "\n");
453 if (Ctx
.Ptr
!= Ctx
.End
) {
454 return make_error
<GenericBinaryError
>(
455 "dylink.0 sub-section ended prematurely", object_error::parse_failed
);
459 if (Ctx
.Ptr
!= Ctx
.End
)
460 return make_error
<GenericBinaryError
>("dylink.0 section ended prematurely",
461 object_error::parse_failed
);
462 return Error::success();
465 Error
WasmObjectFile::parseNameSection(ReadContext
&Ctx
) {
466 llvm::DenseSet
<uint64_t> SeenFunctions
;
467 llvm::DenseSet
<uint64_t> SeenGlobals
;
468 llvm::DenseSet
<uint64_t> SeenSegments
;
470 while (Ctx
.Ptr
< Ctx
.End
) {
471 uint8_t Type
= readUint8(Ctx
);
472 uint32_t Size
= readVaruint32(Ctx
);
473 const uint8_t *SubSectionEnd
= Ctx
.Ptr
+ Size
;
475 case wasm::WASM_NAMES_FUNCTION
:
476 case wasm::WASM_NAMES_GLOBAL
:
477 case wasm::WASM_NAMES_DATA_SEGMENT
: {
478 uint32_t Count
= readVaruint32(Ctx
);
480 uint32_t Index
= readVaruint32(Ctx
);
481 StringRef Name
= readString(Ctx
);
482 wasm::NameType nameType
= wasm::NameType::FUNCTION
;
483 if (Type
== wasm::WASM_NAMES_FUNCTION
) {
484 if (!SeenFunctions
.insert(Index
).second
)
485 return make_error
<GenericBinaryError
>(
486 "function named more than once", object_error::parse_failed
);
487 if (!isValidFunctionIndex(Index
) || Name
.empty())
488 return make_error
<GenericBinaryError
>("invalid function name entry",
489 object_error::parse_failed
);
491 if (isDefinedFunctionIndex(Index
))
492 getDefinedFunction(Index
).DebugName
= Name
;
493 } else if (Type
== wasm::WASM_NAMES_GLOBAL
) {
494 nameType
= wasm::NameType::GLOBAL
;
495 if (!SeenGlobals
.insert(Index
).second
)
496 return make_error
<GenericBinaryError
>("global named more than once",
497 object_error::parse_failed
);
498 if (!isValidGlobalIndex(Index
) || Name
.empty())
499 return make_error
<GenericBinaryError
>("invalid global name entry",
500 object_error::parse_failed
);
502 nameType
= wasm::NameType::DATA_SEGMENT
;
503 if (!SeenSegments
.insert(Index
).second
)
504 return make_error
<GenericBinaryError
>(
505 "segment named more than once", object_error::parse_failed
);
506 if (Index
> DataSegments
.size())
507 return make_error
<GenericBinaryError
>("invalid data segment name entry",
508 object_error::parse_failed
);
510 DebugNames
.push_back(wasm::WasmDebugName
{nameType
, Index
, Name
});
514 // Ignore local names for now
515 case wasm::WASM_NAMES_LOCAL
:
520 if (Ctx
.Ptr
!= SubSectionEnd
)
521 return make_error
<GenericBinaryError
>(
522 "name sub-section ended prematurely", object_error::parse_failed
);
525 if (Ctx
.Ptr
!= Ctx
.End
)
526 return make_error
<GenericBinaryError
>("name section ended prematurely",
527 object_error::parse_failed
);
528 return Error::success();
531 Error
WasmObjectFile::parseLinkingSection(ReadContext
&Ctx
) {
532 HasLinkingSection
= true;
534 LinkingData
.Version
= readVaruint32(Ctx
);
535 if (LinkingData
.Version
!= wasm::WasmMetadataVersion
) {
536 return make_error
<GenericBinaryError
>(
537 "unexpected metadata version: " + Twine(LinkingData
.Version
) +
538 " (Expected: " + Twine(wasm::WasmMetadataVersion
) + ")",
539 object_error::parse_failed
);
542 const uint8_t *OrigEnd
= Ctx
.End
;
543 while (Ctx
.Ptr
< OrigEnd
) {
545 uint8_t Type
= readUint8(Ctx
);
546 uint32_t Size
= readVaruint32(Ctx
);
547 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type
) << " size=" << Size
549 Ctx
.End
= Ctx
.Ptr
+ Size
;
551 case wasm::WASM_SYMBOL_TABLE
:
552 if (Error Err
= parseLinkingSectionSymtab(Ctx
))
555 case wasm::WASM_SEGMENT_INFO
: {
556 uint32_t Count
= readVaruint32(Ctx
);
557 if (Count
> DataSegments
.size())
558 return make_error
<GenericBinaryError
>("too many segment names",
559 object_error::parse_failed
);
560 for (uint32_t I
= 0; I
< Count
; I
++) {
561 DataSegments
[I
].Data
.Name
= readString(Ctx
);
562 DataSegments
[I
].Data
.Alignment
= readVaruint32(Ctx
);
563 DataSegments
[I
].Data
.LinkingFlags
= readVaruint32(Ctx
);
567 case wasm::WASM_INIT_FUNCS
: {
568 uint32_t Count
= readVaruint32(Ctx
);
569 LinkingData
.InitFunctions
.reserve(Count
);
570 for (uint32_t I
= 0; I
< Count
; I
++) {
571 wasm::WasmInitFunc Init
;
572 Init
.Priority
= readVaruint32(Ctx
);
573 Init
.Symbol
= readVaruint32(Ctx
);
574 if (!isValidFunctionSymbol(Init
.Symbol
))
575 return make_error
<GenericBinaryError
>("invalid function symbol: " +
577 object_error::parse_failed
);
578 LinkingData
.InitFunctions
.emplace_back(Init
);
582 case wasm::WASM_COMDAT_INFO
:
583 if (Error Err
= parseLinkingSectionComdat(Ctx
))
590 if (Ctx
.Ptr
!= Ctx
.End
)
591 return make_error
<GenericBinaryError
>(
592 "linking sub-section ended prematurely", object_error::parse_failed
);
594 if (Ctx
.Ptr
!= OrigEnd
)
595 return make_error
<GenericBinaryError
>("linking section ended prematurely",
596 object_error::parse_failed
);
597 return Error::success();
600 Error
WasmObjectFile::parseLinkingSectionSymtab(ReadContext
&Ctx
) {
601 uint32_t Count
= readVaruint32(Ctx
);
602 LinkingData
.SymbolTable
.reserve(Count
);
603 Symbols
.reserve(Count
);
604 StringSet
<> SymbolNames
;
606 std::vector
<wasm::WasmImport
*> ImportedGlobals
;
607 std::vector
<wasm::WasmImport
*> ImportedFunctions
;
608 std::vector
<wasm::WasmImport
*> ImportedTags
;
609 std::vector
<wasm::WasmImport
*> ImportedTables
;
610 ImportedGlobals
.reserve(Imports
.size());
611 ImportedFunctions
.reserve(Imports
.size());
612 ImportedTags
.reserve(Imports
.size());
613 ImportedTables
.reserve(Imports
.size());
614 for (auto &I
: Imports
) {
615 if (I
.Kind
== wasm::WASM_EXTERNAL_FUNCTION
)
616 ImportedFunctions
.emplace_back(&I
);
617 else if (I
.Kind
== wasm::WASM_EXTERNAL_GLOBAL
)
618 ImportedGlobals
.emplace_back(&I
);
619 else if (I
.Kind
== wasm::WASM_EXTERNAL_TAG
)
620 ImportedTags
.emplace_back(&I
);
621 else if (I
.Kind
== wasm::WASM_EXTERNAL_TABLE
)
622 ImportedTables
.emplace_back(&I
);
626 wasm::WasmSymbolInfo Info
;
627 const wasm::WasmSignature
*Signature
= nullptr;
628 const wasm::WasmGlobalType
*GlobalType
= nullptr;
629 const wasm::WasmTableType
*TableType
= nullptr;
631 Info
.Kind
= readUint8(Ctx
);
632 Info
.Flags
= readVaruint32(Ctx
);
633 bool IsDefined
= (Info
.Flags
& wasm::WASM_SYMBOL_UNDEFINED
) == 0;
636 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
637 Info
.ElementIndex
= readVaruint32(Ctx
);
638 if (!isValidFunctionIndex(Info
.ElementIndex
) ||
639 IsDefined
!= isDefinedFunctionIndex(Info
.ElementIndex
))
640 return make_error
<GenericBinaryError
>("invalid function symbol index",
641 object_error::parse_failed
);
643 Info
.Name
= readString(Ctx
);
644 unsigned FuncIndex
= Info
.ElementIndex
- NumImportedFunctions
;
645 wasm::WasmFunction
&Function
= Functions
[FuncIndex
];
646 Signature
= &Signatures
[Function
.SigIndex
];
647 if (Function
.SymbolName
.empty())
648 Function
.SymbolName
= Info
.Name
;
650 wasm::WasmImport
&Import
= *ImportedFunctions
[Info
.ElementIndex
];
651 if ((Info
.Flags
& wasm::WASM_SYMBOL_EXPLICIT_NAME
) != 0) {
652 Info
.Name
= readString(Ctx
);
653 Info
.ImportName
= Import
.Field
;
655 Info
.Name
= Import
.Field
;
657 Signature
= &Signatures
[Import
.SigIndex
];
658 Info
.ImportModule
= Import
.Module
;
662 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
663 Info
.ElementIndex
= readVaruint32(Ctx
);
664 if (!isValidGlobalIndex(Info
.ElementIndex
) ||
665 IsDefined
!= isDefinedGlobalIndex(Info
.ElementIndex
))
666 return make_error
<GenericBinaryError
>("invalid global symbol index",
667 object_error::parse_failed
);
668 if (!IsDefined
&& (Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) ==
669 wasm::WASM_SYMBOL_BINDING_WEAK
)
670 return make_error
<GenericBinaryError
>("undefined weak global symbol",
671 object_error::parse_failed
);
673 Info
.Name
= readString(Ctx
);
674 unsigned GlobalIndex
= Info
.ElementIndex
- NumImportedGlobals
;
675 wasm::WasmGlobal
&Global
= Globals
[GlobalIndex
];
676 GlobalType
= &Global
.Type
;
677 if (Global
.SymbolName
.empty())
678 Global
.SymbolName
= Info
.Name
;
680 wasm::WasmImport
&Import
= *ImportedGlobals
[Info
.ElementIndex
];
681 if ((Info
.Flags
& wasm::WASM_SYMBOL_EXPLICIT_NAME
) != 0) {
682 Info
.Name
= readString(Ctx
);
683 Info
.ImportName
= Import
.Field
;
685 Info
.Name
= Import
.Field
;
687 GlobalType
= &Import
.Global
;
688 Info
.ImportModule
= Import
.Module
;
692 case wasm::WASM_SYMBOL_TYPE_TABLE
:
693 Info
.ElementIndex
= readVaruint32(Ctx
);
694 if (!isValidTableNumber(Info
.ElementIndex
) ||
695 IsDefined
!= isDefinedTableNumber(Info
.ElementIndex
))
696 return make_error
<GenericBinaryError
>("invalid table symbol index",
697 object_error::parse_failed
);
698 if (!IsDefined
&& (Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) ==
699 wasm::WASM_SYMBOL_BINDING_WEAK
)
700 return make_error
<GenericBinaryError
>("undefined weak table symbol",
701 object_error::parse_failed
);
703 Info
.Name
= readString(Ctx
);
704 unsigned TableNumber
= Info
.ElementIndex
- NumImportedTables
;
705 wasm::WasmTable
&Table
= Tables
[TableNumber
];
706 TableType
= &Table
.Type
;
707 if (Table
.SymbolName
.empty())
708 Table
.SymbolName
= Info
.Name
;
710 wasm::WasmImport
&Import
= *ImportedTables
[Info
.ElementIndex
];
711 if ((Info
.Flags
& wasm::WASM_SYMBOL_EXPLICIT_NAME
) != 0) {
712 Info
.Name
= readString(Ctx
);
713 Info
.ImportName
= Import
.Field
;
715 Info
.Name
= Import
.Field
;
717 TableType
= &Import
.Table
;
718 Info
.ImportModule
= Import
.Module
;
722 case wasm::WASM_SYMBOL_TYPE_DATA
:
723 Info
.Name
= readString(Ctx
);
725 auto Index
= readVaruint32(Ctx
);
726 auto Offset
= readVaruint64(Ctx
);
727 auto Size
= readVaruint64(Ctx
);
728 if (!(Info
.Flags
& wasm::WASM_SYMBOL_ABSOLUTE
)) {
729 if (static_cast<size_t>(Index
) >= DataSegments
.size())
730 return make_error
<GenericBinaryError
>(
731 "invalid data segment index: " + Twine(Index
),
732 object_error::parse_failed
);
733 size_t SegmentSize
= DataSegments
[Index
].Data
.Content
.size();
734 if (Offset
> SegmentSize
)
735 return make_error
<GenericBinaryError
>(
736 "invalid data symbol offset: `" + Info
.Name
+
737 "` (offset: " + Twine(Offset
) +
738 " segment size: " + Twine(SegmentSize
) + ")",
739 object_error::parse_failed
);
741 Info
.DataRef
= wasm::WasmDataReference
{Index
, Offset
, Size
};
745 case wasm::WASM_SYMBOL_TYPE_SECTION
: {
746 if ((Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) !=
747 wasm::WASM_SYMBOL_BINDING_LOCAL
)
748 return make_error
<GenericBinaryError
>(
749 "section symbols must have local binding",
750 object_error::parse_failed
);
751 Info
.ElementIndex
= readVaruint32(Ctx
);
752 // Use somewhat unique section name as symbol name.
753 StringRef SectionName
= Sections
[Info
.ElementIndex
].Name
;
754 Info
.Name
= SectionName
;
758 case wasm::WASM_SYMBOL_TYPE_TAG
: {
759 Info
.ElementIndex
= readVaruint32(Ctx
);
760 if (!isValidTagIndex(Info
.ElementIndex
) ||
761 IsDefined
!= isDefinedTagIndex(Info
.ElementIndex
))
762 return make_error
<GenericBinaryError
>("invalid tag symbol index",
763 object_error::parse_failed
);
764 if (!IsDefined
&& (Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) ==
765 wasm::WASM_SYMBOL_BINDING_WEAK
)
766 return make_error
<GenericBinaryError
>("undefined weak global symbol",
767 object_error::parse_failed
);
769 Info
.Name
= readString(Ctx
);
770 unsigned TagIndex
= Info
.ElementIndex
- NumImportedTags
;
771 wasm::WasmTag
&Tag
= Tags
[TagIndex
];
772 Signature
= &Signatures
[Tag
.SigIndex
];
773 if (Tag
.SymbolName
.empty())
774 Tag
.SymbolName
= Info
.Name
;
777 wasm::WasmImport
&Import
= *ImportedTags
[Info
.ElementIndex
];
778 if ((Info
.Flags
& wasm::WASM_SYMBOL_EXPLICIT_NAME
) != 0) {
779 Info
.Name
= readString(Ctx
);
780 Info
.ImportName
= Import
.Field
;
782 Info
.Name
= Import
.Field
;
784 Signature
= &Signatures
[Import
.SigIndex
];
785 Info
.ImportModule
= Import
.Module
;
791 return make_error
<GenericBinaryError
>("invalid symbol type: " +
792 Twine(unsigned(Info
.Kind
)),
793 object_error::parse_failed
);
796 if ((Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) !=
797 wasm::WASM_SYMBOL_BINDING_LOCAL
&&
798 !SymbolNames
.insert(Info
.Name
).second
)
799 return make_error
<GenericBinaryError
>("duplicate symbol name " +
801 object_error::parse_failed
);
802 LinkingData
.SymbolTable
.emplace_back(Info
);
803 Symbols
.emplace_back(LinkingData
.SymbolTable
.back(), GlobalType
, TableType
,
805 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols
.back() << "\n");
808 return Error::success();
811 Error
WasmObjectFile::parseLinkingSectionComdat(ReadContext
&Ctx
) {
812 uint32_t ComdatCount
= readVaruint32(Ctx
);
813 StringSet
<> ComdatSet
;
814 for (unsigned ComdatIndex
= 0; ComdatIndex
< ComdatCount
; ++ComdatIndex
) {
815 StringRef Name
= readString(Ctx
);
816 if (Name
.empty() || !ComdatSet
.insert(Name
).second
)
817 return make_error
<GenericBinaryError
>("bad/duplicate COMDAT name " +
819 object_error::parse_failed
);
820 LinkingData
.Comdats
.emplace_back(Name
);
821 uint32_t Flags
= readVaruint32(Ctx
);
823 return make_error
<GenericBinaryError
>("unsupported COMDAT flags",
824 object_error::parse_failed
);
826 uint32_t EntryCount
= readVaruint32(Ctx
);
827 while (EntryCount
--) {
828 unsigned Kind
= readVaruint32(Ctx
);
829 unsigned Index
= readVaruint32(Ctx
);
832 return make_error
<GenericBinaryError
>("invalid COMDAT entry type",
833 object_error::parse_failed
);
834 case wasm::WASM_COMDAT_DATA
:
835 if (Index
>= DataSegments
.size())
836 return make_error
<GenericBinaryError
>(
837 "COMDAT data index out of range", object_error::parse_failed
);
838 if (DataSegments
[Index
].Data
.Comdat
!= UINT32_MAX
)
839 return make_error
<GenericBinaryError
>("data segment in two COMDATs",
840 object_error::parse_failed
);
841 DataSegments
[Index
].Data
.Comdat
= ComdatIndex
;
843 case wasm::WASM_COMDAT_FUNCTION
:
844 if (!isDefinedFunctionIndex(Index
))
845 return make_error
<GenericBinaryError
>(
846 "COMDAT function index out of range", object_error::parse_failed
);
847 if (getDefinedFunction(Index
).Comdat
!= UINT32_MAX
)
848 return make_error
<GenericBinaryError
>("function in two COMDATs",
849 object_error::parse_failed
);
850 getDefinedFunction(Index
).Comdat
= ComdatIndex
;
852 case wasm::WASM_COMDAT_SECTION
:
853 if (Index
>= Sections
.size())
854 return make_error
<GenericBinaryError
>(
855 "COMDAT section index out of range", object_error::parse_failed
);
856 if (Sections
[Index
].Type
!= wasm::WASM_SEC_CUSTOM
)
857 return make_error
<GenericBinaryError
>(
858 "non-custom section in a COMDAT", object_error::parse_failed
);
859 Sections
[Index
].Comdat
= ComdatIndex
;
864 return Error::success();
867 Error
WasmObjectFile::parseProducersSection(ReadContext
&Ctx
) {
868 llvm::SmallSet
<StringRef
, 3> FieldsSeen
;
869 uint32_t Fields
= readVaruint32(Ctx
);
870 for (size_t I
= 0; I
< Fields
; ++I
) {
871 StringRef FieldName
= readString(Ctx
);
872 if (!FieldsSeen
.insert(FieldName
).second
)
873 return make_error
<GenericBinaryError
>(
874 "producers section does not have unique fields",
875 object_error::parse_failed
);
876 std::vector
<std::pair
<std::string
, std::string
>> *ProducerVec
= nullptr;
877 if (FieldName
== "language") {
878 ProducerVec
= &ProducerInfo
.Languages
;
879 } else if (FieldName
== "processed-by") {
880 ProducerVec
= &ProducerInfo
.Tools
;
881 } else if (FieldName
== "sdk") {
882 ProducerVec
= &ProducerInfo
.SDKs
;
884 return make_error
<GenericBinaryError
>(
885 "producers section field is not named one of language, processed-by, "
887 object_error::parse_failed
);
889 uint32_t ValueCount
= readVaruint32(Ctx
);
890 llvm::SmallSet
<StringRef
, 8> ProducersSeen
;
891 for (size_t J
= 0; J
< ValueCount
; ++J
) {
892 StringRef Name
= readString(Ctx
);
893 StringRef Version
= readString(Ctx
);
894 if (!ProducersSeen
.insert(Name
).second
) {
895 return make_error
<GenericBinaryError
>(
896 "producers section contains repeated producer",
897 object_error::parse_failed
);
899 ProducerVec
->emplace_back(std::string(Name
), std::string(Version
));
902 if (Ctx
.Ptr
!= Ctx
.End
)
903 return make_error
<GenericBinaryError
>("producers section ended prematurely",
904 object_error::parse_failed
);
905 return Error::success();
908 Error
WasmObjectFile::parseTargetFeaturesSection(ReadContext
&Ctx
) {
909 llvm::SmallSet
<std::string
, 8> FeaturesSeen
;
910 uint32_t FeatureCount
= readVaruint32(Ctx
);
911 for (size_t I
= 0; I
< FeatureCount
; ++I
) {
912 wasm::WasmFeatureEntry Feature
;
913 Feature
.Prefix
= readUint8(Ctx
);
914 switch (Feature
.Prefix
) {
915 case wasm::WASM_FEATURE_PREFIX_USED
:
916 case wasm::WASM_FEATURE_PREFIX_REQUIRED
:
917 case wasm::WASM_FEATURE_PREFIX_DISALLOWED
:
920 return make_error
<GenericBinaryError
>("unknown feature policy prefix",
921 object_error::parse_failed
);
923 Feature
.Name
= std::string(readString(Ctx
));
924 if (!FeaturesSeen
.insert(Feature
.Name
).second
)
925 return make_error
<GenericBinaryError
>(
926 "target features section contains repeated feature \"" +
928 object_error::parse_failed
);
929 TargetFeatures
.push_back(Feature
);
931 if (Ctx
.Ptr
!= Ctx
.End
)
932 return make_error
<GenericBinaryError
>(
933 "target features section ended prematurely",
934 object_error::parse_failed
);
935 return Error::success();
938 Error
WasmObjectFile::parseRelocSection(StringRef Name
, ReadContext
&Ctx
) {
939 uint32_t SectionIndex
= readVaruint32(Ctx
);
940 if (SectionIndex
>= Sections
.size())
941 return make_error
<GenericBinaryError
>("invalid section index",
942 object_error::parse_failed
);
943 WasmSection
&Section
= Sections
[SectionIndex
];
944 uint32_t RelocCount
= readVaruint32(Ctx
);
945 uint32_t EndOffset
= Section
.Content
.size();
946 uint32_t PreviousOffset
= 0;
947 while (RelocCount
--) {
948 wasm::WasmRelocation Reloc
= {};
949 uint32_t type
= readVaruint32(Ctx
);
951 Reloc
.Offset
= readVaruint32(Ctx
);
952 if (Reloc
.Offset
< PreviousOffset
)
953 return make_error
<GenericBinaryError
>("relocations not in offset order",
954 object_error::parse_failed
);
955 PreviousOffset
= Reloc
.Offset
;
956 Reloc
.Index
= readVaruint32(Ctx
);
958 case wasm::R_WASM_FUNCTION_INDEX_LEB
:
959 case wasm::R_WASM_FUNCTION_INDEX_I32
:
960 case wasm::R_WASM_TABLE_INDEX_SLEB
:
961 case wasm::R_WASM_TABLE_INDEX_SLEB64
:
962 case wasm::R_WASM_TABLE_INDEX_I32
:
963 case wasm::R_WASM_TABLE_INDEX_I64
:
964 case wasm::R_WASM_TABLE_INDEX_REL_SLEB
:
965 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64
:
966 if (!isValidFunctionSymbol(Reloc
.Index
))
967 return make_error
<GenericBinaryError
>(
968 "invalid relocation function index", object_error::parse_failed
);
970 case wasm::R_WASM_TABLE_NUMBER_LEB
:
971 if (!isValidTableSymbol(Reloc
.Index
))
972 return make_error
<GenericBinaryError
>("invalid relocation table index",
973 object_error::parse_failed
);
975 case wasm::R_WASM_TYPE_INDEX_LEB
:
976 if (Reloc
.Index
>= Signatures
.size())
977 return make_error
<GenericBinaryError
>("invalid relocation type index",
978 object_error::parse_failed
);
980 case wasm::R_WASM_GLOBAL_INDEX_LEB
:
981 // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
982 // symbols to refer to their GOT entries.
983 if (!isValidGlobalSymbol(Reloc
.Index
) &&
984 !isValidDataSymbol(Reloc
.Index
) &&
985 !isValidFunctionSymbol(Reloc
.Index
))
986 return make_error
<GenericBinaryError
>("invalid relocation global index",
987 object_error::parse_failed
);
989 case wasm::R_WASM_GLOBAL_INDEX_I32
:
990 if (!isValidGlobalSymbol(Reloc
.Index
))
991 return make_error
<GenericBinaryError
>("invalid relocation global index",
992 object_error::parse_failed
);
994 case wasm::R_WASM_TAG_INDEX_LEB
:
995 if (!isValidTagSymbol(Reloc
.Index
))
996 return make_error
<GenericBinaryError
>("invalid relocation tag index",
997 object_error::parse_failed
);
999 case wasm::R_WASM_MEMORY_ADDR_LEB
:
1000 case wasm::R_WASM_MEMORY_ADDR_SLEB
:
1001 case wasm::R_WASM_MEMORY_ADDR_I32
:
1002 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB
:
1003 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB
:
1004 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32
:
1005 if (!isValidDataSymbol(Reloc
.Index
))
1006 return make_error
<GenericBinaryError
>("invalid relocation data index",
1007 object_error::parse_failed
);
1008 Reloc
.Addend
= readVarint32(Ctx
);
1010 case wasm::R_WASM_MEMORY_ADDR_LEB64
:
1011 case wasm::R_WASM_MEMORY_ADDR_SLEB64
:
1012 case wasm::R_WASM_MEMORY_ADDR_I64
:
1013 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64
:
1014 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64
:
1015 if (!isValidDataSymbol(Reloc
.Index
))
1016 return make_error
<GenericBinaryError
>("invalid relocation data index",
1017 object_error::parse_failed
);
1018 Reloc
.Addend
= readVarint64(Ctx
);
1020 case wasm::R_WASM_FUNCTION_OFFSET_I32
:
1021 if (!isValidFunctionSymbol(Reloc
.Index
))
1022 return make_error
<GenericBinaryError
>(
1023 "invalid relocation function index", object_error::parse_failed
);
1024 Reloc
.Addend
= readVarint32(Ctx
);
1026 case wasm::R_WASM_FUNCTION_OFFSET_I64
:
1027 if (!isValidFunctionSymbol(Reloc
.Index
))
1028 return make_error
<GenericBinaryError
>(
1029 "invalid relocation function index", object_error::parse_failed
);
1030 Reloc
.Addend
= readVarint64(Ctx
);
1032 case wasm::R_WASM_SECTION_OFFSET_I32
:
1033 if (!isValidSectionSymbol(Reloc
.Index
))
1034 return make_error
<GenericBinaryError
>(
1035 "invalid relocation section index", object_error::parse_failed
);
1036 Reloc
.Addend
= readVarint32(Ctx
);
1039 return make_error
<GenericBinaryError
>("invalid relocation type: " +
1041 object_error::parse_failed
);
1044 // Relocations must fit inside the section, and must appear in order. They
1045 // also shouldn't overlap a function/element boundary, but we don't bother
1048 if (Reloc
.Type
== wasm::R_WASM_MEMORY_ADDR_LEB64
||
1049 Reloc
.Type
== wasm::R_WASM_MEMORY_ADDR_SLEB64
||
1050 Reloc
.Type
== wasm::R_WASM_MEMORY_ADDR_REL_SLEB64
)
1052 if (Reloc
.Type
== wasm::R_WASM_TABLE_INDEX_I32
||
1053 Reloc
.Type
== wasm::R_WASM_MEMORY_ADDR_I32
||
1054 Reloc
.Type
== wasm::R_WASM_MEMORY_ADDR_LOCREL_I32
||
1055 Reloc
.Type
== wasm::R_WASM_SECTION_OFFSET_I32
||
1056 Reloc
.Type
== wasm::R_WASM_FUNCTION_OFFSET_I32
||
1057 Reloc
.Type
== wasm::R_WASM_FUNCTION_INDEX_I32
||
1058 Reloc
.Type
== wasm::R_WASM_GLOBAL_INDEX_I32
)
1060 if (Reloc
.Type
== wasm::R_WASM_TABLE_INDEX_I64
||
1061 Reloc
.Type
== wasm::R_WASM_MEMORY_ADDR_I64
||
1062 Reloc
.Type
== wasm::R_WASM_FUNCTION_OFFSET_I64
)
1064 if (Reloc
.Offset
+ Size
> EndOffset
)
1065 return make_error
<GenericBinaryError
>("invalid relocation offset",
1066 object_error::parse_failed
);
1068 Section
.Relocations
.push_back(Reloc
);
1070 if (Ctx
.Ptr
!= Ctx
.End
)
1071 return make_error
<GenericBinaryError
>("reloc section ended prematurely",
1072 object_error::parse_failed
);
1073 return Error::success();
1076 Error
WasmObjectFile::parseCustomSection(WasmSection
&Sec
, ReadContext
&Ctx
) {
1077 if (Sec
.Name
== "dylink") {
1078 if (Error Err
= parseDylinkSection(Ctx
))
1080 } else if (Sec
.Name
== "dylink.0") {
1081 if (Error Err
= parseDylink0Section(Ctx
))
1083 } else if (Sec
.Name
== "name") {
1084 if (Error Err
= parseNameSection(Ctx
))
1086 } else if (Sec
.Name
== "linking") {
1087 if (Error Err
= parseLinkingSection(Ctx
))
1089 } else if (Sec
.Name
== "producers") {
1090 if (Error Err
= parseProducersSection(Ctx
))
1092 } else if (Sec
.Name
== "target_features") {
1093 if (Error Err
= parseTargetFeaturesSection(Ctx
))
1095 } else if (Sec
.Name
.startswith("reloc.")) {
1096 if (Error Err
= parseRelocSection(Sec
.Name
, Ctx
))
1099 return Error::success();
1102 Error
WasmObjectFile::parseTypeSection(ReadContext
&Ctx
) {
1103 uint32_t Count
= readVaruint32(Ctx
);
1104 Signatures
.reserve(Count
);
1106 wasm::WasmSignature Sig
;
1107 uint8_t Form
= readUint8(Ctx
);
1108 if (Form
!= wasm::WASM_TYPE_FUNC
) {
1109 return make_error
<GenericBinaryError
>("invalid signature type",
1110 object_error::parse_failed
);
1112 uint32_t ParamCount
= readVaruint32(Ctx
);
1113 Sig
.Params
.reserve(ParamCount
);
1114 while (ParamCount
--) {
1115 uint32_t ParamType
= readUint8(Ctx
);
1116 Sig
.Params
.push_back(wasm::ValType(ParamType
));
1118 uint32_t ReturnCount
= readVaruint32(Ctx
);
1119 while (ReturnCount
--) {
1120 uint32_t ReturnType
= readUint8(Ctx
);
1121 Sig
.Returns
.push_back(wasm::ValType(ReturnType
));
1123 Signatures
.push_back(std::move(Sig
));
1125 if (Ctx
.Ptr
!= Ctx
.End
)
1126 return make_error
<GenericBinaryError
>("type section ended prematurely",
1127 object_error::parse_failed
);
1128 return Error::success();
1131 Error
WasmObjectFile::parseImportSection(ReadContext
&Ctx
) {
1132 uint32_t Count
= readVaruint32(Ctx
);
1133 uint32_t NumTypes
= Signatures
.size();
1134 Imports
.reserve(Count
);
1135 for (uint32_t I
= 0; I
< Count
; I
++) {
1136 wasm::WasmImport Im
;
1137 Im
.Module
= readString(Ctx
);
1138 Im
.Field
= readString(Ctx
);
1139 Im
.Kind
= readUint8(Ctx
);
1141 case wasm::WASM_EXTERNAL_FUNCTION
:
1142 NumImportedFunctions
++;
1143 Im
.SigIndex
= readVaruint32(Ctx
);
1144 if (Im
.SigIndex
>= NumTypes
)
1145 return make_error
<GenericBinaryError
>("invalid function type",
1146 object_error::parse_failed
);
1148 case wasm::WASM_EXTERNAL_GLOBAL
:
1149 NumImportedGlobals
++;
1150 Im
.Global
.Type
= readUint8(Ctx
);
1151 Im
.Global
.Mutable
= readVaruint1(Ctx
);
1153 case wasm::WASM_EXTERNAL_MEMORY
:
1154 Im
.Memory
= readLimits(Ctx
);
1155 if (Im
.Memory
.Flags
& wasm::WASM_LIMITS_FLAG_IS_64
)
1158 case wasm::WASM_EXTERNAL_TABLE
: {
1159 Im
.Table
= readTableType(Ctx
);
1160 NumImportedTables
++;
1161 auto ElemType
= Im
.Table
.ElemType
;
1162 if (ElemType
!= wasm::WASM_TYPE_FUNCREF
&&
1163 ElemType
!= wasm::WASM_TYPE_EXTERNREF
)
1164 return make_error
<GenericBinaryError
>("invalid table element type",
1165 object_error::parse_failed
);
1168 case wasm::WASM_EXTERNAL_TAG
:
1170 if (readUint8(Ctx
) != 0) // Reserved 'attribute' field
1171 return make_error
<GenericBinaryError
>("invalid attribute",
1172 object_error::parse_failed
);
1173 Im
.SigIndex
= readVaruint32(Ctx
);
1174 if (Im
.SigIndex
>= NumTypes
)
1175 return make_error
<GenericBinaryError
>("invalid tag type",
1176 object_error::parse_failed
);
1179 return make_error
<GenericBinaryError
>("unexpected import kind",
1180 object_error::parse_failed
);
1182 Imports
.push_back(Im
);
1184 if (Ctx
.Ptr
!= Ctx
.End
)
1185 return make_error
<GenericBinaryError
>("import section ended prematurely",
1186 object_error::parse_failed
);
1187 return Error::success();
1190 Error
WasmObjectFile::parseFunctionSection(ReadContext
&Ctx
) {
1191 uint32_t Count
= readVaruint32(Ctx
);
1192 Functions
.reserve(Count
);
1193 uint32_t NumTypes
= Signatures
.size();
1195 uint32_t Type
= readVaruint32(Ctx
);
1196 if (Type
>= NumTypes
)
1197 return make_error
<GenericBinaryError
>("invalid function type",
1198 object_error::parse_failed
);
1199 wasm::WasmFunction F
;
1201 Functions
.push_back(F
);
1203 if (Ctx
.Ptr
!= Ctx
.End
)
1204 return make_error
<GenericBinaryError
>("function section ended prematurely",
1205 object_error::parse_failed
);
1206 return Error::success();
1209 Error
WasmObjectFile::parseTableSection(ReadContext
&Ctx
) {
1210 TableSection
= Sections
.size();
1211 uint32_t Count
= readVaruint32(Ctx
);
1212 Tables
.reserve(Count
);
1215 T
.Type
= readTableType(Ctx
);
1216 T
.Index
= NumImportedTables
+ Tables
.size();
1217 Tables
.push_back(T
);
1218 auto ElemType
= Tables
.back().Type
.ElemType
;
1219 if (ElemType
!= wasm::WASM_TYPE_FUNCREF
&&
1220 ElemType
!= wasm::WASM_TYPE_EXTERNREF
) {
1221 return make_error
<GenericBinaryError
>("invalid table element type",
1222 object_error::parse_failed
);
1225 if (Ctx
.Ptr
!= Ctx
.End
)
1226 return make_error
<GenericBinaryError
>("table section ended prematurely",
1227 object_error::parse_failed
);
1228 return Error::success();
1231 Error
WasmObjectFile::parseMemorySection(ReadContext
&Ctx
) {
1232 uint32_t Count
= readVaruint32(Ctx
);
1233 Memories
.reserve(Count
);
1235 auto Limits
= readLimits(Ctx
);
1236 if (Limits
.Flags
& wasm::WASM_LIMITS_FLAG_IS_64
)
1238 Memories
.push_back(Limits
);
1240 if (Ctx
.Ptr
!= Ctx
.End
)
1241 return make_error
<GenericBinaryError
>("memory section ended prematurely",
1242 object_error::parse_failed
);
1243 return Error::success();
1246 Error
WasmObjectFile::parseTagSection(ReadContext
&Ctx
) {
1247 TagSection
= Sections
.size();
1248 uint32_t Count
= readVaruint32(Ctx
);
1249 Tags
.reserve(Count
);
1250 uint32_t NumTypes
= Signatures
.size();
1252 if (readUint8(Ctx
) != 0) // Reserved 'attribute' field
1253 return make_error
<GenericBinaryError
>("invalid attribute",
1254 object_error::parse_failed
);
1255 uint32_t Type
= readVaruint32(Ctx
);
1256 if (Type
>= NumTypes
)
1257 return make_error
<GenericBinaryError
>("invalid tag type",
1258 object_error::parse_failed
);
1260 Tag
.Index
= NumImportedTags
+ Tags
.size();
1261 Tag
.SigIndex
= Type
;
1262 Tags
.push_back(Tag
);
1265 if (Ctx
.Ptr
!= Ctx
.End
)
1266 return make_error
<GenericBinaryError
>("tag section ended prematurely",
1267 object_error::parse_failed
);
1268 return Error::success();
1271 Error
WasmObjectFile::parseGlobalSection(ReadContext
&Ctx
) {
1272 GlobalSection
= Sections
.size();
1273 uint32_t Count
= readVaruint32(Ctx
);
1274 Globals
.reserve(Count
);
1276 wasm::WasmGlobal Global
;
1277 Global
.Index
= NumImportedGlobals
+ Globals
.size();
1278 Global
.Type
.Type
= readUint8(Ctx
);
1279 Global
.Type
.Mutable
= readVaruint1(Ctx
);
1280 if (Error Err
= readInitExpr(Global
.InitExpr
, Ctx
))
1282 Globals
.push_back(Global
);
1284 if (Ctx
.Ptr
!= Ctx
.End
)
1285 return make_error
<GenericBinaryError
>("global section ended prematurely",
1286 object_error::parse_failed
);
1287 return Error::success();
1290 Error
WasmObjectFile::parseExportSection(ReadContext
&Ctx
) {
1291 uint32_t Count
= readVaruint32(Ctx
);
1292 Exports
.reserve(Count
);
1293 for (uint32_t I
= 0; I
< Count
; I
++) {
1294 wasm::WasmExport Ex
;
1295 Ex
.Name
= readString(Ctx
);
1296 Ex
.Kind
= readUint8(Ctx
);
1297 Ex
.Index
= readVaruint32(Ctx
);
1299 case wasm::WASM_EXTERNAL_FUNCTION
:
1301 if (!isDefinedFunctionIndex(Ex
.Index
))
1302 return make_error
<GenericBinaryError
>("invalid function export",
1303 object_error::parse_failed
);
1304 getDefinedFunction(Ex
.Index
).ExportName
= Ex
.Name
;
1306 case wasm::WASM_EXTERNAL_GLOBAL
:
1307 if (!isValidGlobalIndex(Ex
.Index
))
1308 return make_error
<GenericBinaryError
>("invalid global export",
1309 object_error::parse_failed
);
1311 case wasm::WASM_EXTERNAL_TAG
:
1312 if (!isValidTagIndex(Ex
.Index
))
1313 return make_error
<GenericBinaryError
>("invalid tag export",
1314 object_error::parse_failed
);
1316 case wasm::WASM_EXTERNAL_MEMORY
:
1317 case wasm::WASM_EXTERNAL_TABLE
:
1320 return make_error
<GenericBinaryError
>("unexpected export kind",
1321 object_error::parse_failed
);
1323 Exports
.push_back(Ex
);
1325 if (Ctx
.Ptr
!= Ctx
.End
)
1326 return make_error
<GenericBinaryError
>("export section ended prematurely",
1327 object_error::parse_failed
);
1328 return Error::success();
1331 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index
) const {
1332 return Index
< NumImportedFunctions
+ Functions
.size();
1335 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index
) const {
1336 return Index
>= NumImportedFunctions
&& isValidFunctionIndex(Index
);
1339 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index
) const {
1340 return Index
< NumImportedGlobals
+ Globals
.size();
1343 bool WasmObjectFile::isValidTableNumber(uint32_t Index
) const {
1344 return Index
< NumImportedTables
+ Tables
.size();
1347 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index
) const {
1348 return Index
>= NumImportedGlobals
&& isValidGlobalIndex(Index
);
1351 bool WasmObjectFile::isDefinedTableNumber(uint32_t Index
) const {
1352 return Index
>= NumImportedTables
&& isValidTableNumber(Index
);
1355 bool WasmObjectFile::isValidTagIndex(uint32_t Index
) const {
1356 return Index
< NumImportedTags
+ Tags
.size();
1359 bool WasmObjectFile::isDefinedTagIndex(uint32_t Index
) const {
1360 return Index
>= NumImportedTags
&& isValidTagIndex(Index
);
1363 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index
) const {
1364 return Index
< Symbols
.size() && Symbols
[Index
].isTypeFunction();
1367 bool WasmObjectFile::isValidTableSymbol(uint32_t Index
) const {
1368 return Index
< Symbols
.size() && Symbols
[Index
].isTypeTable();
1371 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index
) const {
1372 return Index
< Symbols
.size() && Symbols
[Index
].isTypeGlobal();
1375 bool WasmObjectFile::isValidTagSymbol(uint32_t Index
) const {
1376 return Index
< Symbols
.size() && Symbols
[Index
].isTypeTag();
1379 bool WasmObjectFile::isValidDataSymbol(uint32_t Index
) const {
1380 return Index
< Symbols
.size() && Symbols
[Index
].isTypeData();
1383 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index
) const {
1384 return Index
< Symbols
.size() && Symbols
[Index
].isTypeSection();
1387 wasm::WasmFunction
&WasmObjectFile::getDefinedFunction(uint32_t Index
) {
1388 assert(isDefinedFunctionIndex(Index
));
1389 return Functions
[Index
- NumImportedFunctions
];
1392 const wasm::WasmFunction
&
1393 WasmObjectFile::getDefinedFunction(uint32_t Index
) const {
1394 assert(isDefinedFunctionIndex(Index
));
1395 return Functions
[Index
- NumImportedFunctions
];
1398 wasm::WasmGlobal
&WasmObjectFile::getDefinedGlobal(uint32_t Index
) {
1399 assert(isDefinedGlobalIndex(Index
));
1400 return Globals
[Index
- NumImportedGlobals
];
1403 wasm::WasmTag
&WasmObjectFile::getDefinedTag(uint32_t Index
) {
1404 assert(isDefinedTagIndex(Index
));
1405 return Tags
[Index
- NumImportedTags
];
1408 Error
WasmObjectFile::parseStartSection(ReadContext
&Ctx
) {
1409 StartFunction
= readVaruint32(Ctx
);
1410 if (!isValidFunctionIndex(StartFunction
))
1411 return make_error
<GenericBinaryError
>("invalid start function",
1412 object_error::parse_failed
);
1413 return Error::success();
1416 Error
WasmObjectFile::parseCodeSection(ReadContext
&Ctx
) {
1417 CodeSection
= Sections
.size();
1418 uint32_t FunctionCount
= readVaruint32(Ctx
);
1419 if (FunctionCount
!= Functions
.size()) {
1420 return make_error
<GenericBinaryError
>("invalid function count",
1421 object_error::parse_failed
);
1424 for (uint32_t i
= 0; i
< FunctionCount
; i
++) {
1425 wasm::WasmFunction
& Function
= Functions
[i
];
1426 const uint8_t *FunctionStart
= Ctx
.Ptr
;
1427 uint32_t Size
= readVaruint32(Ctx
);
1428 const uint8_t *FunctionEnd
= Ctx
.Ptr
+ Size
;
1430 Function
.CodeOffset
= Ctx
.Ptr
- FunctionStart
;
1431 Function
.Index
= NumImportedFunctions
+ i
;
1432 Function
.CodeSectionOffset
= FunctionStart
- Ctx
.Start
;
1433 Function
.Size
= FunctionEnd
- FunctionStart
;
1435 uint32_t NumLocalDecls
= readVaruint32(Ctx
);
1436 Function
.Locals
.reserve(NumLocalDecls
);
1437 while (NumLocalDecls
--) {
1438 wasm::WasmLocalDecl Decl
;
1439 Decl
.Count
= readVaruint32(Ctx
);
1440 Decl
.Type
= readUint8(Ctx
);
1441 Function
.Locals
.push_back(Decl
);
1444 uint32_t BodySize
= FunctionEnd
- Ctx
.Ptr
;
1445 Function
.Body
= ArrayRef
<uint8_t>(Ctx
.Ptr
, BodySize
);
1446 // This will be set later when reading in the linking metadata section.
1447 Function
.Comdat
= UINT32_MAX
;
1448 Ctx
.Ptr
+= BodySize
;
1449 assert(Ctx
.Ptr
== FunctionEnd
);
1451 if (Ctx
.Ptr
!= Ctx
.End
)
1452 return make_error
<GenericBinaryError
>("code section ended prematurely",
1453 object_error::parse_failed
);
1454 return Error::success();
1457 Error
WasmObjectFile::parseElemSection(ReadContext
&Ctx
) {
1458 uint32_t Count
= readVaruint32(Ctx
);
1459 ElemSegments
.reserve(Count
);
1461 wasm::WasmElemSegment Segment
;
1462 Segment
.Flags
= readVaruint32(Ctx
);
1464 uint32_t SupportedFlags
= wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
|
1465 wasm::WASM_ELEM_SEGMENT_IS_PASSIVE
|
1466 wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
;
1467 if (Segment
.Flags
& ~SupportedFlags
)
1468 return make_error
<GenericBinaryError
>(
1469 "Unsupported flags for element segment", object_error::parse_failed
);
1471 if (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
)
1472 Segment
.TableNumber
= readVaruint32(Ctx
);
1474 Segment
.TableNumber
= 0;
1475 if (!isValidTableNumber(Segment
.TableNumber
))
1476 return make_error
<GenericBinaryError
>("invalid TableNumber",
1477 object_error::parse_failed
);
1479 if (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_IS_PASSIVE
) {
1480 Segment
.Offset
.Extended
= false;
1481 Segment
.Offset
.Inst
.Opcode
= wasm::WASM_OPCODE_I32_CONST
;
1482 Segment
.Offset
.Inst
.Value
.Int32
= 0;
1484 if (Error Err
= readInitExpr(Segment
.Offset
, Ctx
))
1488 if (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
) {
1489 Segment
.ElemKind
= readUint8(Ctx
);
1490 if (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
) {
1491 if (Segment
.ElemKind
!= uint8_t(wasm::ValType::FUNCREF
) &&
1492 Segment
.ElemKind
!= uint8_t(wasm::ValType::EXTERNREF
)) {
1493 return make_error
<GenericBinaryError
>("invalid reference type",
1494 object_error::parse_failed
);
1497 if (Segment
.ElemKind
!= 0)
1498 return make_error
<GenericBinaryError
>("invalid elemtype",
1499 object_error::parse_failed
);
1500 Segment
.ElemKind
= uint8_t(wasm::ValType::FUNCREF
);
1503 Segment
.ElemKind
= uint8_t(wasm::ValType::FUNCREF
);
1506 if (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
)
1507 return make_error
<GenericBinaryError
>(
1508 "elem segment init expressions not yet implemented",
1509 object_error::parse_failed
);
1511 uint32_t NumElems
= readVaruint32(Ctx
);
1512 while (NumElems
--) {
1513 Segment
.Functions
.push_back(readVaruint32(Ctx
));
1515 ElemSegments
.push_back(Segment
);
1517 if (Ctx
.Ptr
!= Ctx
.End
)
1518 return make_error
<GenericBinaryError
>("elem section ended prematurely",
1519 object_error::parse_failed
);
1520 return Error::success();
1523 Error
WasmObjectFile::parseDataSection(ReadContext
&Ctx
) {
1524 DataSection
= Sections
.size();
1525 uint32_t Count
= readVaruint32(Ctx
);
1526 if (DataCount
&& Count
!= *DataCount
)
1527 return make_error
<GenericBinaryError
>(
1528 "number of data segments does not match DataCount section");
1529 DataSegments
.reserve(Count
);
1531 WasmSegment Segment
;
1532 Segment
.Data
.InitFlags
= readVaruint32(Ctx
);
1533 Segment
.Data
.MemoryIndex
=
1534 (Segment
.Data
.InitFlags
& wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX
)
1535 ? readVaruint32(Ctx
)
1537 if ((Segment
.Data
.InitFlags
& wasm::WASM_DATA_SEGMENT_IS_PASSIVE
) == 0) {
1538 if (Error Err
= readInitExpr(Segment
.Data
.Offset
, Ctx
))
1541 Segment
.Data
.Offset
.Extended
= false;
1542 Segment
.Data
.Offset
.Inst
.Opcode
= wasm::WASM_OPCODE_I32_CONST
;
1543 Segment
.Data
.Offset
.Inst
.Value
.Int32
= 0;
1545 uint32_t Size
= readVaruint32(Ctx
);
1546 if (Size
> (size_t)(Ctx
.End
- Ctx
.Ptr
))
1547 return make_error
<GenericBinaryError
>("invalid segment size",
1548 object_error::parse_failed
);
1549 Segment
.Data
.Content
= ArrayRef
<uint8_t>(Ctx
.Ptr
, Size
);
1550 // The rest of these Data fields are set later, when reading in the linking
1551 // metadata section.
1552 Segment
.Data
.Alignment
= 0;
1553 Segment
.Data
.LinkingFlags
= 0;
1554 Segment
.Data
.Comdat
= UINT32_MAX
;
1555 Segment
.SectionOffset
= Ctx
.Ptr
- Ctx
.Start
;
1557 DataSegments
.push_back(Segment
);
1559 if (Ctx
.Ptr
!= Ctx
.End
)
1560 return make_error
<GenericBinaryError
>("data section ended prematurely",
1561 object_error::parse_failed
);
1562 return Error::success();
1565 Error
WasmObjectFile::parseDataCountSection(ReadContext
&Ctx
) {
1566 DataCount
= readVaruint32(Ctx
);
1567 return Error::success();
1570 const wasm::WasmObjectHeader
&WasmObjectFile::getHeader() const {
1574 void WasmObjectFile::moveSymbolNext(DataRefImpl
&Symb
) const { Symb
.d
.b
++; }
1576 Expected
<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb
) const {
1577 uint32_t Result
= SymbolRef::SF_None
;
1578 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1580 LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym
<< " " << Sym
<< "\n");
1581 if (Sym
.isBindingWeak())
1582 Result
|= SymbolRef::SF_Weak
;
1583 if (!Sym
.isBindingLocal())
1584 Result
|= SymbolRef::SF_Global
;
1586 Result
|= SymbolRef::SF_Hidden
;
1587 if (!Sym
.isDefined())
1588 Result
|= SymbolRef::SF_Undefined
;
1589 if (Sym
.isTypeFunction())
1590 Result
|= SymbolRef::SF_Executable
;
1594 basic_symbol_iterator
WasmObjectFile::symbol_begin() const {
1596 Ref
.d
.a
= 1; // Arbitrary non-zero value so that Ref.p is non-null
1597 Ref
.d
.b
= 0; // Symbol index
1598 return BasicSymbolRef(Ref
, this);
1601 basic_symbol_iterator
WasmObjectFile::symbol_end() const {
1603 Ref
.d
.a
= 1; // Arbitrary non-zero value so that Ref.p is non-null
1604 Ref
.d
.b
= Symbols
.size(); // Symbol index
1605 return BasicSymbolRef(Ref
, this);
1608 const WasmSymbol
&WasmObjectFile::getWasmSymbol(const DataRefImpl
&Symb
) const {
1609 return Symbols
[Symb
.d
.b
];
1612 const WasmSymbol
&WasmObjectFile::getWasmSymbol(const SymbolRef
&Symb
) const {
1613 return getWasmSymbol(Symb
.getRawDataRefImpl());
1616 Expected
<StringRef
> WasmObjectFile::getSymbolName(DataRefImpl Symb
) const {
1617 return getWasmSymbol(Symb
).Info
.Name
;
1620 Expected
<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb
) const {
1621 auto &Sym
= getWasmSymbol(Symb
);
1622 if (Sym
.Info
.Kind
== wasm::WASM_SYMBOL_TYPE_FUNCTION
&&
1623 isDefinedFunctionIndex(Sym
.Info
.ElementIndex
))
1624 return getDefinedFunction(Sym
.Info
.ElementIndex
).CodeSectionOffset
;
1626 return getSymbolValue(Symb
);
1629 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol
&Sym
) const {
1630 switch (Sym
.Info
.Kind
) {
1631 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
1632 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
1633 case wasm::WASM_SYMBOL_TYPE_TAG
:
1634 case wasm::WASM_SYMBOL_TYPE_TABLE
:
1635 return Sym
.Info
.ElementIndex
;
1636 case wasm::WASM_SYMBOL_TYPE_DATA
: {
1637 // The value of a data symbol is the segment offset, plus the symbol
1638 // offset within the segment.
1639 uint32_t SegmentIndex
= Sym
.Info
.DataRef
.Segment
;
1640 const wasm::WasmDataSegment
&Segment
= DataSegments
[SegmentIndex
].Data
;
1641 if (Segment
.Offset
.Extended
) {
1642 llvm_unreachable("extended init exprs not supported");
1643 } else if (Segment
.Offset
.Inst
.Opcode
== wasm::WASM_OPCODE_I32_CONST
) {
1644 return Segment
.Offset
.Inst
.Value
.Int32
+ Sym
.Info
.DataRef
.Offset
;
1645 } else if (Segment
.Offset
.Inst
.Opcode
== wasm::WASM_OPCODE_I64_CONST
) {
1646 return Segment
.Offset
.Inst
.Value
.Int64
+ Sym
.Info
.DataRef
.Offset
;
1648 llvm_unreachable("unknown init expr opcode");
1651 case wasm::WASM_SYMBOL_TYPE_SECTION
:
1654 llvm_unreachable("invalid symbol type");
1657 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb
) const {
1658 return getWasmSymbolValue(getWasmSymbol(Symb
));
1661 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb
) const {
1662 llvm_unreachable("not yet implemented");
1666 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb
) const {
1667 llvm_unreachable("not yet implemented");
1671 Expected
<SymbolRef::Type
>
1672 WasmObjectFile::getSymbolType(DataRefImpl Symb
) const {
1673 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1675 switch (Sym
.Info
.Kind
) {
1676 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
1677 return SymbolRef::ST_Function
;
1678 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
1679 return SymbolRef::ST_Other
;
1680 case wasm::WASM_SYMBOL_TYPE_DATA
:
1681 return SymbolRef::ST_Data
;
1682 case wasm::WASM_SYMBOL_TYPE_SECTION
:
1683 return SymbolRef::ST_Debug
;
1684 case wasm::WASM_SYMBOL_TYPE_TAG
:
1685 return SymbolRef::ST_Other
;
1686 case wasm::WASM_SYMBOL_TYPE_TABLE
:
1687 return SymbolRef::ST_Other
;
1690 llvm_unreachable("unknown WasmSymbol::SymbolType");
1691 return SymbolRef::ST_Other
;
1694 Expected
<section_iterator
>
1695 WasmObjectFile::getSymbolSection(DataRefImpl Symb
) const {
1696 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1697 if (Sym
.isUndefined())
1698 return section_end();
1701 Ref
.d
.a
= getSymbolSectionIdImpl(Sym
);
1702 return section_iterator(SectionRef(Ref
, this));
1705 uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb
) const {
1706 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1707 return getSymbolSectionIdImpl(Sym
);
1710 uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol
&Sym
) const {
1711 switch (Sym
.Info
.Kind
) {
1712 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
1714 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
1715 return GlobalSection
;
1716 case wasm::WASM_SYMBOL_TYPE_DATA
:
1718 case wasm::WASM_SYMBOL_TYPE_SECTION
:
1719 return Sym
.Info
.ElementIndex
;
1720 case wasm::WASM_SYMBOL_TYPE_TAG
:
1722 case wasm::WASM_SYMBOL_TYPE_TABLE
:
1723 return TableSection
;
1725 llvm_unreachable("unknown WasmSymbol::SymbolType");
1729 void WasmObjectFile::moveSectionNext(DataRefImpl
&Sec
) const { Sec
.d
.a
++; }
1731 Expected
<StringRef
> WasmObjectFile::getSectionName(DataRefImpl Sec
) const {
1732 const WasmSection
&S
= Sections
[Sec
.d
.a
];
1733 if (S
.Type
== wasm::WASM_SEC_CUSTOM
)
1735 if (S
.Type
> wasm::WASM_SEC_LAST_KNOWN
)
1736 return createStringError(object_error::invalid_section_index
, "");
1737 return wasm::sectionTypeToString(S
.Type
);
1740 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec
) const { return 0; }
1742 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec
) const {
1746 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec
) const {
1747 const WasmSection
&S
= Sections
[Sec
.d
.a
];
1748 return S
.Content
.size();
1751 Expected
<ArrayRef
<uint8_t>>
1752 WasmObjectFile::getSectionContents(DataRefImpl Sec
) const {
1753 const WasmSection
&S
= Sections
[Sec
.d
.a
];
1754 // This will never fail since wasm sections can never be empty (user-sections
1755 // must have a name and non-user sections each have a defined structure).
1759 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec
) const {
1763 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
1767 bool WasmObjectFile::isSectionText(DataRefImpl Sec
) const {
1768 return getWasmSection(Sec
).Type
== wasm::WASM_SEC_CODE
;
1771 bool WasmObjectFile::isSectionData(DataRefImpl Sec
) const {
1772 return getWasmSection(Sec
).Type
== wasm::WASM_SEC_DATA
;
1775 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec
) const { return false; }
1777 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec
) const { return false; }
1779 relocation_iterator
WasmObjectFile::section_rel_begin(DataRefImpl Ref
) const {
1780 DataRefImpl RelocRef
;
1781 RelocRef
.d
.a
= Ref
.d
.a
;
1783 return relocation_iterator(RelocationRef(RelocRef
, this));
1786 relocation_iterator
WasmObjectFile::section_rel_end(DataRefImpl Ref
) const {
1787 const WasmSection
&Sec
= getWasmSection(Ref
);
1788 DataRefImpl RelocRef
;
1789 RelocRef
.d
.a
= Ref
.d
.a
;
1790 RelocRef
.d
.b
= Sec
.Relocations
.size();
1791 return relocation_iterator(RelocationRef(RelocRef
, this));
1794 void WasmObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const { Rel
.d
.b
++; }
1796 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref
) const {
1797 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
1801 symbol_iterator
WasmObjectFile::getRelocationSymbol(DataRefImpl Ref
) const {
1802 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
1803 if (Rel
.Type
== wasm::R_WASM_TYPE_INDEX_LEB
)
1804 return symbol_end();
1807 Sym
.d
.b
= Rel
.Index
;
1808 return symbol_iterator(SymbolRef(Sym
, this));
1811 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref
) const {
1812 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
1816 void WasmObjectFile::getRelocationTypeName(
1817 DataRefImpl Ref
, SmallVectorImpl
<char> &Result
) const {
1818 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
1819 StringRef Res
= "Unknown";
1821 #define WASM_RELOC(name, value) \
1827 #include "llvm/BinaryFormat/WasmRelocs.def"
1832 Result
.append(Res
.begin(), Res
.end());
1835 section_iterator
WasmObjectFile::section_begin() const {
1838 return section_iterator(SectionRef(Ref
, this));
1841 section_iterator
WasmObjectFile::section_end() const {
1843 Ref
.d
.a
= Sections
.size();
1844 return section_iterator(SectionRef(Ref
, this));
1847 uint8_t WasmObjectFile::getBytesInAddress() const {
1848 return HasMemory64
? 8 : 4;
1851 StringRef
WasmObjectFile::getFileFormatName() const { return "WASM"; }
1853 Triple::ArchType
WasmObjectFile::getArch() const {
1854 return HasMemory64
? Triple::wasm64
: Triple::wasm32
;
1857 Expected
<SubtargetFeatures
> WasmObjectFile::getFeatures() const {
1858 return SubtargetFeatures();
1861 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection
; }
1863 bool WasmObjectFile::isSharedObject() const { return HasDylinkSection
; }
1865 const WasmSection
&WasmObjectFile::getWasmSection(DataRefImpl Ref
) const {
1866 assert(Ref
.d
.a
< Sections
.size());
1867 return Sections
[Ref
.d
.a
];
1871 WasmObjectFile::getWasmSection(const SectionRef
&Section
) const {
1872 return getWasmSection(Section
.getRawDataRefImpl());
1875 const wasm::WasmRelocation
&
1876 WasmObjectFile::getWasmRelocation(const RelocationRef
&Ref
) const {
1877 return getWasmRelocation(Ref
.getRawDataRefImpl());
1880 const wasm::WasmRelocation
&
1881 WasmObjectFile::getWasmRelocation(DataRefImpl Ref
) const {
1882 assert(Ref
.d
.a
< Sections
.size());
1883 const WasmSection
&Sec
= Sections
[Ref
.d
.a
];
1884 assert(Ref
.d
.b
< Sec
.Relocations
.size());
1885 return Sec
.Relocations
[Ref
.d
.b
];
1888 int WasmSectionOrderChecker::getSectionOrder(unsigned ID
,
1889 StringRef CustomSectionName
) {
1891 case wasm::WASM_SEC_CUSTOM
:
1892 return StringSwitch
<unsigned>(CustomSectionName
)
1893 .Case("dylink", WASM_SEC_ORDER_DYLINK
)
1894 .Case("dylink.0", WASM_SEC_ORDER_DYLINK
)
1895 .Case("linking", WASM_SEC_ORDER_LINKING
)
1896 .StartsWith("reloc.", WASM_SEC_ORDER_RELOC
)
1897 .Case("name", WASM_SEC_ORDER_NAME
)
1898 .Case("producers", WASM_SEC_ORDER_PRODUCERS
)
1899 .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES
)
1900 .Default(WASM_SEC_ORDER_NONE
);
1901 case wasm::WASM_SEC_TYPE
:
1902 return WASM_SEC_ORDER_TYPE
;
1903 case wasm::WASM_SEC_IMPORT
:
1904 return WASM_SEC_ORDER_IMPORT
;
1905 case wasm::WASM_SEC_FUNCTION
:
1906 return WASM_SEC_ORDER_FUNCTION
;
1907 case wasm::WASM_SEC_TABLE
:
1908 return WASM_SEC_ORDER_TABLE
;
1909 case wasm::WASM_SEC_MEMORY
:
1910 return WASM_SEC_ORDER_MEMORY
;
1911 case wasm::WASM_SEC_GLOBAL
:
1912 return WASM_SEC_ORDER_GLOBAL
;
1913 case wasm::WASM_SEC_EXPORT
:
1914 return WASM_SEC_ORDER_EXPORT
;
1915 case wasm::WASM_SEC_START
:
1916 return WASM_SEC_ORDER_START
;
1917 case wasm::WASM_SEC_ELEM
:
1918 return WASM_SEC_ORDER_ELEM
;
1919 case wasm::WASM_SEC_CODE
:
1920 return WASM_SEC_ORDER_CODE
;
1921 case wasm::WASM_SEC_DATA
:
1922 return WASM_SEC_ORDER_DATA
;
1923 case wasm::WASM_SEC_DATACOUNT
:
1924 return WASM_SEC_ORDER_DATACOUNT
;
1925 case wasm::WASM_SEC_TAG
:
1926 return WASM_SEC_ORDER_TAG
;
1928 return WASM_SEC_ORDER_NONE
;
1932 // Represents the edges in a directed graph where any node B reachable from node
1933 // A is not allowed to appear before A in the section ordering, but may appear
1935 int WasmSectionOrderChecker::DisallowedPredecessors
1936 [WASM_NUM_SEC_ORDERS
][WASM_NUM_SEC_ORDERS
] = {
1937 // WASM_SEC_ORDER_NONE
1939 // WASM_SEC_ORDER_TYPE
1940 {WASM_SEC_ORDER_TYPE
, WASM_SEC_ORDER_IMPORT
},
1941 // WASM_SEC_ORDER_IMPORT
1942 {WASM_SEC_ORDER_IMPORT
, WASM_SEC_ORDER_FUNCTION
},
1943 // WASM_SEC_ORDER_FUNCTION
1944 {WASM_SEC_ORDER_FUNCTION
, WASM_SEC_ORDER_TABLE
},
1945 // WASM_SEC_ORDER_TABLE
1946 {WASM_SEC_ORDER_TABLE
, WASM_SEC_ORDER_MEMORY
},
1947 // WASM_SEC_ORDER_MEMORY
1948 {WASM_SEC_ORDER_MEMORY
, WASM_SEC_ORDER_TAG
},
1949 // WASM_SEC_ORDER_TAG
1950 {WASM_SEC_ORDER_TAG
, WASM_SEC_ORDER_GLOBAL
},
1951 // WASM_SEC_ORDER_GLOBAL
1952 {WASM_SEC_ORDER_GLOBAL
, WASM_SEC_ORDER_EXPORT
},
1953 // WASM_SEC_ORDER_EXPORT
1954 {WASM_SEC_ORDER_EXPORT
, WASM_SEC_ORDER_START
},
1955 // WASM_SEC_ORDER_START
1956 {WASM_SEC_ORDER_START
, WASM_SEC_ORDER_ELEM
},
1957 // WASM_SEC_ORDER_ELEM
1958 {WASM_SEC_ORDER_ELEM
, WASM_SEC_ORDER_DATACOUNT
},
1959 // WASM_SEC_ORDER_DATACOUNT
1960 {WASM_SEC_ORDER_DATACOUNT
, WASM_SEC_ORDER_CODE
},
1961 // WASM_SEC_ORDER_CODE
1962 {WASM_SEC_ORDER_CODE
, WASM_SEC_ORDER_DATA
},
1963 // WASM_SEC_ORDER_DATA
1964 {WASM_SEC_ORDER_DATA
, WASM_SEC_ORDER_LINKING
},
1967 // WASM_SEC_ORDER_DYLINK
1968 {WASM_SEC_ORDER_DYLINK
, WASM_SEC_ORDER_TYPE
},
1969 // WASM_SEC_ORDER_LINKING
1970 {WASM_SEC_ORDER_LINKING
, WASM_SEC_ORDER_RELOC
, WASM_SEC_ORDER_NAME
},
1971 // WASM_SEC_ORDER_RELOC (can be repeated)
1973 // WASM_SEC_ORDER_NAME
1974 {WASM_SEC_ORDER_NAME
, WASM_SEC_ORDER_PRODUCERS
},
1975 // WASM_SEC_ORDER_PRODUCERS
1976 {WASM_SEC_ORDER_PRODUCERS
, WASM_SEC_ORDER_TARGET_FEATURES
},
1977 // WASM_SEC_ORDER_TARGET_FEATURES
1978 {WASM_SEC_ORDER_TARGET_FEATURES
}};
1980 bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID
,
1981 StringRef CustomSectionName
) {
1982 int Order
= getSectionOrder(ID
, CustomSectionName
);
1983 if (Order
== WASM_SEC_ORDER_NONE
)
1986 // Disallowed predecessors we need to check for
1987 SmallVector
<int, WASM_NUM_SEC_ORDERS
> WorkList
;
1989 // Keep track of completed checks to avoid repeating work
1990 bool Checked
[WASM_NUM_SEC_ORDERS
] = {};
1994 // Add new disallowed predecessors to work list
1995 for (size_t I
= 0;; ++I
) {
1996 int Next
= DisallowedPredecessors
[Curr
][I
];
1997 if (Next
== WASM_SEC_ORDER_NONE
)
2001 WorkList
.push_back(Next
);
2002 Checked
[Next
] = true;
2005 if (WorkList
.empty())
2008 // Consider next disallowed predecessor
2009 Curr
= WorkList
.pop_back_val();
2014 // Have not seen any disallowed predecessors