diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2018-06-19 14:57:05 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2018-06-20 11:16:02 +0000 |
commit | 42b4d2752cffdb9cf2e395788f979fa35b07f9af (patch) | |
tree | 81a605840749ce5081a94c555fb1d2d4192c16cc | |
parent | b9a998065902d3364c7132bc0cdd48718e6d4ef8 (diff) |
If dwfl_module_getsrc fails, iterate CUs to find source file/linev4.7.2v4.7.1v4.7.0-rc1v4.7.04.7
Some ELF objects have .debug_info and .debug_line sections, but no
.debug_aranges. dwfl_module_getsrc doesn't like this and gives up. We
can, however, do better. The information is all there, we just need to
get hold of the right CU. The iteration is expensive, but as we cache
the resulting locations, it's tolerable.
In case there is no .debug_info at all, this won't iterate, as the Dwarf
object won't be found in the first place.
Task-number: QTCREATORBUG-20441
Change-Id: I9846397d1e930ba5f25ccfa9748542a198f0f2a4
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r-- | app/perfsymboltable.cpp | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/app/perfsymboltable.cpp b/app/perfsymboltable.cpp index 986a463..0b217bb 100644 --- a/app/perfsymboltable.cpp +++ b/app/perfsymboltable.cpp @@ -608,6 +608,32 @@ int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel, const QByteArray file = dwfl_lineinfo(srcLine, nullptr, &addressLocation.line, &addressLocation.column, nullptr, nullptr); addressLocation.file = m_unwind->resolveString(file); + } else { + Dwarf_Addr bias = 0; + if (Dwarf *dwarf = dwfl_module_getdwarf(mod, &bias)) { + const quint64 adjusted = addressLocation.address - bias; + size_t headerSize = 0; + Dwarf_Off nextOffset = 0; + for (Dwarf_Off offset = 0; + dwarf_nextcu(dwarf, offset, &nextOffset, &headerSize, + nullptr, nullptr, nullptr) == 0; + offset = nextOffset) { + Dwarf_Die cudieMemory; + Dwarf_Die *cudie = dwarf_offdie(dwarf, offset + headerSize, &cudieMemory); + + if (!cudie || !dwarf_haspc(cudie, adjusted)) + continue; + + if (Dwarf_Line *line = dwarf_getsrc_die(cudie, adjusted)) { + const QByteArray file = dwarf_linesrc(line, nullptr, nullptr); + addressLocation.file = m_unwind->resolveString(file); + dwarf_lineno(line, &addressLocation.line); + dwarf_linecol(line, &addressLocation.column); + } + + break; + } + } } if (off == addressLocation.address) {// no symbol found |