diff options
Diffstat (limited to '')
-rw-r--r-- | tools/perf/util/dsos.c | 59 |
1 files changed, 52 insertions, 7 deletions
diff --git a/tools/perf/util/dsos.c b/tools/perf/util/dsos.c index 591707c69c39..2bd23e4cf19e 100644 --- a/tools/perf/util/dsos.c +++ b/tools/perf/util/dsos.c @@ -2,12 +2,15 @@ #include "debug.h" #include "dsos.h" #include "dso.h" +#include "util.h" #include "vdso.h" #include "namespaces.h" +#include <errno.h> #include <libgen.h> #include <stdlib.h> #include <string.h> #include <symbol.h> // filename__read_build_id +#include <unistd.h> static int __dso_id__cmp(struct dso_id *a, struct dso_id *b) { @@ -20,19 +23,46 @@ static int __dso_id__cmp(struct dso_id *a, struct dso_id *b) if (a->ino > b->ino) return -1; if (a->ino < b->ino) return 1; - if (a->ino_generation > b->ino_generation) return -1; - if (a->ino_generation < b->ino_generation) return 1; + /* + * Synthesized MMAP events have zero ino_generation, avoid comparing + * them with MMAP events with actual ino_generation. + * + * I found it harmful because the mismatch resulted in a new + * dso that did not have a build ID whereas the original dso did have a + * build ID. The build ID was essential because the object was not found + * otherwise. - Adrian + */ + if (a->ino_generation && b->ino_generation) { + if (a->ino_generation > b->ino_generation) return -1; + if (a->ino_generation < b->ino_generation) return 1; + } return 0; } +static bool dso_id__empty(struct dso_id *id) +{ + if (!id) + return true; + + return !id->maj && !id->min && !id->ino && !id->ino_generation; +} + +static void dso__inject_id(struct dso *dso, struct dso_id *id) +{ + dso->id.maj = id->maj; + dso->id.min = id->min; + dso->id.ino = id->ino; + dso->id.ino_generation = id->ino_generation; +} + static int dso_id__cmp(struct dso_id *a, struct dso_id *b) { /* * The second is always dso->id, so zeroes if not set, assume passing * NULL for a means a zeroed id */ - if (a == NULL) + if (dso_id__empty(a) || dso_id__empty(b)) return 0; return __dso_id__cmp(a, b); @@ -57,10 +87,19 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits) continue; } nsinfo__mountns_enter(pos->nsinfo, &nsc); - if (filename__read_build_id(pos->long_name, pos->build_id, - sizeof(pos->build_id)) > 0) { + if (filename__read_build_id(pos->long_name, &pos->bid) > 0) { have_build_id = true; pos->has_build_id = true; + } else if (errno == ENOENT && pos->nsinfo) { + char *new_name = filename_with_chroot(pos->nsinfo->pid, + pos->long_name); + + if (new_name && filename__read_build_id(new_name, + &pos->bid) > 0) { + have_build_id = true; + pos->has_build_id = true; + } + free(new_name); } nsinfo__mountns_exit(&nsc); } @@ -249,6 +288,10 @@ struct dso *__dsos__addnew(struct dsos *dsos, const char *name) static struct dso *__dsos__findnew_id(struct dsos *dsos, const char *name, struct dso_id *id) { struct dso *dso = __dsos__find_id(dsos, name, id, false); + + if (dso && dso_id__empty(&dso->id) && !dso_id__empty(id)) + dso__inject_id(dso, id); + return dso ? dso : __dsos__addnew_id(dsos, name, id); } @@ -268,10 +311,12 @@ size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, size_t ret = 0; list_for_each_entry(pos, head, node) { + char sbuild_id[SBUILD_ID_SIZE]; + if (skip && skip(pos, parm)) continue; - ret += dso__fprintf_buildid(pos, fp); - ret += fprintf(fp, " %s\n", pos->long_name); + build_id__sprintf(&pos->bid, sbuild_id); + ret += fprintf(fp, "%-40s %s\n", sbuild_id, pos->long_name); } return ret; } |