Working, probably.
diff --git a/check.py b/check.py index 2171a33..b1d52b9 100755 --- a/check.py +++ b/check.py
@@ -156,6 +156,31 @@ fail_with_error('wasm interpreter error: ' + err) # failed to pretty-print fail_with_error('wasm interpreter error') + # verify debug info + if 'debugInfo' in asm: + txtmap = 'a.wasm.txtmap' + cmd += ['--binarymap-file', txtmap, + '--binarymap-url', txtmap + '.map', + '-o', 'a.wasm'] + run_command(cmd) + if not os.path.isfile(txtmap): + fail_with_error('Debug info map not created: %s' % txtmap) + with open(wasm + '.txtmap', 'rb') as expected: + with open(txtmap, 'rb') as actual: + fail_if_not_identical(actual.read(), expected.read()) + with open('a.wasm', 'rb') as binary: + url_section_name = bytearray([16]) + bytearray('sourceMappingURL') + payload = txtmap + '.map' + assert len(payload) < 256, 'name too long' + url_section_contents = bytearray([len(payload)]) + bytearray(payload) + print url_section_name + binary_contents = bytearray(binary.read()) + if url_section_name not in binary_contents: + fail_with_error('source map url section not found in binary') + if url_section_contents not in binary_contents[binary_contents.index(url_section_name):]: + fail_with_error('source map url not found in url section') + + print '\n[ checking asm2wasm binary reading/writing... ]\n' asmjs = os.path.join(options.binaryen_test, 'hello_world.asm.js')
diff --git a/src/tools/asm2wasm.cpp b/src/tools/asm2wasm.cpp index 9f0d0e4..ebc88bf 100644 --- a/src/tools/asm2wasm.cpp +++ b/src/tools/asm2wasm.cpp
@@ -36,6 +36,8 @@ Asm2WasmBuilder::TrapMode trapMode = Asm2WasmBuilder::TrapMode::JS; bool wasmOnly = false; bool debugInfo = false; + std::string binaryMapFile; + std::string binaryMapUrl; std::string symbolMap; bool emitBinary = true; @@ -96,9 +98,15 @@ [&wasmOnly](Options *o, const std::string &) { wasmOnly = true; }) - .add("--debuginfo", "-g", "Emit names section and debug info (for debug info you must emit text, -S, for this to work)", + .add("--debuginfo", "-g", "Emit names section in wasm binary (or full debuginfo in wast)", Options::Arguments::Zero, [&](Options *o, const std::string &arguments) { debugInfo = true; }) + .add("--binarymap-file", "-bm", "Emit binary map (if using binary output) to the specified file", + Options::Arguments::One, + [&binaryMapFile](Options *o, const std::string &argument) { binaryMapFile = argument; }) + .add("--binarymap-url", "-bu", "Use specified string as binary map URL", + Options::Arguments::One, + [&binaryMapUrl](Options *o, const std::string &argument) { binaryMapUrl = argument; }) .add("--symbolmap", "-s", "Emit a symbol map (indexes => names)", Options::Arguments::One, [&](Options *o, const std::string &argument) { symbolMap = argument; }) @@ -127,7 +135,6 @@ } Asm2WasmPreProcessor pre; - // wasm binaries can contain a names section, but not full debug info pre.debugInfo = debugInfo; auto input( read_file<std::vector<char>>(options.extra["infile"], Flags::Text, options.debug ? Flags::Debug : Flags::Release)); @@ -191,7 +198,11 @@ writer.setDebugInfo(debugInfo); writer.setSymbolMap(symbolMap); writer.setBinary(emitBinary); - writer.write(wasm, options.extra["output"]); + if (emitBinary && binaryMapFile.size()) { + writer.writeBinary(wasm, options.extra["output"], binaryMapFile, binaryMapUrl); + } else { + writer.write(wasm, options.extra["output"]); + } if (options.debug) std::cerr << "done." << std::endl; }
diff --git a/src/tools/wasm-as.cpp b/src/tools/wasm-as.cpp index 067c0f2..5bdf74b 100644 --- a/src/tools/wasm-as.cpp +++ b/src/tools/wasm-as.cpp
@@ -86,7 +86,7 @@ if (options.debug) std::cerr << "binarification..." << std::endl; BufferWithRandomAccess buffer(options.debug); WasmBinaryWriter writer(&wasm, buffer, options.debug); - writer.setDebugInfo(debugInfo); + writer.setNamesSection(debugInfo); if (symbolMap.size() > 0) writer.setSymbolMap(symbolMap); writer.write();
diff --git a/src/wasm-binary.h b/src/wasm-binary.h index ec45f24..ee0a8de 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h
@@ -303,6 +303,7 @@ namespace UserSections { extern const char* Name; +extern const char* SourceMapUrl; enum Subsection { NameFunction = 1, @@ -532,6 +533,8 @@ Function* currFunction = nullptr; bool debug; bool debugInfo = true; + std::ostream* binaryMap = nullptr; + std::string binaryMapUrl; std::string symbolMap; MixedArena allocator; @@ -542,7 +545,11 @@ prepare(); } - void setDebugInfo(bool set) { debugInfo = set; } + void setNamesSection(bool set) { debugInfo = set; } + void setBinaryMap(std::ostream* set, std::string url) { + binaryMap = set; + binaryMapUrl = url; + } void setSymbolMap(std::string set) { symbolMap = set; } void write(); @@ -578,6 +585,7 @@ void writeFunctionTableDeclaration(); void writeTableElements(); void writeNames(); + void writeSourceMapUrl(); void writeSymbolMap(); // helpers @@ -604,13 +612,13 @@ std::vector<Name> breakStack; void visit(Expression* curr) { - if (debugInfo && currFunction) { - // show an annotation, if there is one + if (binaryMap && currFunction) { + // Dump the binaryMap debug info auto& debugLocations = currFunction->debugLocations; auto iter = debugLocations.find(curr); if (iter != debugLocations.end()) { auto fileName = wasm->debugInfoFileNames[iter->second.fileIndex]; - std::cout << std::hex <<o.size() << ":" << fileName << ":" << std::dec <<iter->second.lineNumber << '\n'; + *binaryMap << o.size() << ":" << fileName << ":" <<iter->second.lineNumber << '\n'; } } Visitor<WasmBinaryWriter>::visit(curr);
diff --git a/src/wasm-io.h b/src/wasm-io.h index 7d7358f..eb644ba 100644 --- a/src/wasm-io.h +++ b/src/wasm-io.h
@@ -56,7 +56,9 @@ // write text void writeText(Module& wasm, std::string filename); // write binary - void writeBinary(Module& wasm, std::string filename); + void writeBinary(Module& wasm, std::string filename, + std::string binaryMapFilename, + std::string binaryMapUrl); // write text or binary, defaulting to binary unless setBinary(false), // and unless there is no output file (in which case we write text // to stdout).
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 9a3c026..d8a3d99 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp
@@ -46,6 +46,7 @@ writeFunctions(); writeDataSegments(); if (debugInfo) writeNames(); + if (binaryMap) writeSourceMapUrl(); if (symbolMap.size() > 0) writeSymbolMap(); finishUp(); @@ -422,6 +423,14 @@ finishSection(start); } +void WasmBinaryWriter::writeSourceMapUrl() { + if (debug) std::cerr << "== writeSourceMapUrl" << std::endl; + auto start = startSection(BinaryConsts::Section::User); + writeInlineString(BinaryConsts::UserSections::SourceMapUrl); + writeInlineString(binaryMapUrl.c_str()); + finishSection(start); +} + void WasmBinaryWriter::writeSymbolMap() { std::ofstream file(symbolMap); for (auto& import : wasm->imports) {
diff --git a/src/wasm/wasm-io.cpp b/src/wasm/wasm-io.cpp index c3192ef..3366d5e 100644 --- a/src/wasm/wasm-io.cpp +++ b/src/wasm/wasm-io.cpp
@@ -68,24 +68,35 @@ WasmPrinter::printModule(&wasm, output.getStream()); } -void ModuleWriter::writeBinary(Module& wasm, std::string filename) { +void ModuleWriter::writeBinary(Module& wasm, std::string filename, + std::string binaryMapFilename, + std::string binaryMapUrl) { if (debug) std::cerr << "writing binary to " << filename << "\n"; BufferWithRandomAccess buffer(debug); WasmBinaryWriter writer(&wasm, buffer, debug); - writer.setDebugInfo(debugInfo); + writer.setNamesSection(debugInfo); + std::ofstream* binaryMapStream = nullptr; + if (binaryMapFilename.size()) { + binaryMapStream = new std::ofstream; + binaryMapStream->open(binaryMapFilename); + writer.setBinaryMap(binaryMapStream, binaryMapUrl); + } if (symbolMap.size() > 0) writer.setSymbolMap(symbolMap); writer.write(); Output output(filename, Flags::Binary, debug ? Flags::Debug : Flags::Release); buffer.writeTo(output); + if (binaryMapStream) { + binaryMapStream->close(); + delete binaryMapStream; + } } void ModuleWriter::write(Module& wasm, std::string filename) { if (binary && filename.size() > 0) { - writeBinary(wasm, filename); + writeBinary(wasm, filename, std::string(), std::string()); } else { writeText(wasm, filename); } } } -
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index a983fc9..dce9096 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp
@@ -28,6 +28,7 @@ namespace BinaryConsts { namespace UserSections { const char* Name = "name"; +const char* SourceMapUrl = "sourceMappingURL"; } }
diff --git a/test/debugInfo.fromasm.clamp.no-opts.txtmap b/test/debugInfo.fromasm.clamp.no-opts.txtmap new file mode 100644 index 0000000..eec2e7b --- /dev/null +++ b/test/debugInfo.fromasm.clamp.no-opts.txtmap
@@ -0,0 +1,8 @@ +164:tests/hello_world.c:5 +168:tests/hello_world.c:6 +172:tests/other_file.cpp:314159 +194:return.cpp:50 +201:return.cpp:100 +241:even-opted.cpp:1 +248:even-opted.cpp:2 +255:even-opted.cpp:3
diff --git a/test/debugInfo.fromasm.clamp.txtmap b/test/debugInfo.fromasm.clamp.txtmap new file mode 100644 index 0000000..bb25b4d --- /dev/null +++ b/test/debugInfo.fromasm.clamp.txtmap
@@ -0,0 +1,2 @@ +211:even-opted.cpp:2 +223:even-opted.cpp:3
diff --git a/test/debugInfo.fromasm.imprecise.no-opts.txtmap b/test/debugInfo.fromasm.imprecise.no-opts.txtmap new file mode 100644 index 0000000..00a07f1 --- /dev/null +++ b/test/debugInfo.fromasm.imprecise.no-opts.txtmap
@@ -0,0 +1,8 @@ +163:tests/hello_world.c:5 +167:tests/hello_world.c:6 +171:tests/other_file.cpp:314159 +193:return.cpp:50 +200:return.cpp:100 +219:even-opted.cpp:1 +226:even-opted.cpp:2 +233:even-opted.cpp:3
diff --git a/test/debugInfo.fromasm.imprecise.txtmap b/test/debugInfo.fromasm.imprecise.txtmap new file mode 100644 index 0000000..c9f177c --- /dev/null +++ b/test/debugInfo.fromasm.imprecise.txtmap
@@ -0,0 +1 @@ +190:even-opted.cpp:2
diff --git a/test/debugInfo.fromasm.no-opts.txtmap b/test/debugInfo.fromasm.no-opts.txtmap new file mode 100644 index 0000000..eec2e7b --- /dev/null +++ b/test/debugInfo.fromasm.no-opts.txtmap
@@ -0,0 +1,8 @@ +164:tests/hello_world.c:5 +168:tests/hello_world.c:6 +172:tests/other_file.cpp:314159 +194:return.cpp:50 +201:return.cpp:100 +241:even-opted.cpp:1 +248:even-opted.cpp:2 +255:even-opted.cpp:3
diff --git a/test/debugInfo.fromasm.txtmap b/test/debugInfo.fromasm.txtmap new file mode 100644 index 0000000..bb25b4d --- /dev/null +++ b/test/debugInfo.fromasm.txtmap
@@ -0,0 +1,2 @@ +211:even-opted.cpp:2 +223:even-opted.cpp:3