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
= malloc(sizeof(*self
));
60 self
->attr
= malloc(sizeof(void *));
65 self
->data_offset
= 0;
67 self
->trace_info_offset
= 0;
68 self
->trace_info_size
= 0;
73 void perf_header__add_attr(struct perf_header
*self
,
74 struct perf_header_attr
*attr
)
76 int pos
= self
->attrs
;
82 if (self
->attrs
> self
->size
) {
84 self
->attr
= realloc(self
->attr
, self
->size
* sizeof(void *));
88 self
->attr
[pos
] = attr
;
91 #define MAX_EVENT_NAME 64
93 struct perf_trace_event_type
{
95 char name
[MAX_EVENT_NAME
];
98 static int event_count
;
99 static struct perf_trace_event_type
*events
;
101 void perf_header__push_event(u64 id
, const char *name
)
103 if (strlen(name
) > MAX_EVENT_NAME
)
104 printf("Event %s will be truncated\n", name
);
107 events
= malloc(sizeof(struct perf_trace_event_type
));
111 events
= realloc(events
, (event_count
+ 1) * sizeof(struct perf_trace_event_type
));
115 memset(&events
[event_count
], 0, sizeof(struct perf_trace_event_type
));
116 events
[event_count
].event_id
= id
;
117 strncpy(events
[event_count
].name
, name
, MAX_EVENT_NAME
- 1);
121 char *perf_header__find_event(u64 id
)
124 for (i
= 0 ; i
< event_count
; i
++) {
125 if (events
[i
].event_id
== id
)
126 return events
[i
].name
;
131 static const char *__perf_magic
= "PERFFILE";
133 #define PERF_MAGIC (*(u64 *)__perf_magic)
135 struct perf_file_section
{
140 struct perf_file_attr
{
141 struct perf_event_attr attr
;
142 struct perf_file_section ids
;
145 struct perf_file_header
{
149 struct perf_file_section attrs
;
150 struct perf_file_section data
;
151 struct perf_file_section event_types
;
152 struct perf_file_section trace_info
;
155 static int trace_info
;
157 void perf_header__set_trace_info(void)
162 static void do_write(int fd
, void *buf
, size_t size
)
165 int ret
= write(fd
, buf
, size
);
168 die("failed to write");
175 void perf_header__write(struct perf_header
*self
, int fd
)
177 struct perf_file_header f_header
;
178 struct perf_file_attr f_attr
;
179 struct perf_header_attr
*attr
;
182 lseek(fd
, sizeof(f_header
), SEEK_SET
);
185 for (i
= 0; i
< self
->attrs
; i
++) {
186 attr
= self
->attr
[i
];
188 attr
->id_offset
= lseek(fd
, 0, SEEK_CUR
);
189 do_write(fd
, attr
->id
, attr
->ids
* sizeof(u64
));
193 self
->attr_offset
= lseek(fd
, 0, SEEK_CUR
);
195 for (i
= 0; i
< self
->attrs
; i
++) {
196 attr
= self
->attr
[i
];
198 f_attr
= (struct perf_file_attr
){
201 .offset
= attr
->id_offset
,
202 .size
= attr
->ids
* sizeof(u64
),
205 do_write(fd
, &f_attr
, sizeof(f_attr
));
208 self
->event_offset
= lseek(fd
, 0, SEEK_CUR
);
209 self
->event_size
= event_count
* sizeof(struct perf_trace_event_type
);
211 do_write(fd
, events
, self
->event_size
);
214 static int trace_info_written
;
219 if (!trace_info_written
) {
220 self
->trace_info_offset
= lseek(fd
, 0, SEEK_CUR
);
221 read_tracing_data(fd
, attrs
, nr_counters
);
222 self
->trace_info_size
= lseek(fd
, 0, SEEK_CUR
) -
223 self
->trace_info_offset
;
224 trace_info_written
= 1;
226 lseek(fd
, self
->trace_info_offset
+
227 self
->trace_info_size
, SEEK_SET
);
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
,
250 .offset
= self
->trace_info_offset
,
251 .size
= self
->trace_info_size
,
255 lseek(fd
, 0, SEEK_SET
);
256 do_write(fd
, &f_header
, sizeof(f_header
));
257 lseek(fd
, self
->data_offset
+ self
->data_size
, SEEK_SET
);
262 static void do_read(int fd
, void *buf
, size_t size
)
265 int ret
= read(fd
, buf
, size
);
268 die("failed to read");
270 die("failed to read: missing data");
277 struct perf_header
*perf_header__read(int fd
)
279 struct perf_header
*self
= perf_header__new();
280 struct perf_file_header f_header
;
281 struct perf_file_attr f_attr
;
284 int nr_attrs
, nr_ids
, i
, j
;
286 lseek(fd
, 0, SEEK_SET
);
287 do_read(fd
, &f_header
, sizeof(f_header
));
289 if (f_header
.magic
!= PERF_MAGIC
||
290 f_header
.attr_size
!= sizeof(f_attr
))
291 die("incompatible file format");
293 if (f_header
.size
!= sizeof(f_header
)) {
294 /* Support the previous format */
295 if (f_header
.size
== offsetof(typeof(f_header
), trace_info
))
296 f_header
.trace_info
.size
= 0;
298 die("incompatible file format");
300 nr_attrs
= f_header
.attrs
.size
/ sizeof(f_attr
);
301 lseek(fd
, f_header
.attrs
.offset
, SEEK_SET
);
303 for (i
= 0; i
< nr_attrs
; i
++) {
304 struct perf_header_attr
*attr
;
307 do_read(fd
, &f_attr
, sizeof(f_attr
));
308 tmp
= lseek(fd
, 0, SEEK_CUR
);
310 attr
= perf_header_attr__new(&f_attr
.attr
);
312 nr_ids
= f_attr
.ids
.size
/ sizeof(u64
);
313 lseek(fd
, f_attr
.ids
.offset
, SEEK_SET
);
315 for (j
= 0; j
< nr_ids
; j
++) {
316 do_read(fd
, &f_id
, sizeof(f_id
));
318 perf_header_attr__add_id(attr
, f_id
);
320 perf_header__add_attr(self
, attr
);
321 lseek(fd
, tmp
, SEEK_SET
);
324 if (f_header
.event_types
.size
) {
325 lseek(fd
, f_header
.event_types
.offset
, SEEK_SET
);
326 events
= malloc(f_header
.event_types
.size
);
329 do_read(fd
, events
, f_header
.event_types
.size
);
330 event_count
= f_header
.event_types
.size
/ sizeof(struct perf_trace_event_type
);
333 self
->trace_info_offset
= f_header
.trace_info
.offset
;
334 self
->trace_info_size
= f_header
.trace_info
.size
;
336 if (self
->trace_info_size
) {
337 lseek(fd
, self
->trace_info_offset
, SEEK_SET
);
341 self
->event_offset
= f_header
.event_types
.offset
;
342 self
->event_size
= f_header
.event_types
.size
;
344 self
->data_offset
= f_header
.data
.offset
;
345 self
->data_size
= f_header
.data
.size
;
347 lseek(fd
, self
->data_offset
, SEEK_SET
);
354 u64
perf_header__sample_type(struct perf_header
*header
)
359 for (i
= 0; i
< header
->attrs
; i
++) {
360 struct perf_header_attr
*attr
= header
->attr
[i
];
363 type
= attr
->attr
.sample_type
;
364 else if (type
!= attr
->attr
.sample_type
)
365 die("non matching sample_type");
371 struct perf_event_attr
*
372 perf_header__find_attr(u64 id
, struct perf_header
*header
)
376 for (i
= 0; i
< header
->attrs
; i
++) {
377 struct perf_header_attr
*attr
= header
->attr
[i
];
380 for (j
= 0; j
< attr
->ids
; j
++) {
381 if (attr
->id
[j
] == id
)