xref: /linux/tools/perf/util/dsos.c (revision 36ec807b627b4c0a0a382f0ae48eac7187d14b2b)
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_rwsem(&dsos->lock);
183f4ac23aSIan Rogers 
193f4ac23aSIan Rogers 	dsos->cnt = 0;
203f4ac23aSIan Rogers 	dsos->allocated = 0;
213f4ac23aSIan Rogers 	dsos->dsos = NULL;
223f4ac23aSIan Rogers 	dsos->sorted = true;
2383acca9fSIan Rogers }
2483acca9fSIan Rogers 
2583acca9fSIan Rogers static void dsos__purge(struct dsos *dsos)
2683acca9fSIan Rogers {
2783acca9fSIan Rogers 	down_write(&dsos->lock);
2883acca9fSIan Rogers 
293f4ac23aSIan Rogers 	for (unsigned int i = 0; i < dsos->cnt; i++) {
303f4ac23aSIan Rogers 		struct dso *dso = dsos->dsos[i];
313f4ac23aSIan Rogers 
32ee756ef7SIan Rogers 		dso__set_dsos(dso, NULL);
333f4ac23aSIan Rogers 		dso__put(dso);
3483acca9fSIan Rogers 	}
3583acca9fSIan Rogers 
363f4ac23aSIan Rogers 	zfree(&dsos->dsos);
373f4ac23aSIan Rogers 	dsos->cnt = 0;
383f4ac23aSIan Rogers 	dsos->allocated = 0;
393f4ac23aSIan Rogers 	dsos->sorted = true;
403f4ac23aSIan Rogers 
4183acca9fSIan Rogers 	up_write(&dsos->lock);
4283acca9fSIan Rogers }
4383acca9fSIan Rogers 
4483acca9fSIan Rogers void dsos__exit(struct dsos *dsos)
4583acca9fSIan Rogers {
4683acca9fSIan Rogers 	dsos__purge(dsos);
4783acca9fSIan Rogers 	exit_rwsem(&dsos->lock);
4883acca9fSIan Rogers }
4983acca9fSIan Rogers 
500ffc8fcaSIan Rogers 
510ffc8fcaSIan Rogers static int __dsos__for_each_dso(struct dsos *dsos,
520ffc8fcaSIan Rogers 				int (*cb)(struct dso *dso, void *data),
530ffc8fcaSIan Rogers 				void *data)
544a3cec84SArnaldo Carvalho de Melo {
553f4ac23aSIan Rogers 	for (unsigned int i = 0; i < dsos->cnt; i++) {
563f4ac23aSIan Rogers 		struct dso *dso = dsos->dsos[i];
570ffc8fcaSIan Rogers 		int err;
580ffc8fcaSIan Rogers 
590ffc8fcaSIan Rogers 		err = cb(dso, data);
600ffc8fcaSIan Rogers 		if (err)
610ffc8fcaSIan Rogers 			return err;
620ffc8fcaSIan Rogers 	}
630ffc8fcaSIan Rogers 	return 0;
640ffc8fcaSIan Rogers }
650ffc8fcaSIan Rogers 
660ffc8fcaSIan Rogers struct dsos__read_build_ids_cb_args {
670ffc8fcaSIan Rogers 	bool with_hits;
680ffc8fcaSIan Rogers 	bool have_build_id;
690ffc8fcaSIan Rogers };
700ffc8fcaSIan Rogers 
710ffc8fcaSIan Rogers static int dsos__read_build_ids_cb(struct dso *dso, void *data)
720ffc8fcaSIan Rogers {
730ffc8fcaSIan Rogers 	struct dsos__read_build_ids_cb_args *args = data;
744a3cec84SArnaldo Carvalho de Melo 	struct nscookie nsc;
754a3cec84SArnaldo Carvalho de Melo 
76ee756ef7SIan Rogers 	if (args->with_hits && !dso__hit(dso) && !dso__is_vdso(dso))
770ffc8fcaSIan Rogers 		return 0;
78ee756ef7SIan Rogers 	if (dso__has_build_id(dso)) {
790ffc8fcaSIan Rogers 		args->have_build_id = true;
800ffc8fcaSIan Rogers 		return 0;
814a3cec84SArnaldo Carvalho de Melo 	}
82ee756ef7SIan Rogers 	nsinfo__mountns_enter(dso__nsinfo(dso), &nsc);
83ee756ef7SIan Rogers 	if (filename__read_build_id(dso__long_name(dso), dso__bid(dso)) > 0) {
840ffc8fcaSIan Rogers 		args->have_build_id = true;
85ee756ef7SIan Rogers 		dso__set_has_build_id(dso);
86ee756ef7SIan Rogers 	} else if (errno == ENOENT && dso__nsinfo(dso)) {
87ee756ef7SIan Rogers 		char *new_name = dso__filename_with_chroot(dso, dso__long_name(dso));
8867fd1892SNamhyung Kim 
89ee756ef7SIan Rogers 		if (new_name && filename__read_build_id(new_name, dso__bid(dso)) > 0) {
900ffc8fcaSIan Rogers 			args->have_build_id = true;
91ee756ef7SIan Rogers 			dso__set_has_build_id(dso);
9267fd1892SNamhyung Kim 		}
9367fd1892SNamhyung Kim 		free(new_name);
944a3cec84SArnaldo Carvalho de Melo 	}
954a3cec84SArnaldo Carvalho de Melo 	nsinfo__mountns_exit(&nsc);
960ffc8fcaSIan Rogers 	return 0;
974a3cec84SArnaldo Carvalho de Melo }
984a3cec84SArnaldo Carvalho de Melo 
990ffc8fcaSIan Rogers bool dsos__read_build_ids(struct dsos *dsos, bool with_hits)
1000ffc8fcaSIan Rogers {
1010ffc8fcaSIan Rogers 	struct dsos__read_build_ids_cb_args args = {
1020ffc8fcaSIan Rogers 		.with_hits = with_hits,
1030ffc8fcaSIan Rogers 		.have_build_id = false,
1040ffc8fcaSIan Rogers 	};
1050ffc8fcaSIan Rogers 
1060ffc8fcaSIan Rogers 	dsos__for_each_dso(dsos, dsos__read_build_ids_cb, &args);
1070ffc8fcaSIan Rogers 	return args.have_build_id;
1084a3cec84SArnaldo Carvalho de Melo }
1094a3cec84SArnaldo Carvalho de Melo 
1107a9418cfSIan Rogers static int __dso__cmp_long_name(const char *long_name, const struct dso_id *id,
1117a9418cfSIan Rogers 				const struct dso *b)
1120e3149f8SArnaldo Carvalho de Melo {
113ee756ef7SIan Rogers 	int rc = strcmp(long_name, dso__long_name(b));
114ee756ef7SIan Rogers 	return rc ?: dso_id__cmp(id, dso__id_const(b));
1150e3149f8SArnaldo Carvalho de Melo }
1160e3149f8SArnaldo Carvalho de Melo 
1177a9418cfSIan Rogers static int __dso__cmp_short_name(const char *short_name, const struct dso_id *id,
1187a9418cfSIan Rogers 				 const struct dso *b)
1190e3149f8SArnaldo Carvalho de Melo {
120ee756ef7SIan Rogers 	int rc = strcmp(short_name, dso__short_name(b));
121ee756ef7SIan Rogers 	return rc ?: dso_id__cmp(id, dso__id_const(b));
1220e3149f8SArnaldo Carvalho de Melo }
1230e3149f8SArnaldo Carvalho de Melo 
1243f4ac23aSIan Rogers static int dsos__cmp_long_name_id_short_name(const void *va, const void *vb)
1253f4ac23aSIan Rogers {
1263f4ac23aSIan Rogers 	const struct dso *a = *((const struct dso **)va);
1273f4ac23aSIan Rogers 	const struct dso *b = *((const struct dso **)vb);
128ee756ef7SIan Rogers 	int rc = strcmp(dso__long_name(a), dso__long_name(b));
1293f4ac23aSIan Rogers 
1303f4ac23aSIan Rogers 	if (!rc) {
131ee756ef7SIan Rogers 		rc = dso_id__cmp(dso__id_const(a), dso__id_const(b));
1323f4ac23aSIan Rogers 		if (!rc)
133ee756ef7SIan Rogers 			rc = strcmp(dso__short_name(a), dso__short_name(b));
1343f4ac23aSIan Rogers 	}
1353f4ac23aSIan Rogers 	return rc;
1363f4ac23aSIan Rogers }
1373f4ac23aSIan Rogers 
1387a9418cfSIan Rogers struct dsos__key {
1397a9418cfSIan Rogers 	const char *long_name;
1407a9418cfSIan Rogers 	const struct dso_id *id;
1417a9418cfSIan Rogers };
1427a9418cfSIan Rogers 
1437a9418cfSIan Rogers static int dsos__cmp_key_long_name_id(const void *vkey, const void *vdso)
1447a9418cfSIan Rogers {
1457a9418cfSIan Rogers 	const struct dsos__key *key = vkey;
1467a9418cfSIan Rogers 	const struct dso *dso = *((const struct dso **)vdso);
1477a9418cfSIan Rogers 
1487a9418cfSIan Rogers 	return __dso__cmp_long_name(key->long_name, key->id, dso);
1497a9418cfSIan Rogers }
1507a9418cfSIan Rogers 
1514a3cec84SArnaldo Carvalho de Melo /*
1524a3cec84SArnaldo Carvalho de Melo  * Find a matching entry and/or link current entry to RB tree.
1534a3cec84SArnaldo Carvalho de Melo  * Either one of the dso or name parameter must be non-NULL or the
1544a3cec84SArnaldo Carvalho de Melo  * function will not work.
1554a3cec84SArnaldo Carvalho de Melo  */
1567410d600SIan Rogers static struct dso *__dsos__find_by_longname_id(struct dsos *dsos,
1573f4ac23aSIan Rogers 					       const char *name,
1583f4ac23aSIan Rogers 					       struct dso_id *id,
1593f4ac23aSIan Rogers 					       bool write_locked)
1604a3cec84SArnaldo Carvalho de Melo {
1617a9418cfSIan Rogers 	struct dsos__key key = {
1627a9418cfSIan Rogers 		.long_name = name,
1637a9418cfSIan Rogers 		.id = id,
1647a9418cfSIan Rogers 	};
1657a9418cfSIan Rogers 	struct dso **res;
1663f4ac23aSIan Rogers 
1670eb739d8SNamhyung Kim 	if (dsos->dsos == NULL)
1680eb739d8SNamhyung Kim 		return NULL;
1690eb739d8SNamhyung Kim 
1703f4ac23aSIan Rogers 	if (!dsos->sorted) {
1713f4ac23aSIan Rogers 		if (!write_locked) {
1727410d600SIan Rogers 			struct dso *dso;
1737410d600SIan Rogers 
1743f4ac23aSIan Rogers 			up_read(&dsos->lock);
1753f4ac23aSIan Rogers 			down_write(&dsos->lock);
1767410d600SIan Rogers 			dso = __dsos__find_by_longname_id(dsos, name, id,
1773f4ac23aSIan Rogers 							  /*write_locked=*/true);
1783f4ac23aSIan Rogers 			up_write(&dsos->lock);
1793f4ac23aSIan Rogers 			down_read(&dsos->lock);
1803f4ac23aSIan Rogers 			return dso;
1813f4ac23aSIan Rogers 		}
1823f4ac23aSIan Rogers 		qsort(dsos->dsos, dsos->cnt, sizeof(struct dso *),
1833f4ac23aSIan Rogers 		      dsos__cmp_long_name_id_short_name);
1843f4ac23aSIan Rogers 		dsos->sorted = true;
1853f4ac23aSIan Rogers 	}
1864a3cec84SArnaldo Carvalho de Melo 
1877a9418cfSIan Rogers 	res = bsearch(&key, dsos->dsos, dsos->cnt, sizeof(struct dso *),
1887a9418cfSIan Rogers 		      dsos__cmp_key_long_name_id);
1897a9418cfSIan Rogers 	if (!res)
1904a3cec84SArnaldo Carvalho de Melo 		return NULL;
1917a9418cfSIan Rogers 
1927a9418cfSIan Rogers 	return dso__get(*res);
1934a3cec84SArnaldo Carvalho de Melo }
1944a3cec84SArnaldo Carvalho de Melo 
1953f4ac23aSIan Rogers int __dsos__add(struct dsos *dsos, struct dso *dso)
1964a3cec84SArnaldo Carvalho de Melo {
1973f4ac23aSIan Rogers 	if (dsos->cnt == dsos->allocated) {
1983f4ac23aSIan Rogers 		unsigned int to_allocate = 2;
1993f4ac23aSIan Rogers 		struct dso **temp;
2003f4ac23aSIan Rogers 
2013f4ac23aSIan Rogers 		if (dsos->allocated > 0)
2023f4ac23aSIan Rogers 			to_allocate = dsos->allocated * 2;
2033f4ac23aSIan Rogers 		temp = realloc(dsos->dsos, sizeof(struct dso *) * to_allocate);
2043f4ac23aSIan Rogers 		if (!temp)
2053f4ac23aSIan Rogers 			return -ENOMEM;
2063f4ac23aSIan Rogers 		dsos->dsos = temp;
2073f4ac23aSIan Rogers 		dsos->allocated = to_allocate;
2083f4ac23aSIan Rogers 	}
209*1059fb52SIan Rogers 	if (!dsos->sorted) {
2103f4ac23aSIan Rogers 		dsos->dsos[dsos->cnt++] = dso__get(dso);
211*1059fb52SIan Rogers 	} else {
212*1059fb52SIan Rogers 		int low = 0, high = dsos->cnt - 1;
213*1059fb52SIan Rogers 		int insert = dsos->cnt; /* Default to inserting at the end. */
214*1059fb52SIan Rogers 
215*1059fb52SIan Rogers 		while (low <= high) {
216*1059fb52SIan Rogers 			int mid = low + (high - low) / 2;
217*1059fb52SIan Rogers 			int cmp = dsos__cmp_long_name_id_short_name(&dsos->dsos[mid], &dso);
218*1059fb52SIan Rogers 
219*1059fb52SIan Rogers 			if (cmp < 0) {
220*1059fb52SIan Rogers 				low = mid + 1;
221*1059fb52SIan Rogers 			} else {
222*1059fb52SIan Rogers 				high = mid - 1;
223*1059fb52SIan Rogers 				insert = mid;
224*1059fb52SIan Rogers 			}
225*1059fb52SIan Rogers 		}
226*1059fb52SIan Rogers 		memmove(&dsos->dsos[insert + 1], &dsos->dsos[insert],
227*1059fb52SIan Rogers 			(dsos->cnt - insert) * sizeof(struct dso *));
228*1059fb52SIan Rogers 		dsos->cnt++;
229*1059fb52SIan Rogers 		dsos->dsos[insert] = dso__get(dso);
2303f4ac23aSIan Rogers 	}
231ee756ef7SIan Rogers 	dso__set_dsos(dso, dsos);
2323f4ac23aSIan Rogers 	return 0;
2334a3cec84SArnaldo Carvalho de Melo }
2344a3cec84SArnaldo Carvalho de Melo 
2353f4ac23aSIan Rogers int dsos__add(struct dsos *dsos, struct dso *dso)
2364a3cec84SArnaldo Carvalho de Melo {
2373f4ac23aSIan Rogers 	int ret;
2383f4ac23aSIan Rogers 
2394a3cec84SArnaldo Carvalho de Melo 	down_write(&dsos->lock);
2403f4ac23aSIan Rogers 	ret = __dsos__add(dsos, dso);
2414a3cec84SArnaldo Carvalho de Melo 	up_write(&dsos->lock);
2423f4ac23aSIan Rogers 	return ret;
2434a3cec84SArnaldo Carvalho de Melo }
2444a3cec84SArnaldo Carvalho de Melo 
2450ffc8fcaSIan Rogers struct dsos__find_id_cb_args {
2460ffc8fcaSIan Rogers 	const char *name;
2470ffc8fcaSIan Rogers 	struct dso_id *id;
2480ffc8fcaSIan Rogers 	struct dso *res;
2490ffc8fcaSIan Rogers };
2500ffc8fcaSIan Rogers 
2510ffc8fcaSIan Rogers static int dsos__find_id_cb(struct dso *dso, void *data)
2520ffc8fcaSIan Rogers {
2530ffc8fcaSIan Rogers 	struct dsos__find_id_cb_args *args = data;
2540ffc8fcaSIan Rogers 
2550ffc8fcaSIan Rogers 	if (__dso__cmp_short_name(args->name, args->id, dso) == 0) {
2560ffc8fcaSIan Rogers 		args->res = dso__get(dso);
2570ffc8fcaSIan Rogers 		return 1;
2580ffc8fcaSIan Rogers 	}
2590ffc8fcaSIan Rogers 	return 0;
2600ffc8fcaSIan Rogers 
2610ffc8fcaSIan Rogers }
2620ffc8fcaSIan Rogers 
2633f4ac23aSIan Rogers static struct dso *__dsos__find_id(struct dsos *dsos, const char *name, struct dso_id *id,
2643f4ac23aSIan Rogers 				   bool cmp_short, bool write_locked)
2654a3cec84SArnaldo Carvalho de Melo {
2660ffc8fcaSIan Rogers 	struct dso *res;
2674a3cec84SArnaldo Carvalho de Melo 
2684a3cec84SArnaldo Carvalho de Melo 	if (cmp_short) {
2690ffc8fcaSIan Rogers 		struct dsos__find_id_cb_args args = {
2700ffc8fcaSIan Rogers 			.name = name,
2710ffc8fcaSIan Rogers 			.id = id,
2720ffc8fcaSIan Rogers 			.res = NULL,
2730ffc8fcaSIan Rogers 		};
2740ffc8fcaSIan Rogers 
2750ffc8fcaSIan Rogers 		__dsos__for_each_dso(dsos, dsos__find_id_cb, &args);
2760ffc8fcaSIan Rogers 		return args.res;
2774a3cec84SArnaldo Carvalho de Melo 	}
2787410d600SIan Rogers 	res = __dsos__find_by_longname_id(dsos, name, id, write_locked);
2790ffc8fcaSIan Rogers 	return res;
2800e3149f8SArnaldo Carvalho de Melo }
2810e3149f8SArnaldo Carvalho de Melo 
282f649ed80SIan Rogers struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
2830e3149f8SArnaldo Carvalho de Melo {
284f649ed80SIan Rogers 	struct dso *res;
285f649ed80SIan Rogers 
286f649ed80SIan Rogers 	down_read(&dsos->lock);
2873f4ac23aSIan Rogers 	res = __dsos__find_id(dsos, name, NULL, cmp_short, /*write_locked=*/false);
288f649ed80SIan Rogers 	up_read(&dsos->lock);
289f649ed80SIan Rogers 	return res;
2904a3cec84SArnaldo Carvalho de Melo }
2914a3cec84SArnaldo Carvalho de Melo 
2924a3cec84SArnaldo Carvalho de Melo static void dso__set_basename(struct dso *dso)
2934a3cec84SArnaldo Carvalho de Melo {
2944a3cec84SArnaldo Carvalho de Melo 	char *base, *lname;
2954a3cec84SArnaldo Carvalho de Melo 	int tid;
2964a3cec84SArnaldo Carvalho de Melo 
297b9241f15SAthira Rajeev 	if (perf_pid_map_tid(dso__long_name(dso), &tid)) {
2984a3cec84SArnaldo Carvalho de Melo 		if (asprintf(&base, "[JIT] tid %d", tid) < 0)
2994a3cec84SArnaldo Carvalho de Melo 			return;
3004a3cec84SArnaldo Carvalho de Melo 	} else {
3014a3cec84SArnaldo Carvalho de Melo 	      /*
3024a3cec84SArnaldo Carvalho de Melo 	       * basename() may modify path buffer, so we must pass
3034a3cec84SArnaldo Carvalho de Melo                * a copy.
3044a3cec84SArnaldo Carvalho de Melo                */
305ee756ef7SIan Rogers 		lname = strdup(dso__long_name(dso));
3064a3cec84SArnaldo Carvalho de Melo 		if (!lname)
3074a3cec84SArnaldo Carvalho de Melo 			return;
3084a3cec84SArnaldo Carvalho de Melo 
3094a3cec84SArnaldo Carvalho de Melo 		/*
3104a3cec84SArnaldo Carvalho de Melo 		 * basename() may return a pointer to internal
3114a3cec84SArnaldo Carvalho de Melo 		 * storage which is reused in subsequent calls
3124a3cec84SArnaldo Carvalho de Melo 		 * so copy the result.
3134a3cec84SArnaldo Carvalho de Melo 		 */
3144a3cec84SArnaldo Carvalho de Melo 		base = strdup(basename(lname));
3154a3cec84SArnaldo Carvalho de Melo 
3164a3cec84SArnaldo Carvalho de Melo 		free(lname);
3174a3cec84SArnaldo Carvalho de Melo 
3184a3cec84SArnaldo Carvalho de Melo 		if (!base)
3194a3cec84SArnaldo Carvalho de Melo 			return;
3204a3cec84SArnaldo Carvalho de Melo 	}
3214a3cec84SArnaldo Carvalho de Melo 	dso__set_short_name(dso, base, true);
3224a3cec84SArnaldo Carvalho de Melo }
3234a3cec84SArnaldo Carvalho de Melo 
3240e3149f8SArnaldo Carvalho de Melo static struct dso *__dsos__addnew_id(struct dsos *dsos, const char *name, struct dso_id *id)
3254a3cec84SArnaldo Carvalho de Melo {
3260e3149f8SArnaldo Carvalho de Melo 	struct dso *dso = dso__new_id(name, id);
3274a3cec84SArnaldo Carvalho de Melo 
3284a3cec84SArnaldo Carvalho de Melo 	if (dso != NULL) {
3293f4ac23aSIan Rogers 		/*
3303f4ac23aSIan Rogers 		 * The dsos lock is held on entry, so rename the dso before
3313f4ac23aSIan Rogers 		 * adding it to avoid needing to take the dsos lock again to say
3323f4ac23aSIan Rogers 		 * the array isn't sorted.
3333f4ac23aSIan Rogers 		 */
3344a3cec84SArnaldo Carvalho de Melo 		dso__set_basename(dso);
3353f4ac23aSIan Rogers 		__dsos__add(dsos, dso);
3364a3cec84SArnaldo Carvalho de Melo 	}
3374a3cec84SArnaldo Carvalho de Melo 	return dso;
3384a3cec84SArnaldo Carvalho de Melo }
3394a3cec84SArnaldo Carvalho de Melo 
3400e3149f8SArnaldo Carvalho de Melo static struct dso *__dsos__findnew_id(struct dsos *dsos, const char *name, struct dso_id *id)
3410e3149f8SArnaldo Carvalho de Melo {
3423f4ac23aSIan Rogers 	struct dso *dso = __dsos__find_id(dsos, name, id, false, /*write_locked=*/true);
3430d33b343SRavi Bangoria 
344ee756ef7SIan Rogers 	if (dso && dso_id__empty(dso__id(dso)) && !dso_id__empty(id))
3453f4ac23aSIan Rogers 		__dso__inject_id(dso, id);
3460d33b343SRavi Bangoria 
3470e3149f8SArnaldo Carvalho de Melo 	return dso ? dso : __dsos__addnew_id(dsos, name, id);
3480e3149f8SArnaldo Carvalho de Melo }
3490e3149f8SArnaldo Carvalho de Melo 
3500e3149f8SArnaldo Carvalho de Melo struct dso *dsos__findnew_id(struct dsos *dsos, const char *name, struct dso_id *id)
3514a3cec84SArnaldo Carvalho de Melo {
3524a3cec84SArnaldo Carvalho de Melo 	struct dso *dso;
3534a3cec84SArnaldo Carvalho de Melo 	down_write(&dsos->lock);
354f649ed80SIan Rogers 	dso = __dsos__findnew_id(dsos, name, id);
3554a3cec84SArnaldo Carvalho de Melo 	up_write(&dsos->lock);
3564a3cec84SArnaldo Carvalho de Melo 	return dso;
3574a3cec84SArnaldo Carvalho de Melo }
3584a3cec84SArnaldo Carvalho de Melo 
3590ffc8fcaSIan Rogers struct dsos__fprintf_buildid_cb_args {
3600ffc8fcaSIan Rogers 	FILE *fp;
3610ffc8fcaSIan Rogers 	bool (*skip)(struct dso *dso, int parm);
3620ffc8fcaSIan Rogers 	int parm;
3630ffc8fcaSIan Rogers 	size_t ret;
3640ffc8fcaSIan Rogers };
3654a3cec84SArnaldo Carvalho de Melo 
3660ffc8fcaSIan Rogers static int dsos__fprintf_buildid_cb(struct dso *dso, void *data)
3670ffc8fcaSIan Rogers {
3680ffc8fcaSIan Rogers 	struct dsos__fprintf_buildid_cb_args *args = data;
369e9ad9438SJiri Olsa 	char sbuild_id[SBUILD_ID_SIZE];
370e9ad9438SJiri Olsa 
3710ffc8fcaSIan Rogers 	if (args->skip && args->skip(dso, args->parm))
37283acca9fSIan Rogers 		return 0;
373ee756ef7SIan Rogers 	build_id__sprintf(dso__bid(dso), sbuild_id);
374ee756ef7SIan Rogers 	args->ret += fprintf(args->fp, "%-40s %s\n", sbuild_id, dso__long_name(dso));
3750ffc8fcaSIan Rogers 	return 0;
3760ffc8fcaSIan Rogers }
3770ffc8fcaSIan Rogers 
3780ffc8fcaSIan Rogers size_t dsos__fprintf_buildid(struct dsos *dsos, FILE *fp,
3790ffc8fcaSIan Rogers 			       bool (*skip)(struct dso *dso, int parm), int parm)
3800ffc8fcaSIan Rogers {
3810ffc8fcaSIan Rogers 	struct dsos__fprintf_buildid_cb_args args = {
3820ffc8fcaSIan Rogers 		.fp = fp,
3830ffc8fcaSIan Rogers 		.skip = skip,
3840ffc8fcaSIan Rogers 		.parm = parm,
3850ffc8fcaSIan Rogers 		.ret = 0,
3860ffc8fcaSIan Rogers 	};
3870ffc8fcaSIan Rogers 
3880ffc8fcaSIan Rogers 	dsos__for_each_dso(dsos, dsos__fprintf_buildid_cb, &args);
3890ffc8fcaSIan Rogers 	return args.ret;
3900ffc8fcaSIan Rogers }
3910ffc8fcaSIan Rogers 
3920ffc8fcaSIan Rogers struct dsos__fprintf_cb_args {
3930ffc8fcaSIan Rogers 	FILE *fp;
3940ffc8fcaSIan Rogers 	size_t ret;
3950ffc8fcaSIan Rogers };
3960ffc8fcaSIan Rogers 
3970ffc8fcaSIan Rogers static int dsos__fprintf_cb(struct dso *dso, void *data)
3980ffc8fcaSIan Rogers {
3990ffc8fcaSIan Rogers 	struct dsos__fprintf_cb_args *args = data;
4000ffc8fcaSIan Rogers 
4010ffc8fcaSIan Rogers 	args->ret += dso__fprintf(dso, args->fp);
4020ffc8fcaSIan Rogers 	return 0;
4030ffc8fcaSIan Rogers }
4040ffc8fcaSIan Rogers 
4050ffc8fcaSIan Rogers size_t dsos__fprintf(struct dsos *dsos, FILE *fp)
4060ffc8fcaSIan Rogers {
4070ffc8fcaSIan Rogers 	struct dsos__fprintf_cb_args args = {
4080ffc8fcaSIan Rogers 		.fp = fp,
4090ffc8fcaSIan Rogers 		.ret = 0,
4100ffc8fcaSIan Rogers 	};
4110ffc8fcaSIan Rogers 
4120ffc8fcaSIan Rogers 	dsos__for_each_dso(dsos, dsos__fprintf_cb, &args);
4130ffc8fcaSIan Rogers 	return args.ret;
4140ffc8fcaSIan Rogers }
4150ffc8fcaSIan Rogers 
4160ffc8fcaSIan Rogers static int dsos__hit_all_cb(struct dso *dso, void *data __maybe_unused)
4170ffc8fcaSIan Rogers {
418ee756ef7SIan Rogers 	dso__set_hit(dso);
4190ffc8fcaSIan Rogers 	return 0;
4200ffc8fcaSIan Rogers }
4210ffc8fcaSIan Rogers 
4220ffc8fcaSIan Rogers int dsos__hit_all(struct dsos *dsos)
4230ffc8fcaSIan Rogers {
4240ffc8fcaSIan Rogers 	return dsos__for_each_dso(dsos, dsos__hit_all_cb, NULL);
42583acca9fSIan Rogers }
426f649ed80SIan Rogers 
427f649ed80SIan Rogers struct dso *dsos__findnew_module_dso(struct dsos *dsos,
428f649ed80SIan Rogers 				     struct machine *machine,
429f649ed80SIan Rogers 				     struct kmod_path *m,
430f649ed80SIan Rogers 				     const char *filename)
431f649ed80SIan Rogers {
432f649ed80SIan Rogers 	struct dso *dso;
433f649ed80SIan Rogers 
434f649ed80SIan Rogers 	down_write(&dsos->lock);
435f649ed80SIan Rogers 
4363f4ac23aSIan Rogers 	dso = __dsos__find_id(dsos, m->name, NULL, /*cmp_short=*/true, /*write_locked=*/true);
4373f4ac23aSIan Rogers 	if (dso) {
4383f4ac23aSIan Rogers 		up_write(&dsos->lock);
4393f4ac23aSIan Rogers 		return dso;
4403f4ac23aSIan Rogers 	}
4413f4ac23aSIan Rogers 	/*
4423f4ac23aSIan Rogers 	 * Failed to find the dso so create it. Change the name before adding it
4433f4ac23aSIan Rogers 	 * to the array, to avoid unnecessary sorts and potential locking
4443f4ac23aSIan Rogers 	 * issues.
4453f4ac23aSIan Rogers 	 */
4463f4ac23aSIan Rogers 	dso = dso__new_id(m->name, /*id=*/NULL);
447f649ed80SIan Rogers 	if (!dso) {
4483f4ac23aSIan Rogers 		up_write(&dsos->lock);
4493f4ac23aSIan Rogers 		return NULL;
4503f4ac23aSIan Rogers 	}
4513f4ac23aSIan Rogers 	dso__set_basename(dso);
452f649ed80SIan Rogers 	dso__set_module_info(dso, m, machine);
453f649ed80SIan Rogers 	dso__set_long_name(dso,	strdup(filename), true);
454ee756ef7SIan Rogers 	dso__set_kernel(dso, DSO_SPACE__KERNEL);
4553f4ac23aSIan Rogers 	__dsos__add(dsos, dso);
456f649ed80SIan Rogers 
457f649ed80SIan Rogers 	up_write(&dsos->lock);
458f649ed80SIan Rogers 	return dso;
459f649ed80SIan Rogers }
460f649ed80SIan Rogers 
4610ffc8fcaSIan Rogers static int dsos__find_kernel_dso_cb(struct dso *dso, void *data)
462f649ed80SIan Rogers {
4630ffc8fcaSIan Rogers 	struct dso **res = data;
464f649ed80SIan Rogers 	/*
4650ffc8fcaSIan Rogers 	 * The cpumode passed to is_kernel_module is not the cpumode of *this*
4660ffc8fcaSIan Rogers 	 * event. If we insist on passing correct cpumode to is_kernel_module,
4670ffc8fcaSIan Rogers 	 * we should record the cpumode when we adding this dso to the linked
4680ffc8fcaSIan Rogers 	 * list.
469f649ed80SIan Rogers 	 *
4700ffc8fcaSIan Rogers 	 * However we don't really need passing correct cpumode.  We know the
4710ffc8fcaSIan Rogers 	 * correct cpumode must be kernel mode (if not, we should not link it
4720ffc8fcaSIan Rogers 	 * onto kernel_dsos list).
473f649ed80SIan Rogers 	 *
474f649ed80SIan Rogers 	 * Therefore, we pass PERF_RECORD_MISC_CPUMODE_UNKNOWN.
475f649ed80SIan Rogers 	 * is_kernel_module() treats it as a kernel cpumode.
476f649ed80SIan Rogers 	 */
477ee756ef7SIan Rogers 	if (!dso__kernel(dso) ||
478ee756ef7SIan Rogers 	    is_kernel_module(dso__long_name(dso), PERF_RECORD_MISC_CPUMODE_UNKNOWN))
4790ffc8fcaSIan Rogers 		return 0;
480f649ed80SIan Rogers 
4810ffc8fcaSIan Rogers 	*res = dso__get(dso);
4820ffc8fcaSIan Rogers 	return 1;
483f649ed80SIan Rogers }
4840ffc8fcaSIan Rogers 
4850ffc8fcaSIan Rogers struct dso *dsos__find_kernel_dso(struct dsos *dsos)
4860ffc8fcaSIan Rogers {
4870ffc8fcaSIan Rogers 	struct dso *res = NULL;
4880ffc8fcaSIan Rogers 
4890ffc8fcaSIan Rogers 	dsos__for_each_dso(dsos, dsos__find_kernel_dso_cb, &res);
490f649ed80SIan Rogers 	return res;
491f649ed80SIan Rogers }
49273f3fea2SIan Rogers 
49373f3fea2SIan Rogers int dsos__for_each_dso(struct dsos *dsos, int (*cb)(struct dso *dso, void *data), void *data)
49473f3fea2SIan Rogers {
49573f3fea2SIan Rogers 	int err;
49673f3fea2SIan Rogers 
4970ffc8fcaSIan Rogers 	down_read(&dsos->lock);
4980ffc8fcaSIan Rogers 	err = __dsos__for_each_dso(dsos, cb, data);
49973f3fea2SIan Rogers 	up_read(&dsos->lock);
5000ffc8fcaSIan Rogers 	return err;
50173f3fea2SIan Rogers }
502