From df0d8d59bb1b78c169822c244ddccbb046945dd9 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 25 Jan 2018 11:29:22 +0100 Subject: Use dwfl_report_begin/_end correctly The documentation states that you cannot use dwfl until dwfl_report_end returns 0. In fact you can, but then you run into strange corner cases where dwfl doesn't find certain modules that have been reported before. So far it was assumed that we cannot report additional modules while unwinding a stack, but in fact I don't see a reason why. So, whenever we want to report an additional module we call dwfl_report_begin_add before and dwfl_report_end afterwards. In addition, to make our dwfl initially usable we do one round of dwfl_report_begin and dwfl_report_end when creating it, and we have to change the order of begin and end on clear because the usual state of the dwfl is now "closed for reporting". Change-Id: I7468204c8f48a8a0c8f68f78e81f5c4aeb8fb8d4 Reviewed-by: Milian Wolff --- app/perfsymboltable.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/perfsymboltable.cpp b/app/perfsymboltable.cpp index 3a1b451..8787b73 100644 --- a/app/perfsymboltable.cpp +++ b/app/perfsymboltable.cpp @@ -75,6 +75,11 @@ PerfSymbolTable::PerfSymbolTable(qint32 pid, Dwfl_Callbacks *callbacks, PerfUnwi m_pid(pid) { m_dwfl = dwfl_begin(m_callbacks); + dwfl_report_begin(m_dwfl); + + // "DWFL can not be used until this function returns 0" + const int reportEnd = dwfl_report_end(m_dwfl, NULL, NULL); + Q_ASSERT(reportEnd == 0); } PerfSymbolTable::~PerfSymbolTable() @@ -484,6 +489,7 @@ Dwfl_Module *PerfSymbolTable::reportElf(const PerfElfMap::ElfInfo& info) return nullptr; } + dwfl_report_begin_add(m_dwfl); Dwfl_Module *ret = dwfl_report_elf( m_dwfl, info.originalFileName.constData(), info.localFile.absoluteFilePath().toLocal8Bit().constData(), -1, info.addr, @@ -498,6 +504,8 @@ Dwfl_Module *PerfSymbolTable::reportElf(const PerfElfMap::ElfInfo& info) nullptr, nullptr); *userData = this; } + const int reportEnd = dwfl_report_end(m_dwfl, NULL, NULL); + Q_ASSERT(reportEnd == 0); return ret; } @@ -756,8 +764,9 @@ void PerfSymbolTable::clearCache() m_perfMapFile.reset(); // Throw out the dwfl state - dwfl_report_end(m_dwfl, NULL, NULL); dwfl_report_begin(m_dwfl); + const int reportEnd = dwfl_report_end(m_dwfl, NULL, NULL); + Q_ASSERT(reportEnd == 0); m_cacheIsDirty = false; } -- cgit v1.2.3