blob: 8e121c9d3063f2c56d2277d4a788061678d513d6 [file] [log] [blame]
// 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_
#include "src/common/globals.h"
#include "src/wasm/function-body-decoder.h"
#include "src/wasm/wasm-constants.h"
#include "src/wasm/wasm-features.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-result.h"
namespace v8 {
namespace internal {
class Counters;
namespace wasm {
struct CompilationEnv;
inline bool IsValidSectionCode(uint8_t byte) {
return kTypeSectionCode <= byte && byte <= kLastKnownModuleSection;
}
const char* SectionName(SectionCode code);
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>;
struct AsmJsOffsetEntry {
int byte_offset;
int source_position_call;
int source_position_number_conversion;
};
using AsmJsOffsets = std::vector<std::vector<AsmJsOffsetEntry>>;
using AsmJsOffsetsResult = Result<AsmJsOffsets>;
struct LocalName {
int local_index;
WireBytesRef name;
LocalName(int local_index, WireBytesRef name)
: local_index(local_index), name(name) {}
};
struct LocalNamesPerFunction {
int function_index;
int max_local_index = -1;
std::vector<LocalName> names;
explicit LocalNamesPerFunction(int function_index)
: function_index(function_index) {}
};
struct LocalNames {
int max_function_index = -1;
std::vector<LocalNamesPerFunction> names;
};
// Decodes the bytes of a wasm module between {module_start} and {module_end}.
V8_EXPORT_PRIVATE ModuleResult DecodeWasmModule(
const WasmFeatures& enabled, const byte* module_start,
const byte* module_end, bool verify_functions, ModuleOrigin origin,
Counters* counters, AccountingAllocator* allocator);
// Exposed for testing. Decodes a single function signature, allocating it
// in the given zone. Returns {nullptr} upon failure.
V8_EXPORT_PRIVATE FunctionSig* DecodeWasmSignatureForTesting(
const WasmFeatures& enabled, Zone* zone, const byte* start,
const byte* end);
// Decodes the bytes of a wasm function between
// {function_start} and {function_end}.
V8_EXPORT_PRIVATE FunctionResult DecodeWasmFunctionForTesting(
const WasmFeatures& enabled, Zone* zone, const ModuleWireBytes& wire_bytes,
const WasmModule* module, const byte* function_start,
const byte* function_end, Counters* counters);
V8_EXPORT_PRIVATE WasmInitExpr DecodeWasmInitExprForTesting(
const WasmFeatures& enabled, const byte* start, const byte* end);
struct CustomSectionOffset {
WireBytesRef section;
WireBytesRef name;
WireBytesRef payload;
};
V8_EXPORT_PRIVATE std::vector<CustomSectionOffset> DecodeCustomSections(
const byte* start, const byte* end);
// Extracts the mapping from wasm byte offset to asm.js source position per
// function.
// Returns a vector of vectors with <byte_offset, source_position> entries, or
// failure if the wasm bytes are detected as invalid. Note that this validation
// is not complete.
AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* module_start,
const byte* module_end);
// Decode the function names from the name section.
// 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.
void DecodeFunctionNames(const byte* module_start, const byte* module_end,
std::unordered_map<uint32_t, WireBytesRef>* names);
// Decode the local names assignment from the name section.
// Stores the result in the given {LocalNames} structure. 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.
void DecodeLocalNames(const byte* module_start, const byte* module_end,
LocalNames* result);
class ModuleDecoderImpl;
class ModuleDecoder {
public:
explicit ModuleDecoder(const WasmFeatures& enabled);
~ModuleDecoder();
void StartDecoding(Counters* counters, AccountingAllocator* allocator,
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);
const std::shared_ptr<WasmModule>& shared_module() const;
WasmModule* module() const { return shared_module().get(); }
bool ok();
// Translates the unknown section that decoder is pointing to to an extended
// SectionCode if the unknown section is known to decoder.
// The decoder is expected to point after the section length and just before
// the identifier string of the unknown section.
// If a SectionCode other than kUnknownSectionCode is returned, the decoder
// will point right after the identifier string. Otherwise, the position is
// undefined.
static SectionCode IdentifyUnknownSection(Decoder* decoder, const byte* end);
private:
const WasmFeatures enabled_features_;
std::unique_ptr<ModuleDecoderImpl> impl_;
};
} // namespace wasm
} // namespace internal
} // namespace v8
#endif // V8_WASM_MODULE_DECODER_H_