9 #include "trace-event.h"
12 * Create new perf.data header attribute:
14 struct perf_header_attr
*perf_header_attr__new(struct perf_event_attr
*attr
)
16 struct perf_header_attr
*self
= malloc(sizeof(*self
));
24 self
->id
= malloc(sizeof(u64
));
32 void perf_header_attr__add_id(struct perf_header_attr
*self
, u64 id
)
37 if (self
->ids
> self
->size
) {
39 self
->id
= realloc(self
->id
, self
->size
* sizeof(u64
));
47 * Create new perf.data header:
49 struct perf_header
*perf_header__new(void)
51 struct perf_header
*self
= calloc(sizeof(*self
), 1);
57 self
->attr
= malloc(sizeof(void *));
65 void perf_header__add_attr(struct perf_header
*self
,
66 struct perf_header_attr
*attr
)
68 int pos
= self
->attrs
;
74 if (self
->attrs
> self
->size
) {
76 self
->attr
= realloc(self
->attr
, self
->size
* sizeof(void *));
80 self
->attr
[pos
] = attr
;
83 #define MAX_EVENT_NAME 64
85 struct perf_trace_event_type
{
87 char name
[MAX_EVENT_NAME
];
90 static int event_count
;
91 static struct perf_trace_event_type
*events
;
93 void perf_header__push_event(u64 id
, const char *name
)
95 if (strlen(name
) > MAX_EVENT_NAME
)
96 pr_warning("Event %s will be truncated\n", name
);
99 events
= malloc(sizeof(struct perf_trace_event_type
));
103 events
= realloc(events
, (event_count
+ 1) * sizeof(struct perf_trace_event_type
));
107 memset(&events
[event_count
], 0, sizeof(struct perf_trace_event_type
));
108 events
[event_count
].event_id
= id
;
109 strncpy(events
[event_count
].name
, name
, MAX_EVENT_NAME
- 1);
113 char *perf_header__find_event(u64 id
)
116 for (i
= 0 ; i
< event_count
; i
++) {
117 if (events
[i
].event_id
== id
)
118 return events
[i
].name
;
123 static const char *__perf_magic
= "PERFFILE";
125 #define PERF_MAGIC (*(u64 *)__perf_magic)
127 struct perf_file_section
{
132 struct perf_file_attr
{
133 struct perf_event_attr attr
;
134 struct perf_file_section ids
;
137 struct perf_file_header
{
141 struct perf_file_section attrs
;
142 struct perf_file_section data
;
143 struct perf_file_section event_types
;
144 DECLARE_BITMAP(adds_features
, HEADER_FEAT_BITS
);
147 void perf_header__feat_trace_info(struct perf_header
*header
)
149 set_bit(HEADER_TRACE_INFO
, header
->adds_features
);
152 static void do_write(int fd
, void *buf
, size_t size
)
155 int ret
= write(fd
, buf
, size
);
158 die("failed to write");
165 static void perf_header__adds_write(struct perf_header
*self
, int fd
)
167 struct perf_file_section trace_sec
;
168 u64 cur_offset
= lseek(fd
, 0, SEEK_CUR
);
169 unsigned long *feat_mask
= self
->adds_features
;
171 if (test_bit(HEADER_TRACE_INFO
, feat_mask
)) {
172 /* Write trace info */
173 trace_sec
.offset
= lseek(fd
, sizeof(trace_sec
), SEEK_CUR
);
174 read_tracing_data(fd
, attrs
, nr_counters
);
175 trace_sec
.size
= lseek(fd
, 0, SEEK_CUR
) - trace_sec
.offset
;
177 /* Write trace info headers */
178 lseek(fd
, cur_offset
, SEEK_SET
);
179 do_write(fd
, &trace_sec
, sizeof(trace_sec
));
182 * Update cur_offset. So that other (future)
183 * features can set their own infos in this place. But if we are
184 * the only feature, at least that seeks to the place the data
187 cur_offset
= lseek(fd
, trace_sec
.offset
+ trace_sec
.size
, SEEK_SET
);
191 void perf_header__write(struct perf_header
*self
, int fd
)
193 struct perf_file_header f_header
;
194 struct perf_file_attr f_attr
;
195 struct perf_header_attr
*attr
;
198 lseek(fd
, sizeof(f_header
), SEEK_SET
);
201 for (i
= 0; i
< self
->attrs
; i
++) {
202 attr
= self
->attr
[i
];
204 attr
->id_offset
= lseek(fd
, 0, SEEK_CUR
);
205 do_write(fd
, attr
->id
, attr
->ids
* sizeof(u64
));
209 self
->attr_offset
= lseek(fd
, 0, SEEK_CUR
);
211 for (i
= 0; i
< self
->attrs
; i
++) {
212 attr
= self
->attr
[i
];
214 f_attr
= (struct perf_file_attr
){
217 .offset
= attr
->id_offset
,
218 .size
= attr
->ids
* sizeof(u64
),
221 do_write(fd
, &f_attr
, sizeof(f_attr
));
224 self
->event_offset
= lseek(fd
, 0, SEEK_CUR
);
225 self
->event_size
= event_count
* sizeof(struct perf_trace_event_type
);
227 do_write(fd
, events
, self
->event_size
);
229 perf_header__adds_write(self
, fd
);
231 self
->data_offset
= lseek(fd
, 0, SEEK_CUR
);
233 f_header
= (struct perf_file_header
){
235 .size
= sizeof(f_header
),
236 .attr_size
= sizeof(f_attr
),
238 .offset
= self
->attr_offset
,
239 .size
= self
->attrs
* sizeof(f_attr
),
242 .offset
= self
->data_offset
,
243 .size
= self
->data_size
,
246 .offset
= self
->event_offset
,
247 .size
= self
->event_size
,
251 memcpy(&f_header
.adds_features
, &self
->adds_features
, sizeof(self
->adds_features
));
253 lseek(fd
, 0, SEEK_SET
);
254 do_write(fd
, &f_header
, sizeof(f_header
));
255 lseek(fd
, self
->data_offset
+ self
->data_size
, SEEK_SET
);
260 static void do_read(int fd
, void *buf
, size_t size
)
263 int ret
= read(fd
, buf
, size
);
266 die("failed to read");
268 die("failed to read: missing data");
275 static void perf_header__adds_read(struct perf_header
*self
, int fd
)
277 const unsigned long *feat_mask
= self
->adds_features
;
279 if (test_bit(HEADER_TRACE_INFO
, feat_mask
)) {
280 struct perf_file_section trace_sec
;
282 do_read(fd
, &trace_sec
, sizeof(trace_sec
));
283 lseek(fd
, trace_sec
.offset
, SEEK_SET
);
285 lseek(fd
, trace_sec
.offset
+ trace_sec
.size
, SEEK_SET
);
289 struct perf_header
*perf_header__read(int fd
)
291 struct perf_header
*self
= perf_header__new();
292 struct perf_file_header f_header
;
293 struct perf_file_attr f_attr
;
296 int nr_attrs
, nr_ids
, i
, j
;
298 lseek(fd
, 0, SEEK_SET
);
299 do_read(fd
, &f_header
, sizeof(f_header
));
301 if (f_header
.magic
!= PERF_MAGIC
||
302 f_header
.attr_size
!= sizeof(f_attr
))
303 die("incompatible file format");
305 if (f_header
.size
!= sizeof(f_header
)) {
306 /* Support the previous format */
307 if (f_header
.size
== offsetof(typeof(f_header
), adds_features
))
308 bitmap_zero(f_header
.adds_features
, HEADER_FEAT_BITS
);
310 die("incompatible file format");
312 nr_attrs
= f_header
.attrs
.size
/ sizeof(f_attr
);
313 lseek(fd
, f_header
.attrs
.offset
, SEEK_SET
);
315 for (i
= 0; i
< nr_attrs
; i
++) {
316 struct perf_header_attr
*attr
;
319 do_read(fd
, &f_attr
, sizeof(f_attr
));
320 tmp
= lseek(fd
, 0, SEEK_CUR
);
322 attr
= perf_header_attr__new(&f_attr
.attr
);
324 nr_ids
= f_attr
.ids
.size
/ sizeof(u64
);
325 lseek(fd
, f_attr
.ids
.offset
, SEEK_SET
);
327 for (j
= 0; j
< nr_ids
; j
++) {
328 do_read(fd
, &f_id
, sizeof(f_id
));
330 perf_header_attr__add_id(attr
, f_id
);
332 perf_header__add_attr(self
, attr
);
333 lseek(fd
, tmp
, SEEK_SET
);
336 if (f_header
.event_types
.size
) {
337 lseek(fd
, f_header
.event_types
.offset
, SEEK_SET
);
338 events
= malloc(f_header
.event_types
.size
);
341 do_read(fd
, events
, f_header
.event_types
.size
);
342 event_count
= f_header
.event_types
.size
/ sizeof(struct perf_trace_event_type
);
345 memcpy(&self
->adds_features
, &f_header
.adds_features
, sizeof(f_header
.adds_features
));
347 perf_header__adds_read(self
, fd
);
349 self
->event_offset
= f_header
.event_types
.offset
;
350 self
->event_size
= f_header
.event_types
.size
;
352 self
->data_offset
= f_header
.data
.offset
;
353 self
->data_size
= f_header
.data
.size
;
355 lseek(fd
, self
->data_offset
, SEEK_SET
);
362 u64
perf_header__sample_type(struct perf_header
*header
)
367 for (i
= 0; i
< header
->attrs
; i
++) {
368 struct perf_header_attr
*attr
= header
->attr
[i
];
371 type
= attr
->attr
.sample_type
;
372 else if (type
!= attr
->attr
.sample_type
)
373 die("non matching sample_type");
379 struct perf_event_attr
*
380 perf_header__find_attr(u64 id
, struct perf_header
*header
)
384 for (i
= 0; i
< header
->attrs
; i
++) {
385 struct perf_header_attr
*attr
= header
->attr
[i
];
388 for (j
= 0; j
< attr
->ids
; j
++) {
389 if (attr
->id
[j
] == id
)