summaryrefslogtreecommitdiff
path: root/simpleperf/record.h
blob: fbd523d1f9c78f0cc5a17c5380edca144238bb74 (plain)
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SIMPLE_PERF_RECORD_H_
#define SIMPLE_PERF_RECORD_H_

#include <string>
#include <vector>

#include "perf_event.h"

struct KernelMmap;
struct ModuleMmap;
struct ThreadComm;
struct ThreadMmap;

enum user_record_type {
  PERF_RECORD_ATTR = 64,
  PERF_RECORD_EVENT_TYPE,
  PERF_RECORD_TRACING_DATA,
  PERF_RECORD_BUILD_ID,
  PERF_RECORD_FINISHED_ROUND,
};

struct PerfSampleIpType {
  uint64_t ip;
};

struct PerfSampleTidType {
  uint32_t pid, tid;
};

struct PerfSampleTimeType {
  uint64_t time;
};

struct PerfSampleAddrType {
  uint64_t addr;
};

struct PerfSampleIdType {
  uint64_t id;
};

struct PerfSampleStreamIdType {
  uint64_t stream_id;
};

struct PerfSampleCpuType {
  uint32_t cpu, res;
};

struct PerfSamplePeriodType {
  uint64_t period;
};

// SampleId is optional at the end of a record in binary format. Its content is determined by
// sample_id_all and sample_type in perf_event_attr. To avoid the complexity of referring to
// perf_event_attr each time, we copy sample_id_all and sample_type inside the SampleId structure.
struct SampleId {
  bool sample_id_all;
  uint64_t sample_type;

  PerfSampleTidType tid_data;             // Valid if sample_id_all && PERF_SAMPLE_TID.
  PerfSampleTimeType time_data;           // Valid if sample_id_all && PERF_SAMPLE_TIME.
  PerfSampleIdType id_data;               // Valid if sample_id_all && PERF_SAMPLE_ID.
  PerfSampleStreamIdType stream_id_data;  // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
  PerfSampleCpuType cpu_data;             // Valid if sample_id_all && PERF_SAMPLE_CPU.

  SampleId();

  // Create the content of sample_id. It depends on the attr we use.
  size_t CreateContent(const perf_event_attr& attr);

  // Parse sample_id from binary format in the buffer pointed by p.
  void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p, const char* end);

  // Write the binary format of sample_id to the buffer pointed by p.
  void WriteToBinaryFormat(char*& p) const;
  void Dump(size_t indent) const;
};

// Usually one record contains the following three parts in order in binary format:
//   perf_event_header (at the head of a record, containing type and size information)
//   data depends on the record type
//   sample_id (optional part at the end of a record)
// We hold the common parts (perf_event_header and sample_id) in the base class Record, and
// hold the type specific data part in classes derived from Record.
struct Record {
  perf_event_header header;
  SampleId sample_id;

  Record();
  Record(const perf_event_header* pheader);

  virtual ~Record() {
  }

  void Dump(size_t indent = 0) const;

 protected:
  virtual void DumpData(size_t) const {
  }
};

struct MmapRecord : public Record {
  struct MmapRecordDataType {
    uint32_t pid, tid;
    uint64_t addr;
    uint64_t len;
    uint64_t pgoff;
  } data;
  std::string filename;

  MmapRecord() {  // For storage in std::vector.
  }

  MmapRecord(const perf_event_attr& attr, const perf_event_header* pheader);
  void DumpData(size_t indent) const override;
  std::vector<char> BinaryFormat() const;
};

struct CommRecord : public Record {
  struct CommRecordDataType {
    uint32_t pid, tid;
  } data;
  std::string comm;

  CommRecord() {
  }

  CommRecord(const perf_event_attr& attr, const perf_event_header* pheader);
  void DumpData(size_t indent) const override;
  std::vector<char> BinaryFormat() const;
};

struct ExitRecord : public Record {
  struct ExitRecordDataType {
    uint32_t pid, ppid;
    uint32_t tid, ptid;
    uint64_t time;
  } data;

  ExitRecord(const perf_event_attr& attr, const perf_event_header* pheader);
  void DumpData(size_t indent) const override;
};

struct SampleRecord : public Record {
  uint64_t sample_type;  // sample_type is a bit mask determining which fields below are valid.

  PerfSampleIpType ip_data;               // Valid if PERF_SAMPLE_IP.
  PerfSampleTidType tid_data;             // Valid if PERF_SAMPLE_TID.
  PerfSampleTimeType time_data;           // Valid if PERF_SAMPLE_TIME.
  PerfSampleAddrType addr_data;           // Valid if PERF_SAMPLE_ADDR.
  PerfSampleIdType id_data;               // Valid if PERF_SAMPLE_ID.
  PerfSampleStreamIdType stream_id_data;  // Valid if PERF_SAMPLE_STREAM_ID.
  PerfSampleCpuType cpu_data;             // Valid if PERF_SAMPLE_CPU.
  PerfSamplePeriodType period_data;       // Valid if PERF_SAMPLE_PERIOD.

  SampleRecord(const perf_event_attr& attr, const perf_event_header* pheader);
  void DumpData(size_t indent) const override;
};

std::unique_ptr<const Record> ReadRecordFromBuffer(const perf_event_attr& attr,
                                                   const perf_event_header* pheader);

#endif  // SIMPLE_PERF_RECORD_H_