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
= reinterpret_cast<const uint8_t *>(getData().data());
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 if ((Info
.Flags
& wasm::WASM_SYMBOL_EXPLICIT_NAME
) != 0)
509 Info
.Name
= readString(Ctx
);
511 Info
.Name
= Import
.Field
;
512 Signature
= &Signatures
[Import
.SigIndex
];
513 Info
.ImportName
= Import
.Field
;
514 Info
.ImportModule
= Import
.Module
;
518 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
519 Info
.ElementIndex
= readVaruint32(Ctx
);
520 if (!isValidGlobalIndex(Info
.ElementIndex
) ||
521 IsDefined
!= isDefinedGlobalIndex(Info
.ElementIndex
))
522 return make_error
<GenericBinaryError
>("invalid global symbol index",
523 object_error::parse_failed
);
524 if (!IsDefined
&& (Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) ==
525 wasm::WASM_SYMBOL_BINDING_WEAK
)
526 return make_error
<GenericBinaryError
>("undefined weak global symbol",
527 object_error::parse_failed
);
529 Info
.Name
= readString(Ctx
);
530 unsigned GlobalIndex
= Info
.ElementIndex
- NumImportedGlobals
;
531 wasm::WasmGlobal
&Global
= Globals
[GlobalIndex
];
532 GlobalType
= &Global
.Type
;
533 if (Global
.SymbolName
.empty())
534 Global
.SymbolName
= Info
.Name
;
536 wasm::WasmImport
&Import
= *ImportedGlobals
[Info
.ElementIndex
];
537 if ((Info
.Flags
& wasm::WASM_SYMBOL_EXPLICIT_NAME
) != 0)
538 Info
.Name
= readString(Ctx
);
540 Info
.Name
= Import
.Field
;
541 GlobalType
= &Import
.Global
;
542 Info
.ImportName
= Import
.Field
;
543 Info
.ImportModule
= Import
.Module
;
547 case wasm::WASM_SYMBOL_TYPE_DATA
:
548 Info
.Name
= readString(Ctx
);
550 uint32_t Index
= readVaruint32(Ctx
);
551 if (Index
>= DataSegments
.size())
552 return make_error
<GenericBinaryError
>("invalid data symbol index",
553 object_error::parse_failed
);
554 uint32_t Offset
= readVaruint32(Ctx
);
555 uint32_t Size
= readVaruint32(Ctx
);
556 if (Offset
+ Size
> DataSegments
[Index
].Data
.Content
.size())
557 return make_error
<GenericBinaryError
>("invalid data symbol offset",
558 object_error::parse_failed
);
559 Info
.DataRef
= wasm::WasmDataReference
{Index
, Offset
, Size
};
563 case wasm::WASM_SYMBOL_TYPE_SECTION
: {
564 if ((Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) !=
565 wasm::WASM_SYMBOL_BINDING_LOCAL
)
566 return make_error
<GenericBinaryError
>(
567 "Section symbols must have local binding",
568 object_error::parse_failed
);
569 Info
.ElementIndex
= readVaruint32(Ctx
);
570 // Use somewhat unique section name as symbol name.
571 StringRef SectionName
= Sections
[Info
.ElementIndex
].Name
;
572 Info
.Name
= SectionName
;
576 case wasm::WASM_SYMBOL_TYPE_EVENT
: {
577 Info
.ElementIndex
= readVaruint32(Ctx
);
578 if (!isValidEventIndex(Info
.ElementIndex
) ||
579 IsDefined
!= isDefinedEventIndex(Info
.ElementIndex
))
580 return make_error
<GenericBinaryError
>("invalid event symbol index",
581 object_error::parse_failed
);
582 if (!IsDefined
&& (Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) ==
583 wasm::WASM_SYMBOL_BINDING_WEAK
)
584 return make_error
<GenericBinaryError
>("undefined weak global symbol",
585 object_error::parse_failed
);
587 Info
.Name
= readString(Ctx
);
588 unsigned EventIndex
= Info
.ElementIndex
- NumImportedEvents
;
589 wasm::WasmEvent
&Event
= Events
[EventIndex
];
590 Signature
= &Signatures
[Event
.Type
.SigIndex
];
591 EventType
= &Event
.Type
;
592 if (Event
.SymbolName
.empty())
593 Event
.SymbolName
= Info
.Name
;
596 wasm::WasmImport
&Import
= *ImportedEvents
[Info
.ElementIndex
];
597 if ((Info
.Flags
& wasm::WASM_SYMBOL_EXPLICIT_NAME
) != 0)
598 Info
.Name
= readString(Ctx
);
600 Info
.Name
= Import
.Field
;
601 EventType
= &Import
.Event
;
602 Signature
= &Signatures
[EventType
->SigIndex
];
603 Info
.ImportName
= Import
.Field
;
604 Info
.ImportModule
= Import
.Module
;
610 return make_error
<GenericBinaryError
>("Invalid symbol type",
611 object_error::parse_failed
);
614 if ((Info
.Flags
& wasm::WASM_SYMBOL_BINDING_MASK
) !=
615 wasm::WASM_SYMBOL_BINDING_LOCAL
&&
616 !SymbolNames
.insert(Info
.Name
).second
)
617 return make_error
<GenericBinaryError
>("Duplicate symbol name " +
619 object_error::parse_failed
);
620 LinkingData
.SymbolTable
.emplace_back(Info
);
621 Symbols
.emplace_back(LinkingData
.SymbolTable
.back(), GlobalType
, EventType
,
623 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols
.back() << "\n");
626 return Error::success();
629 Error
WasmObjectFile::parseLinkingSectionComdat(ReadContext
&Ctx
) {
630 uint32_t ComdatCount
= readVaruint32(Ctx
);
631 StringSet
<> ComdatSet
;
632 for (unsigned ComdatIndex
= 0; ComdatIndex
< ComdatCount
; ++ComdatIndex
) {
633 StringRef Name
= readString(Ctx
);
634 if (Name
.empty() || !ComdatSet
.insert(Name
).second
)
635 return make_error
<GenericBinaryError
>("Bad/duplicate COMDAT name " +
637 object_error::parse_failed
);
638 LinkingData
.Comdats
.emplace_back(Name
);
639 uint32_t Flags
= readVaruint32(Ctx
);
641 return make_error
<GenericBinaryError
>("Unsupported COMDAT flags",
642 object_error::parse_failed
);
644 uint32_t EntryCount
= readVaruint32(Ctx
);
645 while (EntryCount
--) {
646 unsigned Kind
= readVaruint32(Ctx
);
647 unsigned Index
= readVaruint32(Ctx
);
650 return make_error
<GenericBinaryError
>("Invalid COMDAT entry type",
651 object_error::parse_failed
);
652 case wasm::WASM_COMDAT_DATA
:
653 if (Index
>= DataSegments
.size())
654 return make_error
<GenericBinaryError
>(
655 "COMDAT data index out of range", object_error::parse_failed
);
656 if (DataSegments
[Index
].Data
.Comdat
!= UINT32_MAX
)
657 return make_error
<GenericBinaryError
>("Data segment in two COMDATs",
658 object_error::parse_failed
);
659 DataSegments
[Index
].Data
.Comdat
= ComdatIndex
;
661 case wasm::WASM_COMDAT_FUNCTION
:
662 if (!isDefinedFunctionIndex(Index
))
663 return make_error
<GenericBinaryError
>(
664 "COMDAT function index out of range", object_error::parse_failed
);
665 if (getDefinedFunction(Index
).Comdat
!= UINT32_MAX
)
666 return make_error
<GenericBinaryError
>("Function in two COMDATs",
667 object_error::parse_failed
);
668 getDefinedFunction(Index
).Comdat
= ComdatIndex
;
673 return Error::success();
676 Error
WasmObjectFile::parseProducersSection(ReadContext
&Ctx
) {
677 llvm::SmallSet
<StringRef
, 3> FieldsSeen
;
678 uint32_t Fields
= readVaruint32(Ctx
);
679 for (size_t I
= 0; I
< Fields
; ++I
) {
680 StringRef FieldName
= readString(Ctx
);
681 if (!FieldsSeen
.insert(FieldName
).second
)
682 return make_error
<GenericBinaryError
>(
683 "Producers section does not have unique fields",
684 object_error::parse_failed
);
685 std::vector
<std::pair
<std::string
, std::string
>> *ProducerVec
= nullptr;
686 if (FieldName
== "language") {
687 ProducerVec
= &ProducerInfo
.Languages
;
688 } else if (FieldName
== "processed-by") {
689 ProducerVec
= &ProducerInfo
.Tools
;
690 } else if (FieldName
== "sdk") {
691 ProducerVec
= &ProducerInfo
.SDKs
;
693 return make_error
<GenericBinaryError
>(
694 "Producers section field is not named one of language, processed-by, "
696 object_error::parse_failed
);
698 uint32_t ValueCount
= readVaruint32(Ctx
);
699 llvm::SmallSet
<StringRef
, 8> ProducersSeen
;
700 for (size_t J
= 0; J
< ValueCount
; ++J
) {
701 StringRef Name
= readString(Ctx
);
702 StringRef Version
= readString(Ctx
);
703 if (!ProducersSeen
.insert(Name
).second
) {
704 return make_error
<GenericBinaryError
>(
705 "Producers section contains repeated producer",
706 object_error::parse_failed
);
708 ProducerVec
->emplace_back(Name
, Version
);
711 if (Ctx
.Ptr
!= Ctx
.End
)
712 return make_error
<GenericBinaryError
>("Producers section ended prematurely",
713 object_error::parse_failed
);
714 return Error::success();
717 Error
WasmObjectFile::parseRelocSection(StringRef Name
, ReadContext
&Ctx
) {
718 uint32_t SectionIndex
= readVaruint32(Ctx
);
719 if (SectionIndex
>= Sections
.size())
720 return make_error
<GenericBinaryError
>("Invalid section index",
721 object_error::parse_failed
);
722 WasmSection
&Section
= Sections
[SectionIndex
];
723 uint32_t RelocCount
= readVaruint32(Ctx
);
724 uint32_t EndOffset
= Section
.Content
.size();
725 uint32_t PreviousOffset
= 0;
726 while (RelocCount
--) {
727 wasm::WasmRelocation Reloc
= {};
728 Reloc
.Type
= readVaruint32(Ctx
);
729 Reloc
.Offset
= readVaruint32(Ctx
);
730 if (Reloc
.Offset
< PreviousOffset
)
731 return make_error
<GenericBinaryError
>("Relocations not in offset order",
732 object_error::parse_failed
);
733 PreviousOffset
= Reloc
.Offset
;
734 Reloc
.Index
= readVaruint32(Ctx
);
735 switch (Reloc
.Type
) {
736 case wasm::R_WASM_FUNCTION_INDEX_LEB
:
737 case wasm::R_WASM_TABLE_INDEX_SLEB
:
738 case wasm::R_WASM_TABLE_INDEX_I32
:
739 if (!isValidFunctionSymbol(Reloc
.Index
))
740 return make_error
<GenericBinaryError
>("Bad relocation function index",
741 object_error::parse_failed
);
743 case wasm::R_WASM_TYPE_INDEX_LEB
:
744 if (Reloc
.Index
>= Signatures
.size())
745 return make_error
<GenericBinaryError
>("Bad relocation type index",
746 object_error::parse_failed
);
748 case wasm::R_WASM_GLOBAL_INDEX_LEB
:
749 if (!isValidGlobalSymbol(Reloc
.Index
))
750 return make_error
<GenericBinaryError
>("Bad relocation global index",
751 object_error::parse_failed
);
753 case wasm::R_WASM_EVENT_INDEX_LEB
:
754 if (!isValidEventSymbol(Reloc
.Index
))
755 return make_error
<GenericBinaryError
>("Bad relocation event index",
756 object_error::parse_failed
);
758 case wasm::R_WASM_MEMORY_ADDR_LEB
:
759 case wasm::R_WASM_MEMORY_ADDR_SLEB
:
760 case wasm::R_WASM_MEMORY_ADDR_I32
:
761 if (!isValidDataSymbol(Reloc
.Index
))
762 return make_error
<GenericBinaryError
>("Bad relocation data index",
763 object_error::parse_failed
);
764 Reloc
.Addend
= readVarint32(Ctx
);
766 case wasm::R_WASM_FUNCTION_OFFSET_I32
:
767 if (!isValidFunctionSymbol(Reloc
.Index
))
768 return make_error
<GenericBinaryError
>("Bad relocation function index",
769 object_error::parse_failed
);
770 Reloc
.Addend
= readVarint32(Ctx
);
772 case wasm::R_WASM_SECTION_OFFSET_I32
:
773 if (!isValidSectionSymbol(Reloc
.Index
))
774 return make_error
<GenericBinaryError
>("Bad relocation section index",
775 object_error::parse_failed
);
776 Reloc
.Addend
= readVarint32(Ctx
);
779 return make_error
<GenericBinaryError
>("Bad relocation type: " +
781 object_error::parse_failed
);
784 // Relocations must fit inside the section, and must appear in order. They
785 // also shouldn't overlap a function/element boundary, but we don't bother
788 if (Reloc
.Type
== wasm::R_WASM_TABLE_INDEX_I32
||
789 Reloc
.Type
== wasm::R_WASM_MEMORY_ADDR_I32
||
790 Reloc
.Type
== wasm::R_WASM_SECTION_OFFSET_I32
||
791 Reloc
.Type
== wasm::R_WASM_FUNCTION_OFFSET_I32
)
793 if (Reloc
.Offset
+ Size
> EndOffset
)
794 return make_error
<GenericBinaryError
>("Bad relocation offset",
795 object_error::parse_failed
);
797 Section
.Relocations
.push_back(Reloc
);
799 if (Ctx
.Ptr
!= Ctx
.End
)
800 return make_error
<GenericBinaryError
>("Reloc section ended prematurely",
801 object_error::parse_failed
);
802 return Error::success();
805 Error
WasmObjectFile::parseCustomSection(WasmSection
&Sec
, ReadContext
&Ctx
) {
806 if (Sec
.Name
== "dylink") {
807 if (Error Err
= parseDylinkSection(Ctx
))
809 } else if (Sec
.Name
== "name") {
810 if (Error Err
= parseNameSection(Ctx
))
812 } else if (Sec
.Name
== "linking") {
813 if (Error Err
= parseLinkingSection(Ctx
))
815 } else if (Sec
.Name
== "producers") {
816 if (Error Err
= parseProducersSection(Ctx
))
818 } else if (Sec
.Name
.startswith("reloc.")) {
819 if (Error Err
= parseRelocSection(Sec
.Name
, Ctx
))
822 return Error::success();
825 Error
WasmObjectFile::parseTypeSection(ReadContext
&Ctx
) {
826 uint32_t Count
= readVaruint32(Ctx
);
827 Signatures
.reserve(Count
);
829 wasm::WasmSignature Sig
;
830 uint8_t Form
= readUint8(Ctx
);
831 if (Form
!= wasm::WASM_TYPE_FUNC
) {
832 return make_error
<GenericBinaryError
>("Invalid signature type",
833 object_error::parse_failed
);
835 uint32_t ParamCount
= readVaruint32(Ctx
);
836 Sig
.Params
.reserve(ParamCount
);
837 while (ParamCount
--) {
838 uint32_t ParamType
= readUint8(Ctx
);
839 Sig
.Params
.push_back(wasm::ValType(ParamType
));
841 uint32_t ReturnCount
= readVaruint32(Ctx
);
843 if (ReturnCount
!= 1) {
844 return make_error
<GenericBinaryError
>(
845 "Multiple return types not supported", object_error::parse_failed
);
847 Sig
.Returns
.push_back(wasm::ValType(readUint8(Ctx
)));
849 Signatures
.push_back(std::move(Sig
));
851 if (Ctx
.Ptr
!= Ctx
.End
)
852 return make_error
<GenericBinaryError
>("Type section ended prematurely",
853 object_error::parse_failed
);
854 return Error::success();
857 Error
WasmObjectFile::parseImportSection(ReadContext
&Ctx
) {
858 uint32_t Count
= readVaruint32(Ctx
);
859 Imports
.reserve(Count
);
860 for (uint32_t I
= 0; I
< Count
; I
++) {
862 Im
.Module
= readString(Ctx
);
863 Im
.Field
= readString(Ctx
);
864 Im
.Kind
= readUint8(Ctx
);
866 case wasm::WASM_EXTERNAL_FUNCTION
:
867 NumImportedFunctions
++;
868 Im
.SigIndex
= readVaruint32(Ctx
);
870 case wasm::WASM_EXTERNAL_GLOBAL
:
871 NumImportedGlobals
++;
872 Im
.Global
.Type
= readUint8(Ctx
);
873 Im
.Global
.Mutable
= readVaruint1(Ctx
);
875 case wasm::WASM_EXTERNAL_MEMORY
:
876 Im
.Memory
= readLimits(Ctx
);
878 case wasm::WASM_EXTERNAL_TABLE
:
879 Im
.Table
= readTable(Ctx
);
880 if (Im
.Table
.ElemType
!= wasm::WASM_TYPE_FUNCREF
)
881 return make_error
<GenericBinaryError
>("Invalid table element type",
882 object_error::parse_failed
);
884 case wasm::WASM_EXTERNAL_EVENT
:
886 Im
.Event
.Attribute
= readVarint32(Ctx
);
887 Im
.Event
.SigIndex
= readVarint32(Ctx
);
890 return make_error
<GenericBinaryError
>("Unexpected import kind",
891 object_error::parse_failed
);
893 Imports
.push_back(Im
);
895 if (Ctx
.Ptr
!= Ctx
.End
)
896 return make_error
<GenericBinaryError
>("Import section ended prematurely",
897 object_error::parse_failed
);
898 return Error::success();
901 Error
WasmObjectFile::parseFunctionSection(ReadContext
&Ctx
) {
902 uint32_t Count
= readVaruint32(Ctx
);
903 FunctionTypes
.reserve(Count
);
904 uint32_t NumTypes
= Signatures
.size();
906 uint32_t Type
= readVaruint32(Ctx
);
907 if (Type
>= NumTypes
)
908 return make_error
<GenericBinaryError
>("Invalid function type",
909 object_error::parse_failed
);
910 FunctionTypes
.push_back(Type
);
912 if (Ctx
.Ptr
!= Ctx
.End
)
913 return make_error
<GenericBinaryError
>("Function section ended prematurely",
914 object_error::parse_failed
);
915 return Error::success();
918 Error
WasmObjectFile::parseTableSection(ReadContext
&Ctx
) {
919 uint32_t Count
= readVaruint32(Ctx
);
920 Tables
.reserve(Count
);
922 Tables
.push_back(readTable(Ctx
));
923 if (Tables
.back().ElemType
!= wasm::WASM_TYPE_FUNCREF
) {
924 return make_error
<GenericBinaryError
>("Invalid table element type",
925 object_error::parse_failed
);
928 if (Ctx
.Ptr
!= Ctx
.End
)
929 return make_error
<GenericBinaryError
>("Table section ended prematurely",
930 object_error::parse_failed
);
931 return Error::success();
934 Error
WasmObjectFile::parseMemorySection(ReadContext
&Ctx
) {
935 uint32_t Count
= readVaruint32(Ctx
);
936 Memories
.reserve(Count
);
938 Memories
.push_back(readLimits(Ctx
));
940 if (Ctx
.Ptr
!= Ctx
.End
)
941 return make_error
<GenericBinaryError
>("Memory section ended prematurely",
942 object_error::parse_failed
);
943 return Error::success();
946 Error
WasmObjectFile::parseGlobalSection(ReadContext
&Ctx
) {
947 GlobalSection
= Sections
.size();
948 uint32_t Count
= readVaruint32(Ctx
);
949 Globals
.reserve(Count
);
951 wasm::WasmGlobal Global
;
952 Global
.Index
= NumImportedGlobals
+ Globals
.size();
953 Global
.Type
.Type
= readUint8(Ctx
);
954 Global
.Type
.Mutable
= readVaruint1(Ctx
);
955 if (Error Err
= readInitExpr(Global
.InitExpr
, Ctx
))
957 Globals
.push_back(Global
);
959 if (Ctx
.Ptr
!= Ctx
.End
)
960 return make_error
<GenericBinaryError
>("Global section ended prematurely",
961 object_error::parse_failed
);
962 return Error::success();
965 Error
WasmObjectFile::parseEventSection(ReadContext
&Ctx
) {
966 EventSection
= Sections
.size();
967 uint32_t Count
= readVarint32(Ctx
);
968 Events
.reserve(Count
);
970 wasm::WasmEvent Event
;
971 Event
.Index
= NumImportedEvents
+ Events
.size();
972 Event
.Type
.Attribute
= readVaruint32(Ctx
);
973 Event
.Type
.SigIndex
= readVarint32(Ctx
);
974 Events
.push_back(Event
);
977 if (Ctx
.Ptr
!= Ctx
.End
)
978 return make_error
<GenericBinaryError
>("Event section ended prematurely",
979 object_error::parse_failed
);
980 return Error::success();
983 Error
WasmObjectFile::parseExportSection(ReadContext
&Ctx
) {
984 uint32_t Count
= readVaruint32(Ctx
);
985 Exports
.reserve(Count
);
986 for (uint32_t I
= 0; I
< Count
; I
++) {
988 Ex
.Name
= readString(Ctx
);
989 Ex
.Kind
= readUint8(Ctx
);
990 Ex
.Index
= readVaruint32(Ctx
);
992 case wasm::WASM_EXTERNAL_FUNCTION
:
993 if (!isValidFunctionIndex(Ex
.Index
))
994 return make_error
<GenericBinaryError
>("Invalid function export",
995 object_error::parse_failed
);
997 case wasm::WASM_EXTERNAL_GLOBAL
:
998 if (!isValidGlobalIndex(Ex
.Index
))
999 return make_error
<GenericBinaryError
>("Invalid global export",
1000 object_error::parse_failed
);
1002 case wasm::WASM_EXTERNAL_EVENT
:
1003 if (!isValidEventIndex(Ex
.Index
))
1004 return make_error
<GenericBinaryError
>("Invalid event export",
1005 object_error::parse_failed
);
1007 case wasm::WASM_EXTERNAL_MEMORY
:
1008 case wasm::WASM_EXTERNAL_TABLE
:
1011 return make_error
<GenericBinaryError
>("Unexpected export kind",
1012 object_error::parse_failed
);
1014 Exports
.push_back(Ex
);
1016 if (Ctx
.Ptr
!= Ctx
.End
)
1017 return make_error
<GenericBinaryError
>("Export section ended prematurely",
1018 object_error::parse_failed
);
1019 return Error::success();
1022 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index
) const {
1023 return Index
< NumImportedFunctions
+ FunctionTypes
.size();
1026 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index
) const {
1027 return Index
>= NumImportedFunctions
&& isValidFunctionIndex(Index
);
1030 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index
) const {
1031 return Index
< NumImportedGlobals
+ Globals
.size();
1034 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index
) const {
1035 return Index
>= NumImportedGlobals
&& isValidGlobalIndex(Index
);
1038 bool WasmObjectFile::isValidEventIndex(uint32_t Index
) const {
1039 return Index
< NumImportedEvents
+ Events
.size();
1042 bool WasmObjectFile::isDefinedEventIndex(uint32_t Index
) const {
1043 return Index
>= NumImportedEvents
&& isValidEventIndex(Index
);
1046 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index
) const {
1047 return Index
< Symbols
.size() && Symbols
[Index
].isTypeFunction();
1050 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index
) const {
1051 return Index
< Symbols
.size() && Symbols
[Index
].isTypeGlobal();
1054 bool WasmObjectFile::isValidEventSymbol(uint32_t Index
) const {
1055 return Index
< Symbols
.size() && Symbols
[Index
].isTypeEvent();
1058 bool WasmObjectFile::isValidDataSymbol(uint32_t Index
) const {
1059 return Index
< Symbols
.size() && Symbols
[Index
].isTypeData();
1062 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index
) const {
1063 return Index
< Symbols
.size() && Symbols
[Index
].isTypeSection();
1066 wasm::WasmFunction
&WasmObjectFile::getDefinedFunction(uint32_t Index
) {
1067 assert(isDefinedFunctionIndex(Index
));
1068 return Functions
[Index
- NumImportedFunctions
];
1071 const wasm::WasmFunction
&
1072 WasmObjectFile::getDefinedFunction(uint32_t Index
) const {
1073 assert(isDefinedFunctionIndex(Index
));
1074 return Functions
[Index
- NumImportedFunctions
];
1077 wasm::WasmGlobal
&WasmObjectFile::getDefinedGlobal(uint32_t Index
) {
1078 assert(isDefinedGlobalIndex(Index
));
1079 return Globals
[Index
- NumImportedGlobals
];
1082 wasm::WasmEvent
&WasmObjectFile::getDefinedEvent(uint32_t Index
) {
1083 assert(isDefinedEventIndex(Index
));
1084 return Events
[Index
- NumImportedEvents
];
1087 Error
WasmObjectFile::parseStartSection(ReadContext
&Ctx
) {
1088 StartFunction
= readVaruint32(Ctx
);
1089 if (!isValidFunctionIndex(StartFunction
))
1090 return make_error
<GenericBinaryError
>("Invalid start function",
1091 object_error::parse_failed
);
1092 return Error::success();
1095 Error
WasmObjectFile::parseCodeSection(ReadContext
&Ctx
) {
1096 CodeSection
= Sections
.size();
1097 uint32_t FunctionCount
= readVaruint32(Ctx
);
1098 if (FunctionCount
!= FunctionTypes
.size()) {
1099 return make_error
<GenericBinaryError
>("Invalid function count",
1100 object_error::parse_failed
);
1103 while (FunctionCount
--) {
1104 wasm::WasmFunction Function
;
1105 const uint8_t *FunctionStart
= Ctx
.Ptr
;
1106 uint32_t Size
= readVaruint32(Ctx
);
1107 const uint8_t *FunctionEnd
= Ctx
.Ptr
+ Size
;
1109 Function
.CodeOffset
= Ctx
.Ptr
- FunctionStart
;
1110 Function
.Index
= NumImportedFunctions
+ Functions
.size();
1111 Function
.CodeSectionOffset
= FunctionStart
- Ctx
.Start
;
1112 Function
.Size
= FunctionEnd
- FunctionStart
;
1114 uint32_t NumLocalDecls
= readVaruint32(Ctx
);
1115 Function
.Locals
.reserve(NumLocalDecls
);
1116 while (NumLocalDecls
--) {
1117 wasm::WasmLocalDecl Decl
;
1118 Decl
.Count
= readVaruint32(Ctx
);
1119 Decl
.Type
= readUint8(Ctx
);
1120 Function
.Locals
.push_back(Decl
);
1123 uint32_t BodySize
= FunctionEnd
- Ctx
.Ptr
;
1124 Function
.Body
= ArrayRef
<uint8_t>(Ctx
.Ptr
, BodySize
);
1125 // This will be set later when reading in the linking metadata section.
1126 Function
.Comdat
= UINT32_MAX
;
1127 Ctx
.Ptr
+= BodySize
;
1128 assert(Ctx
.Ptr
== FunctionEnd
);
1129 Functions
.push_back(Function
);
1131 if (Ctx
.Ptr
!= Ctx
.End
)
1132 return make_error
<GenericBinaryError
>("Code section ended prematurely",
1133 object_error::parse_failed
);
1134 return Error::success();
1137 Error
WasmObjectFile::parseElemSection(ReadContext
&Ctx
) {
1138 uint32_t Count
= readVaruint32(Ctx
);
1139 ElemSegments
.reserve(Count
);
1141 wasm::WasmElemSegment Segment
;
1142 Segment
.TableIndex
= readVaruint32(Ctx
);
1143 if (Segment
.TableIndex
!= 0) {
1144 return make_error
<GenericBinaryError
>("Invalid TableIndex",
1145 object_error::parse_failed
);
1147 if (Error Err
= readInitExpr(Segment
.Offset
, Ctx
))
1149 uint32_t NumElems
= readVaruint32(Ctx
);
1150 while (NumElems
--) {
1151 Segment
.Functions
.push_back(readVaruint32(Ctx
));
1153 ElemSegments
.push_back(Segment
);
1155 if (Ctx
.Ptr
!= Ctx
.End
)
1156 return make_error
<GenericBinaryError
>("Elem section ended prematurely",
1157 object_error::parse_failed
);
1158 return Error::success();
1161 Error
WasmObjectFile::parseDataSection(ReadContext
&Ctx
) {
1162 DataSection
= Sections
.size();
1163 uint32_t Count
= readVaruint32(Ctx
);
1164 DataSegments
.reserve(Count
);
1166 WasmSegment Segment
;
1167 Segment
.Data
.MemoryIndex
= readVaruint32(Ctx
);
1168 if (Error Err
= readInitExpr(Segment
.Data
.Offset
, Ctx
))
1170 uint32_t Size
= readVaruint32(Ctx
);
1171 if (Size
> (size_t)(Ctx
.End
- Ctx
.Ptr
))
1172 return make_error
<GenericBinaryError
>("Invalid segment size",
1173 object_error::parse_failed
);
1174 Segment
.Data
.Content
= ArrayRef
<uint8_t>(Ctx
.Ptr
, Size
);
1175 // The rest of these Data fields are set later, when reading in the linking
1176 // metadata section.
1177 Segment
.Data
.Alignment
= 0;
1178 Segment
.Data
.Flags
= 0;
1179 Segment
.Data
.Comdat
= UINT32_MAX
;
1180 Segment
.SectionOffset
= Ctx
.Ptr
- Ctx
.Start
;
1182 DataSegments
.push_back(Segment
);
1184 if (Ctx
.Ptr
!= Ctx
.End
)
1185 return make_error
<GenericBinaryError
>("Data section ended prematurely",
1186 object_error::parse_failed
);
1187 return Error::success();
1190 const wasm::WasmObjectHeader
&WasmObjectFile::getHeader() const {
1194 void WasmObjectFile::moveSymbolNext(DataRefImpl
&Symb
) const { Symb
.d
.b
++; }
1196 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb
) const {
1197 uint32_t Result
= SymbolRef::SF_None
;
1198 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1200 LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym
<< " " << Sym
<< "\n");
1201 if (Sym
.isBindingWeak())
1202 Result
|= SymbolRef::SF_Weak
;
1203 if (!Sym
.isBindingLocal())
1204 Result
|= SymbolRef::SF_Global
;
1206 Result
|= SymbolRef::SF_Hidden
;
1207 if (!Sym
.isDefined())
1208 Result
|= SymbolRef::SF_Undefined
;
1209 if (Sym
.isTypeFunction())
1210 Result
|= SymbolRef::SF_Executable
;
1214 basic_symbol_iterator
WasmObjectFile::symbol_begin() const {
1216 Ref
.d
.a
= 1; // Arbitrary non-zero value so that Ref.p is non-null
1217 Ref
.d
.b
= 0; // Symbol index
1218 return BasicSymbolRef(Ref
, this);
1221 basic_symbol_iterator
WasmObjectFile::symbol_end() const {
1223 Ref
.d
.a
= 1; // Arbitrary non-zero value so that Ref.p is non-null
1224 Ref
.d
.b
= Symbols
.size(); // Symbol index
1225 return BasicSymbolRef(Ref
, this);
1228 const WasmSymbol
&WasmObjectFile::getWasmSymbol(const DataRefImpl
&Symb
) const {
1229 return Symbols
[Symb
.d
.b
];
1232 const WasmSymbol
&WasmObjectFile::getWasmSymbol(const SymbolRef
&Symb
) const {
1233 return getWasmSymbol(Symb
.getRawDataRefImpl());
1236 Expected
<StringRef
> WasmObjectFile::getSymbolName(DataRefImpl Symb
) const {
1237 return getWasmSymbol(Symb
).Info
.Name
;
1240 Expected
<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb
) const {
1241 auto &Sym
= getWasmSymbol(Symb
);
1242 if (Sym
.Info
.Kind
== wasm::WASM_SYMBOL_TYPE_FUNCTION
&&
1243 isDefinedFunctionIndex(Sym
.Info
.ElementIndex
))
1244 return getDefinedFunction(Sym
.Info
.ElementIndex
).CodeSectionOffset
;
1246 return getSymbolValue(Symb
);
1249 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol
&Sym
) const {
1250 switch (Sym
.Info
.Kind
) {
1251 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
1252 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
1253 case wasm::WASM_SYMBOL_TYPE_EVENT
:
1254 return Sym
.Info
.ElementIndex
;
1255 case wasm::WASM_SYMBOL_TYPE_DATA
: {
1256 // The value of a data symbol is the segment offset, plus the symbol
1257 // offset within the segment.
1258 uint32_t SegmentIndex
= Sym
.Info
.DataRef
.Segment
;
1259 const wasm::WasmDataSegment
&Segment
= DataSegments
[SegmentIndex
].Data
;
1260 assert(Segment
.Offset
.Opcode
== wasm::WASM_OPCODE_I32_CONST
);
1261 return Segment
.Offset
.Value
.Int32
+ Sym
.Info
.DataRef
.Offset
;
1263 case wasm::WASM_SYMBOL_TYPE_SECTION
:
1266 llvm_unreachable("invalid symbol type");
1269 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb
) const {
1270 return getWasmSymbolValue(getWasmSymbol(Symb
));
1273 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb
) const {
1274 llvm_unreachable("not yet implemented");
1278 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb
) const {
1279 llvm_unreachable("not yet implemented");
1283 Expected
<SymbolRef::Type
>
1284 WasmObjectFile::getSymbolType(DataRefImpl Symb
) const {
1285 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1287 switch (Sym
.Info
.Kind
) {
1288 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
1289 return SymbolRef::ST_Function
;
1290 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
1291 return SymbolRef::ST_Other
;
1292 case wasm::WASM_SYMBOL_TYPE_DATA
:
1293 return SymbolRef::ST_Data
;
1294 case wasm::WASM_SYMBOL_TYPE_SECTION
:
1295 return SymbolRef::ST_Debug
;
1296 case wasm::WASM_SYMBOL_TYPE_EVENT
:
1297 return SymbolRef::ST_Other
;
1300 llvm_unreachable("Unknown WasmSymbol::SymbolType");
1301 return SymbolRef::ST_Other
;
1304 Expected
<section_iterator
>
1305 WasmObjectFile::getSymbolSection(DataRefImpl Symb
) const {
1306 const WasmSymbol
&Sym
= getWasmSymbol(Symb
);
1307 if (Sym
.isUndefined())
1308 return section_end();
1311 switch (Sym
.Info
.Kind
) {
1312 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
1313 Ref
.d
.a
= CodeSection
;
1315 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
1316 Ref
.d
.a
= GlobalSection
;
1318 case wasm::WASM_SYMBOL_TYPE_DATA
:
1319 Ref
.d
.a
= DataSection
;
1321 case wasm::WASM_SYMBOL_TYPE_SECTION
:
1322 Ref
.d
.a
= Sym
.Info
.ElementIndex
;
1324 case wasm::WASM_SYMBOL_TYPE_EVENT
:
1325 Ref
.d
.a
= EventSection
;
1328 llvm_unreachable("Unknown WasmSymbol::SymbolType");
1330 return section_iterator(SectionRef(Ref
, this));
1333 void WasmObjectFile::moveSectionNext(DataRefImpl
&Sec
) const { Sec
.d
.a
++; }
1335 std::error_code
WasmObjectFile::getSectionName(DataRefImpl Sec
,
1336 StringRef
&Res
) const {
1337 const WasmSection
&S
= Sections
[Sec
.d
.a
];
1339 case wasm::WASM_SEC_##X: \
1355 case wasm::WASM_SEC_CUSTOM
:
1359 return object_error::invalid_section_index
;
1362 return std::error_code();
1365 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec
) const { return 0; }
1367 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec
) const {
1371 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec
) const {
1372 const WasmSection
&S
= Sections
[Sec
.d
.a
];
1373 return S
.Content
.size();
1376 std::error_code
WasmObjectFile::getSectionContents(DataRefImpl Sec
,
1377 StringRef
&Res
) const {
1378 const WasmSection
&S
= Sections
[Sec
.d
.a
];
1379 // This will never fail since wasm sections can never be empty (user-sections
1380 // must have a name and non-user sections each have a defined structure).
1381 Res
= StringRef(reinterpret_cast<const char *>(S
.Content
.data()),
1383 return std::error_code();
1386 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec
) const {
1390 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
1394 bool WasmObjectFile::isSectionText(DataRefImpl Sec
) const {
1395 return getWasmSection(Sec
).Type
== wasm::WASM_SEC_CODE
;
1398 bool WasmObjectFile::isSectionData(DataRefImpl Sec
) const {
1399 return getWasmSection(Sec
).Type
== wasm::WASM_SEC_DATA
;
1402 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec
) const { return false; }
1404 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec
) const { return false; }
1406 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec
) const { return false; }
1408 relocation_iterator
WasmObjectFile::section_rel_begin(DataRefImpl Ref
) const {
1409 DataRefImpl RelocRef
;
1410 RelocRef
.d
.a
= Ref
.d
.a
;
1412 return relocation_iterator(RelocationRef(RelocRef
, this));
1415 relocation_iterator
WasmObjectFile::section_rel_end(DataRefImpl Ref
) const {
1416 const WasmSection
&Sec
= getWasmSection(Ref
);
1417 DataRefImpl RelocRef
;
1418 RelocRef
.d
.a
= Ref
.d
.a
;
1419 RelocRef
.d
.b
= Sec
.Relocations
.size();
1420 return relocation_iterator(RelocationRef(RelocRef
, this));
1423 void WasmObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const { Rel
.d
.b
++; }
1425 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref
) const {
1426 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
1430 symbol_iterator
WasmObjectFile::getRelocationSymbol(DataRefImpl Ref
) const {
1431 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
1432 if (Rel
.Type
== wasm::R_WASM_TYPE_INDEX_LEB
)
1433 return symbol_end();
1436 Sym
.d
.b
= Rel
.Index
;
1437 return symbol_iterator(SymbolRef(Sym
, this));
1440 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref
) const {
1441 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
1445 void WasmObjectFile::getRelocationTypeName(
1446 DataRefImpl Ref
, SmallVectorImpl
<char> &Result
) const {
1447 const wasm::WasmRelocation
&Rel
= getWasmRelocation(Ref
);
1448 StringRef Res
= "Unknown";
1450 #define WASM_RELOC(name, value) \
1456 #include "llvm/BinaryFormat/WasmRelocs.def"
1461 Result
.append(Res
.begin(), Res
.end());
1464 section_iterator
WasmObjectFile::section_begin() const {
1467 return section_iterator(SectionRef(Ref
, this));
1470 section_iterator
WasmObjectFile::section_end() const {
1472 Ref
.d
.a
= Sections
.size();
1473 return section_iterator(SectionRef(Ref
, this));
1476 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1478 StringRef
WasmObjectFile::getFileFormatName() const { return "WASM"; }
1480 Triple::ArchType
WasmObjectFile::getArch() const { return Triple::wasm32
; }
1482 SubtargetFeatures
WasmObjectFile::getFeatures() const {
1483 return SubtargetFeatures();
1486 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection
; }
1488 bool WasmObjectFile::isSharedObject() const { return HasDylinkSection
; }
1490 const WasmSection
&WasmObjectFile::getWasmSection(DataRefImpl Ref
) const {
1491 assert(Ref
.d
.a
< Sections
.size());
1492 return Sections
[Ref
.d
.a
];
1496 WasmObjectFile::getWasmSection(const SectionRef
&Section
) const {
1497 return getWasmSection(Section
.getRawDataRefImpl());
1500 const wasm::WasmRelocation
&
1501 WasmObjectFile::getWasmRelocation(const RelocationRef
&Ref
) const {
1502 return getWasmRelocation(Ref
.getRawDataRefImpl());
1505 const wasm::WasmRelocation
&
1506 WasmObjectFile::getWasmRelocation(DataRefImpl Ref
) const {
1507 assert(Ref
.d
.a
< Sections
.size());
1508 const WasmSection
&Sec
= Sections
[Ref
.d
.a
];
1509 assert(Ref
.d
.b
< Sec
.Relocations
.size());
1510 return Sec
.Relocations
[Ref
.d
.b
];
1513 int WasmSectionOrderChecker::getSectionOrder(unsigned ID
,
1514 StringRef CustomSectionName
) {
1516 case wasm::WASM_SEC_CUSTOM
:
1517 return StringSwitch
<unsigned>(CustomSectionName
)
1518 .Case("dylink", WASM_SEC_ORDER_DYLINK
)
1519 .Case("linking", WASM_SEC_ORDER_LINKING
)
1520 .StartsWith("reloc.", WASM_SEC_ORDER_RELOC
)
1521 .Case("name", WASM_SEC_ORDER_NAME
)
1522 .Case("producers", WASM_SEC_ORDER_PRODUCERS
)
1524 case wasm::WASM_SEC_TYPE
:
1525 return WASM_SEC_ORDER_TYPE
;
1526 case wasm::WASM_SEC_IMPORT
:
1527 return WASM_SEC_ORDER_IMPORT
;
1528 case wasm::WASM_SEC_FUNCTION
:
1529 return WASM_SEC_ORDER_FUNCTION
;
1530 case wasm::WASM_SEC_TABLE
:
1531 return WASM_SEC_ORDER_TABLE
;
1532 case wasm::WASM_SEC_MEMORY
:
1533 return WASM_SEC_ORDER_MEMORY
;
1534 case wasm::WASM_SEC_GLOBAL
:
1535 return WASM_SEC_ORDER_GLOBAL
;
1536 case wasm::WASM_SEC_EXPORT
:
1537 return WASM_SEC_ORDER_EXPORT
;
1538 case wasm::WASM_SEC_START
:
1539 return WASM_SEC_ORDER_START
;
1540 case wasm::WASM_SEC_ELEM
:
1541 return WASM_SEC_ORDER_ELEM
;
1542 case wasm::WASM_SEC_CODE
:
1543 return WASM_SEC_ORDER_CODE
;
1544 case wasm::WASM_SEC_DATA
:
1545 return WASM_SEC_ORDER_DATA
;
1546 case wasm::WASM_SEC_DATACOUNT
:
1547 return WASM_SEC_ORDER_DATACOUNT
;
1548 case wasm::WASM_SEC_EVENT
:
1549 return WASM_SEC_ORDER_EVENT
;
1551 llvm_unreachable("invalid section");
1555 bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID
,
1556 StringRef CustomSectionName
) {
1557 int Order
= getSectionOrder(ID
, CustomSectionName
);
1558 if (Order
== -1) // Skip unknown sections
1560 // There can be multiple "reloc." sections. Otherwise there shouldn't be any
1561 // duplicate section orders.
1562 bool IsValid
= (LastOrder
== Order
&& Order
== WASM_SEC_ORDER_RELOC
) ||