summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2018-01-25 11:29:22 +0100
committerUlf Hermann <ulf.hermann@qt.io>2018-01-25 12:11:15 +0000
commitdf0d8d59bb1b78c169822c244ddccbb046945dd9 (patch)
treee5ff77fdcc3d3a2964abeb9167a2eacfba24e07f
parentc7a2d7623825ec0d514dabb44c4729f79ac5ab6c (diff)
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 <milian.wolff@kdab.com>
-rw-r--r--app/perfsymboltable.cpp11
1 files changed, 10 insertions, 1 deletions
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;
}