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/Triple.h"
16 #include "llvm/BinaryFormat/Wasm.h"
17 #include "llvm/MC/SubtargetFeature.h"
18 #include "llvm/Object/Binary.h"
19 #include "llvm/Object/Error.h"
20 #include "llvm/Object/ObjectFile.h"
21 #include "llvm/Object/SymbolicFile.h"
22 #include "llvm/Object/Wasm.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/Error.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/LEB128.h"
27 #include "llvm/Support/ScopedPrinter.h"
32 #include <system_error>
34 #define DEBUG_TYPE "wasm-object"
37 using namespace object
;
39 void WasmSymbol::print(raw_ostream
&Out
) const {
40 Out
<< "Name=" << Info
.Name
41 << ", Kind=" << toString(wasm::WasmSymbolType(Info
.Kind
))
42 << ", Flags=" << Info
.Flags
;
44 Out
<< ", ElemIndex=" << Info
.ElementIndex
;
45 } else if (isDefined()) {
46 Out
<< ", Segment=" << Info
.DataRef
.Segment
;
47 Out
<< ", Offset=" << Info
.DataRef
.Offset
;
48 Out
<< ", Size=" << Info
.DataRef
.Size
;
52 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
53 LLVM_DUMP_METHOD
void WasmSymbol::dump() const { print(dbgs()); }
56 Expected
<std::unique_ptr
<WasmObjectFile
>>
57 ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer
) {
58 Error Err
= Error::success();
59 auto ObjectFile
= llvm::make_unique
<WasmObjectFile
>(Buffer
, Err
);
61 return std::move(Err
);
63 return std::move(ObjectFile
);
66 #define VARINT7_MAX ((1 << 7) - 1)
67 #define VARINT7_MIN (-(1 << 7))
68 #define VARUINT7_MAX (1 << 7)
69 #define VARUINT1_MAX (1)
71 static uint8_t readUint8(WasmObjectFile::ReadContext
&Ctx
) {
72 if (Ctx
.Ptr
== Ctx
.End
)
73 report_fatal_error("EOF while reading uint8");
77 static uint32_t readUint32(WasmObjectFile::ReadContext
&Ctx
) {
78 if (Ctx
.Ptr
+ 4 > Ctx
.End
)
79 report_fatal_error("EOF while reading uint32");
80 uint32_t Result
= support::endian::read32le(Ctx
.Ptr
);
85 static int32_t readFloat32(WasmObjectFile::ReadContext
&Ctx
) {
86 if (Ctx
.Ptr
+ 4 > Ctx
.End
)
87 report_fatal_error("EOF while reading float64");
89 memcpy(&Result
, Ctx
.Ptr
, sizeof(Result
));
90 Ctx
.Ptr
+= sizeof(Result
);
94 static int64_t readFloat64(WasmObjectFile::ReadContext
&Ctx
) {
95 if (Ctx
.Ptr
+ 8 > Ctx
.End
)
96 report_fatal_error("EOF while reading float64");
98 memcpy(&Result
, Ctx
.Ptr
, sizeof(Result
));
99 Ctx
.Ptr
+= sizeof(Result
);
103 static uint64_t readULEB128(WasmObjectFile::ReadContext
&Ctx
) {
105 const char *Error
= nullptr;
106 uint64_t Result
= decodeULEB128(Ctx
.Ptr
, &Count
, Ctx
.End
, &Error
);
108 report_fatal_error(Error
);
113 static StringRef
readString(WasmObjectFile::ReadContext
&Ctx
) {
114 uint32_t StringLen
= readULEB128(Ctx
);
115 if (Ctx
.Ptr
+ StringLen
> Ctx
.End
)
116 report_fatal_error("EOF while reading string");
118 StringRef(reinterpret_cast<const char *>(Ctx
.Ptr
), StringLen
);
119 Ctx
.Ptr
+= StringLen
;
123 static int64_t readLEB128(WasmObjectFile::ReadContext
&Ctx
) {
125 const char *Error
= nullptr;
126 uint64_t Result
= decodeSLEB128(Ctx
.Ptr
, &Count
, Ctx
.End
, &Error
);
128 report_fatal_error(Error
);
133 static uint8_t readVaruint1(WasmObjectFile::ReadContext
&Ctx
) {
134 int64_t result
= readLEB128(Ctx
);
135 if (result
> VARUINT1_MAX
|| result
< 0)
136 report_fatal_error("LEB is outside Varuint1 range");
140 static int32_t readVarint32(WasmObjectFile::ReadContext
&Ctx
) {
141 int64_t result
= readLEB128(Ctx
);
142 if (result
> INT32_MAX
|| result
< INT32_MIN
)
143 report_fatal_error("LEB is outside Varint32 range");
147 static uint32_t readVaruint32(WasmObjectFile::ReadContext
&Ctx
) {
148 uint64_t result
= readULEB128(Ctx
);
149 if (result
> UINT32_MAX
)
150 report_fatal_error("LEB is outside Varuint32 range");
154 static int64_t readVarint64(WasmObjectFile::ReadContext
&Ctx
) {
155 return readLEB128(Ctx
);
158 static uint8_t readOpcode(WasmObjectFile::ReadContext
&Ctx
) {
159 return readUint8(Ctx
);
162 static Error
readInitExpr(wasm::WasmInitExpr
&Expr
,
163 WasmObjectFile::ReadContext
&Ctx
) {
164 Expr
.Opcode
= readOpcode(Ctx
);
166 switch (Expr
.Opcode
) {
167 case wasm::WASM_OPCODE_I32_CONST
:
168 Expr
.Value
.Int32
= readVarint32(Ctx
);
170 case wasm::WASM_OPCODE_I64_CONST
:
171 Expr
.Value
.Int64
= readVarint64(Ctx
);
173 case wasm::WASM_OPCODE_F32_CONST
:
174 Expr
.Value
.Float32
= readFloat32(Ctx
);
176 case wasm::WASM_OPCODE_F64_CONST
:
177 Expr
.Value
.Float64
= readFloat64(Ctx
);
179 case wasm::WASM_OPCODE_GLOBAL_GET
:
180 Expr
.Value
.Global
= readULEB128(Ctx
);
183 return make_error
<GenericBinaryError
>("Invalid opcode in init_expr",
184 object_error::parse_failed
);
187 uint8_t EndOpcode
= readOpcode(Ctx
);
188 if (EndOpcode
!= wasm::WASM_OPCODE_END
) {
189 return make_error
<GenericBinaryError
>("Invalid init_expr",
190 object_error::parse_failed
);
192 return Error::success();
195 static wasm::WasmLimits
readLimits(WasmObjectFile::ReadContext
&Ctx
) {
196 wasm::WasmLimits Result
;
197 Result
.Flags
= readVaruint32(Ctx
);
198 Result
.Initial
= readVaruint32(Ctx
);
199 if (Result
.Flags
& wasm::WASM_LIMITS_FLAG_HAS_MAX
)
200 Result
.Maximum
= readVaruint32(Ctx
);
204 static wasm::WasmTable
readTable(WasmObjectFile::ReadContext
&Ctx
) {
205 wasm::WasmTable Table
;
206 Table
.ElemType
= readUint8(Ctx
);
207 Table
.Limits
= readLimits(Ctx
);
211 static Error
readSection(WasmSection
&Section
, WasmObjectFile::ReadContext
&Ctx
,
212 WasmSectionOrderChecker
&Checker
) {
213 Section
.Offset
= Ctx
.Ptr
- Ctx
.Start
;
214 Section
.Type
= readUint8(Ctx
);
215 LLVM_DEBUG(dbgs() << "readSection type=" << Section
.Type
<< "\n");
216 uint32_t Size
= readVaruint32(Ctx
);
218 return make_error
<StringError
>("Zero length section",
219 object_error::parse_failed
);
220 if (Ctx
.Ptr
+ Size
> Ctx
.End
)
221 return make_error
<StringError
>("Section too large",
222 object_error::parse_failed
);
223 if (Section
.Type
== wasm::WASM_SEC_CUSTOM
) {
224 WasmObjectFile::ReadContext SectionCtx
;
225 SectionCtx
.Start
= Ctx
.Ptr
;
226 SectionCtx
.Ptr
= Ctx
.Ptr
;
227 SectionCtx
.End
= Ctx
.Ptr
+ Size
;
229 Section
.Name
= readString(SectionCtx
);
231 uint32_t SectionNameSize
= SectionCtx
.Ptr
- SectionCtx
.Start
;
232 Ctx
.Ptr
+= SectionNameSize
;
233 Size
-= SectionNameSize
;
236 if (!Checker
.isValidSectionOrder(Section
.Type
, Section
.Name
)) {
237 return make_error
<StringError
>("Out of order section type: " +
238 llvm::to_string(Section
.Type
),
239 object_error::parse_failed
);
242 Section
.Content
= ArrayRef
<uint8_t>(Ctx
.Ptr
, Size
);
244 return Error::success();
247 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer
, Error
&Err
)
248 : ObjectFile(Binary::ID_Wasm
, Buffer
) {
249 ErrorAsOutParameter
ErrAsOutParam(&Err
);
250 Header
.Magic
= getData().substr(0, 4);
251 if (Header
.Magic
!= StringRef("\0asm", 4)) {
253 make_error
<StringError
>("Bad magic number", object_error::parse_failed
);
258 Ctx
.Start
= getPtr(0);
259 Ctx
.Ptr
= Ctx
.Start
+ 4;
260 Ctx
.End
= Ctx
.Start
+ getData().size();
262 if (Ctx
.Ptr
+ 4 > Ctx
.End
) {
263 Err
= make_error
<StringError
>("Missing version number",
264 object_error::parse_failed
);
268 Header
.Version
= readUint32(Ctx
);
269 if (Header
.Version
!= wasm::WasmVersion
) {
270 Err
= make_error
<StringError
>("Bad version number",
271 object_error::parse_failed
);
276 WasmSectionOrderChecker Checker
;
277 while (Ctx
.Ptr
< Ctx
.End
) {
278 if ((Err
= readSection(Sec
, Ctx
, Checker
)))
280 if ((Err
= parseSection(Sec
)))
283 Sections
.push_back(Sec
);
287 Error
WasmObjectFile::parseSection(WasmSection
&Sec
) {
289 Ctx
.Start
= Sec
.Content
.data();
290 Ctx
.End
= Ctx
.Start
+ Sec
.Content
.size();
293 case wasm::WASM_SEC_CUSTOM
:
294 return parseCustomSection(Sec
, Ctx
);
295 case wasm::WASM_SEC_TYPE
:
296 return parseTypeSection(Ctx
);
297 case wasm::WASM_SEC_IMPORT
:
298 return parseImportSection(Ctx
);
299 case wasm::WASM_SEC_FUNCTION
:
300 return parseFunctionSection(Ctx
);
301 case wasm::WASM_SEC_TABLE
:
302 return parseTableSection(Ctx
);
303 case wasm::WASM_SEC_MEMORY
:
304 return parseMemorySection(Ctx
);
305 case wasm::WASM_SEC_GLOBAL
:
306 return parseGlobalSection(Ctx
);
307 case wasm::WASM_SEC_EVENT
:
308 return parseEventSection(Ctx
);
309 case wasm::WASM_SEC_EXPORT
:
310 return parseExportSection(Ctx
);
311 case wasm::WASM_SEC_START
:
312 return parseStartSection(Ctx
);
313 case wasm::WASM_SEC_ELEM
:
314 return parseElemSection(Ctx
);
315 case wasm::WASM_SEC_CODE
:
316 return parseCodeSection(Ctx
);
317 case wasm::WASM_SEC_DATA
:
318 return parseDataSection(Ctx
);
320 return make_error
<GenericBinaryError
>("Bad section type",
321 object_error::parse_failed
);
325 Error
WasmObjectFile::parseDylinkSection(ReadContext
&Ctx
) {
326 // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
327 DylinkInfo
.MemorySize
= readVaruint32(Ctx
);
328 DylinkInfo
.MemoryAlignment
= readVaruint32(Ctx
);
329 DylinkInfo
.TableSize
= readVaruint32(Ctx
);
330 DylinkInfo
.TableAlignment
= readVaruint32(Ctx
);
331 uint32_t Count
= readVaruint32(Ctx
);
333 DylinkInfo
.Needed
.push_back(readString(Ctx
));
335 if (Ctx
.Ptr
!= Ctx
.End
)
336 return make_error
<GenericBinaryError
>("dylink section ended prematurely",
337 object_error::parse_failed
);
338 return Error::success();
341 Error
WasmObjectFile::parseNameSection(ReadContext
&Ctx
) {
342 llvm::DenseSet
<uint64_t> Seen
;
343 if (Functions
.size() != FunctionTypes
.size()) {
344 return make_error
<GenericBinaryError
>("Names must come after code section",
345 object_error::parse_failed
);
348 while (Ctx
.Ptr
< Ctx
.End
) {
349 uint8_t Type
= readUint8(Ctx
);
350 uint32_t Size
= readVaruint32(Ctx
);
351 const uint8_t *SubSectionEnd
= Ctx
.Ptr
+ Size
;
353 case wasm::WASM_NAMES_FUNCTION
: {
354 uint32_t Count
= readVaruint32(Ctx
);
356 uint32_t Index
= readVaruint32(Ctx
);
357 if (!Seen
.insert(Index
).second
)
358 return make_error
<GenericBinaryError
>("Function named more than once",
359 object_error::parse_failed
);
360 StringRef Name
= readString(Ctx
);
361 if (!isValidFunctionIndex(Index
) || Name
.empty())
362 return make_error
<GenericBinaryError
>("Invalid name entry",
363 object_error::parse_failed
);
364 DebugNames
.push_back(wasm::WasmFunctionName
{Index
, Name
});
365 if (isDefinedFunctionIndex(Index
))
366 getDefinedFunction(Index
).DebugName
= Name
;
370 // Ignore local names for now
371 case wasm::WASM_NAMES_LOCAL
:
376 if (Ctx
.Ptr
!= SubSectionEnd
)
377 return make_error
<GenericBinaryError
>(
378 "Name sub-section ended prematurely", object_error::parse_failed
);
381 if (Ctx
.Ptr
!= Ctx
.End
)
382 return make_error
<GenericBinaryError
>("Name section ended prematurely",
383 object_error::parse_failed
);
384 return Error::success();
387 Error
WasmObjectFile::parseLinkingSection(ReadContext
&Ctx
) {
388 HasLinkingSection
= true;
389 if (Functions
.size() != FunctionTypes
.size()) {
390 return make_error
<GenericBinaryError
>(
391 "Linking data must come after code section",
392 object_error::parse_failed
);
395 LinkingData
.Version
= readVaruint32(Ctx
);
396 if (LinkingData
.Version
!= wasm::WasmMetadataVersion
) {
397 return make_error
<GenericBinaryError
>(
398 "Unexpected metadata version: " + Twine(LinkingData
.Version
) +
399 " (Expected: " + Twine(wasm::WasmMetadataVersion
) + ")",
400 object_error::parse_failed
);
403 const uint8_t *OrigEnd
= Ctx
.End
;
404 while (Ctx
.Ptr
< OrigEnd
) {
406 uint8_t Type
= readUint8(Ctx
);
407 uint32_t Size
= readVaruint32(Ctx
);
408 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type
) << " size=" << Size
410 Ctx
.End
= Ctx
.Ptr
+ Size
;
412 case wasm::WASM_SYMBOL_TABLE
:
413 if (Error Err
= parseLinkingSectionSymtab(Ctx
))
416 case wasm::WASM_SEGMENT_INFO
: {
417 uint32_t Count
= readVaruint32(Ctx
);
418 if (Count
> DataSegments
.size())
419 return make_error
<GenericBinaryError
>("Too many segment names",
420 object_error::parse_failed
);
421 for (uint32_t i
= 0; i
< Count
; i
++) {
422 DataSegments
[i
].Data
.Name
= readString(Ctx
);
423 DataSegments
[i
].Data
.Alignment
= readVaruint32(Ctx
);
424 DataSegments
[i
].Data
.Flags
= readVaruint32(Ctx
);
428 case wasm::WASM_INIT_FUNCS
: {
429 uint32_t Count
= readVaruint32(Ctx
);
430 LinkingData
.InitFunctions
.reserve(Count
);
431 for (uint32_t i
= 0; i
< Count
; i
++) {
432 wasm::WasmInitFunc Init
;
433 Init
.Priority
= readVaruint32(Ctx
);
434 Init
.Symbol
= readVaruint32(Ctx
);
435 if (!isValidFunctionSymbol(Init
.Symbol
))
436 return make_error
<GenericBinaryError
>("Invalid function symbol: " +
438 object_error::parse_failed
);
439 LinkingData
.InitFunctions
.emplace_back(Init
);
443 case wasm::WASM_COMDAT_INFO
:
444 if (Error Err
= parseLinkingSectionComdat(Ctx
))
451 if (Ctx
.Ptr
!= Ctx
.End
)
452 return make_error
<GenericBinaryError
>(
453 "Linking sub-section ended prematurely", object_error::parse_failed
);
455 if (Ctx
.Ptr
!= OrigEnd
)
456 return make_error
<GenericBinaryError
>("Linking section ended prematurely",
457 object_error::parse_failed
);
458 return Error::success();
461 Error
WasmObjectFile::parseLinkingSectionSymtab(ReadContext
&Ctx
) {
462 uint32_t Count
= readVaruint32(Ctx
);
463 LinkingData
.SymbolTable
.reserve(Count
);
464 Symbols
.reserve(Count
);
465 StringSet
<> SymbolNames
;
467 std::vector
<wasm::WasmImport
*> ImportedGlobals
;
468 std::vector
<wasm::WasmImport
*> ImportedFunctions
;
469 std::vector
<wasm::WasmImport
*> ImportedEvents
;
470 ImportedGlobals
.reserve(Imports
.size());
471 ImportedFunctions
.reserve(Imports
.size());
472 ImportedEvents
.reserve(Imports
.size());
473 for (auto &I
: Imports
) {
474 if (I
.Kind
== wasm::WASM_EXTERNAL_FUNCTION
)
475 ImportedFunctions
.emplace_back(&I
);
476 else if (I
.Kind
== wasm::WASM_EXTERNAL_GLOBAL
)
477 ImportedGlobals
.emplace_back(&I
);
478 else if (I
.Kind
== wasm::WASM_EXTERNAL_EVENT
)
479 ImportedEvents
.emplace_back(&I
);
483 wasm::WasmSymbolInfo Info
;
484 const wasm::WasmSignature
*Signature
= nullptr;
485 const wasm::WasmGlobalType
*GlobalType
= nullptr;
486 const wasm::WasmEventType
*EventType
= nullptr;
488 Info
.Kind
= readUint8(Ctx
);
489 Info
.Flags
= readVaruint32(Ctx
);
490 bool IsDefined
= (Info
.Flags
& wasm::WASM_SYMBOL_UNDEFINED
) == 0;
493 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
494 Info
.ElementIndex
= readVaruint32(Ctx
);
495 if (!isValidFunctionIndex(Info
.ElementIndex
) ||
496 IsDefined
!= isDefinedFunctionIndex(Info
.ElementIndex
))
497 return make_error
<GenericBinaryError
>("invalid function symbol index",
498 object_error::parse_failed
);
500 Info
.Name
= readString(Ctx
);
501 unsigned FuncIndex
= Info
.ElementIndex
- NumImportedFunctions
;
502 Signature
= &Signatures
[FunctionTypes
[FuncIndex
]];
503 wasm::WasmFunction
&Function
= Functions
[FuncIndex
];
504 if (Function
.SymbolName
.empty())
505 Function
.SymbolName
= Info
.Name
;
507 wasm::WasmImport
&Import
= *ImportedFunctions
[Info
.ElementIndex
];
508 Signature
= &Signatures
[Import
.SigIndex
];
509 Info
.Name
= Import
.Field
;
510 Info
.Module
= Import
.Module
;
514 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
515 Info
.ElementIndex
= readVaruint32(Ctx
);
516 if (!isValidGlobalIndex(Info
.ElementIndex
) ||
517 IsDefined
!= isDefinedGlobalIndex(Info
.ElementIndex
))
518 return make_error
<GenericBinaryError
>("invalid global symbol index",
519 object_error::parse_failed
);
520 if (!IsDefined
&& (Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) ==
521 wasm::WASM_SYMBOL_BINDING_WEAK
)
522 return make_error
<GenericBinaryError
>("undefined weak global symbol",
523 object_error::parse_failed
);
525 Info
.Name
= readString(Ctx
);
526 unsigned GlobalIndex
= Info
.ElementIndex
- NumImportedGlobals
;
527 wasm::WasmGlobal
&Global
= Globals
[GlobalIndex
];
528 GlobalType
= &Global
.Type
;
529 if (Global
.SymbolName
.empty())
530 Global
.SymbolName
= Info
.Name
;
532 wasm::WasmImport
&Import
= *ImportedGlobals
[Info
.ElementIndex
];
533 Info
.Name
= Import
.Field
;
534 GlobalType
= &Import
.Global
;
538 case wasm::WASM_SYMBOL_TYPE_DATA
:
539 Info
.Name
= readString(Ctx
);
541 uint32_t Index
= readVaruint32(Ctx
);
542 if (Index
>= DataSegments
.size())
543 return make_error
<GenericBinaryError
>("invalid data symbol index",
544 object_error::parse_failed
);
545 uint32_t Offset
= readVaruint32(Ctx
);
546 uint32_t Size
= readVaruint32(Ctx
);
547 if (Offset
+ Size
> DataSegments
[Index
].Data
.Content
.size())
548 return make_error
<GenericBinaryError
>("invalid data symbol offset",
549 object_error::parse_failed
);
550 Info
.DataRef
= wasm::WasmDataReference
{Index
, Offset
, Size
};
554 case wasm::WASM_SYMBOL_TYPE_SECTION
: {
555 if ((Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) !=
556 wasm::WASM_SYMBOL_BINDING_LOCAL
)
557 return make_error
<GenericBinaryError
>(
558 "Section symbols must have local binding",
559 object_error::parse_failed
);
560 Info
.ElementIndex
= readVaruint32(Ctx
);
561 // Use somewhat unique section name as symbol name.
562 StringRef SectionName
= Sections
[Info
.ElementIndex
].Name
;
563 Info
.Name
= SectionName
;
567 case wasm::WASM_SYMBOL_TYPE_EVENT
: {
568 Info
.ElementIndex
= readVaruint32(Ctx
);
569 if (!isValidEventIndex(Info
.ElementIndex
) ||
570 IsDefined
!= isDefinedEventIndex(Info
.ElementIndex
))
571 return make_error
<GenericBinaryError
>("invalid event 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 EventIndex
= Info
.ElementIndex
- NumImportedEvents
;
580 wasm::WasmEvent
&Event
= Events
[EventIndex
];
581 Signature
= &Signatures
[Event
.Type
.SigIndex
];
582 EventType
= &Event
.Type
;
583 if (Event
.SymbolName
.empty())
584 Event
.SymbolName
= Info
.Name
;
587 wasm::WasmImport
&Import
= *ImportedEvents
[Info
.ElementIndex
];
588 EventType
= &Import
.Event
;
589 Signature
= &Signatures
[EventType
->SigIndex
];
590 Info
.Name
= Import
.Field
;
596 return make_error
<GenericBinaryError
>("Invalid symbol type",
597 object_error::parse_failed
);
600 if ((Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) !=
601 wasm::WASM_SYMBOL_BINDING_LOCAL
&&
602 !SymbolNames
.insert(Info
.Name
).second
)
603 return make_error
<GenericBinaryError
>("Duplicate symbol name " +
605 object_error::parse_failed
);
606 LinkingData
.SymbolTable
.emplace_back(Info
);
607 Symbols
.emplace_back(LinkingData
.SymbolTable
.back(), GlobalType
, EventType
,
609 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols
.back() << "\n");
612 return Error::success();
615 Error
WasmObjectFile::parseLinkingSectionComdat(ReadContext
&Ctx
) {
616 uint32_t ComdatCount
= readVaruint32(Ctx
);
617 StringSet
<> ComdatSet
;
618 for (unsigned ComdatIndex
= 0; ComdatIndex
< ComdatCount
; ++ComdatIndex
) {
619 StringRef Name
= readString(Ctx
);
620 if (Name
.empty() || !ComdatSet
.insert(Name
).second
)
621 return make_error
<GenericBinaryError
>("Bad/duplicate COMDAT name " +
623 object_error::parse_failed
);
624 LinkingData
.Comdats
.emplace_back(Name
);
625 uint32_t Flags
= readVaruint32(Ctx
);
627 return make_error
<GenericBinaryError
>("Unsupported COMDAT flags",
628 object_error::parse_failed
);
630 uint32_t EntryCount
= readVaruint32(Ctx
);
631 while (EntryCount
--) {
632 unsigned Kind
= readVaruint32(Ctx
);
633 unsigned Index
= readVaruint32(Ctx
);
636 return make_error
<GenericBinaryError
>("Invalid COMDAT entry type",
637 object_error::parse_failed
);
638 case wasm::WASM_COMDAT_DATA
:
639 if (Index
>= DataSegments
.size())
640 return make_error
<GenericBinaryError
>(
641 "COMDAT data index out of range", object_error::parse_failed
);
642 if (DataSegments
[Index
].Data
.Comdat
!= UINT32_MAX
)
643 return make_error
<GenericBinaryError
>("Data segment in two COMDATs",
644 object_error::parse_failed
);
645 DataSegments
[Index
].Data
.Comdat
= ComdatIndex
;
647 case wasm::WASM_COMDAT_FUNCTION
:
648 if (!isDefinedFunctionIndex(Index
))
649 return make_error
<GenericBinaryError
>(
650 "COMDAT function index out of range", object_error::parse_failed
);
651 if (getDefinedFunction(Index
).Comdat
!= UINT32_MAX
)
652 return make_error
<GenericBinaryError
>("Function in two COMDATs",
653 object_error::parse_failed
);
654 getDefinedFunction(Index
).Comdat
= ComdatIndex
;
659 return Error::success();
662 Error
WasmObjectFile::parseProducersSection(ReadContext
&Ctx
) {
663 llvm::SmallSet
<StringRef
, 3> FieldsSeen
;
664 uint32_t Fields
= readVaruint32(Ctx
);
665 for (size_t i
= 0; i
< Fields
; ++i
) {
666 StringRef FieldName
= readString(Ctx
);
667 if (!FieldsSeen
.insert(FieldName
).second
)
668 return make_error
<GenericBinaryError
>(
669 "Producers section does not have unique fields",
670 object_error::parse_failed
);
671 std::vector
<std::pair
<std::string
, std::string
>> *ProducerVec
= nullptr;
672 if (FieldName
== "language") {
673 ProducerVec
= &ProducerInfo
.Languages
;
674 } else if (FieldName
== "processed-by") {
675 ProducerVec
= &ProducerInfo
.Tools
;
676 } else if (FieldName
== "sdk") {
677 ProducerVec
= &ProducerInfo
.SDKs
;
679 return make_error
<GenericBinaryError
>(
680 "Producers section field is not named one of language, processed-by, "
682 object_error::parse_failed
);
684 uint32_t ValueCount
= readVaruint32(Ctx
);
685 llvm::SmallSet
<StringRef
, 8> ProducersSeen
;
686 for (size_t j
= 0; j
< ValueCount
; ++j
) {
687 StringRef Name
= readString(Ctx
);
688 StringRef Version
= readString(Ctx
);
689 if (!ProducersSeen
.insert(Name
).second
) {
690 return make_error
<GenericBinaryError
>(
691 "Producers section contains repeated producer",
692 object_error::parse_failed
);
694 ProducerVec
->emplace_back(Name
, Version
);
697 if (Ctx
.Ptr
!= Ctx
.End
)
698 return make_error
<GenericBinaryError
>("Producers section ended prematurely",
699 object_error::parse_failed
);
700 return Error::success();
703 Error
WasmObjectFile::parseRelocSection(StringRef Name
, ReadContext
&Ctx
) {
704 uint32_t SectionIndex
= readVaruint32(Ctx
);
705 if (SectionIndex
>= Sections
.size())
706 return make_error
<GenericBinaryError
>("Invalid section index",
707 object_error::parse_failed
);
708 WasmSection
&Section
= Sections
[SectionIndex
];
709 uint32_t RelocCount
= readVaruint32(Ctx
);
710 uint32_t EndOffset
= Section
.Content
.size();
711 uint32_t PreviousOffset
= 0;
712 while (RelocCount
--) {
713 wasm::WasmRelocation Reloc
= {};
714 Reloc
.Type
= readVaruint32(Ctx
);
715 Reloc
.Offset
= readVaruint32(Ctx
);
716 if (Reloc
.Offset
< PreviousOffset
)
717 return make_error
<GenericBinaryError
>("Relocations not in offset order",
718 object_error::parse_failed
);
719 PreviousOffset
= Reloc
.Offset
;
720 Reloc
.Index
= readVaruint32(Ctx
);
721 switch (Reloc
.Type
) {
722 case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB
:
723 case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB
:
724 case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32
:
725 if (!isValidFunctionSymbol(Reloc
.Index
))
726 return make_error
<GenericBinaryError
>("Bad relocation function index",
727 object_error::parse_failed
);
729 case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB
:
730 if (Reloc
.Index
>= Signatures
.size())
731 return make_error
<GenericBinaryError
>("Bad relocation type index",
732 object_error::parse_failed
);
734 case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB
:
735 if (!isValidGlobalSymbol(Reloc
.Index
))
736 return make_error
<GenericBinaryError
>("Bad relocation global index",
737 object_error::parse_failed
);
739 case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB
:
740 if (!isValidEventSymbol(Reloc
.Index
))
741 return make_error
<GenericBinaryError
>("Bad relocation event index",
742 object_error::parse_failed
);
744 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB
:
745 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB
:
746 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32
:
747 if (!isValidDataSymbol(Reloc
.Index
))
748 return make_error
<GenericBinaryError
>("Bad relocation data index",
749 object_error::parse_failed
);
750 Reloc
.Addend
= readVarint32(Ctx
);
752 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32
:
753 if (!isValidFunctionSymbol(Reloc
.Index
))
754 return make_error
<GenericBinaryError
>("Bad relocation function index",
755 object_error::parse_failed
);
756 Reloc
.Addend
= readVarint32(Ctx
);
758 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32
:
759 if (!isValidSectionSymbol(Reloc
.Index
))
760 return make_error
<GenericBinaryError
>("Bad relocation section index",
761 object_error::parse_failed
);
762 Reloc
.Addend
= readVarint32(Ctx
);
765 return make_error
<GenericBinaryError
>("Bad relocation type: " +
767 object_error::parse_failed
);
770 // Relocations must fit inside the section, and must appear in order. They
771 // also shouldn't overlap a function/element boundary, but we don't bother
774 if (Reloc
.Type
== wasm::R_WEBASSEMBLY_TABLE_INDEX_I32
||
775 Reloc
.Type
== wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32
||
776 Reloc
.Type
== wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32
||
777 Reloc
.Type
== wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32
)
779 if (Reloc
.Offset
+ Size
> EndOffset
)
780 return make_error
<GenericBinaryError
>("Bad relocation offset",
781 object_error::parse_failed
);
783 Section
.Relocations
.push_back(Reloc
);
785 if (Ctx
.Ptr
!= Ctx
.End
)
786 return make_error
<GenericBinaryError
>("Reloc section ended prematurely",
787 object_error::parse_failed
);
788 return Error::success();
791 Error
WasmObjectFile::parseCustomSection(WasmSection
&Sec
, ReadContext
&Ctx
) {
792 if (Sec
.Name
== "dylink") {
793 if (Error Err
= parseDylinkSection(Ctx
))
795 } else if (Sec
.Name
== "name") {
796 if (Error Err
= parseNameSection(Ctx
))
798 } else if (Sec
.Name
== "linking") {
799 if (Error Err
= parseLinkingSection(Ctx
))
801 } else if (Sec
.Name
== "producers") {
802 if (Error Err
= parseProducersSection(Ctx
))
804 } else if (Sec
.Name
.startswith("reloc.")) {
805 if (Error Err
= parseRelocSection(Sec
.Name
, Ctx
))
808 return Error::success();
811 Error
WasmObjectFile::parseTypeSection(ReadContext
&Ctx
) {
812 uint32_t Count
= readVaruint32(Ctx
);
813 Signatures
.reserve(Count
);
815 wasm::WasmSignature Sig
;
816 uint8_t Form
= readUint8(Ctx
);
817 if (Form
!= wasm::WASM_TYPE_FUNC
) {
818 return make_error
<GenericBinaryError
>("Invalid signature type",
819 object_error::parse_failed
);
821 uint32_t ParamCount
= readVaruint32(Ctx
);
822 Sig
.Params
.reserve(ParamCount
);
823 while (ParamCount
--) {
824 uint32_t ParamType
= readUint8(Ctx
);
825 Sig
.Params
.push_back(wasm::ValType(ParamType
));
827 uint32_t ReturnCount
= readVaruint32(Ctx
);
829 if (ReturnCount
!= 1) {
830 return make_error
<GenericBinaryError
>(
831 "Multiple return types not supported", object_error::parse_failed
);
833 Sig
.Returns
.push_back(wasm::ValType(readUint8(Ctx
)));
835 Signatures
.push_back(std::move(Sig
));
837 if (Ctx
.Ptr
!= Ctx
.End
)
838 return make_error
<GenericBinaryError
>("Type section ended prematurely",
839 object_error::parse_failed
);
840 return Error::success();
843 Error
WasmObjectFile::parseImportSection(ReadContext
&Ctx
) {
844 uint32_t Count
= readVaruint32(Ctx
);
845 Imports
.reserve(Count
);
846 for (uint32_t i
= 0; i
< Count
; i
++) {
848 Im
.Module
= readString(Ctx
);
849 Im
.Field
= readString(Ctx
);
850 Im
.Kind
= readUint8(Ctx
);
852 case wasm::WASM_EXTERNAL_FUNCTION
:
853 NumImportedFunctions
++;
854 Im
.SigIndex
= readVaruint32(Ctx
);
856 case wasm::WASM_EXTERNAL_GLOBAL
:
857 NumImportedGlobals
++;
858 Im
.Global
.Type
= readUint8(Ctx
);
859 Im
.Global
.Mutable
= readVaruint1(Ctx
);
861 case wasm::WASM_EXTERNAL_MEMORY
:
862 Im
.Memory
= readLimits(Ctx
);
864 case wasm::WASM_EXTERNAL_TABLE
:
865 Im
.Table
= readTable(Ctx
);
866 if (Im
.Table
.ElemType
!= wasm::WASM_TYPE_FUNCREF
)
867 return make_error
<GenericBinaryError
>("Invalid table element type",
868 object_error::parse_failed
);
870 case wasm::WASM_EXTERNAL_EVENT
:
872 Im
.Event
.Attribute
= readVarint32(Ctx
);
873 Im
.Event
.SigIndex
= readVarint32(Ctx
);
876 return make_error
<GenericBinaryError
>("Unexpected import kind",
877 object_error::parse_failed
);
879 Imports
.push_back(Im
);
881 if (Ctx
.Ptr
!= Ctx
.End
)
882 return make_error
<GenericBinaryError
>("Import section ended prematurely",
883 object_error::parse_failed
);
884 return Error::success();
887 Error
WasmObjectFile::parseFunctionSection(ReadContext
&Ctx
) {
888 uint32_t Count
= readVaruint32(Ctx
);
889 FunctionTypes
.reserve(Count
);
890 uint32_t NumTypes
= Signatures
.size();
892 uint32_t Type
= readVaruint32(Ctx
);
893 if (Type
>= NumTypes
)
894 return make_error
<GenericBinaryError
>("Invalid function type",
895 object_error::parse_failed
);
896 FunctionTypes
.push_back(Type
);
898 if (Ctx
.Ptr
!= Ctx
.End
)
899 return make_error
<GenericBinaryError
>("Function section ended prematurely",
900 object_error::parse_failed
);
901 return Error::success();
904 Error
WasmObjectFile::parseTableSection(ReadContext
&Ctx
) {
905 uint32_t Count
= readVaruint32(Ctx
);
906 Tables
.reserve(Count
);
908 Tables
.push_back(readTable(Ctx
));
909 if (Tables
.back().ElemType
!= wasm::WASM_TYPE_FUNCREF
) {
910 return make_error
<GenericBinaryError
>("Invalid table element type",
911 object_error::parse_failed
);
914 if (Ctx
.Ptr
!= Ctx
.End
)
915 return make_error
<GenericBinaryError
>("Table section ended prematurely",
916 object_error::parse_failed
);
917 return Error::success();
920 Error
WasmObjectFile::parseMemorySection(ReadContext
&Ctx
) {
921 uint32_t Count
= readVaruint32(Ctx
);
922 Memories
.reserve(Count
);
924 Memories
.push_back(readLimits(Ctx
));
926 if (Ctx
.Ptr
!= Ctx
.End
)
927 return make_error
<GenericBinaryError
>("Memory section ended prematurely",
928 object_error::parse_failed
);
929 return Error::success();
932 Error
WasmObjectFile::parseGlobalSection(ReadContext
&Ctx
) {
933 GlobalSection
= Sections
.size();
934 uint32_t Count
= readVaruint32(Ctx
);
935 Globals
.reserve(Count
);
937 wasm::WasmGlobal Global
;
938 Global
.Index
= NumImportedGlobals
+ Globals
.size();
939 Global
.Type
.Type
= readUint8(Ctx
);
940 Global
.Type
.Mutable
= readVaruint1(Ctx
);
941 if (Error Err
= readInitExpr(Global
.InitExpr
, Ctx
))
943 Globals
.push_back(Global
);
945 if (Ctx
.Ptr
!= Ctx
.End
)
946 return make_error
<GenericBinaryError
>("Global section ended prematurely",
947 object_error::parse_failed
);
948 return Error::success();
951 Error
WasmObjectFile::parseEventSection(ReadContext
&Ctx
) {
952 EventSection
= Sections
.size();
953 uint32_t Count
= readVarint32(Ctx
);
954 Events
.reserve(Count
);
956 wasm::WasmEvent Event
;
957 Event
.Index
= NumImportedEvents
+ Events
.size();
958 Event
.Type
.Attribute
= readVaruint32(Ctx
);
959 Event
.Type
.SigIndex
= readVarint32(Ctx
);
960 Events
.push_back(Event
);
963 if (Ctx
.Ptr
!= Ctx
.End
)
964 return make_error
<GenericBinaryError
>("Event section ended prematurely",
965 object_error::parse_failed
);
966 return Error::success();
969 Error
WasmObjectFile::parseExportSection(ReadContext
&Ctx
) {
970 uint32_t Count
= readVaruint32(Ctx
);
971 Exports
.reserve(Count
);
972 for (uint32_t i
= 0; i
< Count
; i
++) {
974 Ex
.Name
= readString(Ctx
);
975 Ex
.Kind
= readUint8(Ctx
);
976 Ex
.Index
= readVaruint32(Ctx
);
978 case wasm::WASM_EXTERNAL_FUNCTION
:
979 if (!isValidFunctionIndex(Ex
.Index
))
980 return make_error
<GenericBinaryError
>("Invalid function export",
981 object_error::parse_failed
);
983 case wasm::WASM_EXTERNAL_GLOBAL
:
984 if (!isValidGlobalIndex(Ex
.Index
))
985 return make_error
<GenericBinaryError
>("Invalid global export",
986 object_error::parse_failed
);
988 case wasm::WASM_EXTERNAL_EVENT
:
989 if (!isValidEventIndex(Ex
.Index
))
990 return make_error
<GenericBinaryError
>("Invalid event export",
991 object_error::parse_failed
);
993 case wasm::WASM_EXTERNAL_MEMORY
:
994 case wasm::WASM_EXTERNAL_TABLE
:
997 return make_error
<GenericBinaryError
>("Unexpected export kind",
998 object_error::parse_failed
);
1000 Exports
.push_back(Ex
);
1002 if (Ctx
.Ptr
!= Ctx
.End
)
1003 return make_error
<GenericBinaryError
>("Export section ended prematurely",
1004 object_error::parse_failed
);
1005 return Error::success();
1008 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index
) const {
1009 return Index
< NumImportedFunctions
+ FunctionTypes
.size();
1012 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index
) const {
1013 return Index
>= NumImportedFunctions
&& isValidFunctionIndex(Index
);
1016 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index
) const {
1017 return Index
< NumImportedGlobals
+ Globals
.size();
1020 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index
) const {
1021 return Index
>= NumImportedGlobals
&& isValidGlobalIndex(Index
);
1024 bool WasmObjectFile::isValidEventIndex(uint32_t Index
) const {
1025 return Index
< NumImportedEvents
+ Events
.size();
1028 bool WasmObjectFile::isDefinedEventIndex(uint32_t Index
) const {
1029 return Index
>= NumImportedEvents
&& isValidEventIndex(Index
);
1032 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index
) const {
1033 return Index
< Symbols
.size() && Symbols
[Index
].isTypeFunction();
1036 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index
) const {
1037 return Index
< Symbols
.size() && Symbols
[Index
].isTypeGlobal();
1040 bool WasmObjectFile::isValidEventSymbol(uint32_t Index
) const {
1041 return Index
< Symbols
.size() && Symbols
[Index
].isTypeEvent();
1044 bool WasmObjectFile::isValidDataSymbol(uint32_t Index
) const {
1045 return Index
< Symbols
.size() && Symbols
[Index
].isTypeData();
1048 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index
) const {
1049 return Index
< Symbols
.size() && Symbols
[Index
].isTypeSection();
1052 wasm::WasmFunction
&WasmObjectFile::getDefinedFunction(uint32_t Index
) {
1053 assert(isDefinedFunctionIndex(Index
));
1054 return Functions
[Index
- NumImportedFunctions
];
1057 const wasm::WasmFunction
&
1058 WasmObjectFile::getDefinedFunction(uint32_t Index
) const {
1059 assert(isDefinedFunctionIndex(Index
));
1060 return Functions
[Index
- NumImportedFunctions
];
1063 wasm::WasmGlobal
&WasmObjectFile::getDefinedGlobal(uint32_t Index
) {
1064 assert(isDefinedGlobalIndex(Index
));
1065 return Globals
[Index
- NumImportedGlobals
];
1068 wasm::WasmEvent
&WasmObjectFile::getDefinedEvent(uint32_t Index
) {
1069 assert(isDefinedEventIndex(Index
));
1070 return Events
[Index
- NumImportedEvents
];
1073 Error
WasmObjectFile::parseStartSection(ReadContext
&Ctx
) {
1074 StartFunction
= readVaruint32(Ctx
);
1075 if (!isValidFunctionIndex(StartFunction
))
1076 return make_error
<GenericBinaryError
>("Invalid start function",
1077 object_error::parse_failed
);
1078 return Error::success();
1081 Error
WasmObjectFile::parseCodeSection(ReadContext
&Ctx
) {
1082 CodeSection
= Sections
.size();
1083 uint32_t FunctionCount
= readVaruint32(Ctx
);
1084 if (FunctionCount
!= FunctionTypes
.size()) {
1085 return make_error
<GenericBinaryError
>("Invalid function count",
1086 object_error::parse_failed
);
1089 while (FunctionCount
--) {
1090 wasm::WasmFunction Function
;
1091 const uint8_t *FunctionStart
= Ctx
.Ptr
;
1092 uint32_t Size
= readVaruint32(Ctx
);
1093 const uint8_t *FunctionEnd
= Ctx
.Ptr
+ Size
;
1095 Function
.CodeOffset
= Ctx
.Ptr
- FunctionStart
;
1096 Function
.Index
= NumImportedFunctions
+ Functions
.size();
1097 Function
.CodeSectionOffset
= FunctionStart
- Ctx
.Start
;
1098 Function
.Size
= FunctionEnd
- FunctionStart
;
1100 uint32_t NumLocalDecls
= readVaruint32(Ctx
);
1101 Function
.Locals
.reserve(NumLocalDecls
);
1102 while (NumLocalDecls
--) {
1103 wasm::WasmLocalDecl Decl
;
1104 Decl
.Count
= readVaruint32(Ctx
);
1105 Decl
.Type
= readUint8(Ctx
);
1106 Function
.Locals
.push_back(Decl
);
1109 uint32_t BodySize
= FunctionEnd
- Ctx
.Ptr
;
1110 Function
.Body
= ArrayRef
<uint8_t>(Ctx
.Ptr
, BodySize
);
1111 // This will be set later when reading in the linking metadata section.
1112 Function
.Comdat
= UINT32_MAX
;
1113 Ctx
.Ptr
+= BodySize
;
1114 assert(Ctx
.Ptr
== FunctionEnd
);
1115 Functions
.push_back(Function
);
1117 if (Ctx
.Ptr
!= Ctx
.End
)
1118 return make_error
<GenericBinaryError
>("Code section ended prematurely",
1119 object_error::parse_failed
);
1120 return Error::success();
1123 Error
WasmObjectFile::parseElemSection(ReadContext
&Ctx
) {
1124 uint32_t Count
= readVaruint32(Ctx
);
1125 ElemSegments
.reserve(Count
);
1127 wasm::WasmElemSegment Segment
;
1128 Segment
.TableIndex
= readVaruint32(Ctx
);
1129 if (Segment
.TableIndex
!= 0) {
1130 return make_error
<GenericBinaryError
>("Invalid TableIndex",
1131 object_error::parse_failed
);
1133 if (Error Err
= readInitExpr(Segment
.Offset
, Ctx
))
1135 uint32_t NumElems
= readVaruint32(Ctx
);
1136 while (NumElems
--) {
1137 Segment
.Functions
.push_back(readVaruint32(Ctx
));
1139 ElemSegments
.push_back(Segment
);
1141 if (Ctx
.Ptr
!= Ctx
.End
)
1142 return make_error
<GenericBinaryError
>("Elem section ended prematurely",
1143 object_error::parse_failed
);
1144 return Error::success();
1147 Error
WasmObjectFile::parseDataSection(ReadContext
&Ctx
) {
1148 DataSection
= Sections
.size();
1149 uint32_t Count
= readVaruint32(Ctx
);
1150 DataSegments
.reserve(Count
);
1152 WasmSegment Segment
;
1153 Segment
.Data
.MemoryIndex
= readVaruint32(Ctx
);
1154 if (Error Err
= readInitExpr(Segment
.Data
.Offset
, Ctx
))
1156 uint32_t Size
= readVaruint32(Ctx
);
1157 if (Size
> (size_t)(Ctx
.End
- Ctx
.Ptr
))
1158 return make_error
<GenericBinaryError
>("Invalid segment size",
1159 object_error::parse_failed
);
1160 Segment
.Data
.Content
= ArrayRef
<uint8_t>(Ctx
.Ptr
, Size
);
1161 // The rest of these Data fields are set later, when reading in the linking
1162 // metadata section.
1163 Segment
.Data
.Alignment
= 0;
1164 Segment
.Data
.Flags
= 0;
1165 Segment
.Data
.Comdat
= UINT32_MAX
;
1166 Segment
.SectionOffset
= Ctx
.Ptr
- Ctx
.Start
;
1168 DataSegments
.push_back(Segment
);
1170 if (Ctx
.Ptr
!= Ctx
.End
)
1171 return make_error
<GenericBinaryError
>("Data section ended prematurely",
1172 object_error::parse_failed
);
1173 return Error::success();
1176 const uint8_t *WasmObjectFile::getPtr(size_t Offset
) const {
1177 return reinterpret_cast<const uint8_t *>(getData().data() + Offset
);
1180 const wasm::WasmObjectHeader
&WasmObjectFile::getHeader() const {
1184 void WasmObjectFile::moveSymbolNext(DataRefImpl
&Symb
) const { Symb
.d
.b
++; }
1186 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb
) const {
1187 uint32_t Result
= SymbolRef::SF_None
;
1188 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1190 LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym
<< " " << Sym
<< "\n");
1191 if (Sym
.isBindingWeak())
1192 Result
|= SymbolRef::SF_Weak
;
1193 if (!Sym
.isBindingLocal())
1194 Result
|= SymbolRef::SF_Global
;
1196 Result
|= SymbolRef::SF_Hidden
;
1197 if (!Sym
.isDefined())
1198 Result
|= SymbolRef::SF_Undefined
;
1199 if (Sym
.isTypeFunction())
1200 Result
|= SymbolRef::SF_Executable
;
1204 basic_symbol_iterator
WasmObjectFile::symbol_begin() const {
1206 Ref
.d
.a
= 1; // Arbitrary non-zero value so that Ref.p is non-null
1207 Ref
.d
.b
= 0; // Symbol index
1208 return BasicSymbolRef(Ref
, this);
1211 basic_symbol_iterator
WasmObjectFile::symbol_end() const {
1213 Ref
.d
.a
= 1; // Arbitrary non-zero value so that Ref.p is non-null
1214 Ref
.d
.b
= Symbols
.size(); // Symbol index
1215 return BasicSymbolRef(Ref
, this);
1218 const WasmSymbol
&WasmObjectFile::getWasmSymbol(const DataRefImpl
&Symb
) const {
1219 return Symbols
[Symb
.d
.b
];
1222 const WasmSymbol
&WasmObjectFile::getWasmSymbol(const SymbolRef
&Symb
) const {
1223 return getWasmSymbol(Symb
.getRawDataRefImpl());
1226 Expected
<StringRef
> WasmObjectFile::getSymbolName(DataRefImpl Symb
) const {
1227 return getWasmSymbol(Symb
).Info
.Name
;
1230 Expected
<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb
) const {
1231 auto &Sym
= getWasmSymbol(Symb
);
1232 if (Sym
.Info
.Kind
== wasm::WASM_SYMBOL_TYPE_FUNCTION
&&
1233 isDefinedFunctionIndex(Sym
.Info
.ElementIndex
))
1234 return getDefinedFunction(Sym
.Info
.ElementIndex
).CodeSectionOffset
;
1236 return getSymbolValue(Symb
);
1239 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol
&Sym
) const {
1240 switch (Sym
.Info
.Kind
) {
1241 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
1242 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
1243 case wasm::WASM_SYMBOL_TYPE_EVENT
:
1244 return Sym
.Info
.ElementIndex
;
1245 case wasm::WASM_SYMBOL_TYPE_DATA
: {
1246 // The value of a data symbol is the segment offset, plus the symbol
1247 // offset within the segment.
1248 uint32_t SegmentIndex
= Sym
.Info
.DataRef
.Segment
;
1249 const wasm::WasmDataSegment
&Segment
= DataSegments
[SegmentIndex
].Data
;
1250 assert(Segment
.Offset
.Opcode
== wasm::WASM_OPCODE_I32_CONST
);
1251 return Segment
.Offset
.Value
.Int32
+ Sym
.Info
.DataRef
.Offset
;
1253 case wasm::WASM_SYMBOL_TYPE_SECTION
:
1256 llvm_unreachable("invalid symbol type");
1259 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb
) const {
1260 return getWasmSymbolValue(getWasmSymbol(Symb
));
1263 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb
) const {
1264 llvm_unreachable("not yet implemented");
1268 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb
) const {
1269 llvm_unreachable("not yet implemented");
1273 Expected
<SymbolRef::Type
>
1274 WasmObjectFile::getSymbolType(DataRefImpl Symb
) const {
1275 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1277 switch (Sym
.Info
.Kind
) {
1278 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
1279 return SymbolRef::ST_Function
;
1280 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
1281 return SymbolRef::ST_Other
;
1282 case wasm::WASM_SYMBOL_TYPE_DATA
:
1283 return SymbolRef::ST_Data
;
1284 case wasm::WASM_SYMBOL_TYPE_SECTION
:
1285 return SymbolRef::ST_Debug
;
1286 case wasm::WASM_SYMBOL_TYPE_EVENT
:
1287 return SymbolRef::ST_Other
;
1290 llvm_unreachable("Unknown WasmSymbol::SymbolType");
1291 return SymbolRef::ST_Other
;
1294 Expected
<section_iterator
>
1295 WasmObjectFile::getSymbolSection(DataRefImpl Symb
) const {
1296 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1297 if (Sym
.isUndefined())
1298 return section_end();
1301 switch (Sym
.Info
.Kind
) {
1302 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
1303 Ref
.d
.a
= CodeSection
;
1305 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
1306 Ref
.d
.a
= GlobalSection
;
1308 case wasm::WASM_SYMBOL_TYPE_DATA
:
1309 Ref
.d
.a
= DataSection
;
1311 case wasm::WASM_SYMBOL_TYPE_SECTION
:
1312 Ref
.d
.a
= Sym
.Info
.ElementIndex
;
1314 case wasm::WASM_SYMBOL_TYPE_EVENT
:
1315 Ref
.d
.a
= EventSection
;
1318 llvm_unreachable("Unknown WasmSymbol::SymbolType");
1320 return section_iterator(SectionRef(Ref
, this));
1323 void WasmObjectFile::moveSectionNext(DataRefImpl
&Sec
) const { Sec
.d
.a
++; }
1325 std::error_code
WasmObjectFile::getSectionName(DataRefImpl Sec
,
1326 StringRef
&Res
) const {
1327 const WasmSection
&S
= Sections
[Sec
.d
.a
];
1329 case wasm::WASM_SEC_##X: \
1345 case wasm::WASM_SEC_CUSTOM
:
1349 return object_error::invalid_section_index
;
1352 return std::error_code();
1355 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec
) const { return 0; }
1357 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec
) const {
1361 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec
) const {
1362 const WasmSection
&S
= Sections
[Sec
.d
.a
];
1363 return S
.Content
.size();
1366 std::error_code
WasmObjectFile::getSectionContents(DataRefImpl Sec
,
1367 StringRef
&Res
) const {
1368 const WasmSection
&S
= Sections
[Sec
.d
.a
];
1369 // This will never fail since wasm sections can never be empty (user-sections
1370 // must have a name and non-user sections each have a defined structure).
1371 Res
= StringRef(reinterpret_cast<const char *>(S
.Content
.data()),
1373 return std::error_code();
1376 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec
) const {
1380 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
1384 bool WasmObjectFile::isSectionText(DataRefImpl Sec
) const {
1385 return getWasmSection(Sec
).Type
== wasm::WASM_SEC_CODE
;
1388 bool WasmObjectFile::isSectionData(DataRefImpl Sec
) const {
1389 return getWasmSection(Sec
).Type
== wasm::WASM_SEC_DATA
;
1392 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec
) const { return false; }
1394 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec
) const { return false; }
1396 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec
) const { return false; }
1398 relocation_iterator
WasmObjectFile::section_rel_begin(DataRefImpl Ref
) const {
1399 DataRefImpl RelocRef
;
1400 RelocRef
.d
.a
= Ref
.d
.a
;
1402 return relocation_iterator(RelocationRef(RelocRef
, this));
1405 relocation_iterator
WasmObjectFile::section_rel_end(DataRefImpl Ref
) const {
1406 const WasmSection
&Sec
= getWasmSection(Ref
);
1407 DataRefImpl RelocRef
;
1408 RelocRef
.d
.a
= Ref
.d
.a
;
1409 RelocRef
.d
.b
= Sec
.Relocations
.size();
1410 return relocation_iterator(RelocationRef(RelocRef
, this));
1413 void WasmObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const { Rel
.d
.b
++; }
1415 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref
) const {
1416 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
1420 symbol_iterator
WasmObjectFile::getRelocationSymbol(DataRefImpl Ref
) const {
1421 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
1422 if (Rel
.Type
== wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB
)
1423 return symbol_end();
1425 Sym
.d
.a
= Rel
.Index
;
1427 return symbol_iterator(SymbolRef(Sym
, this));
1430 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref
) const {
1431 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
1435 void WasmObjectFile::getRelocationTypeName(
1436 DataRefImpl Ref
, SmallVectorImpl
<char> &Result
) const {
1437 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
1438 StringRef Res
= "Unknown";
1440 #define WASM_RELOC(name, value) \
1446 #include "llvm/BinaryFormat/WasmRelocs.def"
1451 Result
.append(Res
.begin(), Res
.end());
1454 section_iterator
WasmObjectFile::section_begin() const {
1457 return section_iterator(SectionRef(Ref
, this));
1460 section_iterator
WasmObjectFile::section_end() const {
1462 Ref
.d
.a
= Sections
.size();
1463 return section_iterator(SectionRef(Ref
, this));
1466 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1468 StringRef
WasmObjectFile::getFileFormatName() const { return "WASM"; }
1470 Triple::ArchType
WasmObjectFile::getArch() const { return Triple::wasm32
; }
1472 SubtargetFeatures
WasmObjectFile::getFeatures() const {
1473 return SubtargetFeatures();
1476 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection
; }
1478 bool WasmObjectFile::isSharedObject() const { return HasDylinkSection
; }
1480 const WasmSection
&WasmObjectFile::getWasmSection(DataRefImpl Ref
) const {
1481 assert(Ref
.d
.a
< Sections
.size());
1482 return Sections
[Ref
.d
.a
];
1486 WasmObjectFile::getWasmSection(const SectionRef
&Section
) const {
1487 return getWasmSection(Section
.getRawDataRefImpl());
1490 const wasm::WasmRelocation
&
1491 WasmObjectFile::getWasmRelocation(const RelocationRef
&Ref
) const {
1492 return getWasmRelocation(Ref
.getRawDataRefImpl());
1495 const wasm::WasmRelocation
&
1496 WasmObjectFile::getWasmRelocation(DataRefImpl Ref
) const {
1497 assert(Ref
.d
.a
< Sections
.size());
1498 const WasmSection
&Sec
= Sections
[Ref
.d
.a
];
1499 assert(Ref
.d
.b
< Sec
.Relocations
.size());
1500 return Sec
.Relocations
[Ref
.d
.b
];
1503 int WasmSectionOrderChecker::getSectionOrder(unsigned ID
,
1504 StringRef CustomSectionName
) {
1506 case wasm::WASM_SEC_CUSTOM
:
1507 return StringSwitch
<unsigned>(CustomSectionName
)
1508 .Case("dylink", WASM_SEC_ORDER_DYLINK
)
1509 .Case("linking", WASM_SEC_ORDER_LINKING
)
1510 .StartsWith("reloc.", WASM_SEC_ORDER_RELOC
)
1511 .Case("name", WASM_SEC_ORDER_NAME
)
1512 .Case("producers", WASM_SEC_ORDER_PRODUCERS
)
1514 case wasm::WASM_SEC_TYPE
:
1515 return WASM_SEC_ORDER_TYPE
;
1516 case wasm::WASM_SEC_IMPORT
:
1517 return WASM_SEC_ORDER_IMPORT
;
1518 case wasm::WASM_SEC_FUNCTION
:
1519 return WASM_SEC_ORDER_FUNCTION
;
1520 case wasm::WASM_SEC_TABLE
:
1521 return WASM_SEC_ORDER_TABLE
;
1522 case wasm::WASM_SEC_MEMORY
:
1523 return WASM_SEC_ORDER_MEMORY
;
1524 case wasm::WASM_SEC_GLOBAL
:
1525 return WASM_SEC_ORDER_GLOBAL
;
1526 case wasm::WASM_SEC_EXPORT
:
1527 return WASM_SEC_ORDER_EXPORT
;
1528 case wasm::WASM_SEC_START
:
1529 return WASM_SEC_ORDER_START
;
1530 case wasm::WASM_SEC_ELEM
:
1531 return WASM_SEC_ORDER_ELEM
;
1532 case wasm::WASM_SEC_CODE
:
1533 return WASM_SEC_ORDER_CODE
;
1534 case wasm::WASM_SEC_DATA
:
1535 return WASM_SEC_ORDER_DATA
;
1536 case wasm::WASM_SEC_DATACOUNT
:
1537 return WASM_SEC_ORDER_DATACOUNT
;
1538 case wasm::WASM_SEC_EVENT
:
1539 return WASM_SEC_ORDER_EVENT
;
1541 llvm_unreachable("invalid section");
1545 bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID
,
1546 StringRef CustomSectionName
) {
1547 int Order
= getSectionOrder(ID
, CustomSectionName
);
1548 if (Order
== -1) // Skip unknown sections
1550 // There can be multiple "reloc." sections. Otherwise there shouldn't be any
1551 // duplicate section orders.
1552 bool IsValid
= (LastOrder
== Order
&& Order
== WASM_SEC_ORDER_RELOC
) ||