summaryrefslogtreecommitdiff
path: root/tools/perf/util/build-id.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/build-id.c')
-rw-r--r--tools/perf/util/build-id.c240
1 files changed, 99 insertions, 141 deletions
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index ea9c083ab1e3..fdb35133fde4 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -42,10 +42,20 @@
static bool no_buildid_cache;
-int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
+static int mark_dso_hit_callback(struct callchain_cursor_node *node, void *data __maybe_unused)
+{
+ struct map *map = node->ms.map;
+
+ if (map)
+ dso__set_hit(map__dso(map));
+
+ return 0;
+}
+
+int build_id__mark_dso_hit(const struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample,
- struct evsel *evsel __maybe_unused,
+ struct evsel *evsel,
struct machine *machine)
{
struct addr_location al;
@@ -58,66 +68,41 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
return -1;
}
+ addr_location__init(&al);
if (thread__find_map(thread, sample->cpumode, sample->ip, &al))
- al.map->dso->hit = 1;
+ dso__set_hit(map__dso(al.map));
- thread__put(thread);
- return 0;
-}
+ addr_location__exit(&al);
-static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
- union perf_event *event,
- struct perf_sample *sample
- __maybe_unused,
- struct machine *machine)
-{
- struct thread *thread = machine__findnew_thread(machine,
- event->fork.pid,
- event->fork.tid);
-
- dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
- event->fork.ppid, event->fork.ptid);
+ sample__for_each_callchain_node(thread, evsel, sample, PERF_MAX_STACK_DEPTH,
+ /*symbols=*/false, mark_dso_hit_callback, /*data=*/NULL);
- if (thread) {
- machine__remove_thread(machine, thread);
- thread__put(thread);
- }
+ thread__put(thread);
return 0;
}
-struct perf_tool build_id__mark_dso_hit_ops = {
- .sample = build_id__mark_dso_hit,
- .mmap = perf_event__process_mmap,
- .mmap2 = perf_event__process_mmap2,
- .fork = perf_event__process_fork,
- .exit = perf_event__exit_del_thread,
- .attr = perf_event__process_attr,
- .build_id = perf_event__process_build_id,
- .ordered_events = true,
-};
-
-int build_id__sprintf(const struct build_id *build_id, char *bf)
+int build_id__snprintf(const struct build_id *build_id, char *bf, size_t bf_size)
{
- char *bid = bf;
- const u8 *raw = build_id->data;
- size_t i;
-
- bf[0] = 0x0;
+ size_t offs = 0;
- for (i = 0; i < build_id->size; ++i) {
- sprintf(bid, "%02x", *raw);
- ++raw;
- bid += 2;
+ if (build_id->size == 0) {
+ /* Ensure bf is always \0 terminated. */
+ if (bf_size > 0)
+ bf[0] = '\0';
+ return 0;
}
- return (bid - bf) + 1;
+ for (size_t i = 0; i < build_id->size && offs < bf_size; ++i)
+ offs += snprintf(bf + offs, bf_size - offs, "%02x", build_id->data[i]);
+
+ return offs;
}
-int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id)
+int sysfs__snprintf_build_id(const char *root_dir, char *sbuild_id, size_t sbuild_id_size)
{
char notes[PATH_MAX];
- struct build_id bid;
+ struct build_id bid = { .size = 0, };
int ret;
if (!root_dir)
@@ -129,19 +114,19 @@ int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id)
if (ret < 0)
return ret;
- return build_id__sprintf(&bid, sbuild_id);
+ return build_id__snprintf(&bid, sbuild_id, sbuild_id_size);
}
-int filename__sprintf_build_id(const char *pathname, char *sbuild_id)
+int filename__snprintf_build_id(const char *pathname, char *sbuild_id, size_t sbuild_id_size)
{
- struct build_id bid;
+ struct build_id bid = { .size = 0, };
int ret;
ret = filename__read_build_id(pathname, &bid);
if (ret < 0)
return ret;
- return build_id__sprintf(&bid, sbuild_id);
+ return build_id__snprintf(&bid, sbuild_id, sbuild_id_size);
}
/* asnprintf consolidates asprintf and snprintf */
@@ -242,9 +227,9 @@ static bool build_id_cache__valid_id(char *sbuild_id)
return false;
if (!strcmp(pathname, DSO__NAME_KALLSYMS))
- ret = sysfs__sprintf_build_id("/", real_sbuild_id);
+ ret = sysfs__snprintf_build_id("/", real_sbuild_id, sizeof(real_sbuild_id));
else if (pathname[0] == '/')
- ret = filename__sprintf_build_id(pathname, real_sbuild_id);
+ ret = filename__snprintf_build_id(pathname, real_sbuild_id, sizeof(real_sbuild_id));
else
ret = -EINVAL; /* Should we support other special DSO cache? */
if (ret >= 0)
@@ -270,10 +255,10 @@ char *__dso__build_id_filename(const struct dso *dso, char *bf, size_t size,
bool alloc = (bf == NULL);
int ret;
- if (!dso->has_build_id)
+ if (!dso__has_build_id(dso))
return NULL;
- build_id__sprintf(&dso->bid, sbuild_id);
+ build_id__snprintf(dso__bid(dso), sbuild_id, sizeof(sbuild_id));
linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
if (!linkname)
return NULL;
@@ -308,7 +293,7 @@ static int write_buildid(const char *name, size_t name_len, struct build_id *bid
size_t len;
len = name_len + 1;
- len = PERF_ALIGN(len, NAME_ALIGN);
+ len = PERF_ALIGN(len, sizeof(u64));
memset(&b, 0, sizeof(b));
memcpy(&b.data, bid->data, bid->size);
@@ -325,48 +310,56 @@ static int write_buildid(const char *name, size_t name_len, struct build_id *bid
return write_padded(fd, name, name_len + 1, len);
}
-static int machine__write_buildid_table(struct machine *machine,
- struct feat_fd *fd)
+struct machine__write_buildid_table_cb_args {
+ struct machine *machine;
+ struct feat_fd *fd;
+ u16 kmisc, umisc;
+};
+
+static int machine__write_buildid_table_cb(struct dso *dso, void *data)
{
- int err = 0;
- struct dso *pos;
- u16 kmisc = PERF_RECORD_MISC_KERNEL,
- umisc = PERF_RECORD_MISC_USER;
+ struct machine__write_buildid_table_cb_args *args = data;
+ const char *name;
+ size_t name_len;
+ bool in_kernel = false;
- if (!machine__is_host(machine)) {
- kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
- umisc = PERF_RECORD_MISC_GUEST_USER;
- }
+ if (!dso__has_build_id(dso))
+ return 0;
+
+ if (!dso__hit(dso) && !dso__is_vdso(dso))
+ return 0;
- dsos__for_each_with_build_id(pos, &machine->dsos.head) {
- const char *name;
- size_t name_len;
- bool in_kernel = false;
+ if (dso__is_vdso(dso)) {
+ name = dso__short_name(dso);
+ name_len = dso__short_name_len(dso);
+ } else if (dso__is_kcore(dso)) {
+ name = args->machine->mmap_name;
+ name_len = strlen(name);
+ } else {
+ name = dso__long_name(dso);
+ name_len = dso__long_name_len(dso);
+ }
- if (!pos->hit && !dso__is_vdso(pos))
- continue;
+ in_kernel = dso__kernel(dso) || is_kernel_module(name, PERF_RECORD_MISC_CPUMODE_UNKNOWN);
+ return write_buildid(name, name_len, &dso__id(dso)->build_id, args->machine->pid,
+ in_kernel ? args->kmisc : args->umisc, args->fd);
+}
- if (dso__is_vdso(pos)) {
- name = pos->short_name;
- name_len = pos->short_name_len;
- } else if (dso__is_kcore(pos)) {
- name = machine->mmap_name;
- name_len = strlen(name);
- } else {
- name = pos->long_name;
- name_len = pos->long_name_len;
- }
+static int machine__write_buildid_table(struct machine *machine, struct feat_fd *fd)
+{
+ struct machine__write_buildid_table_cb_args args = {
+ .machine = machine,
+ .fd = fd,
+ .kmisc = PERF_RECORD_MISC_KERNEL,
+ .umisc = PERF_RECORD_MISC_USER,
+ };
- in_kernel = pos->kernel ||
- is_kernel_module(name,
- PERF_RECORD_MISC_CPUMODE_UNKNOWN);
- err = write_buildid(name, name_len, &pos->bid, machine->pid,
- in_kernel ? kmisc : umisc, fd);
- if (err)
- break;
+ if (!machine__is_host(machine)) {
+ args.kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
+ args.umisc = PERF_RECORD_MISC_GUEST_USER;
}
- return err;
+ return dsos__for_each_dso(&machine->dsos, machine__write_buildid_table_cb, &args);
}
int perf_session__write_buildid_table(struct perf_session *session,
@@ -388,42 +381,6 @@ int perf_session__write_buildid_table(struct perf_session *session,
return err;
}
-static int __dsos__hit_all(struct list_head *head)
-{
- struct dso *pos;
-
- list_for_each_entry(pos, head, node)
- pos->hit = true;
-
- return 0;
-}
-
-static int machine__hit_all_dsos(struct machine *machine)
-{
- return __dsos__hit_all(&machine->dsos.head);
-}
-
-int dsos__hit_all(struct perf_session *session)
-{
- struct rb_node *nd;
- int err;
-
- err = machine__hit_all_dsos(&session->machines.host);
- if (err)
- return err;
-
- for (nd = rb_first_cached(&session->machines.guests); nd;
- nd = rb_next(nd)) {
- struct machine *pos = rb_entry(nd, struct machine, rb_node);
-
- err = machine__hit_all_dsos(pos);
- if (err)
- return err;
- }
-
- return 0;
-}
-
void disable_buildid_cache(void)
{
no_buildid_cache = true;
@@ -558,7 +515,7 @@ char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
struct nsinfo *nsi, bool is_kallsyms,
bool is_vdso)
{
- char *realname = (char *)name, *filename;
+ char *realname = NULL, *filename;
bool slash = is_kallsyms || is_vdso;
if (!slash)
@@ -569,9 +526,7 @@ char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
sbuild_id ? "/" : "", sbuild_id ?: "") < 0)
filename = NULL;
- if (!slash)
- free(realname);
-
+ free(realname);
return filename;
}
@@ -829,7 +784,7 @@ static int build_id_cache__add_b(const struct build_id *bid,
{
char sbuild_id[SBUILD_ID_SIZE];
- build_id__sprintf(bid, sbuild_id);
+ build_id__snprintf(bid, sbuild_id, sizeof(sbuild_id));
return __build_id_cache__add_s(sbuild_id, name, nsi, is_kallsyms,
is_vdso, proper_name, root_dir);
@@ -901,14 +856,14 @@ static int filename__read_build_id_ns(const char *filename,
static bool dso__build_id_mismatch(struct dso *dso, const char *name)
{
- struct build_id bid;
+ struct build_id bid = { .size = 0, };
bool ret = false;
- mutex_lock(&dso->lock);
- if (filename__read_build_id_ns(name, &bid, dso->nsinfo) >= 0)
+ mutex_lock(dso__lock(dso));
+ if (filename__read_build_id_ns(name, &bid, dso__nsinfo(dso)) >= 0)
ret = !dso__build_id_equal(dso, &bid);
- mutex_unlock(&dso->lock);
+ mutex_unlock(dso__lock(dso));
return ret;
}
@@ -918,13 +873,13 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine,
{
bool is_kallsyms = dso__is_kallsyms(dso);
bool is_vdso = dso__is_vdso(dso);
- const char *name = dso->long_name;
+ const char *name = dso__long_name(dso);
const char *proper_name = NULL;
const char *root_dir = NULL;
char *allocated_name = NULL;
int ret = 0;
- if (!dso->has_build_id)
+ if (!dso__has_build_id(dso) || !dso__hit(dso))
return 0;
if (dso__is_kcore(dso)) {
@@ -949,10 +904,10 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine,
if (!is_kallsyms && dso__build_id_mismatch(dso, name))
goto out_free;
- mutex_lock(&dso->lock);
- ret = build_id_cache__add_b(&dso->bid, name, dso->nsinfo,
+ mutex_lock(dso__lock(dso));
+ ret = build_id_cache__add_b(dso__bid(dso), name, dso__nsinfo(dso),
is_kallsyms, is_vdso, proper_name, root_dir);
- mutex_unlock(&dso->lock);
+ mutex_unlock(dso__lock(dso));
out_free:
free(allocated_name);
return ret;
@@ -992,7 +947,7 @@ int perf_session__cache_build_ids(struct perf_session *session)
static bool machine__read_build_ids(struct machine *machine, bool with_hits)
{
- return __dsos__read_build_ids(&machine->dsos.head, with_hits);
+ return dsos__read_build_ids(&machine->dsos, with_hits);
}
bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
@@ -1011,7 +966,10 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
void build_id__init(struct build_id *bid, const u8 *data, size_t size)
{
- WARN_ON(size > BUILD_ID_SIZE);
+ if (size > BUILD_ID_SIZE) {
+ pr_debug("Truncating build_id size from %zd\n", size);
+ size = BUILD_ID_SIZE;
+ }
memcpy(bid->data, data, size);
bid->size = size;
}