1 // SPDX-License-Identifier: GPL-2.0
7 * Copyright (C) 2009, 2010 Red Hat Inc.
8 * Copyright (C) 2009, 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
10 #include "util.h" // lsdir(), mkdir_p(), rm_rf()
15 #include <sys/types.h>
16 #include "util/copyfile.h"
20 #include "namespaces.h"
24 #include <linux/kernel.h>
31 #include "probe-file.h"
34 #ifdef HAVE_DEBUGINFOD_SUPPORT
35 #include <elfutils/debuginfod.h>
38 #include <linux/ctype.h>
39 #include <linux/zalloc.h>
40 #include <linux/string.h>
43 static bool no_buildid_cache
;
45 int build_id__mark_dso_hit(const struct perf_tool
*tool __maybe_unused
,
46 union perf_event
*event
,
47 struct perf_sample
*sample
,
48 struct evsel
*evsel __maybe_unused
,
49 struct machine
*machine
)
51 struct addr_location al
;
52 struct thread
*thread
= machine__findnew_thread(machine
, sample
->pid
,
56 pr_err("problem processing %d event, skipping it.\n",
61 addr_location__init(&al
);
62 if (thread__find_map(thread
, sample
->cpumode
, sample
->ip
, &al
))
63 dso__set_hit(map__dso(al
.map
));
65 addr_location__exit(&al
);
70 int build_id__sprintf(const struct build_id
*build_id
, char *bf
)
73 const u8
*raw
= build_id
->data
;
78 for (i
= 0; i
< build_id
->size
; ++i
) {
79 sprintf(bid
, "%02x", *raw
);
84 return (bid
- bf
) + 1;
87 int sysfs__sprintf_build_id(const char *root_dir
, char *sbuild_id
)
96 scnprintf(notes
, sizeof(notes
), "%s/sys/kernel/notes", root_dir
);
98 ret
= sysfs__read_build_id(notes
, &bid
);
102 return build_id__sprintf(&bid
, sbuild_id
);
105 int filename__sprintf_build_id(const char *pathname
, char *sbuild_id
)
110 ret
= filename__read_build_id(pathname
, &bid
);
114 return build_id__sprintf(&bid
, sbuild_id
);
117 /* asnprintf consolidates asprintf and snprintf */
118 static int asnprintf(char **strp
, size_t size
, const char *fmt
, ...)
128 ret
= vsnprintf(*strp
, size
, fmt
, ap
);
130 ret
= vasprintf(strp
, fmt
, ap
);
136 char *build_id_cache__kallsyms_path(const char *sbuild_id
, char *bf
,
139 bool retry_old
= true;
141 snprintf(bf
, size
, "%s/%s/%s/kallsyms",
142 buildid_dir
, DSO__NAME_KALLSYMS
, sbuild_id
);
144 if (!access(bf
, F_OK
))
147 /* Try old style kallsyms cache */
148 snprintf(bf
, size
, "%s/%s/%s",
149 buildid_dir
, DSO__NAME_KALLSYMS
, sbuild_id
);
157 char *build_id_cache__linkname(const char *sbuild_id
, char *bf
, size_t size
)
160 int ret
= asnprintf(&bf
, size
, "%s/.build-id/%.2s/%s", buildid_dir
,
161 sbuild_id
, sbuild_id
+ 2);
162 if (ret
< 0 || (tmp
&& size
< (unsigned int)ret
))
167 /* The caller is responsible to free the returned buffer. */
168 char *build_id_cache__origname(const char *sbuild_id
)
172 char *ret
= NULL
, *p
;
173 size_t offs
= 5; /* == strlen("../..") */
176 linkname
= build_id_cache__linkname(sbuild_id
, NULL
, 0);
180 len
= readlink(linkname
, buf
, sizeof(buf
) - 1);
185 /* The link should be "../..<origpath>/<sbuild_id>" */
186 p
= strrchr(buf
, '/'); /* Cut off the "/<sbuild_id>" */
187 if (p
&& (p
> buf
+ offs
)) {
189 if (buf
[offs
+ 1] == '[')
191 * This is a DSO name, like [kernel.kallsyms].
192 * Skip the first '/', since this is not the
193 * cache of a regular file.
195 ret
= strdup(buf
+ offs
); /* Skip "../..[/]" */
202 /* Check if the given build_id cache is valid on current running system */
203 static bool build_id_cache__valid_id(char *sbuild_id
)
205 char real_sbuild_id
[SBUILD_ID_SIZE
] = "";
210 pathname
= build_id_cache__origname(sbuild_id
);
214 if (!strcmp(pathname
, DSO__NAME_KALLSYMS
))
215 ret
= sysfs__sprintf_build_id("/", real_sbuild_id
);
216 else if (pathname
[0] == '/')
217 ret
= filename__sprintf_build_id(pathname
, real_sbuild_id
);
219 ret
= -EINVAL
; /* Should we support other special DSO cache? */
221 result
= (strcmp(sbuild_id
, real_sbuild_id
) == 0);
227 static const char *build_id_cache__basename(bool is_kallsyms
, bool is_vdso
,
230 return is_kallsyms
? "kallsyms" : (is_vdso
? "vdso" : (is_debug
?
234 char *__dso__build_id_filename(const struct dso
*dso
, char *bf
, size_t size
,
235 bool is_debug
, bool is_kallsyms
)
237 bool is_vdso
= dso__is_vdso((struct dso
*)dso
);
238 char sbuild_id
[SBUILD_ID_SIZE
];
240 bool alloc
= (bf
== NULL
);
243 if (!dso__has_build_id(dso
))
246 build_id__sprintf(dso__bid_const(dso
), sbuild_id
);
247 linkname
= build_id_cache__linkname(sbuild_id
, NULL
, 0);
251 /* Check if old style build_id cache */
252 if (is_regular_file(linkname
))
253 ret
= asnprintf(&bf
, size
, "%s", linkname
);
255 ret
= asnprintf(&bf
, size
, "%s/%s", linkname
,
256 build_id_cache__basename(is_kallsyms
, is_vdso
,
258 if (ret
< 0 || (!alloc
&& size
< (unsigned int)ret
))
265 char *dso__build_id_filename(const struct dso
*dso
, char *bf
, size_t size
,
268 bool is_kallsyms
= dso__is_kallsyms((struct dso
*)dso
);
270 return __dso__build_id_filename(dso
, bf
, size
, is_debug
, is_kallsyms
);
273 static int write_buildid(const char *name
, size_t name_len
, struct build_id
*bid
,
274 pid_t pid
, u16 misc
, struct feat_fd
*fd
)
277 struct perf_record_header_build_id b
;
280 len
= sizeof(b
) + name_len
+ 1;
281 len
= PERF_ALIGN(len
, sizeof(u64
));
283 memset(&b
, 0, sizeof(b
));
284 memcpy(&b
.data
, bid
->data
, bid
->size
);
285 b
.size
= (u8
) bid
->size
;
286 misc
|= PERF_RECORD_MISC_BUILD_ID_SIZE
;
288 b
.header
.misc
= misc
;
291 err
= do_write(fd
, &b
, sizeof(b
));
295 return write_padded(fd
, name
, name_len
+ 1, len
);
298 struct machine__write_buildid_table_cb_args
{
299 struct machine
*machine
;
304 static int machine__write_buildid_table_cb(struct dso
*dso
, void *data
)
306 struct machine__write_buildid_table_cb_args
*args
= data
;
309 bool in_kernel
= false;
311 if (!dso__has_build_id(dso
))
314 if (!dso__hit(dso
) && !dso__is_vdso(dso
))
317 if (dso__is_vdso(dso
)) {
318 name
= dso__short_name(dso
);
319 name_len
= dso__short_name_len(dso
);
320 } else if (dso__is_kcore(dso
)) {
321 name
= args
->machine
->mmap_name
;
322 name_len
= strlen(name
);
324 name
= dso__long_name(dso
);
325 name_len
= dso__long_name_len(dso
);
328 in_kernel
= dso__kernel(dso
) || is_kernel_module(name
, PERF_RECORD_MISC_CPUMODE_UNKNOWN
);
329 return write_buildid(name
, name_len
, dso__bid(dso
), args
->machine
->pid
,
330 in_kernel
? args
->kmisc
: args
->umisc
, args
->fd
);
333 static int machine__write_buildid_table(struct machine
*machine
, struct feat_fd
*fd
)
335 struct machine__write_buildid_table_cb_args args
= {
338 .kmisc
= PERF_RECORD_MISC_KERNEL
,
339 .umisc
= PERF_RECORD_MISC_USER
,
342 if (!machine__is_host(machine
)) {
343 args
.kmisc
= PERF_RECORD_MISC_GUEST_KERNEL
;
344 args
.umisc
= PERF_RECORD_MISC_GUEST_USER
;
347 return dsos__for_each_dso(&machine
->dsos
, machine__write_buildid_table_cb
, &args
);
350 int perf_session__write_buildid_table(struct perf_session
*session
,
354 int err
= machine__write_buildid_table(&session
->machines
.host
, fd
);
359 for (nd
= rb_first_cached(&session
->machines
.guests
); nd
;
361 struct machine
*pos
= rb_entry(nd
, struct machine
, rb_node
);
362 err
= machine__write_buildid_table(pos
, fd
);
369 void disable_buildid_cache(void)
371 no_buildid_cache
= true;
374 static bool lsdir_bid_head_filter(const char *name __maybe_unused
,
377 return (strlen(d
->d_name
) == 2) &&
378 isxdigit(d
->d_name
[0]) && isxdigit(d
->d_name
[1]);
381 static bool lsdir_bid_tail_filter(const char *name __maybe_unused
,
385 while (isxdigit(d
->d_name
[i
]) && i
< SBUILD_ID_SIZE
- 3)
387 return (i
>= SBUILD_ID_MIN_SIZE
- 3) && (i
<= SBUILD_ID_SIZE
- 3) &&
388 (d
->d_name
[i
] == '\0');
391 struct strlist
*build_id_cache__list_all(bool validonly
)
393 struct strlist
*toplist
, *linklist
= NULL
, *bidlist
;
394 struct str_node
*nd
, *nd2
;
395 char *topdir
, *linkdir
= NULL
;
396 char sbuild_id
[SBUILD_ID_SIZE
];
398 /* for filename__ functions */
402 /* Open the top-level directory */
403 if (asprintf(&topdir
, "%s/.build-id/", buildid_dir
) < 0)
406 bidlist
= strlist__new(NULL
, NULL
);
410 toplist
= lsdir(topdir
, lsdir_bid_head_filter
);
412 pr_debug("Error in lsdir(%s): %d\n", topdir
, errno
);
413 /* If there is no buildid cache, return an empty list */
419 strlist__for_each_entry(nd
, toplist
) {
420 if (asprintf(&linkdir
, "%s/%s", topdir
, nd
->s
) < 0)
422 /* Open the lower-level directory */
423 linklist
= lsdir(linkdir
, lsdir_bid_tail_filter
);
425 pr_debug("Error in lsdir(%s): %d\n", linkdir
, errno
);
428 strlist__for_each_entry(nd2
, linklist
) {
429 if (snprintf(sbuild_id
, SBUILD_ID_SIZE
, "%s%s",
430 nd
->s
, nd2
->s
) > SBUILD_ID_SIZE
- 1)
432 if (validonly
&& !build_id_cache__valid_id(sbuild_id
))
434 if (strlist__add(bidlist
, sbuild_id
) < 0)
437 strlist__delete(linklist
);
442 strlist__delete(toplist
);
449 strlist__delete(linklist
);
451 strlist__delete(bidlist
);
456 static bool str_is_build_id(const char *maybe_sbuild_id
, size_t len
)
460 for (i
= 0; i
< len
; i
++) {
461 if (!isxdigit(maybe_sbuild_id
[i
]))
467 /* Return the valid complete build-id */
468 char *build_id_cache__complement(const char *incomplete_sbuild_id
)
470 struct strlist
*bidlist
;
471 struct str_node
*nd
, *cand
= NULL
;
472 char *sbuild_id
= NULL
;
473 size_t len
= strlen(incomplete_sbuild_id
);
475 if (len
>= SBUILD_ID_SIZE
||
476 !str_is_build_id(incomplete_sbuild_id
, len
))
479 bidlist
= build_id_cache__list_all(true);
483 strlist__for_each_entry(nd
, bidlist
) {
484 if (strncmp(nd
->s
, incomplete_sbuild_id
, len
) != 0)
486 if (cand
) { /* Error: There are more than 2 candidates. */
493 sbuild_id
= strdup(cand
->s
);
494 strlist__delete(bidlist
);
499 char *build_id_cache__cachedir(const char *sbuild_id
, const char *name
,
500 struct nsinfo
*nsi
, bool is_kallsyms
,
503 char *realname
= NULL
, *filename
;
504 bool slash
= is_kallsyms
|| is_vdso
;
507 realname
= nsinfo__realpath(name
, nsi
);
509 if (asprintf(&filename
, "%s%s%s%s%s", buildid_dir
, slash
? "/" : "",
510 is_vdso
? DSO__NAME_VDSO
: (realname
? realname
: name
),
511 sbuild_id
? "/" : "", sbuild_id
?: "") < 0)
518 int build_id_cache__list_build_ids(const char *pathname
, struct nsinfo
*nsi
,
519 struct strlist
**result
)
524 dir_name
= build_id_cache__cachedir(NULL
, pathname
, nsi
, false, false);
528 *result
= lsdir(dir_name
, lsdir_no_dot_filter
);
536 #if defined(HAVE_LIBELF_SUPPORT) && defined(HAVE_GELF_GETNOTE_SUPPORT)
537 static int build_id_cache__add_sdt_cache(const char *sbuild_id
,
538 const char *realname
,
541 struct probe_cache
*cache
;
545 cache
= probe_cache__new(sbuild_id
, nsi
);
549 nsinfo__mountns_enter(nsi
, &nsc
);
550 ret
= probe_cache__scan_sdt(cache
, realname
);
551 nsinfo__mountns_exit(&nsc
);
553 pr_debug4("Found %d SDTs in %s\n", ret
, realname
);
554 if (probe_cache__commit(cache
) < 0)
557 probe_cache__delete(cache
);
561 #define build_id_cache__add_sdt_cache(sbuild_id, realname, nsi) (0)
564 static char *build_id_cache__find_debug(const char *sbuild_id
,
566 const char *root_dir
)
568 const char *dirname
= "/usr/lib/debug/.build-id/";
569 char *realname
= NULL
;
570 char dirbuf
[PATH_MAX
];
575 debugfile
= calloc(1, PATH_MAX
);
580 path__join(dirbuf
, PATH_MAX
, root_dir
, dirname
);
584 len
= __symbol__join_symfs(debugfile
, PATH_MAX
, dirname
);
585 snprintf(debugfile
+ len
, PATH_MAX
- len
, "%.2s/%s.debug", sbuild_id
,
588 nsinfo__mountns_enter(nsi
, &nsc
);
589 realname
= realpath(debugfile
, NULL
);
590 if (realname
&& access(realname
, R_OK
))
592 nsinfo__mountns_exit(&nsc
);
594 #ifdef HAVE_DEBUGINFOD_SUPPORT
595 if (realname
== NULL
) {
596 debuginfod_client
* c
;
598 pr_debug("Downloading debug info with build id %s\n", sbuild_id
);
600 c
= debuginfod_begin();
602 int fd
= debuginfod_find_debuginfo(c
,
603 (const unsigned char*)sbuild_id
, 0,
606 close(fd
); /* retaining reference by realname */
618 build_id_cache__add(const char *sbuild_id
, const char *name
, const char *realname
,
619 struct nsinfo
*nsi
, bool is_kallsyms
, bool is_vdso
,
620 const char *proper_name
, const char *root_dir
)
622 const size_t size
= PATH_MAX
;
623 char *filename
= NULL
, *dir_name
= NULL
, *linkname
= zalloc(size
), *tmp
;
624 char *debugfile
= NULL
;
630 dir_name
= build_id_cache__cachedir(sbuild_id
, proper_name
, nsi
, is_kallsyms
,
635 /* Remove old style build-id cache */
636 if (is_regular_file(dir_name
))
637 if (unlink(dir_name
))
640 if (mkdir_p(dir_name
, 0755))
643 /* Save the allocated buildid dirname */
644 if (asprintf(&filename
, "%s/%s", dir_name
,
645 build_id_cache__basename(is_kallsyms
, is_vdso
,
651 if (access(filename
, F_OK
)) {
653 if (copyfile("/proc/kallsyms", filename
))
655 } else if (nsi
&& nsinfo__need_setns(nsi
)) {
656 if (copyfile_ns(name
, filename
, nsi
))
658 } else if (link(realname
, filename
) && errno
!= EEXIST
) {
661 if (!(stat(name
, &f_stat
) < 0) &&
662 copyfile_mode(name
, filename
, f_stat
.st_mode
))
667 /* Some binaries are stripped, but have .debug files with their symbol
668 * table. Check to see if we can locate one of those, since the elf
669 * file itself may not be very useful to users of our tools without a
672 if (!is_kallsyms
&& !is_vdso
&&
673 strncmp(".ko", name
+ strlen(name
) - 3, 3)) {
674 debugfile
= build_id_cache__find_debug(sbuild_id
, nsi
, root_dir
);
677 if (asprintf(&filename
, "%s/%s", dir_name
,
678 build_id_cache__basename(false, false, true)) < 0) {
682 if (access(filename
, F_OK
)) {
683 if (nsi
&& nsinfo__need_setns(nsi
)) {
684 if (copyfile_ns(debugfile
, filename
,
687 } else if (link(debugfile
, filename
) &&
689 copyfile(debugfile
, filename
))
695 if (!build_id_cache__linkname(sbuild_id
, linkname
, size
))
697 tmp
= strrchr(linkname
, '/');
700 if (access(linkname
, X_OK
) && mkdir_p(linkname
, 0755))
704 tmp
= dir_name
+ strlen(buildid_dir
) - 5;
705 memcpy(tmp
, "../..", 5);
707 if (symlink(tmp
, linkname
) == 0) {
709 } else if (errno
== EEXIST
) {
713 len
= readlink(linkname
, path
, sizeof(path
) - 1);
715 pr_err("Can't read link: %s\n", linkname
);
720 if (strcmp(tmp
, path
)) {
721 pr_debug("build <%s> already linked to %s\n",
722 sbuild_id
, linkname
);
727 /* Update SDT cache : error is just warned */
729 build_id_cache__add_sdt_cache(sbuild_id
, realname
, nsi
) < 0)
730 pr_debug4("Failed to update/scan SDT cache for %s\n", realname
);
740 int __build_id_cache__add_s(const char *sbuild_id
, const char *name
,
741 struct nsinfo
*nsi
, bool is_kallsyms
, bool is_vdso
,
742 const char *proper_name
, const char *root_dir
)
744 char *realname
= NULL
;
749 realname
= nsinfo__realpath(name
, nsi
);
751 realname
= realpath(name
, NULL
);
756 err
= build_id_cache__add(sbuild_id
, name
, realname
, nsi
,
757 is_kallsyms
, is_vdso
, proper_name
, root_dir
);
764 static int build_id_cache__add_b(const struct build_id
*bid
,
765 const char *name
, struct nsinfo
*nsi
,
766 bool is_kallsyms
, bool is_vdso
,
767 const char *proper_name
,
768 const char *root_dir
)
770 char sbuild_id
[SBUILD_ID_SIZE
];
772 build_id__sprintf(bid
, sbuild_id
);
774 return __build_id_cache__add_s(sbuild_id
, name
, nsi
, is_kallsyms
,
775 is_vdso
, proper_name
, root_dir
);
778 bool build_id_cache__cached(const char *sbuild_id
)
781 char *filename
= build_id_cache__linkname(sbuild_id
, NULL
, 0);
783 if (filename
&& !access(filename
, F_OK
))
790 int build_id_cache__remove_s(const char *sbuild_id
)
792 const size_t size
= PATH_MAX
;
793 char *filename
= zalloc(size
),
794 *linkname
= zalloc(size
), *tmp
;
797 if (filename
== NULL
|| linkname
== NULL
)
800 if (!build_id_cache__linkname(sbuild_id
, linkname
, size
))
803 if (access(linkname
, F_OK
))
806 if (readlink(linkname
, filename
, size
- 1) < 0)
809 if (unlink(linkname
))
813 * Since the link is relative, we must make it absolute:
815 tmp
= strrchr(linkname
, '/') + 1;
816 snprintf(tmp
, size
- (tmp
- linkname
), "%s", filename
);
828 static int filename__read_build_id_ns(const char *filename
,
829 struct build_id
*bid
,
835 nsinfo__mountns_enter(nsi
, &nsc
);
836 ret
= filename__read_build_id(filename
, bid
);
837 nsinfo__mountns_exit(&nsc
);
842 static bool dso__build_id_mismatch(struct dso
*dso
, const char *name
)
847 mutex_lock(dso__lock(dso
));
848 if (filename__read_build_id_ns(name
, &bid
, dso__nsinfo(dso
)) >= 0)
849 ret
= !dso__build_id_equal(dso
, &bid
);
851 mutex_unlock(dso__lock(dso
));
856 static int dso__cache_build_id(struct dso
*dso
, struct machine
*machine
,
857 void *priv __maybe_unused
)
859 bool is_kallsyms
= dso__is_kallsyms(dso
);
860 bool is_vdso
= dso__is_vdso(dso
);
861 const char *name
= dso__long_name(dso
);
862 const char *proper_name
= NULL
;
863 const char *root_dir
= NULL
;
864 char *allocated_name
= NULL
;
867 if (!dso__has_build_id(dso
))
870 if (dso__is_kcore(dso
)) {
872 name
= machine
->mmap_name
;
875 if (!machine__is_host(machine
)) {
876 if (*machine
->root_dir
) {
877 root_dir
= machine
->root_dir
;
878 ret
= asprintf(&allocated_name
, "%s/%s", root_dir
, name
);
882 name
= allocated_name
;
883 } else if (is_kallsyms
) {
884 /* Cannot get guest kallsyms */
889 if (!is_kallsyms
&& dso__build_id_mismatch(dso
, name
))
892 mutex_lock(dso__lock(dso
));
893 ret
= build_id_cache__add_b(dso__bid(dso
), name
, dso__nsinfo(dso
),
894 is_kallsyms
, is_vdso
, proper_name
, root_dir
);
895 mutex_unlock(dso__lock(dso
));
897 free(allocated_name
);
902 machines__for_each_dso(struct machines
*machines
, machine__dso_t fn
, void *priv
)
904 int ret
= machine__for_each_dso(&machines
->host
, fn
, priv
);
907 for (nd
= rb_first_cached(&machines
->guests
); nd
;
909 struct machine
*pos
= rb_entry(nd
, struct machine
, rb_node
);
911 ret
|= machine__for_each_dso(pos
, fn
, priv
);
916 int __perf_session__cache_build_ids(struct perf_session
*session
,
917 machine__dso_t fn
, void *priv
)
919 if (no_buildid_cache
)
922 if (mkdir(buildid_dir
, 0755) != 0 && errno
!= EEXIST
)
925 return machines__for_each_dso(&session
->machines
, fn
, priv
) ? -1 : 0;
928 int perf_session__cache_build_ids(struct perf_session
*session
)
930 return __perf_session__cache_build_ids(session
, dso__cache_build_id
, NULL
);
933 static bool machine__read_build_ids(struct machine
*machine
, bool with_hits
)
935 return dsos__read_build_ids(&machine
->dsos
, with_hits
);
938 bool perf_session__read_build_ids(struct perf_session
*session
, bool with_hits
)
941 bool ret
= machine__read_build_ids(&session
->machines
.host
, with_hits
);
943 for (nd
= rb_first_cached(&session
->machines
.guests
); nd
;
945 struct machine
*pos
= rb_entry(nd
, struct machine
, rb_node
);
946 ret
|= machine__read_build_ids(pos
, with_hits
);
952 void build_id__init(struct build_id
*bid
, const u8
*data
, size_t size
)
954 WARN_ON(size
> BUILD_ID_SIZE
);
955 memcpy(bid
->data
, data
, size
);
959 bool build_id__is_defined(const struct build_id
*bid
)
961 return bid
&& bid
->size
? !!memchr_inv(bid
->data
, 0, bid
->size
) : false;