llvm-project

Форк
0
/
WasmObjectFile.cpp 
2255 строк · 79.8 Кб
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/Format.h"
25
#include "llvm/Support/LEB128.h"
26
#include "llvm/Support/ScopedPrinter.h"
27
#include "llvm/TargetParser/SubtargetFeature.h"
28
#include "llvm/TargetParser/Triple.h"
29
#include <algorithm>
30
#include <cassert>
31
#include <cstdint>
32
#include <cstring>
33
#include <limits>
34

35
#define DEBUG_TYPE "wasm-object"
36

37
using namespace llvm;
38
using namespace object;
39

40
void WasmSymbol::print(raw_ostream &Out) const {
41
  Out << "Name=" << Info.Name
42
      << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"
43
      << Twine::utohexstr(Info.Flags) << " [";
44
  switch (getBinding()) {
45
    case wasm::WASM_SYMBOL_BINDING_GLOBAL: Out << "global"; break;
46
    case wasm::WASM_SYMBOL_BINDING_LOCAL: Out << "local"; break;
47
    case wasm::WASM_SYMBOL_BINDING_WEAK: Out << "weak"; break;
48
  }
49
  if (isHidden()) {
50
    Out << ", hidden";
51
  } else {
52
    Out << ", default";
53
  }
54
  Out << "]";
55
  if (!isTypeData()) {
56
    Out << ", ElemIndex=" << Info.ElementIndex;
57
  } else if (isDefined()) {
58
    Out << ", Segment=" << Info.DataRef.Segment;
59
    Out << ", Offset=" << Info.DataRef.Offset;
60
    Out << ", Size=" << Info.DataRef.Size;
61
  }
62
}
63

64
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
65
LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
66
#endif
67

68
Expected<std::unique_ptr<WasmObjectFile>>
69
ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
70
  Error Err = Error::success();
71
  auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
72
  if (Err)
73
    return std::move(Err);
74

75
  return std::move(ObjectFile);
76
}
77

78
#define VARINT7_MAX ((1 << 7) - 1)
79
#define VARINT7_MIN (-(1 << 7))
80
#define VARUINT7_MAX (1 << 7)
81
#define VARUINT1_MAX (1)
82

83
static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
84
  if (Ctx.Ptr == Ctx.End)
85
    report_fatal_error("EOF while reading uint8");
86
  return *Ctx.Ptr++;
87
}
88

89
static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
90
  if (Ctx.Ptr + 4 > Ctx.End)
91
    report_fatal_error("EOF while reading uint32");
92
  uint32_t Result = support::endian::read32le(Ctx.Ptr);
93
  Ctx.Ptr += 4;
94
  return Result;
95
}
96

97
static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
98
  if (Ctx.Ptr + 4 > Ctx.End)
99
    report_fatal_error("EOF while reading float64");
100
  int32_t Result = 0;
101
  memcpy(&Result, Ctx.Ptr, sizeof(Result));
102
  Ctx.Ptr += sizeof(Result);
103
  return Result;
104
}
105

106
static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
107
  if (Ctx.Ptr + 8 > Ctx.End)
108
    report_fatal_error("EOF while reading float64");
109
  int64_t Result = 0;
110
  memcpy(&Result, Ctx.Ptr, sizeof(Result));
111
  Ctx.Ptr += sizeof(Result);
112
  return Result;
113
}
114

115
static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
116
  unsigned Count;
117
  const char *Error = nullptr;
118
  uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
119
  if (Error)
120
    report_fatal_error(Error);
121
  Ctx.Ptr += Count;
122
  return Result;
123
}
124

125
static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
126
  uint32_t StringLen = readULEB128(Ctx);
127
  if (Ctx.Ptr + StringLen > Ctx.End)
128
    report_fatal_error("EOF while reading string");
129
  StringRef Return =
130
      StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
131
  Ctx.Ptr += StringLen;
132
  return Return;
133
}
134

135
static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
136
  unsigned Count;
137
  const char *Error = nullptr;
138
  uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
139
  if (Error)
140
    report_fatal_error(Error);
141
  Ctx.Ptr += Count;
142
  return Result;
143
}
144

145
static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
146
  int64_t Result = readLEB128(Ctx);
147
  if (Result > VARUINT1_MAX || Result < 0)
148
    report_fatal_error("LEB is outside Varuint1 range");
149
  return Result;
150
}
151

152
static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
153
  int64_t Result = readLEB128(Ctx);
154
  if (Result > INT32_MAX || Result < INT32_MIN)
155
    report_fatal_error("LEB is outside Varint32 range");
156
  return Result;
157
}
158

159
static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
160
  uint64_t Result = readULEB128(Ctx);
161
  if (Result > UINT32_MAX)
162
    report_fatal_error("LEB is outside Varuint32 range");
163
  return Result;
164
}
165

166
static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
167
  return readLEB128(Ctx);
168
}
169

170
static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) {
171
  return readULEB128(Ctx);
172
}
173

174
static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
175
  return readUint8(Ctx);
176
}
177

178
static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx,
179
                                  uint32_t Code) {
180
  // only directly encoded FUNCREF/EXTERNREF/EXNREF are supported
181
  // (not ref null func, ref null extern, or ref null exn)
182
  switch (Code) {
183
  case wasm::WASM_TYPE_I32:
184
  case wasm::WASM_TYPE_I64:
185
  case wasm::WASM_TYPE_F32:
186
  case wasm::WASM_TYPE_F64:
187
  case wasm::WASM_TYPE_V128:
188
  case wasm::WASM_TYPE_FUNCREF:
189
  case wasm::WASM_TYPE_EXTERNREF:
190
  case wasm::WASM_TYPE_EXNREF:
191
    return wasm::ValType(Code);
192
  }
193
  if (Code == wasm::WASM_TYPE_NULLABLE || Code == wasm::WASM_TYPE_NONNULLABLE) {
194
    /* Discard HeapType */ readVarint64(Ctx);
195
  }
196
  return wasm::ValType(wasm::ValType::OTHERREF);
197
}
198

199
static Error readInitExpr(wasm::WasmInitExpr &Expr,
200
                          WasmObjectFile::ReadContext &Ctx) {
201
  auto Start = Ctx.Ptr;
202

203
  Expr.Extended = false;
204
  Expr.Inst.Opcode = readOpcode(Ctx);
205
  switch (Expr.Inst.Opcode) {
206
  case wasm::WASM_OPCODE_I32_CONST:
207
    Expr.Inst.Value.Int32 = readVarint32(Ctx);
208
    break;
209
  case wasm::WASM_OPCODE_I64_CONST:
210
    Expr.Inst.Value.Int64 = readVarint64(Ctx);
211
    break;
212
  case wasm::WASM_OPCODE_F32_CONST:
213
    Expr.Inst.Value.Float32 = readFloat32(Ctx);
214
    break;
215
  case wasm::WASM_OPCODE_F64_CONST:
216
    Expr.Inst.Value.Float64 = readFloat64(Ctx);
217
    break;
218
  case wasm::WASM_OPCODE_GLOBAL_GET:
219
    Expr.Inst.Value.Global = readULEB128(Ctx);
220
    break;
221
  case wasm::WASM_OPCODE_REF_NULL: {
222
    /* Discard type */ parseValType(Ctx, readVaruint32(Ctx));
223
    break;
224
  }
225
  default:
226
    Expr.Extended = true;
227
  }
228

229
  if (!Expr.Extended) {
230
    uint8_t EndOpcode = readOpcode(Ctx);
231
    if (EndOpcode != wasm::WASM_OPCODE_END)
232
      Expr.Extended = true;
233
  }
234

235
  if (Expr.Extended) {
236
    Ctx.Ptr = Start;
237
    while (true) {
238
      uint8_t Opcode = readOpcode(Ctx);
239
      switch (Opcode) {
240
      case wasm::WASM_OPCODE_I32_CONST:
241
      case wasm::WASM_OPCODE_GLOBAL_GET:
242
      case wasm::WASM_OPCODE_REF_NULL:
243
      case wasm::WASM_OPCODE_REF_FUNC:
244
      case wasm::WASM_OPCODE_I64_CONST:
245
        readULEB128(Ctx);
246
        break;
247
      case wasm::WASM_OPCODE_F32_CONST:
248
        readFloat32(Ctx);
249
        break;
250
      case wasm::WASM_OPCODE_F64_CONST:
251
        readFloat64(Ctx);
252
        break;
253
      case wasm::WASM_OPCODE_I32_ADD:
254
      case wasm::WASM_OPCODE_I32_SUB:
255
      case wasm::WASM_OPCODE_I32_MUL:
256
      case wasm::WASM_OPCODE_I64_ADD:
257
      case wasm::WASM_OPCODE_I64_SUB:
258
      case wasm::WASM_OPCODE_I64_MUL:
259
        break;
260
      case wasm::WASM_OPCODE_GC_PREFIX:
261
        break;
262
      // The GC opcodes are in a separate (prefixed space). This flat switch
263
      // structure works as long as there is no overlap between the GC and
264
      // general opcodes used in init exprs.
265
      case wasm::WASM_OPCODE_STRUCT_NEW:
266
      case wasm::WASM_OPCODE_STRUCT_NEW_DEFAULT:
267
      case wasm::WASM_OPCODE_ARRAY_NEW:
268
      case wasm::WASM_OPCODE_ARRAY_NEW_DEFAULT:
269
        readULEB128(Ctx); // heap type index
270
        break;
271
      case wasm::WASM_OPCODE_ARRAY_NEW_FIXED:
272
        readULEB128(Ctx); // heap type index
273
        readULEB128(Ctx); // array size
274
        break;
275
      case wasm::WASM_OPCODE_REF_I31:
276
        break;
277
      case wasm::WASM_OPCODE_END:
278
        Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start);
279
        return Error::success();
280
      default:
281
        return make_error<GenericBinaryError>(
282
            Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode)),
283
            object_error::parse_failed);
284
      }
285
    }
286
  }
287

288
  return Error::success();
289
}
290

291
static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
292
  wasm::WasmLimits Result;
293
  Result.Flags = readVaruint32(Ctx);
294
  Result.Minimum = readVaruint64(Ctx);
295
  if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
296
    Result.Maximum = readVaruint64(Ctx);
297
  return Result;
298
}
299

300
static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) {
301
  wasm::WasmTableType TableType;
302
  auto ElemType = parseValType(Ctx, readVaruint32(Ctx));
303
  TableType.ElemType = ElemType;
304
  TableType.Limits = readLimits(Ctx);
305
  return TableType;
306
}
307

308
static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
309
                         WasmSectionOrderChecker &Checker) {
310
  Section.Type = readUint8(Ctx);
311
  LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
312
  // When reading the section's size, store the size of the LEB used to encode
313
  // it. This allows objcopy/strip to reproduce the binary identically.
314
  const uint8_t *PreSizePtr = Ctx.Ptr;
315
  uint32_t Size = readVaruint32(Ctx);
316
  Section.HeaderSecSizeEncodingLen = Ctx.Ptr - PreSizePtr;
317
  Section.Offset = Ctx.Ptr - Ctx.Start;
318
  if (Size == 0)
319
    return make_error<StringError>("zero length section",
320
                                   object_error::parse_failed);
321
  if (Ctx.Ptr + Size > Ctx.End)
322
    return make_error<StringError>("section too large",
323
                                   object_error::parse_failed);
324
  if (Section.Type == wasm::WASM_SEC_CUSTOM) {
325
    WasmObjectFile::ReadContext SectionCtx;
326
    SectionCtx.Start = Ctx.Ptr;
327
    SectionCtx.Ptr = Ctx.Ptr;
328
    SectionCtx.End = Ctx.Ptr + Size;
329

330
    Section.Name = readString(SectionCtx);
331

332
    uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
333
    Ctx.Ptr += SectionNameSize;
334
    Size -= SectionNameSize;
335
  }
336

337
  if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
338
    return make_error<StringError>("out of order section type: " +
339
                                       llvm::to_string(Section.Type),
340
                                   object_error::parse_failed);
341
  }
342

343
  Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
344
  Ctx.Ptr += Size;
345
  return Error::success();
346
}
347

348
WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
349
    : ObjectFile(Binary::ID_Wasm, Buffer) {
350
  ErrorAsOutParameter ErrAsOutParam(&Err);
351
  Header.Magic = getData().substr(0, 4);
352
  if (Header.Magic != StringRef("\0asm", 4)) {
353
    Err = make_error<StringError>("invalid magic number",
354
                                  object_error::parse_failed);
355
    return;
356
  }
357

358
  ReadContext Ctx;
359
  Ctx.Start = getData().bytes_begin();
360
  Ctx.Ptr = Ctx.Start + 4;
361
  Ctx.End = Ctx.Start + getData().size();
362

363
  if (Ctx.Ptr + 4 > Ctx.End) {
364
    Err = make_error<StringError>("missing version number",
365
                                  object_error::parse_failed);
366
    return;
367
  }
368

369
  Header.Version = readUint32(Ctx);
370
  if (Header.Version != wasm::WasmVersion) {
371
    Err = make_error<StringError>("invalid version number: " +
372
                                      Twine(Header.Version),
373
                                  object_error::parse_failed);
374
    return;
375
  }
376

377
  WasmSectionOrderChecker Checker;
378
  while (Ctx.Ptr < Ctx.End) {
379
    WasmSection Sec;
380
    if ((Err = readSection(Sec, Ctx, Checker)))
381
      return;
382
    if ((Err = parseSection(Sec)))
383
      return;
384

385
    Sections.push_back(Sec);
386
  }
387
}
388

389
Error WasmObjectFile::parseSection(WasmSection &Sec) {
390
  ReadContext Ctx;
391
  Ctx.Start = Sec.Content.data();
392
  Ctx.End = Ctx.Start + Sec.Content.size();
393
  Ctx.Ptr = Ctx.Start;
394
  switch (Sec.Type) {
395
  case wasm::WASM_SEC_CUSTOM:
396
    return parseCustomSection(Sec, Ctx);
397
  case wasm::WASM_SEC_TYPE:
398
    return parseTypeSection(Ctx);
399
  case wasm::WASM_SEC_IMPORT:
400
    return parseImportSection(Ctx);
401
  case wasm::WASM_SEC_FUNCTION:
402
    return parseFunctionSection(Ctx);
403
  case wasm::WASM_SEC_TABLE:
404
    return parseTableSection(Ctx);
405
  case wasm::WASM_SEC_MEMORY:
406
    return parseMemorySection(Ctx);
407
  case wasm::WASM_SEC_TAG:
408
    return parseTagSection(Ctx);
409
  case wasm::WASM_SEC_GLOBAL:
410
    return parseGlobalSection(Ctx);
411
  case wasm::WASM_SEC_EXPORT:
412
    return parseExportSection(Ctx);
413
  case wasm::WASM_SEC_START:
414
    return parseStartSection(Ctx);
415
  case wasm::WASM_SEC_ELEM:
416
    return parseElemSection(Ctx);
417
  case wasm::WASM_SEC_CODE:
418
    return parseCodeSection(Ctx);
419
  case wasm::WASM_SEC_DATA:
420
    return parseDataSection(Ctx);
421
  case wasm::WASM_SEC_DATACOUNT:
422
    return parseDataCountSection(Ctx);
423
  default:
424
    return make_error<GenericBinaryError>(
425
        "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
426
  }
427
}
428

429
Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
430
  // Legacy "dylink" section support.
431
  // See parseDylink0Section for the current "dylink.0" section parsing.
432
  HasDylinkSection = true;
433
  DylinkInfo.MemorySize = readVaruint32(Ctx);
434
  DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
435
  DylinkInfo.TableSize = readVaruint32(Ctx);
436
  DylinkInfo.TableAlignment = readVaruint32(Ctx);
437
  uint32_t Count = readVaruint32(Ctx);
438
  while (Count--) {
439
    DylinkInfo.Needed.push_back(readString(Ctx));
440
  }
441

442
  if (Ctx.Ptr != Ctx.End)
443
    return make_error<GenericBinaryError>("dylink section ended prematurely",
444
                                          object_error::parse_failed);
445
  return Error::success();
446
}
447

448
Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
449
  // See
450
  // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
451
  HasDylinkSection = true;
452

453
  const uint8_t *OrigEnd = Ctx.End;
454
  while (Ctx.Ptr < OrigEnd) {
455
    Ctx.End = OrigEnd;
456
    uint8_t Type = readUint8(Ctx);
457
    uint32_t Size = readVaruint32(Ctx);
458
    LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
459
                      << "\n");
460
    Ctx.End = Ctx.Ptr + Size;
461
    uint32_t Count;
462
    switch (Type) {
463
    case wasm::WASM_DYLINK_MEM_INFO:
464
      DylinkInfo.MemorySize = readVaruint32(Ctx);
465
      DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
466
      DylinkInfo.TableSize = readVaruint32(Ctx);
467
      DylinkInfo.TableAlignment = readVaruint32(Ctx);
468
      break;
469
    case wasm::WASM_DYLINK_NEEDED:
470
      Count = readVaruint32(Ctx);
471
      while (Count--) {
472
        DylinkInfo.Needed.push_back(readString(Ctx));
473
      }
474
      break;
475
    case wasm::WASM_DYLINK_EXPORT_INFO: {
476
      uint32_t Count = readVaruint32(Ctx);
477
      while (Count--) {
478
        DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)});
479
      }
480
      break;
481
    }
482
    case wasm::WASM_DYLINK_IMPORT_INFO: {
483
      uint32_t Count = readVaruint32(Ctx);
484
      while (Count--) {
485
        DylinkInfo.ImportInfo.push_back(
486
            {readString(Ctx), readString(Ctx), readVaruint32(Ctx)});
487
      }
488
      break;
489
    }
490
    default:
491
      LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n");
492
      Ctx.Ptr += Size;
493
      break;
494
    }
495
    if (Ctx.Ptr != Ctx.End) {
496
      return make_error<GenericBinaryError>(
497
          "dylink.0 sub-section ended prematurely", object_error::parse_failed);
498
    }
499
  }
500

501
  if (Ctx.Ptr != Ctx.End)
502
    return make_error<GenericBinaryError>("dylink.0 section ended prematurely",
503
                                          object_error::parse_failed);
504
  return Error::success();
505
}
506

507
Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
508
  llvm::DenseSet<uint64_t> SeenFunctions;
509
  llvm::DenseSet<uint64_t> SeenGlobals;
510
  llvm::DenseSet<uint64_t> SeenSegments;
511

512
  // If there is symbol info from the export section, this info will supersede
513
  // it, but not info from a linking section
514
  if (!HasLinkingSection) {
515
    Symbols.clear();
516
  }
517

518
  while (Ctx.Ptr < Ctx.End) {
519
    uint8_t Type = readUint8(Ctx);
520
    uint32_t Size = readVaruint32(Ctx);
521
    const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
522

523
    switch (Type) {
524
    case wasm::WASM_NAMES_FUNCTION:
525
    case wasm::WASM_NAMES_GLOBAL:
526
    case wasm::WASM_NAMES_DATA_SEGMENT: {
527
      uint32_t Count = readVaruint32(Ctx);
528
      while (Count--) {
529
        uint32_t Index = readVaruint32(Ctx);
530
        StringRef Name = readString(Ctx);
531
        wasm::NameType nameType = wasm::NameType::FUNCTION;
532
        wasm::WasmSymbolInfo Info{Name,
533
                                  /*Kind */ wasm::WASM_SYMBOL_TYPE_FUNCTION,
534
                                  /* Flags */ 0,
535
                                  /* ImportModule */ std::nullopt,
536
                                  /* ImportName */ std::nullopt,
537
                                  /* ExportName */ std::nullopt,
538
                                  {/* ElementIndex */ Index}};
539
        const wasm::WasmSignature *Signature = nullptr;
540
        const wasm::WasmGlobalType *GlobalType = nullptr;
541
        const wasm::WasmTableType *TableType = nullptr;
542
        if (Type == wasm::WASM_NAMES_FUNCTION) {
543
          if (!SeenFunctions.insert(Index).second)
544
            return make_error<GenericBinaryError>(
545
                "function named more than once", object_error::parse_failed);
546
          if (!isValidFunctionIndex(Index) || Name.empty())
547
            return make_error<GenericBinaryError>("invalid function name entry",
548
                                                  object_error::parse_failed);
549

550
          if (isDefinedFunctionIndex(Index)) {
551
            wasm::WasmFunction &F = getDefinedFunction(Index);
552
            F.DebugName = Name;
553
            Signature = &Signatures[F.SigIndex];
554
            if (F.ExportName) {
555
              Info.ExportName = F.ExportName;
556
              Info.Flags |= wasm::WASM_SYMBOL_BINDING_GLOBAL;
557
            } else {
558
              Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
559
            }
560
          } else {
561
            Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED;
562
          }
563
        } else if (Type == wasm::WASM_NAMES_GLOBAL) {
564
          if (!SeenGlobals.insert(Index).second)
565
            return make_error<GenericBinaryError>("global named more than once",
566
                                                  object_error::parse_failed);
567
          if (!isValidGlobalIndex(Index) || Name.empty())
568
            return make_error<GenericBinaryError>("invalid global name entry",
569
                                                  object_error::parse_failed);
570
          nameType = wasm::NameType::GLOBAL;
571
          Info.Kind = wasm::WASM_SYMBOL_TYPE_GLOBAL;
572
          if (isDefinedGlobalIndex(Index)) {
573
            GlobalType = &getDefinedGlobal(Index).Type;
574
          } else {
575
            Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED;
576
          }
577
        } else {
578
          if (!SeenSegments.insert(Index).second)
579
            return make_error<GenericBinaryError>(
580
                "segment named more than once", object_error::parse_failed);
581
          if (Index > DataSegments.size())
582
            return make_error<GenericBinaryError>("invalid data segment name entry",
583
                                                  object_error::parse_failed);
584
          nameType = wasm::NameType::DATA_SEGMENT;
585
          Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA;
586
          Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
587
          assert(Index < DataSegments.size());
588
          Info.DataRef = wasm::WasmDataReference{
589
              Index, 0, DataSegments[Index].Data.Content.size()};
590
        }
591
        DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
592
        if (!HasLinkingSection)
593
          Symbols.emplace_back(Info, GlobalType, TableType, Signature);
594
      }
595
      break;
596
    }
597
    // Ignore local names for now
598
    case wasm::WASM_NAMES_LOCAL:
599
    default:
600
      Ctx.Ptr += Size;
601
      break;
602
    }
603
    if (Ctx.Ptr != SubSectionEnd)
604
      return make_error<GenericBinaryError>(
605
          "name sub-section ended prematurely", object_error::parse_failed);
606
  }
607

608
  if (Ctx.Ptr != Ctx.End)
609
    return make_error<GenericBinaryError>("name section ended prematurely",
610
                                          object_error::parse_failed);
611
  return Error::success();
612
}
613

614
Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
615
  HasLinkingSection = true;
616

617
  LinkingData.Version = readVaruint32(Ctx);
618
  if (LinkingData.Version != wasm::WasmMetadataVersion) {
619
    return make_error<GenericBinaryError>(
620
        "unexpected metadata version: " + Twine(LinkingData.Version) +
621
            " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
622
        object_error::parse_failed);
623
  }
624

625
  const uint8_t *OrigEnd = Ctx.End;
626
  while (Ctx.Ptr < OrigEnd) {
627
    Ctx.End = OrigEnd;
628
    uint8_t Type = readUint8(Ctx);
629
    uint32_t Size = readVaruint32(Ctx);
630
    LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
631
                      << "\n");
632
    Ctx.End = Ctx.Ptr + Size;
633
    switch (Type) {
634
    case wasm::WASM_SYMBOL_TABLE:
635
      if (Error Err = parseLinkingSectionSymtab(Ctx))
636
        return Err;
637
      break;
638
    case wasm::WASM_SEGMENT_INFO: {
639
      uint32_t Count = readVaruint32(Ctx);
640
      if (Count > DataSegments.size())
641
        return make_error<GenericBinaryError>("too many segment names",
642
                                              object_error::parse_failed);
643
      for (uint32_t I = 0; I < Count; I++) {
644
        DataSegments[I].Data.Name = readString(Ctx);
645
        DataSegments[I].Data.Alignment = readVaruint32(Ctx);
646
        DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);
647
      }
648
      break;
649
    }
650
    case wasm::WASM_INIT_FUNCS: {
651
      uint32_t Count = readVaruint32(Ctx);
652
      LinkingData.InitFunctions.reserve(Count);
653
      for (uint32_t I = 0; I < Count; I++) {
654
        wasm::WasmInitFunc Init;
655
        Init.Priority = readVaruint32(Ctx);
656
        Init.Symbol = readVaruint32(Ctx);
657
        if (!isValidFunctionSymbol(Init.Symbol))
658
          return make_error<GenericBinaryError>("invalid function symbol: " +
659
                                                    Twine(Init.Symbol),
660
                                                object_error::parse_failed);
661
        LinkingData.InitFunctions.emplace_back(Init);
662
      }
663
      break;
664
    }
665
    case wasm::WASM_COMDAT_INFO:
666
      if (Error Err = parseLinkingSectionComdat(Ctx))
667
        return Err;
668
      break;
669
    default:
670
      Ctx.Ptr += Size;
671
      break;
672
    }
673
    if (Ctx.Ptr != Ctx.End)
674
      return make_error<GenericBinaryError>(
675
          "linking sub-section ended prematurely", object_error::parse_failed);
676
  }
677
  if (Ctx.Ptr != OrigEnd)
678
    return make_error<GenericBinaryError>("linking section ended prematurely",
679
                                          object_error::parse_failed);
680
  return Error::success();
681
}
682

683
Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
684
  uint32_t Count = readVaruint32(Ctx);
685
  // Clear out any symbol information that was derived from the exports
686
  // section.
687
  Symbols.clear();
688
  Symbols.reserve(Count);
689
  StringSet<> SymbolNames;
690

691
  std::vector<wasm::WasmImport *> ImportedGlobals;
692
  std::vector<wasm::WasmImport *> ImportedFunctions;
693
  std::vector<wasm::WasmImport *> ImportedTags;
694
  std::vector<wasm::WasmImport *> ImportedTables;
695
  ImportedGlobals.reserve(Imports.size());
696
  ImportedFunctions.reserve(Imports.size());
697
  ImportedTags.reserve(Imports.size());
698
  ImportedTables.reserve(Imports.size());
699
  for (auto &I : Imports) {
700
    if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
701
      ImportedFunctions.emplace_back(&I);
702
    else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
703
      ImportedGlobals.emplace_back(&I);
704
    else if (I.Kind == wasm::WASM_EXTERNAL_TAG)
705
      ImportedTags.emplace_back(&I);
706
    else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
707
      ImportedTables.emplace_back(&I);
708
  }
709

710
  while (Count--) {
711
    wasm::WasmSymbolInfo Info;
712
    const wasm::WasmSignature *Signature = nullptr;
713
    const wasm::WasmGlobalType *GlobalType = nullptr;
714
    const wasm::WasmTableType *TableType = nullptr;
715

716
    Info.Kind = readUint8(Ctx);
717
    Info.Flags = readVaruint32(Ctx);
718
    bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
719

720
    switch (Info.Kind) {
721
    case wasm::WASM_SYMBOL_TYPE_FUNCTION:
722
      Info.ElementIndex = readVaruint32(Ctx);
723
      if (!isValidFunctionIndex(Info.ElementIndex) ||
724
          IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
725
        return make_error<GenericBinaryError>("invalid function symbol index",
726
                                              object_error::parse_failed);
727
      if (IsDefined) {
728
        Info.Name = readString(Ctx);
729
        unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
730
        wasm::WasmFunction &Function = Functions[FuncIndex];
731
        Signature = &Signatures[Function.SigIndex];
732
        if (Function.SymbolName.empty())
733
          Function.SymbolName = Info.Name;
734
      } else {
735
        wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
736
        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
737
          Info.Name = readString(Ctx);
738
          Info.ImportName = Import.Field;
739
        } else {
740
          Info.Name = Import.Field;
741
        }
742
        Signature = &Signatures[Import.SigIndex];
743
        Info.ImportModule = Import.Module;
744
      }
745
      break;
746

747
    case wasm::WASM_SYMBOL_TYPE_GLOBAL:
748
      Info.ElementIndex = readVaruint32(Ctx);
749
      if (!isValidGlobalIndex(Info.ElementIndex) ||
750
          IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
751
        return make_error<GenericBinaryError>("invalid global symbol index",
752
                                              object_error::parse_failed);
753
      if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
754
                            wasm::WASM_SYMBOL_BINDING_WEAK)
755
        return make_error<GenericBinaryError>("undefined weak global symbol",
756
                                              object_error::parse_failed);
757
      if (IsDefined) {
758
        Info.Name = readString(Ctx);
759
        unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
760
        wasm::WasmGlobal &Global = Globals[GlobalIndex];
761
        GlobalType = &Global.Type;
762
        if (Global.SymbolName.empty())
763
          Global.SymbolName = Info.Name;
764
      } else {
765
        wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
766
        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
767
          Info.Name = readString(Ctx);
768
          Info.ImportName = Import.Field;
769
        } else {
770
          Info.Name = Import.Field;
771
        }
772
        GlobalType = &Import.Global;
773
        Info.ImportModule = Import.Module;
774
      }
775
      break;
776

777
    case wasm::WASM_SYMBOL_TYPE_TABLE:
778
      Info.ElementIndex = readVaruint32(Ctx);
779
      if (!isValidTableNumber(Info.ElementIndex) ||
780
          IsDefined != isDefinedTableNumber(Info.ElementIndex))
781
        return make_error<GenericBinaryError>("invalid table symbol index",
782
                                              object_error::parse_failed);
783
      if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
784
                            wasm::WASM_SYMBOL_BINDING_WEAK)
785
        return make_error<GenericBinaryError>("undefined weak table symbol",
786
                                              object_error::parse_failed);
787
      if (IsDefined) {
788
        Info.Name = readString(Ctx);
789
        unsigned TableNumber = Info.ElementIndex - NumImportedTables;
790
        wasm::WasmTable &Table = Tables[TableNumber];
791
        TableType = &Table.Type;
792
        if (Table.SymbolName.empty())
793
          Table.SymbolName = Info.Name;
794
      } else {
795
        wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
796
        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
797
          Info.Name = readString(Ctx);
798
          Info.ImportName = Import.Field;
799
        } else {
800
          Info.Name = Import.Field;
801
        }
802
        TableType = &Import.Table;
803
        Info.ImportModule = Import.Module;
804
      }
805
      break;
806

807
    case wasm::WASM_SYMBOL_TYPE_DATA:
808
      Info.Name = readString(Ctx);
809
      if (IsDefined) {
810
        auto Index = readVaruint32(Ctx);
811
        auto Offset = readVaruint64(Ctx);
812
        auto Size = readVaruint64(Ctx);
813
        if (!(Info.Flags & wasm::WASM_SYMBOL_ABSOLUTE)) {
814
          if (static_cast<size_t>(Index) >= DataSegments.size())
815
            return make_error<GenericBinaryError>(
816
                "invalid data segment index: " + Twine(Index),
817
                object_error::parse_failed);
818
          size_t SegmentSize = DataSegments[Index].Data.Content.size();
819
          if (Offset > SegmentSize)
820
            return make_error<GenericBinaryError>(
821
                "invalid data symbol offset: `" + Info.Name +
822
                    "` (offset: " + Twine(Offset) +
823
                    " segment size: " + Twine(SegmentSize) + ")",
824
                object_error::parse_failed);
825
        }
826
        Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
827
      }
828
      break;
829

830
    case wasm::WASM_SYMBOL_TYPE_SECTION: {
831
      if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
832
          wasm::WASM_SYMBOL_BINDING_LOCAL)
833
        return make_error<GenericBinaryError>(
834
            "section symbols must have local binding",
835
            object_error::parse_failed);
836
      Info.ElementIndex = readVaruint32(Ctx);
837
      // Use somewhat unique section name as symbol name.
838
      StringRef SectionName = Sections[Info.ElementIndex].Name;
839
      Info.Name = SectionName;
840
      break;
841
    }
842

843
    case wasm::WASM_SYMBOL_TYPE_TAG: {
844
      Info.ElementIndex = readVaruint32(Ctx);
845
      if (!isValidTagIndex(Info.ElementIndex) ||
846
          IsDefined != isDefinedTagIndex(Info.ElementIndex))
847
        return make_error<GenericBinaryError>("invalid tag symbol index",
848
                                              object_error::parse_failed);
849
      if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
850
                            wasm::WASM_SYMBOL_BINDING_WEAK)
851
        return make_error<GenericBinaryError>("undefined weak global symbol",
852
                                              object_error::parse_failed);
853
      if (IsDefined) {
854
        Info.Name = readString(Ctx);
855
        unsigned TagIndex = Info.ElementIndex - NumImportedTags;
856
        wasm::WasmTag &Tag = Tags[TagIndex];
857
        Signature = &Signatures[Tag.SigIndex];
858
        if (Tag.SymbolName.empty())
859
          Tag.SymbolName = Info.Name;
860

861
      } else {
862
        wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex];
863
        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
864
          Info.Name = readString(Ctx);
865
          Info.ImportName = Import.Field;
866
        } else {
867
          Info.Name = Import.Field;
868
        }
869
        Signature = &Signatures[Import.SigIndex];
870
        Info.ImportModule = Import.Module;
871
      }
872
      break;
873
    }
874

875
    default:
876
      return make_error<GenericBinaryError>("invalid symbol type: " +
877
                                                Twine(unsigned(Info.Kind)),
878
                                            object_error::parse_failed);
879
    }
880

881
    if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
882
            wasm::WASM_SYMBOL_BINDING_LOCAL &&
883
        !SymbolNames.insert(Info.Name).second)
884
      return make_error<GenericBinaryError>("duplicate symbol name " +
885
                                                Twine(Info.Name),
886
                                            object_error::parse_failed);
887
    Symbols.emplace_back(Info, GlobalType, TableType, Signature);
888
    LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
889
  }
890

891
  return Error::success();
892
}
893

894
Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
895
  uint32_t ComdatCount = readVaruint32(Ctx);
896
  StringSet<> ComdatSet;
897
  for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
898
    StringRef Name = readString(Ctx);
899
    if (Name.empty() || !ComdatSet.insert(Name).second)
900
      return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
901
                                                Twine(Name),
902
                                            object_error::parse_failed);
903
    LinkingData.Comdats.emplace_back(Name);
904
    uint32_t Flags = readVaruint32(Ctx);
905
    if (Flags != 0)
906
      return make_error<GenericBinaryError>("unsupported COMDAT flags",
907
                                            object_error::parse_failed);
908

909
    uint32_t EntryCount = readVaruint32(Ctx);
910
    while (EntryCount--) {
911
      unsigned Kind = readVaruint32(Ctx);
912
      unsigned Index = readVaruint32(Ctx);
913
      switch (Kind) {
914
      default:
915
        return make_error<GenericBinaryError>("invalid COMDAT entry type",
916
                                              object_error::parse_failed);
917
      case wasm::WASM_COMDAT_DATA:
918
        if (Index >= DataSegments.size())
919
          return make_error<GenericBinaryError>(
920
              "COMDAT data index out of range", object_error::parse_failed);
921
        if (DataSegments[Index].Data.Comdat != UINT32_MAX)
922
          return make_error<GenericBinaryError>("data segment in two COMDATs",
923
                                                object_error::parse_failed);
924
        DataSegments[Index].Data.Comdat = ComdatIndex;
925
        break;
926
      case wasm::WASM_COMDAT_FUNCTION:
927
        if (!isDefinedFunctionIndex(Index))
928
          return make_error<GenericBinaryError>(
929
              "COMDAT function index out of range", object_error::parse_failed);
930
        if (getDefinedFunction(Index).Comdat != UINT32_MAX)
931
          return make_error<GenericBinaryError>("function in two COMDATs",
932
                                                object_error::parse_failed);
933
        getDefinedFunction(Index).Comdat = ComdatIndex;
934
        break;
935
      case wasm::WASM_COMDAT_SECTION:
936
        if (Index >= Sections.size())
937
          return make_error<GenericBinaryError>(
938
              "COMDAT section index out of range", object_error::parse_failed);
939
        if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
940
          return make_error<GenericBinaryError>(
941
              "non-custom section in a COMDAT", object_error::parse_failed);
942
        Sections[Index].Comdat = ComdatIndex;
943
        break;
944
      }
945
    }
946
  }
947
  return Error::success();
948
}
949

950
Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
951
  llvm::SmallSet<StringRef, 3> FieldsSeen;
952
  uint32_t Fields = readVaruint32(Ctx);
953
  for (size_t I = 0; I < Fields; ++I) {
954
    StringRef FieldName = readString(Ctx);
955
    if (!FieldsSeen.insert(FieldName).second)
956
      return make_error<GenericBinaryError>(
957
          "producers section does not have unique fields",
958
          object_error::parse_failed);
959
    std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
960
    if (FieldName == "language") {
961
      ProducerVec = &ProducerInfo.Languages;
962
    } else if (FieldName == "processed-by") {
963
      ProducerVec = &ProducerInfo.Tools;
964
    } else if (FieldName == "sdk") {
965
      ProducerVec = &ProducerInfo.SDKs;
966
    } else {
967
      return make_error<GenericBinaryError>(
968
          "producers section field is not named one of language, processed-by, "
969
          "or sdk",
970
          object_error::parse_failed);
971
    }
972
    uint32_t ValueCount = readVaruint32(Ctx);
973
    llvm::SmallSet<StringRef, 8> ProducersSeen;
974
    for (size_t J = 0; J < ValueCount; ++J) {
975
      StringRef Name = readString(Ctx);
976
      StringRef Version = readString(Ctx);
977
      if (!ProducersSeen.insert(Name).second) {
978
        return make_error<GenericBinaryError>(
979
            "producers section contains repeated producer",
980
            object_error::parse_failed);
981
      }
982
      ProducerVec->emplace_back(std::string(Name), std::string(Version));
983
    }
984
  }
985
  if (Ctx.Ptr != Ctx.End)
986
    return make_error<GenericBinaryError>("producers section ended prematurely",
987
                                          object_error::parse_failed);
988
  return Error::success();
989
}
990

991
Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
992
  llvm::SmallSet<std::string, 8> FeaturesSeen;
993
  uint32_t FeatureCount = readVaruint32(Ctx);
994
  for (size_t I = 0; I < FeatureCount; ++I) {
995
    wasm::WasmFeatureEntry Feature;
996
    Feature.Prefix = readUint8(Ctx);
997
    switch (Feature.Prefix) {
998
    case wasm::WASM_FEATURE_PREFIX_USED:
999
    case wasm::WASM_FEATURE_PREFIX_REQUIRED:
1000
    case wasm::WASM_FEATURE_PREFIX_DISALLOWED:
1001
      break;
1002
    default:
1003
      return make_error<GenericBinaryError>("unknown feature policy prefix",
1004
                                            object_error::parse_failed);
1005
    }
1006
    Feature.Name = std::string(readString(Ctx));
1007
    if (!FeaturesSeen.insert(Feature.Name).second)
1008
      return make_error<GenericBinaryError>(
1009
          "target features section contains repeated feature \"" +
1010
              Feature.Name + "\"",
1011
          object_error::parse_failed);
1012
    TargetFeatures.push_back(Feature);
1013
  }
1014
  if (Ctx.Ptr != Ctx.End)
1015
    return make_error<GenericBinaryError>(
1016
        "target features section ended prematurely",
1017
        object_error::parse_failed);
1018
  return Error::success();
1019
}
1020

1021
Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
1022
  uint32_t SectionIndex = readVaruint32(Ctx);
1023
  if (SectionIndex >= Sections.size())
1024
    return make_error<GenericBinaryError>("invalid section index",
1025
                                          object_error::parse_failed);
1026
  WasmSection &Section = Sections[SectionIndex];
1027
  uint32_t RelocCount = readVaruint32(Ctx);
1028
  uint32_t EndOffset = Section.Content.size();
1029
  uint32_t PreviousOffset = 0;
1030
  while (RelocCount--) {
1031
    wasm::WasmRelocation Reloc = {};
1032
    uint32_t type = readVaruint32(Ctx);
1033
    Reloc.Type = type;
1034
    Reloc.Offset = readVaruint32(Ctx);
1035
    if (Reloc.Offset < PreviousOffset)
1036
      return make_error<GenericBinaryError>("relocations not in offset order",
1037
                                            object_error::parse_failed);
1038

1039
    auto badReloc = [&](StringRef msg) {
1040
      return make_error<GenericBinaryError>(
1041
          msg + ": " + Twine(Symbols[Reloc.Index].Info.Name),
1042
          object_error::parse_failed);
1043
    };
1044

1045
    PreviousOffset = Reloc.Offset;
1046
    Reloc.Index = readVaruint32(Ctx);
1047
    switch (type) {
1048
    case wasm::R_WASM_FUNCTION_INDEX_LEB:
1049
    case wasm::R_WASM_FUNCTION_INDEX_I32:
1050
    case wasm::R_WASM_TABLE_INDEX_SLEB:
1051
    case wasm::R_WASM_TABLE_INDEX_SLEB64:
1052
    case wasm::R_WASM_TABLE_INDEX_I32:
1053
    case wasm::R_WASM_TABLE_INDEX_I64:
1054
    case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
1055
    case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
1056
      if (!isValidFunctionSymbol(Reloc.Index))
1057
        return badReloc("invalid function relocation");
1058
      break;
1059
    case wasm::R_WASM_TABLE_NUMBER_LEB:
1060
      if (!isValidTableSymbol(Reloc.Index))
1061
        return badReloc("invalid table relocation");
1062
      break;
1063
    case wasm::R_WASM_TYPE_INDEX_LEB:
1064
      if (Reloc.Index >= Signatures.size())
1065
        return badReloc("invalid relocation type index");
1066
      break;
1067
    case wasm::R_WASM_GLOBAL_INDEX_LEB:
1068
      // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
1069
      // symbols to refer to their GOT entries.
1070
      if (!isValidGlobalSymbol(Reloc.Index) &&
1071
          !isValidDataSymbol(Reloc.Index) &&
1072
          !isValidFunctionSymbol(Reloc.Index))
1073
        return badReloc("invalid global relocation");
1074
      break;
1075
    case wasm::R_WASM_GLOBAL_INDEX_I32:
1076
      if (!isValidGlobalSymbol(Reloc.Index))
1077
        return badReloc("invalid global relocation");
1078
      break;
1079
    case wasm::R_WASM_TAG_INDEX_LEB:
1080
      if (!isValidTagSymbol(Reloc.Index))
1081
        return badReloc("invalid tag relocation");
1082
      break;
1083
    case wasm::R_WASM_MEMORY_ADDR_LEB:
1084
    case wasm::R_WASM_MEMORY_ADDR_SLEB:
1085
    case wasm::R_WASM_MEMORY_ADDR_I32:
1086
    case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
1087
    case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
1088
    case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
1089
      if (!isValidDataSymbol(Reloc.Index))
1090
        return badReloc("invalid data relocation");
1091
      Reloc.Addend = readVarint32(Ctx);
1092
      break;
1093
    case wasm::R_WASM_MEMORY_ADDR_LEB64:
1094
    case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1095
    case wasm::R_WASM_MEMORY_ADDR_I64:
1096
    case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1097
    case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1098
      if (!isValidDataSymbol(Reloc.Index))
1099
        return badReloc("invalid data relocation");
1100
      Reloc.Addend = readVarint64(Ctx);
1101
      break;
1102
    case wasm::R_WASM_FUNCTION_OFFSET_I32:
1103
      if (!isValidFunctionSymbol(Reloc.Index))
1104
        return badReloc("invalid function relocation");
1105
      Reloc.Addend = readVarint32(Ctx);
1106
      break;
1107
    case wasm::R_WASM_FUNCTION_OFFSET_I64:
1108
      if (!isValidFunctionSymbol(Reloc.Index))
1109
        return badReloc("invalid function relocation");
1110
      Reloc.Addend = readVarint64(Ctx);
1111
      break;
1112
    case wasm::R_WASM_SECTION_OFFSET_I32:
1113
      if (!isValidSectionSymbol(Reloc.Index))
1114
        return badReloc("invalid section relocation");
1115
      Reloc.Addend = readVarint32(Ctx);
1116
      break;
1117
    default:
1118
      return make_error<GenericBinaryError>("invalid relocation type: " +
1119
                                                Twine(type),
1120
                                            object_error::parse_failed);
1121
    }
1122

1123
    // Relocations must fit inside the section, and must appear in order.  They
1124
    // also shouldn't overlap a function/element boundary, but we don't bother
1125
    // to check that.
1126
    uint64_t Size = 5;
1127
    if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1128
        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1129
        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1130
      Size = 10;
1131
    if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1132
        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1133
        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1134
        Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1135
        Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1136
        Reloc.Type == wasm::R_WASM_FUNCTION_INDEX_I32 ||
1137
        Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
1138
      Size = 4;
1139
    if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1140
        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1141
        Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
1142
      Size = 8;
1143
    if (Reloc.Offset + Size > EndOffset)
1144
      return make_error<GenericBinaryError>("invalid relocation offset",
1145
                                            object_error::parse_failed);
1146

1147
    Section.Relocations.push_back(Reloc);
1148
  }
1149
  if (Ctx.Ptr != Ctx.End)
1150
    return make_error<GenericBinaryError>("reloc section ended prematurely",
1151
                                          object_error::parse_failed);
1152
  return Error::success();
1153
}
1154

1155
Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
1156
  if (Sec.Name == "dylink") {
1157
    if (Error Err = parseDylinkSection(Ctx))
1158
      return Err;
1159
  } else if (Sec.Name == "dylink.0") {
1160
    if (Error Err = parseDylink0Section(Ctx))
1161
      return Err;
1162
  } else if (Sec.Name == "name") {
1163
    if (Error Err = parseNameSection(Ctx))
1164
      return Err;
1165
  } else if (Sec.Name == "linking") {
1166
    if (Error Err = parseLinkingSection(Ctx))
1167
      return Err;
1168
  } else if (Sec.Name == "producers") {
1169
    if (Error Err = parseProducersSection(Ctx))
1170
      return Err;
1171
  } else if (Sec.Name == "target_features") {
1172
    if (Error Err = parseTargetFeaturesSection(Ctx))
1173
      return Err;
1174
  } else if (Sec.Name.starts_with("reloc.")) {
1175
    if (Error Err = parseRelocSection(Sec.Name, Ctx))
1176
      return Err;
1177
  }
1178
  return Error::success();
1179
}
1180

1181
Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1182
  auto parseFieldDef = [&]() {
1183
    uint32_t TypeCode = readVaruint32((Ctx));
1184
    /* Discard StorageType */ parseValType(Ctx, TypeCode);
1185
    /* Discard Mutability */ readVaruint32(Ctx);
1186
  };
1187

1188
  uint32_t Count = readVaruint32(Ctx);
1189
  Signatures.reserve(Count);
1190
  while (Count--) {
1191
    wasm::WasmSignature Sig;
1192
    uint8_t Form = readUint8(Ctx);
1193
    if (Form == wasm::WASM_TYPE_REC) {
1194
      // Rec groups expand the type index space (beyond what was declared at
1195
      // the top of the section, and also consume one element in that space.
1196
      uint32_t RecSize = readVaruint32(Ctx);
1197
      if (RecSize == 0)
1198
        return make_error<GenericBinaryError>("Rec group size cannot be 0",
1199
                                              object_error::parse_failed);
1200
      Signatures.reserve(Signatures.size() + RecSize);
1201
      Count += RecSize;
1202
      Sig.Kind = wasm::WasmSignature::Placeholder;
1203
      Signatures.push_back(std::move(Sig));
1204
      HasUnmodeledTypes = true;
1205
      continue;
1206
    }
1207
    if (Form != wasm::WASM_TYPE_FUNC) {
1208
      // Currently LLVM only models function types, and not other composite
1209
      // types. Here we parse the type declarations just enough to skip past
1210
      // them in the binary.
1211
      if (Form == wasm::WASM_TYPE_SUB || Form == wasm::WASM_TYPE_SUB_FINAL) {
1212
        uint32_t Supers = readVaruint32(Ctx);
1213
        if (Supers > 0) {
1214
          if (Supers != 1)
1215
            return make_error<GenericBinaryError>(
1216
                "Invalid number of supertypes", object_error::parse_failed);
1217
          /* Discard SuperIndex */ readVaruint32(Ctx);
1218
        }
1219
        Form = readVaruint32(Ctx);
1220
      }
1221
      if (Form == wasm::WASM_TYPE_STRUCT) {
1222
        uint32_t FieldCount = readVaruint32(Ctx);
1223
        while (FieldCount--) {
1224
          parseFieldDef();
1225
        }
1226
      } else if (Form == wasm::WASM_TYPE_ARRAY) {
1227
        parseFieldDef();
1228
      } else {
1229
        return make_error<GenericBinaryError>("bad form",
1230
                                              object_error::parse_failed);
1231
      }
1232
      Sig.Kind = wasm::WasmSignature::Placeholder;
1233
      Signatures.push_back(std::move(Sig));
1234
      HasUnmodeledTypes = true;
1235
      continue;
1236
    }
1237

1238
    uint32_t ParamCount = readVaruint32(Ctx);
1239
    Sig.Params.reserve(ParamCount);
1240
    while (ParamCount--) {
1241
      uint32_t ParamType = readUint8(Ctx);
1242
      Sig.Params.push_back(parseValType(Ctx, ParamType));
1243
      continue;
1244
    }
1245
    uint32_t ReturnCount = readVaruint32(Ctx);
1246
    while (ReturnCount--) {
1247
      uint32_t ReturnType = readUint8(Ctx);
1248
      Sig.Returns.push_back(parseValType(Ctx, ReturnType));
1249
    }
1250

1251
    Signatures.push_back(std::move(Sig));
1252
  }
1253
  if (Ctx.Ptr != Ctx.End)
1254
    return make_error<GenericBinaryError>("type section ended prematurely",
1255
                                          object_error::parse_failed);
1256
  return Error::success();
1257
}
1258

1259
Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1260
  uint32_t Count = readVaruint32(Ctx);
1261
  uint32_t NumTypes = Signatures.size();
1262
  Imports.reserve(Count);
1263
  for (uint32_t I = 0; I < Count; I++) {
1264
    wasm::WasmImport Im;
1265
    Im.Module = readString(Ctx);
1266
    Im.Field = readString(Ctx);
1267
    Im.Kind = readUint8(Ctx);
1268
    switch (Im.Kind) {
1269
    case wasm::WASM_EXTERNAL_FUNCTION:
1270
      NumImportedFunctions++;
1271
      Im.SigIndex = readVaruint32(Ctx);
1272
      if (Im.SigIndex >= NumTypes)
1273
        return make_error<GenericBinaryError>("invalid function type",
1274
                                              object_error::parse_failed);
1275
      break;
1276
    case wasm::WASM_EXTERNAL_GLOBAL:
1277
      NumImportedGlobals++;
1278
      Im.Global.Type = readUint8(Ctx);
1279
      Im.Global.Mutable = readVaruint1(Ctx);
1280
      break;
1281
    case wasm::WASM_EXTERNAL_MEMORY:
1282
      Im.Memory = readLimits(Ctx);
1283
      if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1284
        HasMemory64 = true;
1285
      break;
1286
    case wasm::WASM_EXTERNAL_TABLE: {
1287
      Im.Table = readTableType(Ctx);
1288
      NumImportedTables++;
1289
      auto ElemType = Im.Table.ElemType;
1290
      if (ElemType != wasm::ValType::FUNCREF &&
1291
          ElemType != wasm::ValType::EXTERNREF &&
1292
          ElemType != wasm::ValType::EXNREF &&
1293
          ElemType != wasm::ValType::OTHERREF)
1294
        return make_error<GenericBinaryError>("invalid table element type",
1295
                                              object_error::parse_failed);
1296
      break;
1297
    }
1298
    case wasm::WASM_EXTERNAL_TAG:
1299
      NumImportedTags++;
1300
      if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1301
        return make_error<GenericBinaryError>("invalid attribute",
1302
                                              object_error::parse_failed);
1303
      Im.SigIndex = readVaruint32(Ctx);
1304
      if (Im.SigIndex >= NumTypes)
1305
        return make_error<GenericBinaryError>("invalid tag type",
1306
                                              object_error::parse_failed);
1307
      break;
1308
    default:
1309
      return make_error<GenericBinaryError>("unexpected import kind",
1310
                                            object_error::parse_failed);
1311
    }
1312
    Imports.push_back(Im);
1313
  }
1314
  if (Ctx.Ptr != Ctx.End)
1315
    return make_error<GenericBinaryError>("import section ended prematurely",
1316
                                          object_error::parse_failed);
1317
  return Error::success();
1318
}
1319

1320
Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1321
  uint32_t Count = readVaruint32(Ctx);
1322
  Functions.reserve(Count);
1323
  uint32_t NumTypes = Signatures.size();
1324
  while (Count--) {
1325
    uint32_t Type = readVaruint32(Ctx);
1326
    if (Type >= NumTypes)
1327
      return make_error<GenericBinaryError>("invalid function type",
1328
                                            object_error::parse_failed);
1329
    wasm::WasmFunction F;
1330
    F.SigIndex = Type;
1331
    Functions.push_back(F);
1332
  }
1333
  if (Ctx.Ptr != Ctx.End)
1334
    return make_error<GenericBinaryError>("function section ended prematurely",
1335
                                          object_error::parse_failed);
1336
  return Error::success();
1337
}
1338

1339
Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1340
  TableSection = Sections.size();
1341
  uint32_t Count = readVaruint32(Ctx);
1342
  Tables.reserve(Count);
1343
  while (Count--) {
1344
    wasm::WasmTable T;
1345
    T.Type = readTableType(Ctx);
1346
    T.Index = NumImportedTables + Tables.size();
1347
    Tables.push_back(T);
1348
    auto ElemType = Tables.back().Type.ElemType;
1349
    if (ElemType != wasm::ValType::FUNCREF &&
1350
        ElemType != wasm::ValType::EXTERNREF &&
1351
        ElemType != wasm::ValType::EXNREF &&
1352
        ElemType != wasm::ValType::OTHERREF) {
1353
      return make_error<GenericBinaryError>("invalid table element type",
1354
                                            object_error::parse_failed);
1355
    }
1356
  }
1357
  if (Ctx.Ptr != Ctx.End)
1358
    return make_error<GenericBinaryError>("table section ended prematurely",
1359
                                          object_error::parse_failed);
1360
  return Error::success();
1361
}
1362

1363
Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1364
  uint32_t Count = readVaruint32(Ctx);
1365
  Memories.reserve(Count);
1366
  while (Count--) {
1367
    auto Limits = readLimits(Ctx);
1368
    if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1369
      HasMemory64 = true;
1370
    Memories.push_back(Limits);
1371
  }
1372
  if (Ctx.Ptr != Ctx.End)
1373
    return make_error<GenericBinaryError>("memory section ended prematurely",
1374
                                          object_error::parse_failed);
1375
  return Error::success();
1376
}
1377

1378
Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1379
  TagSection = Sections.size();
1380
  uint32_t Count = readVaruint32(Ctx);
1381
  Tags.reserve(Count);
1382
  uint32_t NumTypes = Signatures.size();
1383
  while (Count--) {
1384
    if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1385
      return make_error<GenericBinaryError>("invalid attribute",
1386
                                            object_error::parse_failed);
1387
    uint32_t Type = readVaruint32(Ctx);
1388
    if (Type >= NumTypes)
1389
      return make_error<GenericBinaryError>("invalid tag type",
1390
                                            object_error::parse_failed);
1391
    wasm::WasmTag Tag;
1392
    Tag.Index = NumImportedTags + Tags.size();
1393
    Tag.SigIndex = Type;
1394
    Signatures[Type].Kind = wasm::WasmSignature::Tag;
1395
    Tags.push_back(Tag);
1396
  }
1397

1398
  if (Ctx.Ptr != Ctx.End)
1399
    return make_error<GenericBinaryError>("tag section ended prematurely",
1400
                                          object_error::parse_failed);
1401
  return Error::success();
1402
}
1403

1404
Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1405
  GlobalSection = Sections.size();
1406
  const uint8_t *SectionStart = Ctx.Ptr;
1407
  uint32_t Count = readVaruint32(Ctx);
1408
  Globals.reserve(Count);
1409
  while (Count--) {
1410
    wasm::WasmGlobal Global;
1411
    Global.Index = NumImportedGlobals + Globals.size();
1412
    const uint8_t *GlobalStart = Ctx.Ptr;
1413
    Global.Offset = static_cast<uint32_t>(GlobalStart - SectionStart);
1414
    auto GlobalOpcode = readVaruint32(Ctx);
1415
    Global.Type.Type = (uint8_t)parseValType(Ctx, GlobalOpcode);
1416
    Global.Type.Mutable = readVaruint1(Ctx);
1417
    if (Error Err = readInitExpr(Global.InitExpr, Ctx))
1418
      return Err;
1419
    Global.Size = static_cast<uint32_t>(Ctx.Ptr - GlobalStart);
1420
    Globals.push_back(Global);
1421
  }
1422
  if (Ctx.Ptr != Ctx.End)
1423
    return make_error<GenericBinaryError>("global section ended prematurely",
1424
                                          object_error::parse_failed);
1425
  return Error::success();
1426
}
1427

1428
Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1429
  uint32_t Count = readVaruint32(Ctx);
1430
  Exports.reserve(Count);
1431
  Symbols.reserve(Count);
1432
  for (uint32_t I = 0; I < Count; I++) {
1433
    wasm::WasmExport Ex;
1434
    Ex.Name = readString(Ctx);
1435
    Ex.Kind = readUint8(Ctx);
1436
    Ex.Index = readVaruint32(Ctx);
1437
    const wasm::WasmSignature *Signature = nullptr;
1438
    const wasm::WasmGlobalType *GlobalType = nullptr;
1439
    const wasm::WasmTableType *TableType = nullptr;
1440
    wasm::WasmSymbolInfo Info;
1441
    Info.Name = Ex.Name;
1442
    Info.Flags = 0;
1443
    switch (Ex.Kind) {
1444
    case wasm::WASM_EXTERNAL_FUNCTION: {
1445
      if (!isDefinedFunctionIndex(Ex.Index))
1446
        return make_error<GenericBinaryError>("invalid function export",
1447
                                              object_error::parse_failed);
1448
      getDefinedFunction(Ex.Index).ExportName = Ex.Name;
1449
      Info.Kind = wasm::WASM_SYMBOL_TYPE_FUNCTION;
1450
      Info.ElementIndex = Ex.Index;
1451
      unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
1452
      wasm::WasmFunction &Function = Functions[FuncIndex];
1453
      Signature = &Signatures[Function.SigIndex];
1454
      break;
1455
    }
1456
    case wasm::WASM_EXTERNAL_GLOBAL: {
1457
      if (!isValidGlobalIndex(Ex.Index))
1458
        return make_error<GenericBinaryError>("invalid global export",
1459
                                              object_error::parse_failed);
1460
      Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA;
1461
      uint64_t Offset = 0;
1462
      if (isDefinedGlobalIndex(Ex.Index)) {
1463
        auto Global = getDefinedGlobal(Ex.Index);
1464
        if (!Global.InitExpr.Extended) {
1465
          auto Inst = Global.InitExpr.Inst;
1466
          if (Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1467
            Offset = Inst.Value.Int32;
1468
          } else if (Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1469
            Offset = Inst.Value.Int64;
1470
          }
1471
        }
1472
      }
1473
      Info.DataRef = wasm::WasmDataReference{0, Offset, 0};
1474
      break;
1475
    }
1476
    case wasm::WASM_EXTERNAL_TAG:
1477
      if (!isValidTagIndex(Ex.Index))
1478
        return make_error<GenericBinaryError>("invalid tag export",
1479
                                              object_error::parse_failed);
1480
      Info.Kind = wasm::WASM_SYMBOL_TYPE_TAG;
1481
      Info.ElementIndex = Ex.Index;
1482
      break;
1483
    case wasm::WASM_EXTERNAL_MEMORY:
1484
      break;
1485
    case wasm::WASM_EXTERNAL_TABLE:
1486
      Info.Kind = wasm::WASM_SYMBOL_TYPE_TABLE;
1487
      Info.ElementIndex = Ex.Index;
1488
      break;
1489
    default:
1490
      return make_error<GenericBinaryError>("unexpected export kind",
1491
                                            object_error::parse_failed);
1492
    }
1493
    Exports.push_back(Ex);
1494
    if (Ex.Kind != wasm::WASM_EXTERNAL_MEMORY) {
1495
      Symbols.emplace_back(Info, GlobalType, TableType, Signature);
1496
      LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
1497
    }
1498
  }
1499
  if (Ctx.Ptr != Ctx.End)
1500
    return make_error<GenericBinaryError>("export section ended prematurely",
1501
                                          object_error::parse_failed);
1502
  return Error::success();
1503
}
1504

1505
bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1506
  return Index < NumImportedFunctions + Functions.size();
1507
}
1508

1509
bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
1510
  return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1511
}
1512

1513
bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
1514
  return Index < NumImportedGlobals + Globals.size();
1515
}
1516

1517
bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
1518
  return Index < NumImportedTables + Tables.size();
1519
}
1520

1521
bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
1522
  return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1523
}
1524

1525
bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
1526
  return Index >= NumImportedTables && isValidTableNumber(Index);
1527
}
1528

1529
bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
1530
  return Index < NumImportedTags + Tags.size();
1531
}
1532

1533
bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
1534
  return Index >= NumImportedTags && isValidTagIndex(Index);
1535
}
1536

1537
bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1538
  return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1539
}
1540

1541
bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
1542
  return Index < Symbols.size() && Symbols[Index].isTypeTable();
1543
}
1544

1545
bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1546
  return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1547
}
1548

1549
bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
1550
  return Index < Symbols.size() && Symbols[Index].isTypeTag();
1551
}
1552

1553
bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1554
  return Index < Symbols.size() && Symbols[Index].isTypeData();
1555
}
1556

1557
bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1558
  return Index < Symbols.size() && Symbols[Index].isTypeSection();
1559
}
1560

1561
wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1562
  assert(isDefinedFunctionIndex(Index));
1563
  return Functions[Index - NumImportedFunctions];
1564
}
1565

1566
const wasm::WasmFunction &
1567
WasmObjectFile::getDefinedFunction(uint32_t Index) const {
1568
  assert(isDefinedFunctionIndex(Index));
1569
  return Functions[Index - NumImportedFunctions];
1570
}
1571

1572
const wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) const {
1573
  assert(isDefinedGlobalIndex(Index));
1574
  return Globals[Index - NumImportedGlobals];
1575
}
1576

1577
wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1578
  assert(isDefinedTagIndex(Index));
1579
  return Tags[Index - NumImportedTags];
1580
}
1581

1582
Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1583
  StartFunction = readVaruint32(Ctx);
1584
  if (!isValidFunctionIndex(StartFunction))
1585
    return make_error<GenericBinaryError>("invalid start function",
1586
                                          object_error::parse_failed);
1587
  return Error::success();
1588
}
1589

1590
Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1591
  CodeSection = Sections.size();
1592
  uint32_t FunctionCount = readVaruint32(Ctx);
1593
  if (FunctionCount != Functions.size()) {
1594
    return make_error<GenericBinaryError>("invalid function count",
1595
                                          object_error::parse_failed);
1596
  }
1597

1598
  for (uint32_t i = 0; i < FunctionCount; i++) {
1599
    wasm::WasmFunction& Function = Functions[i];
1600
    const uint8_t *FunctionStart = Ctx.Ptr;
1601
    uint32_t Size = readVaruint32(Ctx);
1602
    const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1603

1604
    Function.CodeOffset = Ctx.Ptr - FunctionStart;
1605
    Function.Index = NumImportedFunctions + i;
1606
    Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1607
    Function.Size = FunctionEnd - FunctionStart;
1608

1609
    uint32_t NumLocalDecls = readVaruint32(Ctx);
1610
    Function.Locals.reserve(NumLocalDecls);
1611
    while (NumLocalDecls--) {
1612
      wasm::WasmLocalDecl Decl;
1613
      Decl.Count = readVaruint32(Ctx);
1614
      Decl.Type = readUint8(Ctx);
1615
      Function.Locals.push_back(Decl);
1616
    }
1617

1618
    uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1619
    // Ensure that Function is within Ctx's buffer.
1620
    if (Ctx.Ptr + BodySize > Ctx.End) {
1621
      return make_error<GenericBinaryError>("Function extends beyond buffer",
1622
                                            object_error::parse_failed);
1623
    }
1624
    Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1625
    // This will be set later when reading in the linking metadata section.
1626
    Function.Comdat = UINT32_MAX;
1627
    Ctx.Ptr += BodySize;
1628
    assert(Ctx.Ptr == FunctionEnd);
1629
  }
1630
  if (Ctx.Ptr != Ctx.End)
1631
    return make_error<GenericBinaryError>("code section ended prematurely",
1632
                                          object_error::parse_failed);
1633
  return Error::success();
1634
}
1635

1636
Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1637
  uint32_t Count = readVaruint32(Ctx);
1638
  ElemSegments.reserve(Count);
1639
  while (Count--) {
1640
    wasm::WasmElemSegment Segment;
1641
    Segment.Flags = readVaruint32(Ctx);
1642

1643
    uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER |
1644
                              wasm::WASM_ELEM_SEGMENT_IS_PASSIVE |
1645
                              wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS;
1646
    if (Segment.Flags & ~SupportedFlags)
1647
      return make_error<GenericBinaryError>(
1648
          "Unsupported flags for element segment", object_error::parse_failed);
1649

1650
    bool IsPassive = (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) != 0;
1651
    bool IsDeclarative =
1652
        IsPassive && (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_DECLARATIVE);
1653
    bool HasTableNumber =
1654
        !IsPassive &&
1655
        (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER);
1656
    bool HasInitExprs =
1657
        (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS);
1658
    bool HasElemKind =
1659
        (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) &&
1660
        !HasInitExprs;
1661

1662
    if (HasTableNumber)
1663
      Segment.TableNumber = readVaruint32(Ctx);
1664
    else
1665
      Segment.TableNumber = 0;
1666

1667
    if (!isValidTableNumber(Segment.TableNumber))
1668
      return make_error<GenericBinaryError>("invalid TableNumber",
1669
                                            object_error::parse_failed);
1670

1671
    if (IsPassive || IsDeclarative) {
1672
      Segment.Offset.Extended = false;
1673
      Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1674
      Segment.Offset.Inst.Value.Int32 = 0;
1675
    } else {
1676
      if (Error Err = readInitExpr(Segment.Offset, Ctx))
1677
        return Err;
1678
    }
1679

1680
    if (HasElemKind) {
1681
      auto ElemKind = readVaruint32(Ctx);
1682
      if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {
1683
        Segment.ElemKind = parseValType(Ctx, ElemKind);
1684
        if (Segment.ElemKind != wasm::ValType::FUNCREF &&
1685
            Segment.ElemKind != wasm::ValType::EXTERNREF &&
1686
            Segment.ElemKind != wasm::ValType::EXNREF &&
1687
            Segment.ElemKind != wasm::ValType::OTHERREF) {
1688
          return make_error<GenericBinaryError>("invalid elem type",
1689
                                                object_error::parse_failed);
1690
        }
1691
      } else {
1692
        if (ElemKind != 0)
1693
          return make_error<GenericBinaryError>("invalid elem type",
1694
                                                object_error::parse_failed);
1695
        Segment.ElemKind = wasm::ValType::FUNCREF;
1696
      }
1697
    } else if (HasInitExprs) {
1698
      auto ElemType = parseValType(Ctx, readVaruint32(Ctx));
1699
      Segment.ElemKind = ElemType;
1700
    } else {
1701
      Segment.ElemKind = wasm::ValType::FUNCREF;
1702
    }
1703

1704
    uint32_t NumElems = readVaruint32(Ctx);
1705

1706
    if (HasInitExprs) {
1707
      while (NumElems--) {
1708
        wasm::WasmInitExpr Expr;
1709
        if (Error Err = readInitExpr(Expr, Ctx))
1710
          return Err;
1711
      }
1712
    } else {
1713
      while (NumElems--) {
1714
        Segment.Functions.push_back(readVaruint32(Ctx));
1715
      }
1716
    }
1717
    ElemSegments.push_back(Segment);
1718
  }
1719
  if (Ctx.Ptr != Ctx.End)
1720
    return make_error<GenericBinaryError>("elem section ended prematurely",
1721
                                          object_error::parse_failed);
1722
  return Error::success();
1723
}
1724

1725
Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1726
  DataSection = Sections.size();
1727
  uint32_t Count = readVaruint32(Ctx);
1728
  if (DataCount && Count != *DataCount)
1729
    return make_error<GenericBinaryError>(
1730
        "number of data segments does not match DataCount section");
1731
  DataSegments.reserve(Count);
1732
  while (Count--) {
1733
    WasmSegment Segment;
1734
    Segment.Data.InitFlags = readVaruint32(Ctx);
1735
    Segment.Data.MemoryIndex =
1736
        (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
1737
            ? readVaruint32(Ctx)
1738
            : 0;
1739
    if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1740
      if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1741
        return Err;
1742
    } else {
1743
      Segment.Data.Offset.Extended = false;
1744
      Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1745
      Segment.Data.Offset.Inst.Value.Int32 = 0;
1746
    }
1747
    uint32_t Size = readVaruint32(Ctx);
1748
    if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1749
      return make_error<GenericBinaryError>("invalid segment size",
1750
                                            object_error::parse_failed);
1751
    Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1752
    // The rest of these Data fields are set later, when reading in the linking
1753
    // metadata section.
1754
    Segment.Data.Alignment = 0;
1755
    Segment.Data.LinkingFlags = 0;
1756
    Segment.Data.Comdat = UINT32_MAX;
1757
    Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1758
    Ctx.Ptr += Size;
1759
    DataSegments.push_back(Segment);
1760
  }
1761
  if (Ctx.Ptr != Ctx.End)
1762
    return make_error<GenericBinaryError>("data section ended prematurely",
1763
                                          object_error::parse_failed);
1764
  return Error::success();
1765
}
1766

1767
Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1768
  DataCount = readVaruint32(Ctx);
1769
  return Error::success();
1770
}
1771

1772
const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1773
  return Header;
1774
}
1775

1776
void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
1777

1778
Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
1779
  uint32_t Result = SymbolRef::SF_None;
1780
  const WasmSymbol &Sym = getWasmSymbol(Symb);
1781

1782
  LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1783
  if (Sym.isBindingWeak())
1784
    Result |= SymbolRef::SF_Weak;
1785
  if (!Sym.isBindingLocal())
1786
    Result |= SymbolRef::SF_Global;
1787
  if (Sym.isHidden())
1788
    Result |= SymbolRef::SF_Hidden;
1789
  if (!Sym.isDefined())
1790
    Result |= SymbolRef::SF_Undefined;
1791
  if (Sym.isTypeFunction())
1792
    Result |= SymbolRef::SF_Executable;
1793
  return Result;
1794
}
1795

1796
basic_symbol_iterator WasmObjectFile::symbol_begin() const {
1797
  DataRefImpl Ref;
1798
  Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1799
  Ref.d.b = 0; // Symbol index
1800
  return BasicSymbolRef(Ref, this);
1801
}
1802

1803
basic_symbol_iterator WasmObjectFile::symbol_end() const {
1804
  DataRefImpl Ref;
1805
  Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1806
  Ref.d.b = Symbols.size(); // Symbol index
1807
  return BasicSymbolRef(Ref, this);
1808
}
1809

1810
const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
1811
  return Symbols[Symb.d.b];
1812
}
1813

1814
const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1815
  return getWasmSymbol(Symb.getRawDataRefImpl());
1816
}
1817

1818
Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
1819
  return getWasmSymbol(Symb).Info.Name;
1820
}
1821

1822
Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
1823
  auto &Sym = getWasmSymbol(Symb);
1824
  if (!Sym.isDefined())
1825
    return 0;
1826
  Expected<section_iterator> Sec = getSymbolSection(Symb);
1827
  if (!Sec)
1828
    return Sec.takeError();
1829
  uint32_t SectionAddress = getSectionAddress(Sec.get()->getRawDataRefImpl());
1830
  if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1831
      isDefinedFunctionIndex(Sym.Info.ElementIndex)) {
1832
    return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +
1833
           SectionAddress;
1834
  }
1835
  if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL &&
1836
      isDefinedGlobalIndex(Sym.Info.ElementIndex)) {
1837
    return getDefinedGlobal(Sym.Info.ElementIndex).Offset + SectionAddress;
1838
  }
1839

1840
  return getSymbolValue(Symb);
1841
}
1842

1843
uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
1844
  switch (Sym.Info.Kind) {
1845
  case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1846
  case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1847
  case wasm::WASM_SYMBOL_TYPE_TAG:
1848
  case wasm::WASM_SYMBOL_TYPE_TABLE:
1849
    return Sym.Info.ElementIndex;
1850
  case wasm::WASM_SYMBOL_TYPE_DATA: {
1851
    // The value of a data symbol is the segment offset, plus the symbol
1852
    // offset within the segment.
1853
    uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1854
    const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1855
    if (Segment.Offset.Extended) {
1856
      llvm_unreachable("extended init exprs not supported");
1857
    } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1858
      return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset;
1859
    } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1860
      return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset;
1861
    } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) {
1862
      return Sym.Info.DataRef.Offset;
1863
    } else {
1864
      llvm_unreachable("unknown init expr opcode");
1865
    }
1866
  }
1867
  case wasm::WASM_SYMBOL_TYPE_SECTION:
1868
    return 0;
1869
  }
1870
  llvm_unreachable("invalid symbol type");
1871
}
1872

1873
uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1874
  return getWasmSymbolValue(getWasmSymbol(Symb));
1875
}
1876

1877
uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1878
  llvm_unreachable("not yet implemented");
1879
  return 0;
1880
}
1881

1882
uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1883
  llvm_unreachable("not yet implemented");
1884
  return 0;
1885
}
1886

1887
Expected<SymbolRef::Type>
1888
WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
1889
  const WasmSymbol &Sym = getWasmSymbol(Symb);
1890

1891
  switch (Sym.Info.Kind) {
1892
  case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1893
    return SymbolRef::ST_Function;
1894
  case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1895
    return SymbolRef::ST_Other;
1896
  case wasm::WASM_SYMBOL_TYPE_DATA:
1897
    return SymbolRef::ST_Data;
1898
  case wasm::WASM_SYMBOL_TYPE_SECTION:
1899
    return SymbolRef::ST_Debug;
1900
  case wasm::WASM_SYMBOL_TYPE_TAG:
1901
    return SymbolRef::ST_Other;
1902
  case wasm::WASM_SYMBOL_TYPE_TABLE:
1903
    return SymbolRef::ST_Other;
1904
  }
1905

1906
  llvm_unreachable("unknown WasmSymbol::SymbolType");
1907
  return SymbolRef::ST_Other;
1908
}
1909

1910
Expected<section_iterator>
1911
WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1912
  const WasmSymbol &Sym = getWasmSymbol(Symb);
1913
  if (Sym.isUndefined())
1914
    return section_end();
1915

1916
  DataRefImpl Ref;
1917
  Ref.d.a = getSymbolSectionIdImpl(Sym);
1918
  return section_iterator(SectionRef(Ref, this));
1919
}
1920

1921
uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const {
1922
  const WasmSymbol &Sym = getWasmSymbol(Symb);
1923
  return getSymbolSectionIdImpl(Sym);
1924
}
1925

1926
uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
1927
  switch (Sym.Info.Kind) {
1928
  case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1929
    return CodeSection;
1930
  case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1931
    return GlobalSection;
1932
  case wasm::WASM_SYMBOL_TYPE_DATA:
1933
    return DataSection;
1934
  case wasm::WASM_SYMBOL_TYPE_SECTION:
1935
    return Sym.Info.ElementIndex;
1936
  case wasm::WASM_SYMBOL_TYPE_TAG:
1937
    return TagSection;
1938
  case wasm::WASM_SYMBOL_TYPE_TABLE:
1939
    return TableSection;
1940
  default:
1941
    llvm_unreachable("unknown WasmSymbol::SymbolType");
1942
  }
1943
}
1944

1945
uint32_t WasmObjectFile::getSymbolSize(SymbolRef Symb) const {
1946
  const WasmSymbol &Sym = getWasmSymbol(Symb);
1947
  if (!Sym.isDefined())
1948
    return 0;
1949
  if (Sym.isTypeGlobal())
1950
    return getDefinedGlobal(Sym.Info.ElementIndex).Size;
1951
  if (Sym.isTypeData())
1952
    return Sym.Info.DataRef.Size;
1953
  if (Sym.isTypeFunction())
1954
    return functions()[Sym.Info.ElementIndex - getNumImportedFunctions()].Size;
1955
  // Currently symbol size is only tracked for data segments and functions. In
1956
  // principle we could also track size (e.g. binary size) for tables, globals
1957
  // and element segments etc too.
1958
  return 0;
1959
}
1960

1961
void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1962

1963
Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
1964
  const WasmSection &S = Sections[Sec.d.a];
1965
  if (S.Type == wasm::WASM_SEC_CUSTOM)
1966
    return S.Name;
1967
  if (S.Type > wasm::WASM_SEC_LAST_KNOWN)
1968
    return createStringError(object_error::invalid_section_index, "");
1969
  return wasm::sectionTypeToString(S.Type);
1970
}
1971

1972
uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const {
1973
  // For object files, use 0 for section addresses, and section offsets for
1974
  // symbol addresses. For linked files, use file offsets.
1975
  // See also getSymbolAddress.
1976
  return isRelocatableObject() || isSharedObject() ? 0
1977
                                                   : Sections[Sec.d.a].Offset;
1978
}
1979

1980
uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1981
  return Sec.d.a;
1982
}
1983

1984
uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1985
  const WasmSection &S = Sections[Sec.d.a];
1986
  return S.Content.size();
1987
}
1988

1989
Expected<ArrayRef<uint8_t>>
1990
WasmObjectFile::getSectionContents(DataRefImpl Sec) const {
1991
  const WasmSection &S = Sections[Sec.d.a];
1992
  // This will never fail since wasm sections can never be empty (user-sections
1993
  // must have a name and non-user sections each have a defined structure).
1994
  return S.Content;
1995
}
1996

1997
uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1998
  return 1;
1999
}
2000

2001
bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
2002
  return false;
2003
}
2004

2005
bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
2006
  return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
2007
}
2008

2009
bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
2010
  return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
2011
}
2012

2013
bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
2014

2015
bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
2016

2017
relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
2018
  DataRefImpl RelocRef;
2019
  RelocRef.d.a = Ref.d.a;
2020
  RelocRef.d.b = 0;
2021
  return relocation_iterator(RelocationRef(RelocRef, this));
2022
}
2023

2024
relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
2025
  const WasmSection &Sec = getWasmSection(Ref);
2026
  DataRefImpl RelocRef;
2027
  RelocRef.d.a = Ref.d.a;
2028
  RelocRef.d.b = Sec.Relocations.size();
2029
  return relocation_iterator(RelocationRef(RelocRef, this));
2030
}
2031

2032
void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
2033

2034
uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
2035
  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
2036
  return Rel.Offset;
2037
}
2038

2039
symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
2040
  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
2041
  if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
2042
    return symbol_end();
2043
  DataRefImpl Sym;
2044
  Sym.d.a = 1;
2045
  Sym.d.b = Rel.Index;
2046
  return symbol_iterator(SymbolRef(Sym, this));
2047
}
2048

2049
uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
2050
  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
2051
  return Rel.Type;
2052
}
2053

2054
void WasmObjectFile::getRelocationTypeName(
2055
    DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
2056
  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
2057
  StringRef Res = "Unknown";
2058

2059
#define WASM_RELOC(name, value)                                                \
2060
  case wasm::name:                                                             \
2061
    Res = #name;                                                               \
2062
    break;
2063

2064
  switch (Rel.Type) {
2065
#include "llvm/BinaryFormat/WasmRelocs.def"
2066
  }
2067

2068
#undef WASM_RELOC
2069

2070
  Result.append(Res.begin(), Res.end());
2071
}
2072

2073
section_iterator WasmObjectFile::section_begin() const {
2074
  DataRefImpl Ref;
2075
  Ref.d.a = 0;
2076
  return section_iterator(SectionRef(Ref, this));
2077
}
2078

2079
section_iterator WasmObjectFile::section_end() const {
2080
  DataRefImpl Ref;
2081
  Ref.d.a = Sections.size();
2082
  return section_iterator(SectionRef(Ref, this));
2083
}
2084

2085
uint8_t WasmObjectFile::getBytesInAddress() const {
2086
  return HasMemory64 ? 8 : 4;
2087
}
2088

2089
StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
2090

2091
Triple::ArchType WasmObjectFile::getArch() const {
2092
  return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
2093
}
2094

2095
Expected<SubtargetFeatures> WasmObjectFile::getFeatures() const {
2096
  return SubtargetFeatures();
2097
}
2098

2099
bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
2100

2101
bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
2102

2103
const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
2104
  assert(Ref.d.a < Sections.size());
2105
  return Sections[Ref.d.a];
2106
}
2107

2108
const WasmSection &
2109
WasmObjectFile::getWasmSection(const SectionRef &Section) const {
2110
  return getWasmSection(Section.getRawDataRefImpl());
2111
}
2112

2113
const wasm::WasmRelocation &
2114
WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
2115
  return getWasmRelocation(Ref.getRawDataRefImpl());
2116
}
2117

2118
const wasm::WasmRelocation &
2119
WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
2120
  assert(Ref.d.a < Sections.size());
2121
  const WasmSection &Sec = Sections[Ref.d.a];
2122
  assert(Ref.d.b < Sec.Relocations.size());
2123
  return Sec.Relocations[Ref.d.b];
2124
}
2125

2126
int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
2127
                                             StringRef CustomSectionName) {
2128
  switch (ID) {
2129
  case wasm::WASM_SEC_CUSTOM:
2130
    return StringSwitch<unsigned>(CustomSectionName)
2131
        .Case("dylink", WASM_SEC_ORDER_DYLINK)
2132
        .Case("dylink.0", WASM_SEC_ORDER_DYLINK)
2133
        .Case("linking", WASM_SEC_ORDER_LINKING)
2134
        .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
2135
        .Case("name", WASM_SEC_ORDER_NAME)
2136
        .Case("producers", WASM_SEC_ORDER_PRODUCERS)
2137
        .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
2138
        .Default(WASM_SEC_ORDER_NONE);
2139
  case wasm::WASM_SEC_TYPE:
2140
    return WASM_SEC_ORDER_TYPE;
2141
  case wasm::WASM_SEC_IMPORT:
2142
    return WASM_SEC_ORDER_IMPORT;
2143
  case wasm::WASM_SEC_FUNCTION:
2144
    return WASM_SEC_ORDER_FUNCTION;
2145
  case wasm::WASM_SEC_TABLE:
2146
    return WASM_SEC_ORDER_TABLE;
2147
  case wasm::WASM_SEC_MEMORY:
2148
    return WASM_SEC_ORDER_MEMORY;
2149
  case wasm::WASM_SEC_GLOBAL:
2150
    return WASM_SEC_ORDER_GLOBAL;
2151
  case wasm::WASM_SEC_EXPORT:
2152
    return WASM_SEC_ORDER_EXPORT;
2153
  case wasm::WASM_SEC_START:
2154
    return WASM_SEC_ORDER_START;
2155
  case wasm::WASM_SEC_ELEM:
2156
    return WASM_SEC_ORDER_ELEM;
2157
  case wasm::WASM_SEC_CODE:
2158
    return WASM_SEC_ORDER_CODE;
2159
  case wasm::WASM_SEC_DATA:
2160
    return WASM_SEC_ORDER_DATA;
2161
  case wasm::WASM_SEC_DATACOUNT:
2162
    return WASM_SEC_ORDER_DATACOUNT;
2163
  case wasm::WASM_SEC_TAG:
2164
    return WASM_SEC_ORDER_TAG;
2165
  default:
2166
    return WASM_SEC_ORDER_NONE;
2167
  }
2168
}
2169

2170
// Represents the edges in a directed graph where any node B reachable from node
2171
// A is not allowed to appear before A in the section ordering, but may appear
2172
// afterward.
2173
int WasmSectionOrderChecker::DisallowedPredecessors
2174
    [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
2175
        // WASM_SEC_ORDER_NONE
2176
        {},
2177
        // WASM_SEC_ORDER_TYPE
2178
        {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
2179
        // WASM_SEC_ORDER_IMPORT
2180
        {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
2181
        // WASM_SEC_ORDER_FUNCTION
2182
        {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
2183
        // WASM_SEC_ORDER_TABLE
2184
        {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
2185
        // WASM_SEC_ORDER_MEMORY
2186
        {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2187
        // WASM_SEC_ORDER_TAG
2188
        {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
2189
        // WASM_SEC_ORDER_GLOBAL
2190
        {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
2191
        // WASM_SEC_ORDER_EXPORT
2192
        {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
2193
        // WASM_SEC_ORDER_START
2194
        {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2195
        // WASM_SEC_ORDER_ELEM
2196
        {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2197
        // WASM_SEC_ORDER_DATACOUNT
2198
        {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2199
        // WASM_SEC_ORDER_CODE
2200
        {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2201
        // WASM_SEC_ORDER_DATA
2202
        {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2203

2204
        // Custom Sections
2205
        // WASM_SEC_ORDER_DYLINK
2206
        {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2207
        // WASM_SEC_ORDER_LINKING
2208
        {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2209
        // WASM_SEC_ORDER_RELOC (can be repeated)
2210
        {},
2211
        // WASM_SEC_ORDER_NAME
2212
        {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2213
        // WASM_SEC_ORDER_PRODUCERS
2214
        {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2215
        // WASM_SEC_ORDER_TARGET_FEATURES
2216
        {WASM_SEC_ORDER_TARGET_FEATURES}};
2217

2218
bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
2219
                                                  StringRef CustomSectionName) {
2220
  int Order = getSectionOrder(ID, CustomSectionName);
2221
  if (Order == WASM_SEC_ORDER_NONE)
2222
    return true;
2223

2224
  // Disallowed predecessors we need to check for
2225
  SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
2226

2227
  // Keep track of completed checks to avoid repeating work
2228
  bool Checked[WASM_NUM_SEC_ORDERS] = {};
2229

2230
  int Curr = Order;
2231
  while (true) {
2232
    // Add new disallowed predecessors to work list
2233
    for (size_t I = 0;; ++I) {
2234
      int Next = DisallowedPredecessors[Curr][I];
2235
      if (Next == WASM_SEC_ORDER_NONE)
2236
        break;
2237
      if (Checked[Next])
2238
        continue;
2239
      WorkList.push_back(Next);
2240
      Checked[Next] = true;
2241
    }
2242

2243
    if (WorkList.empty())
2244
      break;
2245

2246
    // Consider next disallowed predecessor
2247
    Curr = WorkList.pop_back_val();
2248
    if (Seen[Curr])
2249
      return false;
2250
  }
2251

2252
  // Have not seen any disallowed predecessors
2253
  Seen[Order] = true;
2254
  return true;
2255
}
2256

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.