Commit 37cdcdf4 authored by Philip Pfaffe's avatar Philip Pfaffe Committed by Commit Bot

Support .external_debug_info symbol references

Wasm modules generated by emscripten today have two ways to point to
debug symbol files, the source mapping url and external debug info
custom sections. To support both, this CL extends CDP to appropriately
report the symbol type and location.

Bug: chromium:1064248
Change-Id: I9076034f6d73901d8a9c5cfd7c2988fb30bb14c1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2116208Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Philip Pfaffe <pfaffe@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67571}
parent 0c9a0072
......@@ -525,6 +525,18 @@ domain Debugger
JavaScript
WebAssembly
# Debug symbols available for a wasm script.
type DebugSymbols extends object
properties
# Type of the debug symbols.
enum type
None
SourceMap
EmbeddedDWARF
ExternalDWARF
# URL of the external symbol source.
optional string externalURL
# Fired when virtual machine fails to parse the script.
event scriptFailedToParse
parameters
......@@ -599,6 +611,8 @@ domain Debugger
experimental optional integer codeOffset
# The language of the script.
experimental optional Debugger.ScriptLanguage scriptLanguage
# If the scriptLanguage is WebASsembly, the source of debug symbols for the module.
experimental optional Debugger.DebugSymbols debugSymbols
experimental domain HeapProfiler
depends on Runtime
......
......@@ -9729,6 +9729,37 @@ debug::WasmScript* debug::WasmScript::Cast(debug::Script* script) {
return static_cast<WasmScript*>(script);
}
debug::WasmScript::DebugSymbolsType debug::WasmScript::GetDebugSymbolType()
const {
i::Handle<i::Script> script = Utils::OpenHandle(this);
DCHECK_EQ(i::Script::TYPE_WASM, script->type());
switch (script->wasm_native_module()->module()->debug_symbols.type) {
case i::wasm::WasmDebugSymbols::Type::None:
return debug::WasmScript::DebugSymbolsType::None;
case i::wasm::WasmDebugSymbols::Type::EmbeddedDWARF:
return debug::WasmScript::DebugSymbolsType::EmbeddedDWARF;
case i::wasm::WasmDebugSymbols::Type::ExternalDWARF:
return debug::WasmScript::DebugSymbolsType::ExternalDWARF;
case i::wasm::WasmDebugSymbols::Type::SourceMap:
return debug::WasmScript::DebugSymbolsType::SourceMap;
}
}
MemorySpan<const char> debug::WasmScript::ExternalSymbolsURL() const {
i::Handle<i::Script> script = Utils::OpenHandle(this);
DCHECK_EQ(i::Script::TYPE_WASM, script->type());
const i::wasm::WasmDebugSymbols& symbols =
script->wasm_native_module()->module()->debug_symbols;
if (symbols.external_url.is_empty()) return {};
internal::wasm::ModuleWireBytes wire_bytes(
script->wasm_native_module()->wire_bytes());
i::wasm::WasmName external_url =
wire_bytes.GetNameOrNull(symbols.external_url);
return {external_url.data(), external_url.size()};
}
int debug::WasmScript::NumFunctions() const {
i::DisallowHeapAllocation no_gc;
i::Handle<i::Script> script = Utils::OpenHandle(this);
......
......@@ -173,6 +173,9 @@ class WasmScript : public Script {
public:
static WasmScript* Cast(Script* script);
enum class DebugSymbolsType { None, SourceMap, EmbeddedDWARF, ExternalDWARF };
DebugSymbolsType GetDebugSymbolType() const;
MemorySpan<const char> ExternalSymbolsURL() const;
int NumFunctions() const;
int NumImportedFunctions() const;
MemorySpan<const uint8_t> Bytecode() const;
......
......@@ -1471,6 +1471,39 @@ static String16 getScriptLanguage(const V8DebuggerScript& script) {
}
}
static const char* getDebugSymbolTypeName(
v8::debug::WasmScript::DebugSymbolsType type) {
switch (type) {
case v8::debug::WasmScript::DebugSymbolsType::None:
return v8_inspector::protocol::Debugger::DebugSymbols::TypeEnum::None;
case v8::debug::WasmScript::DebugSymbolsType::SourceMap:
return v8_inspector::protocol::Debugger::DebugSymbols::TypeEnum::
SourceMap;
case v8::debug::WasmScript::DebugSymbolsType::EmbeddedDWARF:
return v8_inspector::protocol::Debugger::DebugSymbols::TypeEnum::
EmbeddedDWARF;
case v8::debug::WasmScript::DebugSymbolsType::ExternalDWARF:
return v8_inspector::protocol::Debugger::DebugSymbols::TypeEnum::
ExternalDWARF;
}
}
static std::unique_ptr<protocol::Debugger::DebugSymbols> getDebugSymbols(
const V8DebuggerScript& script) {
v8::debug::WasmScript::DebugSymbolsType type;
if (!script.getDebugSymbolsType().To(&type)) return {};
std::unique_ptr<protocol::Debugger::DebugSymbols> debugSymbols =
v8_inspector::protocol::Debugger::DebugSymbols::create()
.setType(getDebugSymbolTypeName(type))
.build();
String16 externalUrl;
if (script.getExternalDebugSymbolsURL().To(&externalUrl)) {
debugSymbols->setExternalURL(externalUrl);
}
return debugSymbols;
}
void V8DebuggerAgentImpl::didParseSource(
std::unique_ptr<V8DebuggerScript> script, bool success) {
v8::HandleScope handles(m_isolate);
......@@ -1506,6 +1539,8 @@ void V8DebuggerAgentImpl::didParseSource(
script->getLanguage() == V8DebuggerScript::Language::JavaScript
? Maybe<int>()
: script->codeOffset();
std::unique_ptr<protocol::Debugger::DebugSymbols> debugSymbols =
getDebugSymbols(*script);
m_scripts[scriptId] = std::move(script);
// Release the strong reference to get notified when debugger is the only
......@@ -1553,8 +1588,8 @@ void V8DebuggerAgentImpl::didParseSource(
scriptId, scriptURL, 0, 0, 0, 0, contextId, scriptRef->hash(),
std::move(executionContextAuxDataParam), isLiveEditParam,
std::move(sourceMapURLParam), hasSourceURLParam, isModuleParam, 0,
std::move(stackTrace), std::move(codeOffset),
std::move(scriptLanguage));
std::move(stackTrace), std::move(codeOffset), std::move(scriptLanguage),
std::move(debugSymbols));
} else {
m_frontend.scriptParsed(
scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(),
......@@ -1562,7 +1597,8 @@ void V8DebuggerAgentImpl::didParseSource(
scriptRef->hash(), std::move(executionContextAuxDataParam),
isLiveEditParam, std::move(sourceMapURLParam), hasSourceURLParam,
isModuleParam, scriptRef->length(), std::move(stackTrace),
std::move(codeOffset), std::move(scriptLanguage));
std::move(codeOffset), std::move(scriptLanguage),
std::move(debugSymbols));
}
std::vector<protocol::DictionaryValue*> potentialBreakpoints;
......
......@@ -122,6 +122,21 @@ class ActualScript : public V8DebuggerScript {
return v8::Just(v8::debug::WasmScript::Cast(*script)->Bytecode());
}
Language getLanguage() const override { return m_language; }
v8::Maybe<v8::debug::WasmScript::DebugSymbolsType> getDebugSymbolsType()
const override {
auto script = this->script();
if (!script->IsWasm())
return v8::Nothing<v8::debug::WasmScript::DebugSymbolsType>();
return v8::Just(v8::debug::WasmScript::Cast(*script)->GetDebugSymbolType());
}
v8::Maybe<String16> getExternalDebugSymbolsURL() const override {
auto script = this->script();
if (!script->IsWasm()) return v8::Nothing<String16>();
v8::MemorySpan<const char> external_url =
v8::debug::WasmScript::Cast(*script)->ExternalSymbolsURL();
if (external_url.size() == 0) return v8::Nothing<String16>();
return v8::Just(String16(external_url.data(), external_url.size()));
}
int startLine() const override { return m_startLine; }
int startColumn() const override { return m_startColumn; }
int endLine() const override { return m_endLine; }
......
......@@ -61,6 +61,9 @@ class V8DebuggerScript {
virtual String16 source(size_t pos, size_t len = UINT_MAX) const = 0;
virtual v8::Maybe<v8::MemorySpan<const uint8_t>> wasmBytecode() const = 0;
virtual Language getLanguage() const = 0;
virtual v8::Maybe<String16> getExternalDebugSymbolsURL() const = 0;
virtual v8::Maybe<v8::debug::WasmScript::DebugSymbolsType>
getDebugSymbolsType() const = 0;
virtual const String16& hash() const = 0;
virtual int startLine() const = 0;
virtual int startColumn() const = 0;
......
......@@ -1684,10 +1684,13 @@ void AsyncCompileJob::FinishCompile(bool is_after_cache_hit) {
DCHECK(!isolate_->context().is_null());
// Finish the wasm script now and make it public to the debugger.
Handle<Script> script(module_object_->script(), isolate_);
const WasmModule* module = module_object_->module();
if (script->type() == Script::TYPE_WASM &&
module_object_->module()->source_map_url.size() != 0) {
module->debug_symbols.type == WasmDebugSymbols::Type::SourceMap &&
!module->debug_symbols.external_url.is_empty()) {
ModuleWireBytes wire_bytes(module_object_->native_module()->wire_bytes());
MaybeHandle<String> src_map_str = isolate_->factory()->NewStringFromUtf8(
CStrVector(module_object_->module()->source_map_url.c_str()),
wire_bytes.GetNameOrNull(module->debug_symbols.external_url),
AllocationType::kOld);
script->set_source_mapping_url(*src_map_str.ToHandleChecked());
}
......@@ -1702,11 +1705,10 @@ void AsyncCompileJob::FinishCompile(bool is_after_cache_hit) {
Handle<FixedArray> export_wrappers;
if (is_after_cache_hit) {
// TODO(thibaudm): Look into sharing wrappers.
CompileJsToWasmWrappers(isolate_, module_object_->module(),
&export_wrappers);
CompileJsToWasmWrappers(isolate_, module, &export_wrappers);
} else {
compilation_state->FinalizeJSToWasmWrappers(
isolate_, module_object_->module(), &export_wrappers);
compilation_state->FinalizeJSToWasmWrappers(isolate_, module,
&export_wrappers);
}
module_object_->set_export_wrappers(*export_wrappers);
}
......
......@@ -33,6 +33,7 @@ constexpr char kNameString[] = "name";
constexpr char kSourceMappingURLString[] = "sourceMappingURL";
constexpr char kCompilationHintsString[] = "compilationHints";
constexpr char kDebugInfoString[] = ".debug_info";
constexpr char kExternalDebugInfoString[] = ".external_debug_info";
template <size_t N>
constexpr size_t num_chars(const char (&)[N]) {
......@@ -93,6 +94,8 @@ const char* SectionName(SectionCode code) {
return kSourceMappingURLString;
case kDebugInfoSectionCode:
return kDebugInfoString;
case kExternalDebugInfoSectionCode:
return kExternalDebugInfoString;
case kCompilationHintsSectionCode:
return kCompilationHintsString;
default:
......@@ -182,6 +185,11 @@ SectionCode IdentifyUnknownSectionInternal(Decoder* decoder) {
strncmp(reinterpret_cast<const char*>(section_name_start),
kDebugInfoString, num_chars(kDebugInfoString)) == 0) {
return kDebugInfoSectionCode;
} else if (string.length() == num_chars(kExternalDebugInfoString) &&
strncmp(reinterpret_cast<const char*>(section_name_start),
kExternalDebugInfoString,
num_chars(kExternalDebugInfoString)) == 0) {
return kExternalDebugInfoSectionCode;
}
return kUnknownSectionCode;
}
......@@ -452,6 +460,9 @@ class ModuleDecoderImpl : public Decoder {
// .debug_info is a custom section containing core DWARF information
// if produced by compiler. Its presence likely means that Wasm was
// built in a debug mode.
case kExternalDebugInfoSectionCode:
// .external_debug_info is a custom section containing a reference to an
// external symbol file.
case kCompilationHintsSectionCode:
// TODO(frgossen): report out of place compilation hints section as a
// warning.
......@@ -508,11 +519,14 @@ class ModuleDecoderImpl : public Decoder {
break;
case kDebugInfoSectionCode:
// If there is an explicit source map, prefer it over DWARF info.
if (!has_seen_unordered_section(kSourceMappingURLSectionCode)) {
module_->source_map_url.assign("wasm://dwarf");
if (module_->debug_symbols.type == WasmDebugSymbols::Type::None) {
module_->debug_symbols = {WasmDebugSymbols::Type::EmbeddedDWARF, {}};
}
consume_bytes(static_cast<uint32_t>(end_ - start_), ".debug_info");
break;
case kExternalDebugInfoSectionCode:
DecodeExternalDebugInfoSection();
break;
case kCompilationHintsSectionCode:
if (enabled_features_.has_compilation_hints()) {
DecodeCompilationHintsSection();
......@@ -1063,12 +1077,22 @@ class ModuleDecoderImpl : public Decoder {
Decoder inner(start_, pc_, end_, buffer_offset_);
WireBytesRef url = wasm::consume_string(&inner, true, "module name");
if (inner.ok() &&
!has_seen_unordered_section(kSourceMappingURLSectionCode)) {
const byte* url_start =
inner.start() + inner.GetBufferRelativeOffset(url.offset());
module_->source_map_url.assign(reinterpret_cast<const char*>(url_start),
url.length());
set_seen_unordered_section(kSourceMappingURLSectionCode);
module_->debug_symbols.type != WasmDebugSymbols::Type::SourceMap) {
module_->debug_symbols = {WasmDebugSymbols::Type::SourceMap, url};
}
set_seen_unordered_section(kSourceMappingURLSectionCode);
consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
}
void DecodeExternalDebugInfoSection() {
Decoder inner(start_, pc_, end_, buffer_offset_);
WireBytesRef url =
wasm::consume_string(&inner, true, "external symbol file");
// If there is an explicit source map, prefer it over DWARF info.
if (inner.ok() &&
module_->debug_symbols.type != WasmDebugSymbols::Type::SourceMap) {
module_->debug_symbols = {WasmDebugSymbols::Type::ExternalDWARF, url};
set_seen_unordered_section(kExternalDebugInfoSectionCode);
}
consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
}
......@@ -2157,8 +2181,8 @@ FunctionResult DecodeWasmFunctionForTesting(
const byte* function_end, Counters* counters) {
size_t size = function_end - function_start;
CHECK_LE(function_start, function_end);
auto size_histogram = SELECT_WASM_COUNTER(counters, module->origin, wasm,
function_size_bytes);
auto size_histogram =
SELECT_WASM_COUNTER(counters, module->origin, wasm, function_size_bytes);
// TODO(bradnelson): Improve histogram handling of ptrdiff_t.
size_histogram->AddSample(static_cast<int>(size));
if (size > kV8MaxWasmFunctionSize) {
......
......@@ -221,14 +221,19 @@ void WasmCode::LogCode(Isolate* isolate) const {
VectorOf(native_module()->module()->export_table));
WasmName name = wire_bytes.GetNameOrNull(name_ref);
const std::string& source_map_url = native_module()->module()->source_map_url;
const WasmDebugSymbols& debug_symbols =
native_module()->module()->debug_symbols;
auto load_wasm_source_map = isolate->wasm_load_source_map_callback();
auto source_map = native_module()->GetWasmSourceMap();
if (!source_map && !source_map_url.empty() && load_wasm_source_map) {
if (!source_map && debug_symbols.type == WasmDebugSymbols::Type::SourceMap &&
!debug_symbols.external_url.is_empty() && load_wasm_source_map) {
WasmName external_url =
wire_bytes.GetNameOrNull(debug_symbols.external_url);
std::string external_url_string(external_url.data(), external_url.size());
HandleScope scope(isolate);
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
Local<v8::String> source_map_str =
load_wasm_source_map(v8_isolate, source_map_url.c_str());
load_wasm_source_map(v8_isolate, external_url_string.c_str());
native_module()->SetWasmSourceMap(
std::make_unique<WasmModuleSourceMap>(v8_isolate, source_map_str));
}
......
......@@ -87,10 +87,11 @@ enum SectionCode : int8_t {
// The following sections are custom sections, and are identified using a
// string rather than an integer. Their enumeration values are not guaranteed
// to be consistent.
kNameSectionCode, // Name section (encoded as a string)
kSourceMappingURLSectionCode, // Source Map URL section
kDebugInfoSectionCode, // DWARF section .debug_info
kCompilationHintsSectionCode, // Compilation hints section
kNameSectionCode, // Name section (encoded as a string)
kSourceMappingURLSectionCode, // Source Map URL section
kDebugInfoSectionCode, // DWARF section .debug_info
kExternalDebugInfoSectionCode, // Section encoding the external symbol path
kCompilationHintsSectionCode, // Compilation hints section
// Helper values
kFirstSectionInModule = kTypeSectionCode,
......
......@@ -707,10 +707,14 @@ Handle<Script> CreateWasmScript(Isolate* isolate,
}
script->set_source_url(*url_str.ToHandleChecked());
auto source_map_url = VectorOf(module->source_map_url);
if (!source_map_url.empty()) {
const WasmDebugSymbols& debug_symbols =
native_module->module()->debug_symbols;
if (debug_symbols.type == WasmDebugSymbols::Type::SourceMap &&
!debug_symbols.external_url.is_empty()) {
Vector<const char> external_url =
ModuleWireBytes(wire_bytes).GetNameOrNull(debug_symbols.external_url);
MaybeHandle<String> src_map_str = isolate->factory()->NewStringFromUtf8(
source_map_url, AllocationType::kOld);
external_url, AllocationType::kOld);
script->set_source_mapping_url(*src_map_str.ToHandleChecked());
}
......
......@@ -259,6 +259,12 @@ struct TypeDefinition {
};
};
struct V8_EXPORT_PRIVATE WasmDebugSymbols {
enum class Type { None, SourceMap, EmbeddedDWARF, ExternalDWARF };
Type type = Type::None;
WireBytesRef external_url;
};
// Static representation of a module.
struct V8_EXPORT_PRIVATE WasmModule {
std::unique_ptr<Zone> signature_zone;
......@@ -333,7 +339,7 @@ struct V8_EXPORT_PRIVATE WasmModule {
ModuleOrigin origin = kWasmOrigin; // origin of the module
LazilyGeneratedNames lazily_generated_names;
std::string source_map_url;
WasmDebugSymbols debug_symbols;
// Asm.js source position information. Only available for modules compiled
// from asm.js.
......
......@@ -52,12 +52,25 @@ InspectorTest.log(
// Sample .debug_info section.
// Content doesn't matter, as we don't try to parse it in V8,
// but should be non-empty to check that we're skipping it correctly.
const dwarfSection = { name: '.debug_info', value: [1, 2, 3, 4, 5] };
const embeddedDWARFSection = {
name: '.debug_info',
value: [1, 2, 3, 4, 5]
};
// Sample external_debug_info section set to "abc".
const externalDWARFSection = {
name: '.external_debug_info',
value: [3, 97, 98, 99]
};
// Sample sourceMappingURL section set to "abc".
const sourceMapSection = { name: 'sourceMappingURL', value: [3, 97, 98, 99] };
const sourceMapSection = {
name: 'sourceMappingURL',
value: [3, 97, 98, 99]
};
sessions[0].Protocol.Runtime
sessions[0]
.Protocol.Runtime
.evaluate({
'expression': `//# sourceURL=v8://test/runTestRunction
......@@ -67,24 +80,41 @@ sessions[0].Protocol.Runtime
// shared script for identical modules
testFunction([${createModule()}]);
// DWARF
testFunction([${createModule(dwarfSection)}]);
// External DWARF
testFunction([${createModule(externalDWARFSection)}]);
// Embedded DWARF
testFunction([${createModule(embeddedDWARFSection)}]);
// Source map
testFunction([${createModule(sourceMapSection)}]);
// DWARF + source map
testFunction([${createModule(dwarfSection, sourceMapSection)}]);
// SourceMap + External DWARF
testFunction([${createModule(sourceMapSection, externalDWARFSection)}]);
// External DWARF + SourceMap (different order)
testFunction([${createModule(externalDWARFSection, sourceMapSection)}]);
// Embedded DWARF + External DWARF
testFunction([${
createModule(embeddedDWARFSection, externalDWARFSection)}]);
// External + Embedded DWARF (different order)
testFunction([${
createModule(externalDWARFSection, embeddedDWARFSection)}]);
// Embedded DWARF + source map
testFunction([${createModule(embeddedDWARFSection, sourceMapSection)}]);
// Source map + DWARF (different order)
testFunction([${createModule(sourceMapSection, dwarfSection)}]);
// Source map + Embedded DWARF (different order)
testFunction([${createModule(sourceMapSection, embeddedDWARFSection)}]);
`
})
.then(() => (
// At this point all scripts were parsed.
// Stop tracking and wait for script sources in each session.
Promise.all(sessions.map(session => session.getScripts()))
))
.then(
() => (
// At this point all scripts were parsed.
// Stop tracking and wait for script sources in each session.
Promise.all(sessions.map(session => session.getScripts()))))
.catch(err => {
InspectorTest.log(err.stack);
})
......@@ -97,12 +127,21 @@ function trackScripts(debuggerParams) {
Protocol.Debugger.enable(debuggerParams);
Protocol.Debugger.onScriptParsed(handleScriptParsed);
async function loadScript(
{url, scriptId, sourceMapURL, startColumn, endColumn, codeOffset}) {
async function loadScript({
url,
scriptId,
sourceMapURL,
startColumn,
endColumn,
codeOffset,
debugSymbols
}) {
let stableId = nextStableId(scriptId);
InspectorTest.log(`Session #${sessionId}: Script #${
scripts.length} parsed. URL: ${url}. Script ID: ${stableId}, Source map URL: ${
sourceMapURL}, module begin: ${startColumn}, module end: ${endColumn}, code offset: ${codeOffset}`);
scripts.length} parsed. URL: ${url}. Script ID: ${
stableId}, Source map URL: ${sourceMapURL}, debug symbols: ${
debugSymbols.type}:${debugSymbols.externalURL}. module begin: ${
startColumn}, module end: ${endColumn}, code offset: ${codeOffset}`);
let {result: {scriptSource, bytecode}} =
await Protocol.Debugger.getScriptSource({scriptId});
if (bytecode) {
......@@ -114,10 +153,17 @@ function trackScripts(debuggerParams) {
bytecode = InspectorTest.decodeBase64(bytecode);
// Check that it can be parsed back to a WebAssembly module.
let module = new WebAssembly.Module(bytecode);
scriptSource = `
scriptSource =
`
Raw: ${Array.from(bytecode, b => ('0' + b.toString(16)).slice(-2)).join(' ')}
Imports: [${WebAssembly.Module.imports(module).map(i => `${i.name}: ${i.kind} from "${i.module}"`).join(', ')}]
Exports: [${WebAssembly.Module.exports(module).map(e => `${e.name}: ${e.kind}`).join(', ')}]
Imports: [${
WebAssembly.Module.imports(module)
.map(i => `${i.name}: ${i.kind} from "${i.module}"`)
.join(', ')}]
Exports: [${
WebAssembly.Module.exports(module)
.map(e => `${e.name}: ${e.kind}`)
.join(', ')}]
`.trim();
}
InspectorTest.log(`Session #${sessionId}: Source for ${url}:`);
......
......@@ -2428,26 +2428,40 @@ TEST_F(WasmModuleCustomSectionTest, TwoKnownTwoUnknownSections) {
TEST_F(WasmModuleVerifyTest, SourceMappingURLSection) {
static const byte data[] = {
WASM_MODULE_HEADER,
SECTION_SRC_MAP('s', 'r', 'c', '/', 'x', 'y', 'z', '.', 'c')};
ModuleResult result = DecodeModule(data, data + sizeof(data));
ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data));
EXPECT_TRUE(result.ok());
EXPECT_EQ("src/xyz.c", result.value()->source_map_url);
EXPECT_EQ(WasmDebugSymbols::Type::SourceMap,
result.value()->debug_symbols.type);
ModuleWireBytes wire_bytes(data, data + sizeof(data));
WasmName external_url =
wire_bytes.GetNameOrNull(result.value()->debug_symbols.external_url);
EXPECT_EQ("src/xyz.c", std::string(external_url.data(), external_url.size()));
}
TEST_F(WasmModuleVerifyTest, BadSourceMappingURLSection) {
static const byte data[] = {
WASM_MODULE_HEADER,
SECTION_SRC_MAP('s', 'r', 'c', '/', 'x', 0xff, 'z', '.', 'c')};
ModuleResult result = DecodeModule(data, data + sizeof(data));
ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data));
EXPECT_TRUE(result.ok());
EXPECT_EQ(0u, result.value()->source_map_url.size());
EXPECT_EQ(WasmDebugSymbols::Type::None, result.value()->debug_symbols.type);
EXPECT_EQ(0u, result.value()->debug_symbols.external_url.length());
}
TEST_F(WasmModuleVerifyTest, MultipleSourceMappingURLSections) {
static const byte data[] = {SECTION_SRC_MAP('a', 'b', 'c'),
static const byte data[] = {WASM_MODULE_HEADER,
SECTION_SRC_MAP('a', 'b', 'c'),
SECTION_SRC_MAP('p', 'q', 'r')};
ModuleResult result = DecodeModule(data, data + sizeof(data));
ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data));
EXPECT_TRUE(result.ok());
EXPECT_EQ("abc", result.value()->source_map_url);
EXPECT_EQ(WasmDebugSymbols::Type::SourceMap,
result.value()->debug_symbols.type);
ModuleWireBytes wire_bytes(data, data + sizeof(data));
WasmName external_url =
wire_bytes.GetNameOrNull(result.value()->debug_symbols.external_url);
EXPECT_EQ("abc", std::string(external_url.data(), external_url.size()));
}
TEST_F(WasmModuleVerifyTest, MultipleNameSections) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment