diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2018-05-17 13:10:05 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2018-05-17 13:21:33 +0000 |
commit | 01b4d7d8c98a13df10ce22dd86188806b99205f3 (patch) | |
tree | 501700a189879e7ac5402dd492e840ac677c0401 | |
parent | 9f43fc9b48535a9204c17fabf9e542dcd1052ccf (diff) |
Don't repeatedly report unsuitable modules for an address
dwfl may disagree with our mmap events about the length of a module. If
dwfl considers the module to be shorter, the address we are looking for
may fall in an area that's not covered by the reported module. In that
case we should not try to report the same module again the next time we
catch this address. We already know that it doesn't fit, after all.
Task-number: QTCREATORBUG-20427
Change-Id: I852dd39f0a53fe7bc1bde149efa3541d0fc7b8ba
Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
-rw-r--r-- | app/perfelfmap.cpp | 15 | ||||
-rw-r--r-- | app/perfelfmap.h | 4 | ||||
-rw-r--r-- | app/perfsymboltable.cpp | 7 |
3 files changed, 23 insertions, 3 deletions
diff --git a/app/perfelfmap.cpp b/app/perfelfmap.cpp index 3e0a6b4..6ba72ba 100644 --- a/app/perfelfmap.cpp +++ b/app/perfelfmap.cpp @@ -114,7 +114,20 @@ PerfElfMap::ElfInfo PerfElfMap::findElf(quint64 ip) const return ElfInfo(); } - return (i->addr + i->length > ip) ? *i : ElfInfo(); + if (i->dwflStart < i->dwflEnd) + return (i->dwflStart <= ip && i->dwflEnd > ip) ? *i : ElfInfo(); + else + return (i->addr + i->length > ip) ? *i : ElfInfo(); +} + +void PerfElfMap::updateElf(quint64 addr, quint64 dwflStart, quint64 dwflEnd) +{ + auto i = std::upper_bound(m_elfs.begin(), m_elfs.end(), addr, SortByAddr()); + Q_ASSERT(i != m_elfs.begin()); + --i; + Q_ASSERT(i->addr == addr); + i->dwflStart = dwflStart; + i->dwflEnd = dwflEnd; } bool PerfElfMap::isAddressInRange(quint64 addr) const diff --git a/app/perfelfmap.h b/app/perfelfmap.h index a9af9f9..2396046 100644 --- a/app/perfelfmap.h +++ b/app/perfelfmap.h @@ -68,6 +68,9 @@ public: quint64 addr; quint64 length; quint64 pgoff; + + quint64 dwflStart = 0; + quint64 dwflEnd = 0; }; bool registerElf(quint64 addr, quint64 len, quint64 pgoff, @@ -75,6 +78,7 @@ public: const QByteArray &originalFileName = {}, const QByteArray &originalPath = {}); ElfInfo findElf(quint64 ip) const; + void updateElf(quint64 addr, quint64 dwflStart, quint64 dwflEnd); bool isEmpty() const { diff --git a/app/perfsymboltable.cpp b/app/perfsymboltable.cpp index 2cc7107..644e947 100644 --- a/app/perfsymboltable.cpp +++ b/app/perfsymboltable.cpp @@ -486,9 +486,12 @@ Dwfl_Module *PerfSymbolTable::reportElf(const PerfElfMap::ElfInfo& info) } else { // set symbol table as user data, cf. find_debuginfo callback in perfunwind.cpp void** userData; - dwfl_module_info(ret, &userData, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr); + Dwarf_Addr start = 0; + Dwarf_Addr end = 0; + + dwfl_module_info(ret, &userData, &start, &end, nullptr, nullptr, nullptr, nullptr); *userData = this; + m_elfs.updateElf(info.addr, start, end); } const int reportEnd = dwfl_report_end(m_dwfl, NULL, NULL); Q_ASSERT(reportEnd == 0); |