Line data Source code
1 : //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/ADT/ArrayRef.h"
11 : #include "llvm/ADT/DenseSet.h"
12 : #include "llvm/ADT/STLExtras.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 <algorithm>
28 : #include <cassert>
29 : #include <cstdint>
30 : #include <cstring>
31 : #include <system_error>
32 :
33 : #define DEBUG_TYPE "wasm-object"
34 :
35 : using namespace llvm;
36 : using namespace object;
37 :
38 0 : void WasmSymbol::print(raw_ostream &Out) const {
39 0 : Out << "Name=" << Info.Name
40 0 : << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
41 0 : << ", Flags=" << Info.Flags;
42 0 : if (!isTypeData()) {
43 0 : Out << ", ElemIndex=" << Info.ElementIndex;
44 0 : } else if (isDefined()) {
45 0 : Out << ", Segment=" << Info.DataRef.Segment;
46 0 : Out << ", Offset=" << Info.DataRef.Offset;
47 0 : Out << ", Size=" << Info.DataRef.Size;
48 : }
49 0 : }
50 :
51 : #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
52 : LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
53 : #endif
54 :
55 : Expected<std::unique_ptr<WasmObjectFile>>
56 360 : ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
57 : Error Err = Error::success();
58 360 : auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err);
59 358 : if (Err)
60 : return std::move(Err);
61 :
62 : return std::move(ObjectFile);
63 : }
64 :
65 : #define VARINT7_MAX ((1 << 7) - 1)
66 : #define VARINT7_MIN (-(1 << 7))
67 : #define VARUINT7_MAX (1 << 7)
68 : #define VARUINT1_MAX (1)
69 :
70 0 : static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
71 0 : if (Ctx.Ptr == Ctx.End)
72 0 : report_fatal_error("EOF while reading uint8");
73 7184 : return *Ctx.Ptr++;
74 : }
75 :
76 0 : static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
77 0 : if (Ctx.Ptr + 4 > Ctx.End)
78 0 : report_fatal_error("EOF while reading uint32");
79 : uint32_t Result = support::endian::read32le(Ctx.Ptr);
80 359 : Ctx.Ptr += 4;
81 0 : return Result;
82 : }
83 :
84 0 : static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
85 0 : if (Ctx.Ptr + 4 > Ctx.End)
86 0 : report_fatal_error("EOF while reading float64");
87 : int32_t Result = 0;
88 0 : memcpy(&Result, Ctx.Ptr, sizeof(Result));
89 0 : Ctx.Ptr += sizeof(Result);
90 0 : return Result;
91 : }
92 :
93 0 : static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
94 0 : if (Ctx.Ptr + 8 > Ctx.End)
95 0 : report_fatal_error("EOF while reading float64");
96 : int64_t Result = 0;
97 0 : memcpy(&Result, Ctx.Ptr, sizeof(Result));
98 0 : Ctx.Ptr += sizeof(Result);
99 0 : return Result;
100 : }
101 :
102 0 : static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
103 : unsigned Count;
104 0 : const char *Error = nullptr;
105 0 : uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
106 0 : if (Error)
107 0 : report_fatal_error(Error);
108 0 : Ctx.Ptr += Count;
109 0 : return Result;
110 : }
111 :
112 3794 : static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
113 3794 : uint32_t StringLen = readULEB128(Ctx);
114 3794 : if (Ctx.Ptr + StringLen > Ctx.End)
115 1 : report_fatal_error("EOF while reading string");
116 : StringRef Return =
117 : StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
118 3793 : Ctx.Ptr += StringLen;
119 3793 : return Return;
120 : }
121 :
122 0 : static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
123 : unsigned Count;
124 0 : const char *Error = nullptr;
125 0 : uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
126 0 : if (Error)
127 0 : report_fatal_error(Error);
128 0 : Ctx.Ptr += Count;
129 0 : return Result;
130 : }
131 :
132 891 : static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
133 891 : int64_t result = readLEB128(Ctx);
134 891 : if (result > VARUINT1_MAX || result < 0)
135 0 : report_fatal_error("LEB is outside Varuint1 range");
136 891 : return result;
137 : }
138 :
139 894 : static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
140 894 : int64_t result = readLEB128(Ctx);
141 894 : if (result > INT32_MAX || result < INT32_MIN)
142 0 : report_fatal_error("LEB is outside Varint32 range");
143 894 : return result;
144 : }
145 :
146 16882 : static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
147 16882 : uint64_t result = readULEB128(Ctx);
148 16881 : if (result > UINT32_MAX)
149 0 : report_fatal_error("LEB is outside Varuint32 range");
150 16881 : return result;
151 : }
152 :
153 : static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
154 12 : return readLEB128(Ctx);
155 : }
156 :
157 : static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
158 449 : return readUint8(Ctx);
159 : }
160 :
161 449 : static Error readInitExpr(wasm::WasmInitExpr &Expr,
162 : WasmObjectFile::ReadContext &Ctx) {
163 449 : Expr.Opcode = readOpcode(Ctx);
164 :
165 449 : switch (Expr.Opcode) {
166 436 : case wasm::WASM_OPCODE_I32_CONST:
167 436 : Expr.Value.Int32 = readVarint32(Ctx);
168 436 : break;
169 : case wasm::WASM_OPCODE_I64_CONST:
170 12 : Expr.Value.Int64 = readVarint64(Ctx);
171 12 : break;
172 0 : case wasm::WASM_OPCODE_F32_CONST:
173 0 : Expr.Value.Float32 = readFloat32(Ctx);
174 0 : break;
175 0 : case wasm::WASM_OPCODE_F64_CONST:
176 0 : Expr.Value.Float64 = readFloat64(Ctx);
177 0 : break;
178 1 : case wasm::WASM_OPCODE_GET_GLOBAL:
179 1 : Expr.Value.Global = readULEB128(Ctx);
180 1 : break;
181 0 : default:
182 : return make_error<GenericBinaryError>("Invalid opcode in init_expr",
183 : object_error::parse_failed);
184 : }
185 :
186 : uint8_t EndOpcode = readOpcode(Ctx);
187 449 : if (EndOpcode != wasm::WASM_OPCODE_END) {
188 : return make_error<GenericBinaryError>("Invalid init_expr",
189 : object_error::parse_failed);
190 : }
191 : return Error::success();
192 : }
193 :
194 657 : static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
195 : wasm::WasmLimits Result;
196 657 : Result.Flags = readVaruint1(Ctx);
197 657 : Result.Initial = readVaruint32(Ctx);
198 657 : if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
199 83 : Result.Maximum = readVaruint32(Ctx);
200 657 : return Result;
201 : }
202 :
203 328 : static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) {
204 : wasm::WasmTable Table;
205 328 : Table.ElemType = readUint8(Ctx);
206 328 : Table.Limits = readLimits(Ctx);
207 328 : return Table;
208 : }
209 :
210 2236 : static Error readSection(WasmSection &Section,
211 : WasmObjectFile::ReadContext &Ctx) {
212 2236 : Section.Offset = Ctx.Ptr - Ctx.Start;
213 2236 : Section.Type = readUint8(Ctx);
214 : LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
215 2236 : uint32_t Size = readVaruint32(Ctx);
216 2235 : if (Size == 0)
217 : return make_error<StringError>("Zero length section",
218 : object_error::parse_failed);
219 2235 : if (Ctx.Ptr + Size > Ctx.End)
220 : return make_error<StringError>("Section too large",
221 : object_error::parse_failed);
222 2233 : if (Section.Type == wasm::WASM_SEC_CUSTOM) {
223 : WasmObjectFile::ReadContext SectionCtx;
224 586 : SectionCtx.Start = Ctx.Ptr;
225 586 : SectionCtx.Ptr = Ctx.Ptr;
226 586 : SectionCtx.End = Ctx.Ptr + Size;
227 :
228 586 : Section.Name = readString(SectionCtx);
229 :
230 585 : uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
231 585 : Ctx.Ptr += SectionNameSize;
232 585 : Size -= SectionNameSize;
233 : }
234 2232 : Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
235 2232 : Ctx.Ptr += Size;
236 : return Error::success();
237 : }
238 :
239 360 : WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
240 360 : : ObjectFile(Binary::ID_Wasm, Buffer) {
241 : ErrorAsOutParameter ErrAsOutParam(&Err);
242 720 : Header.Magic = getData().substr(0, 4);
243 : if (Header.Magic != StringRef("\0asm", 4)) {
244 : Err =
245 : make_error<StringError>("Bad magic number", object_error::parse_failed);
246 0 : return;
247 : }
248 :
249 : ReadContext Ctx;
250 360 : Ctx.Start = getPtr(0);
251 360 : Ctx.Ptr = Ctx.Start + 4;
252 360 : Ctx.End = Ctx.Start + getData().size();
253 :
254 360 : if (Ctx.Ptr + 4 > Ctx.End) {
255 : Err = make_error<StringError>("Missing version number",
256 : object_error::parse_failed);
257 1 : return;
258 : }
259 :
260 359 : Header.Version = readUint32(Ctx);
261 359 : if (Header.Version != wasm::WasmVersion) {
262 : Err = make_error<StringError>("Bad version number",
263 : object_error::parse_failed);
264 2 : return;
265 : }
266 :
267 : WasmSection Sec;
268 2584 : while (Ctx.Ptr < Ctx.End) {
269 4470 : if ((Err = readSection(Sec, Ctx)))
270 : return;
271 4464 : if ((Err = parseSection(Sec)))
272 : return;
273 :
274 2227 : Sections.push_back(Sec);
275 : }
276 : }
277 :
278 2232 : Error WasmObjectFile::parseSection(WasmSection &Sec) {
279 : ReadContext Ctx;
280 2232 : Ctx.Start = Sec.Content.data();
281 2232 : Ctx.End = Ctx.Start + Sec.Content.size();
282 2232 : Ctx.Ptr = Ctx.Start;
283 2232 : switch (Sec.Type) {
284 585 : case wasm::WASM_SEC_CUSTOM:
285 585 : return parseCustomSection(Sec, Ctx);
286 318 : case wasm::WASM_SEC_TYPE:
287 318 : return parseTypeSection(Ctx);
288 274 : case wasm::WASM_SEC_IMPORT:
289 274 : return parseImportSection(Ctx);
290 311 : case wasm::WASM_SEC_FUNCTION:
291 311 : return parseFunctionSection(Ctx);
292 77 : case wasm::WASM_SEC_TABLE:
293 77 : return parseTableSection(Ctx);
294 76 : case wasm::WASM_SEC_MEMORY:
295 76 : return parseMemorySection(Ctx);
296 70 : case wasm::WASM_SEC_GLOBAL:
297 70 : return parseGlobalSection(Ctx);
298 66 : case wasm::WASM_SEC_EXPORT:
299 66 : return parseExportSection(Ctx);
300 2 : case wasm::WASM_SEC_START:
301 2 : return parseStartSection(Ctx);
302 51 : case wasm::WASM_SEC_ELEM:
303 51 : return parseElemSection(Ctx);
304 311 : case wasm::WASM_SEC_CODE:
305 311 : return parseCodeSection(Ctx);
306 91 : case wasm::WASM_SEC_DATA:
307 91 : return parseDataSection(Ctx);
308 0 : default:
309 : return make_error<GenericBinaryError>("Bad section type",
310 : object_error::parse_failed);
311 : }
312 : }
313 :
314 74 : Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
315 : llvm::DenseSet<uint64_t> Seen;
316 222 : if (Functions.size() != FunctionTypes.size()) {
317 : return make_error<GenericBinaryError>("Names must come after code section",
318 : object_error::parse_failed);
319 : }
320 :
321 147 : while (Ctx.Ptr < Ctx.End) {
322 : uint8_t Type = readUint8(Ctx);
323 74 : uint32_t Size = readVaruint32(Ctx);
324 74 : const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
325 74 : switch (Type) {
326 74 : case wasm::WASM_NAMES_FUNCTION: {
327 74 : uint32_t Count = readVaruint32(Ctx);
328 510 : while (Count--) {
329 437 : uint32_t Index = readVaruint32(Ctx);
330 437 : if (!Seen.insert(Index).second)
331 : return make_error<GenericBinaryError>("Function named more than once",
332 : object_error::parse_failed);
333 436 : StringRef Name = readString(Ctx);
334 436 : if (!isValidFunctionIndex(Index) || Name.empty())
335 : return make_error<GenericBinaryError>("Invalid name entry",
336 : object_error::parse_failed);
337 436 : DebugNames.push_back(wasm::WasmFunctionName{Index, Name});
338 436 : if (isDefinedFunctionIndex(Index))
339 418 : getDefinedFunction(Index).DebugName = Name;
340 : }
341 : break;
342 : }
343 : // Ignore local names for now
344 0 : case wasm::WASM_NAMES_LOCAL:
345 : default:
346 0 : Ctx.Ptr += Size;
347 0 : break;
348 : }
349 73 : if (Ctx.Ptr != SubSectionEnd)
350 : return make_error<GenericBinaryError>(
351 : "Name sub-section ended prematurely", object_error::parse_failed);
352 : }
353 :
354 73 : if (Ctx.Ptr != Ctx.End)
355 : return make_error<GenericBinaryError>("Name section ended prematurely",
356 : object_error::parse_failed);
357 : return Error::success();
358 : }
359 :
360 275 : Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
361 275 : HasLinkingSection = true;
362 825 : if (Functions.size() != FunctionTypes.size()) {
363 : return make_error<GenericBinaryError>(
364 : "Linking data must come after code section",
365 : object_error::parse_failed);
366 : }
367 :
368 275 : LinkingData.Version = readVaruint32(Ctx);
369 275 : if (LinkingData.Version != wasm::WasmMetadataVersion) {
370 : return make_error<GenericBinaryError>(
371 1 : "Unexpected metadata version: " + Twine(LinkingData.Version) +
372 1 : " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
373 : object_error::parse_failed);
374 : }
375 :
376 274 : const uint8_t *OrigEnd = Ctx.End;
377 635 : while (Ctx.Ptr < OrigEnd) {
378 362 : Ctx.End = OrigEnd;
379 : uint8_t Type = readUint8(Ctx);
380 362 : uint32_t Size = readVaruint32(Ctx);
381 : LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
382 : << "\n");
383 362 : Ctx.End = Ctx.Ptr + Size;
384 362 : switch (Type) {
385 263 : case wasm::WASM_SYMBOL_TABLE:
386 526 : if (Error Err = parseLinkingSectionSymtab(Ctx))
387 263 : return Err;
388 : break;
389 74 : case wasm::WASM_SEGMENT_INFO: {
390 74 : uint32_t Count = readVaruint32(Ctx);
391 148 : if (Count > DataSegments.size())
392 : return make_error<GenericBinaryError>("Too many segment names",
393 : object_error::parse_failed);
394 235 : for (uint32_t i = 0; i < Count; i++) {
395 322 : DataSegments[i].Data.Name = readString(Ctx);
396 322 : DataSegments[i].Data.Alignment = readVaruint32(Ctx);
397 322 : DataSegments[i].Data.Flags = readVaruint32(Ctx);
398 : }
399 : break;
400 : }
401 7 : case wasm::WASM_INIT_FUNCS: {
402 7 : uint32_t Count = readVaruint32(Ctx);
403 7 : LinkingData.InitFunctions.reserve(Count);
404 51 : for (uint32_t i = 0; i < Count; i++) {
405 : wasm::WasmInitFunc Init;
406 44 : Init.Priority = readVaruint32(Ctx);
407 44 : Init.Symbol = readVaruint32(Ctx);
408 44 : if (!isValidFunctionSymbol(Init.Symbol))
409 0 : return make_error<GenericBinaryError>("Invalid function symbol: " +
410 0 : Twine(Init.Symbol),
411 : object_error::parse_failed);
412 44 : LinkingData.InitFunctions.emplace_back(Init);
413 : }
414 : break;
415 : }
416 5 : case wasm::WASM_COMDAT_INFO:
417 10 : if (Error Err = parseLinkingSectionComdat(Ctx))
418 5 : return Err;
419 : break;
420 13 : default:
421 13 : Ctx.Ptr += Size;
422 13 : break;
423 : }
424 361 : if (Ctx.Ptr != Ctx.End)
425 : return make_error<GenericBinaryError>(
426 : "Linking sub-section ended prematurely", object_error::parse_failed);
427 : }
428 273 : if (Ctx.Ptr != OrigEnd)
429 : return make_error<GenericBinaryError>("Linking section ended prematurely",
430 : object_error::parse_failed);
431 : return Error::success();
432 : }
433 :
434 263 : Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
435 263 : uint32_t Count = readVaruint32(Ctx);
436 263 : LinkingData.SymbolTable.reserve(Count);
437 263 : Symbols.reserve(Count);
438 : StringSet<> SymbolNames;
439 :
440 : std::vector<wasm::WasmImport *> ImportedGlobals;
441 : std::vector<wasm::WasmImport *> ImportedFunctions;
442 526 : ImportedGlobals.reserve(Imports.size());
443 526 : ImportedFunctions.reserve(Imports.size());
444 903 : for (auto &I : Imports) {
445 640 : if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
446 144 : ImportedFunctions.emplace_back(&I);
447 496 : else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
448 20 : ImportedGlobals.emplace_back(&I);
449 : }
450 :
451 1362 : while (Count--) {
452 : wasm::WasmSymbolInfo Info;
453 1100 : const wasm::WasmSignature *FunctionType = nullptr;
454 1100 : const wasm::WasmGlobalType *GlobalType = nullptr;
455 :
456 1100 : Info.Kind = readUint8(Ctx);
457 1100 : Info.Flags = readVaruint32(Ctx);
458 1100 : bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
459 :
460 1100 : switch (Info.Kind) {
461 863 : case wasm::WASM_SYMBOL_TYPE_FUNCTION:
462 863 : Info.ElementIndex = readVaruint32(Ctx);
463 1726 : if (!isValidFunctionIndex(Info.ElementIndex) ||
464 863 : IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
465 : return make_error<GenericBinaryError>("invalid function symbol index",
466 : object_error::parse_failed);
467 863 : if (IsDefined) {
468 719 : Info.Name = readString(Ctx);
469 719 : unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
470 1438 : FunctionType = &Signatures[FunctionTypes[FuncIndex]];
471 719 : wasm::WasmFunction &Function = Functions[FuncIndex];
472 719 : if (Function.SymbolName.empty())
473 712 : Function.SymbolName = Info.Name;
474 : } else {
475 144 : wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
476 144 : FunctionType = &Signatures[Import.SigIndex];
477 144 : Info.Name = Import.Field;
478 144 : Info.Module = Import.Module;
479 : }
480 : break;
481 :
482 27 : case wasm::WASM_SYMBOL_TYPE_GLOBAL:
483 27 : Info.ElementIndex = readVaruint32(Ctx);
484 54 : if (!isValidGlobalIndex(Info.ElementIndex) ||
485 27 : IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
486 : return make_error<GenericBinaryError>("invalid global symbol index",
487 : object_error::parse_failed);
488 27 : if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
489 : wasm::WASM_SYMBOL_BINDING_WEAK)
490 : return make_error<GenericBinaryError>("undefined weak global symbol",
491 : object_error::parse_failed);
492 26 : if (IsDefined) {
493 7 : Info.Name = readString(Ctx);
494 7 : unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
495 7 : wasm::WasmGlobal &Global = Globals[GlobalIndex];
496 7 : GlobalType = &Global.Type;
497 7 : if (Global.SymbolName.empty())
498 7 : Global.SymbolName = Info.Name;
499 : } else {
500 19 : wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
501 19 : Info.Name = Import.Field;
502 19 : GlobalType = &Import.Global;
503 : }
504 : break;
505 :
506 188 : case wasm::WASM_SYMBOL_TYPE_DATA:
507 188 : Info.Name = readString(Ctx);
508 188 : if (IsDefined) {
509 166 : uint32_t Index = readVaruint32(Ctx);
510 332 : if (Index >= DataSegments.size())
511 : return make_error<GenericBinaryError>("invalid data symbol index",
512 : object_error::parse_failed);
513 166 : uint32_t Offset = readVaruint32(Ctx);
514 166 : uint32_t Size = readVaruint32(Ctx);
515 332 : if (Offset + Size > DataSegments[Index].Data.Content.size())
516 : return make_error<GenericBinaryError>("invalid data symbol offset",
517 : object_error::parse_failed);
518 166 : Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
519 : }
520 : break;
521 :
522 22 : case wasm::WASM_SYMBOL_TYPE_SECTION: {
523 22 : if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
524 : wasm::WASM_SYMBOL_BINDING_LOCAL)
525 : return make_error<GenericBinaryError>(
526 : "Section symbols must have local binding",
527 : object_error::parse_failed);
528 22 : Info.ElementIndex = readVaruint32(Ctx);
529 : // Use somewhat unique section name as symbol name.
530 22 : StringRef SectionName = Sections[Info.ElementIndex].Name;
531 22 : Info.Name = SectionName;
532 : break;
533 : }
534 :
535 0 : default:
536 : return make_error<GenericBinaryError>("Invalid symbol type",
537 : object_error::parse_failed);
538 : }
539 :
540 1099 : if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
541 1099 : wasm::WASM_SYMBOL_BINDING_LOCAL &&
542 978 : !SymbolNames.insert(Info.Name).second)
543 0 : return make_error<GenericBinaryError>("Duplicate symbol name " +
544 0 : Twine(Info.Name),
545 : object_error::parse_failed);
546 1099 : LinkingData.SymbolTable.emplace_back(Info);
547 1099 : Symbols.emplace_back(LinkingData.SymbolTable.back(), FunctionType,
548 : GlobalType);
549 : LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
550 : }
551 :
552 : return Error::success();
553 : }
554 :
555 5 : Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
556 5 : uint32_t ComdatCount = readVaruint32(Ctx);
557 : StringSet<> ComdatSet;
558 11 : for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
559 6 : StringRef Name = readString(Ctx);
560 12 : if (Name.empty() || !ComdatSet.insert(Name).second)
561 0 : return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
562 0 : Twine(Name),
563 : object_error::parse_failed);
564 6 : LinkingData.Comdats.emplace_back(Name);
565 6 : uint32_t Flags = readVaruint32(Ctx);
566 6 : if (Flags != 0)
567 : return make_error<GenericBinaryError>("Unsupported COMDAT flags",
568 : object_error::parse_failed);
569 :
570 6 : uint32_t EntryCount = readVaruint32(Ctx);
571 17 : while (EntryCount--) {
572 11 : unsigned Kind = readVaruint32(Ctx);
573 11 : unsigned Index = readVaruint32(Ctx);
574 11 : switch (Kind) {
575 0 : default:
576 : return make_error<GenericBinaryError>("Invalid COMDAT entry type",
577 : object_error::parse_failed);
578 5 : case wasm::WASM_COMDAT_DATA:
579 10 : if (Index >= DataSegments.size())
580 : return make_error<GenericBinaryError>(
581 : "COMDAT data index out of range", object_error::parse_failed);
582 5 : if (DataSegments[Index].Data.Comdat != UINT32_MAX)
583 : return make_error<GenericBinaryError>("Data segment in two COMDATs",
584 : object_error::parse_failed);
585 5 : DataSegments[Index].Data.Comdat = ComdatIndex;
586 5 : break;
587 6 : case wasm::WASM_COMDAT_FUNCTION:
588 6 : if (!isDefinedFunctionIndex(Index))
589 : return make_error<GenericBinaryError>(
590 : "COMDAT function index out of range", object_error::parse_failed);
591 6 : if (getDefinedFunction(Index).Comdat != UINT32_MAX)
592 : return make_error<GenericBinaryError>("Function in two COMDATs",
593 : object_error::parse_failed);
594 6 : getDefinedFunction(Index).Comdat = ComdatIndex;
595 6 : break;
596 : }
597 : }
598 : }
599 : return Error::success();
600 : }
601 :
602 175 : Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
603 175 : uint32_t SectionIndex = readVaruint32(Ctx);
604 350 : if (SectionIndex >= Sections.size())
605 : return make_error<GenericBinaryError>("Invalid section index",
606 : object_error::parse_failed);
607 : WasmSection &Section = Sections[SectionIndex];
608 175 : uint32_t RelocCount = readVaruint32(Ctx);
609 175 : uint32_t EndOffset = Section.Content.size();
610 : uint32_t PreviousOffset = 0;
611 978 : while (RelocCount--) {
612 803 : wasm::WasmRelocation Reloc = {};
613 803 : Reloc.Type = readVaruint32(Ctx);
614 803 : Reloc.Offset = readVaruint32(Ctx);
615 803 : if (Reloc.Offset < PreviousOffset)
616 : return make_error<GenericBinaryError>("Relocations not in offset order",
617 : object_error::parse_failed);
618 : PreviousOffset = Reloc.Offset;
619 803 : Reloc.Index = readVaruint32(Ctx);
620 803 : switch (Reloc.Type) {
621 288 : case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
622 : case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
623 : case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
624 288 : if (!isValidFunctionSymbol(Reloc.Index))
625 : return make_error<GenericBinaryError>("Bad relocation function index",
626 : object_error::parse_failed);
627 : break;
628 17 : case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
629 34 : if (Reloc.Index >= Signatures.size())
630 : return make_error<GenericBinaryError>("Bad relocation type index",
631 : object_error::parse_failed);
632 : break;
633 40 : case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
634 40 : if (!isValidGlobalSymbol(Reloc.Index))
635 : return make_error<GenericBinaryError>("Bad relocation global index",
636 : object_error::parse_failed);
637 : break;
638 375 : case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
639 : case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
640 : case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
641 375 : if (!isValidDataSymbol(Reloc.Index))
642 : return make_error<GenericBinaryError>("Bad relocation data index",
643 : object_error::parse_failed);
644 375 : Reloc.Addend = readVarint32(Ctx);
645 375 : break;
646 25 : case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
647 25 : if (!isValidFunctionSymbol(Reloc.Index))
648 : return make_error<GenericBinaryError>("Bad relocation function index",
649 : object_error::parse_failed);
650 25 : Reloc.Addend = readVarint32(Ctx);
651 25 : break;
652 58 : case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
653 58 : if (!isValidSectionSymbol(Reloc.Index))
654 : return make_error<GenericBinaryError>("Bad relocation section index",
655 : object_error::parse_failed);
656 58 : Reloc.Addend = readVarint32(Ctx);
657 58 : break;
658 0 : default:
659 0 : return make_error<GenericBinaryError>("Bad relocation type: " +
660 0 : Twine(Reloc.Type),
661 : object_error::parse_failed);
662 : }
663 :
664 : // Relocations must fit inside the section, and must appear in order. They
665 : // also shouldn't overlap a function/element boundary, but we don't bother
666 : // to check that.
667 : uint64_t Size = 5;
668 803 : if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 ||
669 745 : Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32 ||
670 687 : Reloc.Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32 ||
671 : Reloc.Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32)
672 : Size = 4;
673 803 : if (Reloc.Offset + Size > EndOffset)
674 : return make_error<GenericBinaryError>("Bad relocation offset",
675 : object_error::parse_failed);
676 :
677 803 : Section.Relocations.push_back(Reloc);
678 : }
679 175 : if (Ctx.Ptr != Ctx.End)
680 : return make_error<GenericBinaryError>("Reloc section ended prematurely",
681 : object_error::parse_failed);
682 : return Error::success();
683 : }
684 :
685 585 : Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
686 : if (Sec.Name == "name") {
687 148 : if (Error Err = parseNameSection(Ctx))
688 : return Err;
689 : } else if (Sec.Name == "linking") {
690 550 : if (Error Err = parseLinkingSection(Ctx))
691 : return Err;
692 : } else if (Sec.Name.startswith("reloc.")) {
693 350 : if (Error Err = parseRelocSection(Sec.Name, Ctx))
694 : return Err;
695 : }
696 : return Error::success();
697 : }
698 :
699 318 : Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
700 318 : uint32_t Count = readVaruint32(Ctx);
701 318 : Signatures.reserve(Count);
702 823 : while (Count--) {
703 505 : wasm::WasmSignature Sig;
704 505 : uint8_t Form = readUint8(Ctx);
705 505 : if (Form != wasm::WASM_TYPE_FUNC) {
706 : return make_error<GenericBinaryError>("Invalid signature type",
707 : object_error::parse_failed);
708 : }
709 505 : uint32_t ParamCount = readVaruint32(Ctx);
710 505 : Sig.Params.reserve(ParamCount);
711 674 : while (ParamCount--) {
712 169 : uint32_t ParamType = readUint8(Ctx);
713 169 : Sig.Params.push_back(wasm::ValType(ParamType));
714 : }
715 505 : uint32_t ReturnCount = readVaruint32(Ctx);
716 505 : if (ReturnCount) {
717 247 : if (ReturnCount != 1) {
718 : return make_error<GenericBinaryError>(
719 : "Multiple return types not supported", object_error::parse_failed);
720 : }
721 247 : Sig.Returns.push_back(wasm::ValType(readUint8(Ctx)));
722 : }
723 : Signatures.push_back(std::move(Sig));
724 : }
725 318 : if (Ctx.Ptr != Ctx.End)
726 : return make_error<GenericBinaryError>("Type section ended prematurely",
727 : object_error::parse_failed);
728 : return Error::success();
729 : }
730 :
731 274 : Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
732 274 : uint32_t Count = readVaruint32(Ctx);
733 274 : Imports.reserve(Count);
734 958 : for (uint32_t i = 0; i < Count; i++) {
735 : wasm::WasmImport Im;
736 684 : Im.Module = readString(Ctx);
737 684 : Im.Field = readString(Ctx);
738 684 : Im.Kind = readUint8(Ctx);
739 684 : switch (Im.Kind) {
740 157 : case wasm::WASM_EXTERNAL_FUNCTION:
741 157 : NumImportedFunctions++;
742 157 : Im.SigIndex = readVaruint32(Ctx);
743 157 : break;
744 24 : case wasm::WASM_EXTERNAL_GLOBAL:
745 24 : NumImportedGlobals++;
746 24 : Im.Global.Type = readUint8(Ctx);
747 24 : Im.Global.Mutable = readVaruint1(Ctx);
748 24 : break;
749 252 : case wasm::WASM_EXTERNAL_MEMORY:
750 252 : Im.Memory = readLimits(Ctx);
751 252 : break;
752 251 : case wasm::WASM_EXTERNAL_TABLE:
753 251 : Im.Table = readTable(Ctx);
754 251 : if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC)
755 : return make_error<GenericBinaryError>("Invalid table element type",
756 : object_error::parse_failed);
757 : break;
758 0 : default:
759 : return make_error<GenericBinaryError>("Unexpected import kind",
760 : object_error::parse_failed);
761 : }
762 684 : Imports.push_back(Im);
763 : }
764 274 : if (Ctx.Ptr != Ctx.End)
765 : return make_error<GenericBinaryError>("Import section ended prematurely",
766 : object_error::parse_failed);
767 : return Error::success();
768 : }
769 :
770 311 : Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
771 311 : uint32_t Count = readVaruint32(Ctx);
772 311 : FunctionTypes.reserve(Count);
773 622 : uint32_t NumTypes = Signatures.size();
774 1271 : while (Count--) {
775 960 : uint32_t Type = readVaruint32(Ctx);
776 960 : if (Type >= NumTypes)
777 : return make_error<GenericBinaryError>("Invalid function type",
778 : object_error::parse_failed);
779 960 : FunctionTypes.push_back(Type);
780 : }
781 311 : if (Ctx.Ptr != Ctx.End)
782 : return make_error<GenericBinaryError>("Function section ended prematurely",
783 : object_error::parse_failed);
784 : return Error::success();
785 : }
786 :
787 77 : Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
788 77 : uint32_t Count = readVaruint32(Ctx);
789 77 : Tables.reserve(Count);
790 154 : while (Count--) {
791 154 : Tables.push_back(readTable(Ctx));
792 77 : if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) {
793 : return make_error<GenericBinaryError>("Invalid table element type",
794 : object_error::parse_failed);
795 : }
796 : }
797 77 : if (Ctx.Ptr != Ctx.End)
798 : return make_error<GenericBinaryError>("Table section ended prematurely",
799 : object_error::parse_failed);
800 : return Error::success();
801 : }
802 :
803 76 : Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
804 76 : uint32_t Count = readVaruint32(Ctx);
805 76 : Memories.reserve(Count);
806 153 : while (Count--) {
807 154 : Memories.push_back(readLimits(Ctx));
808 : }
809 76 : if (Ctx.Ptr != Ctx.End)
810 : return make_error<GenericBinaryError>("Memory section ended prematurely",
811 : object_error::parse_failed);
812 : return Error::success();
813 : }
814 :
815 70 : Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
816 70 : GlobalSection = Sections.size();
817 70 : uint32_t Count = readVaruint32(Ctx);
818 70 : Globals.reserve(Count);
819 280 : while (Count--) {
820 : wasm::WasmGlobal Global;
821 210 : Global.Index = NumImportedGlobals + Globals.size();
822 210 : Global.Type.Type = readUint8(Ctx);
823 210 : Global.Type.Mutable = readVaruint1(Ctx);
824 420 : if (Error Err = readInitExpr(Global.InitExpr, Ctx))
825 : return Err;
826 210 : Globals.push_back(Global);
827 : }
828 70 : if (Ctx.Ptr != Ctx.End)
829 : return make_error<GenericBinaryError>("Global section ended prematurely",
830 : object_error::parse_failed);
831 : return Error::success();
832 : }
833 :
834 66 : Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
835 66 : uint32_t Count = readVaruint32(Ctx);
836 66 : Exports.reserve(Count);
837 388 : for (uint32_t i = 0; i < Count; i++) {
838 : wasm::WasmExport Ex;
839 323 : Ex.Name = readString(Ctx);
840 323 : Ex.Kind = readUint8(Ctx);
841 323 : Ex.Index = readVaruint32(Ctx);
842 323 : switch (Ex.Kind) {
843 123 : case wasm::WASM_EXTERNAL_FUNCTION:
844 123 : if (!isValidFunctionIndex(Ex.Index))
845 : return make_error<GenericBinaryError>("Invalid function export",
846 : object_error::parse_failed);
847 : break;
848 136 : case wasm::WASM_EXTERNAL_GLOBAL:
849 136 : if (!isValidGlobalIndex(Ex.Index))
850 : return make_error<GenericBinaryError>("Invalid global export",
851 : object_error::parse_failed);
852 : break;
853 : case wasm::WASM_EXTERNAL_MEMORY:
854 : case wasm::WASM_EXTERNAL_TABLE:
855 : break;
856 0 : default:
857 : return make_error<GenericBinaryError>("Unexpected export kind",
858 : object_error::parse_failed);
859 : }
860 322 : Exports.push_back(Ex);
861 : }
862 65 : if (Ctx.Ptr != Ctx.End)
863 : return make_error<GenericBinaryError>("Export section ended prematurely",
864 : object_error::parse_failed);
865 : return Error::success();
866 : }
867 :
868 2567 : bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
869 5134 : return Index < NumImportedFunctions + FunctionTypes.size();
870 : }
871 :
872 1305 : bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
873 1305 : return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
874 : }
875 :
876 170 : bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
877 340 : return Index < NumImportedGlobals + Globals.size();
878 : }
879 :
880 27 : bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
881 27 : return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
882 : }
883 :
884 357 : bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
885 714 : return Index < Symbols.size() && Symbols[Index].isTypeFunction();
886 : }
887 :
888 40 : bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
889 80 : return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
890 : }
891 :
892 375 : bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
893 750 : return Index < Symbols.size() && Symbols[Index].isTypeData();
894 : }
895 :
896 58 : bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
897 116 : return Index < Symbols.size() && Symbols[Index].isTypeSection();
898 : }
899 :
900 430 : wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
901 : assert(isDefinedFunctionIndex(Index));
902 860 : return Functions[Index - NumImportedFunctions];
903 : }
904 :
905 0 : wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
906 : assert(isDefinedGlobalIndex(Index));
907 0 : return Globals[Index - NumImportedGlobals];
908 : }
909 :
910 2 : Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
911 2 : StartFunction = readVaruint32(Ctx);
912 2 : if (!isValidFunctionIndex(StartFunction))
913 : return make_error<GenericBinaryError>("Invalid start function",
914 : object_error::parse_failed);
915 : return Error::success();
916 : }
917 :
918 311 : Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
919 311 : CodeSection = Sections.size();
920 311 : uint32_t FunctionCount = readVaruint32(Ctx);
921 622 : if (FunctionCount != FunctionTypes.size()) {
922 : return make_error<GenericBinaryError>("Invalid function count",
923 : object_error::parse_failed);
924 : }
925 :
926 1271 : while (FunctionCount--) {
927 : wasm::WasmFunction Function;
928 960 : const uint8_t *FunctionStart = Ctx.Ptr;
929 960 : uint32_t Size = readVaruint32(Ctx);
930 960 : const uint8_t *FunctionEnd = Ctx.Ptr + Size;
931 :
932 960 : Function.CodeOffset = Ctx.Ptr - FunctionStart;
933 960 : Function.Index = NumImportedFunctions + Functions.size();
934 960 : Function.CodeSectionOffset = FunctionStart - Ctx.Start;
935 960 : Function.Size = FunctionEnd - FunctionStart;
936 :
937 960 : uint32_t NumLocalDecls = readVaruint32(Ctx);
938 960 : Function.Locals.reserve(NumLocalDecls);
939 984 : while (NumLocalDecls--) {
940 : wasm::WasmLocalDecl Decl;
941 24 : Decl.Count = readVaruint32(Ctx);
942 24 : Decl.Type = readUint8(Ctx);
943 24 : Function.Locals.push_back(Decl);
944 : }
945 :
946 960 : uint32_t BodySize = FunctionEnd - Ctx.Ptr;
947 960 : Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
948 : // This will be set later when reading in the linking metadata section.
949 960 : Function.Comdat = UINT32_MAX;
950 960 : Ctx.Ptr += BodySize;
951 : assert(Ctx.Ptr == FunctionEnd);
952 960 : Functions.push_back(Function);
953 : }
954 311 : if (Ctx.Ptr != Ctx.End)
955 : return make_error<GenericBinaryError>("Code section ended prematurely",
956 : object_error::parse_failed);
957 : return Error::success();
958 : }
959 :
960 51 : Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
961 51 : uint32_t Count = readVaruint32(Ctx);
962 51 : ElemSegments.reserve(Count);
963 102 : while (Count--) {
964 : wasm::WasmElemSegment Segment;
965 51 : Segment.TableIndex = readVaruint32(Ctx);
966 51 : if (Segment.TableIndex != 0) {
967 : return make_error<GenericBinaryError>("Invalid TableIndex",
968 : object_error::parse_failed);
969 : }
970 102 : if (Error Err = readInitExpr(Segment.Offset, Ctx))
971 : return Err;
972 51 : uint32_t NumElems = readVaruint32(Ctx);
973 154 : while (NumElems--) {
974 103 : Segment.Functions.push_back(readVaruint32(Ctx));
975 : }
976 51 : ElemSegments.push_back(Segment);
977 : }
978 51 : if (Ctx.Ptr != Ctx.End)
979 : return make_error<GenericBinaryError>("Elem section ended prematurely",
980 : object_error::parse_failed);
981 : return Error::success();
982 : }
983 :
984 91 : Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
985 91 : DataSection = Sections.size();
986 91 : uint32_t Count = readVaruint32(Ctx);
987 91 : DataSegments.reserve(Count);
988 279 : while (Count--) {
989 : WasmSegment Segment;
990 188 : Segment.Data.MemoryIndex = readVaruint32(Ctx);
991 376 : if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
992 : return Err;
993 188 : uint32_t Size = readVaruint32(Ctx);
994 188 : if (Size > (size_t)(Ctx.End - Ctx.Ptr))
995 : return make_error<GenericBinaryError>("Invalid segment size",
996 : object_error::parse_failed);
997 188 : Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
998 : // The rest of these Data fields are set later, when reading in the linking
999 : // metadata section.
1000 188 : Segment.Data.Alignment = 0;
1001 188 : Segment.Data.Flags = 0;
1002 188 : Segment.Data.Comdat = UINT32_MAX;
1003 188 : Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1004 188 : Ctx.Ptr += Size;
1005 188 : DataSegments.push_back(Segment);
1006 : }
1007 91 : if (Ctx.Ptr != Ctx.End)
1008 : return make_error<GenericBinaryError>("Data section ended prematurely",
1009 : object_error::parse_failed);
1010 : return Error::success();
1011 : }
1012 :
1013 360 : const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
1014 360 : return reinterpret_cast<const uint8_t *>(getData().data() + Offset);
1015 : }
1016 :
1017 106 : const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1018 106 : return Header;
1019 : }
1020 :
1021 718 : void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
1022 :
1023 196 : uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
1024 : uint32_t Result = SymbolRef::SF_None;
1025 196 : const WasmSymbol &Sym = getWasmSymbol(Symb);
1026 :
1027 : LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1028 196 : if (Sym.isBindingWeak())
1029 : Result |= SymbolRef::SF_Weak;
1030 196 : if (!Sym.isBindingLocal())
1031 186 : Result |= SymbolRef::SF_Global;
1032 196 : if (Sym.isHidden())
1033 23 : Result |= SymbolRef::SF_Hidden;
1034 196 : if (!Sym.isDefined())
1035 40 : Result |= SymbolRef::SF_Undefined;
1036 196 : if (Sym.isTypeFunction())
1037 139 : Result |= SymbolRef::SF_Executable;
1038 196 : return Result;
1039 : }
1040 :
1041 220 : basic_symbol_iterator WasmObjectFile::symbol_begin() const {
1042 : DataRefImpl Ref;
1043 : Ref.d.a = 0;
1044 660 : return BasicSymbolRef(Ref, this);
1045 : }
1046 :
1047 278 : basic_symbol_iterator WasmObjectFile::symbol_end() const {
1048 : DataRefImpl Ref;
1049 556 : Ref.d.a = Symbols.size();
1050 834 : return BasicSymbolRef(Ref, this);
1051 : }
1052 :
1053 1029 : const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
1054 2058 : return Symbols[Symb.d.a];
1055 : }
1056 :
1057 0 : const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1058 0 : return getWasmSymbol(Symb.getRawDataRefImpl());
1059 : }
1060 :
1061 101 : Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
1062 101 : return getWasmSymbol(Symb).Info.Name;
1063 : }
1064 :
1065 55 : Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
1066 55 : return getSymbolValue(Symb);
1067 : }
1068 :
1069 45 : uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
1070 45 : switch (Sym.Info.Kind) {
1071 30 : case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1072 : case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1073 30 : return Sym.Info.ElementIndex;
1074 12 : case wasm::WASM_SYMBOL_TYPE_DATA: {
1075 : // The value of a data symbol is the segment offset, plus the symbol
1076 : // offset within the segment.
1077 12 : uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1078 12 : const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1079 : assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST);
1080 12 : return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
1081 : }
1082 : case wasm::WASM_SYMBOL_TYPE_SECTION:
1083 : return 0;
1084 : }
1085 0 : llvm_unreachable("invalid symbol type");
1086 : }
1087 :
1088 45 : uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1089 45 : return getWasmSymbolValue(getWasmSymbol(Symb));
1090 : }
1091 :
1092 0 : uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1093 0 : llvm_unreachable("not yet implemented");
1094 : return 0;
1095 : }
1096 :
1097 0 : uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1098 0 : llvm_unreachable("not yet implemented");
1099 : return 0;
1100 : }
1101 :
1102 : Expected<SymbolRef::Type>
1103 15 : WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
1104 15 : const WasmSymbol &Sym = getWasmSymbol(Symb);
1105 :
1106 15 : switch (Sym.Info.Kind) {
1107 9 : case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1108 : return SymbolRef::ST_Function;
1109 0 : case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1110 : return SymbolRef::ST_Other;
1111 6 : case wasm::WASM_SYMBOL_TYPE_DATA:
1112 : return SymbolRef::ST_Data;
1113 0 : case wasm::WASM_SYMBOL_TYPE_SECTION:
1114 : return SymbolRef::ST_Debug;
1115 : }
1116 :
1117 0 : llvm_unreachable("Unknown WasmSymbol::SymbolType");
1118 : return SymbolRef::ST_Other;
1119 : }
1120 :
1121 : Expected<section_iterator>
1122 22 : WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1123 22 : const WasmSymbol &Sym = getWasmSymbol(Symb);
1124 44 : if (Sym.isUndefined())
1125 2 : return section_end();
1126 :
1127 : DataRefImpl Ref;
1128 20 : switch (Sym.Info.Kind) {
1129 9 : case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1130 9 : Ref.d.a = CodeSection;
1131 9 : break;
1132 0 : case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1133 0 : Ref.d.a = GlobalSection;
1134 0 : break;
1135 8 : case wasm::WASM_SYMBOL_TYPE_DATA:
1136 8 : Ref.d.a = DataSection;
1137 8 : break;
1138 3 : case wasm::WASM_SYMBOL_TYPE_SECTION: {
1139 3 : Ref.d.a = Sym.Info.ElementIndex;
1140 3 : break;
1141 : }
1142 0 : default:
1143 0 : llvm_unreachable("Unknown WasmSymbol::SymbolType");
1144 : }
1145 80 : return section_iterator(SectionRef(Ref, this));
1146 : }
1147 :
1148 2014 : void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1149 :
1150 232 : std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
1151 : StringRef &Res) const {
1152 232 : const WasmSection &S = Sections[Sec.d.a];
1153 : #define ECase(X) \
1154 : case wasm::WASM_SEC_##X: \
1155 : Res = #X; \
1156 : break
1157 232 : switch (S.Type) {
1158 16 : ECase(TYPE);
1159 10 : ECase(IMPORT);
1160 15 : ECase(FUNCTION);
1161 6 : ECase(TABLE);
1162 6 : ECase(MEMORY);
1163 6 : ECase(GLOBAL);
1164 6 : ECase(EXPORT);
1165 0 : ECase(START);
1166 5 : ECase(ELEM);
1167 25 : ECase(CODE);
1168 19 : ECase(DATA);
1169 118 : case wasm::WASM_SEC_CUSTOM:
1170 118 : Res = S.Name;
1171 118 : break;
1172 : default:
1173 0 : return object_error::invalid_section_index;
1174 : }
1175 : #undef ECase
1176 232 : return std::error_code();
1177 : }
1178 :
1179 8 : uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1180 :
1181 14 : uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1182 14 : return Sec.d.a;
1183 : }
1184 :
1185 8 : uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1186 8 : const WasmSection &S = Sections[Sec.d.a];
1187 8 : return S.Content.size();
1188 : }
1189 :
1190 54 : std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
1191 : StringRef &Res) const {
1192 54 : const WasmSection &S = Sections[Sec.d.a];
1193 : // This will never fail since wasm sections can never be empty (user-sections
1194 : // must have a name and non-user sections each have a defined structure).
1195 54 : Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
1196 : S.Content.size());
1197 54 : return std::error_code();
1198 : }
1199 :
1200 0 : uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1201 0 : return 1;
1202 : }
1203 :
1204 52 : bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1205 52 : return false;
1206 : }
1207 :
1208 7 : bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
1209 7 : return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1210 : }
1211 :
1212 7 : bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
1213 7 : return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1214 : }
1215 :
1216 60 : bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1217 :
1218 52 : bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1219 :
1220 0 : bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
1221 :
1222 72 : relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1223 : DataRefImpl RelocRef;
1224 72 : RelocRef.d.a = Ref.d.a;
1225 : RelocRef.d.b = 0;
1226 216 : return relocation_iterator(RelocationRef(RelocRef, this));
1227 : }
1228 :
1229 72 : relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1230 72 : const WasmSection &Sec = getWasmSection(Ref);
1231 : DataRefImpl RelocRef;
1232 72 : RelocRef.d.a = Ref.d.a;
1233 144 : RelocRef.d.b = Sec.Relocations.size();
1234 216 : return relocation_iterator(RelocationRef(RelocRef, this));
1235 : }
1236 :
1237 55 : void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
1238 :
1239 55 : uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1240 55 : const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1241 55 : return Rel.Offset;
1242 : }
1243 :
1244 55 : symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
1245 55 : const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1246 55 : if (Rel.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
1247 3 : return symbol_end();
1248 : DataRefImpl Sym;
1249 52 : Sym.d.a = Rel.Index;
1250 : Sym.d.b = 0;
1251 156 : return symbol_iterator(SymbolRef(Sym, this));
1252 : }
1253 :
1254 50 : uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1255 50 : const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1256 50 : return Rel.Type;
1257 : }
1258 :
1259 41 : void WasmObjectFile::getRelocationTypeName(
1260 : DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1261 41 : const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1262 : StringRef Res = "Unknown";
1263 :
1264 : #define WASM_RELOC(name, value) \
1265 : case wasm::name: \
1266 : Res = #name; \
1267 : break;
1268 :
1269 41 : switch (Rel.Type) {
1270 : #include "llvm/BinaryFormat/WasmRelocs.def"
1271 : }
1272 :
1273 : #undef WASM_RELOC
1274 :
1275 41 : Result.append(Res.begin(), Res.end());
1276 41 : }
1277 :
1278 311 : section_iterator WasmObjectFile::section_begin() const {
1279 : DataRefImpl Ref;
1280 : Ref.d.a = 0;
1281 933 : return section_iterator(SectionRef(Ref, this));
1282 : }
1283 :
1284 409 : section_iterator WasmObjectFile::section_end() const {
1285 : DataRefImpl Ref;
1286 818 : Ref.d.a = Sections.size();
1287 1227 : return section_iterator(SectionRef(Ref, this));
1288 : }
1289 :
1290 35 : uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1291 :
1292 26 : StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1293 :
1294 32 : Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
1295 :
1296 0 : SubtargetFeatures WasmObjectFile::getFeatures() const {
1297 0 : return SubtargetFeatures();
1298 : }
1299 :
1300 192 : bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1301 :
1302 1975 : const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
1303 : assert(Ref.d.a < Sections.size());
1304 3950 : return Sections[Ref.d.a];
1305 : }
1306 :
1307 : const WasmSection &
1308 1889 : WasmObjectFile::getWasmSection(const SectionRef &Section) const {
1309 1889 : return getWasmSection(Section.getRawDataRefImpl());
1310 : }
1311 :
1312 : const wasm::WasmRelocation &
1313 41 : WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1314 41 : return getWasmRelocation(Ref.getRawDataRefImpl());
1315 : }
1316 :
1317 : const wasm::WasmRelocation &
1318 242 : WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
1319 : assert(Ref.d.a < Sections.size());
1320 242 : const WasmSection &Sec = Sections[Ref.d.a];
1321 : assert(Ref.d.b < Sec.Relocations.size());
1322 484 : return Sec.Relocations[Ref.d.b];
1323 : }
|