Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion src/tools/wasm-opt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ int main(int argc, const char* argv[]) {
std::string outputSourceMapFilename;
std::string outputSourceMapUrl;
bool emitExnref = false;
bool needCodeLocations = false;

const std::string WasmOptOption = "wasm-opt options";

Expand Down Expand Up @@ -280,7 +281,21 @@ For more on how to optimize effectively, see
"post-translation optimizations.",
WasmOptOption,
Options::Arguments::Zero,
[&emitExnref](Options*, const std::string&) { emitExnref = true; });
[&emitExnref](Options*, const std::string&) { emitExnref = true; })
.add("--print-binary-offsets",
"-pbo",
"Print wat text annotated with binary offsets",
WasmOptOption,
Options::Arguments::Zero,
[&](Options*, const std::string&) {
// Track code locations, so we can print them.
needCodeLocations = true;
// Enable debugInfo, so that we print code locations (which are part
// of debugInfo).
options.passOptions.debugInfo = true;
// Run the print pass, to do the printing.
options.passes.push_back("print");
});
options.parse(argc, argv);

Module wasm;
Expand Down Expand Up @@ -315,6 +330,7 @@ For more on how to optimize effectively, see
reader.setDWARF(options.passOptions.debugInfo &&
!willRemoveDebugInfo(options.passes));
reader.setProfile(options.profile);
reader.setNeedCodeLocations(needCodeLocations);
try {
reader.read(inputFile, wasm, inputSourceMapFilename);
} catch (ParseException& p) {
Expand All @@ -335,6 +351,15 @@ For more on how to optimize effectively, see
"request for silly amounts of memory)";
}

if (needCodeLocations) {
if (auto codeSectionLocation = reader.getCodeSectionLocation()) {
std::cout << ";; Code section offset: 0x" << std::hex
<< *codeSectionLocation << std::dec << '\n'
<< ";; (binary offsets in VM stack traces include this;"
<< " add it to the offsets below)\n";
}
}

options.applyOptionsAfterParse(wasm);

if (options.passOptions.validate) {
Expand Down
4 changes: 4 additions & 0 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -1572,6 +1572,8 @@ class WasmBinaryReader {
void setSkipFunctionBodies(bool skipFunctionBodies_) {
skipFunctionBodies = skipFunctionBodies_;
}
void setNeedCodeLocations(bool value) { needCodeLocations = value; }

void read();
void readCustomSection(size_t payloadLen);

Expand Down Expand Up @@ -1746,6 +1748,8 @@ class WasmBinaryReader {
// Allow users to query the target features section features after parsing.
FeatureSet getFeaturesSectionFeatures() { return featuresSectionFeatures; }

size_t getCodeSectionLocation() { return codeSectionLocation; }

private:
// In certain modes we need to note the locations of expressions, to match
// them against sections like DWARF or custom annotations. As this incurs
Expand Down
11 changes: 11 additions & 0 deletions src/wasm-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ class ModuleReader : public ModuleIOBase {
skipFunctionBodies = skipFunctionBodies_;
}

void setNeedCodeLocations(bool needCodeLocations_) {
needCodeLocations = needCodeLocations_;
}

// read text
void readText(std::string filename, Module& wasm);
// read binary
Expand All @@ -68,15 +72,22 @@ class ModuleReader : public ModuleIOBase {

FeatureSet getFeaturesSectionFeatures() { return featuresSectionFeatures; }

// Return the offset of the code section, or nothing if we did not read a
// binary.
std::optional<size_t> getCodeSectionLocation() { return codeSectionLocation; }

private:
bool DWARF = false;

IRProfile profile = IRProfile::Normal;

bool skipFunctionBodies = false;
bool needCodeLocations = false;

FeatureSet featuresSectionFeatures = FeatureSet::MVP;

std::optional<size_t> codeSectionLocation;

void readStdin(Module& wasm, std::string sourceMapFilename);

void readBinaryData(std::vector<char>& input,
Expand Down
2 changes: 2 additions & 0 deletions src/wasm/wasm-io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,12 @@ void ModuleReader::readBinaryData(std::vector<char>& input,
parser.setDebugInfo(debugInfo);
parser.setDWARF(DWARF);
parser.setSkipFunctionBodies(skipFunctionBodies);
parser.setNeedCodeLocations(needCodeLocations);
parser.read();
if (wasm.hasFeaturesSection) {
featuresSectionFeatures = parser.getFeaturesSectionFeatures();
}
codeSectionLocation = parser.getCodeSectionLocation();
}

void ModuleReader::readBinary(std::string filename,
Expand Down
20 changes: 20 additions & 0 deletions test/lit/debug/print-binary-offsets.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
;; RUN: wasm-opt %s -o %t.wasm
;; RUN: wasm-opt %t.wasm --print-binary-offsets | filecheck %s

;; The command makes us print binary offsets in wat text. Note that it works
;; even without -g for the names section.

(module
(func $test
(call $test)
)
)

;; CHECK: ;; Code section offset: 0x14
;; CHECK-NEXT: ;; (binary offsets in VM stack traces include this; add it to the offsets below)

;; CHECK: (func $0
;; CHECK-NEXT: ;; code offset: 0x3
;; CHECK-NEXT: (call $0)
;; CHECK-NEXT: )

Loading