xref: /linux/tools/perf/util/dsos.c (revision f649ed80f3cabbf16b228894bb7ecd718da86e47)
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