14a3cec84SArnaldo Carvalho de Melo // SPDX-License-Identifier: GPL-2.0 24a3cec84SArnaldo Carvalho de Melo #include "debug.h" 34a3cec84SArnaldo Carvalho de Melo #include "dsos.h" 44a3cec84SArnaldo Carvalho de Melo #include "dso.h" 567fd1892SNamhyung Kim #include "util.h" 64a3cec84SArnaldo Carvalho de Melo #include "vdso.h" 74a3cec84SArnaldo Carvalho de Melo #include "namespaces.h" 867fd1892SNamhyung Kim #include <errno.h> 94a3cec84SArnaldo Carvalho de Melo #include <libgen.h> 104a3cec84SArnaldo Carvalho de Melo #include <stdlib.h> 114a3cec84SArnaldo Carvalho de Melo #include <string.h> 124a3cec84SArnaldo Carvalho de Melo #include <symbol.h> // filename__read_build_id 1367fd1892SNamhyung Kim #include <unistd.h> 144a3cec84SArnaldo Carvalho de Melo 1583acca9fSIan Rogers void dsos__init(struct dsos *dsos) 1683acca9fSIan Rogers { 1783acca9fSIan Rogers INIT_LIST_HEAD(&dsos->head); 1883acca9fSIan Rogers dsos->root = RB_ROOT; 1983acca9fSIan Rogers init_rwsem(&dsos->lock); 2083acca9fSIan Rogers } 2183acca9fSIan Rogers 2283acca9fSIan Rogers static void dsos__purge(struct dsos *dsos) 2383acca9fSIan Rogers { 2483acca9fSIan Rogers struct dso *pos, *n; 2583acca9fSIan Rogers 2683acca9fSIan Rogers down_write(&dsos->lock); 2783acca9fSIan Rogers 2883acca9fSIan Rogers list_for_each_entry_safe(pos, n, &dsos->head, node) { 2983acca9fSIan Rogers RB_CLEAR_NODE(&pos->rb_node); 3083acca9fSIan Rogers pos->root = NULL; 3183acca9fSIan Rogers list_del_init(&pos->node); 3283acca9fSIan Rogers dso__put(pos); 3383acca9fSIan Rogers } 3483acca9fSIan Rogers 3583acca9fSIan Rogers up_write(&dsos->lock); 3683acca9fSIan Rogers } 3783acca9fSIan Rogers 3883acca9fSIan Rogers void dsos__exit(struct dsos *dsos) 3983acca9fSIan Rogers { 4083acca9fSIan Rogers dsos__purge(dsos); 4183acca9fSIan Rogers exit_rwsem(&dsos->lock); 4283acca9fSIan Rogers } 4383acca9fSIan Rogers 440e3149f8SArnaldo Carvalho de Melo static int __dso_id__cmp(struct dso_id *a, struct dso_id *b) 457b59a824SArnaldo Carvalho de Melo { 467b59a824SArnaldo Carvalho de Melo if (a->maj > b->maj) return -1; 477b59a824SArnaldo Carvalho de Melo if (a->maj < b->maj) return 1; 487b59a824SArnaldo Carvalho de Melo 497b59a824SArnaldo Carvalho de Melo if (a->min > b->min) return -1; 507b59a824SArnaldo Carvalho de Melo if (a->min < b->min) return 1; 517b59a824SArnaldo Carvalho de Melo 527b59a824SArnaldo Carvalho de Melo if (a->ino > b->ino) return -1; 537b59a824SArnaldo Carvalho de Melo if (a->ino < b->ino) return 1; 547b59a824SArnaldo Carvalho de Melo 5568566a7cSAdrian Hunter /* 5668566a7cSAdrian Hunter * Synthesized MMAP events have zero ino_generation, avoid comparing 5768566a7cSAdrian Hunter * them with MMAP events with actual ino_generation. 5868566a7cSAdrian Hunter * 5968566a7cSAdrian Hunter * I found it harmful because the mismatch resulted in a new 6068566a7cSAdrian Hunter * dso that did not have a build ID whereas the original dso did have a 6168566a7cSAdrian Hunter * build ID. The build ID was essential because the object was not found 6268566a7cSAdrian Hunter * otherwise. - Adrian 6368566a7cSAdrian Hunter */ 6468566a7cSAdrian Hunter if (a->ino_generation && b->ino_generation) { 657b59a824SArnaldo Carvalho de Melo if (a->ino_generation > b->ino_generation) return -1; 667b59a824SArnaldo Carvalho de Melo if (a->ino_generation < b->ino_generation) return 1; 6768566a7cSAdrian Hunter } 687b59a824SArnaldo Carvalho de Melo 697b59a824SArnaldo Carvalho de Melo return 0; 707b59a824SArnaldo Carvalho de Melo } 717b59a824SArnaldo Carvalho de Melo 720d33b343SRavi Bangoria static bool dso_id__empty(struct dso_id *id) 730d33b343SRavi Bangoria { 740d33b343SRavi Bangoria if (!id) 750d33b343SRavi Bangoria return true; 760d33b343SRavi Bangoria 770d33b343SRavi Bangoria return !id->maj && !id->min && !id->ino && !id->ino_generation; 780d33b343SRavi Bangoria } 790d33b343SRavi Bangoria 800d33b343SRavi Bangoria static void dso__inject_id(struct dso *dso, struct dso_id *id) 810d33b343SRavi Bangoria { 820d33b343SRavi Bangoria dso->id.maj = id->maj; 830d33b343SRavi Bangoria dso->id.min = id->min; 840d33b343SRavi Bangoria dso->id.ino = id->ino; 850d33b343SRavi Bangoria dso->id.ino_generation = id->ino_generation; 860d33b343SRavi Bangoria } 870d33b343SRavi Bangoria 880e3149f8SArnaldo Carvalho de Melo static int dso_id__cmp(struct dso_id *a, struct dso_id *b) 890e3149f8SArnaldo Carvalho de Melo { 900e3149f8SArnaldo Carvalho de Melo /* 910e3149f8SArnaldo Carvalho de Melo * The second is always dso->id, so zeroes if not set, assume passing 920e3149f8SArnaldo Carvalho de Melo * NULL for a means a zeroed id 930e3149f8SArnaldo Carvalho de Melo */ 940d33b343SRavi Bangoria if (dso_id__empty(a) || dso_id__empty(b)) 950e3149f8SArnaldo Carvalho de Melo return 0; 960e3149f8SArnaldo Carvalho de Melo 970e3149f8SArnaldo Carvalho de Melo return __dso_id__cmp(a, b); 980e3149f8SArnaldo Carvalho de Melo } 990e3149f8SArnaldo Carvalho de Melo 1000e3149f8SArnaldo Carvalho de Melo int dso__cmp_id(struct dso *a, struct dso *b) 1010e3149f8SArnaldo Carvalho de Melo { 1020e3149f8SArnaldo Carvalho de Melo return __dso_id__cmp(&a->id, &b->id); 1030e3149f8SArnaldo Carvalho de Melo } 1040e3149f8SArnaldo Carvalho de Melo 10583acca9fSIan Rogers bool __dsos__read_build_ids(struct dsos *dsos, bool with_hits) 1064a3cec84SArnaldo Carvalho de Melo { 10783acca9fSIan Rogers struct list_head *head = &dsos->head; 1084a3cec84SArnaldo Carvalho de Melo bool have_build_id = false; 1094a3cec84SArnaldo Carvalho de Melo struct dso *pos; 1104a3cec84SArnaldo Carvalho de Melo struct nscookie nsc; 1114a3cec84SArnaldo Carvalho de Melo 1124a3cec84SArnaldo Carvalho de Melo list_for_each_entry(pos, head, node) { 1134a3cec84SArnaldo Carvalho de Melo if (with_hits && !pos->hit && !dso__is_vdso(pos)) 1144a3cec84SArnaldo Carvalho de Melo continue; 1154a3cec84SArnaldo Carvalho de Melo if (pos->has_build_id) { 1164a3cec84SArnaldo Carvalho de Melo have_build_id = true; 1174a3cec84SArnaldo Carvalho de Melo continue; 1184a3cec84SArnaldo Carvalho de Melo } 1194a3cec84SArnaldo Carvalho de Melo nsinfo__mountns_enter(pos->nsinfo, &nsc); 120f766819cSJiri Olsa if (filename__read_build_id(pos->long_name, &pos->bid) > 0) { 1214a3cec84SArnaldo Carvalho de Melo have_build_id = true; 1224a3cec84SArnaldo Carvalho de Melo pos->has_build_id = true; 12367fd1892SNamhyung Kim } else if (errno == ENOENT && pos->nsinfo) { 1247031edacSArnaldo Carvalho de Melo char *new_name = dso__filename_with_chroot(pos, pos->long_name); 12567fd1892SNamhyung Kim 12667fd1892SNamhyung Kim if (new_name && filename__read_build_id(new_name, 12767fd1892SNamhyung Kim &pos->bid) > 0) { 12867fd1892SNamhyung Kim have_build_id = true; 12967fd1892SNamhyung Kim pos->has_build_id = true; 13067fd1892SNamhyung Kim } 13167fd1892SNamhyung Kim free(new_name); 1324a3cec84SArnaldo Carvalho de Melo } 1334a3cec84SArnaldo Carvalho de Melo nsinfo__mountns_exit(&nsc); 1344a3cec84SArnaldo Carvalho de Melo } 1354a3cec84SArnaldo Carvalho de Melo 1364a3cec84SArnaldo Carvalho de Melo return have_build_id; 1374a3cec84SArnaldo Carvalho de Melo } 1384a3cec84SArnaldo Carvalho de Melo 1390e3149f8SArnaldo Carvalho de Melo static int __dso__cmp_long_name(const char *long_name, struct dso_id *id, struct dso *b) 1400e3149f8SArnaldo Carvalho de Melo { 1410e3149f8SArnaldo Carvalho de Melo int rc = strcmp(long_name, b->long_name); 1420e3149f8SArnaldo Carvalho de Melo return rc ?: dso_id__cmp(id, &b->id); 1430e3149f8SArnaldo Carvalho de Melo } 1440e3149f8SArnaldo Carvalho de Melo 1450e3149f8SArnaldo Carvalho de Melo static int __dso__cmp_short_name(const char *short_name, struct dso_id *id, struct dso *b) 1460e3149f8SArnaldo Carvalho de Melo { 1470e3149f8SArnaldo Carvalho de Melo int rc = strcmp(short_name, b->short_name); 1480e3149f8SArnaldo Carvalho de Melo return rc ?: dso_id__cmp(id, &b->id); 1490e3149f8SArnaldo Carvalho de Melo } 1500e3149f8SArnaldo Carvalho de Melo 1510e3149f8SArnaldo Carvalho de Melo static int dso__cmp_short_name(struct dso *a, struct dso *b) 1520e3149f8SArnaldo Carvalho de Melo { 1530e3149f8SArnaldo Carvalho de Melo return __dso__cmp_short_name(a->short_name, &a->id, b); 1540e3149f8SArnaldo Carvalho de Melo } 1550e3149f8SArnaldo Carvalho de Melo 1564a3cec84SArnaldo Carvalho de Melo /* 1574a3cec84SArnaldo Carvalho de Melo * Find a matching entry and/or link current entry to RB tree. 1584a3cec84SArnaldo Carvalho de Melo * Either one of the dso or name parameter must be non-NULL or the 1594a3cec84SArnaldo Carvalho de Melo * function will not work. 1604a3cec84SArnaldo Carvalho de Melo */ 1610e3149f8SArnaldo Carvalho de Melo struct dso *__dsos__findnew_link_by_longname_id(struct rb_root *root, struct dso *dso, 1620e3149f8SArnaldo Carvalho de Melo const char *name, struct dso_id *id) 1634a3cec84SArnaldo Carvalho de Melo { 1644a3cec84SArnaldo Carvalho de Melo struct rb_node **p = &root->rb_node; 1654a3cec84SArnaldo Carvalho de Melo struct rb_node *parent = NULL; 1664a3cec84SArnaldo Carvalho de Melo 1674a3cec84SArnaldo Carvalho de Melo if (!name) 1684a3cec84SArnaldo Carvalho de Melo name = dso->long_name; 1694a3cec84SArnaldo Carvalho de Melo /* 1704a3cec84SArnaldo Carvalho de Melo * Find node with the matching name 1714a3cec84SArnaldo Carvalho de Melo */ 1724a3cec84SArnaldo Carvalho de Melo while (*p) { 1734a3cec84SArnaldo Carvalho de Melo struct dso *this = rb_entry(*p, struct dso, rb_node); 1740e3149f8SArnaldo Carvalho de Melo int rc = __dso__cmp_long_name(name, id, this); 1754a3cec84SArnaldo Carvalho de Melo 1764a3cec84SArnaldo Carvalho de Melo parent = *p; 1774a3cec84SArnaldo Carvalho de Melo if (rc == 0) { 1784a3cec84SArnaldo Carvalho de Melo /* 1794a3cec84SArnaldo Carvalho de Melo * In case the new DSO is a duplicate of an existing 1804a3cec84SArnaldo Carvalho de Melo * one, print a one-time warning & put the new entry 1814a3cec84SArnaldo Carvalho de Melo * at the end of the list of duplicates. 1824a3cec84SArnaldo Carvalho de Melo */ 1834a3cec84SArnaldo Carvalho de Melo if (!dso || (dso == this)) 184*f649ed80SIan Rogers return dso__get(this); /* Find matching dso */ 1854a3cec84SArnaldo Carvalho de Melo /* 1864a3cec84SArnaldo Carvalho de Melo * The core kernel DSOs may have duplicated long name. 1874a3cec84SArnaldo Carvalho de Melo * In this case, the short name should be different. 1884a3cec84SArnaldo Carvalho de Melo * Comparing the short names to differentiate the DSOs. 1894a3cec84SArnaldo Carvalho de Melo */ 1900e3149f8SArnaldo Carvalho de Melo rc = dso__cmp_short_name(dso, this); 1914a3cec84SArnaldo Carvalho de Melo if (rc == 0) { 1924a3cec84SArnaldo Carvalho de Melo pr_err("Duplicated dso name: %s\n", name); 1934a3cec84SArnaldo Carvalho de Melo return NULL; 1944a3cec84SArnaldo Carvalho de Melo } 1954a3cec84SArnaldo Carvalho de Melo } 1964a3cec84SArnaldo Carvalho de Melo if (rc < 0) 1974a3cec84SArnaldo Carvalho de Melo p = &parent->rb_left; 1984a3cec84SArnaldo Carvalho de Melo else 1994a3cec84SArnaldo Carvalho de Melo p = &parent->rb_right; 2004a3cec84SArnaldo Carvalho de Melo } 2014a3cec84SArnaldo Carvalho de Melo if (dso) { 2024a3cec84SArnaldo Carvalho de Melo /* Add new node and rebalance tree */ 2034a3cec84SArnaldo Carvalho de Melo rb_link_node(&dso->rb_node, parent, p); 2044a3cec84SArnaldo Carvalho de Melo rb_insert_color(&dso->rb_node, root); 2054a3cec84SArnaldo Carvalho de Melo dso->root = root; 2064a3cec84SArnaldo Carvalho de Melo } 2074a3cec84SArnaldo Carvalho de Melo return NULL; 2084a3cec84SArnaldo Carvalho de Melo } 2094a3cec84SArnaldo Carvalho de Melo 2104a3cec84SArnaldo Carvalho de Melo void __dsos__add(struct dsos *dsos, struct dso *dso) 2114a3cec84SArnaldo Carvalho de Melo { 2124a3cec84SArnaldo Carvalho de Melo list_add_tail(&dso->node, &dsos->head); 2130e3149f8SArnaldo Carvalho de Melo __dsos__findnew_link_by_longname_id(&dsos->root, dso, NULL, &dso->id); 2144a3cec84SArnaldo Carvalho de Melo /* 2154a3cec84SArnaldo Carvalho de Melo * It is now in the linked list, grab a reference, then garbage collect 2164a3cec84SArnaldo Carvalho de Melo * this when needing memory, by looking at LRU dso instances in the 2174a3cec84SArnaldo Carvalho de Melo * list with atomic_read(&dso->refcnt) == 1, i.e. no references 2184a3cec84SArnaldo Carvalho de Melo * anywhere besides the one for the list, do, under a lock for the 2194a3cec84SArnaldo Carvalho de Melo * list: remove it from the list, then a dso__put(), that probably will 2204a3cec84SArnaldo Carvalho de Melo * be the last and will then call dso__delete(), end of life. 2214a3cec84SArnaldo Carvalho de Melo * 2224a3cec84SArnaldo Carvalho de Melo * That, or at the end of the 'struct machine' lifetime, when all 2234a3cec84SArnaldo Carvalho de Melo * 'struct dso' instances will be removed from the list, in 2244a3cec84SArnaldo Carvalho de Melo * dsos__exit(), if they have no other reference from some other data 2254a3cec84SArnaldo Carvalho de Melo * structure. 2264a3cec84SArnaldo Carvalho de Melo * 2274a3cec84SArnaldo Carvalho de Melo * E.g.: after processing a 'perf.data' file and storing references 2284a3cec84SArnaldo Carvalho de Melo * to objects instantiated while processing events, we will have 2294a3cec84SArnaldo Carvalho de Melo * references to the 'thread', 'map', 'dso' structs all from 'struct 2304a3cec84SArnaldo Carvalho de Melo * hist_entry' instances, but we may not need anything not referenced, 2314a3cec84SArnaldo Carvalho de Melo * so we might as well call machines__exit()/machines__delete() and 2324a3cec84SArnaldo Carvalho de Melo * garbage collect it. 2334a3cec84SArnaldo Carvalho de Melo */ 2344a3cec84SArnaldo Carvalho de Melo dso__get(dso); 2354a3cec84SArnaldo Carvalho de Melo } 2364a3cec84SArnaldo Carvalho de Melo 2374a3cec84SArnaldo Carvalho de Melo void dsos__add(struct dsos *dsos, struct dso *dso) 2384a3cec84SArnaldo Carvalho de Melo { 2394a3cec84SArnaldo Carvalho de Melo down_write(&dsos->lock); 2404a3cec84SArnaldo Carvalho de Melo __dsos__add(dsos, dso); 2414a3cec84SArnaldo Carvalho de Melo up_write(&dsos->lock); 2424a3cec84SArnaldo Carvalho de Melo } 2434a3cec84SArnaldo Carvalho de Melo 2440e3149f8SArnaldo Carvalho de Melo static struct dso *__dsos__findnew_by_longname_id(struct rb_root *root, const char *name, struct dso_id *id) 2450e3149f8SArnaldo Carvalho de Melo { 2460e3149f8SArnaldo Carvalho de Melo return __dsos__findnew_link_by_longname_id(root, NULL, name, id); 2470e3149f8SArnaldo Carvalho de Melo } 2480e3149f8SArnaldo Carvalho de Melo 2490e3149f8SArnaldo Carvalho de Melo static struct dso *__dsos__find_id(struct dsos *dsos, const char *name, struct dso_id *id, bool cmp_short) 2504a3cec84SArnaldo Carvalho de Melo { 2514a3cec84SArnaldo Carvalho de Melo struct dso *pos; 2524a3cec84SArnaldo Carvalho de Melo 2534a3cec84SArnaldo Carvalho de Melo if (cmp_short) { 2544a3cec84SArnaldo Carvalho de Melo list_for_each_entry(pos, &dsos->head, node) 2550e3149f8SArnaldo Carvalho de Melo if (__dso__cmp_short_name(name, id, pos) == 0) 256*f649ed80SIan Rogers return dso__get(pos); 2574a3cec84SArnaldo Carvalho de Melo return NULL; 2584a3cec84SArnaldo Carvalho de Melo } 2590e3149f8SArnaldo Carvalho de Melo return __dsos__findnew_by_longname_id(&dsos->root, name, id); 2600e3149f8SArnaldo Carvalho de Melo } 2610e3149f8SArnaldo Carvalho de Melo 262*f649ed80SIan Rogers struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short) 2630e3149f8SArnaldo Carvalho de Melo { 264*f649ed80SIan Rogers struct dso *res; 265*f649ed80SIan Rogers 266*f649ed80SIan Rogers down_read(&dsos->lock); 267*f649ed80SIan Rogers res = __dsos__find_id(dsos, name, NULL, cmp_short); 268*f649ed80SIan Rogers up_read(&dsos->lock); 269*f649ed80SIan Rogers return res; 2704a3cec84SArnaldo Carvalho de Melo } 2714a3cec84SArnaldo Carvalho de Melo 2724a3cec84SArnaldo Carvalho de Melo static void dso__set_basename(struct dso *dso) 2734a3cec84SArnaldo Carvalho de Melo { 2744a3cec84SArnaldo Carvalho de Melo char *base, *lname; 2754a3cec84SArnaldo Carvalho de Melo int tid; 2764a3cec84SArnaldo Carvalho de Melo 2774a3cec84SArnaldo Carvalho de Melo if (sscanf(dso->long_name, "/tmp/perf-%d.map", &tid) == 1) { 2784a3cec84SArnaldo Carvalho de Melo if (asprintf(&base, "[JIT] tid %d", tid) < 0) 2794a3cec84SArnaldo Carvalho de Melo return; 2804a3cec84SArnaldo Carvalho de Melo } else { 2814a3cec84SArnaldo Carvalho de Melo /* 2824a3cec84SArnaldo Carvalho de Melo * basename() may modify path buffer, so we must pass 2834a3cec84SArnaldo Carvalho de Melo * a copy. 2844a3cec84SArnaldo Carvalho de Melo */ 2854a3cec84SArnaldo Carvalho de Melo lname = strdup(dso->long_name); 2864a3cec84SArnaldo Carvalho de Melo if (!lname) 2874a3cec84SArnaldo Carvalho de Melo return; 2884a3cec84SArnaldo Carvalho de Melo 2894a3cec84SArnaldo Carvalho de Melo /* 2904a3cec84SArnaldo Carvalho de Melo * basename() may return a pointer to internal 2914a3cec84SArnaldo Carvalho de Melo * storage which is reused in subsequent calls 2924a3cec84SArnaldo Carvalho de Melo * so copy the result. 2934a3cec84SArnaldo Carvalho de Melo */ 2944a3cec84SArnaldo Carvalho de Melo base = strdup(basename(lname)); 2954a3cec84SArnaldo Carvalho de Melo 2964a3cec84SArnaldo Carvalho de Melo free(lname); 2974a3cec84SArnaldo Carvalho de Melo 2984a3cec84SArnaldo Carvalho de Melo if (!base) 2994a3cec84SArnaldo Carvalho de Melo return; 3004a3cec84SArnaldo Carvalho de Melo } 3014a3cec84SArnaldo Carvalho de Melo dso__set_short_name(dso, base, true); 3024a3cec84SArnaldo Carvalho de Melo } 3034a3cec84SArnaldo Carvalho de Melo 3040e3149f8SArnaldo Carvalho de Melo static struct dso *__dsos__addnew_id(struct dsos *dsos, const char *name, struct dso_id *id) 3054a3cec84SArnaldo Carvalho de Melo { 3060e3149f8SArnaldo Carvalho de Melo struct dso *dso = dso__new_id(name, id); 3074a3cec84SArnaldo Carvalho de Melo 3084a3cec84SArnaldo Carvalho de Melo if (dso != NULL) { 3094a3cec84SArnaldo Carvalho de Melo __dsos__add(dsos, dso); 3104a3cec84SArnaldo Carvalho de Melo dso__set_basename(dso); 3114a3cec84SArnaldo Carvalho de Melo } 3124a3cec84SArnaldo Carvalho de Melo return dso; 3134a3cec84SArnaldo Carvalho de Melo } 3144a3cec84SArnaldo Carvalho de Melo 3150e3149f8SArnaldo Carvalho de Melo struct dso *__dsos__addnew(struct dsos *dsos, const char *name) 3164a3cec84SArnaldo Carvalho de Melo { 3170e3149f8SArnaldo Carvalho de Melo return __dsos__addnew_id(dsos, name, NULL); 3184a3cec84SArnaldo Carvalho de Melo } 3194a3cec84SArnaldo Carvalho de Melo 3200e3149f8SArnaldo Carvalho de Melo static struct dso *__dsos__findnew_id(struct dsos *dsos, const char *name, struct dso_id *id) 3210e3149f8SArnaldo Carvalho de Melo { 3220e3149f8SArnaldo Carvalho de Melo struct dso *dso = __dsos__find_id(dsos, name, id, false); 3230d33b343SRavi Bangoria 3240d33b343SRavi Bangoria if (dso && dso_id__empty(&dso->id) && !dso_id__empty(id)) 3250d33b343SRavi Bangoria dso__inject_id(dso, id); 3260d33b343SRavi Bangoria 3270e3149f8SArnaldo Carvalho de Melo return dso ? dso : __dsos__addnew_id(dsos, name, id); 3280e3149f8SArnaldo Carvalho de Melo } 3290e3149f8SArnaldo Carvalho de Melo 3300e3149f8SArnaldo Carvalho de Melo struct dso *dsos__findnew_id(struct dsos *dsos, const char *name, struct dso_id *id) 3314a3cec84SArnaldo Carvalho de Melo { 3324a3cec84SArnaldo Carvalho de Melo struct dso *dso; 3334a3cec84SArnaldo Carvalho de Melo down_write(&dsos->lock); 334*f649ed80SIan Rogers dso = __dsos__findnew_id(dsos, name, id); 3354a3cec84SArnaldo Carvalho de Melo up_write(&dsos->lock); 3364a3cec84SArnaldo Carvalho de Melo return dso; 3374a3cec84SArnaldo Carvalho de Melo } 3384a3cec84SArnaldo Carvalho de Melo 33983acca9fSIan Rogers size_t __dsos__fprintf_buildid(struct dsos *dsos, FILE *fp, 3404a3cec84SArnaldo Carvalho de Melo bool (skip)(struct dso *dso, int parm), int parm) 3414a3cec84SArnaldo Carvalho de Melo { 34283acca9fSIan Rogers struct list_head *head = &dsos->head; 3434a3cec84SArnaldo Carvalho de Melo struct dso *pos; 3444a3cec84SArnaldo Carvalho de Melo size_t ret = 0; 3454a3cec84SArnaldo Carvalho de Melo 3464a3cec84SArnaldo Carvalho de Melo list_for_each_entry(pos, head, node) { 347e9ad9438SJiri Olsa char sbuild_id[SBUILD_ID_SIZE]; 348e9ad9438SJiri Olsa 3494a3cec84SArnaldo Carvalho de Melo if (skip && skip(pos, parm)) 3504a3cec84SArnaldo Carvalho de Melo continue; 351e9ad9438SJiri Olsa build_id__sprintf(&pos->bid, sbuild_id); 352e9ad9438SJiri Olsa ret += fprintf(fp, "%-40s %s\n", sbuild_id, pos->long_name); 3534a3cec84SArnaldo Carvalho de Melo } 3544a3cec84SArnaldo Carvalho de Melo return ret; 3554a3cec84SArnaldo Carvalho de Melo } 3564a3cec84SArnaldo Carvalho de Melo 35783acca9fSIan Rogers size_t __dsos__fprintf(struct dsos *dsos, FILE *fp) 3584a3cec84SArnaldo Carvalho de Melo { 35983acca9fSIan Rogers struct list_head *head = &dsos->head; 3604a3cec84SArnaldo Carvalho de Melo struct dso *pos; 3614a3cec84SArnaldo Carvalho de Melo size_t ret = 0; 3624a3cec84SArnaldo Carvalho de Melo 3634a3cec84SArnaldo Carvalho de Melo list_for_each_entry(pos, head, node) { 3644a3cec84SArnaldo Carvalho de Melo ret += dso__fprintf(pos, fp); 3654a3cec84SArnaldo Carvalho de Melo } 3664a3cec84SArnaldo Carvalho de Melo 3674a3cec84SArnaldo Carvalho de Melo return ret; 3684a3cec84SArnaldo Carvalho de Melo } 36983acca9fSIan Rogers 37083acca9fSIan Rogers int __dsos__hit_all(struct dsos *dsos) 37183acca9fSIan Rogers { 37283acca9fSIan Rogers struct list_head *head = &dsos->head; 37383acca9fSIan Rogers struct dso *pos; 37483acca9fSIan Rogers 37583acca9fSIan Rogers list_for_each_entry(pos, head, node) 37683acca9fSIan Rogers pos->hit = true; 37783acca9fSIan Rogers 37883acca9fSIan Rogers return 0; 37983acca9fSIan Rogers } 380*f649ed80SIan Rogers 381*f649ed80SIan Rogers struct dso *dsos__findnew_module_dso(struct dsos *dsos, 382*f649ed80SIan Rogers struct machine *machine, 383*f649ed80SIan Rogers struct kmod_path *m, 384*f649ed80SIan Rogers const char *filename) 385*f649ed80SIan Rogers { 386*f649ed80SIan Rogers struct dso *dso; 387*f649ed80SIan Rogers 388*f649ed80SIan Rogers down_write(&dsos->lock); 389*f649ed80SIan Rogers 390*f649ed80SIan Rogers dso = __dsos__find_id(dsos, m->name, NULL, /*cmp_short=*/true); 391*f649ed80SIan Rogers if (!dso) { 392*f649ed80SIan Rogers dso = __dsos__addnew(dsos, m->name); 393*f649ed80SIan Rogers if (dso == NULL) 394*f649ed80SIan Rogers goto out_unlock; 395*f649ed80SIan Rogers 396*f649ed80SIan Rogers dso__set_module_info(dso, m, machine); 397*f649ed80SIan Rogers dso__set_long_name(dso, strdup(filename), true); 398*f649ed80SIan Rogers dso->kernel = DSO_SPACE__KERNEL; 399*f649ed80SIan Rogers } 400*f649ed80SIan Rogers 401*f649ed80SIan Rogers out_unlock: 402*f649ed80SIan Rogers up_write(&dsos->lock); 403*f649ed80SIan Rogers return dso; 404*f649ed80SIan Rogers } 405*f649ed80SIan Rogers 406*f649ed80SIan Rogers struct dso *dsos__find_kernel_dso(struct dsos *dsos) 407*f649ed80SIan Rogers { 408*f649ed80SIan Rogers struct dso *dso, *res = NULL; 409*f649ed80SIan Rogers 410*f649ed80SIan Rogers down_read(&dsos->lock); 411*f649ed80SIan Rogers list_for_each_entry(dso, &dsos->head, node) { 412*f649ed80SIan Rogers /* 413*f649ed80SIan Rogers * The cpumode passed to is_kernel_module is not the cpumode of 414*f649ed80SIan Rogers * *this* event. If we insist on passing correct cpumode to 415*f649ed80SIan Rogers * is_kernel_module, we should record the cpumode when we adding 416*f649ed80SIan Rogers * this dso to the linked list. 417*f649ed80SIan Rogers * 418*f649ed80SIan Rogers * However we don't really need passing correct cpumode. We 419*f649ed80SIan Rogers * know the correct cpumode must be kernel mode (if not, we 420*f649ed80SIan Rogers * should not link it onto kernel_dsos list). 421*f649ed80SIan Rogers * 422*f649ed80SIan Rogers * Therefore, we pass PERF_RECORD_MISC_CPUMODE_UNKNOWN. 423*f649ed80SIan Rogers * is_kernel_module() treats it as a kernel cpumode. 424*f649ed80SIan Rogers */ 425*f649ed80SIan Rogers if (!dso->kernel || 426*f649ed80SIan Rogers is_kernel_module(dso->long_name, 427*f649ed80SIan Rogers PERF_RECORD_MISC_CPUMODE_UNKNOWN)) 428*f649ed80SIan Rogers continue; 429*f649ed80SIan Rogers 430*f649ed80SIan Rogers res = dso__get(dso); 431*f649ed80SIan Rogers break; 432*f649ed80SIan Rogers } 433*f649ed80SIan Rogers up_read(&dsos->lock); 434*f649ed80SIan Rogers return res; 435*f649ed80SIan Rogers } 436