aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/header.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r--tools/perf/util/header.c361
1 files changed, 10 insertions, 351 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 26f5b2fe5dc8..b20e40c74468 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -24,8 +24,6 @@
24#include "build-id.h" 24#include "build-id.h"
25#include "data.h" 25#include "data.h"
26 26
27static bool no_buildid_cache = false;
28
29static u32 header_argc; 27static u32 header_argc;
30static const char **header_argv; 28static const char **header_argv;
31 29
@@ -79,10 +77,7 @@ static int do_write(int fd, const void *buf, size_t size)
79 return 0; 77 return 0;
80} 78}
81 79
82#define NAME_ALIGN 64 80int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
83
84static int write_padded(int fd, const void *bf, size_t count,
85 size_t count_aligned)
86{ 81{
87 static const char zero_buf[NAME_ALIGN]; 82 static const char zero_buf[NAME_ALIGN];
88 int err = do_write(fd, bf, count); 83 int err = do_write(fd, bf, count);
@@ -171,340 +166,6 @@ perf_header__set_cmdline(int argc, const char **argv)
171 return 0; 166 return 0;
172} 167}
173 168
174#define dsos__for_each_with_build_id(pos, head) \
175 list_for_each_entry(pos, head, node) \
176 if (!pos->has_build_id) \
177 continue; \
178 else
179
180static int write_buildid(const char *name, size_t name_len, u8 *build_id,
181 pid_t pid, u16 misc, int fd)
182{
183 int err;
184 struct build_id_event b;
185 size_t len;
186
187 len = name_len + 1;
188 len = PERF_ALIGN(len, NAME_ALIGN);
189
190 memset(&b, 0, sizeof(b));
191 memcpy(&b.build_id, build_id, BUILD_ID_SIZE);
192 b.pid = pid;
193 b.header.misc = misc;
194 b.header.size = sizeof(b) + len;
195
196 err = do_write(fd, &b, sizeof(b));
197 if (err < 0)
198 return err;
199
200 return write_padded(fd, name, name_len + 1, len);
201}
202
203static int __dsos__hit_all(struct list_head *head)
204{
205 struct dso *pos;
206
207 list_for_each_entry(pos, head, node)
208 pos->hit = true;
209
210 return 0;
211}
212
213static int machine__hit_all_dsos(struct machine *machine)
214{
215 int err;
216
217 err = __dsos__hit_all(&machine->kernel_dsos.head);
218 if (err)
219 return err;
220
221 return __dsos__hit_all(&machine->user_dsos.head);
222}
223
224int dsos__hit_all(struct perf_session *session)
225{
226 struct rb_node *nd;
227 int err;
228
229 err = machine__hit_all_dsos(&session->machines.host);
230 if (err)
231 return err;
232
233 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
234 struct machine *pos = rb_entry(nd, struct machine, rb_node);
235
236 err = machine__hit_all_dsos(pos);
237 if (err)
238 return err;
239 }
240
241 return 0;
242}
243
244static int __dsos__write_buildid_table(struct list_head *head,
245 struct machine *machine,
246 pid_t pid, u16 misc, int fd)
247{
248 char nm[PATH_MAX];
249 struct dso *pos;
250
251 dsos__for_each_with_build_id(pos, head) {
252 int err;
253 const char *name;
254 size_t name_len;
255
256 if (!pos->hit)
257 continue;
258
259 if (dso__is_vdso(pos)) {
260 name = pos->short_name;
261 name_len = pos->short_name_len + 1;
262 } else if (dso__is_kcore(pos)) {
263 machine__mmap_name(machine, nm, sizeof(nm));
264 name = nm;
265 name_len = strlen(nm) + 1;
266 } else {
267 name = pos->long_name;
268 name_len = pos->long_name_len + 1;
269 }
270
271 err = write_buildid(name, name_len, pos->build_id,
272 pid, misc, fd);
273 if (err)
274 return err;
275 }
276
277 return 0;
278}
279
280static int machine__write_buildid_table(struct machine *machine, int fd)
281{
282 int err;
283 u16 kmisc = PERF_RECORD_MISC_KERNEL,
284 umisc = PERF_RECORD_MISC_USER;
285
286 if (!machine__is_host(machine)) {
287 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
288 umisc = PERF_RECORD_MISC_GUEST_USER;
289 }
290
291 err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
292 machine->pid, kmisc, fd);
293 if (err == 0)
294 err = __dsos__write_buildid_table(&machine->user_dsos.head,
295 machine, machine->pid, umisc,
296 fd);
297 return err;
298}
299
300static int dsos__write_buildid_table(struct perf_header *header, int fd)
301{
302 struct perf_session *session = container_of(header,
303 struct perf_session, header);
304 struct rb_node *nd;
305 int err = machine__write_buildid_table(&session->machines.host, fd);
306
307 if (err)
308 return err;
309
310 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
311 struct machine *pos = rb_entry(nd, struct machine, rb_node);
312 err = machine__write_buildid_table(pos, fd);
313 if (err)
314 break;
315 }
316 return err;
317}
318
319int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
320 const char *name, bool is_kallsyms, bool is_vdso)
321{
322 const size_t size = PATH_MAX;
323 char *realname, *filename = zalloc(size),
324 *linkname = zalloc(size), *targetname;
325 int len, err = -1;
326 bool slash = is_kallsyms || is_vdso;
327
328 if (is_kallsyms) {
329 if (symbol_conf.kptr_restrict) {
330 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
331 err = 0;
332 goto out_free;
333 }
334 realname = (char *) name;
335 } else
336 realname = realpath(name, NULL);
337
338 if (realname == NULL || filename == NULL || linkname == NULL)
339 goto out_free;
340
341 len = scnprintf(filename, size, "%s%s%s",
342 debugdir, slash ? "/" : "",
343 is_vdso ? DSO__NAME_VDSO : realname);
344 if (mkdir_p(filename, 0755))
345 goto out_free;
346
347 snprintf(filename + len, size - len, "/%s", sbuild_id);
348
349 if (access(filename, F_OK)) {
350 if (is_kallsyms) {
351 if (copyfile("/proc/kallsyms", filename))
352 goto out_free;
353 } else if (link(realname, filename) && copyfile(name, filename))
354 goto out_free;
355 }
356
357 len = scnprintf(linkname, size, "%s/.build-id/%.2s",
358 debugdir, sbuild_id);
359
360 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
361 goto out_free;
362
363 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
364 targetname = filename + strlen(debugdir) - 5;
365 memcpy(targetname, "../..", 5);
366
367 if (symlink(targetname, linkname) == 0)
368 err = 0;
369out_free:
370 if (!is_kallsyms)
371 free(realname);
372 free(filename);
373 free(linkname);
374 return err;
375}
376
377static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
378 const char *name, const char *debugdir,
379 bool is_kallsyms, bool is_vdso)
380{
381 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
382
383 build_id__sprintf(build_id, build_id_size, sbuild_id);
384
385 return build_id_cache__add_s(sbuild_id, debugdir, name,
386 is_kallsyms, is_vdso);
387}
388
389int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
390{
391 const size_t size = PATH_MAX;
392 char *filename = zalloc(size),
393 *linkname = zalloc(size);
394 int err = -1;
395
396 if (filename == NULL || linkname == NULL)
397 goto out_free;
398
399 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
400 debugdir, sbuild_id, sbuild_id + 2);
401
402 if (access(linkname, F_OK))
403 goto out_free;
404
405 if (readlink(linkname, filename, size - 1) < 0)
406 goto out_free;
407
408 if (unlink(linkname))
409 goto out_free;
410
411 /*
412 * Since the link is relative, we must make it absolute:
413 */
414 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
415 debugdir, sbuild_id, filename);
416
417 if (unlink(linkname))
418 goto out_free;
419
420 err = 0;
421out_free:
422 free(filename);
423 free(linkname);
424 return err;
425}
426
427static int dso__cache_build_id(struct dso *dso, struct machine *machine,
428 const char *debugdir)
429{
430 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
431 bool is_vdso = dso__is_vdso(dso);
432 const char *name = dso->long_name;
433 char nm[PATH_MAX];
434
435 if (dso__is_kcore(dso)) {
436 is_kallsyms = true;
437 machine__mmap_name(machine, nm, sizeof(nm));
438 name = nm;
439 }
440 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
441 debugdir, is_kallsyms, is_vdso);
442}
443
444static int __dsos__cache_build_ids(struct list_head *head,
445 struct machine *machine, const char *debugdir)
446{
447 struct dso *pos;
448 int err = 0;
449
450 dsos__for_each_with_build_id(pos, head)
451 if (dso__cache_build_id(pos, machine, debugdir))
452 err = -1;
453
454 return err;
455}
456
457static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
458{
459 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
460 debugdir);
461 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
462 debugdir);
463 return ret;
464}
465
466static int perf_session__cache_build_ids(struct perf_session *session)
467{
468 struct rb_node *nd;
469 int ret;
470 char debugdir[PATH_MAX];
471
472 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
473
474 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
475 return -1;
476
477 ret = machine__cache_build_ids(&session->machines.host, debugdir);
478
479 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
480 struct machine *pos = rb_entry(nd, struct machine, rb_node);
481 ret |= machine__cache_build_ids(pos, debugdir);
482 }
483 return ret ? -1 : 0;
484}
485
486static bool machine__read_build_ids(struct machine *machine, bool with_hits)
487{
488 bool ret;
489
490 ret = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits);
491 ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits);
492 return ret;
493}
494
495static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
496{
497 struct rb_node *nd;
498 bool ret = machine__read_build_ids(&session->machines.host, with_hits);
499
500 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
501 struct machine *pos = rb_entry(nd, struct machine, rb_node);
502 ret |= machine__read_build_ids(pos, with_hits);
503 }
504
505 return ret;
506}
507
508static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, 169static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
509 struct perf_evlist *evlist) 170 struct perf_evlist *evlist)
510{ 171{
@@ -523,13 +184,12 @@ static int write_build_id(int fd, struct perf_header *h,
523 if (!perf_session__read_build_ids(session, true)) 184 if (!perf_session__read_build_ids(session, true))
524 return -1; 185 return -1;
525 186
526 err = dsos__write_buildid_table(h, fd); 187 err = perf_session__write_buildid_table(session, fd);
527 if (err < 0) { 188 if (err < 0) {
528 pr_debug("failed to write buildid table\n"); 189 pr_debug("failed to write buildid table\n");
529 return err; 190 return err;
530 } 191 }
531 if (!no_buildid_cache) 192 perf_session__cache_build_ids(session);
532 perf_session__cache_build_ids(session);
533 193
534 return 0; 194 return 0;
535} 195}
@@ -601,8 +261,10 @@ static int __write_cpudesc(int fd, const char *cpuinfo_proc)
601 break; 261 break;
602 } 262 }
603 263
604 if (ret) 264 if (ret) {
265 ret = -1;
605 goto done; 266 goto done;
267 }
606 268
607 s = buf; 269 s = buf;
608 270
@@ -965,7 +627,8 @@ static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
965 n = sscanf(buf, "%*s %"PRIu64, &mem); 627 n = sscanf(buf, "%*s %"PRIu64, &mem);
966 if (n == 1) 628 if (n == 1)
967 ret = do_write(fd, &mem, sizeof(mem)); 629 ret = do_write(fd, &mem, sizeof(mem));
968 } 630 } else
631 ret = -1;
969 free(buf); 632 free(buf);
970 fclose(fp); 633 fclose(fp);
971 return ret; 634 return ret;
@@ -1603,7 +1266,7 @@ static int __event_process_build_id(struct build_id_event *bev,
1603 1266
1604 dso__set_build_id(dso, &bev->build_id); 1267 dso__set_build_id(dso, &bev->build_id);
1605 1268
1606 if (filename[0] == '[') 1269 if (!is_kernel_module(filename, NULL))
1607 dso->kernel = dso_type; 1270 dso->kernel = dso_type;
1608 1271
1609 build_id__sprintf(dso->build_id, sizeof(dso->build_id), 1272 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
@@ -2477,6 +2140,7 @@ static const int attr_file_abi_sizes[] = {
2477 [1] = PERF_ATTR_SIZE_VER1, 2140 [1] = PERF_ATTR_SIZE_VER1,
2478 [2] = PERF_ATTR_SIZE_VER2, 2141 [2] = PERF_ATTR_SIZE_VER2,
2479 [3] = PERF_ATTR_SIZE_VER3, 2142 [3] = PERF_ATTR_SIZE_VER3,
2143 [4] = PERF_ATTR_SIZE_VER4,
2480 0, 2144 0,
2481}; 2145};
2482 2146
@@ -3124,8 +2788,3 @@ int perf_event__process_build_id(struct perf_tool *tool __maybe_unused,
3124 session); 2788 session);
3125 return 0; 2789 return 0;
3126} 2790}
3127
3128void disable_buildid_cache(void)
3129{
3130 no_buildid_cache = true;
3131}