diff options
author | Paolo Severini <paolosev@microsoft.com> | 2020-05-27 08:03:46 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-27 08:03:46 -0700 |
commit | a57ff3c61125b890dbd5f4937e6c9ea26c830cfc (patch) | |
tree | b6bf2390b02deba82d9193e10fdc65b37e8af36c /src | |
parent | 25912210b32012bf64359a89baef4514a6b37205 (diff) | |
download | binaryen-a57ff3c61125b890dbd5f4937e6c9ea26c830cfc.tar.gz binaryen-a57ff3c61125b890dbd5f4937e6c9ea26c830cfc.tar.bz2 binaryen-a57ff3c61125b890dbd5f4937e6c9ea26c830cfc.zip |
Fix DWARF location list updating with nonzero compilation unit base addr (#2862)
In the .debug_loc section the Start/End address offsets in a location list are
relative to the address of the compilation unit that refers that location list.
There is a problem in function wasm::Debug:: updateLoc(), which compares these
offsets with the actual module addresses of expressions and functions, causing
the generation of invalid location lists.
The fix is not trivial, because the DWARF debug_loc section does not specify
which is the compilation unit associated to each location list entry.
A simple workaround is to store, in LocationUpdater, a map of location list
offsets to the base address of the compilation units referencing them, and that
can be easily calculated in updateDIE().
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm/wasm-debug.cpp | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/src/wasm/wasm-debug.cpp b/src/wasm/wasm-debug.cpp index 93eb259e9..8ae7497ed 100644 --- a/src/wasm/wasm-debug.cpp +++ b/src/wasm/wasm-debug.cpp @@ -473,6 +473,10 @@ struct LocationUpdater { // Map start of line tables in the debug_line section to their new locations. std::map<BinaryLocation, BinaryLocation> debugLineMap; + // Map offset of location list entries in the debug_loc section to the base + // address of the compilation units referencing them. + std::map<BinaryLocation, BinaryLocation> debugLocToUnitMap; + // TODO: for memory efficiency, we may want to do this in a streaming manner, // binary to binary, without YAML IR. @@ -610,6 +614,10 @@ struct LocationUpdater { BinaryLocation getNewDebugLineLocation(BinaryLocation old) const { return debugLineMap.at(old); } + + BinaryLocation getLocationBaseAddress(BinaryLocation offset) const { + return debugLocToUnitMap.at(offset); + } }; // Update debug lines, and update the locationUpdater with debug line offset @@ -724,10 +732,14 @@ static void iterContextAndYAML(const T& contextList, U& yamlList, W func) { assert(yamlValue == yamlList.end()); } +// Updates a YAML entry from a DWARF DIE. Also updates LocationUpdater +// associating each .debug_loc entry with the base address of its corresponding +// compilation unit. static void updateDIE(const llvm::DWARFDebugInfoEntry& DIE, llvm::DWARFYAML::Entry& yamlEntry, const llvm::DWARFAbbreviationDeclaration* abbrevDecl, - const LocationUpdater& locationUpdater) { + LocationUpdater& locationUpdater, + BinaryLocation compilationUnitBaseAddress) { auto tag = DIE.getTag(); // Pairs of low/high_pc require some special handling, as the high // may be an offset relative to the low. First, process everything but @@ -761,6 +773,11 @@ static void updateDIE(const llvm::DWARFDebugInfoEntry& DIE, // This is an offset into the debug line section. yamlValue.Value = locationUpdater.getNewDebugLineLocation(yamlValue.Value); + } else if (attr == llvm::dwarf::DW_AT_location && + attrSpec.Form == llvm::dwarf::DW_FORM_sec_offset) { + BinaryLocation locOffset = yamlValue.Value; + locationUpdater.debugLocToUnitMap[locOffset] = + compilationUnitBaseAddress; } }); // Next, process the high_pcs. @@ -801,7 +818,7 @@ static void updateDIE(const llvm::DWARFDebugInfoEntry& DIE, static void updateCompileUnits(const BinaryenDWARFInfo& info, llvm::DWARFYAML::Data& yaml, - const LocationUpdater& locationUpdater) { + LocationUpdater& locationUpdater) { // The context has the high-level information we need, and the YAML is where // we write changes. First, iterate over the compile units. iterContextAndYAML( @@ -820,7 +837,13 @@ static void updateCompileUnits(const BinaryenDWARFInfo& info, auto abbrevDecl = DIE.getAbbreviationDeclarationPtr(); if (abbrevDecl) { // This is relevant; look for things to update. - updateDIE(DIE, yamlEntry, abbrevDecl, locationUpdater); + BinaryLocation compilationUnitBaseAddress = + CU->getBaseAddress() ? CU->getBaseAddress()->Address : 0; + updateDIE(DIE, + yamlEntry, + abbrevDecl, + locationUpdater, + compilationUnitBaseAddress); } }); }); @@ -874,9 +897,14 @@ static void updateLoc(llvm::DWARFYAML::Data& yaml, // can't skip since the location description is a variable number of bytes, // so we mark no longer valid addresses as empty. // Locations have an optional base. + bool atStart = true; BinaryLocation base = 0; for (size_t i = 0; i < yaml.Locs.size(); i++) { auto& loc = yaml.Locs[i]; + if (atStart) { + base = locationUpdater.getLocationBaseAddress(loc.CompileUnitOffset); + atStart = false; + } BinaryLocation newStart = loc.Start, newEnd = loc.End; if (newStart == BinaryLocation(-1)) { // This is a new base. @@ -887,6 +915,7 @@ static void updateLoc(llvm::DWARFYAML::Data& yaml, } else if (newStart == 0 && newEnd == 0) { // This is an end marker, this list is done. base = 0; + atStart = true; } else { // This is a normal entry, try to find what it should be updated to. First // de-relativize it to the base to get the absolute address, then look for |