Skip to content

Commit 7425d2b

Browse files
dschuffyurydelendik
authored andcommitted
Exports .txtmap file when .wasm is exported from asm2wasm.
1 parent 2ddb7cb commit 7425d2b

14 files changed

+125
-11
lines changed

check.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,31 @@ def do_asm2wasm_test():
175175
fail_with_error('wasm interpreter error: ' + err) # failed to pretty-print
176176
fail_with_error('wasm interpreter error')
177177

178+
# verify debug info
179+
if 'debugInfo' in asm:
180+
txtmap = 'a.wasm.txtmap'
181+
cmd += ['--binarymap-file', txtmap,
182+
'--binarymap-url', txtmap + '.map',
183+
'-o', 'a.wasm']
184+
run_command(cmd)
185+
if not os.path.isfile(txtmap):
186+
fail_with_error('Debug info map not created: %s' % txtmap)
187+
with open(wasm + '.txtmap', 'rb') as expected:
188+
with open(txtmap, 'rb') as actual:
189+
fail_if_not_identical(actual.read(), expected.read())
190+
with open('a.wasm', 'rb') as binary:
191+
url_section_name = bytearray([16]) + bytearray('sourceMappingURL')
192+
payload = txtmap + '.map'
193+
assert len(payload) < 256, 'name too long'
194+
url_section_contents = bytearray([len(payload)]) + bytearray(payload)
195+
print url_section_name
196+
binary_contents = bytearray(binary.read())
197+
if url_section_name not in binary_contents:
198+
fail_with_error('source map url section not found in binary')
199+
if url_section_contents not in binary_contents[binary_contents.index(url_section_name):]:
200+
fail_with_error('source map url not found in url section')
201+
202+
178203
print '\n[ checking asm2wasm binary reading/writing... ]\n'
179204

180205
asmjs = os.path.join(options.binaryen_test, 'hello_world.asm.js')

src/tools/asm2wasm.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ int main(int argc, const char *argv[]) {
3737
bool runOptimizationPasses = false;
3838
Asm2WasmBuilder::TrapMode trapMode = Asm2WasmBuilder::TrapMode::JS;
3939
bool wasmOnly = false;
40+
std::string binaryMapFile;
41+
std::string binaryMapUrl;
4042
std::string symbolMap;
4143
bool emitBinary = true;
4244

@@ -101,9 +103,15 @@ int main(int argc, const char *argv[]) {
101103
[&legalizeJavaScriptFFI](Options *o, const std::string &) {
102104
legalizeJavaScriptFFI = false;
103105
})
104-
.add("--debuginfo", "-g", "Emit names section and debug info (for debug info you must emit text, -S, for this to work)",
106+
.add("--debuginfo", "-g", "Emit names section in wasm binary (or full debuginfo in wast)",
105107
Options::Arguments::Zero,
106108
[&](Options *o, const std::string &arguments) { passOptions.debugInfo = true; })
109+
.add("--binarymap-file", "-bm", "Emit binary map (if using binary output) to the specified file",
110+
Options::Arguments::One,
111+
[&binaryMapFile](Options *o, const std::string &argument) { binaryMapFile = argument; })
112+
.add("--binarymap-url", "-bu", "Use specified string as binary map URL",
113+
Options::Arguments::One,
114+
[&binaryMapUrl](Options *o, const std::string &argument) { binaryMapUrl = argument; })
107115
.add("--symbolmap", "-s", "Emit a symbol map (indexes => names)",
108116
Options::Arguments::One,
109117
[&](Options *o, const std::string &argument) { symbolMap = argument; })
@@ -132,8 +140,9 @@ int main(int argc, const char *argv[]) {
132140
}
133141

134142
Asm2WasmPreProcessor pre;
135-
// wasm binaries can contain a names section, but not full debug info
136-
pre.debugInfo = passOptions.debugInfo && !emitBinary;
143+
// wasm binaries can contain a names section, but not full debug info --
144+
// debug info is disabled if a map file is not specified with wasm binary
145+
pre.debugInfo = passOptions.debugInfo && (!emitBinary || binaryMapFile.size());
137146
auto input(
138147
read_file<std::vector<char>>(options.extra["infile"], Flags::Text, options.debug ? Flags::Debug : Flags::Release));
139148
char *start = pre.process(input.data());
@@ -200,7 +209,11 @@ int main(int argc, const char *argv[]) {
200209
writer.setDebugInfo(passOptions.debugInfo);
201210
writer.setSymbolMap(symbolMap);
202211
writer.setBinary(emitBinary);
203-
writer.write(wasm, options.extra["output"]);
212+
if (emitBinary && binaryMapFile.size()) {
213+
writer.writeBinary(wasm, options.extra["output"], binaryMapFile, binaryMapUrl);
214+
} else {
215+
writer.write(wasm, options.extra["output"]);
216+
}
204217

205218
if (options.debug) std::cerr << "done." << std::endl;
206219
}

src/tools/wasm-as.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ int main(int argc, const char *argv[]) {
8686
if (options.debug) std::cerr << "binarification..." << std::endl;
8787
BufferWithRandomAccess buffer(options.debug);
8888
WasmBinaryWriter writer(&wasm, buffer, options.debug);
89-
writer.setDebugInfo(debugInfo);
89+
writer.setNamesSection(debugInfo);
9090
if (symbolMap.size() > 0) writer.setSymbolMap(symbolMap);
9191
writer.write();
9292

src/wasm-binary.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ enum EncodedType {
308308

309309
namespace UserSections {
310310
extern const char* Name;
311+
extern const char* SourceMapUrl;
311312

312313
enum Subsection {
313314
NameFunction = 1,
@@ -534,8 +535,11 @@ inline S32LEB binaryWasmType(WasmType type) {
534535
class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
535536
Module* wasm;
536537
BufferWithRandomAccess& o;
538+
Function* currFunction = nullptr;
537539
bool debug;
538540
bool debugInfo = true;
541+
std::ostream* binaryMap = nullptr;
542+
std::string binaryMapUrl;
539543
std::string symbolMap;
540544

541545
MixedArena allocator;
@@ -546,7 +550,11 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
546550
prepare();
547551
}
548552

549-
void setDebugInfo(bool set) { debugInfo = set; }
553+
void setNamesSection(bool set) { debugInfo = set; }
554+
void setBinaryMap(std::ostream* set, std::string url) {
555+
binaryMap = set;
556+
binaryMapUrl = url;
557+
}
550558
void setSymbolMap(std::string set) { symbolMap = set; }
551559

552560
void write();
@@ -582,6 +590,7 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
582590
void writeFunctionTableDeclaration();
583591
void writeTableElements();
584592
void writeNames();
593+
void writeSourceMapUrl();
585594
void writeSymbolMap();
586595

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

619+
void visit(Expression* curr) {
620+
if (binaryMap && currFunction) {
621+
// Dump the binaryMap debug info
622+
auto& debugLocations = currFunction->debugLocations;
623+
auto iter = debugLocations.find(curr);
624+
if (iter != debugLocations.end()) {
625+
auto fileName = wasm->debugInfoFileNames[iter->second.fileIndex];
626+
*binaryMap << o.size() << ":" << fileName << ":" <<iter->second.lineNumber << '\n';
627+
}
628+
}
629+
Visitor<WasmBinaryWriter>::visit(curr);
630+
}
631+
610632
void visitBlock(Block *curr);
611633
// emits a node, but if it is a block with no name, emit a list of its contents
612634
void recursePossibleBlockContents(Expression* curr);

src/wasm-io.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ class ModuleWriter : public ModuleIO {
5757
// write text
5858
void writeText(Module& wasm, std::string filename);
5959
// write binary
60-
void writeBinary(Module& wasm, std::string filename);
60+
void writeBinary(Module& wasm, std::string filename,
61+
std::string binaryMapFilename,
62+
std::string binaryMapUrl);
6163
// write text or binary, defaulting to binary unless setBinary(false),
6264
// and unless there is no output file (in which case we write text
6365
// to stdout).

src/wasm/wasm-binary.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ void WasmBinaryWriter::write() {
4646
writeFunctions();
4747
writeDataSegments();
4848
if (debugInfo) writeNames();
49+
if (binaryMap) writeSourceMapUrl();
4950
if (symbolMap.size() > 0) writeSymbolMap();
5051

5152
finishUp();
@@ -236,6 +237,7 @@ void WasmBinaryWriter::writeFunctions() {
236237
size_t sizePos = writeU32LEBPlaceholder();
237238
size_t start = o.size();
238239
Function* function = wasm->functions[i].get();
240+
currFunction = function;
239241
mappedLocals.clear();
240242
numLocalsByType.clear();
241243
if (debug) std::cerr << "writing" << function->name << std::endl;
@@ -258,6 +260,7 @@ void WasmBinaryWriter::writeFunctions() {
258260
if (debug) std::cerr << "body size: " << size << ", writing at " << sizePos << ", next starts at " << o.size() << std::endl;
259261
o.writeAt(sizePos, U32LEB(size));
260262
}
263+
currFunction = nullptr;
261264
finishSection(start);
262265
}
263266

@@ -420,6 +423,14 @@ void WasmBinaryWriter::writeNames() {
420423
finishSection(start);
421424
}
422425

426+
void WasmBinaryWriter::writeSourceMapUrl() {
427+
if (debug) std::cerr << "== writeSourceMapUrl" << std::endl;
428+
auto start = startSection(BinaryConsts::Section::User);
429+
writeInlineString(BinaryConsts::UserSections::SourceMapUrl);
430+
writeInlineString(binaryMapUrl.c_str());
431+
finishSection(start);
432+
}
433+
423434
void WasmBinaryWriter::writeSymbolMap() {
424435
std::ofstream file(symbolMap);
425436
for (auto& import : wasm->imports) {

src/wasm/wasm-io.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,24 +68,35 @@ void ModuleWriter::writeText(Module& wasm, std::string filename) {
6868
WasmPrinter::printModule(&wasm, output.getStream());
6969
}
7070

71-
void ModuleWriter::writeBinary(Module& wasm, std::string filename) {
71+
void ModuleWriter::writeBinary(Module& wasm, std::string filename,
72+
std::string binaryMapFilename,
73+
std::string binaryMapUrl) {
7274
if (debug) std::cerr << "writing binary to " << filename << "\n";
7375
BufferWithRandomAccess buffer(debug);
7476
WasmBinaryWriter writer(&wasm, buffer, debug);
75-
writer.setDebugInfo(debugInfo);
77+
writer.setNamesSection(debugInfo);
78+
std::ofstream* binaryMapStream = nullptr;
79+
if (binaryMapFilename.size()) {
80+
binaryMapStream = new std::ofstream;
81+
binaryMapStream->open(binaryMapFilename);
82+
writer.setBinaryMap(binaryMapStream, binaryMapUrl);
83+
}
7684
if (symbolMap.size() > 0) writer.setSymbolMap(symbolMap);
7785
writer.write();
7886
Output output(filename, Flags::Binary, debug ? Flags::Debug : Flags::Release);
7987
buffer.writeTo(output);
88+
if (binaryMapStream) {
89+
binaryMapStream->close();
90+
delete binaryMapStream;
91+
}
8092
}
8193

8294
void ModuleWriter::write(Module& wasm, std::string filename) {
8395
if (binary && filename.size() > 0) {
84-
writeBinary(wasm, filename);
96+
writeBinary(wasm, filename, std::string(), std::string());
8597
} else {
8698
writeText(wasm, filename);
8799
}
88100
}
89101

90102
}
91-

src/wasm/wasm.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Name WASM("wasm"),
2828
namespace BinaryConsts {
2929
namespace UserSections {
3030
const char* Name = "name";
31+
const char* SourceMapUrl = "sourceMappingURL";
3132
}
3233
}
3334

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
164:tests/hello_world.c:5
2+
168:tests/hello_world.c:6
3+
172:tests/other_file.cpp:314159
4+
194:return.cpp:50
5+
201:return.cpp:100
6+
241:even-opted.cpp:1
7+
248:even-opted.cpp:2
8+
255:even-opted.cpp:3

test/debugInfo.fromasm.clamp.txtmap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
211:even-opted.cpp:2
2+
223:even-opted.cpp:3

0 commit comments

Comments
 (0)