10 * Create new perf.data header attribute:
12 struct perf_header_attr
*perf_header_attr__new(struct perf_event_attr
*attr
)
14 struct perf_header_attr
*self
= malloc(sizeof(*self
));
22 self
->id
= malloc(sizeof(u64
));
30 void perf_header_attr__add_id(struct perf_header_attr
*self
, u64 id
)
35 if (self
->ids
> self
->size
) {
37 self
->id
= realloc(self
->id
, self
->size
* sizeof(u64
));
45 * Create new perf.data header:
47 struct perf_header
*perf_header__new(void)
49 struct perf_header
*self
= malloc(sizeof(*self
));
58 self
->attr
= malloc(sizeof(void *));
63 self
->data_offset
= 0;
69 void perf_header__add_attr(struct perf_header
*self
,
70 struct perf_header_attr
*attr
)
72 int pos
= self
->attrs
;
78 if (self
->attrs
> self
->size
) {
80 self
->attr
= realloc(self
->attr
, self
->size
* sizeof(void *));
84 self
->attr
[pos
] = attr
;
87 #define MAX_EVENT_NAME 64
89 struct perf_trace_event_type
{
91 char name
[MAX_EVENT_NAME
];
94 static int event_count
;
95 static struct perf_trace_event_type
*events
;
97 void perf_header__push_event(u64 id
, const char *name
)
99 if (strlen(name
) > MAX_EVENT_NAME
)
100 printf("Event %s will be truncated\n", name
);
103 events
= malloc(sizeof(struct perf_trace_event_type
));
107 events
= realloc(events
, (event_count
+ 1) * sizeof(struct perf_trace_event_type
));
111 memset(&events
[event_count
], 0, sizeof(struct perf_trace_event_type
));
112 events
[event_count
].event_id
= id
;
113 strncpy(events
[event_count
].name
, name
, MAX_EVENT_NAME
- 1);
117 char *perf_header__find_event(u64 id
)
120 for (i
= 0 ; i
< event_count
; i
++) {
121 if (events
[i
].event_id
== id
)
122 return events
[i
].name
;
127 static const char *__perf_magic
= "PERFFILE";
129 #define PERF_MAGIC (*(u64 *)__perf_magic)
131 struct perf_file_section
{
136 struct perf_file_attr
{
137 struct perf_event_attr attr
;
138 struct perf_file_section ids
;
141 struct perf_file_header
{
145 struct perf_file_section attrs
;
146 struct perf_file_section data
;
147 struct perf_file_section event_types
;
150 static void do_write(int fd
, void *buf
, size_t size
)
153 int ret
= write(fd
, buf
, size
);
156 die("failed to write");
163 void perf_header__write(struct perf_header
*self
, int fd
)
165 struct perf_file_header f_header
;
166 struct perf_file_attr f_attr
;
167 struct perf_header_attr
*attr
;
170 lseek(fd
, sizeof(f_header
), SEEK_SET
);
173 for (i
= 0; i
< self
->attrs
; i
++) {
174 attr
= self
->attr
[i
];
176 attr
->id_offset
= lseek(fd
, 0, SEEK_CUR
);
177 do_write(fd
, attr
->id
, attr
->ids
* sizeof(u64
));
181 self
->attr_offset
= lseek(fd
, 0, SEEK_CUR
);
183 for (i
= 0; i
< self
->attrs
; i
++) {
184 attr
= self
->attr
[i
];
186 f_attr
= (struct perf_file_attr
){
189 .offset
= attr
->id_offset
,
190 .size
= attr
->ids
* sizeof(u64
),
193 do_write(fd
, &f_attr
, sizeof(f_attr
));
196 self
->event_offset
= lseek(fd
, 0, SEEK_CUR
);
197 self
->event_size
= event_count
* sizeof(struct perf_trace_event_type
);
199 do_write(fd
, events
, self
->event_size
);
202 self
->data_offset
= lseek(fd
, 0, SEEK_CUR
);
204 f_header
= (struct perf_file_header
){
206 .size
= sizeof(f_header
),
207 .attr_size
= sizeof(f_attr
),
209 .offset
= self
->attr_offset
,
210 .size
= self
->attrs
* sizeof(f_attr
),
213 .offset
= self
->data_offset
,
214 .size
= self
->data_size
,
217 .offset
= self
->event_offset
,
218 .size
= self
->event_size
,
222 lseek(fd
, 0, SEEK_SET
);
223 do_write(fd
, &f_header
, sizeof(f_header
));
224 lseek(fd
, self
->data_offset
+ self
->data_size
, SEEK_SET
);
229 static void do_read(int fd
, void *buf
, size_t size
)
232 int ret
= read(fd
, buf
, size
);
235 die("failed to read");
237 die("failed to read: missing data");
244 struct perf_header
*perf_header__read(int fd
)
246 struct perf_header
*self
= perf_header__new();
247 struct perf_file_header f_header
;
248 struct perf_file_attr f_attr
;
251 int nr_attrs
, nr_ids
, i
, j
;
253 lseek(fd
, 0, SEEK_SET
);
254 do_read(fd
, &f_header
, sizeof(f_header
));
256 if (f_header
.magic
!= PERF_MAGIC
||
257 f_header
.size
!= sizeof(f_header
) ||
258 f_header
.attr_size
!= sizeof(f_attr
))
259 die("incompatible file format");
261 nr_attrs
= f_header
.attrs
.size
/ sizeof(f_attr
);
262 lseek(fd
, f_header
.attrs
.offset
, SEEK_SET
);
264 for (i
= 0; i
< nr_attrs
; i
++) {
265 struct perf_header_attr
*attr
;
268 do_read(fd
, &f_attr
, sizeof(f_attr
));
269 tmp
= lseek(fd
, 0, SEEK_CUR
);
271 attr
= perf_header_attr__new(&f_attr
.attr
);
273 nr_ids
= f_attr
.ids
.size
/ sizeof(u64
);
274 lseek(fd
, f_attr
.ids
.offset
, SEEK_SET
);
276 for (j
= 0; j
< nr_ids
; j
++) {
277 do_read(fd
, &f_id
, sizeof(f_id
));
279 perf_header_attr__add_id(attr
, f_id
);
281 perf_header__add_attr(self
, attr
);
282 lseek(fd
, tmp
, SEEK_SET
);
285 if (f_header
.event_types
.size
) {
286 lseek(fd
, f_header
.event_types
.offset
, SEEK_SET
);
287 events
= malloc(f_header
.event_types
.size
);
290 do_read(fd
, events
, f_header
.event_types
.size
);
291 event_count
= f_header
.event_types
.size
/ sizeof(struct perf_trace_event_type
);
293 self
->event_offset
= f_header
.event_types
.offset
;
294 self
->event_size
= f_header
.event_types
.size
;
296 self
->data_offset
= f_header
.data
.offset
;
297 self
->data_size
= f_header
.data
.size
;
299 lseek(fd
, self
->data_offset
, SEEK_SET
);
306 u64
perf_header__sample_type(struct perf_header
*header
)
311 for (i
= 0; i
< header
->attrs
; i
++) {
312 struct perf_header_attr
*attr
= header
->attr
[i
];
315 type
= attr
->attr
.sample_type
;
316 else if (type
!= attr
->attr
.sample_type
)
317 die("non matching sample_type");
323 struct perf_event_attr
*
324 perf_header__find_attr(u64 id
, struct perf_header
*header
)
328 for (i
= 0; i
< header
->attrs
; i
++) {
329 struct perf_header_attr
*attr
= header
->attr
[i
];
332 for (j
= 0; j
< attr
->ids
; j
++) {
333 if (attr
->id
[j
] == id
)