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