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