Skip to content

Commit

Permalink
Exports .txtmap file when .wasm is exported from asm2wasm.
Browse files Browse the repository at this point in the history
  • Loading branch information
dschuff authored and yurydelendik committed May 19, 2017
1 parent 2ddb7cb commit 7425d2b
Show file tree
Hide file tree
Showing 14 changed files with 125 additions and 11 deletions.
25 changes: 25 additions & 0 deletions check.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,31 @@ def do_asm2wasm_test():
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')
Expand Down
21 changes: 17 additions & 4 deletions src/tools/asm2wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ int main(int argc, const char *argv[]) {
bool runOptimizationPasses = false;
Asm2WasmBuilder::TrapMode trapMode = Asm2WasmBuilder::TrapMode::JS;
bool wasmOnly = false;
std::string binaryMapFile;
std::string binaryMapUrl;
std::string symbolMap;
bool emitBinary = true;

Expand Down Expand Up @@ -101,9 +103,15 @@ int main(int argc, const char *argv[]) {
[&legalizeJavaScriptFFI](Options *o, const std::string &) {
legalizeJavaScriptFFI = false;
})
.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) { passOptions.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; })
Expand Down Expand Up @@ -132,8 +140,9 @@ int main(int argc, const char *argv[]) {
}

Asm2WasmPreProcessor pre;
// wasm binaries can contain a names section, but not full debug info
pre.debugInfo = passOptions.debugInfo && !emitBinary;
// wasm binaries can contain a names section, but not full debug info --
// debug info is disabled if a map file is not specified with wasm binary
pre.debugInfo = passOptions.debugInfo && (!emitBinary || binaryMapFile.size());
auto input(
read_file<std::vector<char>>(options.extra["infile"], Flags::Text, options.debug ? Flags::Debug : Flags::Release));
char *start = pre.process(input.data());
Expand Down Expand Up @@ -200,7 +209,11 @@ int main(int argc, const char *argv[]) {
writer.setDebugInfo(passOptions.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;
}
2 changes: 1 addition & 1 deletion src/tools/wasm-as.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ int main(int argc, const char *argv[]) {
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();

Expand Down
24 changes: 23 additions & 1 deletion src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ enum EncodedType {

namespace UserSections {
extern const char* Name;
extern const char* SourceMapUrl;

enum Subsection {
NameFunction = 1,
Expand Down Expand Up @@ -534,8 +535,11 @@ inline S32LEB binaryWasmType(WasmType type) {
class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
Module* wasm;
BufferWithRandomAccess& o;
Function* currFunction = nullptr;
bool debug;
bool debugInfo = true;
std::ostream* binaryMap = nullptr;
std::string binaryMapUrl;
std::string symbolMap;

MixedArena allocator;
Expand All @@ -546,7 +550,11 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
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();
Expand Down Expand Up @@ -582,6 +590,7 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
void writeFunctionTableDeclaration();
void writeTableElements();
void writeNames();
void writeSourceMapUrl();
void writeSymbolMap();

// helpers
Expand All @@ -607,6 +616,19 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
void recurse(Expression*& curr);
std::vector<Name> breakStack;

void visit(Expression* curr) {
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];
*binaryMap << o.size() << ":" << fileName << ":" <<iter->second.lineNumber << '\n';
}
}
Visitor<WasmBinaryWriter>::visit(curr);
}

void visitBlock(Block *curr);
// emits a node, but if it is a block with no name, emit a list of its contents
void recursePossibleBlockContents(Expression* curr);
Expand Down
4 changes: 3 additions & 1 deletion src/wasm-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ class ModuleWriter : public ModuleIO {
// 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).
Expand Down
11 changes: 11 additions & 0 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ void WasmBinaryWriter::write() {
writeFunctions();
writeDataSegments();
if (debugInfo) writeNames();
if (binaryMap) writeSourceMapUrl();
if (symbolMap.size() > 0) writeSymbolMap();

finishUp();
Expand Down Expand Up @@ -236,6 +237,7 @@ void WasmBinaryWriter::writeFunctions() {
size_t sizePos = writeU32LEBPlaceholder();
size_t start = o.size();
Function* function = wasm->functions[i].get();
currFunction = function;
mappedLocals.clear();
numLocalsByType.clear();
if (debug) std::cerr << "writing" << function->name << std::endl;
Expand All @@ -258,6 +260,7 @@ void WasmBinaryWriter::writeFunctions() {
if (debug) std::cerr << "body size: " << size << ", writing at " << sizePos << ", next starts at " << o.size() << std::endl;
o.writeAt(sizePos, U32LEB(size));
}
currFunction = nullptr;
finishSection(start);
}

Expand Down Expand Up @@ -420,6 +423,14 @@ void WasmBinaryWriter::writeNames() {
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) {
Expand Down
19 changes: 15 additions & 4 deletions src/wasm/wasm-io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,24 +68,35 @@ void ModuleWriter::writeText(Module& wasm, std::string filename) {
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);
}
}

}

1 change: 1 addition & 0 deletions src/wasm/wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Name WASM("wasm"),
namespace BinaryConsts {
namespace UserSections {
const char* Name = "name";
const char* SourceMapUrl = "sourceMappingURL";
}
}

Expand Down
8 changes: 8 additions & 0 deletions test/debugInfo.fromasm.clamp.no-opts.txtmap
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions test/debugInfo.fromasm.clamp.txtmap
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
211:even-opted.cpp:2
223:even-opted.cpp:3
8 changes: 8 additions & 0 deletions test/debugInfo.fromasm.imprecise.no-opts.txtmap
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions test/debugInfo.fromasm.imprecise.txtmap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
190:even-opted.cpp:2
8 changes: 8 additions & 0 deletions test/debugInfo.fromasm.no-opts.txtmap
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions test/debugInfo.fromasm.txtmap
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
211:even-opted.cpp:2
223:even-opted.cpp:3

0 comments on commit 7425d2b

Please sign in to comment.