Skip to content

Commit

Permalink
Only call dwfl_attach_state with user-level CPU registers and stack
Browse files Browse the repository at this point in the history
For samples with frame pointer or LBR call chains, we may not have
the CPU registers or stack information available. Under such
circumstances we would spam the command line with repeated warnings
of the form:

```
<pid> failed to attach state Couldn't find architecture of any ELF
```

Prevent that by checking whether the sample has register and stack
information available and only attach dwfl state then.

Note that symbol resolution and inline-frame resolution is independent
of the dwfl_attach_state call - that really is only required for stack
unwinding.

Based on a patch by vtoropov, thanks!

Fixes: KDAB/hotspot#178
Change-Id: I8b88ee5b97d3e9d3ded82a17c4487d01add6d5ca
  • Loading branch information
vtoropov authored and milianw committed Jul 9, 2020
1 parent f85a435 commit 71689f1
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 1 deletion.
3 changes: 2 additions & 1 deletion app/perfdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ enum PerfEventType {

PERF_RECORD_USER_TYPE_START = 64,
PERF_RECORD_HEADER_ATTR = 64,
PERF_RECORD_HEADER_EVENT_TYPE = 65, /* depreceated */
PERF_RECORD_HEADER_EVENT_TYPE = 65, /* deprecated */
PERF_RECORD_HEADER_TRACING_DATA = 66,
PERF_RECORD_HEADER_BUILD_ID = 67,
PERF_RECORD_FINISHED_ROUND = 68,
Expand Down Expand Up @@ -379,6 +379,7 @@ class PerfRecord {
quint32 cpu() const { return m_sampleId.cpu(); }
quint16 size() const { return m_header.size; }
quint16 misc() const { return m_header.misc; }
quint64 type() const { return m_sampleId.sampleType(); }

protected:
PerfRecord(const PerfEventHeader *header, quint64 sampleType, bool sampleIdAll);
Expand Down
10 changes: 10 additions & 0 deletions app/perfsymboltable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,16 @@ Dwfl *PerfSymbolTable::attachDwfl(void *arg)
if (static_cast<pid_t>(m_pid) == dwfl_pid(m_dwfl))
return m_dwfl; // Already attached, nothing to do

// only attach state when we have the required information for stack unwinding
// for normal symbol resolution and inline frame resolution this is not needed
// most notably, this isn't needed for frame pointer callchains
PerfUnwind::UnwindInfo *unwindInfo = static_cast<PerfUnwind::UnwindInfo *>(arg);
const auto sampleType = unwindInfo->sample->type();
const auto hasSampleRegsUser = (sampleType & PerfEventAttributes::SAMPLE_REGS_USER);
const auto hasSampleStackUser = (sampleType & PerfEventAttributes::SAMPLE_STACK_USER);
if (!hasSampleRegsUser || !hasSampleStackUser)
return nullptr;

if (!dwfl_attach_state(m_dwfl, m_firstElf.elf(), m_pid, &threadCallbacks, arg)) {
qWarning() << m_pid << "failed to attach state" << dwfl_errmsg(dwfl_errno());
return nullptr;
Expand Down

0 comments on commit 71689f1

Please sign in to comment.