1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
6 **
7 ** This file is part of the Qt Enterprise Perf Profiler Add-on.
8 **
9 ** GNU General Public License Usage
10 ** This file may be used under the terms of the GNU General Public License
11 ** version 3 as published by the Free Software Foundation and appearing in
12 ** the file LICENSE.GPLv3 included in the packaging of this file. Please
13 ** review the following information to ensure the GNU General Public License
14 ** requirements will be met: https://www.gnu.org/licenses/gpl.html.
15 **
16 ** If you have questions regarding the use of this file, please use
17 ** contact form at http://www.qt.io/contact-us
18 **
19 ****************************************************************************/
20 
21 #pragma once
22 
23 #include "perfattributes.h"
24 #include "perffeatures.h"
25 #include "perfheader.h"
26 
27 #include <QIODevice>
28 
29 #ifdef HAVE_ZSTD
30 #include <zstd.h>
31 
32 constexpr bool CAN_DECOMPRESS_ZSTD = true;
33 #else
34 constexpr bool CAN_DECOMPRESS_ZSTD = false;
35 #endif
36 
37 enum PerfEventType {
38 
39     /*
40      * If perf_event_attr.sample_id_all is set then all event types will
41      * have the sample_type selected fields related to where/when
42      * (identity) an event took place (TID, TIME, ID, STREAM_ID, CPU,
43      * IDENTIFIER) described in PERF_RECORD_SAMPLE below, it will be stashed
44      * just after the perf_event_header and the fields already present for
45      * the existing fields, i.e. at the end of the payload. That way a newer
46      * perf.data file will be supported by older perf tools, with these new
47      * optional fields being ignored.
48      *
49      * struct sample_id {
50      *    { u32           pid, tid; } && PERF_SAMPLE_TID
51      *    { u64           time;     } && PERF_SAMPLE_TIME
52      *    { u64           id;       } && PERF_SAMPLE_ID
53      *    { u64           stream_id;} && PERF_SAMPLE_STREAM_ID
54      *    { u32           cpu, res; } && PERF_SAMPLE_CPU
55      *    { u64           id;       } && PERF_SAMPLE_IDENTIFIER
56      * } && perf_event_attr::sample_id_all
57      *
58      * Note that PERF_SAMPLE_IDENTIFIER duplicates PERF_SAMPLE_ID.  The
59      * advantage of PERF_SAMPLE_IDENTIFIER is that its position is fixed
60      * relative to header.size.
61      */
62 
63     /*
64      * The MMAP events record the PROT_EXEC mappings so that we can
65      * correlate userspace IPs to code. They have the following structure:
66      *
67      * struct {
68      *    struct perf_event_header    header;
69      *
70      *    u32                pid, tid;
71      *    u64                addr;
72      *    u64                len;
73      *    u64                pgoff;
74      *    char               filename[];
75      *    struct sample_id   sample_id;
76      * };
77      */
78     PERF_RECORD_MMAP              = 1,
79 
80     /*
81      * struct {
82      *    struct perf_event_header    header;
83      *    u64                id;
84      *    u64                lost;
85      *    struct sample_id   sample_id;
86      * };
87      */
88     PERF_RECORD_LOST              = 2,
89 
90     /*
91      * struct {
92      *    struct perf_event_header    header;
93      *
94      *    u32                pid, tid;
95      *    char               comm[];
96      *    struct sample_id   sample_id;
97      * };
98      */
99     PERF_RECORD_COMM              = 3,
100 
101     /*
102      * struct {
103      *    struct perf_event_header    header;
104      *    u32                pid, ppid;
105      *    u32                tid, ptid;
106      *    u64                time;
107      *    struct sample_id   sample_id;
108      * };
109      */
110     PERF_RECORD_EXIT              = 4,
111 
112     /*
113      * struct {
114      *    struct perf_event_header    header;
115      *    u64                time;
116      *    u64                id;
117      *    u64                stream_id;
118      *    struct sample_id   sample_id;
119      * };
120      */
121     PERF_RECORD_THROTTLE          = 5,
122     PERF_RECORD_UNTHROTTLE        = 6,
123 
124     /*
125      * struct {
126      *    struct perf_event_header    header;
127      *    u32                pid, ppid;
128      *    u32                tid, ptid;
129      *    u64                time;
130      *    struct sample_id   sample_id;
131      * };
132      */
133     PERF_RECORD_FORK              = 7,
134 
135     /*
136      * struct {
137      *    struct perf_event_header    header;
138      *    u32                pid, tid;
139      *
140      *    struct read_format values;
141      *    struct sample_id   sample_id;
142      * };
143      */
144     PERF_RECORD_READ              = 8,
145 
146     /*
147      * struct {
148      *    struct perf_event_header    header;
149      *
150      *    #
151      *    # Note that PERF_SAMPLE_IDENTIFIER duplicates PERF_SAMPLE_ID.
152      *    # The advantage of PERF_SAMPLE_IDENTIFIER is that its position
153      *    # is fixed relative to header.
154      *    #
155      *
156      *    { u64            id;        } && PERF_SAMPLE_IDENTIFIER
157      *    { u64            ip;        } && PERF_SAMPLE_IP
158      *    { u32            pid, tid;  } && PERF_SAMPLE_TID
159      *    { u64            time;      } && PERF_SAMPLE_TIME
160      *    { u64            addr;      } && PERF_SAMPLE_ADDR
161      *    { u64            id;        } && PERF_SAMPLE_ID
162      *    { u64            stream_id; } && PERF_SAMPLE_STREAM_ID
163      *    { u32            cpu, res;  } && PERF_SAMPLE_CPU
164      *    { u64            period;    } && PERF_SAMPLE_PERIOD
165      *
166      *    { struct read_format values;} && PERF_SAMPLE_READ
167      *
168      *    { u64            nr,
169      *      u64            ips[nr];   } && PERF_SAMPLE_CALLCHAIN
170      *
171      *    #
172      *    # The RAW record below is opaque data wrt the ABI
173      *    #
174      *    # That is, the ABI doesn't make any promises wrt to
175      *    # the stability of its content, it may vary depending
176      *    # on event, hardware, kernel version and phase of
177      *    # the moon.
178      *    #
179      *    # In other words, PERF_SAMPLE_RAW contents are not an ABI.
180      *    #
181      *
182      *    { u32            size;
183      *      char           data[size];} && PERF_SAMPLE_RAW
184      *
185      *    { u64                   nr;
186      *      { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK
187      *
188      *    { u64            abi; # enum perf_sample_regs_abi
189      *      u64            regs[weight(mask)]; } && PERF_SAMPLE_REGS_USER
190      *
191      *    { u64            size;
192      *      char           data[size];
193      *      u64            dyn_size;    } && PERF_SAMPLE_STACK_USER
194      *
195      *    { u64            weight;      } && PERF_SAMPLE_WEIGHT
196      *    { u64            data_src;    } && PERF_SAMPLE_DATA_SRC
197      *    { u64            transaction; } && PERF_SAMPLE_TRANSACTION
198      * };
199      */
200     PERF_RECORD_SAMPLE            = 9,
201 
202     /*
203      * The MMAP2 records are an augmented version of MMAP, they add
204      * maj, min, ino numbers to be used to uniquely identify each mapping
205      *
206      * struct {
207      *    struct perf_event_header    header;
208      *
209      *    u32                pid, tid;
210      *    u64                addr;
211      *    u64                len;
212      *    u64                pgoff;
213      *    u32                maj;
214      *    u32                min;
215      *    u64                ino;
216      *    u64                ino_generation;
217      *    u32                prot, flags;
218      *    char               filename[];
219      *    struct sample_id   sample_id;
220      * };
221      */
222     PERF_RECORD_MMAP2             = 10,
223 
224     /*
225      * Records a context switch in or out (flagged by
226      * PERF_RECORD_MISC_SWITCH_OUT). See also
227      * PERF_RECORD_SWITCH_CPU_WIDE.
228      *
229      * struct {
230      *    struct perf_event_header header;
231      *    struct sample_id         sample_id;
232      * };
233      */
234     PERF_RECORD_SWITCH            = 14,
235 
236     /*
237      * CPU-wide version of PERF_RECORD_SWITCH with next_prev_pid and
238      * next_prev_tid that are the next (switching out) or previous
239      * (switching in) pid/tid.
240      *
241      * struct {
242      *    struct perf_event_header    header;
243      *    u32                next_prev_pid;
244      *    u32                next_prev_tid;
245      *    struct sample_id        sample_id;
246      * };
247      */
248     PERF_RECORD_SWITCH_CPU_WIDE        = 15,
249 
250     /*
251      * struct {
252      *    struct perf_event_header    header;
253      *    u32                pid;
254      *    u32                tid;
255      *    u64                nr_namespaces;
256      *    { u64                dev, inode; } [nr_namespaces];
257      *    struct sample_id        sample_id;
258      * };
259      */
260     PERF_RECORD_NAMESPACES            = 16,
261 
262     /*
263      * Record ksymbol register/unregister events:
264      *
265      * struct {
266      *    struct perf_event_header    header;
267      *    u64                addr;
268      *    u32                len;
269      *    u16                ksym_type;
270      *    u16                flags;
271      *    char                name[];
272      *    struct sample_id        sample_id;
273      * };
274      */
275     PERF_RECORD_KSYMBOL            = 17,
276 
277     /*
278      * Record bpf events:
279      *  enum perf_bpf_event_type {
280      *    PERF_BPF_EVENT_UNKNOWN        = 0,
281      *    PERF_BPF_EVENT_PROG_LOAD    = 1,
282      *    PERF_BPF_EVENT_PROG_UNLOAD    = 2,
283      *  };
284      *
285      * struct {
286      *    struct perf_event_header    header;
287      *    u16                type;
288      *    u16                flags;
289      *    u32                id;
290      *    u8                tag[BPF_TAG_SIZE];
291      *    struct sample_id        sample_id;
292      * };
293      */
294     PERF_RECORD_BPF_EVENT            = 18,
295 
296     /*
297      * struct {
298      *    struct perf_event_header    header;
299      *    u64                id;
300      *    char                path[];
301      *    struct sample_id        sample_id;
302      * };
303      */
304     PERF_RECORD_CGROUP              = 19,
305 
306     PERF_RECORD_MAX,            /* non-ABI */
307 
308     PERF_RECORD_USER_TYPE_START     = 64,
309     PERF_RECORD_HEADER_ATTR         = 64,
310     PERF_RECORD_HEADER_EVENT_TYPE   = 65, /* deprecated */
311     PERF_RECORD_HEADER_TRACING_DATA = 66,
312     PERF_RECORD_HEADER_BUILD_ID     = 67,
313     PERF_RECORD_FINISHED_ROUND      = 68,
314     PERF_RECORD_ID_INDEX            = 69,
315     PERF_RECORD_AUXTRACE_INFO       = 70,
316     PERF_RECORD_AUXTRACE            = 71,
317     PERF_RECORD_AUXTRACE_ERROR      = 72,
318     PERF_RECORD_THREAD_MAP          = 73,
319     PERF_RECORD_CPU_MAP             = 74,
320     PERF_RECORD_STAT_CONFIG         = 75,
321     PERF_RECORD_STAT                = 76,
322     PERF_RECORD_STAT_ROUND          = 77,
323     PERF_RECORD_EVENT_UPDATE        = 78,
324     PERF_RECORD_TIME_CONV           = 79,
325     PERF_RECORD_HEADER_FEATURE      = 80,
326     PERF_RECORD_COMPRESSED          = 81,
327     PERF_RECORD_HEADER_MAX
328 };
329 
330 enum PERF_RECORD_MISC {
331     PERF_RECORD_MISC_SWITCH_OUT = (1 << 13),
332 };
333 
334 class PerfRecordSample;
335 
336 // Use first attribute for deciding if this is present, not the header!
337 // Why the first?!? idiots ... => encoded in sampleType via sampleIdAll
338 struct PerfSampleId {
339     PerfSampleId(quint64 sampleType = 0, bool sampleIdAll = false) : m_pid(0), m_tid(0), m_time(0),
340         m_id(0), m_streamId(0), m_cpu(0), m_res(0),
341         m_sampleType(sampleType
342                      | (sampleIdAll ? static_cast<quint64>(PerfEventAttributes::SAMPLE_ID_ALL) : 0))
343     {}
344 
pidPerfSampleId345     qint32 pid() const { return m_pid; }
tidPerfSampleId346     qint32 tid() const { return m_tid; }
timePerfSampleId347     quint64 time() const { return m_time; }
idPerfSampleId348     quint64 id() const { return m_id; }
349     quint16 fixedLength() const;
sampleTypePerfSampleId350     quint64 sampleType() const { return m_sampleType; }
cpuPerfSampleId351     quint32 cpu() const { return m_cpu; }
352 
353 private:
354     qint32 m_pid;
355     qint32 m_tid;
356     quint64 m_time;
357     quint64 m_id;
358     quint64 m_streamId;
359     quint32 m_cpu;
360     quint32 m_res;
361 
362     union {
363         quint64 m_ignoredDuplicateId; // In the file format this is the same as id above
364         quint64 m_sampleType; // As the id is ignored we can reuse the space for saving the flags
365     };
366 
367     friend QDataStream &operator>>(QDataStream &stream, PerfSampleId &sampleId);
368     friend QDataStream &operator>>(QDataStream &stream, PerfRecordSample &record);
369 };
370 
371 QDataStream &operator>>(QDataStream &stream, PerfSampleId &sampleId);
372 
373 class PerfRecord {
374 public:
pid()375     qint32 pid() const { return m_sampleId.pid(); }
tid()376     qint32 tid() const { return m_sampleId.tid(); }
time()377     quint64 time() const { return m_sampleId.time(); }
id()378     quint64 id() const { return m_sampleId.id(); }
cpu()379     quint32 cpu() const { return m_sampleId.cpu(); }
size()380     quint16 size() const { return m_header.size; }
misc()381     quint16 misc() const { return m_header.misc; }
type()382     quint64 type() const { return m_sampleId.sampleType(); }
383 
384 protected:
385     PerfRecord(const PerfEventHeader *header, quint64 sampleType, bool sampleIdAll);
386     PerfEventHeader m_header;
387     PerfSampleId m_sampleId;
388 
fixedLength()389     quint16 fixedLength() const { return m_header.fixedLength() + m_sampleId.fixedLength(); }
390 };
391 
392 class PerfRecordMmap2;
393 class PerfRecordMmap : public PerfRecord {
394 public:
395     PerfRecordMmap(PerfEventHeader *header = nullptr, quint64 sampleType = 0,
396                    bool sampleIdAll = false);
397 
398     // The pids and tids in the sampleId are always 0 in this case. Go figure ...
pid()399     qint32 pid() const { return m_pid; }
tid()400     qint32 tid() const { return m_tid; }
401 
addr()402     quint64 addr() const { return m_addr; }
len()403     quint64 len() const { return m_len; }
pgoff()404     quint64 pgoff() const { return m_pgoff; }
filename()405     const QByteArray &filename() const { return m_filename; }
406 
407 protected:
408     QDataStream &readNumbers(QDataStream &stream);
409     QDataStream &readFilename(QDataStream &stream, quint16 filenameLength);
410     QDataStream &readSampleId(QDataStream &stream);
411     quint16 fixedLength() const;
412 
413 private:
414     qint32 m_pid;
415     qint32 m_tid;
416     quint64 m_addr;
417     quint64 m_len;
418     quint64 m_pgoff;
419     QByteArray m_filename;
420 
421     friend QDataStream &operator>>(QDataStream &stream, PerfRecordMmap &record);
422     friend QDataStream &operator>>(QDataStream &stream, PerfRecordMmap2 &record);
423 };
424 
425 QDataStream &operator>>(QDataStream &stream, PerfRecordMmap &record);
426 
427 class PerfRecordMmap2 : public PerfRecordMmap
428 {
429 public:
430     PerfRecordMmap2(PerfEventHeader *header = nullptr, quint64 sampleType = 0,
431                     bool sampleIdAll = false);
432 
prot()433     quint32 prot() const { return m_prot; }
434 
435 protected:
436     QDataStream &readNumbers(QDataStream &stream);
437 
438 private:
439     quint32 m_maj;
440     quint32 m_min;
441     quint64 m_ino;
442     quint64 m_ino_generation;
443     quint32 m_prot;
444     quint32 m_flags;
445 
446     quint16 fixedLength() const;
447 
448     friend QDataStream &operator>>(QDataStream &stream, PerfRecordMmap2 &record);
449 };
450 
451 QDataStream &operator>>(QDataStream &stream, PerfRecordMmap2 &record);
452 
453 class PerfRecordLost : public PerfRecord {
454 public:
455     PerfRecordLost(PerfEventHeader *header = nullptr, quint64 sampleType = 0,
456                    bool sampleIdAll = false);
457 
lost()458     quint64 lost() const { return m_lost; }
459 private:
460     quint64 m_id;
461     quint64 m_lost;
462 
463     friend QDataStream &operator>>(QDataStream &stream, PerfRecordLost &record);
464 };
465 
466 QDataStream &operator>>(QDataStream &stream, PerfRecordLost &record);
467 
468 class PerfRecordComm : public PerfRecord {
469 public:
470     PerfRecordComm(PerfEventHeader *header = nullptr, quint64 sampleType = 0,
471                    bool sampleIdAll = false);
comm()472     const QByteArray &comm() const { return m_comm; }
473 
474     // The pids and tids in the sampleId are always 0 in this case. Go figure ...
pid()475     qint32 pid() const { return m_pid; }
tid()476     qint32 tid() const { return m_tid; }
477 
478 private:
479     qint32 m_pid;
480     qint32 m_tid;
481     QByteArray m_comm;
482 
fixedLength()483     quint16 fixedLength() const { return PerfRecord::fixedLength() + sizeof(m_pid) + sizeof(m_tid); }
484 
485     friend QDataStream &operator>>(QDataStream &stream, PerfRecordComm &record);
486 };
487 
488 QDataStream &operator>>(QDataStream &stream, PerfRecordComm &record);
489 
490 class PerfRecordSample : public PerfRecord {
491 public:
492     PerfRecordSample(const PerfEventHeader *header = nullptr,
493                      const PerfEventAttributes *attributes = nullptr);
registerAbi()494     quint64 registerAbi() const { return m_registerAbi; }
495     quint64 registerValue(int reg) const;
ip()496     quint64 ip() const { return m_ip; }
userStack()497     const QByteArray &userStack() const { return m_userStack; }
callchain()498     const QList<quint64> &callchain() const { return m_callchain; }
period()499     quint64 period() const { return m_period; }
weight()500     quint64 weight() const { return m_weight; }
rawData()501     const QByteArray &rawData() const { return m_rawData; }
502 
503     struct ReadFormat {
504         quint64 value;
505         quint64 id;
506     };
507 
readFormats()508     QList<ReadFormat> readFormats() const { return m_readFormats; }
509 
510     struct BranchFlags {
511         quint64 mispred: 1;
512         quint64 predicted: 1;
513         quint64 in_tx: 1;
514         quint64 abort: 1;
515         quint64 cycles: 16;
516         quint64 type: 4;
517         quint64 reserved: 40;
518     };
519 
520     struct BranchEntry {
521         quint64 from;
522         quint64 to;
523         BranchFlags flags;
524     };
branchStack()525     const QList<BranchEntry> &branchStack() const { return m_branchStack; }
526 
527 private:
528 
529     quint64 m_readFormat;
530     quint64 m_registerMask;
531 
532     quint64 m_ip;
533     quint64 m_addr;
534     quint64 m_period;
535     quint64 m_timeEnabled;
536     quint64 m_timeRunning;
537 
538     quint64 m_registerAbi;
539     quint64 m_weight;
540     quint64 m_dataSrc;
541     quint64 m_transaction;
542 
543     QList<ReadFormat> m_readFormats;
544     QList<quint64> m_callchain;
545     QByteArray m_rawData;
546     QList<BranchEntry> m_branchStack;
547     QList<quint64> m_registers;
548     QByteArray m_userStack;
549 
550     friend QDataStream &operator>>(QDataStream &stream, PerfRecordSample &record);
551 };
552 
553 QDataStream &operator>>(QDataStream &stream, PerfRecordSample &record);
554 
555 class PerfRecordAttr : public PerfRecord
556 {
557 public:
558     PerfRecordAttr(const PerfEventHeader *header = nullptr, quint64 sampleType = 0,
559                    bool sampleIdAll = false);
560 
561     PerfRecordAttr(const PerfEventAttributes &attributes, const QList<quint64> &ids);
562 
attr()563     const PerfEventAttributes &attr() const { return m_attr; }
ids()564     const QList<quint64> &ids() const { return m_ids; }
565 
566 private:
567     PerfEventAttributes m_attr;
568     QList<quint64> m_ids;
569 
570     friend QDataStream &operator>>(QDataStream &stream, PerfRecordAttr &record);
571 };
572 
573 QDataStream &operator>>(QDataStream &stream, PerfRecordAttr &record);
574 
575 class PerfRecordFork : public PerfRecord
576 {
577 public:
578     PerfRecordFork(PerfEventHeader *header = nullptr, quint64 sampleType = 0,
579                    bool sampleIdAll = false);
childTid()580     qint32 childTid() const { return m_tid; }
childPid()581     qint32 childPid() const { return m_pid; }
parentTid()582     qint32 parentTid() const { return m_ptid; }
parentPid()583     qint32 parentPid() const { return m_ppid; }
584 private:
585     qint32 m_pid, m_ppid;
586     qint32 m_tid, m_ptid;
587     quint64 m_time;
588 
589     friend QDataStream &operator>>(QDataStream &stream, PerfRecordFork &record);
590 };
591 
592 QDataStream &operator>>(QDataStream &stream, PerfRecordFork &record);
593 
594 typedef PerfRecordFork PerfRecordExit;
595 
596 class PerfRecordContextSwitch : public PerfRecord
597 {
598 public:
599     PerfRecordContextSwitch(PerfEventHeader *header = 0, quint64 sampleType = 0,
600                             bool sampleIdAll = false);
601 
602 private:
603     friend QDataStream &operator>>(QDataStream &stream, PerfRecordContextSwitch &record);
604 };
605 
606 QDataStream &operator>>(QDataStream &stream, PerfRecordContextSwitch &record);
607 
608 class PerfRecordContextSwitchCpuWide : public PerfRecordContextSwitch
609 {
610 public:
611     PerfRecordContextSwitchCpuWide(PerfEventHeader *header = 0, quint64 sampleType = 0,
612                             bool sampleIdAll = false);
613 
nextPrevPid()614     qint32 nextPrevPid() const { return m_nextPrevPid; }
nextPrevTid()615     qint32 nextPrevTid() const { return m_nextPrevTid; }
616 
617 private:
618     qint32 m_nextPrevPid;
619     qint32 m_nextPrevTid;
620     friend QDataStream &operator>>(QDataStream &stream, PerfRecordContextSwitchCpuWide &record);
621 };
622 
623 QDataStream &operator>>(QDataStream &stream, PerfRecordContextSwitchCpuWide &record);
624 
625 class PerfUnwind;
626 class PerfData : public QObject
627 {
628     Q_OBJECT
629 public:
630     PerfData(PerfUnwind *destination, const PerfHeader *header, PerfAttributes *attributes);
631     ~PerfData();
632     void setSource(QIODevice *source);
633 
634     bool setCompressed(const PerfCompressed &compressed);
635 
636 public slots:
637     void read();
638     void finishReading();
639 
640 signals:
641     void finished();
642     void error();
643 
644 private:
645 
646     enum ReadStatus {
647         Rerun,
648         SignalError,
649         SignalFinished
650     };
651 
652     QIODevice *m_source;
653     PerfUnwind *m_destination;
654 
655     const PerfHeader *m_header;
656     PerfAttributes *m_attributes;
657     PerfEventHeader m_eventHeader;
658     PerfTracingData m_tracingData;
659     PerfCompressed m_compressed;
660     QByteArray m_decompressBuffer;
661     QByteArray m_compressedBuffer;
662     int m_remaininingDecompressedDataSize = 0;
663 #ifdef HAVE_ZSTD
664     ZSTD_DStream *m_zstdDstream = nullptr;
665 #endif
666 
667     ReadStatus processEvents(QDataStream &stream);
668     ReadStatus doRead();
669 };
670