Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Object/WasmObjectFile.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "llvm/ADT/ArrayRef.h"
10
#include "llvm/ADT/DenseSet.h"
11
#include "llvm/ADT/STLExtras.h"
12
#include "llvm/ADT/SmallSet.h"
13
#include "llvm/ADT/StringRef.h"
14
#include "llvm/ADT/StringSet.h"
15
#include "llvm/ADT/Triple.h"
16
#include "llvm/BinaryFormat/Wasm.h"
17
#include "llvm/MC/SubtargetFeature.h"
18
#include "llvm/Object/Binary.h"
19
#include "llvm/Object/Error.h"
20
#include "llvm/Object/ObjectFile.h"
21
#include "llvm/Object/SymbolicFile.h"
22
#include "llvm/Object/Wasm.h"
23
#include "llvm/Support/Endian.h"
24
#include "llvm/Support/Error.h"
25
#include "llvm/Support/ErrorHandling.h"
26
#include "llvm/Support/LEB128.h"
27
#include "llvm/Support/ScopedPrinter.h"
28
#include <algorithm>
29
#include <cassert>
30
#include <cstdint>
31
#include <cstring>
32
#include <system_error>
33
34
#define DEBUG_TYPE "wasm-object"
35
36
using namespace llvm;
37
using namespace object;
38
39
0
void WasmSymbol::print(raw_ostream &Out) const {
40
0
  Out << "Name=" << Info.Name
41
0
      << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
42
0
      << ", Flags=" << Info.Flags;
43
0
  if (!isTypeData()) {
44
0
    Out << ", ElemIndex=" << Info.ElementIndex;
45
0
  } else if (isDefined()) {
46
0
    Out << ", Segment=" << Info.DataRef.Segment;
47
0
    Out << ", Offset=" << Info.DataRef.Offset;
48
0
    Out << ", Size=" << Info.DataRef.Size;
49
0
  }
50
0
}
51
52
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
53
LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
54
#endif
55
56
Expected<std::unique_ptr<WasmObjectFile>>
57
844
ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
58
844
  Error Err = Error::success();
59
844
  auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err);
60
844
  if (Err)
61
13
    return std::move(Err);
62
831
63
831
  return std::move(ObjectFile);
64
831
}
65
66
#define VARINT7_MAX ((1 << 7) - 1)
67
#define VARINT7_MIN (-(1 << 7))
68
#define VARUINT7_MAX (1 << 7)
69
570
#define VARUINT1_MAX (1)
70
71
14.9k
static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
72
14.9k
  if (Ctx.Ptr == Ctx.End)
73
0
    report_fatal_error("EOF while reading uint8");
74
14.9k
  return *Ctx.Ptr++;
75
14.9k
}
76
77
843
static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
78
843
  if (Ctx.Ptr + 4 > Ctx.End)
79
0
    report_fatal_error("EOF while reading uint32");
80
843
  uint32_t Result = support::endian::read32le(Ctx.Ptr);
81
843
  Ctx.Ptr += 4;
82
843
  return Result;
83
843
}
84
85
0
static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
86
0
  if (Ctx.Ptr + 4 > Ctx.End)
87
0
    report_fatal_error("EOF while reading float64");
88
0
  int32_t Result = 0;
89
0
  memcpy(&Result, Ctx.Ptr, sizeof(Result));
90
0
  Ctx.Ptr += sizeof(Result);
91
0
  return Result;
92
0
}
93
94
0
static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
95
0
  if (Ctx.Ptr + 8 > Ctx.End)
96
0
    report_fatal_error("EOF while reading float64");
97
0
  int64_t Result = 0;
98
0
  memcpy(&Result, Ctx.Ptr, sizeof(Result));
99
0
  Ctx.Ptr += sizeof(Result);
100
0
  return Result;
101
0
}
102
103
44.3k
static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
104
44.3k
  unsigned Count;
105
44.3k
  const char *Error = nullptr;
106
44.3k
  uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
107
44.3k
  if (Error)
108
1
    report_fatal_error(Error);
109
44.3k
  Ctx.Ptr += Count;
110
44.3k
  return Result;
111
44.3k
}
112
113
8.13k
static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
114
8.13k
  uint32_t StringLen = readULEB128(Ctx);
115
8.13k
  if (Ctx.Ptr + StringLen > Ctx.End)
116
1
    report_fatal_error("EOF while reading string");
117
8.13k
  StringRef Return =
118
8.13k
      StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
119
8.13k
  Ctx.Ptr += StringLen;
120
8.13k
  return Return;
121
8.13k
}
122
123
1.90k
static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
124
1.90k
  unsigned Count;
125
1.90k
  const char *Error = nullptr;
126
1.90k
  uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
127
1.90k
  if (Error)
128
0
    report_fatal_error(Error);
129
1.90k
  Ctx.Ptr += Count;
130
1.90k
  return Result;
131
1.90k
}
132
133
285
static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
134
285
  int64_t Result = readLEB128(Ctx);
135
285
  if (Result > VARUINT1_MAX || Result < 0)
136
0
    report_fatal_error("LEB is outside Varuint1 range");
137
285
  return Result;
138
285
}
139
140
1.60k
static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
141
1.60k
  int64_t Result = readLEB128(Ctx);
142
1.60k
  if (Result > INT32_MAX || Result < INT32_MIN)
143
1.60k
    
report_fatal_error("LEB is outside Varint32 range")0
;
144
1.60k
  return Result;
145
1.60k
}
146
147
36.2k
static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
148
36.2k
  uint64_t Result = readULEB128(Ctx);
149
36.2k
  if (Result > UINT32_MAX)
150
36.2k
    
report_fatal_error("LEB is outside Varuint32 range")0
;
151
36.2k
  return Result;
152
36.2k
}
153
154
16
static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
155
16
  return readLEB128(Ctx);
156
16
}
157
158
1.65k
static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
159
1.65k
  return readUint8(Ctx);
160
1.65k
}
161
162
static Error readInitExpr(wasm::WasmInitExpr &Expr,
163
825
                          WasmObjectFile::ReadContext &Ctx) {
164
825
  Expr.Opcode = readOpcode(Ctx);
165
825
166
825
  switch (Expr.Opcode) {
167
825
  case wasm::WASM_OPCODE_I32_CONST:
168
801
    Expr.Value.Int32 = readVarint32(Ctx);
169
801
    break;
170
825
  case wasm::WASM_OPCODE_I64_CONST:
171
16
    Expr.Value.Int64 = readVarint64(Ctx);
172
16
    break;
173
825
  case wasm::WASM_OPCODE_F32_CONST:
174
0
    Expr.Value.Float32 = readFloat32(Ctx);
175
0
    break;
176
825
  case wasm::WASM_OPCODE_F64_CONST:
177
0
    Expr.Value.Float64 = readFloat64(Ctx);
178
0
    break;
179
825
  case wasm::WASM_OPCODE_GLOBAL_GET:
180
8
    Expr.Value.Global = readULEB128(Ctx);
181
8
    break;
182
825
  default:
183
0
    return make_error<GenericBinaryError>("Invalid opcode in init_expr",
184
0
                                          object_error::parse_failed);
185
825
  }
186
825
187
825
  uint8_t EndOpcode = readOpcode(Ctx);
188
825
  if (EndOpcode != wasm::WASM_OPCODE_END) {
189
0
    return make_error<GenericBinaryError>("Invalid init_expr",
190
0
                                          object_error::parse_failed);
191
0
  }
192
825
  return Error::success();
193
825
}
194
195
1.45k
static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
196
1.45k
  wasm::WasmLimits Result;
197
1.45k
  Result.Flags = readVaruint32(Ctx);
198
1.45k
  Result.Initial = readVaruint32(Ctx);
199
1.45k
  if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
200
151
    Result.Maximum = readVaruint32(Ctx);
201
1.45k
  return Result;
202
1.45k
}
203
204
726
static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) {
205
726
  wasm::WasmTable Table;
206
726
  Table.ElemType = readUint8(Ctx);
207
726
  Table.Limits = readLimits(Ctx);
208
726
  return Table;
209
726
}
210
211
static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
212
5.04k
                         WasmSectionOrderChecker &Checker) {
213
5.04k
  Section.Offset = Ctx.Ptr - Ctx.Start;
214
5.04k
  Section.Type = readUint8(Ctx);
215
5.04k
  LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
216
5.04k
  uint32_t Size = readVaruint32(Ctx);
217
5.04k
  if (Size == 0)
218
0
    return make_error<StringError>("Zero length section",
219
0
                                   object_error::parse_failed);
220
5.04k
  if (Ctx.Ptr + Size > Ctx.End)
221
2
    return make_error<StringError>("Section too large",
222
2
                                   object_error::parse_failed);
223
5.04k
  if (Section.Type == wasm::WASM_SEC_CUSTOM) {
224
1.48k
    WasmObjectFile::ReadContext SectionCtx;
225
1.48k
    SectionCtx.Start = Ctx.Ptr;
226
1.48k
    SectionCtx.Ptr = Ctx.Ptr;
227
1.48k
    SectionCtx.End = Ctx.Ptr + Size;
228
1.48k
229
1.48k
    Section.Name = readString(SectionCtx);
230
1.48k
231
1.48k
    uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
232
1.48k
    Ctx.Ptr += SectionNameSize;
233
1.48k
    Size -= SectionNameSize;
234
1.48k
  }
235
5.04k
236
5.04k
  if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
237
1
    return make_error<StringError>("Out of order section type: " +
238
1
                                       llvm::to_string(Section.Type),
239
1
                                   object_error::parse_failed);
240
1
  }
241
5.04k
242
5.04k
  Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
243
5.04k
  Ctx.Ptr += Size;
244
5.04k
  return Error::success();
245
5.04k
}
246
247
WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
248
844
    : ObjectFile(Binary::ID_Wasm, Buffer) {
249
844
  ErrorAsOutParameter ErrAsOutParam(&Err);
250
844
  Header.Magic = getData().substr(0, 4);
251
844
  if (Header.Magic != StringRef("\0asm", 4)) {
252
0
    Err =
253
0
        make_error<StringError>("Bad magic number", object_error::parse_failed);
254
0
    return;
255
0
  }
256
844
257
844
  ReadContext Ctx;
258
844
  Ctx.Start = getData().bytes_begin();
259
844
  Ctx.Ptr = Ctx.Start + 4;
260
844
  Ctx.End = Ctx.Start + getData().size();
261
844
262
844
  if (Ctx.Ptr + 4 > Ctx.End) {
263
1
    Err = make_error<StringError>("Missing version number",
264
1
                                  object_error::parse_failed);
265
1
    return;
266
1
  }
267
843
268
843
  Header.Version = readUint32(Ctx);
269
843
  if (Header.Version != wasm::WasmVersion) {
270
2
    Err = make_error<StringError>("Bad version number",
271
2
                                  object_error::parse_failed);
272
2
    return;
273
2
  }
274
841
275
841
  WasmSection Sec;
276
841
  WasmSectionOrderChecker Checker;
277
5.87k
  while (Ctx.Ptr < Ctx.End) {
278
5.04k
    if ((Err = readSection(Sec, Ctx, Checker)))
279
3
      return;
280
5.04k
    if ((Err = parseSection(Sec)))
281
7
      return;
282
5.03k
283
5.03k
    Sections.push_back(Sec);
284
5.03k
  }
285
841
}
286
287
5.03k
Error WasmObjectFile::parseSection(WasmSection &Sec) {
288
5.03k
  ReadContext Ctx;
289
5.03k
  Ctx.Start = Sec.Content.data();
290
5.03k
  Ctx.End = Ctx.Start + Sec.Content.size();
291
5.03k
  Ctx.Ptr = Ctx.Start;
292
5.03k
  switch (Sec.Type) {
293
5.03k
  case wasm::WASM_SEC_CUSTOM:
294
1.47k
    return parseCustomSection(Sec, Ctx);
295
5.03k
  case wasm::WASM_SEC_TYPE:
296
640
    return parseTypeSection(Ctx);
297
5.03k
  case wasm::WASM_SEC_IMPORT:
298
623
    return parseImportSection(Ctx);
299
5.03k
  case wasm::WASM_SEC_FUNCTION:
300
633
    return parseFunctionSection(Ctx);
301
5.03k
  case wasm::WASM_SEC_TABLE:
302
134
    return parseTableSection(Ctx);
303
5.03k
  case wasm::WASM_SEC_MEMORY:
304
134
    return parseMemorySection(Ctx);
305
5.03k
  case wasm::WASM_SEC_GLOBAL:
306
131
    return parseGlobalSection(Ctx);
307
5.03k
  case wasm::WASM_SEC_EVENT:
308
8
    return parseEventSection(Ctx);
309
5.03k
  case wasm::WASM_SEC_EXPORT:
310
126
    return parseExportSection(Ctx);
311
5.03k
  case wasm::WASM_SEC_START:
312
2
    return parseStartSection(Ctx);
313
5.03k
  case wasm::WASM_SEC_ELEM:
314
109
    return parseElemSection(Ctx);
315
5.03k
  case wasm::WASM_SEC_CODE:
316
632
    return parseCodeSection(Ctx);
317
5.03k
  case wasm::WASM_SEC_DATA:
318
228
    return parseDataSection(Ctx);
319
5.03k
  case wasm::WASM_SEC_DATACOUNT:
320
159
    return parseDataCountSection(Ctx);
321
5.03k
  default:
322
1
    return make_error<GenericBinaryError>(
323
1
        "Invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
324
5.03k
  }
325
5.03k
}
326
327
7
Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
328
7
  // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
329
7
  HasDylinkSection = true;
330
7
  DylinkInfo.MemorySize = readVaruint32(Ctx);
331
7
  DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
332
7
  DylinkInfo.TableSize = readVaruint32(Ctx);
333
7
  DylinkInfo.TableAlignment = readVaruint32(Ctx);
334
7
  uint32_t Count = readVaruint32(Ctx);
335
10
  while (Count--) {
336
3
    DylinkInfo.Needed.push_back(readString(Ctx));
337
3
  }
338
7
  if (Ctx.Ptr != Ctx.End)
339
0
    return make_error<GenericBinaryError>("dylink section ended prematurely",
340
0
                                          object_error::parse_failed);
341
7
  return Error::success();
342
7
}
343
344
111
Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
345
111
  llvm::DenseSet<uint64_t> Seen;
346
111
  if (Functions.size() != FunctionTypes.size()) {
347
0
    return make_error<GenericBinaryError>("Names must come after code section",
348
0
                                          object_error::parse_failed);
349
0
  }
350
111
351
221
  
while (111
Ctx.Ptr < Ctx.End) {
352
111
    uint8_t Type = readUint8(Ctx);
353
111
    uint32_t Size = readVaruint32(Ctx);
354
111
    const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
355
111
    switch (Type) {
356
111
    case wasm::WASM_NAMES_FUNCTION: {
357
111
      uint32_t Count = readVaruint32(Ctx);
358
613
      while (Count--) {
359
503
        uint32_t Index = readVaruint32(Ctx);
360
503
        if (!Seen.insert(Index).second)
361
1
          return make_error<GenericBinaryError>("Function named more than once",
362
1
                                                object_error::parse_failed);
363
502
        StringRef Name = readString(Ctx);
364
502
        if (!isValidFunctionIndex(Index) || Name.empty())
365
0
          return make_error<GenericBinaryError>("Invalid name entry",
366
0
                                                object_error::parse_failed);
367
502
        DebugNames.push_back(wasm::WasmFunctionName{Index, Name});
368
502
        if (isDefinedFunctionIndex(Index))
369
477
          getDefinedFunction(Index).DebugName = Name;
370
502
      }
371
111
      
break110
;
372
111
    }
373
111
    // Ignore local names for now
374
111
    case wasm::WASM_NAMES_LOCAL:
375
0
    default:
376
0
      Ctx.Ptr += Size;
377
0
      break;
378
110
    }
379
110
    if (Ctx.Ptr != SubSectionEnd)
380
0
      return make_error<GenericBinaryError>(
381
0
          "Name sub-section ended prematurely", object_error::parse_failed);
382
110
  }
383
111
384
111
  
if (110
Ctx.Ptr != Ctx.End110
)
385
0
    return make_error<GenericBinaryError>("Name section ended prematurely",
386
0
                                          object_error::parse_failed);
387
110
  return Error::success();
388
110
}
389
390
694
Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
391
694
  HasLinkingSection = true;
392
694
  if (Functions.size() != FunctionTypes.size()) {
393
0
    return make_error<GenericBinaryError>(
394
0
        "Linking data must come after code section",
395
0
        object_error::parse_failed);
396
0
  }
397
694
398
694
  LinkingData.Version = readVaruint32(Ctx);
399
694
  if (LinkingData.Version != wasm::WasmMetadataVersion) {
400
1
    return make_error<GenericBinaryError>(
401
1
        "Unexpected metadata version: " + Twine(LinkingData.Version) +
402
1
            " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
403
1
        object_error::parse_failed);
404
1
  }
405
693
406
693
  const uint8_t *OrigEnd = Ctx.End;
407
1.52k
  while (Ctx.Ptr < OrigEnd) {
408
830
    Ctx.End = OrigEnd;
409
830
    uint8_t Type = readUint8(Ctx);
410
830
    uint32_t Size = readVaruint32(Ctx);
411
830
    LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
412
830
                      << "\n");
413
830
    Ctx.End = Ctx.Ptr + Size;
414
830
    switch (Type) {
415
830
    case wasm::WASM_SYMBOL_TABLE:
416
606
      if (Error Err = parseLinkingSectionSymtab(Ctx))
417
1
        return Err;
418
605
      break;
419
605
    case wasm::WASM_SEGMENT_INFO: {
420
190
      uint32_t Count = readVaruint32(Ctx);
421
190
      if (Count > DataSegments.size())
422
0
        return make_error<GenericBinaryError>("Too many segment names",
423
0
                                              object_error::parse_failed);
424
660
      
for (uint32_t I = 0; 190
I < Count;
I++470
) {
425
470
        DataSegments[I].Data.Name = readString(Ctx);
426
470
        DataSegments[I].Data.Alignment = readVaruint32(Ctx);
427
470
        DataSegments[I].Data.LinkerFlags = readVaruint32(Ctx);
428
470
      }
429
190
      break;
430
190
    }
431
190
    case wasm::WASM_INIT_FUNCS: {
432
21
      uint32_t Count = readVaruint32(Ctx);
433
21
      LinkingData.InitFunctions.reserve(Count);
434
107
      for (uint32_t I = 0; I < Count; 
I++86
) {
435
86
        wasm::WasmInitFunc Init;
436
86
        Init.Priority = readVaruint32(Ctx);
437
86
        Init.Symbol = readVaruint32(Ctx);
438
86
        if (!isValidFunctionSymbol(Init.Symbol))
439
0
          return make_error<GenericBinaryError>("Invalid function symbol: " +
440
0
                                                    Twine(Init.Symbol),
441
0
                                                object_error::parse_failed);
442
86
        LinkingData.InitFunctions.emplace_back(Init);
443
86
      }
444
21
      break;
445
21
    }
446
21
    case wasm::WASM_COMDAT_INFO:
447
13
      if (Error Err = parseLinkingSectionComdat(Ctx))
448
0
        return Err;
449
13
      break;
450
13
    default:
451
0
      Ctx.Ptr += Size;
452
0
      break;
453
829
    }
454
829
    if (Ctx.Ptr != Ctx.End)
455
0
      return make_error<GenericBinaryError>(
456
0
          "Linking sub-section ended prematurely", object_error::parse_failed);
457
829
  }
458
693
  
if (692
Ctx.Ptr != OrigEnd692
)
459
0
    return make_error<GenericBinaryError>("Linking section ended prematurely",
460
0
                                          object_error::parse_failed);
461
692
  return Error::success();
462
692
}
463
464
606
Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
465
606
  uint32_t Count = readVaruint32(Ctx);
466
606
  LinkingData.SymbolTable.reserve(Count);
467
606
  Symbols.reserve(Count);
468
606
  StringSet<> SymbolNames;
469
606
470
606
  std::vector<wasm::WasmImport *> ImportedGlobals;
471
606
  std::vector<wasm::WasmImport *> ImportedFunctions;
472
606
  std::vector<wasm::WasmImport *> ImportedEvents;
473
606
  ImportedGlobals.reserve(Imports.size());
474
606
  ImportedFunctions.reserve(Imports.size());
475
606
  ImportedEvents.reserve(Imports.size());
476
1.48k
  for (auto &I : Imports) {
477
1.48k
    if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
478
282
      ImportedFunctions.emplace_back(&I);
479
1.19k
    else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
480
66
      ImportedGlobals.emplace_back(&I);
481
1.13k
    else if (I.Kind == wasm::WASM_EXTERNAL_EVENT)
482
0
      ImportedEvents.emplace_back(&I);
483
1.48k
  }
484
606
485
2.92k
  while (Count--) {
486
2.32k
    wasm::WasmSymbolInfo Info;
487
2.32k
    const wasm::WasmSignature *Signature = nullptr;
488
2.32k
    const wasm::WasmGlobalType *GlobalType = nullptr;
489
2.32k
    const wasm::WasmEventType *EventType = nullptr;
490
2.32k
491
2.32k
    Info.Kind = readUint8(Ctx);
492
2.32k
    Info.Flags = readVaruint32(Ctx);
493
2.32k
    bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
494
2.32k
495
2.32k
    switch (Info.Kind) {
496
2.32k
    case wasm::WASM_SYMBOL_TYPE_FUNCTION:
497
1.66k
      Info.ElementIndex = readVaruint32(Ctx);
498
1.66k
      if (!isValidFunctionIndex(Info.ElementIndex) ||
499
1.66k
          IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
500
0
        return make_error<GenericBinaryError>("invalid function symbol index",
501
0
                                              object_error::parse_failed);
502
1.66k
      if (IsDefined) {
503
1.38k
        Info.Name = readString(Ctx);
504
1.38k
        unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
505
1.38k
        Signature = &Signatures[FunctionTypes[FuncIndex]];
506
1.38k
        wasm::WasmFunction &Function = Functions[FuncIndex];
507
1.38k
        if (Function.SymbolName.empty())
508
1.36k
          Function.SymbolName = Info.Name;
509
1.38k
      } else {
510
282
        wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
511
282
        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
512
6
          Info.Name = readString(Ctx);
513
276
        else
514
276
          Info.Name = Import.Field;
515
282
        Signature = &Signatures[Import.SigIndex];
516
282
        Info.ImportName = Import.Field;
517
282
        Info.ImportModule = Import.Module;
518
282
      }
519
1.66k
      break;
520
1.66k
521
1.66k
    case wasm::WASM_SYMBOL_TYPE_GLOBAL:
522
63
      Info.ElementIndex = readVaruint32(Ctx);
523
63
      if (!isValidGlobalIndex(Info.ElementIndex) ||
524
63
          IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
525
0
        return make_error<GenericBinaryError>("invalid global symbol index",
526
0
                                              object_error::parse_failed);
527
63
      if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
528
52
                            wasm::WASM_SYMBOL_BINDING_WEAK)
529
1
        return make_error<GenericBinaryError>("undefined weak global symbol",
530
1
                                              object_error::parse_failed);
531
62
      if (IsDefined) {
532
11
        Info.Name = readString(Ctx);
533
11
        unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
534
11
        wasm::WasmGlobal &Global = Globals[GlobalIndex];
535
11
        GlobalType = &Global.Type;
536
11
        if (Global.SymbolName.empty())
537
11
          Global.SymbolName = Info.Name;
538
51
      } else {
539
51
        wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
540
51
        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
541
0
          Info.Name = readString(Ctx);
542
51
        else
543
51
          Info.Name = Import.Field;
544
51
        GlobalType = &Import.Global;
545
51
        Info.ImportName = Import.Field;
546
51
        Info.ImportModule = Import.Module;
547
51
      }
548
62
      break;
549
62
550
541
    case wasm::WASM_SYMBOL_TYPE_DATA:
551
541
      Info.Name = readString(Ctx);
552
541
      if (IsDefined) {
553
479
        uint32_t Index = readVaruint32(Ctx);
554
479
        if (Index >= DataSegments.size())
555
0
          return make_error<GenericBinaryError>("invalid data symbol index",
556
0
                                                object_error::parse_failed);
557
479
        uint32_t Offset = readVaruint32(Ctx);
558
479
        uint32_t Size = readVaruint32(Ctx);
559
479
        if (Offset + Size > DataSegments[Index].Data.Content.size())
560
0
          return make_error<GenericBinaryError>("invalid data symbol offset",
561
0
                                                object_error::parse_failed);
562
479
        Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
563
479
      }
564
541
      break;
565
541
566
541
    case wasm::WASM_SYMBOL_TYPE_SECTION: {
567
48
      if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
568
48
          wasm::WASM_SYMBOL_BINDING_LOCAL)
569
0
        return make_error<GenericBinaryError>(
570
0
            "Section symbols must have local binding",
571
0
            object_error::parse_failed);
572
48
      Info.ElementIndex = readVaruint32(Ctx);
573
48
      // Use somewhat unique section name as symbol name.
574
48
      StringRef SectionName = Sections[Info.ElementIndex].Name;
575
48
      Info.Name = SectionName;
576
48
      break;
577
48
    }
578
48
579
48
    case wasm::WASM_SYMBOL_TYPE_EVENT: {
580
7
      Info.ElementIndex = readVaruint32(Ctx);
581
7
      if (!isValidEventIndex(Info.ElementIndex) ||
582
7
          IsDefined != isDefinedEventIndex(Info.ElementIndex))
583
0
        return make_error<GenericBinaryError>("invalid event symbol index",
584
0
                                              object_error::parse_failed);
585
7
      if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
586
0
                            wasm::WASM_SYMBOL_BINDING_WEAK)
587
0
        return make_error<GenericBinaryError>("undefined weak global symbol",
588
0
                                              object_error::parse_failed);
589
7
      if (IsDefined) {
590
7
        Info.Name = readString(Ctx);
591
7
        unsigned EventIndex = Info.ElementIndex - NumImportedEvents;
592
7
        wasm::WasmEvent &Event = Events[EventIndex];
593
7
        Signature = &Signatures[Event.Type.SigIndex];
594
7
        EventType = &Event.Type;
595
7
        if (Event.SymbolName.empty())
596
7
          Event.SymbolName = Info.Name;
597
7
598
7
      } else {
599
0
        wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
600
0
        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
601
0
          Info.Name = readString(Ctx);
602
0
        else
603
0
          Info.Name = Import.Field;
604
0
        EventType = &Import.Event;
605
0
        Signature = &Signatures[EventType->SigIndex];
606
0
        Info.ImportName = Import.Field;
607
0
        Info.ImportModule = Import.Module;
608
0
      }
609
7
      break;
610
7
    }
611
7
612
7
    default:
613
0
      return make_error<GenericBinaryError>("Invalid symbol type",
614
0
                                            object_error::parse_failed);
615
2.32k
    }
616
2.32k
617
2.32k
    if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
618
2.32k
            wasm::WASM_SYMBOL_BINDING_LOCAL &&
619
2.32k
        
!SymbolNames.insert(Info.Name).second2.02k
)
620
0
      return make_error<GenericBinaryError>("Duplicate symbol name " +
621
0
                                                Twine(Info.Name),
622
0
                                            object_error::parse_failed);
623
2.32k
    LinkingData.SymbolTable.emplace_back(Info);
624
2.32k
    Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, EventType,
625
2.32k
                         Signature);
626
2.32k
    LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
627
2.32k
  }
628
606
629
606
  
return Error::success()605
;
630
606
}
631
632
13
Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
633
13
  uint32_t ComdatCount = readVaruint32(Ctx);
634
13
  StringSet<> ComdatSet;
635
27
  for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; 
++ComdatIndex14
) {
636
14
    StringRef Name = readString(Ctx);
637
14
    if (Name.empty() || !ComdatSet.insert(Name).second)
638
0
      return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
639
0
                                                Twine(Name),
640
0
                                            object_error::parse_failed);
641
14
    LinkingData.Comdats.emplace_back(Name);
642
14
    uint32_t Flags = readVaruint32(Ctx);
643
14
    if (Flags != 0)
644
0
      return make_error<GenericBinaryError>("Unsupported COMDAT flags",
645
0
                                            object_error::parse_failed);
646
14
647
14
    uint32_t EntryCount = readVaruint32(Ctx);
648
40
    while (EntryCount--) {
649
26
      unsigned Kind = readVaruint32(Ctx);
650
26
      unsigned Index = readVaruint32(Ctx);
651
26
      switch (Kind) {
652
26
      default:
653
0
        return make_error<GenericBinaryError>("Invalid COMDAT entry type",
654
0
                                              object_error::parse_failed);
655
26
      case wasm::WASM_COMDAT_DATA:
656
8
        if (Index >= DataSegments.size())
657
0
          return make_error<GenericBinaryError>(
658
0
              "COMDAT data index out of range", object_error::parse_failed);
659
8
        if (DataSegments[Index].Data.Comdat != UINT32_MAX)
660
8
          return make_error<GenericBinaryError>("Data segment in two COMDATs",
661
0
                                                object_error::parse_failed);
662
8
        DataSegments[Index].Data.Comdat = ComdatIndex;
663
8
        break;
664
18
      case wasm::WASM_COMDAT_FUNCTION:
665
18
        if (!isDefinedFunctionIndex(Index))
666
0
          return make_error<GenericBinaryError>(
667
0
              "COMDAT function index out of range", object_error::parse_failed);
668
18
        if (getDefinedFunction(Index).Comdat != UINT32_MAX)
669
18
          return make_error<GenericBinaryError>("Function in two COMDATs",
670
0
                                                object_error::parse_failed);
671
18
        getDefinedFunction(Index).Comdat = ComdatIndex;
672
18
        break;
673
26
      }
674
26
    }
675
14
  }
676
13
  return Error::success();
677
13
}
678
679
15
Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
680
15
  llvm::SmallSet<StringRef, 3> FieldsSeen;
681
15
  uint32_t Fields = readVaruint32(Ctx);
682
41
  for (size_t I = 0; I < Fields; 
++I26
) {
683
27
    StringRef FieldName = readString(Ctx);
684
27
    if (!FieldsSeen.insert(FieldName).second)
685
0
      return make_error<GenericBinaryError>(
686
0
          "Producers section does not have unique fields",
687
0
          object_error::parse_failed);
688
27
    std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
689
27
    if (FieldName == "language") {
690
12
      ProducerVec = &ProducerInfo.Languages;
691
15
    } else if (FieldName == "processed-by") {
692
14
      ProducerVec = &ProducerInfo.Tools;
693
14
    } else 
if (1
FieldName == "sdk"1
) {
694
1
      ProducerVec = &ProducerInfo.SDKs;
695
1
    } else {
696
0
      return make_error<GenericBinaryError>(
697
0
          "Producers section field is not named one of language, processed-by, "
698
0
          "or sdk",
699
0
          object_error::parse_failed);
700
0
    }
701
27
    uint32_t ValueCount = readVaruint32(Ctx);
702
27
    llvm::SmallSet<StringRef, 8> ProducersSeen;
703
54
    for (size_t J = 0; J < ValueCount; 
++J27
) {
704
28
      StringRef Name = readString(Ctx);
705
28
      StringRef Version = readString(Ctx);
706
28
      if (!ProducersSeen.insert(Name).second) {
707
1
        return make_error<GenericBinaryError>(
708
1
            "Producers section contains repeated producer",
709
1
            object_error::parse_failed);
710
1
      }
711
27
      ProducerVec->emplace_back(Name, Version);
712
27
    }
713
27
  }
714
15
  
if (14
Ctx.Ptr != Ctx.End14
)
715
0
    return make_error<GenericBinaryError>("Producers section ended prematurely",
716
0
                                          object_error::parse_failed);
717
14
  return Error::success();
718
14
}
719
720
149
Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
721
149
  llvm::SmallSet<std::string, 8> FeaturesSeen;
722
149
  uint32_t FeatureCount = readVaruint32(Ctx);
723
318
  for (size_t I = 0; I < FeatureCount; 
++I169
) {
724
169
    wasm::WasmFeatureEntry Feature;
725
169
    Feature.Prefix = readUint8(Ctx);
726
169
    switch (Feature.Prefix) {
727
169
    case wasm::WASM_FEATURE_PREFIX_USED:
728
169
    case wasm::WASM_FEATURE_PREFIX_REQUIRED:
729
169
    case wasm::WASM_FEATURE_PREFIX_DISALLOWED:
730
169
      break;
731
169
    default:
732
0
      return make_error<GenericBinaryError>("Unknown feature policy prefix",
733
0
                                            object_error::parse_failed);
734
169
    }
735
169
    Feature.Name = readString(Ctx);
736
169
    if (!FeaturesSeen.insert(Feature.Name).second)
737
0
      return make_error<GenericBinaryError>(
738
0
          "Target features section contains repeated feature \"" +
739
0
              Feature.Name + "\"",
740
0
          object_error::parse_failed);
741
169
    TargetFeatures.push_back(Feature);
742
169
  }
743
149
  if (Ctx.Ptr != Ctx.End)
744
0
    return make_error<GenericBinaryError>(
745
0
        "Target features section ended prematurely",
746
0
        object_error::parse_failed);
747
149
  return Error::success();
748
149
}
749
750
396
Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
751
396
  uint32_t SectionIndex = readVaruint32(Ctx);
752
396
  if (SectionIndex >= Sections.size())
753
0
    return make_error<GenericBinaryError>("Invalid section index",
754
0
                                          object_error::parse_failed);
755
396
  WasmSection &Section = Sections[SectionIndex];
756
396
  uint32_t RelocCount = readVaruint32(Ctx);
757
396
  uint32_t EndOffset = Section.Content.size();
758
396
  uint32_t PreviousOffset = 0;
759
1.91k
  while (RelocCount--) {
760
1.52k
    wasm::WasmRelocation Reloc = {};
761
1.52k
    Reloc.Type = readVaruint32(Ctx);
762
1.52k
    Reloc.Offset = readVaruint32(Ctx);
763
1.52k
    if (Reloc.Offset < PreviousOffset)
764
0
      return make_error<GenericBinaryError>("Relocations not in offset order",
765
0
                                            object_error::parse_failed);
766
1.52k
    PreviousOffset = Reloc.Offset;
767
1.52k
    Reloc.Index = readVaruint32(Ctx);
768
1.52k
    switch (Reloc.Type) {
769
1.52k
    case wasm::R_WASM_FUNCTION_INDEX_LEB:
770
577
    case wasm::R_WASM_TABLE_INDEX_SLEB:
771
577
    case wasm::R_WASM_TABLE_INDEX_I32:
772
577
    case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
773
577
      if (!isValidFunctionSymbol(Reloc.Index))
774
0
        return make_error<GenericBinaryError>("Bad relocation function index",
775
0
                                              object_error::parse_failed);
776
577
      break;
777
577
    case wasm::R_WASM_TYPE_INDEX_LEB:
778
42
      if (Reloc.Index >= Signatures.size())
779
0
        return make_error<GenericBinaryError>("Bad relocation type index",
780
0
                                              object_error::parse_failed);
781
42
      break;
782
112
    case wasm::R_WASM_GLOBAL_INDEX_LEB:
783
112
      // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
784
112
      // symbols to refer to thier GOT enties.
785
112
      if (!isValidGlobalSymbol(Reloc.Index) &&
786
112
          
!isValidDataSymbol(Reloc.Index)14
&&
787
112
          
!isValidFunctionSymbol(Reloc.Index)3
)
788
0
        return make_error<GenericBinaryError>("Bad relocation global index",
789
0
                                              object_error::parse_failed);
790
112
      break;
791
112
    case wasm::R_WASM_EVENT_INDEX_LEB:
792
9
      if (!isValidEventSymbol(Reloc.Index))
793
0
        return make_error<GenericBinaryError>("Bad relocation event index",
794
0
                                              object_error::parse_failed);
795
9
      break;
796
635
    case wasm::R_WASM_MEMORY_ADDR_LEB:
797
635
    case wasm::R_WASM_MEMORY_ADDR_SLEB:
798
635
    case wasm::R_WASM_MEMORY_ADDR_I32:
799
635
    case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
800
635
      if (!isValidDataSymbol(Reloc.Index))
801
0
        return make_error<GenericBinaryError>("Bad relocation data index",
802
0
                                              object_error::parse_failed);
803
635
      Reloc.Addend = readVarint32(Ctx);
804
635
      break;
805
635
    case wasm::R_WASM_FUNCTION_OFFSET_I32:
806
44
      if (!isValidFunctionSymbol(Reloc.Index))
807
0
        return make_error<GenericBinaryError>("Bad relocation function index",
808
0
                                              object_error::parse_failed);
809
44
      Reloc.Addend = readVarint32(Ctx);
810
44
      break;
811
104
    case wasm::R_WASM_SECTION_OFFSET_I32:
812
104
      if (!isValidSectionSymbol(Reloc.Index))
813
0
        return make_error<GenericBinaryError>("Bad relocation section index",
814
0
                                              object_error::parse_failed);
815
104
      Reloc.Addend = readVarint32(Ctx);
816
104
      break;
817
104
    default:
818
0
      return make_error<GenericBinaryError>("Bad relocation type: " +
819
0
                                                Twine(Reloc.Type),
820
0
                                            object_error::parse_failed);
821
1.52k
    }
822
1.52k
823
1.52k
    // Relocations must fit inside the section, and must appear in order.  They
824
1.52k
    // also shouldn't overlap a function/element boundary, but we don't bother
825
1.52k
    // to check that.
826
1.52k
    uint64_t Size = 5;
827
1.52k
    if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
828
1.52k
        
Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I321.45k
||
829
1.52k
        
Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I321.40k
||
830
1.52k
        
Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I321.30k
)
831
267
      Size = 4;
832
1.52k
    if (Reloc.Offset + Size > EndOffset)
833
0
      return make_error<GenericBinaryError>("Bad relocation offset",
834
0
                                            object_error::parse_failed);
835
1.52k
836
1.52k
    Section.Relocations.push_back(Reloc);
837
1.52k
  }
838
396
  if (Ctx.Ptr != Ctx.End)
839
0
    return make_error<GenericBinaryError>("Reloc section ended prematurely",
840
0
                                          object_error::parse_failed);
841
396
  return Error::success();
842
396
}
843
844
1.47k
Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
845
1.47k
  if (Sec.Name == "dylink") {
846
7
    if (Error Err = parseDylinkSection(Ctx))
847
0
      return Err;
848
1.47k
  } else if (Sec.Name == "name") {
849
111
    if (Error Err = parseNameSection(Ctx))
850
1
      return Err;
851
1.36k
  } else if (Sec.Name == "linking") {
852
694
    if (Error Err = parseLinkingSection(Ctx))
853
2
      return Err;
854
667
  } else if (Sec.Name == "producers") {
855
15
    if (Error Err = parseProducersSection(Ctx))
856
1
      return Err;
857
652
  } else if (Sec.Name == "target_features") {
858
149
    if (Error Err = parseTargetFeaturesSection(Ctx))
859
0
      return Err;
860
503
  } else if (Sec.Name.startswith("reloc.")) {
861
396
    if (Error Err = parseRelocSection(Sec.Name, Ctx))
862
0
      return Err;
863
1.47k
  }
864
1.47k
  return Error::success();
865
1.47k
}
866
867
640
Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
868
640
  uint32_t Count = readVaruint32(Ctx);
869
640
  Signatures.reserve(Count);
870
1.65k
  while (Count--) {
871
1.01k
    wasm::WasmSignature Sig;
872
1.01k
    uint8_t Form = readUint8(Ctx);
873
1.01k
    if (Form != wasm::WASM_TYPE_FUNC) {
874
0
      return make_error<GenericBinaryError>("Invalid signature type",
875
0
                                            object_error::parse_failed);
876
0
    }
877
1.01k
    uint32_t ParamCount = readVaruint32(Ctx);
878
1.01k
    Sig.Params.reserve(ParamCount);
879
1.35k
    while (ParamCount--) {
880
341
      uint32_t ParamType = readUint8(Ctx);
881
341
      Sig.Params.push_back(wasm::ValType(ParamType));
882
341
    }
883
1.01k
    uint32_t ReturnCount = readVaruint32(Ctx);
884
1.01k
    if (ReturnCount) {
885
484
      if (ReturnCount != 1) {
886
0
        return make_error<GenericBinaryError>(
887
0
            "Multiple return types not supported", object_error::parse_failed);
888
0
      }
889
484
      Sig.Returns.push_back(wasm::ValType(readUint8(Ctx)));
890
484
    }
891
1.01k
    Signatures.push_back(std::move(Sig));
892
1.01k
  }
893
640
  if (Ctx.Ptr != Ctx.End)
894
0
    return make_error<GenericBinaryError>("Type section ended prematurely",
895
0
                                          object_error::parse_failed);
896
640
  return Error::success();
897
640
}
898
899
623
Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
900
623
  uint32_t Count = readVaruint32(Ctx);
901
623
  Imports.reserve(Count);
902
2.19k
  for (uint32_t I = 0; I < Count; 
I++1.57k
) {
903
1.57k
    wasm::WasmImport Im;
904
1.57k
    Im.Module = readString(Ctx);
905
1.57k
    Im.Field = readString(Ctx);
906
1.57k
    Im.Kind = readUint8(Ctx);
907
1.57k
    switch (Im.Kind) {
908
1.57k
    case wasm::WASM_EXTERNAL_FUNCTION:
909
300
      NumImportedFunctions++;
910
300
      Im.SigIndex = readVaruint32(Ctx);
911
300
      break;
912
1.57k
    case wasm::WASM_EXTERNAL_GLOBAL:
913
90
      NumImportedGlobals++;
914
90
      Im.Global.Type = readUint8(Ctx);
915
90
      Im.Global.Mutable = readVaruint1(Ctx);
916
90
      break;
917
1.57k
    case wasm::WASM_EXTERNAL_MEMORY:
918
593
      Im.Memory = readLimits(Ctx);
919
593
      break;
920
1.57k
    case wasm::WASM_EXTERNAL_TABLE:
921
592
      Im.Table = readTable(Ctx);
922
592
      if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF)
923
0
        return make_error<GenericBinaryError>("Invalid table element type",
924
0
                                              object_error::parse_failed);
925
592
      break;
926
592
    case wasm::WASM_EXTERNAL_EVENT:
927
0
      NumImportedEvents++;
928
0
      Im.Event.Attribute = readVarint32(Ctx);
929
0
      Im.Event.SigIndex = readVarint32(Ctx);
930
0
      break;
931
592
    default:
932
0
      return make_error<GenericBinaryError>("Unexpected import kind",
933
0
                                            object_error::parse_failed);
934
1.57k
    }
935
1.57k
    Imports.push_back(Im);
936
1.57k
  }
937
623
  if (Ctx.Ptr != Ctx.End)
938
0
    return make_error<GenericBinaryError>("Import section ended prematurely",
939
0
                                          object_error::parse_failed);
940
623
  return Error::success();
941
623
}
942
943
633
Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
944
633
  uint32_t Count = readVaruint32(Ctx);
945
633
  FunctionTypes.reserve(Count);
946
633
  uint32_t NumTypes = Signatures.size();
947
2.29k
  while (Count--) {
948
1.66k
    uint32_t Type = readVaruint32(Ctx);
949
1.66k
    if (Type >= NumTypes)
950
0
      return make_error<GenericBinaryError>("Invalid function type",
951
0
                                            object_error::parse_failed);
952
1.66k
    FunctionTypes.push_back(Type);
953
1.66k
  }
954
633
  if (Ctx.Ptr != Ctx.End)
955
0
    return make_error<GenericBinaryError>("Function section ended prematurely",
956
0
                                          object_error::parse_failed);
957
633
  return Error::success();
958
633
}
959
960
134
Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
961
134
  uint32_t Count = readVaruint32(Ctx);
962
134
  Tables.reserve(Count);
963
268
  while (Count--) {
964
134
    Tables.push_back(readTable(Ctx));
965
134
    if (Tables.back().ElemType != wasm::WASM_TYPE_FUNCREF) {
966
0
      return make_error<GenericBinaryError>("Invalid table element type",
967
0
                                            object_error::parse_failed);
968
0
    }
969
134
  }
970
134
  if (Ctx.Ptr != Ctx.End)
971
0
    return make_error<GenericBinaryError>("Table section ended prematurely",
972
0
                                          object_error::parse_failed);
973
134
  return Error::success();
974
134
}
975
976
134
Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
977
134
  uint32_t Count = readVaruint32(Ctx);
978
134
  Memories.reserve(Count);
979
269
  while (Count--) {
980
135
    Memories.push_back(readLimits(Ctx));
981
135
  }
982
134
  if (Ctx.Ptr != Ctx.End)
983
0
    return make_error<GenericBinaryError>("Memory section ended prematurely",
984
0
                                          object_error::parse_failed);
985
134
  return Error::success();
986
134
}
987
988
131
Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
989
131
  GlobalSection = Sections.size();
990
131
  uint32_t Count = readVaruint32(Ctx);
991
131
  Globals.reserve(Count);
992
326
  while (Count--) {
993
195
    wasm::WasmGlobal Global;
994
195
    Global.Index = NumImportedGlobals + Globals.size();
995
195
    Global.Type.Type = readUint8(Ctx);
996
195
    Global.Type.Mutable = readVaruint1(Ctx);
997
195
    if (Error Err = readInitExpr(Global.InitExpr, Ctx))
998
0
      return Err;
999
195
    Globals.push_back(Global);
1000
195
  }
1001
131
  if (Ctx.Ptr != Ctx.End)
1002
0
    return make_error<GenericBinaryError>("Global section ended prematurely",
1003
0
                                          object_error::parse_failed);
1004
131
  return Error::success();
1005
131
}
1006
1007
8
Error WasmObjectFile::parseEventSection(ReadContext &Ctx) {
1008
8
  EventSection = Sections.size();
1009
8
  uint32_t Count = readVarint32(Ctx);
1010
8
  Events.reserve(Count);
1011
16
  while (Count--) {
1012
8
    wasm::WasmEvent Event;
1013
8
    Event.Index = NumImportedEvents + Events.size();
1014
8
    Event.Type.Attribute = readVaruint32(Ctx);
1015
8
    Event.Type.SigIndex = readVarint32(Ctx);
1016
8
    Events.push_back(Event);
1017
8
  }
1018
8
1019
8
  if (Ctx.Ptr != Ctx.End)
1020
0
    return make_error<GenericBinaryError>("Event section ended prematurely",
1021
0
                                          object_error::parse_failed);
1022
8
  return Error::success();
1023
8
}
1024
1025
126
Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1026
126
  uint32_t Count = readVaruint32(Ctx);
1027
126
  Exports.reserve(Count);
1028
443
  for (uint32_t I = 0; I < Count; 
I++317
) {
1029
318
    wasm::WasmExport Ex;
1030
318
    Ex.Name = readString(Ctx);
1031
318
    Ex.Kind = readUint8(Ctx);
1032
318
    Ex.Index = readVaruint32(Ctx);
1033
318
    switch (Ex.Kind) {
1034
318
    case wasm::WASM_EXTERNAL_FUNCTION:
1035
160
      if (!isValidFunctionIndex(Ex.Index))
1036
1
        return make_error<GenericBinaryError>("Invalid function export",
1037
1
                                              object_error::parse_failed);
1038
159
      break;
1039
159
    case wasm::WASM_EXTERNAL_GLOBAL:
1040
39
      if (!isValidGlobalIndex(Ex.Index))
1041
0
        return make_error<GenericBinaryError>("Invalid global export",
1042
0
                                              object_error::parse_failed);
1043
39
      break;
1044
39
    case wasm::WASM_EXTERNAL_EVENT:
1045
0
      if (!isValidEventIndex(Ex.Index))
1046
0
        return make_error<GenericBinaryError>("Invalid event export",
1047
0
                                              object_error::parse_failed);
1048
0
      break;
1049
119
    case wasm::WASM_EXTERNAL_MEMORY:
1050
119
    case wasm::WASM_EXTERNAL_TABLE:
1051
119
      break;
1052
119
    default:
1053
0
      return make_error<GenericBinaryError>("Unexpected export kind",
1054
0
                                            object_error::parse_failed);
1055
317
    }
1056
317
    Exports.push_back(Ex);
1057
317
  }
1058
126
  
if (125
Ctx.Ptr != Ctx.End125
)
1059
0
    return make_error<GenericBinaryError>("Export section ended prematurely",
1060
0
                                          object_error::parse_failed);
1061
125
  return Error::success();
1062
125
}
1063
1064
4.23k
bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1065
4.23k
  return Index < NumImportedFunctions + FunctionTypes.size();
1066
4.23k
}
1067
1068
2.22k
bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
1069
2.22k
  return Index >= NumImportedFunctions && 
isValidFunctionIndex(Index)1.91k
;
1070
2.22k
}
1071
1072
113
bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
1073
113
  return Index < NumImportedGlobals + Globals.size();
1074
113
}
1075
1076
63
bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
1077
63
  return Index >= NumImportedGlobals && 
isValidGlobalIndex(Index)11
;
1078
63
}
1079
1080
14
bool WasmObjectFile::isValidEventIndex(uint32_t Index) const {
1081
14
  return Index < NumImportedEvents + Events.size();
1082
14
}
1083
1084
7
bool WasmObjectFile::isDefinedEventIndex(uint32_t Index) const {
1085
7
  return Index >= NumImportedEvents && isValidEventIndex(Index);
1086
7
}
1087
1088
710
bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1089
710
  return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1090
710
}
1091
1092
112
bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1093
112
  return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1094
112
}
1095
1096
9
bool WasmObjectFile::isValidEventSymbol(uint32_t Index) const {
1097
9
  return Index < Symbols.size() && Symbols[Index].isTypeEvent();
1098
9
}
1099
1100
649
bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1101
649
  return Index < Symbols.size() && Symbols[Index].isTypeData();
1102
649
}
1103
1104
104
bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1105
104
  return Index < Symbols.size() && Symbols[Index].isTypeSection();
1106
104
}
1107
1108
513
wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1109
513
  assert(isDefinedFunctionIndex(Index));
1110
513
  return Functions[Index - NumImportedFunctions];
1111
513
}
1112
1113
const wasm::WasmFunction &
1114
35
WasmObjectFile::getDefinedFunction(uint32_t Index) const {
1115
35
  assert(isDefinedFunctionIndex(Index));
1116
35
  return Functions[Index - NumImportedFunctions];
1117
35
}
1118
1119
0
wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
1120
0
  assert(isDefinedGlobalIndex(Index));
1121
0
  return Globals[Index - NumImportedGlobals];
1122
0
}
1123
1124
0
wasm::WasmEvent &WasmObjectFile::getDefinedEvent(uint32_t Index) {
1125
0
  assert(isDefinedEventIndex(Index));
1126
0
  return Events[Index - NumImportedEvents];
1127
0
}
1128
1129
2
Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1130
2
  StartFunction = readVaruint32(Ctx);
1131
2
  if (!isValidFunctionIndex(StartFunction))
1132
1
    return make_error<GenericBinaryError>("Invalid start function",
1133
1
                                          object_error::parse_failed);
1134
1
  return Error::success();
1135
1
}
1136
1137
632
Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1138
632
  CodeSection = Sections.size();
1139
632
  uint32_t FunctionCount = readVaruint32(Ctx);
1140
632
  if (FunctionCount != FunctionTypes.size()) {
1141
0
    return make_error<GenericBinaryError>("Invalid function count",
1142
0
                                          object_error::parse_failed);
1143
0
  }
1144
632
1145
2.29k
  
while (632
FunctionCount--) {
1146
1.66k
    wasm::WasmFunction Function;
1147
1.66k
    const uint8_t *FunctionStart = Ctx.Ptr;
1148
1.66k
    uint32_t Size = readVaruint32(Ctx);
1149
1.66k
    const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1150
1.66k
1151
1.66k
    Function.CodeOffset = Ctx.Ptr - FunctionStart;
1152
1.66k
    Function.Index = NumImportedFunctions + Functions.size();
1153
1.66k
    Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1154
1.66k
    Function.Size = FunctionEnd - FunctionStart;
1155
1.66k
1156
1.66k
    uint32_t NumLocalDecls = readVaruint32(Ctx);
1157
1.66k
    Function.Locals.reserve(NumLocalDecls);
1158
1.71k
    while (NumLocalDecls--) {
1159
47
      wasm::WasmLocalDecl Decl;
1160
47
      Decl.Count = readVaruint32(Ctx);
1161
47
      Decl.Type = readUint8(Ctx);
1162
47
      Function.Locals.push_back(Decl);
1163
47
    }
1164
1.66k
1165
1.66k
    uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1166
1.66k
    Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1167
1.66k
    // This will be set later when reading in the linking metadata section.
1168
1.66k
    Function.Comdat = UINT32_MAX;
1169
1.66k
    Ctx.Ptr += BodySize;
1170
1.66k
    assert(Ctx.Ptr == FunctionEnd);
1171
1.66k
    Functions.push_back(Function);
1172
1.66k
  }
1173
632
  if (Ctx.Ptr != Ctx.End)
1174
0
    return make_error<GenericBinaryError>("Code section ended prematurely",
1175
0
                                          object_error::parse_failed);
1176
632
  return Error::success();
1177
632
}
1178
1179
109
Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1180
109
  uint32_t Count = readVaruint32(Ctx);
1181
109
  ElemSegments.reserve(Count);
1182
218
  while (Count--) {
1183
109
    wasm::WasmElemSegment Segment;
1184
109
    Segment.TableIndex = readVaruint32(Ctx);
1185
109
    if (Segment.TableIndex != 0) {
1186
0
      return make_error<GenericBinaryError>("Invalid TableIndex",
1187
0
                                            object_error::parse_failed);
1188
0
    }
1189
109
    if (Error Err = readInitExpr(Segment.Offset, Ctx))
1190
0
      return Err;
1191
109
    uint32_t NumElems = readVaruint32(Ctx);
1192
298
    while (NumElems--) {
1193
189
      Segment.Functions.push_back(readVaruint32(Ctx));
1194
189
    }
1195
109
    ElemSegments.push_back(Segment);
1196
109
  }
1197
109
  if (Ctx.Ptr != Ctx.End)
1198
0
    return make_error<GenericBinaryError>("Elem section ended prematurely",
1199
0
                                          object_error::parse_failed);
1200
109
  return Error::success();
1201
109
}
1202
1203
228
Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1204
228
  DataSection = Sections.size();
1205
228
  uint32_t Count = readVaruint32(Ctx);
1206
228
  if (DataCount && 
Count != DataCount.getValue()159
)
1207
0
    return make_error<GenericBinaryError>(
1208
0
        "Number of data segments does not match DataCount section");
1209
228
  DataSegments.reserve(Count);
1210
773
  while (Count--) {
1211
545
    WasmSegment Segment;
1212
545
    Segment.Data.InitFlags = readVaruint32(Ctx);
1213
545
    Segment.Data.MemoryIndex = (Segment.Data.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
1214
545
                               ? 
readVaruint32(Ctx)1
:
0544
;
1215
545
    if ((Segment.Data.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0) {
1216
521
      if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1217
0
        return Err;
1218
24
    } else {
1219
24
      Segment.Data.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST;
1220
24
      Segment.Data.Offset.Value.Int32 = 0;
1221
24
    }
1222
545
    uint32_t Size = readVaruint32(Ctx);
1223
545
    if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1224
0
      return make_error<GenericBinaryError>("Invalid segment size",
1225
0
                                            object_error::parse_failed);
1226
545
    Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1227
545
    // The rest of these Data fields are set later, when reading in the linking
1228
545
    // metadata section.
1229
545
    Segment.Data.Alignment = 0;
1230
545
    Segment.Data.LinkerFlags = 0;
1231
545
    Segment.Data.Comdat = UINT32_MAX;
1232
545
    Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1233
545
    Ctx.Ptr += Size;
1234
545
    DataSegments.push_back(Segment);
1235
545
  }
1236
228
  if (Ctx.Ptr != Ctx.End)
1237
0
    return make_error<GenericBinaryError>("Data section ended prematurely",
1238
0
                                          object_error::parse_failed);
1239
228
  return Error::success();
1240
228
}
1241
1242
159
Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1243
159
  DataCount = readVaruint32(Ctx);
1244
159
  return Error::success();
1245
159
}
1246
1247
177
const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1248
177
  return Header;
1249
177
}
1250
1251
1.03k
void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
1252
1253
213
uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
1254
213
  uint32_t Result = SymbolRef::SF_None;
1255
213
  const WasmSymbol &Sym = getWasmSymbol(Symb);
1256
213
1257
213
  LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1258
213
  if (Sym.isBindingWeak())
1259
22
    Result |= SymbolRef::SF_Weak;
1260
213
  if (!Sym.isBindingLocal())
1261
187
    Result |= SymbolRef::SF_Global;
1262
213
  if (Sym.isHidden())
1263
20
    Result |= SymbolRef::SF_Hidden;
1264
213
  if (!Sym.isDefined())
1265
41
    Result |= SymbolRef::SF_Undefined;
1266
213
  if (Sym.isTypeFunction())
1267
143
    Result |= SymbolRef::SF_Executable;
1268
213
  return Result;
1269
213
}
1270
1271
354
basic_symbol_iterator WasmObjectFile::symbol_begin() const {
1272
354
  DataRefImpl Ref;
1273
354
  Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1274
354
  Ref.d.b = 0; // Symbol index
1275
354
  return BasicSymbolRef(Ref, this);
1276
354
}
1277
1278
416
basic_symbol_iterator WasmObjectFile::symbol_end() const {
1279
416
  DataRefImpl Ref;
1280
416
  Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1281
416
  Ref.d.b = Symbols.size(); // Symbol index
1282
416
  return BasicSymbolRef(Ref, this);
1283
416
}
1284
1285
1.41k
const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
1286
1.41k
  return Symbols[Symb.d.b];
1287
1.41k
}
1288
1289
0
const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1290
0
  return getWasmSymbol(Symb.getRawDataRefImpl());
1291
0
}
1292
1293
113
Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
1294
113
  return getWasmSymbol(Symb).Info.Name;
1295
113
}
1296
1297
66
Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
1298
66
  auto &Sym = getWasmSymbol(Symb);
1299
66
  if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1300
66
      
isDefinedFunctionIndex(Sym.Info.ElementIndex)42
)
1301
35
    return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset;
1302
31
  else
1303
31
    return getSymbolValue(Symb);
1304
66
}
1305
1306
21
uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
1307
21
  switch (Sym.Info.Kind) {
1308
21
  case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1309
2
  case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1310
2
  case wasm::WASM_SYMBOL_TYPE_EVENT:
1311
2
    return Sym.Info.ElementIndex;
1312
14
  case wasm::WASM_SYMBOL_TYPE_DATA: {
1313
14
    // The value of a data symbol is the segment offset, plus the symbol
1314
14
    // offset within the segment.
1315
14
    uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1316
14
    const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1317
14
    assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST);
1318
14
    return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
1319
2
  }
1320
5
  case wasm::WASM_SYMBOL_TYPE_SECTION:
1321
5
    return 0;
1322
0
  }
1323
0
  llvm_unreachable("invalid symbol type");
1324
0
}
1325
1326
21
uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1327
21
  return getWasmSymbolValue(getWasmSymbol(Symb));
1328
21
}
1329
1330
0
uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1331
0
  llvm_unreachable("not yet implemented");
1332
0
  return 0;
1333
0
}
1334
1335
0
uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1336
0
  llvm_unreachable("not yet implemented");
1337
0
  return 0;
1338
0
}
1339
1340
Expected<SymbolRef::Type>
1341
16
WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
1342
16
  const WasmSymbol &Sym = getWasmSymbol(Symb);
1343
16
1344
16
  switch (Sym.Info.Kind) {
1345
16
  case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1346
10
    return SymbolRef::ST_Function;
1347
16
  case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1348
0
    return SymbolRef::ST_Other;
1349
16
  case wasm::WASM_SYMBOL_TYPE_DATA:
1350
6
    return SymbolRef::ST_Data;
1351
16
  case wasm::WASM_SYMBOL_TYPE_SECTION:
1352
0
    return SymbolRef::ST_Debug;
1353
16
  case wasm::WASM_SYMBOL_TYPE_EVENT:
1354
0
    return SymbolRef::ST_Other;
1355
0
  }
1356
0
1357
0
  llvm_unreachable("Unknown WasmSymbol::SymbolType");
1358
0
  return SymbolRef::ST_Other;
1359
0
}
1360
1361
Expected<section_iterator>
1362
27
WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1363
27
  const WasmSymbol &Sym = getWasmSymbol(Symb);
1364
27
  if (Sym.isUndefined())
1365
2
    return section_end();
1366
25
1367
25
  DataRefImpl Ref;
1368
25
  switch (Sym.Info.Kind) {
1369
25
  case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1370
12
    Ref.d.a = CodeSection;
1371
12
    break;
1372
25
  case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1373
0
    Ref.d.a = GlobalSection;
1374
0
    break;
1375
25
  case wasm::WASM_SYMBOL_TYPE_DATA:
1376
8
    Ref.d.a = DataSection;
1377
8
    break;
1378
25
  case wasm::WASM_SYMBOL_TYPE_SECTION:
1379
5
    Ref.d.a = Sym.Info.ElementIndex;
1380
5
    break;
1381
25
  case wasm::WASM_SYMBOL_TYPE_EVENT:
1382
0
    Ref.d.a = EventSection;
1383
0
    break;
1384
25
  default:
1385
0
    llvm_unreachable("Unknown WasmSymbol::SymbolType");
1386
25
  }
1387
25
  return section_iterator(SectionRef(Ref, this));
1388
25
}
1389
1390
3.23k
void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1391
1392
269
Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
1393
269
  const WasmSection &S = Sections[Sec.d.a];
1394
269
#define ECase(X)                                                               \
1395
269
  case wasm::WASM_SEC_##X:                                                     \
1396
135
    return #X;
1397
269
  switch (S.Type) {
1398
269
    
ECase19
(TYPE);
1399
13
    ECase
(IMPORT)0
;
1400
18
    ECase
(FUNCTION)0
;
1401
6
    ECase
(TABLE)0
;
1402
6
    ECase
(MEMORY)0
;
1403
6
    ECase
(GLOBAL)0
;
1404
0
    ECase(EVENT);
1405
6
    ECase
(EXPORT)0
;
1406
0
    ECase(START);
1407
5
    ECase
(ELEM)0
;
1408
30
    ECase
(CODE)0
;
1409
20
    ECase
(DATA)0
;
1410
6
    ECase
(DATACOUNT)0
;
1411
134
  case wasm::WASM_SEC_CUSTOM:
1412
134
    return S.Name;
1413
0
  default:
1414
0
    return createStringError(object_error::invalid_section_index, "");
1415
269
  }
1416
269
#undef ECase
1417
269
}
1418
1419
23
uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1420
1421
20
uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1422
20
  return Sec.d.a;
1423
20
}
1424
1425
16
uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1426
16
  const WasmSection &S = Sections[Sec.d.a];
1427
16
  return S.Content.size();
1428
16
}
1429
1430
Expected<ArrayRef<uint8_t>>
1431
66
WasmObjectFile::getSectionContents(DataRefImpl Sec) const {
1432
66
  const WasmSection &S = Sections[Sec.d.a];
1433
66
  // This will never fail since wasm sections can never be empty (user-sections
1434
66
  // must have a name and non-user sections each have a defined structure).
1435
66
  return S.Content;
1436
66
}
1437
1438
0
uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1439
0
  return 1;
1440
0
}
1441
1442
56
bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1443
56
  return false;
1444
56
}
1445
1446
13
bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
1447
13
  return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1448
13
}
1449
1450
7
bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
1451
7
  return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1452
7
}
1453
1454
71
bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1455
1456
60
bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1457
1458
0
bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
1459
1460
85
relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1461
85
  DataRefImpl RelocRef;
1462
85
  RelocRef.d.a = Ref.d.a;
1463
85
  RelocRef.d.b = 0;
1464
85
  return relocation_iterator(RelocationRef(RelocRef, this));
1465
85
}
1466
1467
85
relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1468
85
  const WasmSection &Sec = getWasmSection(Ref);
1469
85
  DataRefImpl RelocRef;
1470
85
  RelocRef.d.a = Ref.d.a;
1471
85
  RelocRef.d.b = Sec.Relocations.size();
1472
85
  return relocation_iterator(RelocationRef(RelocRef, this));
1473
85
}
1474
1475
59
void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
1476
1477
59
uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1478
59
  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1479
59
  return Rel.Offset;
1480
59
}
1481
1482
59
symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
1483
59
  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1484
59
  if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
1485
3
    return symbol_end();
1486
56
  DataRefImpl Sym;
1487
56
  Sym.d.a = 1;
1488
56
  Sym.d.b = Rel.Index;
1489
56
  return symbol_iterator(SymbolRef(Sym, this));
1490
56
}
1491
1492
75
uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1493
75
  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1494
75
  return Rel.Type;
1495
75
}
1496
1497
void WasmObjectFile::getRelocationTypeName(
1498
43
    DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1499
43
  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1500
43
  StringRef Res = "Unknown";
1501
43
1502
43
#define WASM_RELOC(name, value)                                                \
1503
43
  case wasm::name:                                                             \
1504
43
    Res = #name;                                                               \
1505
43
    break;
1506
43
1507
43
  switch (Rel.Type) {
1508
43
#include 
"llvm/BinaryFormat/WasmRelocs.def"10
1509
43
  }
1510
43
1511
43
#undef WASM_RELOC
1512
43
1513
43
  Result.append(Res.begin(), Res.end());
1514
43
}
1515
1516
513
section_iterator WasmObjectFile::section_begin() const {
1517
513
  DataRefImpl Ref;
1518
513
  Ref.d.a = 0;
1519
513
  return section_iterator(SectionRef(Ref, this));
1520
513
}
1521
1522
626
section_iterator WasmObjectFile::section_end() const {
1523
626
  DataRefImpl Ref;
1524
626
  Ref.d.a = Sections.size();
1525
626
  return section_iterator(SectionRef(Ref, this));
1526
626
}
1527
1528
43
uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1529
1530
34
StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1531
1532
33
Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
1533
1534
1
SubtargetFeatures WasmObjectFile::getFeatures() const {
1535
1
  return SubtargetFeatures();
1536
1
}
1537
1538
317
bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1539
1540
273
bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
1541
1542
3.18k
const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
1543
3.18k
  assert(Ref.d.a < Sections.size());
1544
3.18k
  return Sections[Ref.d.a];
1545
3.18k
}
1546
1547
const WasmSection &
1548
3.07k
WasmObjectFile::getWasmSection(const SectionRef &Section) const {
1549
3.07k
  return getWasmSection(Section.getRawDataRefImpl());
1550
3.07k
}
1551
1552
const wasm::WasmRelocation &
1553
43
WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1554
43
  return getWasmRelocation(Ref.getRawDataRefImpl());
1555
43
}
1556
1557
const wasm::WasmRelocation &
1558
279
WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
1559
279
  assert(Ref.d.a < Sections.size());
1560
279
  const WasmSection &Sec = Sections[Ref.d.a];
1561
279
  assert(Ref.d.b < Sec.Relocations.size());
1562
279
  return Sec.Relocations[Ref.d.b];
1563
279
}
1564
1565
int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1566
5.17k
                                             StringRef CustomSectionName) {
1567
5.17k
  switch (ID) {
1568
5.17k
  case wasm::WASM_SEC_CUSTOM:
1569
1.53k
    return StringSwitch<unsigned>(CustomSectionName)
1570
1.53k
        .Case("dylink", WASM_SEC_ORDER_DYLINK)
1571
1.53k
        .Case("linking", WASM_SEC_ORDER_LINKING)
1572
1.53k
        .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
1573
1.53k
        .Case("name", WASM_SEC_ORDER_NAME)
1574
1.53k
        .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1575
1.53k
        .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
1576
1.53k
        .Default(WASM_SEC_ORDER_NONE);
1577
5.17k
  case wasm::WASM_SEC_TYPE:
1578
660
    return WASM_SEC_ORDER_TYPE;
1579
5.17k
  case wasm::WASM_SEC_IMPORT:
1580
636
    return WASM_SEC_ORDER_IMPORT;
1581
5.17k
  case wasm::WASM_SEC_FUNCTION:
1582
646
    return WASM_SEC_ORDER_FUNCTION;
1583
5.17k
  case wasm::WASM_SEC_TABLE:
1584
136
    return WASM_SEC_ORDER_TABLE;
1585
5.17k
  case wasm::WASM_SEC_MEMORY:
1586
136
    return WASM_SEC_ORDER_MEMORY;
1587
5.17k
  case wasm::WASM_SEC_GLOBAL:
1588
137
    return WASM_SEC_ORDER_GLOBAL;
1589
5.17k
  case wasm::WASM_SEC_EXPORT:
1590
129
    return WASM_SEC_ORDER_EXPORT;
1591
5.17k
  case wasm::WASM_SEC_START:
1592
4
    return WASM_SEC_ORDER_START;
1593
5.17k
  case wasm::WASM_SEC_ELEM:
1594
110
    return WASM_SEC_ORDER_ELEM;
1595
5.17k
  case wasm::WASM_SEC_CODE:
1596
646
    return WASM_SEC_ORDER_CODE;
1597
5.17k
  case wasm::WASM_SEC_DATA:
1598
234
    return WASM_SEC_ORDER_DATA;
1599
5.17k
  case wasm::WASM_SEC_DATACOUNT:
1600
159
    return WASM_SEC_ORDER_DATACOUNT;
1601
5.17k
  case wasm::WASM_SEC_EVENT:
1602
9
    return WASM_SEC_ORDER_EVENT;
1603
5.17k
  default:
1604
1
    return WASM_SEC_ORDER_NONE;
1605
5.17k
  }
1606
5.17k
}
1607
1608
// Represents the edges in a directed graph where any node B reachable from node
1609
// A is not allowed to appear before A in the section ordering, but may appear
1610
// afterward.
1611
int WasmSectionOrderChecker::DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
1612
  {}, // WASM_SEC_ORDER_NONE
1613
  {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT}, // WASM_SEC_ORDER_TYPE,
1614
  {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION}, // WASM_SEC_ORDER_IMPORT,
1615
  {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE}, // WASM_SEC_ORDER_FUNCTION,
1616
  {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY}, // WASM_SEC_ORDER_TABLE,
1617
  {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_GLOBAL}, // WASM_SEC_ORDER_MEMORY,
1618
  {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EVENT}, // WASM_SEC_ORDER_GLOBAL,
1619
  {WASM_SEC_ORDER_EVENT, WASM_SEC_ORDER_EXPORT}, // WASM_SEC_ORDER_EVENT,
1620
  {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START}, // WASM_SEC_ORDER_EXPORT,
1621
  {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM}, // WASM_SEC_ORDER_START,
1622
  {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT}, // WASM_SEC_ORDER_ELEM,
1623
  {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE}, // WASM_SEC_ORDER_DATACOUNT,
1624
  {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA}, // WASM_SEC_ORDER_CODE,
1625
  {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING}, // WASM_SEC_ORDER_DATA,
1626
1627
  // Custom Sections
1628
  {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE}, // WASM_SEC_ORDER_DYLINK,
1629
  {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME}, // WASM_SEC_ORDER_LINKING,
1630
  {}, // WASM_SEC_ORDER_RELOC (can be repeated),
1631
  {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS}, // WASM_SEC_ORDER_NAME,
1632
  {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES}, // WASM_SEC_ORDER_PRODUCERS,
1633
  {WASM_SEC_ORDER_TARGET_FEATURES}  // WASM_SEC_ORDER_TARGET_FEATURES
1634
};
1635
1636
bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
1637
5.17k
                                                  StringRef CustomSectionName) {
1638
5.17k
  int Order = getSectionOrder(ID, CustomSectionName);
1639
5.17k
  if (Order == WASM_SEC_ORDER_NONE)
1640
111
    return true;
1641
5.06k
1642
5.06k
  // Disallowed predecessors we need to check for
1643
5.06k
  SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
1644
5.06k
1645
5.06k
  // Keep track of completed checks to avoid repeating work
1646
5.06k
  bool Checked[WASM_NUM_SEC_ORDERS] = {};
1647
5.06k
1648
5.06k
  int Curr = Order;
1649
57.8k
  while (true) {
1650
57.8k
    // Add new disallowed predecessors to work list
1651
164k
    for (size_t I = 0;; 
++I106k
) {
1652
164k
      int Next = DisallowedPredecessors[Curr][I];
1653
164k
      if (Next == WASM_SEC_ORDER_NONE)
1654
57.8k
        break;
1655
106k
      if (Checked[Next])
1656
53.6k
        continue;
1657
52.8k
      WorkList.push_back(Next);
1658
52.8k
      Checked[Next] = true;
1659
52.8k
    }
1660
57.8k
1661
57.8k
    if (WorkList.empty())
1662
5.06k
      break;
1663
52.8k
1664
52.8k
    // Consider next disallowed predecessor
1665
52.8k
    Curr = WorkList.pop_back_val();
1666
52.8k
    if (Seen[Curr])
1667
2
      return false;
1668
52.8k
  }
1669
5.06k
1670
5.06k
  // Have not seen any disallowed predecessors
1671
5.06k
  Seen[Order] = true;
1672
5.06k
  return true;
1673
5.06k
}