Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/llvm/lib/Object/WasmObjectFile.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "llvm/ADT/ArrayRef.h"
10
#include "llvm/ADT/DenseSet.h"
11
#include "llvm/ADT/SmallSet.h"
12
#include "llvm/ADT/StringRef.h"
13
#include "llvm/ADT/StringSet.h"
14
#include "llvm/ADT/StringSwitch.h"
15
#include "llvm/BinaryFormat/Wasm.h"
16
#include "llvm/Object/Binary.h"
17
#include "llvm/Object/Error.h"
18
#include "llvm/Object/ObjectFile.h"
19
#include "llvm/Object/SymbolicFile.h"
20
#include "llvm/Object/Wasm.h"
21
#include "llvm/Support/Endian.h"
22
#include "llvm/Support/Error.h"
23
#include "llvm/Support/ErrorHandling.h"
24
#include "llvm/Support/LEB128.h"
25
#include "llvm/Support/ScopedPrinter.h"
26
#include "llvm/TargetParser/SubtargetFeature.h"
27
#include "llvm/TargetParser/Triple.h"
28
#include <algorithm>
29
#include <cassert>
30
#include <cstdint>
31
#include <cstring>
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)) << ", Flags=0x"
41
0
      << Twine::utohexstr(Info.Flags) << " [";
42
0
  switch (getBinding()) {
43
0
    case wasm::WASM_SYMBOL_BINDING_GLOBAL: Out << "global"; break;
44
0
    case wasm::WASM_SYMBOL_BINDING_LOCAL: Out << "local"; break;
45
0
    case wasm::WASM_SYMBOL_BINDING_WEAK: Out << "weak"; break;
46
0
  }
47
0
  if (isHidden()) {
48
0
    Out << ", hidden";
49
0
  } else {
50
0
    Out << ", default";
51
0
  }
52
0
  Out << "]";
53
0
  if (!isTypeData()) {
54
0
    Out << ", ElemIndex=" << Info.ElementIndex;
55
0
  } else if (isDefined()) {
56
0
    Out << ", Segment=" << Info.DataRef.Segment;
57
0
    Out << ", Offset=" << Info.DataRef.Offset;
58
0
    Out << ", Size=" << Info.DataRef.Size;
59
0
  }
60
0
}
61
62
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
63
0
LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
64
#endif
65
66
Expected<std::unique_ptr<WasmObjectFile>>
67
0
ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
68
0
  Error Err = Error::success();
69
0
  auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
70
0
  if (Err)
71
0
    return std::move(Err);
72
73
0
  return std::move(ObjectFile);
74
0
}
75
76
#define VARINT7_MAX ((1 << 7) - 1)
77
#define VARINT7_MIN (-(1 << 7))
78
#define VARUINT7_MAX (1 << 7)
79
0
#define VARUINT1_MAX (1)
80
81
0
static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
82
0
  if (Ctx.Ptr == Ctx.End)
83
0
    report_fatal_error("EOF while reading uint8");
84
0
  return *Ctx.Ptr++;
85
0
}
86
87
0
static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
88
0
  if (Ctx.Ptr + 4 > Ctx.End)
89
0
    report_fatal_error("EOF while reading uint32");
90
0
  uint32_t Result = support::endian::read32le(Ctx.Ptr);
91
0
  Ctx.Ptr += 4;
92
0
  return Result;
93
0
}
94
95
0
static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
96
0
  if (Ctx.Ptr + 4 > Ctx.End)
97
0
    report_fatal_error("EOF while reading float64");
98
0
  int32_t Result = 0;
99
0
  memcpy(&Result, Ctx.Ptr, sizeof(Result));
100
0
  Ctx.Ptr += sizeof(Result);
101
0
  return Result;
102
0
}
103
104
0
static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
105
0
  if (Ctx.Ptr + 8 > Ctx.End)
106
0
    report_fatal_error("EOF while reading float64");
107
0
  int64_t Result = 0;
108
0
  memcpy(&Result, Ctx.Ptr, sizeof(Result));
109
0
  Ctx.Ptr += sizeof(Result);
110
0
  return Result;
111
0
}
112
113
0
static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
114
0
  unsigned Count;
115
0
  const char *Error = nullptr;
116
0
  uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
117
0
  if (Error)
118
0
    report_fatal_error(Error);
119
0
  Ctx.Ptr += Count;
120
0
  return Result;
121
0
}
122
123
0
static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
124
0
  uint32_t StringLen = readULEB128(Ctx);
125
0
  if (Ctx.Ptr + StringLen > Ctx.End)
126
0
    report_fatal_error("EOF while reading string");
127
0
  StringRef Return =
128
0
      StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
129
0
  Ctx.Ptr += StringLen;
130
0
  return Return;
131
0
}
132
133
0
static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
134
0
  unsigned Count;
135
0
  const char *Error = nullptr;
136
0
  uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
137
0
  if (Error)
138
0
    report_fatal_error(Error);
139
0
  Ctx.Ptr += Count;
140
0
  return Result;
141
0
}
142
143
0
static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
144
0
  int64_t Result = readLEB128(Ctx);
145
0
  if (Result > VARUINT1_MAX || Result < 0)
146
0
    report_fatal_error("LEB is outside Varuint1 range");
147
0
  return Result;
148
0
}
149
150
0
static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
151
0
  int64_t Result = readLEB128(Ctx);
152
0
  if (Result > INT32_MAX || Result < INT32_MIN)
153
0
    report_fatal_error("LEB is outside Varint32 range");
154
0
  return Result;
155
0
}
156
157
0
static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
158
0
  uint64_t Result = readULEB128(Ctx);
159
0
  if (Result > UINT32_MAX)
160
0
    report_fatal_error("LEB is outside Varuint32 range");
161
0
  return Result;
162
0
}
163
164
0
static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
165
0
  return readLEB128(Ctx);
166
0
}
167
168
0
static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) {
169
0
  return readULEB128(Ctx);
170
0
}
171
172
0
static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
173
0
  return readUint8(Ctx);
174
0
}
175
176
static Error readInitExpr(wasm::WasmInitExpr &Expr,
177
0
                          WasmObjectFile::ReadContext &Ctx) {
178
0
  auto Start = Ctx.Ptr;
179
180
0
  Expr.Extended = false;
181
0
  Expr.Inst.Opcode = readOpcode(Ctx);
182
0
  switch (Expr.Inst.Opcode) {
183
0
  case wasm::WASM_OPCODE_I32_CONST:
184
0
    Expr.Inst.Value.Int32 = readVarint32(Ctx);
185
0
    break;
186
0
  case wasm::WASM_OPCODE_I64_CONST:
187
0
    Expr.Inst.Value.Int64 = readVarint64(Ctx);
188
0
    break;
189
0
  case wasm::WASM_OPCODE_F32_CONST:
190
0
    Expr.Inst.Value.Float32 = readFloat32(Ctx);
191
0
    break;
192
0
  case wasm::WASM_OPCODE_F64_CONST:
193
0
    Expr.Inst.Value.Float64 = readFloat64(Ctx);
194
0
    break;
195
0
  case wasm::WASM_OPCODE_GLOBAL_GET:
196
0
    Expr.Inst.Value.Global = readULEB128(Ctx);
197
0
    break;
198
0
  case wasm::WASM_OPCODE_REF_NULL: {
199
0
    wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx));
200
0
    if (Ty != wasm::ValType::EXTERNREF) {
201
0
      return make_error<GenericBinaryError>("invalid type for ref.null",
202
0
                                            object_error::parse_failed);
203
0
    }
204
0
    break;
205
0
  }
206
0
  default:
207
0
    Expr.Extended = true;
208
0
  }
209
210
0
  if (!Expr.Extended) {
211
0
    uint8_t EndOpcode = readOpcode(Ctx);
212
0
    if (EndOpcode != wasm::WASM_OPCODE_END)
213
0
      Expr.Extended = true;
214
0
  }
215
216
0
  if (Expr.Extended) {
217
0
    Ctx.Ptr = Start;
218
0
    while (true) {
219
0
      uint8_t Opcode = readOpcode(Ctx);
220
0
      switch (Opcode) {
221
0
      case wasm::WASM_OPCODE_I32_CONST:
222
0
      case wasm::WASM_OPCODE_GLOBAL_GET:
223
0
      case wasm::WASM_OPCODE_REF_NULL:
224
0
      case wasm::WASM_OPCODE_I64_CONST:
225
0
      case wasm::WASM_OPCODE_F32_CONST:
226
0
      case wasm::WASM_OPCODE_F64_CONST:
227
0
        readULEB128(Ctx);
228
0
        break;
229
0
      case wasm::WASM_OPCODE_I32_ADD:
230
0
      case wasm::WASM_OPCODE_I32_SUB:
231
0
      case wasm::WASM_OPCODE_I32_MUL:
232
0
      case wasm::WASM_OPCODE_I64_ADD:
233
0
      case wasm::WASM_OPCODE_I64_SUB:
234
0
      case wasm::WASM_OPCODE_I64_MUL:
235
0
        break;
236
0
      case wasm::WASM_OPCODE_END:
237
0
        Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start);
238
0
        return Error::success();
239
0
      default:
240
0
        return make_error<GenericBinaryError>(
241
0
            Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode)),
242
0
            object_error::parse_failed);
243
0
      }
244
0
    }
245
0
  }
246
247
0
  return Error::success();
248
0
}
249
250
0
static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
251
0
  wasm::WasmLimits Result;
252
0
  Result.Flags = readVaruint32(Ctx);
253
0
  Result.Minimum = readVaruint64(Ctx);
254
0
  if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
255
0
    Result.Maximum = readVaruint64(Ctx);
256
0
  return Result;
257
0
}
258
259
0
static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) {
260
0
  wasm::WasmTableType TableType;
261
0
  TableType.ElemType = readUint8(Ctx);
262
0
  TableType.Limits = readLimits(Ctx);
263
0
  return TableType;
264
0
}
265
266
static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
267
0
                         WasmSectionOrderChecker &Checker) {
268
0
  Section.Type = readUint8(Ctx);
269
0
  LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
270
  // When reading the section's size, store the size of the LEB used to encode
271
  // it. This allows objcopy/strip to reproduce the binary identically.
272
0
  const uint8_t *PreSizePtr = Ctx.Ptr;
273
0
  uint32_t Size = readVaruint32(Ctx);
274
0
  Section.HeaderSecSizeEncodingLen = Ctx.Ptr - PreSizePtr;
275
0
  Section.Offset = Ctx.Ptr - Ctx.Start;
276
0
  if (Size == 0)
277
0
    return make_error<StringError>("zero length section",
278
0
                                   object_error::parse_failed);
279
0
  if (Ctx.Ptr + Size > Ctx.End)
280
0
    return make_error<StringError>("section too large",
281
0
                                   object_error::parse_failed);
282
0
  if (Section.Type == wasm::WASM_SEC_CUSTOM) {
283
0
    WasmObjectFile::ReadContext SectionCtx;
284
0
    SectionCtx.Start = Ctx.Ptr;
285
0
    SectionCtx.Ptr = Ctx.Ptr;
286
0
    SectionCtx.End = Ctx.Ptr + Size;
287
288
0
    Section.Name = readString(SectionCtx);
289
290
0
    uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
291
0
    Ctx.Ptr += SectionNameSize;
292
0
    Size -= SectionNameSize;
293
0
  }
294
295
0
  if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
296
0
    return make_error<StringError>("out of order section type: " +
297
0
                                       llvm::to_string(Section.Type),
298
0
                                   object_error::parse_failed);
299
0
  }
300
301
0
  Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
302
0
  Ctx.Ptr += Size;
303
0
  return Error::success();
304
0
}
305
306
WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
307
0
    : ObjectFile(Binary::ID_Wasm, Buffer) {
308
0
  ErrorAsOutParameter ErrAsOutParam(&Err);
309
0
  Header.Magic = getData().substr(0, 4);
310
0
  if (Header.Magic != StringRef("\0asm", 4)) {
311
0
    Err = make_error<StringError>("invalid magic number",
312
0
                                  object_error::parse_failed);
313
0
    return;
314
0
  }
315
316
0
  ReadContext Ctx;
317
0
  Ctx.Start = getData().bytes_begin();
318
0
  Ctx.Ptr = Ctx.Start + 4;
319
0
  Ctx.End = Ctx.Start + getData().size();
320
321
0
  if (Ctx.Ptr + 4 > Ctx.End) {
322
0
    Err = make_error<StringError>("missing version number",
323
0
                                  object_error::parse_failed);
324
0
    return;
325
0
  }
326
327
0
  Header.Version = readUint32(Ctx);
328
0
  if (Header.Version != wasm::WasmVersion) {
329
0
    Err = make_error<StringError>("invalid version number: " +
330
0
                                      Twine(Header.Version),
331
0
                                  object_error::parse_failed);
332
0
    return;
333
0
  }
334
335
0
  WasmSectionOrderChecker Checker;
336
0
  while (Ctx.Ptr < Ctx.End) {
337
0
    WasmSection Sec;
338
0
    if ((Err = readSection(Sec, Ctx, Checker)))
339
0
      return;
340
0
    if ((Err = parseSection(Sec)))
341
0
      return;
342
343
0
    Sections.push_back(Sec);
344
0
  }
345
0
}
346
347
0
Error WasmObjectFile::parseSection(WasmSection &Sec) {
348
0
  ReadContext Ctx;
349
0
  Ctx.Start = Sec.Content.data();
350
0
  Ctx.End = Ctx.Start + Sec.Content.size();
351
0
  Ctx.Ptr = Ctx.Start;
352
0
  switch (Sec.Type) {
353
0
  case wasm::WASM_SEC_CUSTOM:
354
0
    return parseCustomSection(Sec, Ctx);
355
0
  case wasm::WASM_SEC_TYPE:
356
0
    return parseTypeSection(Ctx);
357
0
  case wasm::WASM_SEC_IMPORT:
358
0
    return parseImportSection(Ctx);
359
0
  case wasm::WASM_SEC_FUNCTION:
360
0
    return parseFunctionSection(Ctx);
361
0
  case wasm::WASM_SEC_TABLE:
362
0
    return parseTableSection(Ctx);
363
0
  case wasm::WASM_SEC_MEMORY:
364
0
    return parseMemorySection(Ctx);
365
0
  case wasm::WASM_SEC_TAG:
366
0
    return parseTagSection(Ctx);
367
0
  case wasm::WASM_SEC_GLOBAL:
368
0
    return parseGlobalSection(Ctx);
369
0
  case wasm::WASM_SEC_EXPORT:
370
0
    return parseExportSection(Ctx);
371
0
  case wasm::WASM_SEC_START:
372
0
    return parseStartSection(Ctx);
373
0
  case wasm::WASM_SEC_ELEM:
374
0
    return parseElemSection(Ctx);
375
0
  case wasm::WASM_SEC_CODE:
376
0
    return parseCodeSection(Ctx);
377
0
  case wasm::WASM_SEC_DATA:
378
0
    return parseDataSection(Ctx);
379
0
  case wasm::WASM_SEC_DATACOUNT:
380
0
    return parseDataCountSection(Ctx);
381
0
  default:
382
0
    return make_error<GenericBinaryError>(
383
0
        "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
384
0
  }
385
0
}
386
387
0
Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
388
  // Legacy "dylink" section support.
389
  // See parseDylink0Section for the current "dylink.0" section parsing.
390
0
  HasDylinkSection = true;
391
0
  DylinkInfo.MemorySize = readVaruint32(Ctx);
392
0
  DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
393
0
  DylinkInfo.TableSize = readVaruint32(Ctx);
394
0
  DylinkInfo.TableAlignment = readVaruint32(Ctx);
395
0
  uint32_t Count = readVaruint32(Ctx);
396
0
  while (Count--) {
397
0
    DylinkInfo.Needed.push_back(readString(Ctx));
398
0
  }
399
400
0
  if (Ctx.Ptr != Ctx.End)
401
0
    return make_error<GenericBinaryError>("dylink section ended prematurely",
402
0
                                          object_error::parse_failed);
403
0
  return Error::success();
404
0
}
405
406
0
Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
407
  // See
408
  // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
409
0
  HasDylinkSection = true;
410
411
0
  const uint8_t *OrigEnd = Ctx.End;
412
0
  while (Ctx.Ptr < OrigEnd) {
413
0
    Ctx.End = OrigEnd;
414
0
    uint8_t Type = readUint8(Ctx);
415
0
    uint32_t Size = readVaruint32(Ctx);
416
0
    LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
417
0
                      << "\n");
418
0
    Ctx.End = Ctx.Ptr + Size;
419
0
    uint32_t Count;
420
0
    switch (Type) {
421
0
    case wasm::WASM_DYLINK_MEM_INFO:
422
0
      DylinkInfo.MemorySize = readVaruint32(Ctx);
423
0
      DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
424
0
      DylinkInfo.TableSize = readVaruint32(Ctx);
425
0
      DylinkInfo.TableAlignment = readVaruint32(Ctx);
426
0
      break;
427
0
    case wasm::WASM_DYLINK_NEEDED:
428
0
      Count = readVaruint32(Ctx);
429
0
      while (Count--) {
430
0
        DylinkInfo.Needed.push_back(readString(Ctx));
431
0
      }
432
0
      break;
433
0
    case wasm::WASM_DYLINK_EXPORT_INFO: {
434
0
      uint32_t Count = readVaruint32(Ctx);
435
0
      while (Count--) {
436
0
        DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)});
437
0
      }
438
0
      break;
439
0
    }
440
0
    case wasm::WASM_DYLINK_IMPORT_INFO: {
441
0
      uint32_t Count = readVaruint32(Ctx);
442
0
      while (Count--) {
443
0
        DylinkInfo.ImportInfo.push_back(
444
0
            {readString(Ctx), readString(Ctx), readVaruint32(Ctx)});
445
0
      }
446
0
      break;
447
0
    }
448
0
    default:
449
0
      LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n");
450
0
      Ctx.Ptr += Size;
451
0
      break;
452
0
    }
453
0
    if (Ctx.Ptr != Ctx.End) {
454
0
      return make_error<GenericBinaryError>(
455
0
          "dylink.0 sub-section ended prematurely", object_error::parse_failed);
456
0
    }
457
0
  }
458
459
0
  if (Ctx.Ptr != Ctx.End)
460
0
    return make_error<GenericBinaryError>("dylink.0 section ended prematurely",
461
0
                                          object_error::parse_failed);
462
0
  return Error::success();
463
0
}
464
465
0
Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
466
0
  llvm::DenseSet<uint64_t> SeenFunctions;
467
0
  llvm::DenseSet<uint64_t> SeenGlobals;
468
0
  llvm::DenseSet<uint64_t> SeenSegments;
469
470
0
  while (Ctx.Ptr < Ctx.End) {
471
0
    uint8_t Type = readUint8(Ctx);
472
0
    uint32_t Size = readVaruint32(Ctx);
473
0
    const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
474
0
    switch (Type) {
475
0
    case wasm::WASM_NAMES_FUNCTION:
476
0
    case wasm::WASM_NAMES_GLOBAL:
477
0
    case wasm::WASM_NAMES_DATA_SEGMENT: {
478
0
      uint32_t Count = readVaruint32(Ctx);
479
0
      while (Count--) {
480
0
        uint32_t Index = readVaruint32(Ctx);
481
0
        StringRef Name = readString(Ctx);
482
0
        wasm::NameType nameType = wasm::NameType::FUNCTION;
483
0
        if (Type == wasm::WASM_NAMES_FUNCTION) {
484
0
          if (!SeenFunctions.insert(Index).second)
485
0
            return make_error<GenericBinaryError>(
486
0
                "function named more than once", object_error::parse_failed);
487
0
          if (!isValidFunctionIndex(Index) || Name.empty())
488
0
            return make_error<GenericBinaryError>("invalid function name entry",
489
0
                                                  object_error::parse_failed);
490
491
0
          if (isDefinedFunctionIndex(Index))
492
0
            getDefinedFunction(Index).DebugName = Name;
493
0
        } else if (Type == wasm::WASM_NAMES_GLOBAL) {
494
0
          nameType = wasm::NameType::GLOBAL;
495
0
          if (!SeenGlobals.insert(Index).second)
496
0
            return make_error<GenericBinaryError>("global named more than once",
497
0
                                                  object_error::parse_failed);
498
0
          if (!isValidGlobalIndex(Index) || Name.empty())
499
0
            return make_error<GenericBinaryError>("invalid global name entry",
500
0
                                                  object_error::parse_failed);
501
0
        } else {
502
0
          nameType = wasm::NameType::DATA_SEGMENT;
503
0
          if (!SeenSegments.insert(Index).second)
504
0
            return make_error<GenericBinaryError>(
505
0
                "segment named more than once", object_error::parse_failed);
506
0
          if (Index > DataSegments.size())
507
0
            return make_error<GenericBinaryError>("invalid data segment name entry",
508
0
                                                  object_error::parse_failed);
509
0
        }
510
0
        DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
511
0
      }
512
0
      break;
513
0
    }
514
    // Ignore local names for now
515
0
    case wasm::WASM_NAMES_LOCAL:
516
0
    default:
517
0
      Ctx.Ptr += Size;
518
0
      break;
519
0
    }
520
0
    if (Ctx.Ptr != SubSectionEnd)
521
0
      return make_error<GenericBinaryError>(
522
0
          "name sub-section ended prematurely", object_error::parse_failed);
523
0
  }
524
525
0
  if (Ctx.Ptr != Ctx.End)
526
0
    return make_error<GenericBinaryError>("name section ended prematurely",
527
0
                                          object_error::parse_failed);
528
0
  return Error::success();
529
0
}
530
531
0
Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
532
0
  HasLinkingSection = true;
533
534
0
  LinkingData.Version = readVaruint32(Ctx);
535
0
  if (LinkingData.Version != wasm::WasmMetadataVersion) {
536
0
    return make_error<GenericBinaryError>(
537
0
        "unexpected metadata version: " + Twine(LinkingData.Version) +
538
0
            " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
539
0
        object_error::parse_failed);
540
0
  }
541
542
0
  const uint8_t *OrigEnd = Ctx.End;
543
0
  while (Ctx.Ptr < OrigEnd) {
544
0
    Ctx.End = OrigEnd;
545
0
    uint8_t Type = readUint8(Ctx);
546
0
    uint32_t Size = readVaruint32(Ctx);
547
0
    LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
548
0
                      << "\n");
549
0
    Ctx.End = Ctx.Ptr + Size;
550
0
    switch (Type) {
551
0
    case wasm::WASM_SYMBOL_TABLE:
552
0
      if (Error Err = parseLinkingSectionSymtab(Ctx))
553
0
        return Err;
554
0
      break;
555
0
    case wasm::WASM_SEGMENT_INFO: {
556
0
      uint32_t Count = readVaruint32(Ctx);
557
0
      if (Count > DataSegments.size())
558
0
        return make_error<GenericBinaryError>("too many segment names",
559
0
                                              object_error::parse_failed);
560
0
      for (uint32_t I = 0; I < Count; I++) {
561
0
        DataSegments[I].Data.Name = readString(Ctx);
562
0
        DataSegments[I].Data.Alignment = readVaruint32(Ctx);
563
0
        DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);
564
0
      }
565
0
      break;
566
0
    }
567
0
    case wasm::WASM_INIT_FUNCS: {
568
0
      uint32_t Count = readVaruint32(Ctx);
569
0
      LinkingData.InitFunctions.reserve(Count);
570
0
      for (uint32_t I = 0; I < Count; I++) {
571
0
        wasm::WasmInitFunc Init;
572
0
        Init.Priority = readVaruint32(Ctx);
573
0
        Init.Symbol = readVaruint32(Ctx);
574
0
        if (!isValidFunctionSymbol(Init.Symbol))
575
0
          return make_error<GenericBinaryError>("invalid function symbol: " +
576
0
                                                    Twine(Init.Symbol),
577
0
                                                object_error::parse_failed);
578
0
        LinkingData.InitFunctions.emplace_back(Init);
579
0
      }
580
0
      break;
581
0
    }
582
0
    case wasm::WASM_COMDAT_INFO:
583
0
      if (Error Err = parseLinkingSectionComdat(Ctx))
584
0
        return Err;
585
0
      break;
586
0
    default:
587
0
      Ctx.Ptr += Size;
588
0
      break;
589
0
    }
590
0
    if (Ctx.Ptr != Ctx.End)
591
0
      return make_error<GenericBinaryError>(
592
0
          "linking sub-section ended prematurely", object_error::parse_failed);
593
0
  }
594
0
  if (Ctx.Ptr != OrigEnd)
595
0
    return make_error<GenericBinaryError>("linking section ended prematurely",
596
0
                                          object_error::parse_failed);
597
0
  return Error::success();
598
0
}
599
600
0
Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
601
0
  uint32_t Count = readVaruint32(Ctx);
602
  // Clear out any symbol information that was derived from the exports
603
  // section.
604
0
  LinkingData.SymbolTable.clear();
605
0
  Symbols.clear();
606
0
  LinkingData.SymbolTable.reserve(Count);
607
0
  Symbols.reserve(Count);
608
0
  StringSet<> SymbolNames;
609
610
0
  std::vector<wasm::WasmImport *> ImportedGlobals;
611
0
  std::vector<wasm::WasmImport *> ImportedFunctions;
612
0
  std::vector<wasm::WasmImport *> ImportedTags;
613
0
  std::vector<wasm::WasmImport *> ImportedTables;
614
0
  ImportedGlobals.reserve(Imports.size());
615
0
  ImportedFunctions.reserve(Imports.size());
616
0
  ImportedTags.reserve(Imports.size());
617
0
  ImportedTables.reserve(Imports.size());
618
0
  for (auto &I : Imports) {
619
0
    if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
620
0
      ImportedFunctions.emplace_back(&I);
621
0
    else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
622
0
      ImportedGlobals.emplace_back(&I);
623
0
    else if (I.Kind == wasm::WASM_EXTERNAL_TAG)
624
0
      ImportedTags.emplace_back(&I);
625
0
    else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
626
0
      ImportedTables.emplace_back(&I);
627
0
  }
628
629
0
  while (Count--) {
630
0
    wasm::WasmSymbolInfo Info;
631
0
    const wasm::WasmSignature *Signature = nullptr;
632
0
    const wasm::WasmGlobalType *GlobalType = nullptr;
633
0
    const wasm::WasmTableType *TableType = nullptr;
634
635
0
    Info.Kind = readUint8(Ctx);
636
0
    Info.Flags = readVaruint32(Ctx);
637
0
    bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
638
639
0
    switch (Info.Kind) {
640
0
    case wasm::WASM_SYMBOL_TYPE_FUNCTION:
641
0
      Info.ElementIndex = readVaruint32(Ctx);
642
0
      if (!isValidFunctionIndex(Info.ElementIndex) ||
643
0
          IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
644
0
        return make_error<GenericBinaryError>("invalid function symbol index",
645
0
                                              object_error::parse_failed);
646
0
      if (IsDefined) {
647
0
        Info.Name = readString(Ctx);
648
0
        unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
649
0
        wasm::WasmFunction &Function = Functions[FuncIndex];
650
0
        Signature = &Signatures[Function.SigIndex];
651
0
        if (Function.SymbolName.empty())
652
0
          Function.SymbolName = Info.Name;
653
0
      } else {
654
0
        wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
655
0
        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
656
0
          Info.Name = readString(Ctx);
657
0
          Info.ImportName = Import.Field;
658
0
        } else {
659
0
          Info.Name = Import.Field;
660
0
        }
661
0
        Signature = &Signatures[Import.SigIndex];
662
0
        Info.ImportModule = Import.Module;
663
0
      }
664
0
      break;
665
666
0
    case wasm::WASM_SYMBOL_TYPE_GLOBAL:
667
0
      Info.ElementIndex = readVaruint32(Ctx);
668
0
      if (!isValidGlobalIndex(Info.ElementIndex) ||
669
0
          IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
670
0
        return make_error<GenericBinaryError>("invalid global symbol index",
671
0
                                              object_error::parse_failed);
672
0
      if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
673
0
                            wasm::WASM_SYMBOL_BINDING_WEAK)
674
0
        return make_error<GenericBinaryError>("undefined weak global symbol",
675
0
                                              object_error::parse_failed);
676
0
      if (IsDefined) {
677
0
        Info.Name = readString(Ctx);
678
0
        unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
679
0
        wasm::WasmGlobal &Global = Globals[GlobalIndex];
680
0
        GlobalType = &Global.Type;
681
0
        if (Global.SymbolName.empty())
682
0
          Global.SymbolName = Info.Name;
683
0
      } else {
684
0
        wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
685
0
        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
686
0
          Info.Name = readString(Ctx);
687
0
          Info.ImportName = Import.Field;
688
0
        } else {
689
0
          Info.Name = Import.Field;
690
0
        }
691
0
        GlobalType = &Import.Global;
692
0
        Info.ImportModule = Import.Module;
693
0
      }
694
0
      break;
695
696
0
    case wasm::WASM_SYMBOL_TYPE_TABLE:
697
0
      Info.ElementIndex = readVaruint32(Ctx);
698
0
      if (!isValidTableNumber(Info.ElementIndex) ||
699
0
          IsDefined != isDefinedTableNumber(Info.ElementIndex))
700
0
        return make_error<GenericBinaryError>("invalid table symbol index",
701
0
                                              object_error::parse_failed);
702
0
      if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
703
0
                            wasm::WASM_SYMBOL_BINDING_WEAK)
704
0
        return make_error<GenericBinaryError>("undefined weak table symbol",
705
0
                                              object_error::parse_failed);
706
0
      if (IsDefined) {
707
0
        Info.Name = readString(Ctx);
708
0
        unsigned TableNumber = Info.ElementIndex - NumImportedTables;
709
0
        wasm::WasmTable &Table = Tables[TableNumber];
710
0
        TableType = &Table.Type;
711
0
        if (Table.SymbolName.empty())
712
0
          Table.SymbolName = Info.Name;
713
0
      } else {
714
0
        wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
715
0
        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
716
0
          Info.Name = readString(Ctx);
717
0
          Info.ImportName = Import.Field;
718
0
        } else {
719
0
          Info.Name = Import.Field;
720
0
        }
721
0
        TableType = &Import.Table;
722
0
        Info.ImportModule = Import.Module;
723
0
      }
724
0
      break;
725
726
0
    case wasm::WASM_SYMBOL_TYPE_DATA:
727
0
      Info.Name = readString(Ctx);
728
0
      if (IsDefined) {
729
0
        auto Index = readVaruint32(Ctx);
730
0
        auto Offset = readVaruint64(Ctx);
731
0
        auto Size = readVaruint64(Ctx);
732
0
        if (!(Info.Flags & wasm::WASM_SYMBOL_ABSOLUTE)) {
733
0
          if (static_cast<size_t>(Index) >= DataSegments.size())
734
0
            return make_error<GenericBinaryError>(
735
0
                "invalid data segment index: " + Twine(Index),
736
0
                object_error::parse_failed);
737
0
          size_t SegmentSize = DataSegments[Index].Data.Content.size();
738
0
          if (Offset > SegmentSize)
739
0
            return make_error<GenericBinaryError>(
740
0
                "invalid data symbol offset: `" + Info.Name +
741
0
                    "` (offset: " + Twine(Offset) +
742
0
                    " segment size: " + Twine(SegmentSize) + ")",
743
0
                object_error::parse_failed);
744
0
        }
745
0
        Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
746
0
      }
747
0
      break;
748
749
0
    case wasm::WASM_SYMBOL_TYPE_SECTION: {
750
0
      if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
751
0
          wasm::WASM_SYMBOL_BINDING_LOCAL)
752
0
        return make_error<GenericBinaryError>(
753
0
            "section symbols must have local binding",
754
0
            object_error::parse_failed);
755
0
      Info.ElementIndex = readVaruint32(Ctx);
756
      // Use somewhat unique section name as symbol name.
757
0
      StringRef SectionName = Sections[Info.ElementIndex].Name;
758
0
      Info.Name = SectionName;
759
0
      break;
760
0
    }
761
762
0
    case wasm::WASM_SYMBOL_TYPE_TAG: {
763
0
      Info.ElementIndex = readVaruint32(Ctx);
764
0
      if (!isValidTagIndex(Info.ElementIndex) ||
765
0
          IsDefined != isDefinedTagIndex(Info.ElementIndex))
766
0
        return make_error<GenericBinaryError>("invalid tag symbol index",
767
0
                                              object_error::parse_failed);
768
0
      if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
769
0
                            wasm::WASM_SYMBOL_BINDING_WEAK)
770
0
        return make_error<GenericBinaryError>("undefined weak global symbol",
771
0
                                              object_error::parse_failed);
772
0
      if (IsDefined) {
773
0
        Info.Name = readString(Ctx);
774
0
        unsigned TagIndex = Info.ElementIndex - NumImportedTags;
775
0
        wasm::WasmTag &Tag = Tags[TagIndex];
776
0
        Signature = &Signatures[Tag.SigIndex];
777
0
        if (Tag.SymbolName.empty())
778
0
          Tag.SymbolName = Info.Name;
779
780
0
      } else {
781
0
        wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex];
782
0
        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
783
0
          Info.Name = readString(Ctx);
784
0
          Info.ImportName = Import.Field;
785
0
        } else {
786
0
          Info.Name = Import.Field;
787
0
        }
788
0
        Signature = &Signatures[Import.SigIndex];
789
0
        Info.ImportModule = Import.Module;
790
0
      }
791
0
      break;
792
0
    }
793
794
0
    default:
795
0
      return make_error<GenericBinaryError>("invalid symbol type: " +
796
0
                                                Twine(unsigned(Info.Kind)),
797
0
                                            object_error::parse_failed);
798
0
    }
799
800
0
    if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
801
0
            wasm::WASM_SYMBOL_BINDING_LOCAL &&
802
0
        !SymbolNames.insert(Info.Name).second)
803
0
      return make_error<GenericBinaryError>("duplicate symbol name " +
804
0
                                                Twine(Info.Name),
805
0
                                            object_error::parse_failed);
806
0
    LinkingData.SymbolTable.emplace_back(Info);
807
0
    Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType,
808
0
                         Signature);
809
0
    LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
810
0
  }
811
812
0
  return Error::success();
813
0
}
814
815
0
Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
816
0
  uint32_t ComdatCount = readVaruint32(Ctx);
817
0
  StringSet<> ComdatSet;
818
0
  for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
819
0
    StringRef Name = readString(Ctx);
820
0
    if (Name.empty() || !ComdatSet.insert(Name).second)
821
0
      return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
822
0
                                                Twine(Name),
823
0
                                            object_error::parse_failed);
824
0
    LinkingData.Comdats.emplace_back(Name);
825
0
    uint32_t Flags = readVaruint32(Ctx);
826
0
    if (Flags != 0)
827
0
      return make_error<GenericBinaryError>("unsupported COMDAT flags",
828
0
                                            object_error::parse_failed);
829
830
0
    uint32_t EntryCount = readVaruint32(Ctx);
831
0
    while (EntryCount--) {
832
0
      unsigned Kind = readVaruint32(Ctx);
833
0
      unsigned Index = readVaruint32(Ctx);
834
0
      switch (Kind) {
835
0
      default:
836
0
        return make_error<GenericBinaryError>("invalid COMDAT entry type",
837
0
                                              object_error::parse_failed);
838
0
      case wasm::WASM_COMDAT_DATA:
839
0
        if (Index >= DataSegments.size())
840
0
          return make_error<GenericBinaryError>(
841
0
              "COMDAT data index out of range", object_error::parse_failed);
842
0
        if (DataSegments[Index].Data.Comdat != UINT32_MAX)
843
0
          return make_error<GenericBinaryError>("data segment in two COMDATs",
844
0
                                                object_error::parse_failed);
845
0
        DataSegments[Index].Data.Comdat = ComdatIndex;
846
0
        break;
847
0
      case wasm::WASM_COMDAT_FUNCTION:
848
0
        if (!isDefinedFunctionIndex(Index))
849
0
          return make_error<GenericBinaryError>(
850
0
              "COMDAT function index out of range", object_error::parse_failed);
851
0
        if (getDefinedFunction(Index).Comdat != UINT32_MAX)
852
0
          return make_error<GenericBinaryError>("function in two COMDATs",
853
0
                                                object_error::parse_failed);
854
0
        getDefinedFunction(Index).Comdat = ComdatIndex;
855
0
        break;
856
0
      case wasm::WASM_COMDAT_SECTION:
857
0
        if (Index >= Sections.size())
858
0
          return make_error<GenericBinaryError>(
859
0
              "COMDAT section index out of range", object_error::parse_failed);
860
0
        if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
861
0
          return make_error<GenericBinaryError>(
862
0
              "non-custom section in a COMDAT", object_error::parse_failed);
863
0
        Sections[Index].Comdat = ComdatIndex;
864
0
        break;
865
0
      }
866
0
    }
867
0
  }
868
0
  return Error::success();
869
0
}
870
871
0
Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
872
0
  llvm::SmallSet<StringRef, 3> FieldsSeen;
873
0
  uint32_t Fields = readVaruint32(Ctx);
874
0
  for (size_t I = 0; I < Fields; ++I) {
875
0
    StringRef FieldName = readString(Ctx);
876
0
    if (!FieldsSeen.insert(FieldName).second)
877
0
      return make_error<GenericBinaryError>(
878
0
          "producers section does not have unique fields",
879
0
          object_error::parse_failed);
880
0
    std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
881
0
    if (FieldName == "language") {
882
0
      ProducerVec = &ProducerInfo.Languages;
883
0
    } else if (FieldName == "processed-by") {
884
0
      ProducerVec = &ProducerInfo.Tools;
885
0
    } else if (FieldName == "sdk") {
886
0
      ProducerVec = &ProducerInfo.SDKs;
887
0
    } else {
888
0
      return make_error<GenericBinaryError>(
889
0
          "producers section field is not named one of language, processed-by, "
890
0
          "or sdk",
891
0
          object_error::parse_failed);
892
0
    }
893
0
    uint32_t ValueCount = readVaruint32(Ctx);
894
0
    llvm::SmallSet<StringRef, 8> ProducersSeen;
895
0
    for (size_t J = 0; J < ValueCount; ++J) {
896
0
      StringRef Name = readString(Ctx);
897
0
      StringRef Version = readString(Ctx);
898
0
      if (!ProducersSeen.insert(Name).second) {
899
0
        return make_error<GenericBinaryError>(
900
0
            "producers section contains repeated producer",
901
0
            object_error::parse_failed);
902
0
      }
903
0
      ProducerVec->emplace_back(std::string(Name), std::string(Version));
904
0
    }
905
0
  }
906
0
  if (Ctx.Ptr != Ctx.End)
907
0
    return make_error<GenericBinaryError>("producers section ended prematurely",
908
0
                                          object_error::parse_failed);
909
0
  return Error::success();
910
0
}
911
912
0
Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
913
0
  llvm::SmallSet<std::string, 8> FeaturesSeen;
914
0
  uint32_t FeatureCount = readVaruint32(Ctx);
915
0
  for (size_t I = 0; I < FeatureCount; ++I) {
916
0
    wasm::WasmFeatureEntry Feature;
917
0
    Feature.Prefix = readUint8(Ctx);
918
0
    switch (Feature.Prefix) {
919
0
    case wasm::WASM_FEATURE_PREFIX_USED:
920
0
    case wasm::WASM_FEATURE_PREFIX_REQUIRED:
921
0
    case wasm::WASM_FEATURE_PREFIX_DISALLOWED:
922
0
      break;
923
0
    default:
924
0
      return make_error<GenericBinaryError>("unknown feature policy prefix",
925
0
                                            object_error::parse_failed);
926
0
    }
927
0
    Feature.Name = std::string(readString(Ctx));
928
0
    if (!FeaturesSeen.insert(Feature.Name).second)
929
0
      return make_error<GenericBinaryError>(
930
0
          "target features section contains repeated feature \"" +
931
0
              Feature.Name + "\"",
932
0
          object_error::parse_failed);
933
0
    TargetFeatures.push_back(Feature);
934
0
  }
935
0
  if (Ctx.Ptr != Ctx.End)
936
0
    return make_error<GenericBinaryError>(
937
0
        "target features section ended prematurely",
938
0
        object_error::parse_failed);
939
0
  return Error::success();
940
0
}
941
942
0
Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
943
0
  uint32_t SectionIndex = readVaruint32(Ctx);
944
0
  if (SectionIndex >= Sections.size())
945
0
    return make_error<GenericBinaryError>("invalid section index",
946
0
                                          object_error::parse_failed);
947
0
  WasmSection &Section = Sections[SectionIndex];
948
0
  uint32_t RelocCount = readVaruint32(Ctx);
949
0
  uint32_t EndOffset = Section.Content.size();
950
0
  uint32_t PreviousOffset = 0;
951
0
  while (RelocCount--) {
952
0
    wasm::WasmRelocation Reloc = {};
953
0
    uint32_t type = readVaruint32(Ctx);
954
0
    Reloc.Type = type;
955
0
    Reloc.Offset = readVaruint32(Ctx);
956
0
    if (Reloc.Offset < PreviousOffset)
957
0
      return make_error<GenericBinaryError>("relocations not in offset order",
958
0
                                            object_error::parse_failed);
959
0
    PreviousOffset = Reloc.Offset;
960
0
    Reloc.Index = readVaruint32(Ctx);
961
0
    switch (type) {
962
0
    case wasm::R_WASM_FUNCTION_INDEX_LEB:
963
0
    case wasm::R_WASM_FUNCTION_INDEX_I32:
964
0
    case wasm::R_WASM_TABLE_INDEX_SLEB:
965
0
    case wasm::R_WASM_TABLE_INDEX_SLEB64:
966
0
    case wasm::R_WASM_TABLE_INDEX_I32:
967
0
    case wasm::R_WASM_TABLE_INDEX_I64:
968
0
    case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
969
0
    case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
970
0
      if (!isValidFunctionSymbol(Reloc.Index))
971
0
        return make_error<GenericBinaryError>(
972
0
            "invalid relocation function index", object_error::parse_failed);
973
0
      break;
974
0
    case wasm::R_WASM_TABLE_NUMBER_LEB:
975
0
      if (!isValidTableSymbol(Reloc.Index))
976
0
        return make_error<GenericBinaryError>("invalid relocation table index",
977
0
                                              object_error::parse_failed);
978
0
      break;
979
0
    case wasm::R_WASM_TYPE_INDEX_LEB:
980
0
      if (Reloc.Index >= Signatures.size())
981
0
        return make_error<GenericBinaryError>("invalid relocation type index",
982
0
                                              object_error::parse_failed);
983
0
      break;
984
0
    case wasm::R_WASM_GLOBAL_INDEX_LEB:
985
      // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
986
      // symbols to refer to their GOT entries.
987
0
      if (!isValidGlobalSymbol(Reloc.Index) &&
988
0
          !isValidDataSymbol(Reloc.Index) &&
989
0
          !isValidFunctionSymbol(Reloc.Index))
990
0
        return make_error<GenericBinaryError>("invalid relocation global index",
991
0
                                              object_error::parse_failed);
992
0
      break;
993
0
    case wasm::R_WASM_GLOBAL_INDEX_I32:
994
0
      if (!isValidGlobalSymbol(Reloc.Index))
995
0
        return make_error<GenericBinaryError>("invalid relocation global index",
996
0
                                              object_error::parse_failed);
997
0
      break;
998
0
    case wasm::R_WASM_TAG_INDEX_LEB:
999
0
      if (!isValidTagSymbol(Reloc.Index))
1000
0
        return make_error<GenericBinaryError>("invalid relocation tag index",
1001
0
                                              object_error::parse_failed);
1002
0
      break;
1003
0
    case wasm::R_WASM_MEMORY_ADDR_LEB:
1004
0
    case wasm::R_WASM_MEMORY_ADDR_SLEB:
1005
0
    case wasm::R_WASM_MEMORY_ADDR_I32:
1006
0
    case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
1007
0
    case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
1008
0
    case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
1009
0
      if (!isValidDataSymbol(Reloc.Index))
1010
0
        return make_error<GenericBinaryError>("invalid relocation data index",
1011
0
                                              object_error::parse_failed);
1012
0
      Reloc.Addend = readVarint32(Ctx);
1013
0
      break;
1014
0
    case wasm::R_WASM_MEMORY_ADDR_LEB64:
1015
0
    case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1016
0
    case wasm::R_WASM_MEMORY_ADDR_I64:
1017
0
    case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1018
0
    case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1019
0
      if (!isValidDataSymbol(Reloc.Index))
1020
0
        return make_error<GenericBinaryError>("invalid relocation data index",
1021
0
                                              object_error::parse_failed);
1022
0
      Reloc.Addend = readVarint64(Ctx);
1023
0
      break;
1024
0
    case wasm::R_WASM_FUNCTION_OFFSET_I32:
1025
0
      if (!isValidFunctionSymbol(Reloc.Index))
1026
0
        return make_error<GenericBinaryError>(
1027
0
            "invalid relocation function index", object_error::parse_failed);
1028
0
      Reloc.Addend = readVarint32(Ctx);
1029
0
      break;
1030
0
    case wasm::R_WASM_FUNCTION_OFFSET_I64:
1031
0
      if (!isValidFunctionSymbol(Reloc.Index))
1032
0
        return make_error<GenericBinaryError>(
1033
0
            "invalid relocation function index", object_error::parse_failed);
1034
0
      Reloc.Addend = readVarint64(Ctx);
1035
0
      break;
1036
0
    case wasm::R_WASM_SECTION_OFFSET_I32:
1037
0
      if (!isValidSectionSymbol(Reloc.Index))
1038
0
        return make_error<GenericBinaryError>(
1039
0
            "invalid relocation section index", object_error::parse_failed);
1040
0
      Reloc.Addend = readVarint32(Ctx);
1041
0
      break;
1042
0
    default:
1043
0
      return make_error<GenericBinaryError>("invalid relocation type: " +
1044
0
                                                Twine(type),
1045
0
                                            object_error::parse_failed);
1046
0
    }
1047
1048
    // Relocations must fit inside the section, and must appear in order.  They
1049
    // also shouldn't overlap a function/element boundary, but we don't bother
1050
    // to check that.
1051
0
    uint64_t Size = 5;
1052
0
    if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1053
0
        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1054
0
        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1055
0
      Size = 10;
1056
0
    if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1057
0
        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1058
0
        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1059
0
        Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1060
0
        Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1061
0
        Reloc.Type == wasm::R_WASM_FUNCTION_INDEX_I32 ||
1062
0
        Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
1063
0
      Size = 4;
1064
0
    if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1065
0
        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1066
0
        Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
1067
0
      Size = 8;
1068
0
    if (Reloc.Offset + Size > EndOffset)
1069
0
      return make_error<GenericBinaryError>("invalid relocation offset",
1070
0
                                            object_error::parse_failed);
1071
1072
0
    Section.Relocations.push_back(Reloc);
1073
0
  }
1074
0
  if (Ctx.Ptr != Ctx.End)
1075
0
    return make_error<GenericBinaryError>("reloc section ended prematurely",
1076
0
                                          object_error::parse_failed);
1077
0
  return Error::success();
1078
0
}
1079
1080
0
Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
1081
0
  if (Sec.Name == "dylink") {
1082
0
    if (Error Err = parseDylinkSection(Ctx))
1083
0
      return Err;
1084
0
  } else if (Sec.Name == "dylink.0") {
1085
0
    if (Error Err = parseDylink0Section(Ctx))
1086
0
      return Err;
1087
0
  } else if (Sec.Name == "name") {
1088
0
    if (Error Err = parseNameSection(Ctx))
1089
0
      return Err;
1090
0
  } else if (Sec.Name == "linking") {
1091
0
    if (Error Err = parseLinkingSection(Ctx))
1092
0
      return Err;
1093
0
  } else if (Sec.Name == "producers") {
1094
0
    if (Error Err = parseProducersSection(Ctx))
1095
0
      return Err;
1096
0
  } else if (Sec.Name == "target_features") {
1097
0
    if (Error Err = parseTargetFeaturesSection(Ctx))
1098
0
      return Err;
1099
0
  } else if (Sec.Name.starts_with("reloc.")) {
1100
0
    if (Error Err = parseRelocSection(Sec.Name, Ctx))
1101
0
      return Err;
1102
0
  }
1103
0
  return Error::success();
1104
0
}
1105
1106
0
Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1107
0
  uint32_t Count = readVaruint32(Ctx);
1108
0
  Signatures.reserve(Count);
1109
0
  while (Count--) {
1110
0
    wasm::WasmSignature Sig;
1111
0
    uint8_t Form = readUint8(Ctx);
1112
0
    if (Form != wasm::WASM_TYPE_FUNC) {
1113
0
      return make_error<GenericBinaryError>("invalid signature type",
1114
0
                                            object_error::parse_failed);
1115
0
    }
1116
0
    uint32_t ParamCount = readVaruint32(Ctx);
1117
0
    Sig.Params.reserve(ParamCount);
1118
0
    while (ParamCount--) {
1119
0
      uint32_t ParamType = readUint8(Ctx);
1120
0
      Sig.Params.push_back(wasm::ValType(ParamType));
1121
0
    }
1122
0
    uint32_t ReturnCount = readVaruint32(Ctx);
1123
0
    while (ReturnCount--) {
1124
0
      uint32_t ReturnType = readUint8(Ctx);
1125
0
      Sig.Returns.push_back(wasm::ValType(ReturnType));
1126
0
    }
1127
0
    Signatures.push_back(std::move(Sig));
1128
0
  }
1129
0
  if (Ctx.Ptr != Ctx.End)
1130
0
    return make_error<GenericBinaryError>("type section ended prematurely",
1131
0
                                          object_error::parse_failed);
1132
0
  return Error::success();
1133
0
}
1134
1135
0
Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1136
0
  uint32_t Count = readVaruint32(Ctx);
1137
0
  uint32_t NumTypes = Signatures.size();
1138
0
  Imports.reserve(Count);
1139
0
  for (uint32_t I = 0; I < Count; I++) {
1140
0
    wasm::WasmImport Im;
1141
0
    Im.Module = readString(Ctx);
1142
0
    Im.Field = readString(Ctx);
1143
0
    Im.Kind = readUint8(Ctx);
1144
0
    switch (Im.Kind) {
1145
0
    case wasm::WASM_EXTERNAL_FUNCTION:
1146
0
      NumImportedFunctions++;
1147
0
      Im.SigIndex = readVaruint32(Ctx);
1148
0
      if (Im.SigIndex >= NumTypes)
1149
0
        return make_error<GenericBinaryError>("invalid function type",
1150
0
                                              object_error::parse_failed);
1151
0
      break;
1152
0
    case wasm::WASM_EXTERNAL_GLOBAL:
1153
0
      NumImportedGlobals++;
1154
0
      Im.Global.Type = readUint8(Ctx);
1155
0
      Im.Global.Mutable = readVaruint1(Ctx);
1156
0
      break;
1157
0
    case wasm::WASM_EXTERNAL_MEMORY:
1158
0
      Im.Memory = readLimits(Ctx);
1159
0
      if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1160
0
        HasMemory64 = true;
1161
0
      break;
1162
0
    case wasm::WASM_EXTERNAL_TABLE: {
1163
0
      Im.Table = readTableType(Ctx);
1164
0
      NumImportedTables++;
1165
0
      auto ElemType = Im.Table.ElemType;
1166
0
      if (ElemType != wasm::WASM_TYPE_FUNCREF &&
1167
0
          ElemType != wasm::WASM_TYPE_EXTERNREF)
1168
0
        return make_error<GenericBinaryError>("invalid table element type",
1169
0
                                              object_error::parse_failed);
1170
0
      break;
1171
0
    }
1172
0
    case wasm::WASM_EXTERNAL_TAG:
1173
0
      NumImportedTags++;
1174
0
      if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1175
0
        return make_error<GenericBinaryError>("invalid attribute",
1176
0
                                              object_error::parse_failed);
1177
0
      Im.SigIndex = readVaruint32(Ctx);
1178
0
      if (Im.SigIndex >= NumTypes)
1179
0
        return make_error<GenericBinaryError>("invalid tag type",
1180
0
                                              object_error::parse_failed);
1181
0
      break;
1182
0
    default:
1183
0
      return make_error<GenericBinaryError>("unexpected import kind",
1184
0
                                            object_error::parse_failed);
1185
0
    }
1186
0
    Imports.push_back(Im);
1187
0
  }
1188
0
  if (Ctx.Ptr != Ctx.End)
1189
0
    return make_error<GenericBinaryError>("import section ended prematurely",
1190
0
                                          object_error::parse_failed);
1191
0
  return Error::success();
1192
0
}
1193
1194
0
Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1195
0
  uint32_t Count = readVaruint32(Ctx);
1196
0
  Functions.reserve(Count);
1197
0
  uint32_t NumTypes = Signatures.size();
1198
0
  while (Count--) {
1199
0
    uint32_t Type = readVaruint32(Ctx);
1200
0
    if (Type >= NumTypes)
1201
0
      return make_error<GenericBinaryError>("invalid function type",
1202
0
                                            object_error::parse_failed);
1203
0
    wasm::WasmFunction F;
1204
0
    F.SigIndex = Type;
1205
0
    Functions.push_back(F);
1206
0
  }
1207
0
  if (Ctx.Ptr != Ctx.End)
1208
0
    return make_error<GenericBinaryError>("function section ended prematurely",
1209
0
                                          object_error::parse_failed);
1210
0
  return Error::success();
1211
0
}
1212
1213
0
Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1214
0
  TableSection = Sections.size();
1215
0
  uint32_t Count = readVaruint32(Ctx);
1216
0
  Tables.reserve(Count);
1217
0
  while (Count--) {
1218
0
    wasm::WasmTable T;
1219
0
    T.Type = readTableType(Ctx);
1220
0
    T.Index = NumImportedTables + Tables.size();
1221
0
    Tables.push_back(T);
1222
0
    auto ElemType = Tables.back().Type.ElemType;
1223
0
    if (ElemType != wasm::WASM_TYPE_FUNCREF &&
1224
0
        ElemType != wasm::WASM_TYPE_EXTERNREF) {
1225
0
      return make_error<GenericBinaryError>("invalid table element type",
1226
0
                                            object_error::parse_failed);
1227
0
    }
1228
0
  }
1229
0
  if (Ctx.Ptr != Ctx.End)
1230
0
    return make_error<GenericBinaryError>("table section ended prematurely",
1231
0
                                          object_error::parse_failed);
1232
0
  return Error::success();
1233
0
}
1234
1235
0
Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1236
0
  uint32_t Count = readVaruint32(Ctx);
1237
0
  Memories.reserve(Count);
1238
0
  while (Count--) {
1239
0
    auto Limits = readLimits(Ctx);
1240
0
    if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1241
0
      HasMemory64 = true;
1242
0
    Memories.push_back(Limits);
1243
0
  }
1244
0
  if (Ctx.Ptr != Ctx.End)
1245
0
    return make_error<GenericBinaryError>("memory section ended prematurely",
1246
0
                                          object_error::parse_failed);
1247
0
  return Error::success();
1248
0
}
1249
1250
0
Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1251
0
  TagSection = Sections.size();
1252
0
  uint32_t Count = readVaruint32(Ctx);
1253
0
  Tags.reserve(Count);
1254
0
  uint32_t NumTypes = Signatures.size();
1255
0
  while (Count--) {
1256
0
    if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1257
0
      return make_error<GenericBinaryError>("invalid attribute",
1258
0
                                            object_error::parse_failed);
1259
0
    uint32_t Type = readVaruint32(Ctx);
1260
0
    if (Type >= NumTypes)
1261
0
      return make_error<GenericBinaryError>("invalid tag type",
1262
0
                                            object_error::parse_failed);
1263
0
    wasm::WasmTag Tag;
1264
0
    Tag.Index = NumImportedTags + Tags.size();
1265
0
    Tag.SigIndex = Type;
1266
0
    Tags.push_back(Tag);
1267
0
  }
1268
1269
0
  if (Ctx.Ptr != Ctx.End)
1270
0
    return make_error<GenericBinaryError>("tag section ended prematurely",
1271
0
                                          object_error::parse_failed);
1272
0
  return Error::success();
1273
0
}
1274
1275
0
Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1276
0
  GlobalSection = Sections.size();
1277
0
  uint32_t Count = readVaruint32(Ctx);
1278
0
  Globals.reserve(Count);
1279
0
  while (Count--) {
1280
0
    wasm::WasmGlobal Global;
1281
0
    Global.Index = NumImportedGlobals + Globals.size();
1282
0
    Global.Type.Type = readUint8(Ctx);
1283
0
    Global.Type.Mutable = readVaruint1(Ctx);
1284
0
    if (Error Err = readInitExpr(Global.InitExpr, Ctx))
1285
0
      return Err;
1286
0
    Globals.push_back(Global);
1287
0
  }
1288
0
  if (Ctx.Ptr != Ctx.End)
1289
0
    return make_error<GenericBinaryError>("global section ended prematurely",
1290
0
                                          object_error::parse_failed);
1291
0
  return Error::success();
1292
0
}
1293
1294
0
Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1295
0
  uint32_t Count = readVaruint32(Ctx);
1296
0
  Exports.reserve(Count);
1297
0
  LinkingData.SymbolTable.reserve(Count);
1298
0
  Symbols.reserve(Count);
1299
0
  for (uint32_t I = 0; I < Count; I++) {
1300
0
    wasm::WasmExport Ex;
1301
0
    Ex.Name = readString(Ctx);
1302
0
    Ex.Kind = readUint8(Ctx);
1303
0
    Ex.Index = readVaruint32(Ctx);
1304
0
    const wasm::WasmSignature *Signature = nullptr;
1305
0
    const wasm::WasmGlobalType *GlobalType = nullptr;
1306
0
    const wasm::WasmTableType *TableType = nullptr;
1307
0
    wasm::WasmSymbolInfo Info;
1308
0
    Info.Name = Ex.Name;
1309
0
    Info.Flags = 0;
1310
0
    switch (Ex.Kind) {
1311
0
    case wasm::WASM_EXTERNAL_FUNCTION: {
1312
0
      if (!isDefinedFunctionIndex(Ex.Index))
1313
0
        return make_error<GenericBinaryError>("invalid function export",
1314
0
                                              object_error::parse_failed);
1315
0
      getDefinedFunction(Ex.Index).ExportName = Ex.Name;
1316
0
      Info.Kind = wasm::WASM_SYMBOL_TYPE_FUNCTION;
1317
0
      Info.ElementIndex = Ex.Index;
1318
0
      unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
1319
0
      wasm::WasmFunction &Function = Functions[FuncIndex];
1320
0
      Signature = &Signatures[Function.SigIndex];
1321
0
      break;
1322
0
    }
1323
0
    case wasm::WASM_EXTERNAL_GLOBAL: {
1324
0
      if (!isValidGlobalIndex(Ex.Index))
1325
0
        return make_error<GenericBinaryError>("invalid global export",
1326
0
                                              object_error::parse_failed);
1327
0
      Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA;
1328
0
      uint64_t Offset = 0;
1329
0
      if (isDefinedGlobalIndex(Ex.Index)) {
1330
0
        auto Global = getDefinedGlobal(Ex.Index);
1331
0
        if (!Global.InitExpr.Extended) {
1332
0
          auto Inst = Global.InitExpr.Inst;
1333
0
          if (Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1334
0
            Offset = Inst.Value.Int32;
1335
0
          } else if (Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1336
0
            Offset = Inst.Value.Int64;
1337
0
          }
1338
0
        }
1339
0
      }
1340
0
      Info.DataRef = wasm::WasmDataReference{0, Offset, 0};
1341
0
      break;
1342
0
    }
1343
0
    case wasm::WASM_EXTERNAL_TAG:
1344
0
      if (!isValidTagIndex(Ex.Index))
1345
0
        return make_error<GenericBinaryError>("invalid tag export",
1346
0
                                              object_error::parse_failed);
1347
0
      Info.Kind = wasm::WASM_SYMBOL_TYPE_TAG;
1348
0
      Info.ElementIndex = Ex.Index;
1349
0
      break;
1350
0
    case wasm::WASM_EXTERNAL_MEMORY:
1351
0
      break;
1352
0
    case wasm::WASM_EXTERNAL_TABLE:
1353
0
      Info.Kind = wasm::WASM_SYMBOL_TYPE_TABLE;
1354
0
      Info.ElementIndex = Ex.Index;
1355
0
      break;
1356
0
    default:
1357
0
      return make_error<GenericBinaryError>("unexpected export kind",
1358
0
                                            object_error::parse_failed);
1359
0
    }
1360
0
    Exports.push_back(Ex);
1361
0
    if (Ex.Kind != wasm::WASM_EXTERNAL_MEMORY) {
1362
0
      LinkingData.SymbolTable.emplace_back(Info);
1363
0
      Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType,
1364
0
                           TableType, Signature);
1365
0
      LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
1366
0
    }
1367
0
  }
1368
0
  if (Ctx.Ptr != Ctx.End)
1369
0
    return make_error<GenericBinaryError>("export section ended prematurely",
1370
0
                                          object_error::parse_failed);
1371
0
  return Error::success();
1372
0
}
1373
1374
0
bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1375
0
  return Index < NumImportedFunctions + Functions.size();
1376
0
}
1377
1378
0
bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
1379
0
  return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1380
0
}
1381
1382
0
bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
1383
0
  return Index < NumImportedGlobals + Globals.size();
1384
0
}
1385
1386
0
bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
1387
0
  return Index < NumImportedTables + Tables.size();
1388
0
}
1389
1390
0
bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
1391
0
  return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1392
0
}
1393
1394
0
bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
1395
0
  return Index >= NumImportedTables && isValidTableNumber(Index);
1396
0
}
1397
1398
0
bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
1399
0
  return Index < NumImportedTags + Tags.size();
1400
0
}
1401
1402
0
bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
1403
0
  return Index >= NumImportedTags && isValidTagIndex(Index);
1404
0
}
1405
1406
0
bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1407
0
  return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1408
0
}
1409
1410
0
bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
1411
0
  return Index < Symbols.size() && Symbols[Index].isTypeTable();
1412
0
}
1413
1414
0
bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1415
0
  return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1416
0
}
1417
1418
0
bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
1419
0
  return Index < Symbols.size() && Symbols[Index].isTypeTag();
1420
0
}
1421
1422
0
bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1423
0
  return Index < Symbols.size() && Symbols[Index].isTypeData();
1424
0
}
1425
1426
0
bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1427
0
  return Index < Symbols.size() && Symbols[Index].isTypeSection();
1428
0
}
1429
1430
0
wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1431
0
  assert(isDefinedFunctionIndex(Index));
1432
0
  return Functions[Index - NumImportedFunctions];
1433
0
}
1434
1435
const wasm::WasmFunction &
1436
0
WasmObjectFile::getDefinedFunction(uint32_t Index) const {
1437
0
  assert(isDefinedFunctionIndex(Index));
1438
0
  return Functions[Index - NumImportedFunctions];
1439
0
}
1440
1441
0
wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
1442
0
  assert(isDefinedGlobalIndex(Index));
1443
0
  return Globals[Index - NumImportedGlobals];
1444
0
}
1445
1446
0
wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1447
0
  assert(isDefinedTagIndex(Index));
1448
0
  return Tags[Index - NumImportedTags];
1449
0
}
1450
1451
0
Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1452
0
  StartFunction = readVaruint32(Ctx);
1453
0
  if (!isValidFunctionIndex(StartFunction))
1454
0
    return make_error<GenericBinaryError>("invalid start function",
1455
0
                                          object_error::parse_failed);
1456
0
  return Error::success();
1457
0
}
1458
1459
0
Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1460
0
  CodeSection = Sections.size();
1461
0
  uint32_t FunctionCount = readVaruint32(Ctx);
1462
0
  if (FunctionCount != Functions.size()) {
1463
0
    return make_error<GenericBinaryError>("invalid function count",
1464
0
                                          object_error::parse_failed);
1465
0
  }
1466
1467
0
  for (uint32_t i = 0; i < FunctionCount; i++) {
1468
0
    wasm::WasmFunction& Function = Functions[i];
1469
0
    const uint8_t *FunctionStart = Ctx.Ptr;
1470
0
    uint32_t Size = readVaruint32(Ctx);
1471
0
    const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1472
1473
0
    Function.CodeOffset = Ctx.Ptr - FunctionStart;
1474
0
    Function.Index = NumImportedFunctions + i;
1475
0
    Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1476
0
    Function.Size = FunctionEnd - FunctionStart;
1477
1478
0
    uint32_t NumLocalDecls = readVaruint32(Ctx);
1479
0
    Function.Locals.reserve(NumLocalDecls);
1480
0
    while (NumLocalDecls--) {
1481
0
      wasm::WasmLocalDecl Decl;
1482
0
      Decl.Count = readVaruint32(Ctx);
1483
0
      Decl.Type = readUint8(Ctx);
1484
0
      Function.Locals.push_back(Decl);
1485
0
    }
1486
1487
0
    uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1488
    // Ensure that Function is within Ctx's buffer.
1489
0
    if (Ctx.Ptr + BodySize > Ctx.End) {
1490
0
      return make_error<GenericBinaryError>("Function extends beyond buffer",
1491
0
                                            object_error::parse_failed);
1492
0
    }
1493
0
    Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1494
    // This will be set later when reading in the linking metadata section.
1495
0
    Function.Comdat = UINT32_MAX;
1496
0
    Ctx.Ptr += BodySize;
1497
0
    assert(Ctx.Ptr == FunctionEnd);
1498
0
  }
1499
0
  if (Ctx.Ptr != Ctx.End)
1500
0
    return make_error<GenericBinaryError>("code section ended prematurely",
1501
0
                                          object_error::parse_failed);
1502
0
  return Error::success();
1503
0
}
1504
1505
0
Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1506
0
  uint32_t Count = readVaruint32(Ctx);
1507
0
  ElemSegments.reserve(Count);
1508
0
  while (Count--) {
1509
0
    wasm::WasmElemSegment Segment;
1510
0
    Segment.Flags = readVaruint32(Ctx);
1511
1512
0
    uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER |
1513
0
                              wasm::WASM_ELEM_SEGMENT_IS_PASSIVE |
1514
0
                              wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS;
1515
0
    if (Segment.Flags & ~SupportedFlags)
1516
0
      return make_error<GenericBinaryError>(
1517
0
          "Unsupported flags for element segment", object_error::parse_failed);
1518
1519
0
    if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
1520
0
      Segment.TableNumber = readVaruint32(Ctx);
1521
0
    else
1522
0
      Segment.TableNumber = 0;
1523
0
    if (!isValidTableNumber(Segment.TableNumber))
1524
0
      return make_error<GenericBinaryError>("invalid TableNumber",
1525
0
                                            object_error::parse_failed);
1526
1527
0
    if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) {
1528
0
      Segment.Offset.Extended = false;
1529
0
      Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1530
0
      Segment.Offset.Inst.Value.Int32 = 0;
1531
0
    } else {
1532
0
      if (Error Err = readInitExpr(Segment.Offset, Ctx))
1533
0
        return Err;
1534
0
    }
1535
1536
0
    if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
1537
0
      Segment.ElemKind = readUint8(Ctx);
1538
0
      if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {
1539
0
        if (Segment.ElemKind != uint8_t(wasm::ValType::FUNCREF) &&
1540
0
            Segment.ElemKind != uint8_t(wasm::ValType::EXTERNREF)) {
1541
0
          return make_error<GenericBinaryError>("invalid reference type",
1542
0
                                                object_error::parse_failed);
1543
0
        }
1544
0
      } else {
1545
0
        if (Segment.ElemKind != 0)
1546
0
          return make_error<GenericBinaryError>("invalid elemtype",
1547
0
                                                object_error::parse_failed);
1548
0
        Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1549
0
      }
1550
0
    } else {
1551
0
      Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1552
0
    }
1553
1554
0
    if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS)
1555
0
      return make_error<GenericBinaryError>(
1556
0
          "elem segment init expressions not yet implemented",
1557
0
          object_error::parse_failed);
1558
1559
0
    uint32_t NumElems = readVaruint32(Ctx);
1560
0
    while (NumElems--) {
1561
0
      Segment.Functions.push_back(readVaruint32(Ctx));
1562
0
    }
1563
0
    ElemSegments.push_back(Segment);
1564
0
  }
1565
0
  if (Ctx.Ptr != Ctx.End)
1566
0
    return make_error<GenericBinaryError>("elem section ended prematurely",
1567
0
                                          object_error::parse_failed);
1568
0
  return Error::success();
1569
0
}
1570
1571
0
Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1572
0
  DataSection = Sections.size();
1573
0
  uint32_t Count = readVaruint32(Ctx);
1574
0
  if (DataCount && Count != *DataCount)
1575
0
    return make_error<GenericBinaryError>(
1576
0
        "number of data segments does not match DataCount section");
1577
0
  DataSegments.reserve(Count);
1578
0
  while (Count--) {
1579
0
    WasmSegment Segment;
1580
0
    Segment.Data.InitFlags = readVaruint32(Ctx);
1581
0
    Segment.Data.MemoryIndex =
1582
0
        (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
1583
0
            ? readVaruint32(Ctx)
1584
0
            : 0;
1585
0
    if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1586
0
      if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1587
0
        return Err;
1588
0
    } else {
1589
0
      Segment.Data.Offset.Extended = false;
1590
0
      Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1591
0
      Segment.Data.Offset.Inst.Value.Int32 = 0;
1592
0
    }
1593
0
    uint32_t Size = readVaruint32(Ctx);
1594
0
    if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1595
0
      return make_error<GenericBinaryError>("invalid segment size",
1596
0
                                            object_error::parse_failed);
1597
0
    Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1598
    // The rest of these Data fields are set later, when reading in the linking
1599
    // metadata section.
1600
0
    Segment.Data.Alignment = 0;
1601
0
    Segment.Data.LinkingFlags = 0;
1602
0
    Segment.Data.Comdat = UINT32_MAX;
1603
0
    Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1604
0
    Ctx.Ptr += Size;
1605
0
    DataSegments.push_back(Segment);
1606
0
  }
1607
0
  if (Ctx.Ptr != Ctx.End)
1608
0
    return make_error<GenericBinaryError>("data section ended prematurely",
1609
0
                                          object_error::parse_failed);
1610
0
  return Error::success();
1611
0
}
1612
1613
0
Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1614
0
  DataCount = readVaruint32(Ctx);
1615
0
  return Error::success();
1616
0
}
1617
1618
0
const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1619
0
  return Header;
1620
0
}
1621
1622
0
void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
1623
1624
0
Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
1625
0
  uint32_t Result = SymbolRef::SF_None;
1626
0
  const WasmSymbol &Sym = getWasmSymbol(Symb);
1627
1628
0
  LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1629
0
  if (Sym.isBindingWeak())
1630
0
    Result |= SymbolRef::SF_Weak;
1631
0
  if (!Sym.isBindingLocal())
1632
0
    Result |= SymbolRef::SF_Global;
1633
0
  if (Sym.isHidden())
1634
0
    Result |= SymbolRef::SF_Hidden;
1635
0
  if (!Sym.isDefined())
1636
0
    Result |= SymbolRef::SF_Undefined;
1637
0
  if (Sym.isTypeFunction())
1638
0
    Result |= SymbolRef::SF_Executable;
1639
0
  return Result;
1640
0
}
1641
1642
0
basic_symbol_iterator WasmObjectFile::symbol_begin() const {
1643
0
  DataRefImpl Ref;
1644
0
  Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1645
0
  Ref.d.b = 0; // Symbol index
1646
0
  return BasicSymbolRef(Ref, this);
1647
0
}
1648
1649
0
basic_symbol_iterator WasmObjectFile::symbol_end() const {
1650
0
  DataRefImpl Ref;
1651
0
  Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1652
0
  Ref.d.b = Symbols.size(); // Symbol index
1653
0
  return BasicSymbolRef(Ref, this);
1654
0
}
1655
1656
0
const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
1657
0
  return Symbols[Symb.d.b];
1658
0
}
1659
1660
0
const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1661
0
  return getWasmSymbol(Symb.getRawDataRefImpl());
1662
0
}
1663
1664
0
Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
1665
0
  return getWasmSymbol(Symb).Info.Name;
1666
0
}
1667
1668
0
Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
1669
0
  auto &Sym = getWasmSymbol(Symb);
1670
0
  if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1671
0
      isDefinedFunctionIndex(Sym.Info.ElementIndex)) {
1672
    // For object files, use the section offset. The linker relies on this.
1673
    // For linked files, use the file offset. This behavior matches the way
1674
    // browsers print stack traces and is useful for binary size analysis.
1675
    // (see https://webassembly.github.io/spec/web-api/index.html#conventions)
1676
0
    uint32_t Adjustment = isRelocatableObject() || isSharedObject()
1677
0
                              ? 0
1678
0
                              : Sections[CodeSection].Offset;
1679
0
    return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +
1680
0
           Adjustment;
1681
0
  }
1682
0
  return getSymbolValue(Symb);
1683
0
}
1684
1685
0
uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
1686
0
  switch (Sym.Info.Kind) {
1687
0
  case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1688
0
  case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1689
0
  case wasm::WASM_SYMBOL_TYPE_TAG:
1690
0
  case wasm::WASM_SYMBOL_TYPE_TABLE:
1691
0
    return Sym.Info.ElementIndex;
1692
0
  case wasm::WASM_SYMBOL_TYPE_DATA: {
1693
    // The value of a data symbol is the segment offset, plus the symbol
1694
    // offset within the segment.
1695
0
    uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1696
0
    const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1697
0
    if (Segment.Offset.Extended) {
1698
0
      llvm_unreachable("extended init exprs not supported");
1699
0
    } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1700
0
      return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset;
1701
0
    } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1702
0
      return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset;
1703
0
    } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) {
1704
0
      return Sym.Info.DataRef.Offset;
1705
0
    } else {
1706
0
      llvm_unreachable("unknown init expr opcode");
1707
0
    }
1708
0
  }
1709
0
  case wasm::WASM_SYMBOL_TYPE_SECTION:
1710
0
    return 0;
1711
0
  }
1712
0
  llvm_unreachable("invalid symbol type");
1713
0
}
1714
1715
0
uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1716
0
  return getWasmSymbolValue(getWasmSymbol(Symb));
1717
0
}
1718
1719
0
uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1720
0
  llvm_unreachable("not yet implemented");
1721
0
  return 0;
1722
0
}
1723
1724
0
uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1725
0
  llvm_unreachable("not yet implemented");
1726
0
  return 0;
1727
0
}
1728
1729
Expected<SymbolRef::Type>
1730
0
WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
1731
0
  const WasmSymbol &Sym = getWasmSymbol(Symb);
1732
1733
0
  switch (Sym.Info.Kind) {
1734
0
  case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1735
0
    return SymbolRef::ST_Function;
1736
0
  case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1737
0
    return SymbolRef::ST_Other;
1738
0
  case wasm::WASM_SYMBOL_TYPE_DATA:
1739
0
    return SymbolRef::ST_Data;
1740
0
  case wasm::WASM_SYMBOL_TYPE_SECTION:
1741
0
    return SymbolRef::ST_Debug;
1742
0
  case wasm::WASM_SYMBOL_TYPE_TAG:
1743
0
    return SymbolRef::ST_Other;
1744
0
  case wasm::WASM_SYMBOL_TYPE_TABLE:
1745
0
    return SymbolRef::ST_Other;
1746
0
  }
1747
1748
0
  llvm_unreachable("unknown WasmSymbol::SymbolType");
1749
0
  return SymbolRef::ST_Other;
1750
0
}
1751
1752
Expected<section_iterator>
1753
0
WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1754
0
  const WasmSymbol &Sym = getWasmSymbol(Symb);
1755
0
  if (Sym.isUndefined())
1756
0
    return section_end();
1757
1758
0
  DataRefImpl Ref;
1759
0
  Ref.d.a = getSymbolSectionIdImpl(Sym);
1760
0
  return section_iterator(SectionRef(Ref, this));
1761
0
}
1762
1763
0
uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const {
1764
0
  const WasmSymbol &Sym = getWasmSymbol(Symb);
1765
0
  return getSymbolSectionIdImpl(Sym);
1766
0
}
1767
1768
0
uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
1769
0
  switch (Sym.Info.Kind) {
1770
0
  case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1771
0
    return CodeSection;
1772
0
  case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1773
0
    return GlobalSection;
1774
0
  case wasm::WASM_SYMBOL_TYPE_DATA:
1775
0
    return DataSection;
1776
0
  case wasm::WASM_SYMBOL_TYPE_SECTION:
1777
0
    return Sym.Info.ElementIndex;
1778
0
  case wasm::WASM_SYMBOL_TYPE_TAG:
1779
0
    return TagSection;
1780
0
  case wasm::WASM_SYMBOL_TYPE_TABLE:
1781
0
    return TableSection;
1782
0
  default:
1783
0
    llvm_unreachable("unknown WasmSymbol::SymbolType");
1784
0
  }
1785
0
}
1786
1787
0
void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1788
1789
0
Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
1790
0
  const WasmSection &S = Sections[Sec.d.a];
1791
0
  if (S.Type == wasm::WASM_SEC_CUSTOM)
1792
0
    return S.Name;
1793
0
  if (S.Type > wasm::WASM_SEC_LAST_KNOWN)
1794
0
    return createStringError(object_error::invalid_section_index, "");
1795
0
  return wasm::sectionTypeToString(S.Type);
1796
0
}
1797
1798
0
uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1799
1800
0
uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1801
0
  return Sec.d.a;
1802
0
}
1803
1804
0
uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1805
0
  const WasmSection &S = Sections[Sec.d.a];
1806
0
  return S.Content.size();
1807
0
}
1808
1809
Expected<ArrayRef<uint8_t>>
1810
0
WasmObjectFile::getSectionContents(DataRefImpl Sec) const {
1811
0
  const WasmSection &S = Sections[Sec.d.a];
1812
  // This will never fail since wasm sections can never be empty (user-sections
1813
  // must have a name and non-user sections each have a defined structure).
1814
0
  return S.Content;
1815
0
}
1816
1817
0
uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1818
0
  return 1;
1819
0
}
1820
1821
0
bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1822
0
  return false;
1823
0
}
1824
1825
0
bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
1826
0
  return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1827
0
}
1828
1829
0
bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
1830
0
  return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1831
0
}
1832
1833
0
bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1834
1835
0
bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1836
1837
0
relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1838
0
  DataRefImpl RelocRef;
1839
0
  RelocRef.d.a = Ref.d.a;
1840
0
  RelocRef.d.b = 0;
1841
0
  return relocation_iterator(RelocationRef(RelocRef, this));
1842
0
}
1843
1844
0
relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1845
0
  const WasmSection &Sec = getWasmSection(Ref);
1846
0
  DataRefImpl RelocRef;
1847
0
  RelocRef.d.a = Ref.d.a;
1848
0
  RelocRef.d.b = Sec.Relocations.size();
1849
0
  return relocation_iterator(RelocationRef(RelocRef, this));
1850
0
}
1851
1852
0
void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
1853
1854
0
uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1855
0
  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1856
0
  return Rel.Offset;
1857
0
}
1858
1859
0
symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
1860
0
  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1861
0
  if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
1862
0
    return symbol_end();
1863
0
  DataRefImpl Sym;
1864
0
  Sym.d.a = 1;
1865
0
  Sym.d.b = Rel.Index;
1866
0
  return symbol_iterator(SymbolRef(Sym, this));
1867
0
}
1868
1869
0
uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1870
0
  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1871
0
  return Rel.Type;
1872
0
}
1873
1874
void WasmObjectFile::getRelocationTypeName(
1875
0
    DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1876
0
  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1877
0
  StringRef Res = "Unknown";
1878
1879
0
#define WASM_RELOC(name, value)                                                \
1880
0
  case wasm::name:                                                             \
1881
0
    Res = #name;                                                               \
1882
0
    break;
1883
1884
0
  switch (Rel.Type) {
1885
0
#include "llvm/BinaryFormat/WasmRelocs.def"
1886
0
  }
1887
1888
0
#undef WASM_RELOC
1889
1890
0
  Result.append(Res.begin(), Res.end());
1891
0
}
1892
1893
0
section_iterator WasmObjectFile::section_begin() const {
1894
0
  DataRefImpl Ref;
1895
0
  Ref.d.a = 0;
1896
0
  return section_iterator(SectionRef(Ref, this));
1897
0
}
1898
1899
0
section_iterator WasmObjectFile::section_end() const {
1900
0
  DataRefImpl Ref;
1901
0
  Ref.d.a = Sections.size();
1902
0
  return section_iterator(SectionRef(Ref, this));
1903
0
}
1904
1905
0
uint8_t WasmObjectFile::getBytesInAddress() const {
1906
0
  return HasMemory64 ? 8 : 4;
1907
0
}
1908
1909
0
StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1910
1911
0
Triple::ArchType WasmObjectFile::getArch() const {
1912
0
  return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
1913
0
}
1914
1915
0
Expected<SubtargetFeatures> WasmObjectFile::getFeatures() const {
1916
0
  return SubtargetFeatures();
1917
0
}
1918
1919
0
bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1920
1921
0
bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
1922
1923
0
const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
1924
0
  assert(Ref.d.a < Sections.size());
1925
0
  return Sections[Ref.d.a];
1926
0
}
1927
1928
const WasmSection &
1929
0
WasmObjectFile::getWasmSection(const SectionRef &Section) const {
1930
0
  return getWasmSection(Section.getRawDataRefImpl());
1931
0
}
1932
1933
const wasm::WasmRelocation &
1934
0
WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1935
0
  return getWasmRelocation(Ref.getRawDataRefImpl());
1936
0
}
1937
1938
const wasm::WasmRelocation &
1939
0
WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
1940
0
  assert(Ref.d.a < Sections.size());
1941
0
  const WasmSection &Sec = Sections[Ref.d.a];
1942
0
  assert(Ref.d.b < Sec.Relocations.size());
1943
0
  return Sec.Relocations[Ref.d.b];
1944
0
}
1945
1946
int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1947
0
                                             StringRef CustomSectionName) {
1948
0
  switch (ID) {
1949
0
  case wasm::WASM_SEC_CUSTOM:
1950
0
    return StringSwitch<unsigned>(CustomSectionName)
1951
0
        .Case("dylink", WASM_SEC_ORDER_DYLINK)
1952
0
        .Case("dylink.0", WASM_SEC_ORDER_DYLINK)
1953
0
        .Case("linking", WASM_SEC_ORDER_LINKING)
1954
0
        .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
1955
0
        .Case("name", WASM_SEC_ORDER_NAME)
1956
0
        .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1957
0
        .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
1958
0
        .Default(WASM_SEC_ORDER_NONE);
1959
0
  case wasm::WASM_SEC_TYPE:
1960
0
    return WASM_SEC_ORDER_TYPE;
1961
0
  case wasm::WASM_SEC_IMPORT:
1962
0
    return WASM_SEC_ORDER_IMPORT;
1963
0
  case wasm::WASM_SEC_FUNCTION:
1964
0
    return WASM_SEC_ORDER_FUNCTION;
1965
0
  case wasm::WASM_SEC_TABLE:
1966
0
    return WASM_SEC_ORDER_TABLE;
1967
0
  case wasm::WASM_SEC_MEMORY:
1968
0
    return WASM_SEC_ORDER_MEMORY;
1969
0
  case wasm::WASM_SEC_GLOBAL:
1970
0
    return WASM_SEC_ORDER_GLOBAL;
1971
0
  case wasm::WASM_SEC_EXPORT:
1972
0
    return WASM_SEC_ORDER_EXPORT;
1973
0
  case wasm::WASM_SEC_START:
1974
0
    return WASM_SEC_ORDER_START;
1975
0
  case wasm::WASM_SEC_ELEM:
1976
0
    return WASM_SEC_ORDER_ELEM;
1977
0
  case wasm::WASM_SEC_CODE:
1978
0
    return WASM_SEC_ORDER_CODE;
1979
0
  case wasm::WASM_SEC_DATA:
1980
0
    return WASM_SEC_ORDER_DATA;
1981
0
  case wasm::WASM_SEC_DATACOUNT:
1982
0
    return WASM_SEC_ORDER_DATACOUNT;
1983
0
  case wasm::WASM_SEC_TAG:
1984
0
    return WASM_SEC_ORDER_TAG;
1985
0
  default:
1986
0
    return WASM_SEC_ORDER_NONE;
1987
0
  }
1988
0
}
1989
1990
// Represents the edges in a directed graph where any node B reachable from node
1991
// A is not allowed to appear before A in the section ordering, but may appear
1992
// afterward.
1993
int WasmSectionOrderChecker::DisallowedPredecessors
1994
    [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
1995
        // WASM_SEC_ORDER_NONE
1996
        {},
1997
        // WASM_SEC_ORDER_TYPE
1998
        {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
1999
        // WASM_SEC_ORDER_IMPORT
2000
        {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
2001
        // WASM_SEC_ORDER_FUNCTION
2002
        {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
2003
        // WASM_SEC_ORDER_TABLE
2004
        {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
2005
        // WASM_SEC_ORDER_MEMORY
2006
        {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2007
        // WASM_SEC_ORDER_TAG
2008
        {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
2009
        // WASM_SEC_ORDER_GLOBAL
2010
        {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
2011
        // WASM_SEC_ORDER_EXPORT
2012
        {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
2013
        // WASM_SEC_ORDER_START
2014
        {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2015
        // WASM_SEC_ORDER_ELEM
2016
        {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2017
        // WASM_SEC_ORDER_DATACOUNT
2018
        {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2019
        // WASM_SEC_ORDER_CODE
2020
        {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2021
        // WASM_SEC_ORDER_DATA
2022
        {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2023
2024
        // Custom Sections
2025
        // WASM_SEC_ORDER_DYLINK
2026
        {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2027
        // WASM_SEC_ORDER_LINKING
2028
        {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2029
        // WASM_SEC_ORDER_RELOC (can be repeated)
2030
        {},
2031
        // WASM_SEC_ORDER_NAME
2032
        {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2033
        // WASM_SEC_ORDER_PRODUCERS
2034
        {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2035
        // WASM_SEC_ORDER_TARGET_FEATURES
2036
        {WASM_SEC_ORDER_TARGET_FEATURES}};
2037
2038
bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
2039
0
                                                  StringRef CustomSectionName) {
2040
0
  int Order = getSectionOrder(ID, CustomSectionName);
2041
0
  if (Order == WASM_SEC_ORDER_NONE)
2042
0
    return true;
2043
2044
  // Disallowed predecessors we need to check for
2045
0
  SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
2046
2047
  // Keep track of completed checks to avoid repeating work
2048
0
  bool Checked[WASM_NUM_SEC_ORDERS] = {};
2049
2050
0
  int Curr = Order;
2051
0
  while (true) {
2052
    // Add new disallowed predecessors to work list
2053
0
    for (size_t I = 0;; ++I) {
2054
0
      int Next = DisallowedPredecessors[Curr][I];
2055
0
      if (Next == WASM_SEC_ORDER_NONE)
2056
0
        break;
2057
0
      if (Checked[Next])
2058
0
        continue;
2059
0
      WorkList.push_back(Next);
2060
0
      Checked[Next] = true;
2061
0
    }
2062
2063
0
    if (WorkList.empty())
2064
0
      break;
2065
2066
    // Consider next disallowed predecessor
2067
0
    Curr = WorkList.pop_back_val();
2068
0
    if (Seen[Curr])
2069
0
      return false;
2070
0
  }
2071
2072
  // Have not seen any disallowed predecessors
2073
0
  Seen[Order] = true;
2074
0
  return true;
2075
0
}