.. | .. |
---|
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 | +} |
---|