Skip to content

Commit 4ab8088

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

14 files changed

+120
-7
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: 16 additions & 3 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,6 +209,10 @@ int main(int argc, const char *argv[]) {
200209
writer.setDebugInfo(passOptions.debugInfo);
201210
writer.setSymbolMap(symbolMap);
202211
writer.setBinary(emitBinary);
212+
if (emitBinary) {
213+
writer.setBinaryMapFilename(binaryMapFile);
214+
writer.setBinaryMapUrl(binaryMapUrl);
215+
}
203216
writer.write(wasm, options.extra["output"]);
204217

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

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: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,15 @@ class ModuleWriter : public ModuleIO {
4848
bool binary = true;
4949
bool debugInfo = false;
5050
std::string symbolMap;
51+
std::string binaryMapFilename;
52+
std::string binaryMapUrl;
5153

5254
public:
5355
void setBinary(bool binary_) { binary = binary_; }
5456
void setDebugInfo(bool debugInfo_) { debugInfo = debugInfo_; }
5557
void setSymbolMap(std::string symbolMap_) { symbolMap = symbolMap_; }
58+
void setBinaryMapFilename(std::string binaryMapFilename_) { binaryMapFilename = binaryMapFilename_; }
59+
void setBinaryMapUrl(std::string binaryMapUrl_) { binaryMapUrl = binaryMapUrl_; }
5660

5761
// write text
5862
void writeText(Module& wasm, std::string filename);

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: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,20 @@ void ModuleWriter::writeBinary(Module& wasm, std::string filename) {
7272
if (debug) std::cerr << "writing binary to " << filename << "\n";
7373
BufferWithRandomAccess buffer(debug);
7474
WasmBinaryWriter writer(&wasm, buffer, debug);
75-
writer.setDebugInfo(debugInfo);
75+
writer.setNamesSection(debugInfo);
76+
std::unique_ptr<std::ofstream> binaryMapStream;
77+
if (binaryMapFilename.size()) {
78+
binaryMapStream = make_unique<std::ofstream>();
79+
binaryMapStream->open(binaryMapFilename);
80+
writer.setBinaryMap(binaryMapStream.get(), binaryMapUrl);
81+
}
7682
if (symbolMap.size() > 0) writer.setSymbolMap(symbolMap);
7783
writer.write();
7884
Output output(filename, Flags::Binary, debug ? Flags::Debug : Flags::Release);
7985
buffer.writeTo(output);
86+
if (binaryMapStream) {
87+
binaryMapStream->close();
88+
}
8089
}
8190

8291
void ModuleWriter::write(Module& wasm, std::string filename) {
@@ -88,4 +97,3 @@ void ModuleWriter::write(Module& wasm, std::string filename) {
8897
}
8998

9099
}
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)