1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_WASM_MODULE_DECODER_H_
6 #define V8_WASM_MODULE_DECODER_H_
7
8 #include "src/globals.h"
9 #include "src/wasm/function-body-decoder.h"
10 #include "src/wasm/wasm-constants.h"
11 #include "src/wasm/wasm-features.h"
12 #include "src/wasm/wasm-module.h"
13 #include "src/wasm/wasm-result.h"
14
15 namespace v8 {
16 namespace internal {
17
18 class Counters;
19
20 namespace wasm {
21
22 struct ModuleEnv;
23
IsValidSectionCode(uint8_t byte)24 inline bool IsValidSectionCode(uint8_t byte) {
25 return kTypeSectionCode <= byte && byte <= kLastKnownModuleSection;
26 }
27
28 const char* SectionName(SectionCode code);
29
30 typedef Result<std::shared_ptr<WasmModule>> ModuleResult;
31 typedef Result<std::unique_ptr<WasmFunction>> FunctionResult;
32 typedef std::vector<std::pair<int, int>> FunctionOffsets;
33 typedef Result<FunctionOffsets> FunctionOffsetsResult;
34
35 struct AsmJsOffsetEntry {
36 int byte_offset;
37 int source_position_call;
38 int source_position_number_conversion;
39 };
40 typedef std::vector<std::vector<AsmJsOffsetEntry>> AsmJsOffsets;
41 typedef Result<AsmJsOffsets> AsmJsOffsetsResult;
42
43 struct LocalName {
44 int local_index;
45 WireBytesRef name;
LocalNameLocalName46 LocalName(int local_index, WireBytesRef name)
47 : local_index(local_index), name(name) {}
48 };
49 struct LocalNamesPerFunction {
50 int function_index;
51 int max_local_index = -1;
52 std::vector<LocalName> names;
LocalNamesPerFunctionLocalNamesPerFunction53 explicit LocalNamesPerFunction(int function_index)
54 : function_index(function_index) {}
55 };
56 struct LocalNames {
57 int max_function_index = -1;
58 std::vector<LocalNamesPerFunction> names;
59 };
60
61 // Decodes the bytes of a wasm module between {module_start} and {module_end}.
62 V8_EXPORT_PRIVATE ModuleResult DecodeWasmModule(
63 const WasmFeatures& enabled, const byte* module_start,
64 const byte* module_end, bool verify_functions, ModuleOrigin origin,
65 Counters* counters, AccountingAllocator* allocator);
66
67 // Exposed for testing. Decodes a single function signature, allocating it
68 // in the given zone. Returns {nullptr} upon failure.
69 V8_EXPORT_PRIVATE FunctionSig* DecodeWasmSignatureForTesting(
70 const WasmFeatures& enabled, Zone* zone, const byte* start,
71 const byte* end);
72
73 // Decodes the bytes of a wasm function between
74 // {function_start} and {function_end}.
75 V8_EXPORT_PRIVATE FunctionResult DecodeWasmFunctionForTesting(
76 const WasmFeatures& enabled, Zone* zone, const ModuleWireBytes& wire_bytes,
77 const WasmModule* module, const byte* function_start,
78 const byte* function_end, Counters* counters);
79
80 V8_EXPORT_PRIVATE WasmInitExpr DecodeWasmInitExprForTesting(
81 const WasmFeatures& enabled, const byte* start, const byte* end);
82
83 struct CustomSectionOffset {
84 WireBytesRef section;
85 WireBytesRef name;
86 WireBytesRef payload;
87 };
88
89 V8_EXPORT_PRIVATE std::vector<CustomSectionOffset> DecodeCustomSections(
90 const byte* start, const byte* end);
91
92 // Extracts the mapping from wasm byte offset to asm.js source position per
93 // function.
94 // Returns a vector of vectors with <byte_offset, source_position> entries, or
95 // failure if the wasm bytes are detected as invalid. Note that this validation
96 // is not complete.
97 AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* module_start,
98 const byte* module_end);
99
100 // Decode the function names from the name section.
101 // Returns the result as an unordered map. Only names with valid utf8 encoding
102 // are stored and conflicts are resolved by choosing the last name read.
103 void DecodeFunctionNames(const byte* module_start, const byte* module_end,
104 std::unordered_map<uint32_t, WireBytesRef>* names);
105
106 // Decode the local names assignment from the name section.
107 // Stores the result in the given {LocalNames} structure. The result will be
108 // empty if no name section is present. On encountering an error in the name
109 // section, returns all information decoded up to the first error.
110 void DecodeLocalNames(const byte* module_start, const byte* module_end,
111 LocalNames* result);
112
113 class ModuleDecoderImpl;
114
115 class ModuleDecoder {
116 public:
117 explicit ModuleDecoder(const WasmFeatures& enabled);
118 ~ModuleDecoder();
119
120 void StartDecoding(Counters* counters, AccountingAllocator* allocator,
121 ModuleOrigin origin = ModuleOrigin::kWasmOrigin);
122
123 void DecodeModuleHeader(Vector<const uint8_t> bytes, uint32_t offset);
124
125 void DecodeSection(SectionCode section_code, Vector<const uint8_t> bytes,
126 uint32_t offset, bool verify_functions = true);
127
128 bool CheckFunctionsCount(uint32_t functions_count, uint32_t offset);
129
130 void DecodeFunctionBody(uint32_t index, uint32_t size, uint32_t offset,
131 bool verify_functions = true);
132
133 ModuleResult FinishDecoding(bool verify_functions = true);
134
135 const std::shared_ptr<WasmModule>& shared_module() const;
module()136 WasmModule* module() const { return shared_module().get(); }
137
138 bool ok();
139
140 // Translates the unknown section that decoder is pointing to to an extended
141 // SectionCode if the unknown section is known to decoder. Currently this only
142 // handles the name section.
143 // The decoder is expected to point after the section lenght and just before
144 // the identifier string of the unknown section.
145 // If a SectionCode other than kUnknownSectionCode is returned, the decoder
146 // will point right after the identifier string. Otherwise, the position is
147 // undefined.
148 static SectionCode IdentifyUnknownSection(Decoder& decoder, const byte* end);
149
150 private:
151 const WasmFeatures enabled_features_;
152 std::unique_ptr<ModuleDecoderImpl> impl_;
153 };
154
155 } // namespace wasm
156 } // namespace internal
157 } // namespace v8
158
159 #endif // V8_WASM_MODULE_DECODER_H_
160