Coverage Report

Created: 2025-12-28 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wabt/src/binary-reader.cc
Line
Count
Source
1
/*
2
 * Copyright 2016 WebAssembly Community Group participants
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#include "wabt/binary-reader.h"
18
19
#include <cassert>
20
#include <cinttypes>
21
#include <cstdarg>
22
#include <cstdint>
23
#include <cstdio>
24
#include <cstring>
25
#include <stack>
26
#include <vector>
27
28
#include "wabt/config.h"
29
30
#include "wabt/binary-reader-logging.h"
31
#include "wabt/binary.h"
32
#include "wabt/leb128.h"
33
#include "wabt/stream.h"
34
#include "wabt/utf8.h"
35
36
#if HAVE_ALLOCA
37
#include <alloca.h>
38
#endif
39
40
#define ERROR(...)           \
41
10.7M
  do {                       \
42
10.7M
    PrintError(__VA_ARGS__); \
43
10.7M
    return Result::Error;    \
44
10.7M
  } while (0)
45
46
#define ERROR_IF(expr, ...) \
47
220M
  do {                      \
48
268M
    if (expr) {             \
49
10.7M
      ERROR(__VA_ARGS__);   \
50
10.7M
    }                       \
51
220M
  } while (0)
52
53
219M
#define ERROR_UNLESS(expr, ...) ERROR_IF(!(expr), __VA_ARGS__)
54
55
#define ERROR_UNLESS_OPCODE_ENABLED(opcode)     \
56
14.6M
  do {                                          \
57
14.6M
    if (!opcode.IsEnabled(options_.features)) { \
58
871
      return ReportUnexpectedOpcode(opcode);    \
59
871
    }                                           \
60
14.6M
  } while (0)
61
62
#define CALLBACK0(member) \
63
23.3M
  ERROR_UNLESS(Succeeded(delegate_->member()), #member " callback failed")
64
65
#define CALLBACK(member, ...)                             \
66
61.9M
  ERROR_UNLESS(Succeeded(delegate_->member(__VA_ARGS__)), \
67
61.9M
               #member " callback failed")
68
69
namespace wabt {
70
71
namespace {
72
73
class BinaryReader {
74
 public:
75
  struct ReadModuleOptions {
76
    bool stop_on_first_error;
77
  };
78
79
  BinaryReader(const void* data,
80
               size_t size,
81
               BinaryReaderDelegate* delegate,
82
               const ReadBinaryOptions& options);
83
84
  Result ReadModule(const ReadModuleOptions& options);
85
86
 private:
87
  template <typename T, T BinaryReader::*member>
88
  struct ValueRestoreGuard {
89
    explicit ValueRestoreGuard(BinaryReader* this_)
90
18.9M
        : this_(this_), previous_value_(this_->*member) {}
binary-reader.cc:wabt::(anonymous namespace)::BinaryReader::ValueRestoreGuard<unsigned long, &wabt::(anonymous namespace)::BinaryReader::read_end_>::ValueRestoreGuard(wabt::(anonymous namespace)::BinaryReader*)
Line
Count
Source
90
14.0M
        : this_(this_), previous_value_(this_->*member) {}
binary-reader.cc:wabt::(anonymous namespace)::BinaryReader::ValueRestoreGuard<bool, &wabt::(anonymous namespace)::BinaryReader::reading_custom_section_>::ValueRestoreGuard(wabt::(anonymous namespace)::BinaryReader*)
Line
Count
Source
90
2.43M
        : this_(this_), previous_value_(this_->*member) {}
binary-reader.cc:wabt::(anonymous namespace)::BinaryReader::ValueRestoreGuard<wabt::BinaryReaderDelegate::State, &wabt::(anonymous namespace)::BinaryReader::state_>::ValueRestoreGuard(wabt::(anonymous namespace)::BinaryReader*)
Line
Count
Source
90
2.43M
        : this_(this_), previous_value_(this_->*member) {}
91
18.9M
    ~ValueRestoreGuard() { this_->*member = previous_value_; }
binary-reader.cc:wabt::(anonymous namespace)::BinaryReader::ValueRestoreGuard<wabt::BinaryReaderDelegate::State, &wabt::(anonymous namespace)::BinaryReader::state_>::~ValueRestoreGuard()
Line
Count
Source
91
2.43M
    ~ValueRestoreGuard() { this_->*member = previous_value_; }
binary-reader.cc:wabt::(anonymous namespace)::BinaryReader::ValueRestoreGuard<bool, &wabt::(anonymous namespace)::BinaryReader::reading_custom_section_>::~ValueRestoreGuard()
Line
Count
Source
91
2.43M
    ~ValueRestoreGuard() { this_->*member = previous_value_; }
binary-reader.cc:wabt::(anonymous namespace)::BinaryReader::ValueRestoreGuard<unsigned long, &wabt::(anonymous namespace)::BinaryReader::read_end_>::~ValueRestoreGuard()
Line
Count
Source
91
14.0M
    ~ValueRestoreGuard() { this_->*member = previous_value_; }
92
93
    BinaryReader* this_;
94
    T previous_value_;
95
  };
96
97
  struct ReadSectionsOptions {
98
    bool stop_on_first_error;
99
  };
100
101
  void WABT_PRINTF_FORMAT(2, 3) PrintError(const char* format, ...);
102
  [[nodiscard]] Result ReadOpcode(Opcode* out_value, const char* desc);
103
  template <typename T>
104
  [[nodiscard]] Result ReadT(T* out_value,
105
                             const char* type_name,
106
                             const char* desc);
107
  [[nodiscard]] Result ReadU8(uint8_t* out_value, const char* desc);
108
  [[nodiscard]] Result ReadU16(uint16_t* out_value, const char* desc);
109
  [[nodiscard]] Result ReadU32(uint32_t* out_value, const char* desc);
110
  [[nodiscard]] Result ReadF32(uint32_t* out_value, const char* desc);
111
  [[nodiscard]] Result ReadF64(uint64_t* out_value, const char* desc);
112
  [[nodiscard]] Result ReadV128(v128* out_value, const char* desc);
113
  [[nodiscard]] Result ReadU32Leb128(uint32_t* out_value, const char* desc);
114
  [[nodiscard]] Result ReadU64Leb128(uint64_t* out_value, const char* desc);
115
  [[nodiscard]] Result ReadS32Leb128(uint32_t* out_value, const char* desc);
116
  [[nodiscard]] Result ReadS64Leb128(uint64_t* out_value, const char* desc);
117
  [[nodiscard]] Result ReadType(Type* out_value, const char* desc);
118
  [[nodiscard]] Result ReadRefType(Type* out_value, const char* desc);
119
  [[nodiscard]] Result ReadExternalKind(ExternalKind* out_value,
120
                                        const char* desc);
121
  [[nodiscard]] Result ReadStr(std::string_view* out_str, const char* desc);
122
  [[nodiscard]] Result ReadBytes(const void** out_data,
123
                                 Address* out_data_size,
124
                                 const char* desc);
125
  [[nodiscard]] Result ReadBytesWithSize(const void** out_data,
126
                                         Offset size,
127
                                         const char* desc);
128
  [[nodiscard]] Result ReadIndex(Index* index, const char* desc);
129
  [[nodiscard]] Result ReadOffset(Offset* offset, const char* desc);
130
  [[nodiscard]] Result ReadAlignment(Address* align_log2, const char* desc);
131
  [[nodiscard]] Result CheckAlignment(Address* align_log2, const char* desc);
132
  [[nodiscard]] Result TakeHasMemidx(Address* align_log2, bool* has_memidx);
133
  [[nodiscard]] Result ReadMemidx(Index* memidx, const char* desc);
134
  [[nodiscard]] Result ReadMemLocation(Address* alignment_log2,
135
                                       Index* memidx,
136
                                       Address* offset,
137
                                       const char* desc_align,
138
                                       const char* desc_memidx,
139
                                       const char* desc_offset,
140
                                       uint8_t* lane_val = nullptr);
141
  [[nodiscard]] Result CallbackMemLocation(const Address* alignment_log2,
142
                                           const Index* memidx,
143
                                           const Address* offset,
144
                                           const uint8_t* lane_val = nullptr);
145
  [[nodiscard]] Result ReadCount(Index* index, const char* desc);
146
  [[nodiscard]] Result ReadField(TypeMut* out_value);
147
148
  bool IsConcreteReferenceType(Type::Enum);
149
  bool IsConcreteType(Type);
150
  bool IsBlockType(Type);
151
152
  Index NumTotalFuncs();
153
154
  [[nodiscard]] Result ReadInitExpr(Index index);
155
  [[nodiscard]] Result ReadTable(Limits* out_elem_limits);
156
  [[nodiscard]] Result ReadMemory(Limits* out_page_limits,
157
                                  uint32_t* out_page_size);
158
  [[nodiscard]] Result ReadGlobalHeader(Type* out_type, bool* out_mutable);
159
  [[nodiscard]] Result ReadTagType(Index* out_sig_index);
160
  [[nodiscard]] Result ReadAddress(Address* out_value,
161
                                   Index memory,
162
                                   const char* desc);
163
  [[nodiscard]] Result ReadFunctionBody(Offset end_offset);
164
  // ReadInstructions reads until end_offset or the nesting depth reaches zero.
165
  [[nodiscard]] Result ReadInstructions(Offset end_offset, const char* context);
166
  [[nodiscard]] Result ReadNameSection(Offset section_size);
167
  [[nodiscard]] Result ReadRelocSection(Offset section_size);
168
  [[nodiscard]] Result ReadDylinkSection(Offset section_size);
169
  [[nodiscard]] Result ReadGenericCustomSection(std::string_view name,
170
                                                Offset section_size);
171
  [[nodiscard]] Result ReadDylink0Section(Offset section_size);
172
  [[nodiscard]] Result ReadTargetFeaturesSections(Offset section_size);
173
  [[nodiscard]] Result ReadLinkingSection(Offset section_size);
174
  [[nodiscard]] Result ReadCodeMetadataSection(std::string_view name,
175
                                               Offset section_size);
176
  [[nodiscard]] Result ReadCustomSection(Index section_index,
177
                                         Offset section_size);
178
  [[nodiscard]] Result ReadTypeSection(Offset section_size);
179
  [[nodiscard]] Result ReadImportSection(Offset section_size);
180
  [[nodiscard]] Result ReadFunctionSection(Offset section_size);
181
  [[nodiscard]] Result ReadTableSection(Offset section_size);
182
  [[nodiscard]] Result ReadMemorySection(Offset section_size);
183
  [[nodiscard]] Result ReadGlobalSection(Offset section_size);
184
  [[nodiscard]] Result ReadExportSection(Offset section_size);
185
  [[nodiscard]] Result ReadStartSection(Offset section_size);
186
  [[nodiscard]] Result ReadElemSection(Offset section_size);
187
  [[nodiscard]] Result ReadCodeSection(Offset section_size);
188
  [[nodiscard]] Result ReadDataSection(Offset section_size);
189
  [[nodiscard]] Result ReadDataCountSection(Offset section_size);
190
  [[nodiscard]] Result ReadTagSection(Offset section_size);
191
  [[nodiscard]] Result ReadSections(const ReadSectionsOptions& options);
192
  Result ReportUnexpectedOpcode(Opcode opcode, const char* message = nullptr);
193
194
  size_t read_end_ = 0;  // Either the section end or data_size.
195
  BinaryReaderDelegate::State state_;
196
  BinaryReaderLogging logging_delegate_;
197
  BinaryReaderDelegate* delegate_ = nullptr;
198
  TypeVector param_types_;
199
  TypeVector result_types_;
200
  TypeMutVector fields_;
201
  std::vector<Index> target_depths_;
202
  CatchClauseVector catches_;
203
  const ReadBinaryOptions& options_;
204
  BinarySection last_known_section_ = BinarySection::Invalid;
205
  bool did_read_names_section_ = false;
206
  bool reading_custom_section_ = false;
207
  Index num_func_imports_ = 0;
208
  Index num_table_imports_ = 0;
209
  Index num_memory_imports_ = 0;
210
  Index num_global_imports_ = 0;
211
  Index num_tag_imports_ = 0;
212
  Index num_function_signatures_ = 0;
213
  Index num_function_bodies_ = 0;
214
  Index num_data_segments_ = 0;
215
  Index data_count_ = kInvalidIndex;
216
217
  using ReadEndRestoreGuard =
218
      ValueRestoreGuard<size_t, &BinaryReader::read_end_>;
219
};
220
221
BinaryReader::BinaryReader(const void* data,
222
                           size_t size,
223
                           BinaryReaderDelegate* delegate,
224
                           const ReadBinaryOptions& options)
225
93.4k
    : read_end_(size),
226
93.4k
      state_(static_cast<const uint8_t*>(data), size),
227
93.4k
      logging_delegate_(options.log_stream, delegate),
228
93.4k
      delegate_(options.log_stream ? &logging_delegate_ : delegate),
229
93.4k
      options_(options),
230
93.4k
      last_known_section_(BinarySection::Invalid) {
231
93.4k
  delegate->OnSetState(&state_);
232
93.4k
}
233
234
void WABT_PRINTF_FORMAT(2, 3) BinaryReader::PrintError(const char* format,
235
11.5M
                                                       ...) {
236
11.5M
  ErrorLevel error_level =
237
11.5M
      reading_custom_section_ && !options_.fail_on_custom_section_error
238
11.5M
          ? ErrorLevel::Warning
239
11.5M
          : ErrorLevel::Error;
240
241
11.5M
  WABT_SNPRINTF_ALLOCA(buffer, length, format);
242
11.5M
  Error error(error_level, Location(state_.offset), buffer);
243
11.5M
  bool handled = delegate_->OnError(error);
244
245
11.5M
  if (!handled) {
246
    // Not great to just print, but we don't want to eat the error either.
247
1.73M
    fprintf(stderr, "%07" PRIzx ": %s: %s\n", state_.offset,
248
1.73M
            GetErrorLevelName(error_level), buffer);
249
1.73M
  }
250
11.5M
}
251
252
5.47k
Result BinaryReader::ReportUnexpectedOpcode(Opcode opcode, const char* where) {
253
5.47k
  std::string message = "unexpected opcode";
254
5.47k
  if (where) {
255
0
    message += ' ';
256
0
    message += where;
257
0
  }
258
259
5.47k
  message += ":";
260
261
5.47k
  std::vector<uint8_t> bytes = opcode.GetBytes();
262
5.47k
  assert(bytes.size() > 0);
263
264
7.63k
  for (uint8_t byte : bytes) {
265
7.63k
    message += StringPrintf(" 0x%x", byte);
266
7.63k
  }
267
268
5.47k
  PrintError("%s", message.c_str());
269
5.47k
  return Result::Error;
270
5.47k
}
271
272
14.6M
Result BinaryReader::ReadOpcode(Opcode* out_value, const char* desc) {
273
14.6M
  uint8_t value = 0;
274
14.6M
  CHECK_RESULT(ReadU8(&value, desc));
275
276
14.6M
  if (Opcode::IsPrefixByte(value)) {
277
755k
    uint32_t code;
278
755k
    CHECK_RESULT(ReadU32Leb128(&code, desc));
279
754k
    *out_value = Opcode::FromCode(value, code);
280
13.8M
  } else {
281
13.8M
    *out_value = Opcode::FromCode(value);
282
13.8M
  }
283
14.6M
  return Result::Ok;
284
14.6M
}
285
286
template <typename T>
287
Result BinaryReader::ReadT(T* out_value,
288
                           const char* type_name,
289
30.4M
                           const char* desc) {
290
30.4M
  if (state_.offset + sizeof(T) > read_end_) {
291
18.6k
    PrintError("unable to read %s: %s", type_name, desc);
292
18.6k
    return Result::Error;
293
18.6k
  }
294
#if WABT_BIG_ENDIAN
295
  uint8_t tmp[sizeof(T)];
296
  memcpy(tmp, state_.data + state_.offset, sizeof(tmp));
297
  SwapBytesSized(tmp, sizeof(tmp));
298
  memcpy(out_value, tmp, sizeof(T));
299
#else
300
30.4M
  memcpy(out_value, state_.data + state_.offset, sizeof(T));
301
30.4M
#endif
302
30.4M
  state_.offset += sizeof(T);
303
30.4M
  return Result::Ok;
304
30.4M
}
binary-reader.cc:wabt::Result wabt::(anonymous namespace)::BinaryReader::ReadT<unsigned int>(unsigned int*, char const*, char const*)
Line
Count
Source
289
153k
                           const char* desc) {
290
153k
  if (state_.offset + sizeof(T) > read_end_) {
291
192
    PrintError("unable to read %s: %s", type_name, desc);
292
192
    return Result::Error;
293
192
  }
294
#if WABT_BIG_ENDIAN
295
  uint8_t tmp[sizeof(T)];
296
  memcpy(tmp, state_.data + state_.offset, sizeof(tmp));
297
  SwapBytesSized(tmp, sizeof(tmp));
298
  memcpy(out_value, tmp, sizeof(T));
299
#else
300
153k
  memcpy(out_value, state_.data + state_.offset, sizeof(T));
301
153k
#endif
302
153k
  state_.offset += sizeof(T);
303
153k
  return Result::Ok;
304
153k
}
binary-reader.cc:wabt::Result wabt::(anonymous namespace)::BinaryReader::ReadT<unsigned short>(unsigned short*, char const*, char const*)
Line
Count
Source
289
185k
                           const char* desc) {
290
185k
  if (state_.offset + sizeof(T) > read_end_) {
291
28
    PrintError("unable to read %s: %s", type_name, desc);
292
28
    return Result::Error;
293
28
  }
294
#if WABT_BIG_ENDIAN
295
  uint8_t tmp[sizeof(T)];
296
  memcpy(tmp, state_.data + state_.offset, sizeof(tmp));
297
  SwapBytesSized(tmp, sizeof(tmp));
298
  memcpy(out_value, tmp, sizeof(T));
299
#else
300
185k
  memcpy(out_value, state_.data + state_.offset, sizeof(T));
301
185k
#endif
302
185k
  state_.offset += sizeof(T);
303
185k
  return Result::Ok;
304
185k
}
binary-reader.cc:wabt::Result wabt::(anonymous namespace)::BinaryReader::ReadT<unsigned char>(unsigned char*, char const*, char const*)
Line
Count
Source
289
30.0M
                           const char* desc) {
290
30.0M
  if (state_.offset + sizeof(T) > read_end_) {
291
18.1k
    PrintError("unable to read %s: %s", type_name, desc);
292
18.1k
    return Result::Error;
293
18.1k
  }
294
#if WABT_BIG_ENDIAN
295
  uint8_t tmp[sizeof(T)];
296
  memcpy(tmp, state_.data + state_.offset, sizeof(tmp));
297
  SwapBytesSized(tmp, sizeof(tmp));
298
  memcpy(out_value, tmp, sizeof(T));
299
#else
300
30.0M
  memcpy(out_value, state_.data + state_.offset, sizeof(T));
301
30.0M
#endif
302
30.0M
  state_.offset += sizeof(T);
303
30.0M
  return Result::Ok;
304
30.0M
}
binary-reader.cc:wabt::Result wabt::(anonymous namespace)::BinaryReader::ReadT<unsigned long>(unsigned long*, char const*, char const*)
Line
Count
Source
289
26.6k
                           const char* desc) {
290
26.6k
  if (state_.offset + sizeof(T) > read_end_) {
291
208
    PrintError("unable to read %s: %s", type_name, desc);
292
208
    return Result::Error;
293
208
  }
294
#if WABT_BIG_ENDIAN
295
  uint8_t tmp[sizeof(T)];
296
  memcpy(tmp, state_.data + state_.offset, sizeof(tmp));
297
  SwapBytesSized(tmp, sizeof(tmp));
298
  memcpy(out_value, tmp, sizeof(T));
299
#else
300
26.4k
  memcpy(out_value, state_.data + state_.offset, sizeof(T));
301
26.4k
#endif
302
26.4k
  state_.offset += sizeof(T);
303
26.4k
  return Result::Ok;
304
26.6k
}
binary-reader.cc:wabt::Result wabt::(anonymous namespace)::BinaryReader::ReadT<v128>(v128*, char const*, char const*)
Line
Count
Source
289
24.4k
                           const char* desc) {
290
24.4k
  if (state_.offset + sizeof(T) > read_end_) {
291
107
    PrintError("unable to read %s: %s", type_name, desc);
292
107
    return Result::Error;
293
107
  }
294
#if WABT_BIG_ENDIAN
295
  uint8_t tmp[sizeof(T)];
296
  memcpy(tmp, state_.data + state_.offset, sizeof(tmp));
297
  SwapBytesSized(tmp, sizeof(tmp));
298
  memcpy(out_value, tmp, sizeof(T));
299
#else
300
24.3k
  memcpy(out_value, state_.data + state_.offset, sizeof(T));
301
24.3k
#endif
302
24.3k
  state_.offset += sizeof(T);
303
24.3k
  return Result::Ok;
304
24.4k
}
305
306
30.0M
Result BinaryReader::ReadU8(uint8_t* out_value, const char* desc) {
307
30.0M
  return ReadT(out_value, "uint8_t", desc);
308
30.0M
}
309
310
185k
Result BinaryReader::ReadU16(uint16_t* out_value, const char* desc) {
311
185k
  return ReadT(out_value, "uint16_t", desc);
312
185k
}
313
314
93.4k
Result BinaryReader::ReadU32(uint32_t* out_value, const char* desc) {
315
93.4k
  return ReadT(out_value, "uint32_t", desc);
316
93.4k
}
317
318
59.9k
Result BinaryReader::ReadF32(uint32_t* out_value, const char* desc) {
319
59.9k
  return ReadT(out_value, "float", desc);
320
59.9k
}
321
322
26.6k
Result BinaryReader::ReadF64(uint64_t* out_value, const char* desc) {
323
26.6k
  return ReadT(out_value, "double", desc);
324
26.6k
}
325
326
24.4k
Result BinaryReader::ReadV128(v128* out_value, const char* desc) {
327
24.4k
  return ReadT(out_value, "v128", desc);
328
24.4k
}
329
330
64.9M
Result BinaryReader::ReadU32Leb128(uint32_t* out_value, const char* desc) {
331
64.9M
  const uint8_t* p = state_.data + state_.offset;
332
64.9M
  const uint8_t* end = state_.data + read_end_;
333
64.9M
  size_t bytes_read = wabt::ReadU32Leb128(p, end, out_value);
334
64.9M
  ERROR_UNLESS(bytes_read > 0, "unable to read u32 leb128: %s", desc);
335
54.7M
  state_.offset += bytes_read;
336
54.7M
  return Result::Ok;
337
64.9M
}
338
339
219k
Result BinaryReader::ReadU64Leb128(uint64_t* out_value, const char* desc) {
340
219k
  const uint8_t* p = state_.data + state_.offset;
341
219k
  const uint8_t* end = state_.data + read_end_;
342
219k
  size_t bytes_read = wabt::ReadU64Leb128(p, end, out_value);
343
219k
  ERROR_UNLESS(bytes_read > 0, "unable to read u64 leb128: %s", desc);
344
218k
  state_.offset += bytes_read;
345
218k
  return Result::Ok;
346
219k
}
347
348
2.91M
Result BinaryReader::ReadS32Leb128(uint32_t* out_value, const char* desc) {
349
2.91M
  const uint8_t* p = state_.data + state_.offset;
350
2.91M
  const uint8_t* end = state_.data + read_end_;
351
2.91M
  size_t bytes_read = wabt::ReadS32Leb128(p, end, out_value);
352
2.91M
  ERROR_UNLESS(bytes_read > 0, "unable to read i32 leb128: %s", desc);
353
2.90M
  state_.offset += bytes_read;
354
2.90M
  return Result::Ok;
355
2.91M
}
356
357
116k
Result BinaryReader::ReadS64Leb128(uint64_t* out_value, const char* desc) {
358
116k
  const uint8_t* p = state_.data + state_.offset;
359
116k
  const uint8_t* end = state_.data + read_end_;
360
116k
  size_t bytes_read = wabt::ReadS64Leb128(p, end, out_value);
361
116k
  ERROR_UNLESS(bytes_read > 0, "unable to read i64 leb128: %s", desc);
362
115k
  state_.offset += bytes_read;
363
115k
  return Result::Ok;
364
116k
}
365
366
2.80M
Result BinaryReader::ReadType(Type* out_value, const char* desc) {
367
2.80M
  uint32_t type = 0;
368
2.80M
  CHECK_RESULT(ReadS32Leb128(&type, desc));
369
2.80M
  if (options_.features.reference_types_enabled() &&
370
2.80M
      Type::EnumIsReferenceWithIndex(static_cast<Type::Enum>(type))) {
371
12.0k
    uint64_t heap_type = 0;
372
12.0k
    CHECK_RESULT(ReadS64Leb128(&heap_type, desc));
373
374
11.7k
    if (static_cast<int64_t>(heap_type) < 0 ||
375
9.78k
        static_cast<int64_t>(heap_type) >= kInvalidIndex) {
376
2.84k
      Type::Enum heap_type_code = static_cast<Type::Enum>(heap_type);
377
2.84k
      ERROR_UNLESS(
378
2.02k
          heap_type_code == Type::FuncRef || heap_type_code == Type::ExternRef,
379
2.02k
          "Reference type is limited to func and extern: %s", desc);
380
2.02k
      type = (static_cast<Type::Enum>(type) == Type::Ref)
381
2.02k
                 ? Type::ReferenceNonNull
382
2.02k
                 : Type::ReferenceOrNull;
383
2.02k
      *out_value = Type(heap_type_code, type);
384
8.94k
    } else {
385
8.94k
      *out_value =
386
8.94k
          Type(static_cast<Type::Enum>(type), static_cast<Index>(heap_type));
387
8.94k
    }
388
2.79M
  } else {
389
2.79M
    *out_value = static_cast<Type>(type);
390
2.79M
  }
391
2.80M
  return Result::Ok;
392
2.80M
}
393
394
156k
Result BinaryReader::ReadRefType(Type* out_value, const char* desc) {
395
156k
  CHECK_RESULT(ReadType(out_value, desc));
396
156k
  ERROR_UNLESS(out_value->IsRef(), "%s must be a reference type", desc);
397
155k
  return Result::Ok;
398
156k
}
399
400
Result BinaryReader::ReadExternalKind(ExternalKind* out_value,
401
147k
                                      const char* desc) {
402
147k
  uint8_t value = 0;
403
147k
  CHECK_RESULT(ReadU8(&value, desc));
404
147k
  ERROR_UNLESS(value < kExternalKindCount, "invalid export external kind: %d",
405
146k
               value);
406
146k
  *out_value = static_cast<ExternalKind>(value);
407
146k
  return Result::Ok;
408
147k
}
409
410
16.5M
Result BinaryReader::ReadStr(std::string_view* out_str, const char* desc) {
411
16.5M
  uint32_t str_len = 0;
412
16.5M
  CHECK_RESULT(ReadU32Leb128(&str_len, "string length"));
413
414
6.57M
  ERROR_UNLESS(state_.offset + str_len <= read_end_,
415
6.49M
               "unable to read string: %s", desc);
416
417
6.49M
  *out_str = std::string_view(
418
6.49M
      reinterpret_cast<const char*>(state_.data) + state_.offset, str_len);
419
6.49M
  state_.offset += str_len;
420
421
6.49M
  ERROR_UNLESS(IsValidUtf8(out_str->data(), out_str->length()),
422
6.46M
               "invalid utf-8 encoding: %s", desc);
423
6.46M
  return Result::Ok;
424
6.49M
}
425
426
Result BinaryReader::ReadBytes(const void** out_data,
427
                               Address* out_data_size,
428
369k
                               const char* desc) {
429
369k
  uint32_t data_size = 0;
430
369k
  CHECK_RESULT(ReadU32Leb128(&data_size, "data size"));
431
367k
  CHECK_RESULT(ReadBytesWithSize(out_data, data_size, desc));
432
358k
  *out_data_size = data_size;
433
358k
  return Result::Ok;
434
367k
}
435
436
Result BinaryReader::ReadBytesWithSize(const void** out_data,
437
                                       Offset size,
438
2.79M
                                       const char* desc) {
439
2.79M
  ERROR_UNLESS(state_.offset + size <= read_end_, "unable to read data: %s",
440
2.79M
               desc);
441
442
2.79M
  *out_data = static_cast<const uint8_t*>(state_.data) + state_.offset;
443
2.79M
  state_.offset += size;
444
2.79M
  return Result::Ok;
445
2.79M
}
446
447
27.5M
Result BinaryReader::ReadIndex(Index* index, const char* desc) {
448
27.5M
  uint32_t value;
449
27.5M
  CHECK_RESULT(ReadU32Leb128(&value, desc));
450
27.5M
  *index = value;
451
27.5M
  return Result::Ok;
452
27.5M
}
453
454
14.6M
Result BinaryReader::ReadOffset(Offset* offset, const char* desc) {
455
14.6M
  uint32_t value;
456
14.6M
  CHECK_RESULT(ReadU32Leb128(&value, desc));
457
14.5M
  *offset = value;
458
14.5M
  return Result::Ok;
459
14.6M
}
460
461
312k
Result BinaryReader::ReadAlignment(Address* alignment_log2, const char* desc) {
462
312k
  uint32_t value;
463
312k
  CHECK_RESULT(ReadU32Leb128(&value, desc));
464
309k
  *alignment_log2 = value;
465
309k
  return Result::Ok;
466
312k
}
467
468
309k
Result BinaryReader::CheckAlignment(Address* align_log2, const char* desc) {
469
309k
  uint32_t value = *align_log2;
470
309k
  if (value >= 32) {
471
3.45k
    PrintError("invalid %s: %" PRIu32, desc, value);
472
3.45k
    return Result::Error;
473
3.45k
  }
474
306k
  return Result::Ok;
475
309k
}
476
477
281k
Result BinaryReader::TakeHasMemidx(Address* align_log2, bool* has_memidx) {
478
  // extract the has_memidx flag
479
281k
  *has_memidx = (*align_log2 >> 6) & 1;
480
  // then clear it
481
281k
  *align_log2 &= ~(1 << 6);
482
281k
  return Result::Ok;
483
281k
}
484
485
53.1k
Result BinaryReader::ReadMemidx(Index* memidx, const char* desc) {
486
53.1k
  CHECK_RESULT(ReadIndex(memidx, desc));
487
52.8k
  return Result::Ok;
488
53.1k
}
489
490
Result BinaryReader::ReadMemLocation(Address* alignment_log2,
491
                                     Index* memidx,
492
                                     Address* offset,
493
                                     const char* desc_align,
494
                                     const char* desc_memidx,
495
                                     const char* desc_offset,
496
283k
                                     uint8_t* lane_val) {
497
283k
  bool has_memidx = false;
498
283k
  CHECK_RESULT(ReadAlignment(alignment_log2, desc_align));
499
281k
  CHECK_RESULT(TakeHasMemidx(alignment_log2, &has_memidx));
500
281k
  CHECK_RESULT(CheckAlignment(alignment_log2, desc_align));
501
279k
  *memidx = 0;
502
279k
  if (has_memidx) {
503
19.1k
    ERROR_IF(!options_.features.multi_memory_enabled(),
504
19.1k
             "multi_memory not allowed");
505
19.0k
    CHECK_RESULT(ReadMemidx(memidx, desc_memidx));
506
19.0k
  }
507
279k
  CHECK_RESULT(ReadAddress(offset, 0, desc_offset));
508
509
278k
  if (lane_val) {
510
22.2k
    CHECK_RESULT(ReadU8(lane_val, "Lane idx"));
511
22.2k
  }
512
513
278k
  return Result::Ok;
514
278k
}
515
516
Result BinaryReader::CallbackMemLocation(const Address* alignment_log2,
517
                                         const Index* memidx,
518
                                         const Address* offset,
519
278k
                                         const uint8_t* lane_val) {
520
278k
  if (lane_val) {
521
22.1k
    if (*memidx) {
522
2.42k
      CALLBACK(OnOpcodeUint32Uint32Uint32Uint32, *alignment_log2, *memidx,
523
2.42k
               *offset, *lane_val);
524
19.7k
    } else {
525
19.7k
      CALLBACK(OnOpcodeUint32Uint32Uint32, *alignment_log2, *offset, *lane_val);
526
19.7k
    }
527
256k
  } else {
528
256k
    if (*memidx) {
529
14.7k
      CALLBACK(OnOpcodeUint32Uint32Uint32, *alignment_log2, *memidx, *offset);
530
241k
    } else {
531
241k
      CALLBACK(OnOpcodeUint32Uint32, *alignment_log2, *offset);
532
241k
    }
533
256k
  }
534
535
278k
  return Result::Ok;
536
278k
}
537
538
2.09M
Result BinaryReader::ReadCount(Index* count, const char* desc) {
539
2.09M
  CHECK_RESULT(ReadIndex(count, desc));
540
541
  // This check assumes that each item follows in this section, and takes at
542
  // least 1 byte. It's possible that this check passes but reading fails
543
  // later. It is still useful to check here, though, because it early-outs
544
  // when an erroneous large count is used, before allocating memory for it.
545
2.07M
  size_t section_remaining = read_end_ - state_.offset;
546
2.07M
  if (*count > section_remaining) {
547
30.8k
    PrintError("invalid %s %" PRIindex ", only %" PRIzd
548
30.8k
               " bytes left in section",
549
30.8k
               desc, *count, section_remaining);
550
30.8k
    return Result::Error;
551
30.8k
  }
552
2.04M
  return Result::Ok;
553
2.07M
}
554
555
2.37k
Result BinaryReader::ReadField(TypeMut* out_value) {
556
  // TODO: Reuse for global header too?
557
2.37k
  Type field_type;
558
2.37k
  CHECK_RESULT(ReadType(&field_type, "field type"));
559
2.34k
  ERROR_UNLESS(IsConcreteType(field_type),
560
1.93k
               "expected valid field type (got " PRItypecode ")",
561
1.93k
               WABT_PRINTF_TYPE_CODE(field_type));
562
563
1.93k
  uint8_t mutable_ = 0;
564
1.93k
  CHECK_RESULT(ReadU8(&mutable_, "field mutability"));
565
1.87k
  ERROR_UNLESS(mutable_ <= 1, "field mutability must be 0 or 1");
566
1.79k
  out_value->type = field_type;
567
1.79k
  out_value->mutable_ = mutable_;
568
1.79k
  return Result::Ok;
569
1.87k
}
570
571
2.28M
bool BinaryReader::IsConcreteReferenceType(Type::Enum type) {
572
2.28M
  switch (type) {
573
27.7k
    case Type::FuncRef:
574
56.5k
    case Type::ExternRef:
575
56.5k
      return options_.features.reference_types_enabled();
576
577
6.03k
    case Type::ExnRef:
578
6.03k
      return options_.features.exceptions_enabled();
579
580
2.22M
    default:
581
2.22M
      return false;
582
2.28M
  }
583
2.28M
}
584
585
2.63M
bool BinaryReader::IsConcreteType(Type type) {
586
2.63M
  switch (type) {
587
43.0k
    case Type::I32:
588
68.0k
    case Type::I64:
589
96.6k
    case Type::F32:
590
334k
    case Type::F64:
591
334k
      return true;
592
593
19.9k
    case Type::V128:
594
19.9k
      return options_.features.simd_enabled();
595
596
2.38k
    case Type::Reference:
597
3.82k
    case Type::Ref:
598
5.63k
    case Type::RefNull:
599
5.63k
      return options_.features.function_references_enabled();
600
601
2.27M
    default:
602
2.27M
      return IsConcreteReferenceType(type);
603
2.63M
  }
604
2.63M
}
605
606
2.26M
bool BinaryReader::IsBlockType(Type type) {
607
2.26M
  if (IsConcreteType(type) || type == Type::Void) {
608
72.0k
    return true;
609
72.0k
  }
610
611
2.19M
  if (!(options_.features.multi_value_enabled() && type.IsIndex())) {
612
899
    return false;
613
899
  }
614
615
2.19M
  return true;
616
2.19M
}
617
618
1.42M
Index BinaryReader::NumTotalFuncs() {
619
1.42M
  return num_func_imports_ + num_function_signatures_;
620
1.42M
}
621
622
116k
Result BinaryReader::ReadInitExpr(Index index) {
623
116k
  CHECK_RESULT(ReadInstructions(read_end_, "init expression"));
624
116k
  assert(state_.offset <= read_end_);
625
83.6k
  return Result::Ok;
626
83.6k
}
627
628
153k
Result BinaryReader::ReadTable(Limits* out_elem_limits) {
629
153k
  uint8_t flags;
630
153k
  uint32_t initial;
631
153k
  uint32_t max = 0;
632
153k
  CHECK_RESULT(ReadU8(&flags, "table flags"));
633
153k
  bool has_max = flags & WABT_BINARY_LIMITS_HAS_MAX_FLAG;
634
153k
  bool is_shared = flags & WABT_BINARY_LIMITS_IS_SHARED_FLAG;
635
153k
  bool is_64 = flags & WABT_BINARY_LIMITS_IS_64_FLAG;
636
153k
  const uint8_t unknown_flags = flags & ~WABT_BINARY_LIMITS_ALL_TABLE_FLAGS;
637
153k
  ERROR_IF(is_shared, "tables may not be shared");
638
153k
  ERROR_IF(is_64 && !options_.features.memory64_enabled(),
639
153k
           "memory64 not allowed");
640
153k
  ERROR_UNLESS(unknown_flags == 0, "malformed table limits flag: %d", flags);
641
153k
  CHECK_RESULT(ReadU32Leb128(&initial, "table initial elem count"));
642
153k
  if (has_max) {
643
122k
    CHECK_RESULT(ReadU32Leb128(&max, "table max elem count"));
644
122k
  }
645
646
153k
  out_elem_limits->has_max = has_max;
647
153k
  out_elem_limits->is_64 = is_64;
648
153k
  out_elem_limits->initial = initial;
649
153k
  out_elem_limits->max = max;
650
153k
  return Result::Ok;
651
153k
}
652
653
Result BinaryReader::ReadMemory(Limits* out_page_limits,
654
187k
                                uint32_t* out_page_size) {
655
187k
  uint8_t flags;
656
187k
  uint64_t initial;
657
187k
  uint64_t max = 0;
658
187k
  CHECK_RESULT(ReadU8(&flags, "memory flags"));
659
187k
  bool has_max = flags & WABT_BINARY_LIMITS_HAS_MAX_FLAG;
660
187k
  bool is_shared = flags & WABT_BINARY_LIMITS_IS_SHARED_FLAG;
661
187k
  bool is_64 = flags & WABT_BINARY_LIMITS_IS_64_FLAG;
662
187k
  bool has_custom_page_size =
663
187k
      flags & WABT_BINARY_LIMITS_HAS_CUSTOM_PAGE_SIZE_FLAG;
664
187k
  const uint8_t unknown_flags = flags & ~WABT_BINARY_LIMITS_ALL_MEMORY_FLAGS;
665
187k
  ERROR_UNLESS(unknown_flags == 0, "malformed memory limits flag: %d", flags);
666
187k
  ERROR_IF(is_shared && !options_.features.threads_enabled(),
667
187k
           "memory may not be shared: threads not allowed");
668
187k
  ERROR_IF(is_64 && !options_.features.memory64_enabled(),
669
187k
           "memory64 not allowed");
670
187k
  ERROR_IF(
671
187k
      has_custom_page_size && !options_.features.custom_page_sizes_enabled(),
672
187k
      "custom page sizes not allowed");
673
187k
  if (options_.features.memory64_enabled()) {
674
46.0k
    CHECK_RESULT(ReadU64Leb128(&initial, "memory initial page count"));
675
45.7k
    if (has_max) {
676
16.2k
      CHECK_RESULT(ReadU64Leb128(&max, "memory max page count"));
677
16.2k
    }
678
141k
  } else {
679
141k
    uint32_t initial32;
680
141k
    CHECK_RESULT(ReadU32Leb128(&initial32, "memory initial page count"));
681
141k
    initial = initial32;
682
141k
    if (has_max) {
683
90.2k
      uint32_t max32;
684
90.2k
      CHECK_RESULT(ReadU32Leb128(&max32, "memory max page count"));
685
90.2k
      max = max32;
686
90.2k
    }
687
141k
  }
688
186k
  if (has_custom_page_size) {
689
8.95k
    uint32_t page_size_log2;
690
8.95k
    CHECK_RESULT(ReadU32Leb128(&page_size_log2, "memory page size"));
691
8.88k
    ERROR_IF(page_size_log2 > 16, "malformed memory page size");
692
8.78k
    *out_page_size = 1 << page_size_log2;
693
177k
  } else {
694
177k
    *out_page_size = WABT_DEFAULT_PAGE_SIZE;
695
177k
  }
696
697
186k
  out_page_limits->has_max = has_max;
698
186k
  out_page_limits->is_shared = is_shared;
699
186k
  out_page_limits->is_64 = is_64;
700
186k
  out_page_limits->initial = initial;
701
186k
  out_page_limits->max = max;
702
703
186k
  return Result::Ok;
704
186k
}
705
706
31.9k
Result BinaryReader::ReadGlobalHeader(Type* out_type, bool* out_mutable) {
707
31.9k
  Type global_type = Type::Void;
708
31.9k
  uint8_t mutable_ = 0;
709
31.9k
  CHECK_RESULT(ReadType(&global_type, "global type"));
710
31.6k
  ERROR_UNLESS(IsConcreteType(global_type), "invalid global type: %#x",
711
30.7k
               static_cast<int>(global_type));
712
713
30.7k
  CHECK_RESULT(ReadU8(&mutable_, "global mutability"));
714
30.6k
  ERROR_UNLESS(mutable_ <= 1, "global mutability must be 0 or 1");
715
716
30.5k
  *out_type = global_type;
717
30.5k
  *out_mutable = mutable_;
718
30.5k
  return Result::Ok;
719
30.6k
}
720
721
Result BinaryReader::ReadAddress(Address* out_value,
722
                                 Index memory,
723
279k
                                 const char* desc) {
724
279k
  if (options_.features.memory64_enabled()) {
725
157k
    return ReadU64Leb128(out_value, desc);
726
157k
  } else {
727
122k
    uint32_t val;
728
122k
    Result res = ReadU32Leb128(&val, desc);
729
122k
    *out_value = val;
730
122k
    return res;
731
122k
  }
732
279k
}
733
734
6.39k
Result BinaryReader::ReadFunctionBody(Offset end_offset) {
735
6.39k
  CHECK_RESULT(ReadInstructions(end_offset, "function body"));
736
2.54k
  ERROR_UNLESS(state_.offset == end_offset,
737
2.42k
               "function body shorter than given size");
738
2.42k
  return Result::Ok;
739
2.54k
}
740
741
122k
Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) {
742
122k
  std::stack<Opcode> nested_blocks;
743
14.6M
  while (state_.offset < end_offset) {
744
14.6M
    Opcode opcode;
745
14.6M
    CHECK_RESULT(ReadOpcode(&opcode, "opcode"));
746
14.6M
    CALLBACK(OnOpcode, opcode);
747
14.6M
    ERROR_UNLESS_OPCODE_ENABLED(opcode);
748
749
14.6M
    switch (opcode) {
750
6.67M
      case Opcode::Unreachable:
751
6.67M
        CALLBACK0(OnUnreachableExpr);
752
6.67M
        CALLBACK0(OnOpcodeBare);
753
6.67M
        break;
754
755
6.67M
      case Opcode::Block: {
756
368k
        nested_blocks.push(opcode);
757
368k
        Type sig_type;
758
368k
        CHECK_RESULT(ReadType(&sig_type, "block signature type"));
759
368k
        ERROR_UNLESS(IsBlockType(sig_type),
760
368k
                     "expected valid block signature type");
761
368k
        CALLBACK(OnBlockExpr, sig_type);
762
368k
        CALLBACK(OnOpcodeBlockSig, sig_type);
763
368k
        break;
764
368k
      }
765
766
422k
      case Opcode::Loop: {
767
422k
        nested_blocks.push(opcode);
768
422k
        Type sig_type;
769
422k
        CHECK_RESULT(ReadType(&sig_type, "loop signature type"));
770
422k
        ERROR_UNLESS(IsBlockType(sig_type),
771
421k
                     "expected valid block signature type");
772
421k
        CALLBACK(OnLoopExpr, sig_type);
773
421k
        CALLBACK(OnOpcodeBlockSig, sig_type);
774
421k
        break;
775
421k
      }
776
777
1.00M
      case Opcode::If: {
778
1.00M
        nested_blocks.push(opcode);
779
1.00M
        Type sig_type;
780
1.00M
        CHECK_RESULT(ReadType(&sig_type, "if signature type"));
781
1.00M
        ERROR_UNLESS(IsBlockType(sig_type),
782
1.00M
                     "expected valid block signature type");
783
1.00M
        CALLBACK(OnIfExpr, sig_type);
784
1.00M
        CALLBACK(OnOpcodeBlockSig, sig_type);
785
1.00M
        break;
786
1.00M
      }
787
788
1.00M
      case Opcode::Else:
789
11.3k
        ERROR_IF(nested_blocks.empty() || (nested_blocks.top() != Opcode::If),
790
11.3k
                 "else outside if block");
791
11.0k
        CALLBACK0(OnElseExpr);
792
11.0k
        CALLBACK0(OnOpcodeBare);
793
11.0k
        break;
794
795
20.6k
      case Opcode::SelectT: {
796
20.6k
        Index num_results;
797
20.6k
        CHECK_RESULT(ReadCount(&num_results, "num result types"));
798
799
20.5k
        result_types_.resize(num_results);
800
241k
        for (Index i = 0; i < num_results; ++i) {
801
222k
          Type result_type;
802
222k
          CHECK_RESULT(ReadType(&result_type, "select result type"));
803
222k
          ERROR_UNLESS(IsConcreteType(result_type),
804
221k
                       "expected valid select result type (got " PRItypecode
805
221k
                       ")",
806
221k
                       WABT_PRINTF_TYPE_CODE(result_type));
807
221k
          result_types_[i] = result_type;
808
221k
        }
809
810
19.6k
        if (num_results) {
811
5.34k
          CALLBACK(OnSelectExpr, num_results, result_types_.data());
812
5.34k
          CALLBACK(OnOpcodeType, result_types_[0]);
813
14.2k
        } else {
814
14.2k
          CALLBACK(OnSelectExpr, 0, NULL);
815
14.2k
          CALLBACK0(OnOpcodeBare);
816
14.2k
        }
817
19.6k
        break;
818
19.6k
      }
819
820
19.6k
      case Opcode::Select:
821
17.3k
        CALLBACK(OnSelectExpr, 0, nullptr);
822
17.3k
        CALLBACK0(OnOpcodeBare);
823
17.3k
        break;
824
825
22.1k
      case Opcode::Br: {
826
22.1k
        Index depth;
827
22.1k
        CHECK_RESULT(ReadIndex(&depth, "br depth"));
828
22.1k
        CALLBACK(OnBrExpr, depth);
829
22.1k
        CALLBACK(OnOpcodeIndex, depth);
830
22.1k
        break;
831
22.1k
      }
832
833
22.1k
      case Opcode::BrIf: {
834
14.4k
        Index depth;
835
14.4k
        CHECK_RESULT(ReadIndex(&depth, "br_if depth"));
836
14.3k
        CALLBACK(OnBrIfExpr, depth);
837
14.3k
        CALLBACK(OnOpcodeIndex, depth);
838
14.3k
        break;
839
14.3k
      }
840
841
14.3k
      case Opcode::BrOnNonNull: {
842
1.47k
        Index depth;
843
1.47k
        CHECK_RESULT(ReadIndex(&depth, "br_on_non_null depth"));
844
1.45k
        CALLBACK(OnBrOnNonNullExpr, depth);
845
1.45k
        CALLBACK(OnOpcodeIndex, depth);
846
1.45k
        break;
847
1.45k
      }
848
849
1.45k
      case Opcode::BrOnNull: {
850
977
        Index depth;
851
977
        CHECK_RESULT(ReadIndex(&depth, "br_on_null depth"));
852
939
        CALLBACK(OnBrOnNullExpr, depth);
853
937
        CALLBACK(OnOpcodeIndex, depth);
854
937
        break;
855
937
      }
856
857
160k
      case Opcode::BrTable: {
858
160k
        Index num_targets;
859
160k
        CHECK_RESULT(ReadCount(&num_targets, "br_table target count"));
860
160k
        target_depths_.resize(num_targets);
861
862
18.0M
        for (Index i = 0; i < num_targets; ++i) {
863
17.8M
          Index target_depth;
864
17.8M
          CHECK_RESULT(ReadIndex(&target_depth, "br_table target depth"));
865
17.8M
          target_depths_[i] = target_depth;
866
17.8M
        }
867
868
159k
        Index default_target_depth;
869
159k
        CHECK_RESULT(
870
159k
            ReadIndex(&default_target_depth, "br_table default target depth"));
871
872
159k
        Index* target_depths = num_targets ? target_depths_.data() : nullptr;
873
874
159k
        CALLBACK(OnBrTableExpr, num_targets, target_depths,
875
159k
                 default_target_depth);
876
159k
        break;
877
159k
      }
878
879
159k
      case Opcode::Return:
880
29.9k
        CALLBACK0(OnReturnExpr);
881
29.9k
        CALLBACK0(OnOpcodeBare);
882
29.9k
        break;
883
884
346k
      case Opcode::Nop:
885
346k
        CALLBACK0(OnNopExpr);
886
346k
        CALLBACK0(OnOpcodeBare);
887
346k
        break;
888
889
346k
      case Opcode::Drop:
890
12.8k
        CALLBACK0(OnDropExpr);
891
12.8k
        CALLBACK0(OnOpcodeBare);
892
12.8k
        break;
893
894
541k
      case Opcode::End:
895
541k
        CALLBACK0(OnEndExpr);
896
541k
        if (nested_blocks.empty()) {
897
86.1k
          return Result::Ok;
898
86.1k
        }
899
454k
        nested_blocks.pop();
900
454k
        break;
901
902
73.1k
      case Opcode::I32Const: {
903
73.1k
        uint32_t value;
904
73.1k
        CHECK_RESULT(ReadS32Leb128(&value, "i32.const value"));
905
73.0k
        CALLBACK(OnI32ConstExpr, value);
906
73.0k
        CALLBACK(OnOpcodeUint32, value);
907
73.0k
        break;
908
73.0k
      }
909
910
91.2k
      case Opcode::I64Const: {
911
91.2k
        uint64_t value;
912
91.2k
        CHECK_RESULT(ReadS64Leb128(&value, "i64.const value"));
913
91.0k
        CALLBACK(OnI64ConstExpr, value);
914
91.0k
        CALLBACK(OnOpcodeUint64, value);
915
91.0k
        break;
916
91.0k
      }
917
918
91.0k
      case Opcode::F32Const: {
919
59.9k
        uint32_t value_bits = 0;
920
59.9k
        CHECK_RESULT(ReadF32(&value_bits, "f32.const value"));
921
59.7k
        CALLBACK(OnF32ConstExpr, value_bits);
922
59.7k
        CALLBACK(OnOpcodeF32, value_bits);
923
59.7k
        break;
924
59.7k
      }
925
926
59.7k
      case Opcode::F64Const: {
927
26.6k
        uint64_t value_bits = 0;
928
26.6k
        CHECK_RESULT(ReadF64(&value_bits, "f64.const value"));
929
26.4k
        CALLBACK(OnF64ConstExpr, value_bits);
930
26.4k
        CALLBACK(OnOpcodeF64, value_bits);
931
26.4k
        break;
932
26.4k
      }
933
934
26.4k
      case Opcode::V128Const: {
935
4.03k
        v128 value_bits;
936
4.03k
        ZeroMemory(value_bits);
937
4.03k
        CHECK_RESULT(ReadV128(&value_bits, "v128.const value"));
938
3.98k
        CALLBACK(OnV128ConstExpr, value_bits);
939
3.98k
        CALLBACK(OnOpcodeV128, value_bits);
940
3.98k
        break;
941
3.98k
      }
942
943
63.8k
      case Opcode::GlobalGet: {
944
63.8k
        Index global_index;
945
63.8k
        CHECK_RESULT(ReadIndex(&global_index, "global.get global index"));
946
63.7k
        CALLBACK(OnGlobalGetExpr, global_index);
947
63.7k
        CALLBACK(OnOpcodeIndex, global_index);
948
63.7k
        break;
949
63.7k
      }
950
951
99.6k
      case Opcode::LocalGet: {
952
99.6k
        Index local_index;
953
99.6k
        CHECK_RESULT(ReadIndex(&local_index, "local.get local index"));
954
99.5k
        CALLBACK(OnLocalGetExpr, local_index);
955
99.5k
        CALLBACK(OnOpcodeIndex, local_index);
956
99.5k
        break;
957
99.5k
      }
958
959
99.5k
      case Opcode::GlobalSet: {
960
48.6k
        Index global_index;
961
48.6k
        CHECK_RESULT(ReadIndex(&global_index, "global.set global index"));
962
48.5k
        CALLBACK(OnGlobalSetExpr, global_index);
963
48.5k
        CALLBACK(OnOpcodeIndex, global_index);
964
48.5k
        break;
965
48.5k
      }
966
967
63.0k
      case Opcode::LocalSet: {
968
63.0k
        Index local_index;
969
63.0k
        CHECK_RESULT(ReadIndex(&local_index, "local.set local index"));
970
62.9k
        CALLBACK(OnLocalSetExpr, local_index);
971
62.9k
        CALLBACK(OnOpcodeIndex, local_index);
972
62.9k
        break;
973
62.9k
      }
974
975
62.9k
      case Opcode::Call: {
976
31.9k
        Index func_index;
977
31.9k
        CHECK_RESULT(ReadIndex(&func_index, "call function index"));
978
31.9k
        CALLBACK(OnCallExpr, func_index);
979
31.9k
        CALLBACK(OnOpcodeIndex, func_index);
980
31.9k
        break;
981
31.9k
      }
982
983
31.9k
      case Opcode::CallIndirect: {
984
24.5k
        Index sig_index;
985
24.5k
        CHECK_RESULT(ReadIndex(&sig_index, "call_indirect signature index"));
986
24.5k
        Index table_index = 0;
987
24.5k
        if (options_.features.reference_types_enabled()) {
988
24.5k
          CHECK_RESULT(ReadIndex(&table_index, "call_indirect table index"));
989
24.5k
        } else {
990
0
          uint8_t reserved;
991
0
          CHECK_RESULT(ReadU8(&reserved, "call_indirect reserved"));
992
0
          ERROR_UNLESS(reserved == 0, "call_indirect reserved value must be 0");
993
0
        }
994
24.4k
        CALLBACK(OnCallIndirectExpr, sig_index, table_index);
995
24.4k
        CALLBACK(OnOpcodeUint32Uint32, sig_index, table_index);
996
24.4k
        break;
997
24.4k
      }
998
999
24.4k
      case Opcode::ReturnCall: {
1000
5.43k
        Index func_index;
1001
5.43k
        CHECK_RESULT(ReadIndex(&func_index, "return_call"));
1002
5.34k
        CALLBACK(OnReturnCallExpr, func_index);
1003
5.34k
        CALLBACK(OnOpcodeIndex, func_index);
1004
5.34k
        break;
1005
5.34k
      }
1006
1007
5.34k
      case Opcode::ReturnCallIndirect: {
1008
3.27k
        Index sig_index;
1009
3.27k
        CHECK_RESULT(ReadIndex(&sig_index, "return_call_indirect"));
1010
3.20k
        Index table_index = 0;
1011
3.20k
        if (options_.features.reference_types_enabled()) {
1012
3.20k
          CHECK_RESULT(
1013
3.20k
              ReadIndex(&table_index, "return_call_indirect table index"));
1014
3.20k
        } else {
1015
0
          uint8_t reserved;
1016
0
          CHECK_RESULT(ReadU8(&reserved, "return_call_indirect reserved"));
1017
0
          ERROR_UNLESS(reserved == 0,
1018
0
                       "return_call_indirect reserved value must be 0");
1019
0
        }
1020
3.15k
        CALLBACK(OnReturnCallIndirectExpr, sig_index, table_index);
1021
3.15k
        CALLBACK(OnOpcodeUint32Uint32, sig_index, table_index);
1022
3.15k
        break;
1023
3.15k
      }
1024
1025
8.27k
      case Opcode::LocalTee: {
1026
8.27k
        Index local_index;
1027
8.27k
        CHECK_RESULT(ReadIndex(&local_index, "local.tee local index"));
1028
8.21k
        CALLBACK(OnLocalTeeExpr, local_index);
1029
8.20k
        CALLBACK(OnOpcodeIndex, local_index);
1030
8.20k
        break;
1031
8.20k
      }
1032
1033
10.7k
      case Opcode::I32Load8S:
1034
16.4k
      case Opcode::I32Load8U:
1035
22.2k
      case Opcode::I32Load16S:
1036
28.9k
      case Opcode::I32Load16U:
1037
38.2k
      case Opcode::I64Load8S:
1038
45.2k
      case Opcode::I64Load8U:
1039
51.1k
      case Opcode::I64Load16S:
1040
53.9k
      case Opcode::I64Load16U:
1041
60.6k
      case Opcode::I64Load32S:
1042
64.1k
      case Opcode::I64Load32U:
1043
75.2k
      case Opcode::I32Load:
1044
81.6k
      case Opcode::I64Load:
1045
106k
      case Opcode::F32Load:
1046
112k
      case Opcode::F64Load:
1047
133k
      case Opcode::V128Load:
1048
138k
      case Opcode::V128Load8X8S:
1049
141k
      case Opcode::V128Load8X8U:
1050
143k
      case Opcode::V128Load16X4S:
1051
146k
      case Opcode::V128Load16X4U:
1052
148k
      case Opcode::V128Load32X2S:
1053
149k
      case Opcode::V128Load32X2U: {
1054
149k
        Address alignment_log2;
1055
149k
        Index memidx;
1056
149k
        Address offset;
1057
149k
        CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset,
1058
149k
                                     "load alignment", "load memidx",
1059
149k
                                     "load offset"));
1060
146k
        CALLBACK(OnLoadExpr, opcode, memidx, alignment_log2, offset);
1061
146k
        CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset));
1062
146k
        break;
1063
146k
      }
1064
1065
146k
      case Opcode::I32Store8:
1066
13.5k
      case Opcode::I32Store16:
1067
15.2k
      case Opcode::I64Store8:
1068
20.1k
      case Opcode::I64Store16:
1069
22.4k
      case Opcode::I64Store32:
1070
24.8k
      case Opcode::I32Store:
1071
26.4k
      case Opcode::I64Store:
1072
29.4k
      case Opcode::F32Store:
1073
32.3k
      case Opcode::F64Store:
1074
59.0k
      case Opcode::V128Store: {
1075
59.0k
        Address alignment_log2;
1076
59.0k
        Index memidx;
1077
59.0k
        Address offset;
1078
59.0k
        CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset,
1079
59.0k
                                     "store alignment", "store memidx",
1080
59.0k
                                     "store offset"));
1081
58.3k
        CALLBACK(OnStoreExpr, opcode, memidx, alignment_log2, offset);
1082
58.3k
        CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset));
1083
58.3k
        break;
1084
58.3k
      }
1085
1086
58.3k
      case Opcode::MemorySize: {
1087
13.7k
        Index memidx = 0;
1088
13.7k
        if (!options_.features.multi_memory_enabled()) {
1089
5.26k
          uint8_t reserved;
1090
5.26k
          CHECK_RESULT(ReadU8(&reserved, "memory.size reserved"));
1091
5.24k
          ERROR_UNLESS(reserved == 0, "memory.size reserved value must be 0");
1092
8.52k
        } else {
1093
8.52k
          CHECK_RESULT(ReadMemidx(&memidx, "memory.size memidx"));
1094
8.52k
        }
1095
13.6k
        CALLBACK(OnMemorySizeExpr, memidx);
1096
13.6k
        CALLBACK(OnOpcodeUint32, memidx);
1097
13.6k
        break;
1098
13.6k
      }
1099
1100
19.0k
      case Opcode::MemoryGrow: {
1101
19.0k
        Index memidx = 0;
1102
19.0k
        if (!options_.features.multi_memory_enabled()) {
1103
7.30k
          uint8_t reserved;
1104
7.30k
          CHECK_RESULT(ReadU8(&reserved, "memory.grow reserved"));
1105
7.27k
          ERROR_UNLESS(reserved == 0, "memory.grow reserved value must be 0");
1106
11.7k
        } else {
1107
11.7k
          CHECK_RESULT(ReadMemidx(&memidx, "memory.grow memidx"));
1108
11.7k
        }
1109
18.8k
        CALLBACK(OnMemoryGrowExpr, memidx);
1110
18.8k
        CALLBACK(OnOpcodeUint32, memidx);
1111
18.8k
        break;
1112
18.8k
      }
1113
1114
18.8k
      case Opcode::I32Add:
1115
30.5k
      case Opcode::I32Sub:
1116
82.3k
      case Opcode::I32Mul:
1117
125k
      case Opcode::I32DivS:
1118
143k
      case Opcode::I32DivU:
1119
206k
      case Opcode::I32RemS:
1120
215k
      case Opcode::I32RemU:
1121
221k
      case Opcode::I32And:
1122
234k
      case Opcode::I32Or:
1123
284k
      case Opcode::I32Xor:
1124
301k
      case Opcode::I32Shl:
1125
308k
      case Opcode::I32ShrU:
1126
319k
      case Opcode::I32ShrS:
1127
329k
      case Opcode::I32Rotr:
1128
337k
      case Opcode::I32Rotl:
1129
1.30M
      case Opcode::I64Add:
1130
1.31M
      case Opcode::I64Sub:
1131
1.33M
      case Opcode::I64Mul:
1132
1.36M
      case Opcode::I64DivS:
1133
1.38M
      case Opcode::I64DivU:
1134
1.39M
      case Opcode::I64RemS:
1135
1.40M
      case Opcode::I64RemU:
1136
1.42M
      case Opcode::I64And:
1137
1.43M
      case Opcode::I64Or:
1138
1.44M
      case Opcode::I64Xor:
1139
1.45M
      case Opcode::I64Shl:
1140
1.46M
      case Opcode::I64ShrU:
1141
1.47M
      case Opcode::I64ShrS:
1142
1.47M
      case Opcode::I64Rotr:
1143
1.48M
      case Opcode::I64Rotl:
1144
1.49M
      case Opcode::F32Add:
1145
1.49M
      case Opcode::F32Sub:
1146
1.49M
      case Opcode::F32Mul:
1147
1.51M
      case Opcode::F32Div:
1148
1.52M
      case Opcode::F32Min:
1149
1.53M
      case Opcode::F32Max:
1150
1.53M
      case Opcode::F32Copysign:
1151
1.55M
      case Opcode::F64Add:
1152
1.56M
      case Opcode::F64Sub:
1153
1.57M
      case Opcode::F64Mul:
1154
1.58M
      case Opcode::F64Div:
1155
1.59M
      case Opcode::F64Min:
1156
1.59M
      case Opcode::F64Max:
1157
1.60M
      case Opcode::F64Copysign:
1158
1.60M
      case Opcode::I8X16Add:
1159
1.60M
      case Opcode::I16X8Add:
1160
1.60M
      case Opcode::I32X4Add:
1161
1.60M
      case Opcode::I64X2Add:
1162
1.60M
      case Opcode::I8X16Sub:
1163
1.60M
      case Opcode::I16X8Sub:
1164
1.60M
      case Opcode::I32X4Sub:
1165
1.61M
      case Opcode::I64X2Sub:
1166
1.61M
      case Opcode::I16X8Mul:
1167
1.61M
      case Opcode::I32X4Mul:
1168
1.61M
      case Opcode::I64X2Mul:
1169
1.62M
      case Opcode::I8X16AddSatS:
1170
1.62M
      case Opcode::I8X16AddSatU:
1171
1.62M
      case Opcode::I16X8AddSatS:
1172
1.62M
      case Opcode::I16X8AddSatU:
1173
1.62M
      case Opcode::I8X16SubSatS:
1174
1.63M
      case Opcode::I8X16SubSatU:
1175
1.63M
      case Opcode::I16X8SubSatS:
1176
1.63M
      case Opcode::I16X8SubSatU:
1177
1.63M
      case Opcode::I8X16MinS:
1178
1.63M
      case Opcode::I16X8MinS:
1179
1.64M
      case Opcode::I32X4MinS:
1180
1.64M
      case Opcode::I8X16MinU:
1181
1.64M
      case Opcode::I16X8MinU:
1182
1.64M
      case Opcode::I32X4MinU:
1183
1.64M
      case Opcode::I8X16MaxS:
1184
1.64M
      case Opcode::I16X8MaxS:
1185
1.64M
      case Opcode::I32X4MaxS:
1186
1.65M
      case Opcode::I8X16MaxU:
1187
1.65M
      case Opcode::I16X8MaxU:
1188
1.65M
      case Opcode::I32X4MaxU:
1189
1.65M
      case Opcode::I8X16Shl:
1190
1.65M
      case Opcode::I16X8Shl:
1191
1.66M
      case Opcode::I32X4Shl:
1192
1.66M
      case Opcode::I64X2Shl:
1193
1.66M
      case Opcode::I8X16ShrS:
1194
1.67M
      case Opcode::I8X16ShrU:
1195
1.67M
      case Opcode::I16X8ShrS:
1196
1.67M
      case Opcode::I16X8ShrU:
1197
1.67M
      case Opcode::I32X4ShrS:
1198
1.67M
      case Opcode::I32X4ShrU:
1199
1.68M
      case Opcode::I64X2ShrS:
1200
1.68M
      case Opcode::I64X2ShrU:
1201
1.68M
      case Opcode::V128And:
1202
1.68M
      case Opcode::V128Or:
1203
1.69M
      case Opcode::V128Xor:
1204
1.69M
      case Opcode::F32X4Min:
1205
1.69M
      case Opcode::F32X4PMin:
1206
1.69M
      case Opcode::F64X2Min:
1207
1.69M
      case Opcode::F64X2PMin:
1208
1.69M
      case Opcode::F32X4Max:
1209
1.69M
      case Opcode::F32X4PMax:
1210
1.70M
      case Opcode::F64X2Max:
1211
1.70M
      case Opcode::F64X2PMax:
1212
1.70M
      case Opcode::F32X4Add:
1213
1.70M
      case Opcode::F64X2Add:
1214
1.70M
      case Opcode::F32X4Sub:
1215
1.70M
      case Opcode::F64X2Sub:
1216
1.70M
      case Opcode::F32X4Div:
1217
1.71M
      case Opcode::F64X2Div:
1218
1.71M
      case Opcode::F32X4Mul:
1219
1.71M
      case Opcode::F64X2Mul:
1220
1.71M
      case Opcode::I8X16Swizzle:
1221
1.73M
      case Opcode::I8X16NarrowI16X8S:
1222
1.74M
      case Opcode::I8X16NarrowI16X8U:
1223
1.74M
      case Opcode::I16X8NarrowI32X4S:
1224
1.74M
      case Opcode::I16X8NarrowI32X4U:
1225
1.75M
      case Opcode::V128Andnot:
1226
1.75M
      case Opcode::I8X16AvgrU:
1227
1.75M
      case Opcode::I16X8AvgrU:
1228
1.75M
      case Opcode::I16X8ExtmulLowI8X16S:
1229
1.76M
      case Opcode::I16X8ExtmulHighI8X16S:
1230
1.76M
      case Opcode::I16X8ExtmulLowI8X16U:
1231
1.76M
      case Opcode::I16X8ExtmulHighI8X16U:
1232
1.76M
      case Opcode::I32X4ExtmulLowI16X8S:
1233
1.76M
      case Opcode::I32X4ExtmulHighI16X8S:
1234
1.77M
      case Opcode::I32X4ExtmulLowI16X8U:
1235
1.77M
      case Opcode::I32X4ExtmulHighI16X8U:
1236
1.77M
      case Opcode::I64X2ExtmulLowI32X4S:
1237
1.78M
      case Opcode::I64X2ExtmulHighI32X4S:
1238
1.78M
      case Opcode::I64X2ExtmulLowI32X4U:
1239
1.78M
      case Opcode::I64X2ExtmulHighI32X4U:
1240
1.78M
      case Opcode::I16X8Q15mulrSatS:
1241
1.78M
      case Opcode::I32X4DotI16X8S:
1242
1.78M
      case Opcode::I8X16RelaxedSwizzle:
1243
1.78M
      case Opcode::F32X4RelaxedMin:
1244
1.78M
      case Opcode::F32X4RelaxedMax:
1245
1.78M
      case Opcode::F64X2RelaxedMin:
1246
1.78M
      case Opcode::F64X2RelaxedMax:
1247
1.78M
      case Opcode::I16X8RelaxedQ15mulrS:
1248
1.78M
      case Opcode::I16X8DotI8X16I7X16S:
1249
1.78M
        CALLBACK(OnBinaryExpr, opcode);
1250
1.78M
        CALLBACK0(OnOpcodeBare);
1251
1.78M
        break;
1252
1253
1.78M
      case Opcode::I32Eq:
1254
28.5k
      case Opcode::I32Ne:
1255
52.8k
      case Opcode::I32LtS:
1256
63.8k
      case Opcode::I32LeS:
1257
68.0k
      case Opcode::I32LtU:
1258
77.1k
      case Opcode::I32LeU:
1259
93.8k
      case Opcode::I32GtS:
1260
107k
      case Opcode::I32GeS:
1261
128k
      case Opcode::I32GtU:
1262
136k
      case Opcode::I32GeU:
1263
142k
      case Opcode::I64Eq:
1264
155k
      case Opcode::I64Ne:
1265
168k
      case Opcode::I64LtS:
1266
177k
      case Opcode::I64LeS:
1267
187k
      case Opcode::I64LtU:
1268
202k
      case Opcode::I64LeU:
1269
238k
      case Opcode::I64GtS:
1270
256k
      case Opcode::I64GeS:
1271
273k
      case Opcode::I64GtU:
1272
280k
      case Opcode::I64GeU:
1273
310k
      case Opcode::F32Eq:
1274
319k
      case Opcode::F32Ne:
1275
338k
      case Opcode::F32Lt:
1276
350k
      case Opcode::F32Le:
1277
361k
      case Opcode::F32Gt:
1278
379k
      case Opcode::F32Ge:
1279
433k
      case Opcode::F64Eq:
1280
440k
      case Opcode::F64Ne:
1281
453k
      case Opcode::F64Lt:
1282
467k
      case Opcode::F64Le:
1283
530k
      case Opcode::F64Gt:
1284
546k
      case Opcode::F64Ge:
1285
548k
      case Opcode::I8X16Eq:
1286
551k
      case Opcode::I16X8Eq:
1287
553k
      case Opcode::I32X4Eq:
1288
553k
      case Opcode::I64X2Eq:
1289
558k
      case Opcode::F32X4Eq:
1290
560k
      case Opcode::F64X2Eq:
1291
561k
      case Opcode::I8X16Ne:
1292
562k
      case Opcode::I16X8Ne:
1293
564k
      case Opcode::I32X4Ne:
1294
565k
      case Opcode::I64X2Ne:
1295
567k
      case Opcode::F32X4Ne:
1296
568k
      case Opcode::F64X2Ne:
1297
569k
      case Opcode::I8X16LtS:
1298
573k
      case Opcode::I8X16LtU:
1299
575k
      case Opcode::I16X8LtS:
1300
578k
      case Opcode::I16X8LtU:
1301
579k
      case Opcode::I32X4LtS:
1302
585k
      case Opcode::I32X4LtU:
1303
586k
      case Opcode::I64X2LtS:
1304
588k
      case Opcode::F32X4Lt:
1305
590k
      case Opcode::F64X2Lt:
1306
593k
      case Opcode::I8X16LeS:
1307
596k
      case Opcode::I8X16LeU:
1308
598k
      case Opcode::I16X8LeS:
1309
601k
      case Opcode::I16X8LeU:
1310
602k
      case Opcode::I32X4LeS:
1311
604k
      case Opcode::I32X4LeU:
1312
604k
      case Opcode::I64X2LeS:
1313
606k
      case Opcode::F32X4Le:
1314
607k
      case Opcode::F64X2Le:
1315
608k
      case Opcode::I8X16GtS:
1316
610k
      case Opcode::I8X16GtU:
1317
614k
      case Opcode::I16X8GtS:
1318
616k
      case Opcode::I16X8GtU:
1319
620k
      case Opcode::I32X4GtS:
1320
621k
      case Opcode::I32X4GtU:
1321
623k
      case Opcode::I64X2GtS:
1322
627k
      case Opcode::F32X4Gt:
1323
629k
      case Opcode::F64X2Gt:
1324
646k
      case Opcode::I8X16GeS:
1325
648k
      case Opcode::I8X16GeU:
1326
650k
      case Opcode::I16X8GeS:
1327
652k
      case Opcode::I16X8GeU:
1328
654k
      case Opcode::I32X4GeS:
1329
655k
      case Opcode::I32X4GeU:
1330
657k
      case Opcode::I64X2GeS:
1331
663k
      case Opcode::F32X4Ge:
1332
665k
      case Opcode::F64X2Ge:
1333
665k
        CALLBACK(OnCompareExpr, opcode);
1334
665k
        CALLBACK0(OnOpcodeBare);
1335
665k
        break;
1336
1337
665k
      case Opcode::I32Clz:
1338
32.0k
      case Opcode::I32Ctz:
1339
51.4k
      case Opcode::I32Popcnt:
1340
66.2k
      case Opcode::I64Clz:
1341
85.2k
      case Opcode::I64Ctz:
1342
133k
      case Opcode::I64Popcnt:
1343
142k
      case Opcode::F32Abs:
1344
146k
      case Opcode::F32Neg:
1345
171k
      case Opcode::F32Ceil:
1346
180k
      case Opcode::F32Floor:
1347
190k
      case Opcode::F32Trunc:
1348
200k
      case Opcode::F32Nearest:
1349
208k
      case Opcode::F32Sqrt:
1350
219k
      case Opcode::F64Abs:
1351
225k
      case Opcode::F64Neg:
1352
230k
      case Opcode::F64Ceil:
1353
236k
      case Opcode::F64Floor:
1354
241k
      case Opcode::F64Trunc:
1355
246k
      case Opcode::F64Nearest:
1356
252k
      case Opcode::F64Sqrt:
1357
254k
      case Opcode::I8X16Splat:
1358
255k
      case Opcode::I16X8Splat:
1359
258k
      case Opcode::I32X4Splat:
1360
260k
      case Opcode::I64X2Splat:
1361
261k
      case Opcode::F32X4Splat:
1362
267k
      case Opcode::F64X2Splat:
1363
271k
      case Opcode::I8X16Neg:
1364
273k
      case Opcode::I16X8Neg:
1365
283k
      case Opcode::I32X4Neg:
1366
285k
      case Opcode::I64X2Neg:
1367
288k
      case Opcode::V128Not:
1368
289k
      case Opcode::V128AnyTrue:
1369
300k
      case Opcode::I8X16Bitmask:
1370
302k
      case Opcode::I16X8Bitmask:
1371
303k
      case Opcode::I32X4Bitmask:
1372
307k
      case Opcode::I64X2Bitmask:
1373
308k
      case Opcode::I8X16AllTrue:
1374
313k
      case Opcode::I16X8AllTrue:
1375
315k
      case Opcode::I32X4AllTrue:
1376
316k
      case Opcode::I64X2AllTrue:
1377
319k
      case Opcode::F32X4Ceil:
1378
321k
      case Opcode::F64X2Ceil:
1379
323k
      case Opcode::F32X4Floor:
1380
327k
      case Opcode::F64X2Floor:
1381
329k
      case Opcode::F32X4Trunc:
1382
343k
      case Opcode::F64X2Trunc:
1383
344k
      case Opcode::F32X4Nearest:
1384
345k
      case Opcode::F64X2Nearest:
1385
349k
      case Opcode::F32X4Neg:
1386
350k
      case Opcode::F64X2Neg:
1387
351k
      case Opcode::F32X4Abs:
1388
353k
      case Opcode::F64X2Abs:
1389
355k
      case Opcode::F32X4Sqrt:
1390
357k
      case Opcode::F64X2Sqrt:
1391
360k
      case Opcode::I16X8ExtendLowI8X16S:
1392
361k
      case Opcode::I16X8ExtendHighI8X16S:
1393
363k
      case Opcode::I16X8ExtendLowI8X16U:
1394
364k
      case Opcode::I16X8ExtendHighI8X16U:
1395
366k
      case Opcode::I32X4ExtendLowI16X8S:
1396
368k
      case Opcode::I32X4ExtendHighI16X8S:
1397
369k
      case Opcode::I32X4ExtendLowI16X8U:
1398
370k
      case Opcode::I32X4ExtendHighI16X8U:
1399
373k
      case Opcode::I64X2ExtendLowI32X4S:
1400
376k
      case Opcode::I64X2ExtendHighI32X4S:
1401
378k
      case Opcode::I64X2ExtendLowI32X4U:
1402
380k
      case Opcode::I64X2ExtendHighI32X4U:
1403
383k
      case Opcode::I8X16Abs:
1404
385k
      case Opcode::I16X8Abs:
1405
386k
      case Opcode::I32X4Abs:
1406
387k
      case Opcode::I64X2Abs:
1407
388k
      case Opcode::I8X16Popcnt:
1408
393k
      case Opcode::I16X8ExtaddPairwiseI8X16S:
1409
395k
      case Opcode::I16X8ExtaddPairwiseI8X16U:
1410
400k
      case Opcode::I32X4ExtaddPairwiseI16X8S:
1411
403k
      case Opcode::I32X4ExtaddPairwiseI16X8U:
1412
403k
      case Opcode::I32X4RelaxedTruncF32X4S:
1413
403k
      case Opcode::I32X4RelaxedTruncF32X4U:
1414
404k
      case Opcode::I32X4RelaxedTruncF64X2SZero:
1415
404k
      case Opcode::I32X4RelaxedTruncF64X2UZero:
1416
404k
        CALLBACK(OnUnaryExpr, opcode);
1417
404k
        CALLBACK0(OnOpcodeBare);
1418
404k
        break;
1419
1420
404k
      case Opcode::V128BitSelect:
1421
2.23k
      case Opcode::F32X4RelaxedMadd:
1422
2.89k
      case Opcode::F32X4RelaxedNmadd:
1423
3.45k
      case Opcode::F64X2RelaxedMadd:
1424
3.81k
      case Opcode::F64X2RelaxedNmadd:
1425
4.42k
      case Opcode::I8X16RelaxedLaneSelect:
1426
4.77k
      case Opcode::I16X8RelaxedLaneSelect:
1427
5.24k
      case Opcode::I32X4RelaxedLaneSelect:
1428
5.81k
      case Opcode::I64X2RelaxedLaneSelect:
1429
6.71k
      case Opcode::I32X4DotI8X16I7X16AddS:
1430
6.71k
        CALLBACK(OnTernaryExpr, opcode);
1431
6.71k
        CALLBACK0(OnOpcodeBare);
1432
6.71k
        break;
1433
1434
6.71k
      case Opcode::I8X16ExtractLaneS:
1435
2.60k
      case Opcode::I8X16ExtractLaneU:
1436
5.12k
      case Opcode::I16X8ExtractLaneS:
1437
6.77k
      case Opcode::I16X8ExtractLaneU:
1438
7.80k
      case Opcode::I32X4ExtractLane:
1439
9.45k
      case Opcode::I64X2ExtractLane:
1440
12.0k
      case Opcode::F32X4ExtractLane:
1441
19.8k
      case Opcode::F64X2ExtractLane:
1442
20.8k
      case Opcode::I8X16ReplaceLane:
1443
27.0k
      case Opcode::I16X8ReplaceLane:
1444
31.7k
      case Opcode::I32X4ReplaceLane:
1445
33.4k
      case Opcode::I64X2ReplaceLane:
1446
35.2k
      case Opcode::F32X4ReplaceLane:
1447
36.7k
      case Opcode::F64X2ReplaceLane: {
1448
36.7k
        uint8_t lane_val;
1449
36.7k
        CHECK_RESULT(ReadU8(&lane_val, "Lane idx"));
1450
36.5k
        CALLBACK(OnSimdLaneOpExpr, opcode, lane_val);
1451
36.5k
        CALLBACK(OnOpcodeUint64, lane_val);
1452
36.5k
        break;
1453
36.5k
      }
1454
1455
36.5k
      case Opcode::I8X16Shuffle: {
1456
20.4k
        v128 value;
1457
20.4k
        CHECK_RESULT(ReadV128(&value, "Lane idx [16]"));
1458
20.3k
        CALLBACK(OnSimdShuffleOpExpr, opcode, value);
1459
20.3k
        CALLBACK(OnOpcodeV128, value);
1460
20.3k
        break;
1461
20.3k
      }
1462
1463
20.3k
      case Opcode::V128Load8Splat:
1464
5.54k
      case Opcode::V128Load16Splat:
1465
6.93k
      case Opcode::V128Load32Splat:
1466
7.95k
      case Opcode::V128Load64Splat: {
1467
7.95k
        Address alignment_log2;
1468
7.95k
        Index memidx;
1469
7.95k
        Address offset;
1470
7.95k
        CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset,
1471
7.95k
                                     "load alignment", "load memidx",
1472
7.95k
                                     "load offset"));
1473
7.84k
        CALLBACK(OnLoadSplatExpr, opcode, memidx, alignment_log2, offset);
1474
7.84k
        CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset));
1475
7.84k
        break;
1476
7.84k
      }
1477
7.84k
      case Opcode::V128Load8Lane:
1478
3.12k
      case Opcode::V128Load16Lane:
1479
6.45k
      case Opcode::V128Load32Lane:
1480
10.2k
      case Opcode::V128Load64Lane: {
1481
10.2k
        Address alignment_log2;
1482
10.2k
        Index memidx;
1483
10.2k
        Address offset;
1484
10.2k
        uint8_t lane_val;
1485
10.2k
        CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset,
1486
10.2k
                                     "load alignment", "load memidx",
1487
10.2k
                                     "load offset", &lane_val));
1488
10.1k
        CALLBACK(OnSimdLoadLaneExpr, opcode, memidx, alignment_log2, offset,
1489
10.1k
                 lane_val);
1490
10.1k
        CHECK_RESULT(
1491
10.1k
            CallbackMemLocation(&alignment_log2, &memidx, &offset, &lane_val));
1492
10.1k
        break;
1493
10.1k
      }
1494
10.1k
      case Opcode::V128Store8Lane:
1495
6.43k
      case Opcode::V128Store16Lane:
1496
10.2k
      case Opcode::V128Store32Lane:
1497
12.1k
      case Opcode::V128Store64Lane: {
1498
12.1k
        Address alignment_log2;
1499
12.1k
        Index memidx;
1500
12.1k
        Address offset;
1501
12.1k
        uint8_t lane_val;
1502
12.1k
        CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset,
1503
12.1k
                                     "store alignment", "store memidx",
1504
12.1k
                                     "store offset", &lane_val));
1505
12.0k
        CALLBACK(OnSimdStoreLaneExpr, opcode, memidx, alignment_log2, offset,
1506
12.0k
                 lane_val);
1507
12.0k
        CHECK_RESULT(
1508
12.0k
            CallbackMemLocation(&alignment_log2, &memidx, &offset, &lane_val));
1509
12.0k
        break;
1510
12.0k
      }
1511
12.0k
      case Opcode::V128Load32Zero:
1512
5.78k
      case Opcode::V128Load64Zero: {
1513
5.78k
        Address alignment_log2;
1514
5.78k
        Index memidx;
1515
5.78k
        Address offset;
1516
5.78k
        CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset,
1517
5.78k
                                     "load alignment", "load memidx",
1518
5.78k
                                     "load offset"));
1519
5.72k
        CALLBACK(OnLoadZeroExpr, opcode, memidx, alignment_log2, offset);
1520
5.72k
        CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset));
1521
5.72k
        break;
1522
5.72k
      }
1523
11.8k
      case Opcode::I32TruncF32S:
1524
38.6k
      case Opcode::I32TruncF64S:
1525
45.6k
      case Opcode::I32TruncF32U:
1526
55.9k
      case Opcode::I32TruncF64U:
1527
62.0k
      case Opcode::I32WrapI64:
1528
67.3k
      case Opcode::I64TruncF32S:
1529
81.6k
      case Opcode::I64TruncF64S:
1530
90.3k
      case Opcode::I64TruncF32U:
1531
123k
      case Opcode::I64TruncF64U:
1532
131k
      case Opcode::I64ExtendI32S:
1533
143k
      case Opcode::I64ExtendI32U:
1534
166k
      case Opcode::F32ConvertI32S:
1535
185k
      case Opcode::F32ConvertI32U:
1536
191k
      case Opcode::F32ConvertI64S:
1537
198k
      case Opcode::F32ConvertI64U:
1538
207k
      case Opcode::F32DemoteF64:
1539
212k
      case Opcode::F32ReinterpretI32:
1540
218k
      case Opcode::F64ConvertI32S:
1541
234k
      case Opcode::F64ConvertI32U:
1542
248k
      case Opcode::F64ConvertI64S:
1543
265k
      case Opcode::F64ConvertI64U:
1544
275k
      case Opcode::F64PromoteF32:
1545
285k
      case Opcode::F64ReinterpretI64:
1546
299k
      case Opcode::I32ReinterpretF32:
1547
342k
      case Opcode::I64ReinterpretF64:
1548
361k
      case Opcode::I32Eqz:
1549
373k
      case Opcode::I64Eqz:
1550
378k
      case Opcode::F32X4ConvertI32X4S:
1551
379k
      case Opcode::F32X4ConvertI32X4U:
1552
381k
      case Opcode::I32X4TruncSatF32X4S:
1553
382k
      case Opcode::I32X4TruncSatF32X4U:
1554
384k
      case Opcode::F32X4DemoteF64X2Zero:
1555
388k
      case Opcode::F64X2PromoteLowF32X4:
1556
396k
      case Opcode::I32X4TruncSatF64X2SZero:
1557
397k
      case Opcode::I32X4TruncSatF64X2UZero:
1558
398k
      case Opcode::F64X2ConvertLowI32X4S:
1559
400k
      case Opcode::F64X2ConvertLowI32X4U:
1560
400k
        CALLBACK(OnConvertExpr, opcode);
1561
400k
        CALLBACK0(OnOpcodeBare);
1562
400k
        break;
1563
1564
459k
      case Opcode::Try: {
1565
459k
        nested_blocks.push(opcode);
1566
459k
        Type sig_type;
1567
459k
        CHECK_RESULT(ReadType(&sig_type, "try signature type"));
1568
458k
        ERROR_UNLESS(IsBlockType(sig_type),
1569
458k
                     "expected valid block signature type");
1570
458k
        CALLBACK(OnTryExpr, sig_type);
1571
458k
        CALLBACK(OnOpcodeBlockSig, sig_type);
1572
458k
        break;
1573
458k
      }
1574
1575
458k
      case Opcode::TryTable: {
1576
9.40k
        nested_blocks.push(opcode);
1577
9.40k
        Type sig_type;
1578
9.40k
        CHECK_RESULT(ReadType(&sig_type, "try_table signature type"));
1579
9.30k
        ERROR_UNLESS(IsBlockType(sig_type),
1580
9.27k
                     "expected valid block signature type");
1581
9.27k
        Index count;
1582
9.27k
        CHECK_RESULT(ReadCount(&count, "catch count"));
1583
1584
9.18k
        catches_.resize(count);
1585
21.3k
        for (Index i = 0; i < count; i++) {
1586
12.5k
          uint8_t handler;
1587
12.5k
          CHECK_RESULT(ReadU8(&handler, "catch handler"));
1588
12.5k
          ERROR_UNLESS(handler < 4, "expected valid catch handler");
1589
12.2k
          bool is_catch_all = handler & 2;
1590
12.2k
          Index tag = kInvalidIndex;
1591
12.2k
          if (!(is_catch_all)) {
1592
8.60k
            CHECK_RESULT(ReadIndex(&tag, "catch tag"));
1593
8.60k
          }
1594
12.2k
          Index depth;
1595
12.2k
          CHECK_RESULT(ReadIndex(&depth, "catch depth"));
1596
12.1k
          CatchClause catch_;
1597
12.1k
          catch_.kind = CatchKind(handler);
1598
12.1k
          catch_.tag = tag;
1599
12.1k
          catch_.depth = depth;
1600
12.1k
          catches_[i] = catch_;
1601
12.1k
        }
1602
1603
8.84k
        CALLBACK(OnTryTableExpr, sig_type, catches_);
1604
8.84k
        break;
1605
8.84k
      }
1606
1607
14.2k
      case Opcode::Catch: {
1608
14.2k
        Index index;
1609
14.2k
        CHECK_RESULT(ReadIndex(&index, "tag index"));
1610
14.1k
        CALLBACK(OnCatchExpr, index);
1611
14.1k
        CALLBACK(OnOpcodeIndex, index);
1612
14.1k
        break;
1613
14.1k
      }
1614
1615
14.1k
      case Opcode::CatchAll: {
1616
10.8k
        CALLBACK(OnCatchAllExpr);
1617
10.8k
        CALLBACK(OnOpcodeBare);
1618
10.8k
        break;
1619
10.8k
      }
1620
1621
10.8k
      case Opcode::Delegate: {
1622
1.22k
        ERROR_IF(nested_blocks.empty() || (nested_blocks.top() != Opcode::Try),
1623
1.22k
                 "delegate outside try block");
1624
1.07k
        nested_blocks.pop();
1625
1.07k
        Index index;
1626
1.07k
        CHECK_RESULT(ReadIndex(&index, "depth"));
1627
1.04k
        CALLBACK(OnDelegateExpr, index);
1628
1.04k
        CALLBACK(OnOpcodeIndex, index);
1629
1.04k
        break;
1630
1.04k
      }
1631
1632
19.3k
      case Opcode::Rethrow: {
1633
19.3k
        Index depth;
1634
19.3k
        CHECK_RESULT(ReadIndex(&depth, "catch depth"));
1635
19.2k
        CALLBACK(OnRethrowExpr, depth);
1636
19.2k
        CALLBACK(OnOpcodeIndex, depth);
1637
19.2k
        break;
1638
19.2k
      }
1639
1640
19.2k
      case Opcode::Throw: {
1641
11.5k
        Index index;
1642
11.5k
        CHECK_RESULT(ReadIndex(&index, "tag index"));
1643
11.4k
        CALLBACK(OnThrowExpr, index);
1644
11.4k
        CALLBACK(OnOpcodeIndex, index);
1645
11.4k
        break;
1646
11.4k
      }
1647
1648
12.6k
      case Opcode::ThrowRef: {
1649
12.6k
        CALLBACK(OnThrowRefExpr);
1650
12.6k
        CALLBACK(OnOpcodeBare);
1651
12.6k
        break;
1652
12.6k
      }
1653
1654
12.6k
      case Opcode::I32Extend8S:
1655
12.0k
      case Opcode::I32Extend16S:
1656
20.7k
      case Opcode::I64Extend8S:
1657
28.2k
      case Opcode::I64Extend16S:
1658
38.3k
      case Opcode::I64Extend32S:
1659
38.3k
        CALLBACK(OnUnaryExpr, opcode);
1660
38.3k
        CALLBACK0(OnOpcodeBare);
1661
38.3k
        break;
1662
1663
38.3k
      case Opcode::I32TruncSatF32S:
1664
9.60k
      case Opcode::I32TruncSatF32U:
1665
11.4k
      case Opcode::I32TruncSatF64S:
1666
14.9k
      case Opcode::I32TruncSatF64U:
1667
18.5k
      case Opcode::I64TruncSatF32S:
1668
19.9k
      case Opcode::I64TruncSatF32U:
1669
21.5k
      case Opcode::I64TruncSatF64S:
1670
25.1k
      case Opcode::I64TruncSatF64U:
1671
25.1k
        CALLBACK(OnConvertExpr, opcode);
1672
25.1k
        CALLBACK0(OnOpcodeBare);
1673
25.1k
        break;
1674
1675
25.1k
      case Opcode::MemoryAtomicNotify: {
1676
2.73k
        Address alignment_log2;
1677
2.73k
        Index memidx;
1678
2.73k
        Address offset;
1679
2.73k
        CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset,
1680
2.73k
                                     "notify alignment", "notify memidx",
1681
2.73k
                                     "notify offset"));
1682
2.71k
        CALLBACK(OnAtomicNotifyExpr, opcode, memidx, alignment_log2, offset);
1683
2.71k
        CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset));
1684
2.71k
        break;
1685
2.71k
      }
1686
1687
2.71k
      case Opcode::MemoryAtomicWait32:
1688
1.24k
      case Opcode::MemoryAtomicWait64: {
1689
1.24k
        Address alignment_log2;
1690
1.24k
        Index memidx;
1691
1.24k
        Address offset;
1692
1.24k
        CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset,
1693
1.24k
                                     "wait alignment", "wait memidx",
1694
1.24k
                                     "wait offset"));
1695
1.18k
        CALLBACK(OnAtomicWaitExpr, opcode, memidx, alignment_log2, offset);
1696
1.18k
        CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset));
1697
1.18k
        break;
1698
1.18k
      }
1699
1700
1.18k
      case Opcode::AtomicFence: {
1701
537
        uint8_t consistency_model;
1702
537
        CHECK_RESULT(ReadU8(&consistency_model, "consistency model"));
1703
520
        ERROR_UNLESS(consistency_model == 0,
1704
473
                     "atomic.fence consistency model must be 0");
1705
473
        CALLBACK(OnAtomicFenceExpr, consistency_model);
1706
473
        CALLBACK(OnOpcodeUint32, consistency_model);
1707
473
        break;
1708
473
      }
1709
1710
900
      case Opcode::I32AtomicLoad8U:
1711
1.63k
      case Opcode::I32AtomicLoad16U:
1712
2.52k
      case Opcode::I64AtomicLoad8U:
1713
2.91k
      case Opcode::I64AtomicLoad16U:
1714
3.38k
      case Opcode::I64AtomicLoad32U:
1715
3.73k
      case Opcode::I32AtomicLoad:
1716
4.48k
      case Opcode::I64AtomicLoad: {
1717
4.48k
        Address alignment_log2;
1718
4.48k
        Index memidx;
1719
4.48k
        Address offset;
1720
4.48k
        CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset,
1721
4.48k
                                     "load alignment", "load memidx",
1722
4.48k
                                     "load offset"));
1723
4.34k
        CALLBACK(OnAtomicLoadExpr, opcode, memidx, alignment_log2, offset);
1724
4.34k
        CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset));
1725
4.34k
        break;
1726
4.34k
      }
1727
1728
4.34k
      case Opcode::I32AtomicStore8:
1729
865
      case Opcode::I32AtomicStore16:
1730
1.25k
      case Opcode::I64AtomicStore8:
1731
1.72k
      case Opcode::I64AtomicStore16:
1732
2.04k
      case Opcode::I64AtomicStore32:
1733
2.33k
      case Opcode::I32AtomicStore:
1734
2.75k
      case Opcode::I64AtomicStore: {
1735
2.75k
        Address alignment_log2;
1736
2.75k
        Index memidx;
1737
2.75k
        Address offset;
1738
2.75k
        CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset,
1739
2.75k
                                     "store alignment", "store memidx",
1740
2.75k
                                     "store offset"));
1741
2.65k
        CALLBACK(OnAtomicStoreExpr, opcode, memidx, alignment_log2, offset);
1742
2.65k
        CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset));
1743
2.65k
        break;
1744
2.65k
      }
1745
1746
2.65k
      case Opcode::I32AtomicRmwAdd:
1747
1.36k
      case Opcode::I64AtomicRmwAdd:
1748
1.80k
      case Opcode::I32AtomicRmw8AddU:
1749
2.29k
      case Opcode::I32AtomicRmw16AddU:
1750
2.77k
      case Opcode::I64AtomicRmw8AddU:
1751
3.50k
      case Opcode::I64AtomicRmw16AddU:
1752
4.41k
      case Opcode::I64AtomicRmw32AddU:
1753
5.24k
      case Opcode::I32AtomicRmwSub:
1754
5.71k
      case Opcode::I64AtomicRmwSub:
1755
6.21k
      case Opcode::I32AtomicRmw8SubU:
1756
6.62k
      case Opcode::I32AtomicRmw16SubU:
1757
6.98k
      case Opcode::I64AtomicRmw8SubU:
1758
7.54k
      case Opcode::I64AtomicRmw16SubU:
1759
8.35k
      case Opcode::I64AtomicRmw32SubU:
1760
8.93k
      case Opcode::I32AtomicRmwAnd:
1761
9.35k
      case Opcode::I64AtomicRmwAnd:
1762
9.80k
      case Opcode::I32AtomicRmw8AndU:
1763
10.2k
      case Opcode::I32AtomicRmw16AndU:
1764
11.8k
      case Opcode::I64AtomicRmw8AndU:
1765
12.4k
      case Opcode::I64AtomicRmw16AndU:
1766
12.9k
      case Opcode::I64AtomicRmw32AndU:
1767
13.4k
      case Opcode::I32AtomicRmwOr:
1768
14.3k
      case Opcode::I64AtomicRmwOr:
1769
14.7k
      case Opcode::I32AtomicRmw8OrU:
1770
15.1k
      case Opcode::I32AtomicRmw16OrU:
1771
15.5k
      case Opcode::I64AtomicRmw8OrU:
1772
16.1k
      case Opcode::I64AtomicRmw16OrU:
1773
16.6k
      case Opcode::I64AtomicRmw32OrU:
1774
17.1k
      case Opcode::I32AtomicRmwXor:
1775
18.4k
      case Opcode::I64AtomicRmwXor:
1776
18.7k
      case Opcode::I32AtomicRmw8XorU:
1777
19.1k
      case Opcode::I32AtomicRmw16XorU:
1778
19.6k
      case Opcode::I64AtomicRmw8XorU:
1779
19.9k
      case Opcode::I64AtomicRmw16XorU:
1780
20.5k
      case Opcode::I64AtomicRmw32XorU:
1781
21.2k
      case Opcode::I32AtomicRmwXchg:
1782
21.7k
      case Opcode::I64AtomicRmwXchg:
1783
22.3k
      case Opcode::I32AtomicRmw8XchgU:
1784
22.8k
      case Opcode::I32AtomicRmw16XchgU:
1785
23.7k
      case Opcode::I64AtomicRmw8XchgU:
1786
24.3k
      case Opcode::I64AtomicRmw16XchgU:
1787
24.8k
      case Opcode::I64AtomicRmw32XchgU: {
1788
24.8k
        Address alignment_log2;
1789
24.8k
        Index memidx;
1790
24.8k
        Address offset;
1791
24.8k
        CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset,
1792
24.8k
                                     "memory alignment", "memory memidx",
1793
24.8k
                                     "memory offset"));
1794
24.1k
        CALLBACK(OnAtomicRmwExpr, opcode, memidx, alignment_log2, offset);
1795
24.1k
        CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset));
1796
24.1k
        break;
1797
24.1k
      }
1798
1799
24.1k
      case Opcode::I32AtomicRmwCmpxchg:
1800
990
      case Opcode::I64AtomicRmwCmpxchg:
1801
1.61k
      case Opcode::I32AtomicRmw8CmpxchgU:
1802
1.94k
      case Opcode::I32AtomicRmw16CmpxchgU:
1803
2.25k
      case Opcode::I64AtomicRmw8CmpxchgU:
1804
2.53k
      case Opcode::I64AtomicRmw16CmpxchgU:
1805
2.88k
      case Opcode::I64AtomicRmw32CmpxchgU: {
1806
2.88k
        Address alignment_log2;
1807
2.88k
        Index memidx;
1808
2.88k
        Address offset;
1809
2.88k
        CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset,
1810
2.88k
                                     "memory alignment", "memory memidx",
1811
2.88k
                                     "memory offset"));
1812
2.75k
        CALLBACK(OnAtomicRmwCmpxchgExpr, opcode, memidx, alignment_log2,
1813
2.75k
                 offset);
1814
2.75k
        CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset));
1815
2.75k
        break;
1816
2.75k
      }
1817
1818
2.75k
      case Opcode::TableInit: {
1819
1.35k
        Index segment;
1820
1.35k
        CHECK_RESULT(ReadIndex(&segment, "elem segment index"));
1821
1.34k
        Index table_index;
1822
1.34k
        CHECK_RESULT(ReadIndex(&table_index, "reserved table index"));
1823
1.32k
        CALLBACK(OnTableInitExpr, segment, table_index);
1824
1.32k
        CALLBACK(OnOpcodeUint32Uint32, segment, table_index);
1825
1.32k
        break;
1826
1.32k
      }
1827
1828
1.32k
      case Opcode::MemoryInit: {
1829
426
        Index segment;
1830
426
        ERROR_IF(data_count_ == kInvalidIndex,
1831
426
                 "memory.init requires data count section");
1832
406
        CHECK_RESULT(ReadIndex(&segment, "elem segment index"));
1833
286
        Index memidx = 0;
1834
286
        if (!options_.features.multi_memory_enabled()) {
1835
102
          uint8_t reserved;
1836
102
          CHECK_RESULT(ReadU8(&reserved, "reserved memory index"));
1837
99
          ERROR_UNLESS(reserved == 0, "reserved value must be 0");
1838
184
        } else {
1839
184
          CHECK_RESULT(ReadMemidx(&memidx, "memory.init memidx"));
1840
184
        }
1841
262
        CALLBACK(OnMemoryInitExpr, segment, memidx);
1842
262
        CALLBACK(OnOpcodeUint32Uint32, segment, memidx);
1843
262
        break;
1844
262
      }
1845
1846
826
      case Opcode::DataDrop:
1847
826
        ERROR_IF(data_count_ == kInvalidIndex,
1848
826
                 "data.drop requires data count section");
1849
812
        [[fallthrough]];
1850
4.55k
      case Opcode::ElemDrop: {
1851
4.55k
        Index segment;
1852
4.55k
        CHECK_RESULT(ReadIndex(&segment, "segment index"));
1853
4.52k
        if (opcode == Opcode::DataDrop) {
1854
804
          CALLBACK(OnDataDropExpr, segment);
1855
3.72k
        } else {
1856
3.72k
          CALLBACK(OnElemDropExpr, segment);
1857
3.72k
        }
1858
4.52k
        CALLBACK(OnOpcodeUint32, segment);
1859
4.52k
        break;
1860
4.52k
      }
1861
1862
12.6k
      case Opcode::MemoryFill: {
1863
12.6k
        Index memidx = 0;
1864
12.6k
        if (!options_.features.multi_memory_enabled()) {
1865
2.96k
          uint8_t reserved;
1866
2.96k
          CHECK_RESULT(ReadU8(&reserved, "memory.fill reserved"));
1867
2.95k
          ERROR_UNLESS(reserved == 0, "memory.fill reserved value must be 0");
1868
9.66k
        } else {
1869
9.66k
          CHECK_RESULT(ReadMemidx(&memidx, "memory.fill memidx"));
1870
9.66k
        }
1871
12.5k
        CALLBACK(OnMemoryFillExpr, memidx);
1872
12.5k
        CALLBACK(OnOpcodeUint32, memidx);
1873
12.5k
        break;
1874
12.5k
      }
1875
1876
12.5k
      case Opcode::MemoryCopy: {
1877
3.38k
        Index destmemidx = 0;
1878
3.38k
        Index srcmemidx = 0;
1879
3.38k
        if (!options_.features.multi_memory_enabled()) {
1880
1.38k
          uint8_t reserved;
1881
1.38k
          CHECK_RESULT(ReadU8(&reserved, "reserved memory index"));
1882
1.37k
          ERROR_UNLESS(reserved == 0, "reserved value must be 0");
1883
1.36k
          CHECK_RESULT(ReadU8(&reserved, "reserved memory index"));
1884
1.35k
          ERROR_UNLESS(reserved == 0, "reserved value must be 0");
1885
2.00k
        } else {
1886
2.00k
          CHECK_RESULT(ReadMemidx(&destmemidx, "memory.copy destmemindex"));
1887
1.98k
          CHECK_RESULT(ReadMemidx(&srcmemidx, "memory.copy srcmemidx"));
1888
1.98k
        }
1889
3.31k
        CALLBACK(OnMemoryCopyExpr, destmemidx, srcmemidx);
1890
3.31k
        CALLBACK(OnOpcodeUint32Uint32, destmemidx, srcmemidx);
1891
3.31k
        break;
1892
3.31k
      }
1893
1894
3.31k
      case Opcode::TableCopy: {
1895
1.91k
        Index table_dst;
1896
1.91k
        Index table_src;
1897
1.91k
        CHECK_RESULT(ReadIndex(&table_dst, "reserved table index"));
1898
1.89k
        CHECK_RESULT(ReadIndex(&table_src, "table src"));
1899
1.88k
        CALLBACK(OnTableCopyExpr, table_dst, table_src);
1900
1.88k
        CALLBACK(OnOpcodeUint32Uint32, table_dst, table_src);
1901
1.88k
        break;
1902
1.88k
      }
1903
1904
16.0k
      case Opcode::TableGet: {
1905
16.0k
        Index table;
1906
16.0k
        CHECK_RESULT(ReadIndex(&table, "table index"));
1907
15.9k
        CALLBACK(OnTableGetExpr, table);
1908
15.9k
        CALLBACK(OnOpcodeUint32, table);
1909
15.9k
        break;
1910
15.9k
      }
1911
1912
15.9k
      case Opcode::TableSet: {
1913
15.1k
        Index table;
1914
15.1k
        CHECK_RESULT(ReadIndex(&table, "table index"));
1915
15.1k
        CALLBACK(OnTableSetExpr, table);
1916
15.1k
        CALLBACK(OnOpcodeUint32, table);
1917
15.1k
        break;
1918
15.1k
      }
1919
1920
15.1k
      case Opcode::TableGrow: {
1921
3.95k
        Index table;
1922
3.95k
        CHECK_RESULT(ReadIndex(&table, "table index"));
1923
3.92k
        CALLBACK(OnTableGrowExpr, table);
1924
3.92k
        CALLBACK(OnOpcodeUint32, table);
1925
3.92k
        break;
1926
3.92k
      }
1927
1928
3.92k
      case Opcode::TableSize: {
1929
1.35k
        Index table;
1930
1.35k
        CHECK_RESULT(ReadIndex(&table, "table index"));
1931
1.32k
        CALLBACK(OnTableSizeExpr, table);
1932
1.32k
        CALLBACK(OnOpcodeUint32, table);
1933
1.32k
        break;
1934
1.32k
      }
1935
1936
5.56k
      case Opcode::TableFill: {
1937
5.56k
        Index table;
1938
5.56k
        CHECK_RESULT(ReadIndex(&table, "table index"));
1939
5.55k
        CALLBACK(OnTableFillExpr, table);
1940
5.55k
        CALLBACK(OnOpcodeUint32, table);
1941
5.55k
        break;
1942
5.55k
      }
1943
1944
5.55k
      case Opcode::RefAsNonNull:
1945
1.41k
        CALLBACK(OnRefAsNonNullExpr);
1946
1.41k
        CALLBACK(OnOpcodeBare);
1947
1.41k
        break;
1948
1949
4.73k
      case Opcode::RefFunc: {
1950
4.73k
        Index func;
1951
4.73k
        CHECK_RESULT(ReadIndex(&func, "func index"));
1952
4.70k
        CALLBACK(OnRefFuncExpr, func);
1953
4.69k
        CALLBACK(OnOpcodeUint32, func);
1954
4.69k
        break;
1955
4.69k
      }
1956
1957
13.1k
      case Opcode::RefNull: {
1958
13.1k
        uint64_t heap_type;
1959
13.1k
        Type type;
1960
13.1k
        CHECK_RESULT(ReadS64Leb128(&heap_type, "ref.null type"));
1961
1962
12.9k
        if (static_cast<int64_t>(heap_type) < 0 ||
1963
9.15k
            static_cast<int64_t>(heap_type) >= kInvalidIndex) {
1964
9.15k
          Type::Enum type_code = static_cast<Type::Enum>(heap_type);
1965
9.15k
          ERROR_UNLESS(IsConcreteReferenceType(type_code),
1966
8.31k
                       "expected valid ref.null type (got " PRItypecode ")",
1967
8.31k
                       WABT_PRINTF_TYPE_CODE(type_code));
1968
8.31k
          type = Type(type_code);
1969
8.31k
        } else {
1970
3.80k
          ERROR_UNLESS(options_.features.function_references_enabled(),
1971
3.72k
                       "function references are not enabled for ref.null");
1972
3.72k
          type = Type(Type::RefNull, static_cast<Index>(heap_type));
1973
3.72k
        }
1974
1975
12.0k
        CALLBACK(OnRefNullExpr, type);
1976
12.0k
        CALLBACK(OnOpcodeType, type);
1977
12.0k
        break;
1978
12.0k
      }
1979
1980
12.0k
      case Opcode::RefIsNull:
1981
4.25k
        CALLBACK(OnRefIsNullExpr);
1982
4.25k
        CALLBACK(OnOpcodeBare);
1983
4.25k
        break;
1984
1985
4.79k
      case Opcode::CallRef: {
1986
4.79k
        uint32_t type;
1987
4.79k
        CHECK_RESULT(ReadU32Leb128(&type, "call_ref type"));
1988
1989
4.73k
        Type sig_type(Type::RefNull, type);
1990
4.73k
        CALLBACK(OnCallRefExpr, sig_type);
1991
4.73k
        CALLBACK(OnOpcodeType, sig_type);
1992
4.73k
        break;
1993
4.73k
      }
1994
1995
4.73k
      case Opcode::ReturnCallRef: {
1996
4.32k
        uint32_t type;
1997
4.32k
        CHECK_RESULT(ReadU32Leb128(&type, "return_call_ref type"));
1998
1999
4.28k
        Type sig_type(Type::RefNull, type);
2000
4.28k
        CALLBACK(OnReturnCallRefExpr, sig_type);
2001
4.28k
        CALLBACK(OnOpcodeType, sig_type);
2002
4.28k
        break;
2003
4.28k
      }
2004
2005
4.60k
      default:
2006
4.60k
        return ReportUnexpectedOpcode(opcode);
2007
14.6M
    }
2008
14.6M
  }
2009
2010
15.0k
  PrintError("%s must end with END opcode", context);
2011
15.0k
  return Result::Error;
2012
122k
}
2013
2014
183k
Result BinaryReader::ReadNameSection(Offset section_size) {
2015
183k
  CALLBACK(BeginNamesSection, section_size);
2016
183k
  Index i = 0;
2017
183k
  uint32_t previous_subsection_type = 0;
2018
567k
  while (state_.offset < read_end_) {
2019
553k
    uint32_t name_type;
2020
553k
    Offset subsection_size;
2021
553k
    CHECK_RESULT(ReadU32Leb128(&name_type, "name type"));
2022
552k
    if (i != 0) {
2023
369k
      ERROR_UNLESS(name_type != previous_subsection_type,
2024
361k
                   "duplicate sub-section");
2025
361k
      ERROR_UNLESS(name_type >= previous_subsection_type,
2026
361k
                   "out-of-order sub-section");
2027
361k
    }
2028
455k
    previous_subsection_type = name_type;
2029
455k
    CHECK_RESULT(ReadOffset(&subsection_size, "subsection size"));
2030
434k
    size_t subsection_end = state_.offset + subsection_size;
2031
434k
    ERROR_UNLESS(subsection_end <= read_end_,
2032
432k
                 "invalid sub-section size: extends past end");
2033
432k
    ReadEndRestoreGuard guard(this);
2034
432k
    read_end_ = subsection_end;
2035
2036
432k
    NameSectionSubsection type = static_cast<NameSectionSubsection>(name_type);
2037
432k
    if (type <= NameSectionSubsection::Last) {
2038
169k
      CALLBACK(OnNameSubsection, i, type, subsection_size);
2039
169k
    }
2040
2041
432k
    switch (type) {
2042
117k
      case NameSectionSubsection::Module:
2043
117k
        CALLBACK(OnModuleNameSubsection, i, name_type, subsection_size);
2044
117k
        if (subsection_size) {
2045
106k
          std::string_view name;
2046
106k
          CHECK_RESULT(ReadStr(&name, "module name"));
2047
99.9k
          CALLBACK(OnModuleName, name);
2048
99.9k
        }
2049
110k
        break;
2050
110k
      case NameSectionSubsection::Function:
2051
4.72k
        CALLBACK(OnFunctionNameSubsection, i, name_type, subsection_size);
2052
4.72k
        if (subsection_size) {
2053
3.82k
          Index num_names;
2054
3.82k
          CHECK_RESULT(ReadCount(&num_names, "name count"));
2055
3.72k
          CALLBACK(OnFunctionNamesCount, num_names);
2056
3.72k
          Index last_function_index = kInvalidIndex;
2057
2058
12.0k
          for (Index j = 0; j < num_names; ++j) {
2059
11.8k
            Index function_index;
2060
11.8k
            std::string_view function_name;
2061
2062
11.8k
            CHECK_RESULT(ReadIndex(&function_index, "function index"));
2063
11.6k
            ERROR_UNLESS(function_index != last_function_index,
2064
11.6k
                         "duplicate function name: %u", function_index);
2065
11.6k
            ERROR_UNLESS(last_function_index == kInvalidIndex ||
2066
9.33k
                             function_index > last_function_index,
2067
9.33k
                         "function index out of order: %u", function_index);
2068
9.33k
            last_function_index = function_index;
2069
9.33k
            ERROR_UNLESS(function_index < NumTotalFuncs(),
2070
8.76k
                         "invalid function index: %" PRIindex, function_index);
2071
8.76k
            CHECK_RESULT(ReadStr(&function_name, "function name"));
2072
8.37k
            CALLBACK(OnFunctionName, function_index, function_name);
2073
8.37k
          }
2074
3.72k
        }
2075
1.14k
        break;
2076
24.9k
      case NameSectionSubsection::Local:
2077
24.9k
        CALLBACK(OnLocalNameSubsection, i, name_type, subsection_size);
2078
24.9k
        if (subsection_size) {
2079
24.5k
          Index num_funcs;
2080
24.5k
          CHECK_RESULT(ReadCount(&num_funcs, "function count"));
2081
24.2k
          CALLBACK(OnLocalNameFunctionCount, num_funcs);
2082
24.2k
          Index last_function_index = kInvalidIndex;
2083
51.2k
          for (Index j = 0; j < num_funcs; ++j) {
2084
48.5k
            Index function_index;
2085
48.5k
            CHECK_RESULT(ReadIndex(&function_index, "function index"));
2086
44.9k
            ERROR_UNLESS(function_index < NumTotalFuncs(),
2087
41.5k
                         "invalid function index: %u", function_index);
2088
41.5k
            ERROR_UNLESS(last_function_index == kInvalidIndex ||
2089
40.2k
                             function_index > last_function_index,
2090
40.2k
                         "locals function index out of order: %u",
2091
40.2k
                         function_index);
2092
40.2k
            last_function_index = function_index;
2093
40.2k
            Index num_locals;
2094
40.2k
            CHECK_RESULT(ReadCount(&num_locals, "local count"));
2095
36.0k
            CALLBACK(OnLocalNameLocalCount, function_index, num_locals);
2096
36.0k
            Index last_local_index = kInvalidIndex;
2097
66.6k
            for (Index k = 0; k < num_locals; ++k) {
2098
39.6k
              Index local_index;
2099
39.6k
              std::string_view local_name;
2100
2101
39.6k
              CHECK_RESULT(ReadIndex(&local_index, "named index"));
2102
38.0k
              ERROR_UNLESS(local_index != last_local_index,
2103
36.5k
                           "duplicate local index: %u", local_index);
2104
36.5k
              ERROR_UNLESS(last_local_index == kInvalidIndex ||
2105
31.1k
                               local_index > last_local_index,
2106
31.1k
                           "local index out of order: %u", local_index);
2107
31.1k
              last_local_index = local_index;
2108
31.1k
              CHECK_RESULT(ReadStr(&local_name, "name"));
2109
30.6k
              CALLBACK(OnLocalName, function_index, local_index, local_name);
2110
30.6k
            }
2111
36.0k
          }
2112
24.2k
        }
2113
3.20k
        break;
2114
3.20k
      case NameSectionSubsection::Label:
2115
        // TODO(sbc): Implement label names. These are slightly more complicated
2116
        // since they refer to offsets in the code section / instruction stream.
2117
270
        state_.offset = subsection_end;
2118
270
        break;
2119
4.77k
      case NameSectionSubsection::Type:
2120
9.50k
      case NameSectionSubsection::Table:
2121
9.71k
      case NameSectionSubsection::Memory:
2122
10.7k
      case NameSectionSubsection::Global:
2123
14.4k
      case NameSectionSubsection::ElemSegment:
2124
20.9k
      case NameSectionSubsection::DataSegment:
2125
21.5k
      case NameSectionSubsection::Tag:
2126
21.5k
        if (subsection_size) {
2127
16.7k
          Index num_names;
2128
16.7k
          CHECK_RESULT(ReadCount(&num_names, "name count"));
2129
12.4k
          CALLBACK(OnNameCount, num_names);
2130
53.9k
          for (Index j = 0; j < num_names; ++j) {
2131
50.0k
            Index index;
2132
50.0k
            std::string_view name;
2133
2134
50.0k
            CHECK_RESULT(ReadIndex(&index, "index"));
2135
48.1k
            CHECK_RESULT(ReadStr(&name, "name"));
2136
41.4k
            CALLBACK(OnNameEntry, type, index, name);
2137
41.4k
          }
2138
12.4k
        }
2139
8.69k
        state_.offset = subsection_end;
2140
8.69k
        break;
2141
263k
      default:
2142
        // Unknown subsection, skip it.
2143
263k
        state_.offset = subsection_end;
2144
263k
        break;
2145
432k
    }
2146
387k
    ++i;
2147
387k
    ERROR_UNLESS(state_.offset == subsection_end,
2148
387k
                 "unfinished sub-section (expected end: 0x%" PRIzx ")",
2149
387k
                 subsection_end);
2150
387k
  }
2151
14.6k
  CALLBACK0(EndNamesSection);
2152
14.6k
  return Result::Ok;
2153
14.6k
}
2154
2155
43.7k
Result BinaryReader::ReadRelocSection(Offset section_size) {
2156
43.7k
  CALLBACK(BeginRelocSection, section_size);
2157
43.7k
  uint32_t section_index;
2158
43.7k
  CHECK_RESULT(ReadU32Leb128(&section_index, "section index"));
2159
43.2k
  Index num_relocs;
2160
43.2k
  CHECK_RESULT(ReadCount(&num_relocs, "relocation count"));
2161
41.8k
  CALLBACK(OnRelocCount, num_relocs, section_index);
2162
179k
  for (Index i = 0; i < num_relocs; ++i) {
2163
165k
    Offset offset;
2164
165k
    Index index;
2165
165k
    uint32_t reloc_type, addend = 0;
2166
165k
    CHECK_RESULT(ReadU32Leb128(&reloc_type, "relocation type"));
2167
164k
    CHECK_RESULT(ReadOffset(&offset, "offset"));
2168
162k
    CHECK_RESULT(ReadIndex(&index, "index"));
2169
154k
    RelocType type = static_cast<RelocType>(reloc_type);
2170
154k
    switch (type) {
2171
1.39k
      case RelocType::MemoryAddressLEB:
2172
5.41k
      case RelocType::MemoryAddressLEB64:
2173
7.67k
      case RelocType::MemoryAddressSLEB:
2174
10.5k
      case RelocType::MemoryAddressSLEB64:
2175
17.3k
      case RelocType::MemoryAddressRelSLEB:
2176
20.3k
      case RelocType::MemoryAddressRelSLEB64:
2177
21.4k
      case RelocType::MemoryAddressI32:
2178
23.0k
      case RelocType::MemoryAddressI64:
2179
24.3k
      case RelocType::MemoryAddressLocRelI32:
2180
25.7k
      case RelocType::FunctionOffsetI32:
2181
26.7k
      case RelocType::FunctionOffsetI64:
2182
29.1k
      case RelocType::SectionOffsetI32:
2183
32.3k
      case RelocType::MemoryAddressTLSSLEB:
2184
33.2k
      case RelocType::MemoryAddressTLSSLEB64:
2185
33.2k
        CHECK_RESULT(ReadS32Leb128(&addend, "addend"));
2186
29.9k
        break;
2187
2188
69.0k
      case RelocType::FuncIndexLEB:
2189
70.2k
      case RelocType::FuncIndexI32:
2190
72.3k
      case RelocType::TableIndexSLEB:
2191
73.4k
      case RelocType::TableIndexSLEB64:
2192
74.3k
      case RelocType::TableIndexI32:
2193
77.1k
      case RelocType::TableIndexI64:
2194
78.5k
      case RelocType::TypeIndexLEB:
2195
80.4k
      case RelocType::GlobalIndexLEB:
2196
81.6k
      case RelocType::GlobalIndexI32:
2197
83.4k
      case RelocType::TagIndexLEB:
2198
84.7k
      case RelocType::TableIndexRelSLEB:
2199
85.5k
      case RelocType::TableIndexRelSLEB64:
2200
111k
      case RelocType::TableNumberLEB:
2201
111k
        break;
2202
2203
9.76k
      default:
2204
9.76k
        PrintError("unknown reloc type: %s", GetRelocTypeName(type));
2205
9.76k
        return Result::Error;
2206
154k
    }
2207
141k
    CALLBACK(OnReloc, type, offset, index, addend);
2208
141k
  }
2209
14.0k
  CALLBACK0(EndRelocSection);
2210
14.0k
  return Result::Ok;
2211
14.0k
}
2212
2213
49.8k
Result BinaryReader::ReadDylink0Section(Offset section_size) {
2214
49.8k
  CALLBACK(BeginDylinkSection, section_size);
2215
2216
215k
  while (state_.offset < read_end_) {
2217
213k
    uint32_t dylink_type;
2218
213k
    Offset subsection_size;
2219
213k
    CHECK_RESULT(ReadU32Leb128(&dylink_type, "type"));
2220
206k
    CHECK_RESULT(ReadOffset(&subsection_size, "subsection size"));
2221
193k
    size_t subsection_end = state_.offset + subsection_size;
2222
193k
    ERROR_UNLESS(subsection_end <= read_end_,
2223
191k
                 "invalid sub-section size: extends past end");
2224
191k
    ReadEndRestoreGuard guard(this);
2225
191k
    read_end_ = subsection_end;
2226
2227
191k
    uint32_t count;
2228
191k
    switch (static_cast<DylinkEntryType>(dylink_type)) {
2229
4.57k
      case DylinkEntryType::MemInfo: {
2230
4.57k
        uint32_t mem_size;
2231
4.57k
        uint32_t mem_align;
2232
4.57k
        uint32_t table_size;
2233
4.57k
        uint32_t table_align;
2234
2235
4.57k
        CHECK_RESULT(ReadU32Leb128(&mem_size, "mem_size"));
2236
4.03k
        CHECK_RESULT(ReadU32Leb128(&mem_align, "mem_align"));
2237
3.43k
        CHECK_RESULT(ReadU32Leb128(&table_size, "table_size"));
2238
2.91k
        CHECK_RESULT(ReadU32Leb128(&table_align, "table_align"));
2239
1.94k
        CALLBACK(OnDylinkInfo, mem_size, mem_align, table_size, table_align);
2240
1.94k
        break;
2241
1.94k
      }
2242
6.37k
      case DylinkEntryType::Needed:
2243
6.37k
        CHECK_RESULT(ReadU32Leb128(&count, "needed_dynlibs"));
2244
5.48k
        CALLBACK(OnDylinkNeededCount, count);
2245
9.82k
        while (count--) {
2246
6.88k
          std::string_view so_name;
2247
6.88k
          CHECK_RESULT(ReadStr(&so_name, "dylib so_name"));
2248
4.34k
          CALLBACK(OnDylinkNeeded, so_name);
2249
4.34k
        }
2250
2.93k
        break;
2251
27.3k
      case DylinkEntryType::ImportInfo:
2252
27.3k
        CHECK_RESULT(ReadU32Leb128(&count, "count"));
2253
26.6k
        CALLBACK(OnDylinkImportCount, count);
2254
58.8k
        for (Index i = 0; i < count; ++i) {
2255
44.3k
          uint32_t flags = 0;
2256
44.3k
          std::string_view module;
2257
44.3k
          std::string_view field;
2258
44.3k
          CHECK_RESULT(ReadStr(&module, "module"));
2259
35.9k
          CHECK_RESULT(ReadStr(&field, "field"));
2260
33.3k
          CHECK_RESULT(ReadU32Leb128(&flags, "flags"));
2261
32.6k
          CALLBACK(OnDylinkImport, module, field, flags);
2262
32.6k
        }
2263
14.5k
        break;
2264
14.5k
      case DylinkEntryType::ExportInfo:
2265
6.31k
        CHECK_RESULT(ReadU32Leb128(&count, "count"));
2266
5.88k
        CALLBACK(OnDylinkExportCount, count);
2267
12.1k
        for (Index i = 0; i < count; ++i) {
2268
9.07k
          uint32_t flags = 0;
2269
9.07k
          std::string_view name;
2270
9.07k
          CHECK_RESULT(ReadStr(&name, "name"));
2271
7.74k
          CHECK_RESULT(ReadU32Leb128(&flags, "flags"));
2272
6.35k
          CALLBACK(OnDylinkExport, name, flags);
2273
6.35k
        }
2274
3.07k
        break;
2275
146k
      default:
2276
        // Unknown subsection, skip it.
2277
146k
        state_.offset = subsection_end;
2278
146k
        break;
2279
191k
    }
2280
169k
    ERROR_UNLESS(state_.offset == subsection_end,
2281
169k
                 "unfinished sub-section (expected end: 0x%" PRIzx ")",
2282
169k
                 subsection_end);
2283
169k
  }
2284
2285
2.37k
  CALLBACK0(EndDylinkSection);
2286
2.37k
  return Result::Ok;
2287
2.37k
}
2288
2289
15.0k
Result BinaryReader::ReadDylinkSection(Offset section_size) {
2290
15.0k
  CALLBACK(BeginDylinkSection, section_size);
2291
15.0k
  uint32_t mem_size;
2292
15.0k
  uint32_t mem_align;
2293
15.0k
  uint32_t table_size;
2294
15.0k
  uint32_t table_align;
2295
2296
15.0k
  CHECK_RESULT(ReadU32Leb128(&mem_size, "mem_size"));
2297
14.6k
  CHECK_RESULT(ReadU32Leb128(&mem_align, "mem_align"));
2298
14.3k
  CHECK_RESULT(ReadU32Leb128(&table_size, "table_size"));
2299
13.9k
  CHECK_RESULT(ReadU32Leb128(&table_align, "table_align"));
2300
13.5k
  CALLBACK(OnDylinkInfo, mem_size, mem_align, table_size, table_align);
2301
2302
13.5k
  uint32_t count;
2303
13.5k
  CHECK_RESULT(ReadU32Leb128(&count, "needed_dynlibs"));
2304
11.6k
  CALLBACK(OnDylinkNeededCount, count);
2305
17.6k
  while (count--) {
2306
7.75k
    std::string_view so_name;
2307
7.75k
    CHECK_RESULT(ReadStr(&so_name, "dylib so_name"));
2308
6.00k
    CALLBACK(OnDylinkNeeded, so_name);
2309
6.00k
  }
2310
2311
9.88k
  CALLBACK0(EndDylinkSection);
2312
9.88k
  return Result::Ok;
2313
9.88k
}
2314
2315
35.1k
Result BinaryReader::ReadTargetFeaturesSections(Offset section_size) {
2316
35.1k
  CALLBACK(BeginTargetFeaturesSection, section_size);
2317
35.1k
  uint32_t count;
2318
35.1k
  CHECK_RESULT(ReadU32Leb128(&count, "sym count"));
2319
34.1k
  CALLBACK(OnFeatureCount, count);
2320
138k
  while (count--) {
2321
126k
    uint8_t prefix;
2322
126k
    std::string_view name;
2323
126k
    CHECK_RESULT(ReadU8(&prefix, "prefix"));
2324
111k
    CHECK_RESULT(ReadStr(&name, "feature name"));
2325
104k
    CALLBACK(OnFeature, prefix, name);
2326
104k
  }
2327
11.8k
  CALLBACK0(EndTargetFeaturesSection);
2328
11.8k
  return Result::Ok;
2329
11.8k
}
2330
2331
Result BinaryReader::ReadGenericCustomSection(std::string_view name,
2332
2.43M
                                              Offset section_size) {
2333
2.43M
  CALLBACK(BeginGenericCustomSection, section_size);
2334
2.43M
  const void* data;
2335
2.43M
  Offset custom_data_size = read_end_ - state_.offset;
2336
2.43M
  CHECK_RESULT(
2337
2.43M
      ReadBytesWithSize(&data, custom_data_size, "custom section data"));
2338
2.43M
  CALLBACK(OnGenericCustomSection, name, data, custom_data_size);
2339
2.43M
  CALLBACK0(EndGenericCustomSection);
2340
2.43M
  return Result::Ok;
2341
2.43M
}
2342
2343
192k
Result BinaryReader::ReadLinkingSection(Offset section_size) {
2344
192k
  CALLBACK(BeginLinkingSection, section_size);
2345
192k
  uint32_t version;
2346
192k
  CHECK_RESULT(ReadU32Leb128(&version, "version"));
2347
191k
  ERROR_UNLESS(version == 2, "invalid linking metadata version: %u", version);
2348
357k
  while (state_.offset < read_end_) {
2349
306k
    uint32_t linking_type;
2350
306k
    Offset subsection_size;
2351
306k
    CHECK_RESULT(ReadU32Leb128(&linking_type, "type"));
2352
305k
    CHECK_RESULT(ReadOffset(&subsection_size, "subsection size"));
2353
301k
    size_t subsection_end = state_.offset + subsection_size;
2354
301k
    ERROR_UNLESS(subsection_end <= read_end_,
2355
299k
                 "invalid sub-section size: extends past end");
2356
299k
    ReadEndRestoreGuard guard(this);
2357
299k
    read_end_ = subsection_end;
2358
2359
299k
    uint32_t count;
2360
299k
    switch (static_cast<LinkingEntryType>(linking_type)) {
2361
153k
      case LinkingEntryType::SymbolTable:
2362
153k
        CHECK_RESULT(ReadU32Leb128(&count, "sym count"));
2363
153k
        CALLBACK(OnSymbolCount, count);
2364
714k
        for (Index i = 0; i < count; ++i) {
2365
654k
          std::string_view name;
2366
654k
          uint32_t flags = 0;
2367
654k
          uint32_t kind = 0;
2368
654k
          CHECK_RESULT(ReadU32Leb128(&kind, "sym type"));
2369
625k
          CHECK_RESULT(ReadU32Leb128(&flags, "sym flags"));
2370
611k
          SymbolType sym_type = static_cast<SymbolType>(kind);
2371
611k
          switch (sym_type) {
2372
177k
            case SymbolType::Function:
2373
250k
            case SymbolType::Global:
2374
296k
            case SymbolType::Tag:
2375
415k
            case SymbolType::Table: {
2376
415k
              uint32_t index = 0;
2377
415k
              CHECK_RESULT(ReadU32Leb128(&index, "index"));
2378
409k
              if ((flags & WABT_SYMBOL_FLAG_UNDEFINED) == 0 ||
2379
117k
                  (flags & WABT_SYMBOL_FLAG_EXPLICIT_NAME) != 0)
2380
370k
                CHECK_RESULT(ReadStr(&name, "symbol name"));
2381
389k
              switch (sym_type) {
2382
153k
                case SymbolType::Function:
2383
153k
                  CALLBACK(OnFunctionSymbol, i, flags, name, index);
2384
152k
                  break;
2385
152k
                case SymbolType::Global:
2386
72.5k
                  CALLBACK(OnGlobalSymbol, i, flags, name, index);
2387
71.2k
                  break;
2388
71.2k
                case SymbolType::Tag:
2389
44.8k
                  CALLBACK(OnTagSymbol, i, flags, name, index);
2390
43.3k
                  break;
2391
118k
                case SymbolType::Table:
2392
118k
                  CALLBACK(OnTableSymbol, i, flags, name, index);
2393
114k
                  break;
2394
114k
                default:
2395
0
                  WABT_UNREACHABLE;
2396
389k
              }
2397
381k
              break;
2398
389k
            }
2399
381k
            case SymbolType::Data: {
2400
53.3k
              uint32_t segment = 0;
2401
53.3k
              uint32_t offset = 0;
2402
53.3k
              uint32_t size = 0;
2403
53.3k
              CHECK_RESULT(ReadStr(&name, "symbol name"));
2404
50.1k
              if ((flags & WABT_SYMBOL_FLAG_UNDEFINED) == 0) {
2405
37.0k
                CHECK_RESULT(ReadU32Leb128(&segment, "segment"));
2406
36.3k
                CHECK_RESULT(ReadU32Leb128(&offset, "offset"));
2407
34.0k
                CHECK_RESULT(ReadU32Leb128(&size, "size"));
2408
34.0k
              }
2409
44.5k
              CALLBACK(OnDataSymbol, i, flags, name, segment, offset, size);
2410
40.5k
              break;
2411
44.5k
            }
2412
40.5k
            case SymbolType::Section: {
2413
13.8k
              uint32_t index = 0;
2414
13.8k
              CHECK_RESULT(ReadU32Leb128(&index, "index"));
2415
11.8k
              CALLBACK(OnSectionSymbol, i, flags, index);
2416
10.3k
              break;
2417
11.8k
            }
2418
611k
          }
2419
611k
        }
2420
59.9k
        break;
2421
59.9k
      case LinkingEntryType::SegmentInfo:
2422
20.3k
        CHECK_RESULT(ReadU32Leb128(&count, "info count"));
2423
19.6k
        CALLBACK(OnSegmentInfoCount, count);
2424
40.9k
        for (Index i = 0; i < count; i++) {
2425
31.8k
          std::string_view name;
2426
31.8k
          Address alignment_log2;
2427
31.8k
          uint32_t flags;
2428
31.8k
          CHECK_RESULT(ReadStr(&name, "segment name"));
2429
28.8k
          CHECK_RESULT(ReadAlignment(&alignment_log2, "segment alignment"));
2430
28.4k
          CHECK_RESULT(CheckAlignment(&alignment_log2, "segment alignment"));
2431
26.9k
          CHECK_RESULT(ReadU32Leb128(&flags, "segment flags"));
2432
26.6k
          CALLBACK(OnSegmentInfo, i, name, alignment_log2, flags);
2433
26.6k
        }
2434
9.09k
        break;
2435
15.9k
      case LinkingEntryType::InitFunctions:
2436
15.9k
        CHECK_RESULT(ReadU32Leb128(&count, "info count"));
2437
14.5k
        CALLBACK(OnInitFunctionCount, count);
2438
35.3k
        while (count--) {
2439
25.5k
          uint32_t priority;
2440
25.5k
          uint32_t symbol;
2441
25.5k
          CHECK_RESULT(ReadU32Leb128(&priority, "priority"));
2442
23.1k
          CHECK_RESULT(ReadU32Leb128(&symbol, "symbol index"));
2443
20.8k
          CALLBACK(OnInitFunction, priority, symbol);
2444
20.8k
        }
2445
9.86k
        break;
2446
13.0k
      case LinkingEntryType::ComdatInfo:
2447
13.0k
        CHECK_RESULT(ReadU32Leb128(&count, "count"));
2448
12.4k
        CALLBACK(OnComdatCount, count);
2449
19.1k
        while (count--) {
2450
16.2k
          uint32_t flags;
2451
16.2k
          uint32_t entry_count;
2452
16.2k
          std::string_view name;
2453
16.2k
          CHECK_RESULT(ReadStr(&name, "comdat name"));
2454
13.8k
          CHECK_RESULT(ReadU32Leb128(&flags, "flags"));
2455
12.8k
          CHECK_RESULT(ReadU32Leb128(&entry_count, "entry count"));
2456
12.3k
          CALLBACK(OnComdatBegin, name, flags, entry_count);
2457
64.9k
          while (entry_count--) {
2458
58.1k
            uint32_t kind;
2459
58.1k
            uint32_t index;
2460
58.1k
            CHECK_RESULT(ReadU32Leb128(&kind, "kind"));
2461
56.1k
            CHECK_RESULT(ReadU32Leb128(&index, "index"));
2462
52.5k
            ComdatType comdat_type = static_cast<ComdatType>(kind);
2463
52.5k
            CALLBACK(OnComdatEntry, comdat_type, index);
2464
52.5k
          }
2465
12.3k
        }
2466
2.95k
        break;
2467
96.1k
      default:
2468
        // Unknown subsection, skip it.
2469
96.1k
        state_.offset = subsection_end;
2470
96.1k
        break;
2471
299k
    }
2472
178k
    ERROR_UNLESS(state_.offset == subsection_end,
2473
178k
                 "unfinished sub-section (expected end: 0x%" PRIzx ")",
2474
178k
                 subsection_end);
2475
178k
  }
2476
50.9k
  CALLBACK0(EndLinkingSection);
2477
50.9k
  return Result::Ok;
2478
50.9k
}
2479
2480
9.62k
Result BinaryReader::ReadTagType(Index* out_sig_index) {
2481
9.62k
  uint8_t attribute;
2482
9.62k
  CHECK_RESULT(ReadU8(&attribute, "tag attribute"));
2483
9.57k
  ERROR_UNLESS(attribute == 0, "tag attribute must be 0");
2484
9.43k
  CHECK_RESULT(ReadIndex(out_sig_index, "tag signature index"));
2485
9.40k
  return Result::Ok;
2486
9.43k
}
2487
2488
731
Result BinaryReader::ReadTagSection(Offset section_size) {
2489
731
  CALLBACK(BeginTagSection, section_size);
2490
731
  Index num_tags;
2491
731
  CHECK_RESULT(ReadCount(&num_tags, "tag count"));
2492
311
  CALLBACK(OnTagCount, num_tags);
2493
2494
3.68k
  for (Index i = 0; i < num_tags; ++i) {
2495
3.55k
    Index tag_index = num_tag_imports_ + i;
2496
3.55k
    Index sig_index;
2497
3.55k
    CHECK_RESULT(ReadTagType(&sig_index));
2498
3.37k
    CALLBACK(OnTagType, tag_index, sig_index);
2499
3.37k
  }
2500
2501
125
  CALLBACK(EndTagSection);
2502
125
  return Result::Ok;
2503
125
}
2504
2505
Result BinaryReader::ReadCodeMetadataSection(std::string_view name,
2506
452k
                                             Offset section_size) {
2507
452k
  CALLBACK(BeginCodeMetadataSection, name, section_size);
2508
2509
452k
  Index num_functions;
2510
452k
  CHECK_RESULT(ReadCount(&num_functions, "function count"));
2511
449k
  CALLBACK(OnCodeMetadataFuncCount, num_functions);
2512
2513
449k
  Index last_function_index = kInvalidIndex;
2514
1.51M
  for (Index i = 0; i < num_functions; ++i) {
2515
1.38M
    Index function_index;
2516
1.38M
    CHECK_RESULT(ReadIndex(&function_index, "function index"));
2517
1.37M
    ERROR_UNLESS(function_index >= num_func_imports_,
2518
1.37M
                 "function import can't have metadata (got %" PRIindex ")",
2519
1.37M
                 function_index);
2520
1.37M
    ERROR_UNLESS(function_index < NumTotalFuncs(),
2521
1.28M
                 "invalid function index: %" PRIindex, function_index);
2522
1.28M
    ERROR_UNLESS(function_index != last_function_index,
2523
1.26M
                 "duplicate function index: %" PRIindex, function_index);
2524
1.26M
    ERROR_UNLESS(last_function_index == kInvalidIndex ||
2525
1.12M
                     function_index > last_function_index,
2526
1.12M
                 "function index out of order: %" PRIindex, function_index);
2527
1.12M
    last_function_index = function_index;
2528
2529
1.12M
    Index num_metadata;
2530
1.12M
    CHECK_RESULT(ReadCount(&num_metadata, "metadata instances count"));
2531
2532
1.12M
    CALLBACK(OnCodeMetadataCount, function_index, num_metadata);
2533
2534
1.12M
    Offset last_code_offset = kInvalidOffset;
2535
1.46M
    for (Index j = 0; j < num_metadata; ++j) {
2536
393k
      Offset code_offset;
2537
393k
      CHECK_RESULT(ReadOffset(&code_offset, "code offset"));
2538
354k
      ERROR_UNLESS(code_offset != last_code_offset,
2539
352k
                   "duplicate code offset: %" PRIzx, code_offset);
2540
352k
      ERROR_UNLESS(
2541
348k
          last_code_offset == kInvalidOffset || code_offset > last_code_offset,
2542
348k
          "code offset out of order: %" PRIzx, code_offset);
2543
348k
      last_code_offset = code_offset;
2544
2545
348k
      Address data_size;
2546
348k
      const void* data;
2547
348k
      CHECK_RESULT(ReadBytes(&data, &data_size, "instance data"));
2548
338k
      CALLBACK(OnCodeMetadata, code_offset, data, data_size);
2549
338k
    }
2550
1.12M
  }
2551
2552
138k
  CALLBACK(EndCodeMetadataSection);
2553
138k
  return Result::Ok;
2554
138k
}
2555
2556
Result BinaryReader::ReadCustomSection(Index section_index,
2557
12.4M
                                       Offset section_size) {
2558
12.4M
  std::string_view section_name;
2559
12.4M
  CHECK_RESULT(ReadStr(&section_name, "section name"));
2560
2.43M
  CALLBACK(BeginCustomSection, section_index, section_size, section_name);
2561
2.43M
  ValueRestoreGuard<bool, &BinaryReader::reading_custom_section_> guard(this);
2562
2.43M
  reading_custom_section_ = true;
2563
2564
2.43M
  {
2565
    // Backtrack parser when scope ends
2566
2.43M
    ValueRestoreGuard<BinaryReaderDelegate::State, &BinaryReader::state_> guard(
2567
2.43M
        this);
2568
2.43M
    CHECK_RESULT(ReadGenericCustomSection(section_name, section_size));
2569
2.43M
  }
2570
2571
2.43M
  if (options_.read_debug_names && section_name == WABT_BINARY_SECTION_NAME) {
2572
183k
    CHECK_RESULT(ReadNameSection(section_size));
2573
14.6k
    did_read_names_section_ = true;
2574
2.24M
  } else if (section_name == WABT_BINARY_SECTION_DYLINK0) {
2575
49.8k
    CHECK_RESULT(ReadDylink0Section(section_size));
2576
2.19M
  } else if (section_name == WABT_BINARY_SECTION_DYLINK) {
2577
15.0k
    CHECK_RESULT(ReadDylinkSection(section_size));
2578
2.18M
  } else if (section_name.rfind(WABT_BINARY_SECTION_RELOC, 0) == 0) {
2579
    // Reloc sections always begin with "reloc."
2580
43.7k
    CHECK_RESULT(ReadRelocSection(section_size));
2581
2.13M
  } else if (section_name == WABT_BINARY_SECTION_TARGET_FEATURES) {
2582
35.1k
    CHECK_RESULT(ReadTargetFeaturesSections(section_size));
2583
2.10M
  } else if (section_name == WABT_BINARY_SECTION_LINKING) {
2584
192k
    CHECK_RESULT(ReadLinkingSection(section_size));
2585
1.91M
  } else if (options_.features.code_metadata_enabled() &&
2586
1.05M
             section_name.find(WABT_BINARY_SECTION_CODE_METADATA) == 0) {
2587
452k
    std::string_view metadata_name = section_name;
2588
452k
    metadata_name.remove_prefix(sizeof(WABT_BINARY_SECTION_CODE_METADATA) - 1);
2589
452k
    CHECK_RESULT(ReadCodeMetadataSection(metadata_name, section_size));
2590
1.45M
  } else {
2591
    // Skip. This is a generic custom section, and is handled above.
2592
1.45M
    state_.offset = read_end_;
2593
1.45M
  }
2594
1.70M
  CALLBACK0(EndCustomSection);
2595
1.70M
  return Result::Ok;
2596
1.70M
}
2597
2598
7.79k
Result BinaryReader::ReadTypeSection(Offset section_size) {
2599
7.79k
  CALLBACK(BeginTypeSection, section_size);
2600
7.79k
  Index num_signatures;
2601
7.79k
  CHECK_RESULT(ReadCount(&num_signatures, "type count"));
2602
5.61k
  CALLBACK(OnTypeCount, num_signatures);
2603
2604
13.2k
  for (Index i = 0; i < num_signatures; ++i) {
2605
12.2k
    Type form;
2606
12.2k
    if (options_.features.gc_enabled()) {
2607
8.44k
      CHECK_RESULT(ReadType(&form, "type form"));
2608
8.44k
    } else {
2609
3.79k
      uint8_t type;
2610
3.79k
      CHECK_RESULT(ReadU8(&type, "type form"));
2611
3.63k
      ERROR_UNLESS(type == 0x60, "unexpected type form (got %#x)", type);
2612
3.43k
      form = Type::Func;
2613
3.43k
    }
2614
2615
11.4k
    switch (form) {
2616
8.02k
      case Type::Func: {
2617
8.02k
        Index num_params;
2618
8.02k
        CHECK_RESULT(ReadCount(&num_params, "function param count"));
2619
2620
7.80k
        param_types_.resize(num_params);
2621
2622
38.8k
        for (Index j = 0; j < num_params; ++j) {
2623
31.8k
          Type param_type;
2624
31.8k
          CHECK_RESULT(ReadType(&param_type, "function param type"));
2625
31.7k
          ERROR_UNLESS(IsConcreteType(param_type),
2626
31.0k
                       "expected valid param type (got " PRItypecode ")",
2627
31.0k
                       WABT_PRINTF_TYPE_CODE(param_type));
2628
31.0k
          param_types_[j] = param_type;
2629
31.0k
        }
2630
2631
7.04k
        Index num_results;
2632
7.04k
        CHECK_RESULT(ReadCount(&num_results, "function result count"));
2633
2634
6.64k
        result_types_.resize(num_results);
2635
2636
66.8k
        for (Index j = 0; j < num_results; ++j) {
2637
60.9k
          Type result_type;
2638
60.9k
          CHECK_RESULT(ReadType(&result_type, "function result type"));
2639
60.9k
          ERROR_UNLESS(IsConcreteType(result_type),
2640
60.1k
                       "expected valid result type (got " PRItypecode ")",
2641
60.1k
                       WABT_PRINTF_TYPE_CODE(result_type));
2642
60.1k
          result_types_[j] = result_type;
2643
60.1k
        }
2644
2645
5.82k
        Type* param_types = num_params ? param_types_.data() : nullptr;
2646
5.82k
        Type* result_types = num_results ? result_types_.data() : nullptr;
2647
2648
5.82k
        CALLBACK(OnFuncType, i, num_params, param_types, num_results,
2649
5.82k
                 result_types);
2650
5.82k
        break;
2651
5.82k
      }
2652
2653
5.82k
      case Type::Struct: {
2654
1.94k
        ERROR_UNLESS(options_.features.gc_enabled(),
2655
1.94k
                     "invalid type form: struct not allowed");
2656
1.94k
        Index num_fields;
2657
1.94k
        CHECK_RESULT(ReadCount(&num_fields, "field count"));
2658
2659
1.78k
        fields_.resize(num_fields);
2660
3.28k
        for (Index j = 0; j < num_fields; ++j) {
2661
1.73k
          CHECK_RESULT(ReadField(&fields_[j]));
2662
1.73k
        }
2663
2664
1.55k
        CALLBACK(OnStructType, i, fields_.size(), fields_.data());
2665
1.55k
        break;
2666
1.55k
      }
2667
2668
1.55k
      case Type::Array: {
2669
638
        ERROR_UNLESS(options_.features.gc_enabled(),
2670
638
                     "invalid type form: array not allowed");
2671
2672
638
        TypeMut field;
2673
638
        CHECK_RESULT(ReadField(&field));
2674
289
        CALLBACK(OnArrayType, i, field);
2675
289
        break;
2676
289
      };
2677
2678
845
      default:
2679
845
        PrintError("unexpected type form (got " PRItypecode ")",
2680
845
                   WABT_PRINTF_TYPE_CODE(form));
2681
845
        return Result::Error;
2682
11.4k
    }
2683
11.4k
  }
2684
1.03k
  CALLBACK0(EndTypeSection);
2685
1.03k
  return Result::Ok;
2686
1.03k
}
2687
2688
4.67k
Result BinaryReader::ReadImportSection(Offset section_size) {
2689
4.67k
  CALLBACK(BeginImportSection, section_size);
2690
4.67k
  Index num_imports;
2691
4.67k
  CHECK_RESULT(ReadCount(&num_imports, "import count"));
2692
3.55k
  CALLBACK(OnImportCount, num_imports);
2693
1.54M
  for (Index i = 0; i < num_imports; ++i) {
2694
1.54M
    std::string_view module_name;
2695
1.54M
    CHECK_RESULT(ReadStr(&module_name, "import module name"));
2696
1.53M
    std::string_view field_name;
2697
1.53M
    CHECK_RESULT(ReadStr(&field_name, "import field name"));
2698
2699
1.53M
    uint8_t kind;
2700
1.53M
    CHECK_RESULT(ReadU8(&kind, "import kind"));
2701
1.53M
    CALLBACK(OnImport, i, static_cast<ExternalKind>(kind), module_name,
2702
1.53M
             field_name);
2703
1.53M
    switch (static_cast<ExternalKind>(kind)) {
2704
1.21M
      case ExternalKind::Func: {
2705
1.21M
        Index sig_index;
2706
1.21M
        CHECK_RESULT(ReadIndex(&sig_index, "import signature index"));
2707
1.21M
        CALLBACK(OnImportFunc, i, module_name, field_name, num_func_imports_,
2708
1.21M
                 sig_index);
2709
1.21M
        num_func_imports_++;
2710
1.21M
        break;
2711
1.21M
      }
2712
2713
150k
      case ExternalKind::Table: {
2714
150k
        Type elem_type;
2715
150k
        Limits elem_limits;
2716
150k
        CHECK_RESULT(ReadRefType(&elem_type, "table elem type"));
2717
150k
        CHECK_RESULT(ReadTable(&elem_limits));
2718
150k
        CALLBACK(OnImportTable, i, module_name, field_name, num_table_imports_,
2719
150k
                 elem_type, &elem_limits);
2720
150k
        num_table_imports_++;
2721
150k
        break;
2722
150k
      }
2723
2724
154k
      case ExternalKind::Memory: {
2725
154k
        Limits page_limits;
2726
154k
        uint32_t page_size;
2727
154k
        CHECK_RESULT(ReadMemory(&page_limits, &page_size));
2728
154k
        CALLBACK(OnImportMemory, i, module_name, field_name,
2729
154k
                 num_memory_imports_, &page_limits, page_size);
2730
154k
        num_memory_imports_++;
2731
154k
        break;
2732
154k
      }
2733
2734
15.0k
      case ExternalKind::Global: {
2735
15.0k
        Type type;
2736
15.0k
        bool mutable_;
2737
15.0k
        CHECK_RESULT(ReadGlobalHeader(&type, &mutable_));
2738
14.9k
        CALLBACK(OnImportGlobal, i, module_name, field_name,
2739
14.9k
                 num_global_imports_, type, mutable_);
2740
14.9k
        num_global_imports_++;
2741
14.9k
        break;
2742
14.9k
      }
2743
2744
6.07k
      case ExternalKind::Tag: {
2745
6.07k
        ERROR_UNLESS(options_.features.exceptions_enabled(),
2746
6.06k
                     "invalid import tag kind: exceptions not allowed");
2747
6.06k
        Index sig_index;
2748
6.06k
        CHECK_RESULT(ReadTagType(&sig_index));
2749
6.03k
        CALLBACK(OnImportTag, i, module_name, field_name, num_tag_imports_,
2750
6.03k
                 sig_index);
2751
6.03k
        num_tag_imports_++;
2752
6.03k
        break;
2753
6.03k
      }
2754
2755
304
      default:
2756
304
        PrintError("malformed import kind: %d", kind);
2757
304
        return Result::Error;
2758
1.53M
    }
2759
1.53M
  }
2760
2761
1.11k
  CALLBACK0(EndImportSection);
2762
1.11k
  return Result::Ok;
2763
1.11k
}
2764
2765
22.5k
Result BinaryReader::ReadFunctionSection(Offset section_size) {
2766
22.5k
  CALLBACK(BeginFunctionSection, section_size);
2767
22.5k
  CHECK_RESULT(
2768
22.5k
      ReadCount(&num_function_signatures_, "function signature count"));
2769
7.69k
  CALLBACK(OnFunctionCount, num_function_signatures_);
2770
2.69M
  for (Index i = 0; i < num_function_signatures_; ++i) {
2771
2.68M
    Index func_index = num_func_imports_ + i;
2772
2.68M
    Index sig_index;
2773
2.68M
    CHECK_RESULT(ReadIndex(&sig_index, "function signature index"));
2774
2.68M
    CALLBACK(OnFunction, func_index, sig_index);
2775
2.68M
  }
2776
4.65k
  CALLBACK0(EndFunctionSection);
2777
4.65k
  return Result::Ok;
2778
4.65k
}
2779
2780
3.47k
Result BinaryReader::ReadTableSection(Offset section_size) {
2781
3.47k
  CALLBACK(BeginTableSection, section_size);
2782
3.47k
  Index num_tables;
2783
3.47k
  CHECK_RESULT(ReadCount(&num_tables, "table count"));
2784
2.56k
  CALLBACK(OnTableCount, num_tables);
2785
5.12k
  for (Index i = 0; i < num_tables; ++i) {
2786
4.52k
    Index table_index = num_table_imports_ + i;
2787
4.52k
    Type elem_type;
2788
4.52k
    Limits elem_limits;
2789
4.52k
    TableInitExprStatus init_provided =
2790
4.52k
        TableInitExprStatus::TableWithoutInitExpression;
2791
2792
4.52k
    CHECK_RESULT(ReadType(&elem_type, "table elem type"));
2793
2794
    // Type::Void will never represent a valid type, so it was
2795
    // choosen to represent the availability of the init expression.
2796
4.07k
    if (options_.features.function_references_enabled() &&
2797
2.54k
        elem_type == Type::Void) {
2798
511
      init_provided = TableInitExprStatus::TableWithInitExpression;
2799
2800
511
      uint8_t value;
2801
511
      CHECK_RESULT(ReadU8(&value, "table init"));
2802
      // This zero value is reserved for future
2803
      // extensions, and currently unused.
2804
504
      if (value != 0) {
2805
36
        PrintError("unsupported table intializer: 0x%x\n",
2806
36
                   static_cast<int>(value));
2807
36
        return Result::Error;
2808
36
      }
2809
2810
468
      CHECK_RESULT(ReadType(&elem_type, "table elem type"));
2811
468
    }
2812
2813
4.02k
    ERROR_UNLESS(elem_type.IsRef(), "table elem type must be a reference type");
2814
2815
3.13k
    CHECK_RESULT(ReadTable(&elem_limits));
2816
2.85k
    CALLBACK(BeginTable, table_index, elem_type, &elem_limits, init_provided);
2817
2818
2.84k
    if (init_provided == TableInitExprStatus::TableWithInitExpression) {
2819
431
      CALLBACK(BeginTableInitExpr, table_index);
2820
431
      CHECK_RESULT(ReadInitExpr(table_index));
2821
145
      CALLBACK(EndTableInitExpr, table_index);
2822
145
    }
2823
2824
2.56k
    CALLBACK(EndTable, table_index);
2825
2.56k
  }
2826
602
  CALLBACK0(EndTableSection);
2827
602
  return Result::Ok;
2828
602
}
2829
2830
2.49k
Result BinaryReader::ReadMemorySection(Offset section_size) {
2831
2.49k
  CALLBACK(BeginMemorySection, section_size);
2832
2.49k
  Index num_memories;
2833
2.49k
  CHECK_RESULT(ReadCount(&num_memories, "memory count"));
2834
1.97k
  CALLBACK(OnMemoryCount, num_memories);
2835
33.6k
  for (Index i = 0; i < num_memories; ++i) {
2836
32.7k
    Index memory_index = num_memory_imports_ + i;
2837
32.7k
    Limits page_limits;
2838
32.7k
    uint32_t page_size;
2839
32.7k
    CHECK_RESULT(ReadMemory(&page_limits, &page_size));
2840
31.7k
    CALLBACK(OnMemory, memory_index, &page_limits, page_size);
2841
31.7k
  }
2842
941
  CALLBACK0(EndMemorySection);
2843
941
  return Result::Ok;
2844
941
}
2845
2846
4.92k
Result BinaryReader::ReadGlobalSection(Offset section_size) {
2847
4.92k
  CALLBACK(BeginGlobalSection, section_size);
2848
4.92k
  Index num_globals;
2849
4.92k
  CHECK_RESULT(ReadCount(&num_globals, "global count"));
2850
4.44k
  CALLBACK(OnGlobalCount, num_globals);
2851
17.7k
  for (Index i = 0; i < num_globals; ++i) {
2852
16.9k
    Index global_index = num_global_imports_ + i;
2853
16.9k
    Type global_type;
2854
16.9k
    bool mutable_;
2855
16.9k
    CHECK_RESULT(ReadGlobalHeader(&global_type, &mutable_));
2856
15.5k
    CALLBACK(BeginGlobal, global_index, global_type, mutable_);
2857
15.5k
    CALLBACK(BeginGlobalInitExpr, global_index);
2858
15.5k
    CHECK_RESULT(ReadInitExpr(global_index));
2859
13.2k
    CALLBACK(EndGlobalInitExpr, global_index);
2860
13.2k
    CALLBACK(EndGlobal, global_index);
2861
13.2k
  }
2862
781
  CALLBACK0(EndGlobalSection);
2863
781
  return Result::Ok;
2864
781
}
2865
2866
5.34k
Result BinaryReader::ReadExportSection(Offset section_size) {
2867
5.34k
  CALLBACK(BeginExportSection, section_size);
2868
5.34k
  Index num_exports;
2869
5.34k
  CHECK_RESULT(ReadCount(&num_exports, "export count"));
2870
4.68k
  CALLBACK(OnExportCount, num_exports);
2871
139k
  for (Index i = 0; i < num_exports; ++i) {
2872
138k
    std::string_view name;
2873
138k
    CHECK_RESULT(ReadStr(&name, "export item name"));
2874
2875
136k
    ExternalKind kind;
2876
136k
    CHECK_RESULT(ReadExternalKind(&kind, "export kind"));
2877
2878
135k
    Index item_index;
2879
135k
    CHECK_RESULT(ReadIndex(&item_index, "export item index"));
2880
135k
    if (kind == ExternalKind::Tag) {
2881
552
      ERROR_UNLESS(options_.features.exceptions_enabled(),
2882
552
                   "invalid export tag kind: exceptions not allowed");
2883
552
    }
2884
2885
134k
    CALLBACK(OnExport, i, static_cast<ExternalKind>(kind), item_index, name);
2886
134k
  }
2887
689
  CALLBACK0(EndExportSection);
2888
689
  return Result::Ok;
2889
689
}
2890
2891
1.22k
Result BinaryReader::ReadStartSection(Offset section_size) {
2892
1.22k
  CALLBACK(BeginStartSection, section_size);
2893
1.22k
  Index func_index;
2894
1.22k
  CHECK_RESULT(ReadIndex(&func_index, "start function index"));
2895
986
  CALLBACK(OnStartFunction, func_index);
2896
964
  CALLBACK0(EndStartSection);
2897
964
  return Result::Ok;
2898
964
}
2899
2900
22.8k
Result BinaryReader::ReadElemSection(Offset section_size) {
2901
22.8k
  CALLBACK(BeginElemSection, section_size);
2902
22.8k
  Index num_elem_segments;
2903
22.8k
  CHECK_RESULT(ReadCount(&num_elem_segments, "elem segment count"));
2904
22.4k
  CALLBACK(OnElemSegmentCount, num_elem_segments);
2905
62.9k
  for (Index i = 0; i < num_elem_segments; ++i) {
2906
62.6k
    uint32_t flags;
2907
62.6k
    CHECK_RESULT(ReadU32Leb128(&flags, "elem segment flags"));
2908
62.2k
    ERROR_IF(flags > SegFlagMax, "invalid elem segment flags: %#x", flags);
2909
61.4k
    Index table_index(0);
2910
61.4k
    if ((flags & (SegPassive | SegExplicitIndex)) == SegExplicitIndex) {
2911
10.9k
      CHECK_RESULT(ReadIndex(&table_index, "elem segment table index"));
2912
10.9k
    }
2913
61.4k
    Type elem_type = Type::FuncRef;
2914
2915
61.4k
    if (options_.features.function_references_enabled() &&
2916
32.0k
        !(flags & SegUseElemExprs)) {
2917
26.5k
      elem_type = Type(Type::FuncRef, Type::ReferenceNonNull);
2918
26.5k
    }
2919
2920
61.4k
    CALLBACK(BeginElemSegment, i, table_index, flags);
2921
2922
61.4k
    if (!(flags & SegPassive)) {
2923
53.1k
      CALLBACK(BeginElemSegmentInitExpr, i);
2924
53.1k
      CHECK_RESULT(ReadInitExpr(i));
2925
35.3k
      CALLBACK(EndElemSegmentInitExpr, i);
2926
35.3k
    }
2927
2928
    // For backwards compat we support not declaring the element kind.
2929
43.6k
    if (flags & (SegPassive | SegExplicitIndex)) {
2930
16.8k
      if (flags & SegUseElemExprs) {
2931
5.71k
        CHECK_RESULT(ReadRefType(&elem_type, "table elem type"));
2932
11.1k
      } else {
2933
11.1k
        ExternalKind kind;
2934
11.1k
        CHECK_RESULT(ReadExternalKind(&kind, "export kind"));
2935
11.0k
        ERROR_UNLESS(kind == ExternalKind::Func,
2936
11.0k
                     "segment elem type must be func (%s)",
2937
11.0k
                     elem_type.GetName().c_str());
2938
11.0k
      }
2939
16.8k
    }
2940
2941
42.9k
    CALLBACK(OnElemSegmentElemType, i, elem_type);
2942
2943
42.9k
    Index num_elem_exprs;
2944
42.9k
    CHECK_RESULT(ReadCount(&num_elem_exprs, "elem count"));
2945
2946
42.4k
    CALLBACK(OnElemSegmentElemExprCount, i, num_elem_exprs);
2947
1.15M
    for (Index j = 0; j < num_elem_exprs; ++j) {
2948
1.11M
      CALLBACK(BeginElemExpr, i, j);
2949
1.11M
      if (flags & SegUseElemExprs) {
2950
20.4k
        CHECK_RESULT(ReadInitExpr(j));
2951
1.08M
      } else {
2952
1.08M
        Index func_index;
2953
1.08M
        CHECK_RESULT(ReadIndex(&func_index, "elem expr func index"));
2954
1.08M
        CALLBACK(OnOpcode, Opcode::RefFunc);
2955
1.08M
        CALLBACK(OnRefFuncExpr, func_index);
2956
1.08M
        CALLBACK(OnOpcodeUint32, func_index);
2957
1.08M
        CALLBACK0(OnEndExpr);
2958
1.08M
      }
2959
1.10M
      CALLBACK(EndElemExpr, i, j);
2960
1.10M
    }
2961
40.5k
    CALLBACK(EndElemSegment, i);
2962
40.5k
  }
2963
355
  CALLBACK0(EndElemSection);
2964
355
  return Result::Ok;
2965
355
}
2966
2967
17.3k
Result BinaryReader::ReadCodeSection(Offset section_size) {
2968
17.3k
  CALLBACK(BeginCodeSection, section_size);
2969
17.3k
  CHECK_RESULT(ReadCount(&num_function_bodies_, "function body count"));
2970
16.8k
  ERROR_UNLESS(num_function_signatures_ == num_function_bodies_,
2971
16.4k
               "function signature count != function body count");
2972
16.4k
  CALLBACK(OnFunctionBodyCount, num_function_bodies_);
2973
34.4k
  for (Index i = 0; i < num_function_bodies_; ++i) {
2974
33.6k
    Index func_index = num_func_imports_ + i;
2975
33.6k
    Offset func_offset = state_.offset;
2976
33.6k
    state_.offset = func_offset;
2977
33.6k
    uint32_t body_size;
2978
33.6k
    CHECK_RESULT(ReadU32Leb128(&body_size, "function body size"));
2979
24.6k
    Offset body_start_offset = state_.offset;
2980
24.6k
    Offset end_offset = body_start_offset + body_size;
2981
24.6k
    CALLBACK(BeginFunctionBody, func_index, body_size);
2982
2983
24.6k
    uint64_t total_locals = 0;
2984
24.6k
    Index num_local_decls;
2985
24.6k
    CHECK_RESULT(ReadCount(&num_local_decls, "local declaration count"));
2986
23.4k
    CALLBACK(OnLocalDeclCount, num_local_decls);
2987
41.8k
    for (Index k = 0; k < num_local_decls; ++k) {
2988
19.8k
      Index num_local_types;
2989
19.8k
      CHECK_RESULT(ReadIndex(&num_local_types, "local type count"));
2990
19.6k
      total_locals += num_local_types;
2991
19.6k
      ERROR_UNLESS(total_locals <= UINT32_MAX, "local count must be <= 0x%x",
2992
19.6k
                   UINT32_MAX);
2993
19.6k
      Type local_type;
2994
19.6k
      CHECK_RESULT(ReadType(&local_type, "local type"));
2995
19.3k
      ERROR_UNLESS(IsConcreteType(local_type), "expected valid local type");
2996
18.4k
      CALLBACK(OnLocalDecl, k, num_local_types, local_type);
2997
18.4k
    }
2998
22.0k
    CALLBACK(EndLocalDecls);
2999
3000
22.0k
    if (options_.skip_function_bodies) {
3001
15.6k
      state_.offset = end_offset;
3002
15.6k
    } else {
3003
6.39k
      CHECK_RESULT(ReadFunctionBody(end_offset));
3004
6.39k
    }
3005
3006
18.0k
    CALLBACK(EndFunctionBody, func_index);
3007
18.0k
  }
3008
772
  CALLBACK0(EndCodeSection);
3009
772
  return Result::Ok;
3010
772
}
3011
3012
13.4k
Result BinaryReader::ReadDataSection(Offset section_size) {
3013
13.4k
  CALLBACK(BeginDataSection, section_size);
3014
13.4k
  CHECK_RESULT(ReadCount(&num_data_segments_, "data segment count"));
3015
12.8k
  CALLBACK(OnDataSegmentCount, num_data_segments_);
3016
  // If the DataCount section is not present, then data_count_ will be invalid.
3017
12.8k
  ERROR_UNLESS(
3018
12.5k
      data_count_ == kInvalidIndex || data_count_ == num_data_segments_,
3019
12.5k
      "data segment count does not equal count in DataCount section");
3020
32.2k
  for (Index i = 0; i < num_data_segments_; ++i) {
3021
32.0k
    uint32_t flags;
3022
32.0k
    CHECK_RESULT(ReadU32Leb128(&flags, "data segment flags"));
3023
31.7k
    ERROR_IF(flags != 0 && !options_.features.bulk_memory_enabled(),
3024
31.7k
             "invalid memory index %d: bulk memory not allowed", flags);
3025
31.7k
    ERROR_IF(flags > SegFlagMax, "invalid data segment flags: %#x", flags);
3026
31.0k
    Index memory_index(0);
3027
31.0k
    if (flags & SegExplicitIndex) {
3028
3.50k
      CHECK_RESULT(ReadIndex(&memory_index, "data segment memory index"));
3029
3.50k
    }
3030
30.9k
    CALLBACK(BeginDataSegment, i, memory_index, flags);
3031
30.9k
    if (!(flags & SegPassive)) {
3032
26.5k
      CALLBACK(BeginDataSegmentInitExpr, i);
3033
26.5k
      CHECK_RESULT(ReadInitExpr(i));
3034
15.7k
      CALLBACK(EndDataSegmentInitExpr, i);
3035
15.7k
    }
3036
3037
20.2k
    Address data_size;
3038
20.2k
    const void* data;
3039
20.2k
    CHECK_RESULT(ReadBytes(&data, &data_size, "data segment data"));
3040
19.7k
    CALLBACK(OnDataSegmentData, i, data, data_size);
3041
19.7k
    CALLBACK(EndDataSegment, i);
3042
19.7k
  }
3043
197
  CALLBACK0(EndDataSection);
3044
197
  return Result::Ok;
3045
197
}
3046
3047
1.50k
Result BinaryReader::ReadDataCountSection(Offset section_size) {
3048
1.50k
  CALLBACK(BeginDataCountSection, section_size);
3049
1.50k
  Index data_count;
3050
1.50k
  CHECK_RESULT(ReadIndex(&data_count, "data count"));
3051
1.43k
  CALLBACK(OnDataCount, data_count);
3052
1.43k
  CALLBACK0(EndDataCountSection);
3053
1.43k
  data_count_ = data_count;
3054
1.43k
  return Result::Ok;
3055
1.43k
}
3056
3057
92.7k
Result BinaryReader::ReadSections(const ReadSectionsOptions& options) {
3058
92.7k
  Result result = Result::Ok;
3059
92.7k
  Index section_index = 0;
3060
92.7k
  bool seen_section_code[static_cast<int>(BinarySection::Last) + 1] = {false};
3061
3062
13.2M
  for (; state_.offset < state_.size; ++section_index) {
3063
13.1M
    uint8_t section_code;
3064
13.1M
    Offset section_size;
3065
13.1M
    CHECK_RESULT(ReadU8(&section_code, "section code"));
3066
13.1M
    CHECK_RESULT(ReadOffset(&section_size, "section size"));
3067
13.1M
    ReadEndRestoreGuard guard(this);
3068
13.1M
    read_end_ = state_.offset + section_size;
3069
13.1M
    if (section_code >= kBinarySectionCount) {
3070
558k
      PrintError("invalid section code: %u", section_code);
3071
558k
      if (options.stop_on_first_error) {
3072
28
        return Result::Error;
3073
28
      }
3074
      // If we don't have to stop on first error, continue reading
3075
      // sections, because although we could not understand the
3076
      // current section, we can continue and correctly parse
3077
      // subsequent sections, so we can give back as much information
3078
      // as we can understand.
3079
558k
      result = Result::Error;
3080
558k
      state_.offset = read_end_;
3081
558k
      continue;
3082
558k
    }
3083
3084
12.5M
    BinarySection section = static_cast<BinarySection>(section_code);
3085
12.5M
    if (section != BinarySection::Custom) {
3086
116k
      if (seen_section_code[section_code]) {
3087
1.97k
        PrintError("multiple %s sections", GetSectionName(section));
3088
1.97k
        return Result::Error;
3089
1.97k
      }
3090
114k
      seen_section_code[section_code] = true;
3091
114k
    }
3092
3093
12.5M
    ERROR_UNLESS(read_end_ <= state_.size,
3094
12.5M
                 "invalid section size: extends past end");
3095
3096
12.5M
    ERROR_UNLESS(
3097
12.5M
        last_known_section_ == BinarySection::Invalid ||
3098
12.5M
            section == BinarySection::Custom ||
3099
12.5M
            GetSectionOrder(section) > GetSectionOrder(last_known_section_),
3100
12.5M
        "section %s out of order", GetSectionName(section));
3101
3102
12.5M
    ERROR_UNLESS(!did_read_names_section_ || section == BinarySection::Custom,
3103
12.5M
                 "%s section can not occur after Name section",
3104
12.5M
                 GetSectionName(section));
3105
3106
12.5M
    CALLBACK(BeginSection, section_index, section, section_size);
3107
3108
12.5M
    bool stop_on_first_error = options_.stop_on_first_error;
3109
12.5M
    Result section_result = Result::Error;
3110
12.5M
    switch (section) {
3111
12.4M
      case BinarySection::Custom:
3112
12.4M
        section_result = ReadCustomSection(section_index, section_size);
3113
12.4M
        if (options_.fail_on_custom_section_error) {
3114
785k
          result |= section_result;
3115
11.6M
        } else {
3116
11.6M
          stop_on_first_error = false;
3117
11.6M
        }
3118
12.4M
        break;
3119
7.79k
      case BinarySection::Type:
3120
7.79k
        section_result = ReadTypeSection(section_size);
3121
7.79k
        result |= section_result;
3122
7.79k
        break;
3123
4.67k
      case BinarySection::Import:
3124
4.67k
        section_result = ReadImportSection(section_size);
3125
4.67k
        result |= section_result;
3126
4.67k
        break;
3127
22.5k
      case BinarySection::Function:
3128
22.5k
        section_result = ReadFunctionSection(section_size);
3129
22.5k
        result |= section_result;
3130
22.5k
        break;
3131
3.47k
      case BinarySection::Table:
3132
3.47k
        section_result = ReadTableSection(section_size);
3133
3.47k
        result |= section_result;
3134
3.47k
        break;
3135
2.49k
      case BinarySection::Memory:
3136
2.49k
        section_result = ReadMemorySection(section_size);
3137
2.49k
        result |= section_result;
3138
2.49k
        break;
3139
4.92k
      case BinarySection::Global:
3140
4.92k
        section_result = ReadGlobalSection(section_size);
3141
4.92k
        result |= section_result;
3142
4.92k
        break;
3143
5.34k
      case BinarySection::Export:
3144
5.34k
        section_result = ReadExportSection(section_size);
3145
5.34k
        result |= section_result;
3146
5.34k
        break;
3147
1.22k
      case BinarySection::Start:
3148
1.22k
        section_result = ReadStartSection(section_size);
3149
1.22k
        result |= section_result;
3150
1.22k
        break;
3151
22.8k
      case BinarySection::Elem:
3152
22.8k
        section_result = ReadElemSection(section_size);
3153
22.8k
        result |= section_result;
3154
22.8k
        break;
3155
17.3k
      case BinarySection::Code:
3156
17.3k
        section_result = ReadCodeSection(section_size);
3157
17.3k
        result |= section_result;
3158
17.3k
        break;
3159
13.4k
      case BinarySection::Data:
3160
13.4k
        section_result = ReadDataSection(section_size);
3161
13.4k
        result |= section_result;
3162
13.4k
        break;
3163
737
      case BinarySection::Tag:
3164
737
        ERROR_UNLESS(options_.features.exceptions_enabled(),
3165
731
                     "invalid section code: %u",
3166
731
                     static_cast<unsigned int>(section));
3167
731
        section_result = ReadTagSection(section_size);
3168
731
        result |= section_result;
3169
731
        break;
3170
1.50k
      case BinarySection::DataCount:
3171
1.50k
        ERROR_UNLESS(options_.features.bulk_memory_enabled(),
3172
1.50k
                     "invalid section code: %u",
3173
1.50k
                     static_cast<unsigned int>(section));
3174
1.50k
        section_result = ReadDataCountSection(section_size);
3175
1.50k
        result |= section_result;
3176
1.50k
        break;
3177
0
      case BinarySection::Invalid:
3178
0
        WABT_UNREACHABLE;
3179
12.5M
    }
3180
3181
12.5M
    if (Succeeded(section_result) && state_.offset != read_end_) {
3182
156k
      PrintError("unfinished section (expected end: 0x%" PRIzx ")", read_end_);
3183
156k
      section_result = Result::Error;
3184
156k
      result |= section_result;
3185
156k
    }
3186
3187
12.5M
    if (Failed(section_result)) {
3188
11.0M
      if (stop_on_first_error) {
3189
11.3k
        return Result::Error;
3190
11.3k
      }
3191
3192
      // If we're continuing after failing to read this section, move the
3193
      // offset to the expected section end. This way we may be able to read
3194
      // further sections.
3195
10.9M
      state_.offset = read_end_;
3196
10.9M
    }
3197
3198
12.5M
    if (section != BinarySection::Custom) {
3199
99.0k
      last_known_section_ = section;
3200
99.0k
    }
3201
12.5M
  }
3202
3203
55.3k
  return result;
3204
92.7k
}
3205
3206
93.4k
Result BinaryReader::ReadModule(const ReadModuleOptions& options) {
3207
93.4k
  uint32_t magic = 0;
3208
93.4k
  CHECK_RESULT(ReadU32(&magic, "magic"));
3209
93.3k
  ERROR_UNLESS(magic == WABT_BINARY_MAGIC, "bad magic value");
3210
3211
92.8k
  uint16_t version = 0, layer = 0;
3212
92.8k
  CHECK_RESULT(ReadU16(&version, "version"));
3213
92.8k
  CHECK_RESULT(ReadU16(&layer, "layer"));
3214
3215
92.8k
  switch (layer) {
3216
92.8k
    case WABT_BINARY_LAYER_MODULE:
3217
92.8k
      ERROR_UNLESS(version == WABT_BINARY_VERSION,
3218
92.7k
                   "bad wasm file version: %#x (expected %#x)", version,
3219
92.7k
                   WABT_BINARY_VERSION);
3220
92.7k
      break;
3221
92.7k
    case WABT_BINARY_LAYER_COMPONENT:
3222
7
      ERROR("wasm components are not yet supported in this tool");
3223
0
      break;
3224
27
    default:
3225
27
      ERROR("unsupported wasm layer: %#x", layer);
3226
0
      break;
3227
92.8k
  }
3228
3229
92.7k
  CALLBACK(BeginModule, version);
3230
92.7k
  CHECK_RESULT(ReadSections(ReadSectionsOptions{options.stop_on_first_error}));
3231
  // This is checked in ReadCodeSection, but it must be checked at the end too,
3232
  // in case the code section was omitted.
3233
8.38k
  ERROR_UNLESS(num_function_signatures_ == num_function_bodies_,
3234
8.04k
               "function signature count != function body count");
3235
  // This is checked in ReadDataSection, but it must be checked at the end too,
3236
  // in case the data section was omitted.
3237
8.04k
  ERROR_IF(num_data_segments_ == 0 && data_count_ != kInvalidIndex &&
3238
8.04k
               data_count_ != 0,
3239
8.04k
           "Data section missing but DataCount non-zero");
3240
7.78k
  CALLBACK0(EndModule);
3241
3242
7.78k
  return Result::Ok;
3243
7.78k
}
3244
3245
}  // end anonymous namespace
3246
3247
Result ReadBinary(const void* data,
3248
                  size_t size,
3249
                  BinaryReaderDelegate* delegate,
3250
93.4k
                  const ReadBinaryOptions& options) {
3251
93.4k
  BinaryReader reader(data, size, delegate, options);
3252
93.4k
  return reader.ReadModule(
3253
93.4k
      BinaryReader::ReadModuleOptions{options.stop_on_first_error});
3254
93.4k
}
3255
3256
}  // namespace wabt