]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
perf dsos: Move the dsos struct and its methods to separate source files
authorArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 30 Aug 2019 14:11:01 +0000 (11:11 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Sun, 1 Sep 2019 01:24:10 +0000 (22:24 -0300)
So that we can reduce the header dependency tree further, in the process
noticed that lots of places were getting even things like build-id
routines and 'struct perf_tool' definition indirectly, so fix all those
too.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lkml.kernel.org/n/tip-ti0btma9ow5ndrytyoqdk62j@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
49 files changed:
tools/perf/builtin-annotate.c
tools/perf/builtin-buildid-cache.c
tools/perf/builtin-buildid-list.c
tools/perf/builtin-inject.c
tools/perf/builtin-kallsyms.c
tools/perf/builtin-kmem.c
tools/perf/builtin-kvm.c
tools/perf/builtin-mem.c
tools/perf/builtin-report.c
tools/perf/builtin-script.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/tests/code-reading.c
tools/perf/tests/dso-data.c
tools/perf/tests/dwarf-unwind.c
tools/perf/tests/event_update.c
tools/perf/tests/hists_common.c
tools/perf/tests/hists_cumulate.c
tools/perf/tests/hists_output.c
tools/perf/tests/vmlinux-kallsyms.c
tools/perf/ui/browsers/annotate.c
tools/perf/ui/browsers/hists.c
tools/perf/util/Build
tools/perf/util/bpf-event.c
tools/perf/util/callchain.c
tools/perf/util/cs-etm.c
tools/perf/util/db-export.c
tools/perf/util/dso.c
tools/perf/util/dso.h
tools/perf/util/dsos.c [new file with mode: 0644]
tools/perf/util/dsos.h [new file with mode: 0644]
tools/perf/util/event.c
tools/perf/util/header.c
tools/perf/util/hist.c
tools/perf/util/intel-bts.c
tools/perf/util/jitdump.c
tools/perf/util/machine.c
tools/perf/util/machine.h
tools/perf/util/map.c
tools/perf/util/parse-events.c
tools/perf/util/probe-event.c
tools/perf/util/s390-cpumsf.c
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/sort.c
tools/perf/util/thread.c
tools/perf/util/unwind-libdw.c
tools/perf/util/unwind-libunwind.c
tools/perf/util/vdso.c

index 9bb637165bf912bae06174e06076f1c673a08351..738471a0a54991b515aff83916c71d2afeff36fa 100644 (file)
@@ -27,6 +27,7 @@
 #include "util/thread.h"
 #include "util/sort.h"
 #include "util/hist.h"
+#include "util/dso.h"
 #include "util/map.h"
 #include "util/session.h"
 #include "util/tool.h"
index 9e756004ef28dd773204691e88ddebfbab64e448..b035911969b8cd89121cd1593b802ac22a7e53ba 100644 (file)
@@ -22,6 +22,7 @@
 #include "util/strlist.h"
 #include "util/build-id.h"
 #include "util/session.h"
+#include "util/dso.h"
 #include "util/symbol.h"
 #include "util/time-utils.h"
 #include "util/util.h"
index 72bdc0eba9904b69160951c1a608895b3d782e6d..38b2ec61c021e8ce26dc03c49a47669032104b5c 100644 (file)
@@ -12,6 +12,7 @@
 #include "util/build-id.h"
 #include "util/cache.h"
 #include "util/debug.h"
+#include "util/dso.h"
 #include <subcmd/parse-options.h>
 #include "util/session.h"
 #include "util/symbol.h"
index ae46de46e826e1278883fbfca88000ed6703a420..c14f40b858bc760c1b9dc632fb4db617a19887b4 100644 (file)
@@ -9,6 +9,7 @@
 #include "builtin.h"
 
 #include "util/color.h"
+#include "util/dso.h"
 #include "util/evlist.h"
 #include "util/evsel.h"
 #include "util/map.h"
index c1a44671b0b548d47b9c74223cb236c7491754d6..c08ee81529e8afeb9bea4e07763ddde1c53f3570 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/compiler.h>
 #include <subcmd/parse-options.h>
 #include "debug.h"
+#include "dso.h"
 #include "machine.h"
 #include "map.h"
 #include "symbol.h"
index 378b09c910a86888dcc142c6aac012abb4173649..b5682beaad72517a02116f72b688ca076df9294c 100644 (file)
@@ -2,6 +2,7 @@
 #include "builtin.h"
 #include "perf.h"
 
+#include "util/dso.h"
 #include "util/evlist.h"
 #include "util/evsel.h"
 #include "util/config.h"
index 69d16ac852c3e62741942f02145c7325518b14e9..474c4799d29de6d3e216c49a93608608a5e96297 100644 (file)
@@ -2,6 +2,7 @@
 #include "builtin.h"
 #include "perf.h"
 
+#include "util/build-id.h"
 #include "util/evsel.h"
 #include "util/evlist.h"
 #include "util/term.h"
index 9e60eda9297dd2560a29812c5979364f6f633370..c5f3b9e9509dc85833fa7a733ed0ebddae45d442 100644 (file)
@@ -13,6 +13,7 @@
 #include "util/data.h"
 #include "util/mem-events.h"
 #include "util/debug.h"
+#include "util/dso.h"
 #include "util/map.h"
 #include "util/symbol.h"
 
index 94e7e354cb1660466c3ec47b1318fc2d6aa2e7f6..ba419ee40283b2147b6e4663ae3d09234ccb0a79 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "util/annotate.h"
 #include "util/color.h"
+#include "util/dso.h"
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include <linux/err.h>
index f3b31c6ed15f58dc191eaf6d949eb41a74a09fb5..1ff04b00a561ebd8627558a328fd0e30f0bd4957 100644 (file)
@@ -4,6 +4,7 @@
 #include "util/cache.h"
 #include "util/counts.h"
 #include "util/debug.h"
+#include "util/dso.h"
 #include <subcmd/exec-cmd.h>
 #include "util/header.h"
 #include <subcmd/parse-options.h>
index 5538b5886e35c86cbcb5e76e96d9b13724632e49..0b7b12cfdd63dca7b885442f8599c641f55e1fe3 100644 (file)
@@ -24,6 +24,7 @@
 #include "util/bpf-event.h"
 #include "util/config.h"
 #include "util/color.h"
+#include "util/dso.h"
 #include "util/evlist.h"
 #include "util/evsel.h"
 #include "util/event.h"
index b1ec8ff52740421483ee7341d65e2895f32165c7..0f633f0d6be8dd0f25e3c0297647cded23745483 100644 (file)
@@ -25,6 +25,7 @@
 #include "util/color.h"
 #include "util/config.h"
 #include "util/debug.h"
+#include "util/dso.h"
 #include "util/env.h"
 #include "util/event.h"
 #include "util/evlist.h"
@@ -42,6 +43,7 @@
 #include "util/intlist.h"
 #include "util/thread_map.h"
 #include "util/stat.h"
+#include "util/tool.h"
 #include "util/util.h"
 #include "trace/beauty/beauty.h"
 #include "trace-event.h"
index c4b73bb4b11386e16363be70f164da3a443bbeae..7b2b89f4b716abbf69e78f243bd79b23ec219897 100644 (file)
@@ -12,6 +12,7 @@
 #include <perf/evlist.h>
 
 #include "debug.h"
+#include "dso.h"
 #include "parse-events.h"
 #include "evlist.h"
 #include "evsel.h"
index 946ab4b63acd3d840d3baf51ce704fb4d57d2cf3..a4874d4ce7ef6e9eead94f9fbf7d6d71aac1d6fa 100644 (file)
@@ -9,6 +9,7 @@
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <api/fs/fs.h>
+#include "dso.h"
 #include "util.h"
 #include "machine.h"
 #include "symbol.h"
index f33709a79335afe61650644fbdf082beca1a7490..4125255ff637a362cb4f67564e4b0203ebb4b959 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/types.h>
 #include <linux/zalloc.h>
 #include <inttypes.h>
+#include <limits.h>
 #include <unistd.h>
 #include "tests.h"
 #include "debug.h"
index 1411155597b84376db8ace7b6a652985afd670df..4b68ec3a13fccbe566d26875c024afc6ace9954a 100644 (file)
@@ -4,6 +4,7 @@
 #include "evlist.h"
 #include "evsel.h"
 #include "machine.h"
+#include "tool.h"
 #include "tests.h"
 #include "debug.h"
 
index 96ad95d3f33869961a21bc6921eda16e1002917f..cdde41c03056be273e4f437f130e3fa67236fc24 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <inttypes.h>
 #include "util/debug.h"
+#include "util/dso.h"
 #include "util/map.h"
 #include "util/symbol.h"
 #include "util/sort.h"
index 93af420ad2e4ee2b2f1a658b45e78b97ce671cbf..fa55b7bad3af28433d7ce475d73910170cb65728 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include "util/debug.h"
+#include "util/dso.h"
 #include "util/event.h"
 #include "util/map.h"
 #include "util/symbol.h"
index 07f4ca0704fbc749990a092457167686b5298486..3f6dfa21226062498e494f76fd39487db022bf3b 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include "util/debug.h"
+#include "util/dso.h"
 #include "util/event.h"
 #include "util/map.h"
 #include "util/symbol.h"
index 5e8834fc7dec5ca684ffc73791937643b80710b0..01f434c067c6d0a0b2d2b879fac89b96c9a4af67 100644 (file)
@@ -4,6 +4,7 @@
 #include <inttypes.h>
 #include <string.h>
 #include <stdlib.h>
+#include "dso.h"
 #include "map.h"
 #include "symbol.h"
 #include "util.h"
index 715601f5fce3099570c87bbd3fc1989b4538fcc4..ac74ed2c23a0c13a3893fbee4418c9d81862dcf4 100644 (file)
@@ -5,6 +5,7 @@
 #include "../util.h"
 #include "../../util/annotate.h"
 #include "../../util/debug.h"
+#include "../../util/dso.h"
 #include "../../util/hist.h"
 #include "../../util/sort.h"
 #include "../../util/map.h"
index a14dda74f43adb9ba1385895b3d17ded7123107a..cf8857456056e9911b5455d9bfff8feec0e20aff 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/zalloc.h>
 
 #include "../../util/debug.h"
+#include "../../util/dso.h"
 #include "../../util/callchain.h"
 #include "../../util/evsel.h"
 #include "../../util/evlist.h"
index 2e3856471e61cb2beddff6a8566cc60c05df83fa..0b4d8e0d474c57d03b6bc26bcf184fe5071cdbbd 100644 (file)
@@ -36,6 +36,7 @@ perf-y += strfilter.o
 perf-y += top.o
 perf-y += usage.o
 perf-y += dso.o
+perf-y += dsos.o
 perf-y += symbol.o
 perf-y += symbol_fprintf.o
 perf-y += color.o
index 2d6d500c9af72bf8ca73db7ea4eb75a679156584..7a3d4b12532369fc537bbd7c02e1fb15a3d12511 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/err.h>
 #include "bpf-event.h"
 #include "debug.h"
+#include "dso.h"
 #include "symbol.h"
 #include "machine.h"
 #include "env.h"
index 76bf05b26d3bd58afbafc3ed3ced9e716c623143..c14646c1f2eba471ba2f63abfab717538c150e6c 100644 (file)
@@ -22,6 +22,7 @@
 #include "asm/bug.h"
 
 #include "debug.h"
+#include "dso.h"
 #include "hist.h"
 #include "sort.h"
 #include "machine.h"
index d6de3834865e7e45b5c08d1743b7cace38f0e512..3ed1d3bb70892b0c482a493d7d1de29151602890 100644 (file)
 #include "cs-etm.h"
 #include "cs-etm-decoder/cs-etm-decoder.h"
 #include "debug.h"
+#include "dso.h"
 #include "evlist.h"
 #include "intlist.h"
 #include "machine.h"
 #include "map.h"
 #include "perf.h"
 #include "symbol.h"
+#include "tool.h"
 #include "thread.h"
 #include "thread_map.h"
 #include "thread-stack.h"
index 701e9f81431323544a5d2dcdde4161ed42582524..752227b265e781152567fcbf7615c92dbeb88f72 100644 (file)
@@ -7,6 +7,7 @@
 #include <errno.h>
 #include <stdlib.h>
 
+#include "dso.h"
 #include "evsel.h"
 #include "machine.h"
 #include "thread.h"
index ebc9d46c15a7ecee48db2ebc2762c77ea650e453..ece97209792d3f43de34d2db9662db216559d3b3 100644 (file)
@@ -10,7 +10,6 @@
 #include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <libgen.h>
 #include <bpf/libbpf.h>
 #include "bpf-event.h"
 #include "compress.h"
@@ -20,6 +19,7 @@
 #include "symbol.h"
 #include "srcline.h"
 #include "dso.h"
+#include "dsos.h"
 #include "machine.h"
 #include "auxtrace.h"
 #include "util.h" /* O_CLOEXEC for older systems */
@@ -1094,66 +1094,6 @@ struct dso *machine__findnew_kernel(struct machine *machine, const char *name,
        return dso;
 }
 
-/*
- * Find a matching entry and/or link current entry to RB tree.
- * Either one of the dso or name parameter must be non-NULL or the
- * function will not work.
- */
-static struct dso *__dso__findlink_by_longname(struct rb_root *root,
-                                              struct dso *dso, const char *name)
-{
-       struct rb_node **p = &root->rb_node;
-       struct rb_node  *parent = NULL;
-
-       if (!name)
-               name = dso->long_name;
-       /*
-        * Find node with the matching name
-        */
-       while (*p) {
-               struct dso *this = rb_entry(*p, struct dso, rb_node);
-               int rc = strcmp(name, this->long_name);
-
-               parent = *p;
-               if (rc == 0) {
-                       /*
-                        * In case the new DSO is a duplicate of an existing
-                        * one, print a one-time warning & put the new entry
-                        * at the end of the list of duplicates.
-                        */
-                       if (!dso || (dso == this))
-                               return this;    /* Find matching dso */
-                       /*
-                        * The core kernel DSOs may have duplicated long name.
-                        * In this case, the short name should be different.
-                        * Comparing the short names to differentiate the DSOs.
-                        */
-                       rc = strcmp(dso->short_name, this->short_name);
-                       if (rc == 0) {
-                               pr_err("Duplicated dso name: %s\n", name);
-                               return NULL;
-                       }
-               }
-               if (rc < 0)
-                       p = &parent->rb_left;
-               else
-                       p = &parent->rb_right;
-       }
-       if (dso) {
-               /* Add new node and rebalance tree */
-               rb_link_node(&dso->rb_node, parent, p);
-               rb_insert_color(&dso->rb_node, root);
-               dso->root = root;
-       }
-       return NULL;
-}
-
-static inline struct dso *__dso__find_by_longname(struct rb_root *root,
-                                                 const char *name)
-{
-       return __dso__findlink_by_longname(root, NULL, name);
-}
-
 void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
 {
        struct rb_root *root = dso->root;
@@ -1167,7 +1107,7 @@ void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
        if (root) {
                rb_erase(&dso->rb_node, root);
                /*
-                * __dso__findlink_by_longname() isn't guaranteed to add it
+                * __dsos__findnew_link_by_longname() isn't guaranteed to add it
                 * back, so a clean removal is required here.
                 */
                RB_CLEAR_NODE(&dso->rb_node);
@@ -1179,7 +1119,7 @@ void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
        dso->long_name_allocated = name_allocated;
 
        if (root)
-               __dso__findlink_by_longname(root, dso, NULL);
+               __dsos__findnew_link_by_longname(root, dso, NULL);
 }
 
 void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)
@@ -1195,38 +1135,6 @@ void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)
        dso->short_name_allocated = name_allocated;
 }
 
-static void dso__set_basename(struct dso *dso)
-{
-       char *base, *lname;
-       int tid;
-
-       if (sscanf(dso->long_name, "/tmp/perf-%d.map", &tid) == 1) {
-               if (asprintf(&base, "[JIT] tid %d", tid) < 0)
-                       return;
-       } else {
-             /*
-              * basename() may modify path buffer, so we must pass
-               * a copy.
-               */
-               lname = strdup(dso->long_name);
-               if (!lname)
-                       return;
-
-               /*
-                * basename() may return a pointer to internal
-                * storage which is reused in subsequent calls
-                * so copy the result.
-                */
-               base = strdup(basename(lname));
-
-               free(lname);
-
-               if (!base)
-                       return;
-       }
-       dso__set_short_name(dso, base, true);
-}
-
 int dso__name_len(const struct dso *dso)
 {
        if (!dso)
@@ -1377,143 +1285,6 @@ int dso__kernel_module_get_build_id(struct dso *dso,
        return 0;
 }
 
-bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
-{
-       bool have_build_id = false;
-       struct dso *pos;
-       struct nscookie nsc;
-
-       list_for_each_entry(pos, head, node) {
-               if (with_hits && !pos->hit && !dso__is_vdso(pos))
-                       continue;
-               if (pos->has_build_id) {
-                       have_build_id = true;
-                       continue;
-               }
-               nsinfo__mountns_enter(pos->nsinfo, &nsc);
-               if (filename__read_build_id(pos->long_name, pos->build_id,
-                                           sizeof(pos->build_id)) > 0) {
-                       have_build_id     = true;
-                       pos->has_build_id = true;
-               }
-               nsinfo__mountns_exit(&nsc);
-       }
-
-       return have_build_id;
-}
-
-void __dsos__add(struct dsos *dsos, struct dso *dso)
-{
-       list_add_tail(&dso->node, &dsos->head);
-       __dso__findlink_by_longname(&dsos->root, dso, NULL);
-       /*
-        * It is now in the linked list, grab a reference, then garbage collect
-        * this when needing memory, by looking at LRU dso instances in the
-        * list with atomic_read(&dso->refcnt) == 1, i.e. no references
-        * anywhere besides the one for the list, do, under a lock for the
-        * list: remove it from the list, then a dso__put(), that probably will
-        * be the last and will then call dso__delete(), end of life.
-        *
-        * That, or at the end of the 'struct machine' lifetime, when all
-        * 'struct dso' instances will be removed from the list, in
-        * dsos__exit(), if they have no other reference from some other data
-        * structure.
-        *
-        * E.g.: after processing a 'perf.data' file and storing references
-        * to objects instantiated while processing events, we will have
-        * references to the 'thread', 'map', 'dso' structs all from 'struct
-        * hist_entry' instances, but we may not need anything not referenced,
-        * so we might as well call machines__exit()/machines__delete() and
-        * garbage collect it.
-        */
-       dso__get(dso);
-}
-
-void dsos__add(struct dsos *dsos, struct dso *dso)
-{
-       down_write(&dsos->lock);
-       __dsos__add(dsos, dso);
-       up_write(&dsos->lock);
-}
-
-struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
-{
-       struct dso *pos;
-
-       if (cmp_short) {
-               list_for_each_entry(pos, &dsos->head, node)
-                       if (strcmp(pos->short_name, name) == 0)
-                               return pos;
-               return NULL;
-       }
-       return __dso__find_by_longname(&dsos->root, name);
-}
-
-struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
-{
-       struct dso *dso;
-       down_read(&dsos->lock);
-       dso = __dsos__find(dsos, name, cmp_short);
-       up_read(&dsos->lock);
-       return dso;
-}
-
-struct dso *__dsos__addnew(struct dsos *dsos, const char *name)
-{
-       struct dso *dso = dso__new(name);
-
-       if (dso != NULL) {
-               __dsos__add(dsos, dso);
-               dso__set_basename(dso);
-               /* Put dso here because __dsos_add already got it */
-               dso__put(dso);
-       }
-       return dso;
-}
-
-struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
-{
-       struct dso *dso = __dsos__find(dsos, name, false);
-
-       return dso ? dso : __dsos__addnew(dsos, name);
-}
-
-struct dso *dsos__findnew(struct dsos *dsos, const char *name)
-{
-       struct dso *dso;
-       down_write(&dsos->lock);
-       dso = dso__get(__dsos__findnew(dsos, name));
-       up_write(&dsos->lock);
-       return dso;
-}
-
-size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
-                              bool (skip)(struct dso *dso, int parm), int parm)
-{
-       struct dso *pos;
-       size_t ret = 0;
-
-       list_for_each_entry(pos, head, node) {
-               if (skip && skip(pos, parm))
-                       continue;
-               ret += dso__fprintf_buildid(pos, fp);
-               ret += fprintf(fp, " %s\n", pos->long_name);
-       }
-       return ret;
-}
-
-size_t __dsos__fprintf(struct list_head *head, FILE *fp)
-{
-       struct dso *pos;
-       size_t ret = 0;
-
-       list_for_each_entry(pos, head, node) {
-               ret += dso__fprintf(pos, fp);
-       }
-
-       return ret;
-}
-
 size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
 {
        char sbuild_id[SBUILD_ID_SIZE];
index ff0b818546282b82de987d91ad754d213506024a..e4dddb76770d4e4e1d609c1604a7bab89ad30890 100644 (file)
@@ -2,13 +2,13 @@
 #ifndef __PERF_DSO
 #define __PERF_DSO
 
+#include <pthread.h>
 #include <linux/refcount.h>
 #include <linux/types.h>
 #include <linux/rbtree.h>
 #include <sys/types.h>
 #include <stdbool.h>
 #include <stdio.h>
-#include "rwsem.h"
 #include <linux/bitops.h>
 #include "build-id.h"
 
@@ -129,16 +129,6 @@ struct dso_cache {
        char data[0];
 };
 
-/*
- * DSOs are put into both a list for fast iteration and rbtree for fast
- * long name lookup.
- */
-struct dsos {
-       struct list_head head;
-       struct rb_root   root;  /* rbtree root sorted by long name */
-       struct rw_semaphore lock;
-};
-
 struct auxtrace_cache;
 
 struct dso {
@@ -347,21 +337,8 @@ struct map *dso__new_map(const char *name);
 struct dso *machine__findnew_kernel(struct machine *machine, const char *name,
                                    const char *short_name, int dso_type);
 
-void __dsos__add(struct dsos *dsos, struct dso *dso);
-void dsos__add(struct dsos *dsos, struct dso *dso);
-struct dso *__dsos__addnew(struct dsos *dsos, const char *name);
-struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
-struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
-struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
-struct dso *dsos__findnew(struct dsos *dsos, const char *name);
-bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
-
 void dso__reset_find_symbol_cache(struct dso *dso);
 
-size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
-                              bool (skip)(struct dso *dso, int parm), int parm);
-size_t __dsos__fprintf(struct list_head *head, FILE *fp);
-
 size_t dso__fprintf_buildid(struct dso *dso, FILE *fp);
 size_t dso__fprintf_symbols_by_name(struct dso *dso, FILE *fp);
 size_t dso__fprintf(struct dso *dso, FILE *fp);
diff --git a/tools/perf/util/dsos.c b/tools/perf/util/dsos.c
new file mode 100644 (file)
index 0000000..3ea80d2
--- /dev/null
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "debug.h"
+#include "dsos.h"
+#include "dso.h"
+#include "vdso.h"
+#include "namespaces.h"
+#include <libgen.h>
+#include <stdlib.h>
+#include <string.h>
+#include <symbol.h> // filename__read_build_id
+
+bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
+{
+       bool have_build_id = false;
+       struct dso *pos;
+       struct nscookie nsc;
+
+       list_for_each_entry(pos, head, node) {
+               if (with_hits && !pos->hit && !dso__is_vdso(pos))
+                       continue;
+               if (pos->has_build_id) {
+                       have_build_id = true;
+                       continue;
+               }
+               nsinfo__mountns_enter(pos->nsinfo, &nsc);
+               if (filename__read_build_id(pos->long_name, pos->build_id,
+                                           sizeof(pos->build_id)) > 0) {
+                       have_build_id     = true;
+                       pos->has_build_id = true;
+               }
+               nsinfo__mountns_exit(&nsc);
+       }
+
+       return have_build_id;
+}
+
+/*
+ * Find a matching entry and/or link current entry to RB tree.
+ * Either one of the dso or name parameter must be non-NULL or the
+ * function will not work.
+ */
+struct dso *__dsos__findnew_link_by_longname(struct rb_root *root, struct dso *dso, const char *name)
+{
+       struct rb_node **p = &root->rb_node;
+       struct rb_node  *parent = NULL;
+
+       if (!name)
+               name = dso->long_name;
+       /*
+        * Find node with the matching name
+        */
+       while (*p) {
+               struct dso *this = rb_entry(*p, struct dso, rb_node);
+               int rc = strcmp(name, this->long_name);
+
+               parent = *p;
+               if (rc == 0) {
+                       /*
+                        * In case the new DSO is a duplicate of an existing
+                        * one, print a one-time warning & put the new entry
+                        * at the end of the list of duplicates.
+                        */
+                       if (!dso || (dso == this))
+                               return this;    /* Find matching dso */
+                       /*
+                        * The core kernel DSOs may have duplicated long name.
+                        * In this case, the short name should be different.
+                        * Comparing the short names to differentiate the DSOs.
+                        */
+                       rc = strcmp(dso->short_name, this->short_name);
+                       if (rc == 0) {
+                               pr_err("Duplicated dso name: %s\n", name);
+                               return NULL;
+                       }
+               }
+               if (rc < 0)
+                       p = &parent->rb_left;
+               else
+                       p = &parent->rb_right;
+       }
+       if (dso) {
+               /* Add new node and rebalance tree */
+               rb_link_node(&dso->rb_node, parent, p);
+               rb_insert_color(&dso->rb_node, root);
+               dso->root = root;
+       }
+       return NULL;
+}
+
+void __dsos__add(struct dsos *dsos, struct dso *dso)
+{
+       list_add_tail(&dso->node, &dsos->head);
+       __dsos__findnew_link_by_longname(&dsos->root, dso, NULL);
+       /*
+        * It is now in the linked list, grab a reference, then garbage collect
+        * this when needing memory, by looking at LRU dso instances in the
+        * list with atomic_read(&dso->refcnt) == 1, i.e. no references
+        * anywhere besides the one for the list, do, under a lock for the
+        * list: remove it from the list, then a dso__put(), that probably will
+        * be the last and will then call dso__delete(), end of life.
+        *
+        * That, or at the end of the 'struct machine' lifetime, when all
+        * 'struct dso' instances will be removed from the list, in
+        * dsos__exit(), if they have no other reference from some other data
+        * structure.
+        *
+        * E.g.: after processing a 'perf.data' file and storing references
+        * to objects instantiated while processing events, we will have
+        * references to the 'thread', 'map', 'dso' structs all from 'struct
+        * hist_entry' instances, but we may not need anything not referenced,
+        * so we might as well call machines__exit()/machines__delete() and
+        * garbage collect it.
+        */
+       dso__get(dso);
+}
+
+void dsos__add(struct dsos *dsos, struct dso *dso)
+{
+       down_write(&dsos->lock);
+       __dsos__add(dsos, dso);
+       up_write(&dsos->lock);
+}
+
+struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
+{
+       struct dso *pos;
+
+       if (cmp_short) {
+               list_for_each_entry(pos, &dsos->head, node)
+                       if (strcmp(pos->short_name, name) == 0)
+                               return pos;
+               return NULL;
+       }
+       return __dsos__findnew_by_longname(&dsos->root, name);
+}
+
+struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
+{
+       struct dso *dso;
+       down_read(&dsos->lock);
+       dso = __dsos__find(dsos, name, cmp_short);
+       up_read(&dsos->lock);
+       return dso;
+}
+
+static void dso__set_basename(struct dso *dso)
+{
+       char *base, *lname;
+       int tid;
+
+       if (sscanf(dso->long_name, "/tmp/perf-%d.map", &tid) == 1) {
+               if (asprintf(&base, "[JIT] tid %d", tid) < 0)
+                       return;
+       } else {
+             /*
+              * basename() may modify path buffer, so we must pass
+               * a copy.
+               */
+               lname = strdup(dso->long_name);
+               if (!lname)
+                       return;
+
+               /*
+                * basename() may return a pointer to internal
+                * storage which is reused in subsequent calls
+                * so copy the result.
+                */
+               base = strdup(basename(lname));
+
+               free(lname);
+
+               if (!base)
+                       return;
+       }
+       dso__set_short_name(dso, base, true);
+}
+
+struct dso *__dsos__addnew(struct dsos *dsos, const char *name)
+{
+       struct dso *dso = dso__new(name);
+
+       if (dso != NULL) {
+               __dsos__add(dsos, dso);
+               dso__set_basename(dso);
+               /* Put dso here because __dsos_add already got it */
+               dso__put(dso);
+       }
+       return dso;
+}
+
+struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
+{
+       struct dso *dso = __dsos__find(dsos, name, false);
+
+       return dso ? dso : __dsos__addnew(dsos, name);
+}
+
+struct dso *dsos__findnew(struct dsos *dsos, const char *name)
+{
+       struct dso *dso;
+       down_write(&dsos->lock);
+       dso = dso__get(__dsos__findnew(dsos, name));
+       up_write(&dsos->lock);
+       return dso;
+}
+
+size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
+                              bool (skip)(struct dso *dso, int parm), int parm)
+{
+       struct dso *pos;
+       size_t ret = 0;
+
+       list_for_each_entry(pos, head, node) {
+               if (skip && skip(pos, parm))
+                       continue;
+               ret += dso__fprintf_buildid(pos, fp);
+               ret += fprintf(fp, " %s\n", pos->long_name);
+       }
+       return ret;
+}
+
+size_t __dsos__fprintf(struct list_head *head, FILE *fp)
+{
+       struct dso *pos;
+       size_t ret = 0;
+
+       list_for_each_entry(pos, head, node) {
+               ret += dso__fprintf(pos, fp);
+       }
+
+       return ret;
+}
diff --git a/tools/perf/util/dsos.h b/tools/perf/util/dsos.h
new file mode 100644 (file)
index 0000000..32f1fbe
--- /dev/null
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PERF_DSOS
+#define __PERF_DSOS
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include "rwsem.h"
+
+struct dso;
+
+/*
+ * DSOs are put into both a list for fast iteration and rbtree for fast
+ * long name lookup.
+ */
+struct dsos {
+       struct list_head    head;
+       struct rb_root      root;       /* rbtree root sorted by long name */
+       struct rw_semaphore lock;
+};
+
+void __dsos__add(struct dsos *dsos, struct dso *dso);
+void dsos__add(struct dsos *dsos, struct dso *dso);
+struct dso *__dsos__addnew(struct dsos *dsos, const char *name);
+struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
+struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
+struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
+struct dso *dsos__findnew(struct dsos *dsos, const char *name);
+
+struct dso *__dsos__findnew_link_by_longname(struct rb_root *root, struct dso *dso, const char *name);
+
+static inline struct dso *__dsos__findnew_by_longname(struct rb_root *root, const char *name)
+{
+       return __dsos__findnew_link_by_longname(root, NULL, name);
+}
+
+bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
+
+size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
+                              bool (skip)(struct dso *dso, int parm), int parm);
+size_t __dsos__fprintf(struct list_head *head, FILE *fp);
+
+#endif /* __PERF_DSOS */
index 54169ad335c75547045ab26fdc0305e5b98de2e7..f4afbb858ebbe18f2383d5fb85df48907e76bf2c 100644 (file)
@@ -11,6 +11,7 @@
 #include <api/fs/fs.h>
 #include <linux/perf_event.h>
 #include <linux/zalloc.h>
+#include "dso.h"
 #include "event.h"
 #include "debug.h"
 #include "hist.h"
@@ -29,6 +30,7 @@
 #include "stat.h"
 #include "session.h"
 #include "bpf-event.h"
+#include "tool.h"
 #include "../perf.h"
 
 #define DEFAULT_PROC_MAP_PARSE_TIMEOUT 500
index 20fb06162fd436a64fca7bf906a2aa686065656f..b0c34dda30a0625c7f767103dd2a45f6762b9d29 100644 (file)
@@ -22,6 +22,7 @@
 #include <bpf/libbpf.h>
 #include <perf/cpumap.h>
 
+#include "dso.h"
 #include "evlist.h"
 #include "evsel.h"
 #include "header.h"
index 02ea2ee628148e0df67224d23dbf97df1fd0ca4c..b526ef3ede98cc822fef507f18f6d48488cf0be2 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include "callchain.h"
 #include "debug.h"
+#include "dso.h"
 #include "build-id.h"
 #include "hist.h"
 #include "map.h"
index 99dddb63dac1cc5ab8b39042dff221f5e2205c5b..a30427aa1de077ff707561c0b3fcd9862f5d3c1b 100644 (file)
@@ -22,6 +22,7 @@
 #include "map.h"
 #include "symbol.h"
 #include "session.h"
+#include "tool.h"
 #include "thread.h"
 #include "thread-stack.h"
 #include "debug.h"
index bbeac4f66402444f3ab12562824d1c5412592cab..b80f29bfc7bb2b1070e85dc01ad0c7b4d386e79a 100644 (file)
@@ -14,6 +14,7 @@
 #include <sys/mman.h>
 #include <linux/stringify.h>
 
+#include "build-id.h"
 #include "util.h"
 #include "event.h"
 #include "debug.h"
index 6e9afe4e55dd3701e787309c95a41378c05f4cb9..003025465198d90fe12baf9da12cf9a653a5e432 100644 (file)
@@ -5,6 +5,7 @@
 #include <regex.h>
 #include "callchain.h"
 #include "debug.h"
+#include "dso.h"
 #include "event.h"
 #include "evsel.h"
 #include "hist.h"
index 7d69119d0b5d157fcb482fb6f9c65da90b6fcdeb..ffd391a925a6e04f894d6aa084869b6b6711f418 100644 (file)
@@ -5,12 +5,13 @@
 #include <sys/types.h>
 #include <linux/rbtree.h>
 #include "map_groups.h"
-#include "dso.h"
+#include "dsos.h"
 #include "event.h"
 #include "rwsem.h"
 
 struct addr_location;
 struct branch_stack;
+struct dso;
 struct evsel;
 struct perf_sample;
 struct symbol;
index c75b20b9382072af1a19dd40fea9c1cb7dbc999f..623a63cd1eec83b6354640a2cabad53cd7d4ad56 100644 (file)
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
+#include "dso.h"
 #include "map.h"
 #include "thread.h"
 #include "vdso.h"
index 5f1ba6820cdddd591b8ceb2a55100666c603fb37..523af1bd82e6204c66945ba4810f6fcbaec20126 100644 (file)
@@ -10,6 +10,7 @@
 #include <fcntl.h>
 #include <sys/param.h>
 #include "term.h"
+#include "build-id.h"
 #include "evlist.h"
 #include "evsel.h"
 #include <subcmd/parse-options.h>
index 8394d48f8b32e4e82c8c3f4f2ffb8aa9039cfeef..5d12a78c8ac81e48cc40ef774166de6851e0febf 100644 (file)
 #include <limits.h>
 #include <elf.h>
 
+#include "build-id.h"
 #include "event.h"
 #include "namespaces.h"
 #include "strlist.h"
 #include "strfilter.h"
 #include "debug.h"
+#include "dso.h"
 #include "cache.h"
 #include "color.h"
 #include "map.h"
index 4f6c1465998f569dec4e4d6bdaf77b5fbbfea948..2ba4baa2c52f8405865ee5302be71bde120004ec 100644 (file)
 #include "evlist.h"
 #include "machine.h"
 #include "session.h"
+#include "tool.h"
 #include "thread.h"
 #include "debug.h"
 #include "auxtrace.h"
index 800e82d3523030ac44e2dd4510c0458990e23c09..15961854ba67d0d09fec7fd96f87035cb1ea53bf 100644 (file)
@@ -35,6 +35,7 @@
 #include <perl.h>
 
 #include "../callchain.h"
+#include "../dso.h"
 #include "../machine.h"
 #include "../map.h"
 #include "../symbol.h"
index abfde356be18369172ef21a8592dec6be7e26692..666a56e88d8e7fa054eb7b93d4ee41ceade6d6c0 100644 (file)
 #include <linux/compiler.h>
 #include <linux/time64.h>
 
+#include "../build-id.h"
 #include "../counts.h"
 #include "../debug.h"
+#include "../dso.h"
 #include "../callchain.h"
 #include "../evsel.h"
 #include "../util.h"
index 4650704540c9e4c9e78550ca3665e32482e29b01..32ade5a1b5531033c24914f9647937a868c2288c 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/mman.h>
 #include <linux/time64.h>
 #include "debug.h"
+#include "dso.h"
 #include "sort.h"
 #include "hist.h"
 #include "cacheline.h"
index 5ba1601e88609473ece0d6cd3d1a128636dba842..b64e9e04963677e26f833d937549b0734a997298 100644 (file)
@@ -5,6 +5,7 @@
 #include <string.h>
 #include <linux/kernel.h>
 #include <linux/zalloc.h>
+#include "dso.h"
 #include "session.h"
 #include "thread.h"
 #include "thread-stack.h"
index 28f71ca6ce1cd9ee61065d2be3628bfbd48dce6a..9ece188ae48ae75a9f6f53fab7744e166a7748ab 100644 (file)
@@ -5,6 +5,7 @@
 #include <inttypes.h>
 #include <errno.h>
 #include "debug.h"
+#include "dso.h"
 #include "unwind.h"
 #include "unwind-libdw.h"
 #include "machine.h"
index 6499b22b158bd2769b7ef1f2b7b977e4385eac03..a24fb57c9b2c85fe85eb24200e9d1dfe5aed5949 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include "unwind.h"
+#include "dso.h"
 #include "map.h"
 #include "thread.h"
 #include "session.h"
index 7f427bab6c1296812fe4c84ccd8365789485f7f1..e5e6599603f416606ce8872ce3efb1e32c16d1ca 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 
 #include "vdso.h"
+#include "dso.h"
 #include "util.h"
 #include "map.h"
 #include "symbol.h"