module-decoder.h 7.73 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_WASM_MODULE_DECODER_H_
#define V8_WASM_MODULE_DECODER_H_

8 9
#include <memory>

10
#include "src/common/globals.h"
11
#include "src/wasm/function-body-decoder.h"
12
#include "src/wasm/wasm-constants.h"
13
#include "src/wasm/wasm-features.h"
14
#include "src/wasm/wasm-module.h"
15
#include "src/wasm/wasm-result.h"
16 17 18

namespace v8 {
namespace internal {
19 20 21

class Counters;

22
namespace wasm {
23

24
struct CompilationEnv;
25

26
inline bool IsValidSectionCode(uint8_t byte) {
27
  return kTypeSectionCode <= byte && byte <= kLastKnownModuleSection;
28 29
}

30
const char* SectionName(SectionCode code);
31

32 33 34 35
using ModuleResult = Result<std::shared_ptr<WasmModule>>;
using FunctionResult = Result<std::unique_ptr<WasmFunction>>;
using FunctionOffsets = std::vector<std::pair<int, int>>;
using FunctionOffsetsResult = Result<FunctionOffsets>;
36

37 38 39 40 41
struct AsmJsOffsetEntry {
  int byte_offset;
  int source_position_call;
  int source_position_number_conversion;
};
42
struct AsmJsOffsetFunctionEntries {
43 44
  int start_offset;
  int end_offset;
45 46 47 48 49
  std::vector<AsmJsOffsetEntry> entries;
};
struct AsmJsOffsets {
  std::vector<AsmJsOffsetFunctionEntries> functions;
};
50
using AsmJsOffsetsResult = Result<AsmJsOffsets>;
51

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
class LocalName {
 public:
  LocalName(int index, WireBytesRef name) : index_(index), name_(name) {}

  int index() const { return index_; }
  WireBytesRef name() const { return name_; }

  struct IndexLess {
    bool operator()(const LocalName& a, const LocalName& b) const {
      return a.index() < b.index();
    }
  };

 private:
  int index_;
  WireBytesRef name_;
68
};
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

class LocalNamesPerFunction {
 public:
  // For performance reasons, {LocalNamesPerFunction} should not be copied.
  MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(LocalNamesPerFunction);

  LocalNamesPerFunction(int function_index, std::vector<LocalName> names)
      : function_index_(function_index), names_(std::move(names)) {
    DCHECK(
        std::is_sorted(names_.begin(), names_.end(), LocalName::IndexLess{}));
  }

  int function_index() const { return function_index_; }

  WireBytesRef GetName(int local_index) {
    auto it =
        std::lower_bound(names_.begin(), names_.end(),
                         LocalName{local_index, {}}, LocalName::IndexLess{});
    if (it == names_.end()) return {};
    if (it->index() != local_index) return {};
    return it->name();
  }

  struct FunctionIndexLess {
    bool operator()(const LocalNamesPerFunction& a,
                    const LocalNamesPerFunction& b) const {
      return a.function_index() < b.function_index();
    }
  };

 private:
  int function_index_;
  std::vector<LocalName> names_;
102
};
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

class LocalNames {
 public:
  // For performance reasons, {LocalNames} should not be copied.
  MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(LocalNames);

  explicit LocalNames(std::vector<LocalNamesPerFunction> functions)
      : functions_(std::move(functions)) {
    DCHECK(std::is_sorted(functions_.begin(), functions_.end(),
                          LocalNamesPerFunction::FunctionIndexLess{}));
  }

  WireBytesRef GetName(int function_index, int local_index) {
    auto it = std::lower_bound(functions_.begin(), functions_.end(),
                               LocalNamesPerFunction{function_index, {}},
                               LocalNamesPerFunction::FunctionIndexLess{});
    if (it == functions_.end()) return {};
    if (it->function_index() != function_index) return {};
    return it->GetName(local_index);
  }

 private:
  std::vector<LocalNamesPerFunction> functions_;
126 127
};

128
// Decodes the bytes of a wasm module between {module_start} and {module_end}.
129
V8_EXPORT_PRIVATE ModuleResult DecodeWasmModule(
130 131 132
    const WasmFeatures& enabled, const byte* module_start,
    const byte* module_end, bool verify_functions, ModuleOrigin origin,
    Counters* counters, AccountingAllocator* allocator);
133 134 135

// Exposed for testing. Decodes a single function signature, allocating it
// in the given zone. Returns {nullptr} upon failure.
136
V8_EXPORT_PRIVATE const FunctionSig* DecodeWasmSignatureForTesting(
137 138
    const WasmFeatures& enabled, Zone* zone, const byte* start,
    const byte* end);
139

140
// Decodes the bytes of a wasm function between
141
// {function_start} and {function_end}.
142
V8_EXPORT_PRIVATE FunctionResult DecodeWasmFunctionForTesting(
143 144 145
    const WasmFeatures& enabled, Zone* zone, const ModuleWireBytes& wire_bytes,
    const WasmModule* module, const byte* function_start,
    const byte* function_end, Counters* counters);
146

147 148
V8_EXPORT_PRIVATE WasmInitExpr DecodeWasmInitExprForTesting(
    const WasmFeatures& enabled, const byte* start, const byte* end);
149

150
struct CustomSectionOffset {
151 152 153
  WireBytesRef section;
  WireBytesRef name;
  WireBytesRef payload;
154 155 156 157 158
};

V8_EXPORT_PRIVATE std::vector<CustomSectionOffset> DecodeCustomSections(
    const byte* start, const byte* end);

159 160
// Extracts the mapping from wasm byte offset to asm.js source position per
// function.
161
AsmJsOffsetsResult DecodeAsmJsOffsets(Vector<const uint8_t> encoded_offsets);
162

163 164 165 166
// Decode the function names from the name section and also look at export
// table. Returns the result as an unordered map. Only names with valid utf8
// encoding are stored and conflicts are resolved by choosing the last name
// read.
167
void DecodeFunctionNames(const byte* module_start, const byte* module_end,
168 169
                         std::unordered_map<uint32_t, WireBytesRef>* names,
                         const Vector<const WasmExport> export_table);
170

171 172 173 174
// Decode the global or memory names from import table and export table. Returns
// the result as an unordered map.
void GenerateNamesFromImportsAndExports(
    ImportExportKindCode kind, const Vector<const WasmImport> import_table,
175 176 177
    const Vector<const WasmExport> export_table,
    std::unordered_map<uint32_t, std::pair<WireBytesRef, WireBytesRef>>* names);

178
// Decode the local names assignment from the name section.
179 180 181 182
// The result will be empty if no name section is present. On encountering an
// error in the name section, returns all information decoded up to the first
// error.
LocalNames DecodeLocalNames(Vector<const uint8_t> module_bytes);
183

184 185 186 187
class ModuleDecoderImpl;

class ModuleDecoder {
 public:
188
  explicit ModuleDecoder(const WasmFeatures& enabled);
189 190
  ~ModuleDecoder();

191
  void StartDecoding(Counters* counters, AccountingAllocator* allocator,
192 193 194 195 196 197 198 199 200 201 202 203 204 205
                     ModuleOrigin origin = ModuleOrigin::kWasmOrigin);

  void DecodeModuleHeader(Vector<const uint8_t> bytes, uint32_t offset);

  void DecodeSection(SectionCode section_code, Vector<const uint8_t> bytes,
                     uint32_t offset, bool verify_functions = true);

  bool CheckFunctionsCount(uint32_t functions_count, uint32_t offset);

  void DecodeFunctionBody(uint32_t index, uint32_t size, uint32_t offset,
                          bool verify_functions = true);

  ModuleResult FinishDecoding(bool verify_functions = true);

206 207
  void set_code_section(uint32_t offset, uint32_t size);

208 209
  const std::shared_ptr<WasmModule>& shared_module() const;
  WasmModule* module() const { return shared_module().get(); }
210 211 212

  bool ok();

213
  // Translates the unknown section that decoder is pointing to to an extended
214
  // SectionCode if the unknown section is known to decoder.
215
  // The decoder is expected to point after the section length and just before
216
  // the identifier string of the unknown section.
217 218 219 220
  // The return value is the number of bytes that were consumed.
  static size_t IdentifyUnknownSection(ModuleDecoder* decoder,
                                       Vector<const uint8_t> bytes,
                                       uint32_t offset, SectionCode* result);
221

222
 private:
223
  const WasmFeatures enabled_features_;
224 225 226
  std::unique_ptr<ModuleDecoderImpl> impl_;
};

227 228 229 230 231
}  // namespace wasm
}  // namespace internal
}  // namespace v8

#endif  // V8_WASM_MODULE_DECODER_H_