| .. | .. |
|---|
| 7 | 7 | * Copyright (C) 2009, 2010 Red Hat Inc. |
|---|
| 8 | 8 | * Copyright (C) 2009, 2010 Arnaldo Carvalho de Melo <acme@redhat.com> |
|---|
| 9 | 9 | */ |
|---|
| 10 | | -#include "util.h" |
|---|
| 10 | +#include "util.h" // lsdir(), mkdir_p(), rm_rf() |
|---|
| 11 | 11 | #include <dirent.h> |
|---|
| 12 | 12 | #include <errno.h> |
|---|
| 13 | 13 | #include <stdio.h> |
|---|
| 14 | 14 | #include <sys/stat.h> |
|---|
| 15 | 15 | #include <sys/types.h> |
|---|
| 16 | +#include "util/copyfile.h" |
|---|
| 17 | +#include "dso.h" |
|---|
| 16 | 18 | #include "build-id.h" |
|---|
| 17 | 19 | #include "event.h" |
|---|
| 20 | +#include "namespaces.h" |
|---|
| 21 | +#include "map.h" |
|---|
| 18 | 22 | #include "symbol.h" |
|---|
| 19 | 23 | #include "thread.h" |
|---|
| 20 | 24 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 27 | 31 | #include "probe-file.h" |
|---|
| 28 | 32 | #include "strlist.h" |
|---|
| 29 | 33 | |
|---|
| 30 | | -#include "sane_ctype.h" |
|---|
| 34 | +#ifdef HAVE_DEBUGINFOD_SUPPORT |
|---|
| 35 | +#include <elfutils/debuginfod.h> |
|---|
| 36 | +#endif |
|---|
| 37 | + |
|---|
| 38 | +#include <linux/ctype.h> |
|---|
| 39 | +#include <linux/zalloc.h> |
|---|
| 40 | +#include <asm/bug.h> |
|---|
| 31 | 41 | |
|---|
| 32 | 42 | static bool no_buildid_cache; |
|---|
| 33 | 43 | |
|---|
| 34 | 44 | int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, |
|---|
| 35 | 45 | union perf_event *event, |
|---|
| 36 | 46 | struct perf_sample *sample, |
|---|
| 37 | | - struct perf_evsel *evsel __maybe_unused, |
|---|
| 47 | + struct evsel *evsel __maybe_unused, |
|---|
| 38 | 48 | struct machine *machine) |
|---|
| 39 | 49 | { |
|---|
| 40 | 50 | struct addr_location al; |
|---|
| .. | .. |
|---|
| 86 | 96 | .ordered_events = true, |
|---|
| 87 | 97 | }; |
|---|
| 88 | 98 | |
|---|
| 89 | | -int build_id__sprintf(const u8 *build_id, int len, char *bf) |
|---|
| 99 | +int build_id__sprintf(const struct build_id *build_id, char *bf) |
|---|
| 90 | 100 | { |
|---|
| 91 | 101 | char *bid = bf; |
|---|
| 92 | | - const u8 *raw = build_id; |
|---|
| 93 | | - int i; |
|---|
| 102 | + const u8 *raw = build_id->data; |
|---|
| 103 | + size_t i; |
|---|
| 94 | 104 | |
|---|
| 95 | | - for (i = 0; i < len; ++i) { |
|---|
| 105 | + bf[0] = 0x0; |
|---|
| 106 | + |
|---|
| 107 | + for (i = 0; i < build_id->size; ++i) { |
|---|
| 96 | 108 | sprintf(bid, "%02x", *raw); |
|---|
| 97 | 109 | ++raw; |
|---|
| 98 | 110 | bid += 2; |
|---|
| .. | .. |
|---|
| 104 | 116 | int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id) |
|---|
| 105 | 117 | { |
|---|
| 106 | 118 | char notes[PATH_MAX]; |
|---|
| 107 | | - u8 build_id[BUILD_ID_SIZE]; |
|---|
| 119 | + struct build_id bid; |
|---|
| 108 | 120 | int ret; |
|---|
| 109 | 121 | |
|---|
| 110 | 122 | if (!root_dir) |
|---|
| .. | .. |
|---|
| 112 | 124 | |
|---|
| 113 | 125 | scnprintf(notes, sizeof(notes), "%s/sys/kernel/notes", root_dir); |
|---|
| 114 | 126 | |
|---|
| 115 | | - ret = sysfs__read_build_id(notes, build_id, sizeof(build_id)); |
|---|
| 127 | + ret = sysfs__read_build_id(notes, &bid); |
|---|
| 116 | 128 | if (ret < 0) |
|---|
| 117 | 129 | return ret; |
|---|
| 118 | 130 | |
|---|
| 119 | | - return build_id__sprintf(build_id, sizeof(build_id), sbuild_id); |
|---|
| 131 | + return build_id__sprintf(&bid, sbuild_id); |
|---|
| 120 | 132 | } |
|---|
| 121 | 133 | |
|---|
| 122 | 134 | int filename__sprintf_build_id(const char *pathname, char *sbuild_id) |
|---|
| 123 | 135 | { |
|---|
| 124 | | - u8 build_id[BUILD_ID_SIZE]; |
|---|
| 136 | + struct build_id bid; |
|---|
| 125 | 137 | int ret; |
|---|
| 126 | 138 | |
|---|
| 127 | | - ret = filename__read_build_id(pathname, build_id, sizeof(build_id)); |
|---|
| 139 | + ret = filename__read_build_id(pathname, &bid); |
|---|
| 128 | 140 | if (ret < 0) |
|---|
| 129 | 141 | return ret; |
|---|
| 130 | | - else if (ret != sizeof(build_id)) |
|---|
| 131 | | - return -EINVAL; |
|---|
| 132 | 142 | |
|---|
| 133 | | - return build_id__sprintf(build_id, sizeof(build_id), sbuild_id); |
|---|
| 143 | + return build_id__sprintf(&bid, sbuild_id); |
|---|
| 134 | 144 | } |
|---|
| 135 | 145 | |
|---|
| 136 | 146 | /* asnprintf consolidates asprintf and snprintf */ |
|---|
| .. | .. |
|---|
| 263 | 273 | if (!dso->has_build_id) |
|---|
| 264 | 274 | return NULL; |
|---|
| 265 | 275 | |
|---|
| 266 | | - build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); |
|---|
| 276 | + build_id__sprintf(&dso->bid, sbuild_id); |
|---|
| 267 | 277 | linkname = build_id_cache__linkname(sbuild_id, NULL, 0); |
|---|
| 268 | 278 | if (!linkname) |
|---|
| 269 | 279 | return NULL; |
|---|
| .. | .. |
|---|
| 288 | 298 | continue; \ |
|---|
| 289 | 299 | else |
|---|
| 290 | 300 | |
|---|
| 291 | | -static int write_buildid(const char *name, size_t name_len, u8 *build_id, |
|---|
| 301 | +static int write_buildid(const char *name, size_t name_len, struct build_id *bid, |
|---|
| 292 | 302 | pid_t pid, u16 misc, struct feat_fd *fd) |
|---|
| 293 | 303 | { |
|---|
| 294 | 304 | int err; |
|---|
| 295 | | - struct build_id_event b; |
|---|
| 305 | + struct perf_record_header_build_id b; |
|---|
| 296 | 306 | size_t len; |
|---|
| 297 | 307 | |
|---|
| 298 | 308 | len = name_len + 1; |
|---|
| 299 | 309 | len = PERF_ALIGN(len, NAME_ALIGN); |
|---|
| 300 | 310 | |
|---|
| 301 | 311 | memset(&b, 0, sizeof(b)); |
|---|
| 302 | | - memcpy(&b.build_id, build_id, BUILD_ID_SIZE); |
|---|
| 312 | + memcpy(&b.data, bid->data, bid->size); |
|---|
| 313 | + b.size = (u8) bid->size; |
|---|
| 314 | + misc |= PERF_RECORD_MISC_BUILD_ID_SIZE; |
|---|
| 303 | 315 | b.pid = pid; |
|---|
| 304 | 316 | b.header.misc = misc; |
|---|
| 305 | 317 | b.header.size = sizeof(b) + len; |
|---|
| .. | .. |
|---|
| 346 | 358 | in_kernel = pos->kernel || |
|---|
| 347 | 359 | is_kernel_module(name, |
|---|
| 348 | 360 | PERF_RECORD_MISC_CPUMODE_UNKNOWN); |
|---|
| 349 | | - err = write_buildid(name, name_len, pos->build_id, machine->pid, |
|---|
| 361 | + err = write_buildid(name, name_len, &pos->bid, machine->pid, |
|---|
| 350 | 362 | in_kernel ? kmisc : umisc, fd); |
|---|
| 351 | 363 | if (err) |
|---|
| 352 | 364 | break; |
|---|
| .. | .. |
|---|
| 364 | 376 | if (err) |
|---|
| 365 | 377 | return err; |
|---|
| 366 | 378 | |
|---|
| 367 | | - for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { |
|---|
| 379 | + for (nd = rb_first_cached(&session->machines.guests); nd; |
|---|
| 380 | + nd = rb_next(nd)) { |
|---|
| 368 | 381 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
|---|
| 369 | 382 | err = machine__write_buildid_table(pos, fd); |
|---|
| 370 | 383 | if (err) |
|---|
| .. | .. |
|---|
| 397 | 410 | if (err) |
|---|
| 398 | 411 | return err; |
|---|
| 399 | 412 | |
|---|
| 400 | | - for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { |
|---|
| 413 | + for (nd = rb_first_cached(&session->machines.guests); nd; |
|---|
| 414 | + nd = rb_next(nd)) { |
|---|
| 401 | 415 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
|---|
| 402 | 416 | |
|---|
| 403 | 417 | err = machine__hit_all_dsos(pos); |
|---|
| .. | .. |
|---|
| 629 | 643 | if (realname && access(realname, R_OK)) |
|---|
| 630 | 644 | zfree(&realname); |
|---|
| 631 | 645 | nsinfo__mountns_exit(&nsc); |
|---|
| 646 | + |
|---|
| 647 | +#ifdef HAVE_DEBUGINFOD_SUPPORT |
|---|
| 648 | + if (realname == NULL) { |
|---|
| 649 | + debuginfod_client* c = debuginfod_begin(); |
|---|
| 650 | + if (c != NULL) { |
|---|
| 651 | + int fd = debuginfod_find_debuginfo(c, |
|---|
| 652 | + (const unsigned char*)sbuild_id, 0, |
|---|
| 653 | + &realname); |
|---|
| 654 | + if (fd >= 0) |
|---|
| 655 | + close(fd); /* retaining reference by realname */ |
|---|
| 656 | + debuginfod_end(c); |
|---|
| 657 | + } |
|---|
| 658 | + } |
|---|
| 659 | +#endif |
|---|
| 660 | + |
|---|
| 632 | 661 | out: |
|---|
| 633 | 662 | free(debugfile); |
|---|
| 634 | 663 | return realname; |
|---|
| .. | .. |
|---|
| 743 | 772 | return err; |
|---|
| 744 | 773 | } |
|---|
| 745 | 774 | |
|---|
| 746 | | -static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, |
|---|
| 775 | +static int build_id_cache__add_b(const struct build_id *bid, |
|---|
| 747 | 776 | const char *name, struct nsinfo *nsi, |
|---|
| 748 | 777 | bool is_kallsyms, bool is_vdso) |
|---|
| 749 | 778 | { |
|---|
| 750 | 779 | char sbuild_id[SBUILD_ID_SIZE]; |
|---|
| 751 | 780 | |
|---|
| 752 | | - build_id__sprintf(build_id, build_id_size, sbuild_id); |
|---|
| 781 | + build_id__sprintf(bid, sbuild_id); |
|---|
| 753 | 782 | |
|---|
| 754 | 783 | return build_id_cache__add_s(sbuild_id, name, nsi, is_kallsyms, |
|---|
| 755 | 784 | is_vdso); |
|---|
| .. | .. |
|---|
| 815 | 844 | is_kallsyms = true; |
|---|
| 816 | 845 | name = machine->mmap_name; |
|---|
| 817 | 846 | } |
|---|
| 818 | | - return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, |
|---|
| 819 | | - dso->nsinfo, is_kallsyms, is_vdso); |
|---|
| 847 | + return build_id_cache__add_b(&dso->bid, name, dso->nsinfo, |
|---|
| 848 | + is_kallsyms, is_vdso); |
|---|
| 820 | 849 | } |
|---|
| 821 | 850 | |
|---|
| 822 | 851 | static int __dsos__cache_build_ids(struct list_head *head, |
|---|
| .. | .. |
|---|
| 850 | 879 | |
|---|
| 851 | 880 | ret = machine__cache_build_ids(&session->machines.host); |
|---|
| 852 | 881 | |
|---|
| 853 | | - for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { |
|---|
| 882 | + for (nd = rb_first_cached(&session->machines.guests); nd; |
|---|
| 883 | + nd = rb_next(nd)) { |
|---|
| 854 | 884 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
|---|
| 855 | 885 | ret |= machine__cache_build_ids(pos); |
|---|
| 856 | 886 | } |
|---|
| .. | .. |
|---|
| 867 | 897 | struct rb_node *nd; |
|---|
| 868 | 898 | bool ret = machine__read_build_ids(&session->machines.host, with_hits); |
|---|
| 869 | 899 | |
|---|
| 870 | | - for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { |
|---|
| 900 | + for (nd = rb_first_cached(&session->machines.guests); nd; |
|---|
| 901 | + nd = rb_next(nd)) { |
|---|
| 871 | 902 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
|---|
| 872 | 903 | ret |= machine__read_build_ids(pos, with_hits); |
|---|
| 873 | 904 | } |
|---|
| 874 | 905 | |
|---|
| 875 | 906 | return ret; |
|---|
| 876 | 907 | } |
|---|
| 908 | + |
|---|
| 909 | +void build_id__init(struct build_id *bid, const u8 *data, size_t size) |
|---|
| 910 | +{ |
|---|
| 911 | + WARN_ON(size > BUILD_ID_SIZE); |
|---|
| 912 | + memcpy(bid->data, data, size); |
|---|
| 913 | + bid->size = size; |
|---|
| 914 | +} |
|---|