diff options
-rw-r--r-- | src/wasm.h | 14 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 20 | ||||
-rw-r--r-- | src/wasm/wasm-debug.cpp | 95 | ||||
-rw-r--r-- | test/passes/fib2.bin.txt | 16 |
4 files changed, 104 insertions, 41 deletions
diff --git a/src/wasm.h b/src/wasm.h index f30a24d6b..29844d855 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1205,7 +1205,17 @@ struct BinaryLocations { }; std::unordered_map<Expression*, DelimiterLocations> delimiters; - std::unordered_map<Function*, Span> functions; + // DWARF debug info can refer to multiple interesting positions in a function. + struct FunctionLocations { + // The very start of the function, where the binary has a size LEB. + BinaryLocation start = 0; + // The area where we declare locals, which is right after the size LEB. + BinaryLocation declarations = 0; + // The end, which is one past the final "end" instruction byte. + BinaryLocation end = 0; + }; + + std::unordered_map<Function*, FunctionLocations> functions; }; // Forward declarations of Stack IR, as functions can contain it, see @@ -1265,7 +1275,7 @@ public: std::unordered_map<Expression*, BinaryLocations::Span> expressionLocations; std::unordered_map<Expression*, BinaryLocations::DelimiterLocations> delimiterLocations; - BinaryLocations::Span funcLocation; + BinaryLocations::FunctionLocations funcLocation; size_t getNumParams(); size_t getNumVars(); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index f834666b4..7dc904cd9 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -165,6 +165,7 @@ void WasmBinaryWriter::finishSection(int32_t start) { } for (auto& pair : binaryLocations.functions) { pair.second.start -= totalAdjustment; + pair.second.declarations -= totalAdjustment; pair.second.end -= totalAdjustment; } for (auto& pair : binaryLocations.delimiters) { @@ -304,7 +305,7 @@ void WasmBinaryWriter::writeFunctions() { return; } BYN_TRACE("== writeFunctions\n"); - auto start = startSection(BinaryConsts::Section::Code); + auto sectionStart = startSection(BinaryConsts::Section::Code); o << U32LEB(importInfo->getNumDefinedFunctions()); ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) { assert(binaryLocationTrackedExpressionsForFunc.empty()); @@ -357,15 +358,16 @@ void WasmBinaryWriter::writeFunctions() { } } if (!binaryLocationTrackedExpressionsForFunc.empty()) { - binaryLocations.functions[func] = - BinaryLocations::Span{BinaryLocation(start - adjustmentForLEBShrinking), - BinaryLocation(o.size())}; + binaryLocations.functions[func] = BinaryLocations::FunctionLocations{ + BinaryLocation(sizePos), + BinaryLocation(start - adjustmentForLEBShrinking), + BinaryLocation(o.size())}; } tableOfContents.functionBodies.emplace_back( func->name, sizePos + sizeFieldSize, size); binaryLocationTrackedExpressionsForFunc.clear(); }); - finishSection(start); + finishSection(sectionStart); } void WasmBinaryWriter::writeGlobals() { @@ -1389,6 +1391,7 @@ void WasmBinaryBuilder::readFunctions() { } for (size_t i = 0; i < total; i++) { BYN_TRACE("read one at " << pos << std::endl); + auto sizePos = pos; size_t size = getU32LEB(); if (size == 0) { throwError("empty function size"); @@ -1401,9 +1404,10 @@ void WasmBinaryBuilder::readFunctions() { currFunction = func; if (DWARF) { - func->funcLocation = - BinaryLocations::Span{BinaryLocation(pos - codeSectionLocation), - BinaryLocation(pos - codeSectionLocation + size)}; + func->funcLocation = BinaryLocations::FunctionLocations{ + BinaryLocation(sizePos - codeSectionLocation), + BinaryLocation(pos - codeSectionLocation), + BinaryLocation(pos - codeSectionLocation + size)}; } readNextDebugLocation(); diff --git a/src/wasm/wasm-debug.cpp b/src/wasm/wasm-debug.cpp index aa596aa61..a79f7f9e3 100644 --- a/src/wasm/wasm-debug.cpp +++ b/src/wasm/wasm-debug.cpp @@ -402,33 +402,38 @@ private: } }; -// Represents a mapping of addresses to expressions. Note that we use a single -// map for the start and end addresses, since there is no chance of a function's -// start overlapping with another's end (there is the size LEB in the middle). +// Represents a mapping of addresses to expressions. As with expressions, we +// track both start and end; here, however, "start" means the "start" and +// "declarations" fields in FunctionLocations, and "end" means the two locations +// of one past the end, and one before it which is the "end" opcode that is +// emitted. struct FuncAddrMap { - std::unordered_map<BinaryLocation, Function*> map; + std::unordered_map<BinaryLocation, Function*> startMap, endMap; // Construct the map from the binaryLocations loaded from the wasm. FuncAddrMap(const Module& wasm) { for (auto& func : wasm.functions) { - map[func->funcLocation.start] = func.get(); - map[func->funcLocation.end] = func.get(); + startMap[func->funcLocation.start] = func.get(); + startMap[func->funcLocation.declarations] = func.get(); + endMap[func->funcLocation.end - 1] = func.get(); + endMap[func->funcLocation.end] = func.get(); } } - Function* get(BinaryLocation addr) const { - auto iter = map.find(addr); - if (iter != map.end()) { + Function* getStart(BinaryLocation addr) const { + auto iter = startMap.find(addr); + if (iter != startMap.end()) { return iter->second; } return nullptr; } - void dump() const { - std::cout << " (size: " << map.size() << ")\n"; - for (auto pair : map) { - std::cout << " " << pair.first << " => " << pair.second->name << '\n'; + Function* getEnd(BinaryLocation addr) const { + auto iter = endMap.find(addr); + if (iter != endMap.end()) { + return iter->second; } + return nullptr; } }; @@ -484,25 +489,59 @@ struct LocationUpdater { return 0; } - BinaryLocation getNewFuncAddr(BinaryLocation oldAddr) const { - if (auto* func = oldFuncAddrMap.get(oldAddr)) { + BinaryLocation getNewFuncStartAddr(BinaryLocation oldAddr) const { + if (auto* func = oldFuncAddrMap.getStart(oldAddr)) { // The function might have been optimized away, check. auto iter = newLocations.functions.find(func); if (iter != newLocations.functions.end()) { - auto oldSpan = func->funcLocation; - auto newSpan = iter->second; - if (oldAddr == oldSpan.start) { - return newSpan.start; - } else if (oldAddr == oldSpan.end) { - return newSpan.end; + auto oldLocations = func->funcLocation; + auto newLocations = iter->second; + if (oldAddr == oldLocations.start) { + return newLocations.start; + } else if (oldAddr == oldLocations.declarations) { + return newLocations.declarations; + } else { + WASM_UNREACHABLE("invalid func start"); } } } return 0; } - bool hasOldFuncAddr(BinaryLocation oldAddr) const { - return oldFuncAddrMap.get(oldAddr); + bool hasOldFuncStartAddr(BinaryLocation oldAddr) const { + return oldFuncAddrMap.getStart(oldAddr); + } + + BinaryLocation getNewFuncEndAddr(BinaryLocation oldAddr) const { + if (auto* func = oldFuncAddrMap.getEnd(oldAddr)) { + // The function might have been optimized away, check. + auto iter = newLocations.functions.find(func); + if (iter != newLocations.functions.end()) { + auto oldLocations = func->funcLocation; + auto newLocations = iter->second; + if (oldAddr == oldLocations.end) { + return newLocations.end; + } else if (oldAddr == oldLocations.end - 1) { + return newLocations.end - 1; + } else { + WASM_UNREACHABLE("invalid func end"); + } + } + } + return 0; + } + + // Check for either the end opcode, or one past the end. + bool hasOldFuncEndAddr(BinaryLocation oldAddr) const { + return oldFuncAddrMap.getEnd(oldAddr); + } + + // Check specifically for the end opcode. + bool hasOldFuncEndOpcodeAddr(BinaryLocation oldAddr) const { + if (auto* func = oldFuncAddrMap.getEnd(oldAddr)) { + return oldAddr == func->funcLocation.end - 1; + } + return false; } BinaryLocation getNewExtraAddr(BinaryLocation oldAddr) const { @@ -552,8 +591,10 @@ static void updateDebugLines(llvm::DWARFYAML::Data& data, BinaryLocation newAddr = 0; if (locationUpdater.hasOldExprAddr(oldAddr)) { newAddr = locationUpdater.getNewExprAddr(oldAddr); - } else if (locationUpdater.hasOldFuncAddr(oldAddr)) { - newAddr = locationUpdater.getNewFuncAddr(oldAddr); + } else if (locationUpdater.hasOldFuncStartAddr(oldAddr)) { + newAddr = locationUpdater.getNewFuncStartAddr(oldAddr); + } else if (locationUpdater.hasOldFuncEndAddr(oldAddr)) { + newAddr = locationUpdater.getNewFuncEndAddr(oldAddr); } else if (locationUpdater.hasOldExtraAddr(oldAddr)) { newAddr = locationUpdater.getNewExtraAddr(oldAddr); } @@ -631,7 +672,7 @@ static void updateDIE(const llvm::DWARFDebugInfoEntry& DIE, newValue = locationUpdater.getNewExprAddr(oldValue); } else if (tag == llvm::dwarf::DW_TAG_compile_unit || tag == llvm::dwarf::DW_TAG_subprogram) { - newValue = locationUpdater.getNewFuncAddr(oldValue); + newValue = locationUpdater.getNewFuncStartAddr(oldValue); } else { Fatal() << "unknown tag with low_pc " << llvm::dwarf::TagString(tag).str(); @@ -664,7 +705,7 @@ static void updateDIE(const llvm::DWARFDebugInfoEntry& DIE, newValue = locationUpdater.getNewExprEndAddr(oldValue); } else if (tag == llvm::dwarf::DW_TAG_compile_unit || tag == llvm::dwarf::DW_TAG_subprogram) { - newValue = locationUpdater.getNewFuncAddr(oldValue); + newValue = locationUpdater.getNewFuncEndAddr(oldValue); } else { Fatal() << "unknown tag with low_pc " << llvm::dwarf::TagString(tag).str(); diff --git a/test/passes/fib2.bin.txt b/test/passes/fib2.bin.txt index 75c58a3d0..e95044c0f 100644 --- a/test/passes/fib2.bin.txt +++ b/test/passes/fib2.bin.txt @@ -305,7 +305,7 @@ Contains section .debug_info (168 bytes) Contains section .debug_loc (143 bytes) Contains section .debug_ranges (24 bytes) Contains section .debug_abbrev (131 bytes) -Contains section .debug_line (194 bytes) +Contains section .debug_line (210 bytes) Contains section .debug_str (180 bytes) .debug_abbrev contents: @@ -484,7 +484,7 @@ Abbrev table for offset: 0x00000000 .debug_line contents: debug_line[0x00000000] Line table prologue: - total_length: 0x000000be + total_length: 0x000000ce version: 4 prologue_length: 0x0000001e min_inst_length: 1 @@ -576,12 +576,20 @@ file_names[ 1]: 0x000000af: 00 DW_LNE_end_sequence 0x0000000000000041 12 10 1 0 0 is_stmt end_sequence -0x000000b2: 00 DW_LNE_set_address (0x0000000000000044) +0x000000b2: 00 DW_LNE_set_address (0x0000000000000043) 0x000000b9: 03 DW_LNS_advance_line (12) 0x000000bb: 05 DW_LNS_set_column (3) 0x000000bd: 06 DW_LNS_negate_stmt 0x000000be: 0a DW_LNS_set_prologue_end 0x000000bf: 00 DW_LNE_end_sequence + 0x0000000000000043 12 3 1 0 0 end_sequence + +0x000000c2: 00 DW_LNE_set_address (0x0000000000000044) +0x000000c9: 03 DW_LNS_advance_line (12) +0x000000cb: 05 DW_LNS_set_column (3) +0x000000cd: 06 DW_LNS_negate_stmt +0x000000ce: 0a DW_LNS_set_prologue_end +0x000000cf: 00 DW_LNE_end_sequence 0x0000000000000044 12 3 1 0 0 end_sequence @@ -706,7 +714,7 @@ file_names[ 1]: ;; custom section ".debug_loc", size 143 ;; custom section ".debug_ranges", size 24 ;; custom section ".debug_abbrev", size 131 - ;; custom section ".debug_line", size 194 + ;; custom section ".debug_line", size 210 ;; custom section ".debug_str", size 180 ;; custom section "producers", size 127 ) |