1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#ifndef PERFSYMBOLTABLE_H
#define PERFSYMBOLTABLE_H
#include "perfdata.h"
#include "perfunwind.h"
#include "perfelfmap.h"
#include <libdwfl.h>
#include <QObject>
class PerfSymbolTable
{
public:
PerfSymbolTable(quint32 pid, Dwfl_Callbacks *callbacks, PerfUnwind *parent);
~PerfSymbolTable();
struct PerfMapSymbol {
PerfMapSymbol(quint64 start = 0, quint64 length = 0, QByteArray name = QByteArray()) :
start(start), length(length), name(name) {}
quint64 start;
quint64 length;
QByteArray name;
};
struct DieAndLocation {
Dwarf_Die die;
int locationId;
};
// Announce an mmap. Invalidate the symbol and address cache and clear the dwfl if it overlaps
// with an existing one.
void registerElf(const PerfRecordMmap &mmap, const QString &appPath,
const QString &systemRoot, const QString &extraLibsPath);
PerfElfMap::ElfInfo findElf(quint64 ip, quint64 timestamp) const;
// Report an mmap to dwfl and parse it for symbols and inlines, or simply return it if dwfl has
// it already
Dwfl_Module *reportElf(const PerfElfMap::ElfInfo& elf);
// Look up a frame and all its inline parents and append them to the given vector.
// If the frame hits an elf that hasn't been reported, yet, report it.
int lookupFrame(Dwarf_Addr ip, quint64 timestamp, bool isKernel, bool *isInterworking);
void updatePerfMap();
bool containsAddress(quint64 address) const;
Dwfl *attachDwfl(quint64 timestamp, void *arg);
void clearCache();
private:
struct AddressCacheEntry {
int locationId;
bool isInterworking;
};
QFile m_perfMapFile;
QVector<PerfMapSymbol> m_perfMap;
QHash<Dwarf_Addr, AddressCacheEntry> m_addressCache;
PerfUnwind *m_unwind;
Dwfl *m_dwfl;
quint64 m_lastMmapAddedTime;
PerfElfMap m_elfs;
Dwfl_Callbacks *m_callbacks;
quint32 m_pid;
QByteArray symbolFromPerfMap(quint64 ip, GElf_Off *offset) const;
int parseDie(Dwarf_Die *top, qint32 binaryId, Dwarf_Files *files, Dwarf_Addr entry,
bool isKernel, const QStack<DieAndLocation> &stack);
int insertSubprogram(Dwarf_Die *top, Dwarf_Addr entry, qint32 binaryId,
qint32 inlineParent, bool isKernel);
void parseDwarf(Dwarf_Die *cudie, Dwarf_Addr bias, qint32 binaryId, bool isKernel);
};
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(PerfSymbolTable::PerfMapSymbol, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(PerfSymbolTable::DieAndLocation, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
#endif // PERFSYMBOLTABLE_H
|