xref: /linux/tools/perf/util/symbol.c (revision e1c7c6a40c8037478742ce134190c1a955853bfb)
186470930SIngo Molnar #include "util.h"
286470930SIngo Molnar #include "../perf.h"
34aa65636SArnaldo Carvalho de Melo #include "session.h"
4655000e7SArnaldo Carvalho de Melo #include "sort.h"
586470930SIngo Molnar #include "string.h"
686470930SIngo Molnar #include "symbol.h"
7439d473bSArnaldo Carvalho de Melo #include "thread.h"
886470930SIngo Molnar 
98f28827aSFrederic Weisbecker #include "debug.h"
108f28827aSFrederic Weisbecker 
11b32d133aSArnaldo Carvalho de Melo #include <asm/bug.h>
1286470930SIngo Molnar #include <libelf.h>
1386470930SIngo Molnar #include <gelf.h>
1486470930SIngo Molnar #include <elf.h>
15f1617b40SArnaldo Carvalho de Melo #include <limits.h>
16439d473bSArnaldo Carvalho de Melo #include <sys/utsname.h>
172cdbc46dSPeter Zijlstra 
18c12e15e7SArnaldo Carvalho de Melo #ifndef NT_GNU_BUILD_ID
19c12e15e7SArnaldo Carvalho de Melo #define NT_GNU_BUILD_ID 3
20c12e15e7SArnaldo Carvalho de Melo #endif
21c12e15e7SArnaldo Carvalho de Melo 
2294cb9e38SArnaldo Carvalho de Melo enum dso_origin {
2394cb9e38SArnaldo Carvalho de Melo 	DSO__ORIG_KERNEL = 0,
2494cb9e38SArnaldo Carvalho de Melo 	DSO__ORIG_JAVA_JIT,
254cf40131SArnaldo Carvalho de Melo 	DSO__ORIG_BUILD_ID_CACHE,
2694cb9e38SArnaldo Carvalho de Melo 	DSO__ORIG_FEDORA,
2794cb9e38SArnaldo Carvalho de Melo 	DSO__ORIG_UBUNTU,
2894cb9e38SArnaldo Carvalho de Melo 	DSO__ORIG_BUILDID,
2994cb9e38SArnaldo Carvalho de Melo 	DSO__ORIG_DSO,
30439d473bSArnaldo Carvalho de Melo 	DSO__ORIG_KMODULE,
3194cb9e38SArnaldo Carvalho de Melo 	DSO__ORIG_NOT_FOUND,
3294cb9e38SArnaldo Carvalho de Melo };
3394cb9e38SArnaldo Carvalho de Melo 
34b0da954aSArnaldo Carvalho de Melo static void dsos__add(struct list_head *head, struct dso *dso);
353610583cSArnaldo Carvalho de Melo static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
36c338aee8SArnaldo Carvalho de Melo static int dso__load_kernel_sym(struct dso *self, struct map *map,
374aa65636SArnaldo Carvalho de Melo 				struct perf_session *session, symbol_filter_t filter);
38cc612d81SArnaldo Carvalho de Melo static int vmlinux_path__nr_entries;
39cc612d81SArnaldo Carvalho de Melo static char **vmlinux_path;
40439d473bSArnaldo Carvalho de Melo 
4175be6cf4SArnaldo Carvalho de Melo struct symbol_conf symbol_conf = {
42d599db3fSArnaldo Carvalho de Melo 	.exclude_other	  = true,
43b32d133aSArnaldo Carvalho de Melo 	.use_modules	  = true,
44b32d133aSArnaldo Carvalho de Melo 	.try_vmlinux_path = true,
45b32d133aSArnaldo Carvalho de Melo };
46b32d133aSArnaldo Carvalho de Melo 
473610583cSArnaldo Carvalho de Melo bool dso__loaded(const struct dso *self, enum map_type type)
483610583cSArnaldo Carvalho de Melo {
493610583cSArnaldo Carvalho de Melo 	return self->loaded & (1 << type);
503610583cSArnaldo Carvalho de Melo }
513610583cSArnaldo Carvalho de Melo 
5279406cd7SArnaldo Carvalho de Melo bool dso__sorted_by_name(const struct dso *self, enum map_type type)
5379406cd7SArnaldo Carvalho de Melo {
5479406cd7SArnaldo Carvalho de Melo 	return self->sorted_by_name & (1 << type);
5579406cd7SArnaldo Carvalho de Melo }
5679406cd7SArnaldo Carvalho de Melo 
573610583cSArnaldo Carvalho de Melo static void dso__set_loaded(struct dso *self, enum map_type type)
583610583cSArnaldo Carvalho de Melo {
593610583cSArnaldo Carvalho de Melo 	self->loaded |= (1 << type);
603610583cSArnaldo Carvalho de Melo }
613610583cSArnaldo Carvalho de Melo 
6279406cd7SArnaldo Carvalho de Melo static void dso__set_sorted_by_name(struct dso *self, enum map_type type)
6379406cd7SArnaldo Carvalho de Melo {
6479406cd7SArnaldo Carvalho de Melo 	self->sorted_by_name |= (1 << type);
6579406cd7SArnaldo Carvalho de Melo }
6679406cd7SArnaldo Carvalho de Melo 
6736a3e646SArnaldo Carvalho de Melo bool symbol_type__is_a(char symbol_type, enum map_type map_type)
686893d4eeSArnaldo Carvalho de Melo {
696893d4eeSArnaldo Carvalho de Melo 	switch (map_type) {
706893d4eeSArnaldo Carvalho de Melo 	case MAP__FUNCTION:
716893d4eeSArnaldo Carvalho de Melo 		return symbol_type == 'T' || symbol_type == 'W';
72f1dfa0b1SArnaldo Carvalho de Melo 	case MAP__VARIABLE:
73f1dfa0b1SArnaldo Carvalho de Melo 		return symbol_type == 'D' || symbol_type == 'd';
746893d4eeSArnaldo Carvalho de Melo 	default:
756893d4eeSArnaldo Carvalho de Melo 		return false;
766893d4eeSArnaldo Carvalho de Melo 	}
776893d4eeSArnaldo Carvalho de Melo }
786893d4eeSArnaldo Carvalho de Melo 
79fcf1203aSArnaldo Carvalho de Melo static void symbols__fixup_end(struct rb_root *self)
80af427bf5SArnaldo Carvalho de Melo {
81fcf1203aSArnaldo Carvalho de Melo 	struct rb_node *nd, *prevnd = rb_first(self);
822e538c4aSArnaldo Carvalho de Melo 	struct symbol *curr, *prev;
83af427bf5SArnaldo Carvalho de Melo 
84af427bf5SArnaldo Carvalho de Melo 	if (prevnd == NULL)
85af427bf5SArnaldo Carvalho de Melo 		return;
86af427bf5SArnaldo Carvalho de Melo 
872e538c4aSArnaldo Carvalho de Melo 	curr = rb_entry(prevnd, struct symbol, rb_node);
882e538c4aSArnaldo Carvalho de Melo 
89af427bf5SArnaldo Carvalho de Melo 	for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
902e538c4aSArnaldo Carvalho de Melo 		prev = curr;
912e538c4aSArnaldo Carvalho de Melo 		curr = rb_entry(nd, struct symbol, rb_node);
92af427bf5SArnaldo Carvalho de Melo 
93af427bf5SArnaldo Carvalho de Melo 		if (prev->end == prev->start)
94af427bf5SArnaldo Carvalho de Melo 			prev->end = curr->start - 1;
95af427bf5SArnaldo Carvalho de Melo 	}
96af427bf5SArnaldo Carvalho de Melo 
972e538c4aSArnaldo Carvalho de Melo 	/* Last entry */
982e538c4aSArnaldo Carvalho de Melo 	if (curr->end == curr->start)
992e538c4aSArnaldo Carvalho de Melo 		curr->end = roundup(curr->start, 4096);
1002e538c4aSArnaldo Carvalho de Melo }
1012e538c4aSArnaldo Carvalho de Melo 
1029958e1f0SArnaldo Carvalho de Melo static void __map_groups__fixup_end(struct map_groups *self, enum map_type type)
103af427bf5SArnaldo Carvalho de Melo {
104af427bf5SArnaldo Carvalho de Melo 	struct map *prev, *curr;
10595011c60SArnaldo Carvalho de Melo 	struct rb_node *nd, *prevnd = rb_first(&self->maps[type]);
106af427bf5SArnaldo Carvalho de Melo 
107af427bf5SArnaldo Carvalho de Melo 	if (prevnd == NULL)
108af427bf5SArnaldo Carvalho de Melo 		return;
109af427bf5SArnaldo Carvalho de Melo 
110af427bf5SArnaldo Carvalho de Melo 	curr = rb_entry(prevnd, struct map, rb_node);
111af427bf5SArnaldo Carvalho de Melo 
112af427bf5SArnaldo Carvalho de Melo 	for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
113af427bf5SArnaldo Carvalho de Melo 		prev = curr;
114af427bf5SArnaldo Carvalho de Melo 		curr = rb_entry(nd, struct map, rb_node);
115af427bf5SArnaldo Carvalho de Melo 		prev->end = curr->start - 1;
1162e538c4aSArnaldo Carvalho de Melo 	}
11790c83218SArnaldo Carvalho de Melo 
11890c83218SArnaldo Carvalho de Melo 	/*
11990c83218SArnaldo Carvalho de Melo 	 * We still haven't the actual symbols, so guess the
12090c83218SArnaldo Carvalho de Melo 	 * last map final address.
12190c83218SArnaldo Carvalho de Melo 	 */
12290c83218SArnaldo Carvalho de Melo 	curr->end = ~0UL;
123af427bf5SArnaldo Carvalho de Melo }
124af427bf5SArnaldo Carvalho de Melo 
1259958e1f0SArnaldo Carvalho de Melo static void map_groups__fixup_end(struct map_groups *self)
12623ea4a3fSArnaldo Carvalho de Melo {
12723ea4a3fSArnaldo Carvalho de Melo 	int i;
12823ea4a3fSArnaldo Carvalho de Melo 	for (i = 0; i < MAP__NR_TYPES; ++i)
1299958e1f0SArnaldo Carvalho de Melo 		__map_groups__fixup_end(self, i);
13023ea4a3fSArnaldo Carvalho de Melo }
13123ea4a3fSArnaldo Carvalho de Melo 
13200a192b3SArnaldo Carvalho de Melo static struct symbol *symbol__new(u64 start, u64 len, const char *name)
13386470930SIngo Molnar {
13486470930SIngo Molnar 	size_t namelen = strlen(name) + 1;
13575be6cf4SArnaldo Carvalho de Melo 	struct symbol *self = zalloc(symbol_conf.priv_size +
13636479484SArnaldo Carvalho de Melo 				     sizeof(*self) + namelen);
13736479484SArnaldo Carvalho de Melo 	if (self == NULL)
13886470930SIngo Molnar 		return NULL;
13986470930SIngo Molnar 
14075be6cf4SArnaldo Carvalho de Melo 	if (symbol_conf.priv_size)
14175be6cf4SArnaldo Carvalho de Melo 		self = ((void *)self) + symbol_conf.priv_size;
14236479484SArnaldo Carvalho de Melo 
14386470930SIngo Molnar 	self->start = start;
1446cfcc53eSMike Galbraith 	self->end   = len ? start + len - 1 : start;
145e4204992SArnaldo Carvalho de Melo 
1466beba7adSArnaldo Carvalho de Melo 	pr_debug3("%s: %s %#Lx-%#Lx\n", __func__, name, start, self->end);
147e4204992SArnaldo Carvalho de Melo 
14886470930SIngo Molnar 	memcpy(self->name, name, namelen);
14986470930SIngo Molnar 
15086470930SIngo Molnar 	return self;
15186470930SIngo Molnar }
15286470930SIngo Molnar 
15300a192b3SArnaldo Carvalho de Melo static void symbol__delete(struct symbol *self)
15486470930SIngo Molnar {
15575be6cf4SArnaldo Carvalho de Melo 	free(((void *)self) - symbol_conf.priv_size);
15686470930SIngo Molnar }
15786470930SIngo Molnar 
15886470930SIngo Molnar static size_t symbol__fprintf(struct symbol *self, FILE *fp)
15986470930SIngo Molnar {
16086470930SIngo Molnar 	return fprintf(fp, " %llx-%llx %s\n",
16186470930SIngo Molnar 		       self->start, self->end, self->name);
16286470930SIngo Molnar }
16386470930SIngo Molnar 
164b7cece76SArnaldo Carvalho de Melo void dso__set_long_name(struct dso *self, char *name)
165cfc10d3bSArnaldo Carvalho de Melo {
166ef6ae724SArnaldo Carvalho de Melo 	if (name == NULL)
167ef6ae724SArnaldo Carvalho de Melo 		return;
168cfc10d3bSArnaldo Carvalho de Melo 	self->long_name = name;
169cfc10d3bSArnaldo Carvalho de Melo 	self->long_name_len = strlen(name);
170cfc10d3bSArnaldo Carvalho de Melo }
171cfc10d3bSArnaldo Carvalho de Melo 
172cfc10d3bSArnaldo Carvalho de Melo static void dso__set_basename(struct dso *self)
173cfc10d3bSArnaldo Carvalho de Melo {
174cfc10d3bSArnaldo Carvalho de Melo 	self->short_name = basename(self->long_name);
175cfc10d3bSArnaldo Carvalho de Melo }
176cfc10d3bSArnaldo Carvalho de Melo 
17700a192b3SArnaldo Carvalho de Melo struct dso *dso__new(const char *name)
17886470930SIngo Molnar {
179b7cece76SArnaldo Carvalho de Melo 	struct dso *self = zalloc(sizeof(*self) + strlen(name) + 1);
18086470930SIngo Molnar 
18186470930SIngo Molnar 	if (self != NULL) {
1826a4694a4SArnaldo Carvalho de Melo 		int i;
18386470930SIngo Molnar 		strcpy(self->name, name);
184cfc10d3bSArnaldo Carvalho de Melo 		dso__set_long_name(self, self->name);
185439d473bSArnaldo Carvalho de Melo 		self->short_name = self->name;
1866a4694a4SArnaldo Carvalho de Melo 		for (i = 0; i < MAP__NR_TYPES; ++i)
18779406cd7SArnaldo Carvalho de Melo 			self->symbols[i] = self->symbol_names[i] = RB_ROOT;
18852d422deSArnaldo Carvalho de Melo 		self->slen_calculated = 0;
18994cb9e38SArnaldo Carvalho de Melo 		self->origin = DSO__ORIG_NOT_FOUND;
1908d06367fSArnaldo Carvalho de Melo 		self->loaded = 0;
19179406cd7SArnaldo Carvalho de Melo 		self->sorted_by_name = 0;
1928d06367fSArnaldo Carvalho de Melo 		self->has_build_id = 0;
19386470930SIngo Molnar 	}
19486470930SIngo Molnar 
19586470930SIngo Molnar 	return self;
19686470930SIngo Molnar }
19786470930SIngo Molnar 
198fcf1203aSArnaldo Carvalho de Melo static void symbols__delete(struct rb_root *self)
19986470930SIngo Molnar {
20086470930SIngo Molnar 	struct symbol *pos;
201fcf1203aSArnaldo Carvalho de Melo 	struct rb_node *next = rb_first(self);
20286470930SIngo Molnar 
20386470930SIngo Molnar 	while (next) {
20486470930SIngo Molnar 		pos = rb_entry(next, struct symbol, rb_node);
20586470930SIngo Molnar 		next = rb_next(&pos->rb_node);
206fcf1203aSArnaldo Carvalho de Melo 		rb_erase(&pos->rb_node, self);
20700a192b3SArnaldo Carvalho de Melo 		symbol__delete(pos);
20886470930SIngo Molnar 	}
20986470930SIngo Molnar }
21086470930SIngo Molnar 
21186470930SIngo Molnar void dso__delete(struct dso *self)
21286470930SIngo Molnar {
2136a4694a4SArnaldo Carvalho de Melo 	int i;
2146a4694a4SArnaldo Carvalho de Melo 	for (i = 0; i < MAP__NR_TYPES; ++i)
2156a4694a4SArnaldo Carvalho de Melo 		symbols__delete(&self->symbols[i]);
216439d473bSArnaldo Carvalho de Melo 	if (self->long_name != self->name)
217439d473bSArnaldo Carvalho de Melo 		free(self->long_name);
21886470930SIngo Molnar 	free(self);
21986470930SIngo Molnar }
22086470930SIngo Molnar 
2218d06367fSArnaldo Carvalho de Melo void dso__set_build_id(struct dso *self, void *build_id)
2228d06367fSArnaldo Carvalho de Melo {
2238d06367fSArnaldo Carvalho de Melo 	memcpy(self->build_id, build_id, sizeof(self->build_id));
2248d06367fSArnaldo Carvalho de Melo 	self->has_build_id = 1;
2258d06367fSArnaldo Carvalho de Melo }
2268d06367fSArnaldo Carvalho de Melo 
227fcf1203aSArnaldo Carvalho de Melo static void symbols__insert(struct rb_root *self, struct symbol *sym)
22886470930SIngo Molnar {
229fcf1203aSArnaldo Carvalho de Melo 	struct rb_node **p = &self->rb_node;
23086470930SIngo Molnar 	struct rb_node *parent = NULL;
2319cffa8d5SPaul Mackerras 	const u64 ip = sym->start;
23286470930SIngo Molnar 	struct symbol *s;
23386470930SIngo Molnar 
23486470930SIngo Molnar 	while (*p != NULL) {
23586470930SIngo Molnar 		parent = *p;
23686470930SIngo Molnar 		s = rb_entry(parent, struct symbol, rb_node);
23786470930SIngo Molnar 		if (ip < s->start)
23886470930SIngo Molnar 			p = &(*p)->rb_left;
23986470930SIngo Molnar 		else
24086470930SIngo Molnar 			p = &(*p)->rb_right;
24186470930SIngo Molnar 	}
24286470930SIngo Molnar 	rb_link_node(&sym->rb_node, parent, p);
243fcf1203aSArnaldo Carvalho de Melo 	rb_insert_color(&sym->rb_node, self);
24486470930SIngo Molnar }
24586470930SIngo Molnar 
246fcf1203aSArnaldo Carvalho de Melo static struct symbol *symbols__find(struct rb_root *self, u64 ip)
24786470930SIngo Molnar {
24886470930SIngo Molnar 	struct rb_node *n;
24986470930SIngo Molnar 
25086470930SIngo Molnar 	if (self == NULL)
25186470930SIngo Molnar 		return NULL;
25286470930SIngo Molnar 
253fcf1203aSArnaldo Carvalho de Melo 	n = self->rb_node;
25486470930SIngo Molnar 
25586470930SIngo Molnar 	while (n) {
25686470930SIngo Molnar 		struct symbol *s = rb_entry(n, struct symbol, rb_node);
25786470930SIngo Molnar 
25886470930SIngo Molnar 		if (ip < s->start)
25986470930SIngo Molnar 			n = n->rb_left;
26086470930SIngo Molnar 		else if (ip > s->end)
26186470930SIngo Molnar 			n = n->rb_right;
26286470930SIngo Molnar 		else
26386470930SIngo Molnar 			return s;
26486470930SIngo Molnar 	}
26586470930SIngo Molnar 
26686470930SIngo Molnar 	return NULL;
26786470930SIngo Molnar }
26886470930SIngo Molnar 
26979406cd7SArnaldo Carvalho de Melo struct symbol_name_rb_node {
27079406cd7SArnaldo Carvalho de Melo 	struct rb_node	rb_node;
27179406cd7SArnaldo Carvalho de Melo 	struct symbol	sym;
27279406cd7SArnaldo Carvalho de Melo };
27379406cd7SArnaldo Carvalho de Melo 
27479406cd7SArnaldo Carvalho de Melo static void symbols__insert_by_name(struct rb_root *self, struct symbol *sym)
27579406cd7SArnaldo Carvalho de Melo {
27679406cd7SArnaldo Carvalho de Melo 	struct rb_node **p = &self->rb_node;
27779406cd7SArnaldo Carvalho de Melo 	struct rb_node *parent = NULL;
27879406cd7SArnaldo Carvalho de Melo 	struct symbol_name_rb_node *symn = ((void *)sym) - sizeof(*parent), *s;
27979406cd7SArnaldo Carvalho de Melo 
28079406cd7SArnaldo Carvalho de Melo 	while (*p != NULL) {
28179406cd7SArnaldo Carvalho de Melo 		parent = *p;
28279406cd7SArnaldo Carvalho de Melo 		s = rb_entry(parent, struct symbol_name_rb_node, rb_node);
28379406cd7SArnaldo Carvalho de Melo 		if (strcmp(sym->name, s->sym.name) < 0)
28479406cd7SArnaldo Carvalho de Melo 			p = &(*p)->rb_left;
28579406cd7SArnaldo Carvalho de Melo 		else
28679406cd7SArnaldo Carvalho de Melo 			p = &(*p)->rb_right;
28779406cd7SArnaldo Carvalho de Melo 	}
28879406cd7SArnaldo Carvalho de Melo 	rb_link_node(&symn->rb_node, parent, p);
28979406cd7SArnaldo Carvalho de Melo 	rb_insert_color(&symn->rb_node, self);
29079406cd7SArnaldo Carvalho de Melo }
29179406cd7SArnaldo Carvalho de Melo 
29279406cd7SArnaldo Carvalho de Melo static void symbols__sort_by_name(struct rb_root *self, struct rb_root *source)
29379406cd7SArnaldo Carvalho de Melo {
29479406cd7SArnaldo Carvalho de Melo 	struct rb_node *nd;
29579406cd7SArnaldo Carvalho de Melo 
29679406cd7SArnaldo Carvalho de Melo 	for (nd = rb_first(source); nd; nd = rb_next(nd)) {
29779406cd7SArnaldo Carvalho de Melo 		struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
29879406cd7SArnaldo Carvalho de Melo 		symbols__insert_by_name(self, pos);
29979406cd7SArnaldo Carvalho de Melo 	}
30079406cd7SArnaldo Carvalho de Melo }
30179406cd7SArnaldo Carvalho de Melo 
30279406cd7SArnaldo Carvalho de Melo static struct symbol *symbols__find_by_name(struct rb_root *self, const char *name)
30379406cd7SArnaldo Carvalho de Melo {
30479406cd7SArnaldo Carvalho de Melo 	struct rb_node *n;
30579406cd7SArnaldo Carvalho de Melo 
30679406cd7SArnaldo Carvalho de Melo 	if (self == NULL)
30779406cd7SArnaldo Carvalho de Melo 		return NULL;
30879406cd7SArnaldo Carvalho de Melo 
30979406cd7SArnaldo Carvalho de Melo 	n = self->rb_node;
31079406cd7SArnaldo Carvalho de Melo 
31179406cd7SArnaldo Carvalho de Melo 	while (n) {
31279406cd7SArnaldo Carvalho de Melo 		struct symbol_name_rb_node *s;
31379406cd7SArnaldo Carvalho de Melo 		int cmp;
31479406cd7SArnaldo Carvalho de Melo 
31579406cd7SArnaldo Carvalho de Melo 		s = rb_entry(n, struct symbol_name_rb_node, rb_node);
31679406cd7SArnaldo Carvalho de Melo 		cmp = strcmp(name, s->sym.name);
31779406cd7SArnaldo Carvalho de Melo 
31879406cd7SArnaldo Carvalho de Melo 		if (cmp < 0)
31979406cd7SArnaldo Carvalho de Melo 			n = n->rb_left;
32079406cd7SArnaldo Carvalho de Melo 		else if (cmp > 0)
32179406cd7SArnaldo Carvalho de Melo 			n = n->rb_right;
32279406cd7SArnaldo Carvalho de Melo 		else
32379406cd7SArnaldo Carvalho de Melo 			return &s->sym;
32479406cd7SArnaldo Carvalho de Melo 	}
32579406cd7SArnaldo Carvalho de Melo 
32679406cd7SArnaldo Carvalho de Melo 	return NULL;
32779406cd7SArnaldo Carvalho de Melo }
32879406cd7SArnaldo Carvalho de Melo 
32979406cd7SArnaldo Carvalho de Melo struct symbol *dso__find_symbol(struct dso *self,
33079406cd7SArnaldo Carvalho de Melo 				enum map_type type, u64 addr)
331fcf1203aSArnaldo Carvalho de Melo {
3326a4694a4SArnaldo Carvalho de Melo 	return symbols__find(&self->symbols[type], addr);
333fcf1203aSArnaldo Carvalho de Melo }
334fcf1203aSArnaldo Carvalho de Melo 
33579406cd7SArnaldo Carvalho de Melo struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type,
33679406cd7SArnaldo Carvalho de Melo 					const char *name)
33779406cd7SArnaldo Carvalho de Melo {
33879406cd7SArnaldo Carvalho de Melo 	return symbols__find_by_name(&self->symbol_names[type], name);
33979406cd7SArnaldo Carvalho de Melo }
34079406cd7SArnaldo Carvalho de Melo 
34179406cd7SArnaldo Carvalho de Melo void dso__sort_by_name(struct dso *self, enum map_type type)
34279406cd7SArnaldo Carvalho de Melo {
34379406cd7SArnaldo Carvalho de Melo 	dso__set_sorted_by_name(self, type);
34479406cd7SArnaldo Carvalho de Melo 	return symbols__sort_by_name(&self->symbol_names[type],
34579406cd7SArnaldo Carvalho de Melo 				     &self->symbols[type]);
34679406cd7SArnaldo Carvalho de Melo }
34779406cd7SArnaldo Carvalho de Melo 
348ef12a141SArnaldo Carvalho de Melo int build_id__sprintf(const u8 *self, int len, char *bf)
3498d06367fSArnaldo Carvalho de Melo {
3508d06367fSArnaldo Carvalho de Melo 	char *bid = bf;
351ef12a141SArnaldo Carvalho de Melo 	const u8 *raw = self;
3528d06367fSArnaldo Carvalho de Melo 	int i;
3538d06367fSArnaldo Carvalho de Melo 
3548d06367fSArnaldo Carvalho de Melo 	for (i = 0; i < len; ++i) {
3558d06367fSArnaldo Carvalho de Melo 		sprintf(bid, "%02x", *raw);
3568d06367fSArnaldo Carvalho de Melo 		++raw;
3578d06367fSArnaldo Carvalho de Melo 		bid += 2;
3588d06367fSArnaldo Carvalho de Melo 	}
3598d06367fSArnaldo Carvalho de Melo 
3608d06367fSArnaldo Carvalho de Melo 	return raw - self;
3618d06367fSArnaldo Carvalho de Melo }
3628d06367fSArnaldo Carvalho de Melo 
3639e03eb2dSArnaldo Carvalho de Melo size_t dso__fprintf_buildid(struct dso *self, FILE *fp)
36486470930SIngo Molnar {
3658d06367fSArnaldo Carvalho de Melo 	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
3668d06367fSArnaldo Carvalho de Melo 
3678d06367fSArnaldo Carvalho de Melo 	build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id);
3689e03eb2dSArnaldo Carvalho de Melo 	return fprintf(fp, "%s", sbuild_id);
3699e03eb2dSArnaldo Carvalho de Melo }
3709e03eb2dSArnaldo Carvalho de Melo 
37195011c60SArnaldo Carvalho de Melo size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
3729e03eb2dSArnaldo Carvalho de Melo {
3739e03eb2dSArnaldo Carvalho de Melo 	struct rb_node *nd;
3749e03eb2dSArnaldo Carvalho de Melo 	size_t ret = fprintf(fp, "dso: %s (", self->short_name);
3759e03eb2dSArnaldo Carvalho de Melo 
3769e03eb2dSArnaldo Carvalho de Melo 	ret += dso__fprintf_buildid(self, fp);
3776a4694a4SArnaldo Carvalho de Melo 	ret += fprintf(fp, ")\n");
37895011c60SArnaldo Carvalho de Melo 	for (nd = rb_first(&self->symbols[type]); nd; nd = rb_next(nd)) {
37986470930SIngo Molnar 		struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
38086470930SIngo Molnar 		ret += symbol__fprintf(pos, fp);
38186470930SIngo Molnar 	}
38286470930SIngo Molnar 
38386470930SIngo Molnar 	return ret;
38486470930SIngo Molnar }
38586470930SIngo Molnar 
3869e201442SArnaldo Carvalho de Melo int kallsyms__parse(const char *filename, void *arg,
3879e201442SArnaldo Carvalho de Melo 		    int (*process_symbol)(void *arg, const char *name,
388682b335aSArnaldo Carvalho de Melo 						     char type, u64 start))
38986470930SIngo Molnar {
39086470930SIngo Molnar 	char *line = NULL;
39186470930SIngo Molnar 	size_t n;
392682b335aSArnaldo Carvalho de Melo 	int err = 0;
3939e201442SArnaldo Carvalho de Melo 	FILE *file = fopen(filename, "r");
39486470930SIngo Molnar 
39586470930SIngo Molnar 	if (file == NULL)
39686470930SIngo Molnar 		goto out_failure;
39786470930SIngo Molnar 
39886470930SIngo Molnar 	while (!feof(file)) {
3999cffa8d5SPaul Mackerras 		u64 start;
40086470930SIngo Molnar 		int line_len, len;
40186470930SIngo Molnar 		char symbol_type;
4022e538c4aSArnaldo Carvalho de Melo 		char *symbol_name;
40386470930SIngo Molnar 
40486470930SIngo Molnar 		line_len = getline(&line, &n, file);
40586470930SIngo Molnar 		if (line_len < 0)
40686470930SIngo Molnar 			break;
40786470930SIngo Molnar 
40886470930SIngo Molnar 		if (!line)
40986470930SIngo Molnar 			goto out_failure;
41086470930SIngo Molnar 
41186470930SIngo Molnar 		line[--line_len] = '\0'; /* \n */
41286470930SIngo Molnar 
41386470930SIngo Molnar 		len = hex2u64(line, &start);
41486470930SIngo Molnar 
41586470930SIngo Molnar 		len++;
41686470930SIngo Molnar 		if (len + 2 >= line_len)
41786470930SIngo Molnar 			continue;
41886470930SIngo Molnar 
41986470930SIngo Molnar 		symbol_type = toupper(line[len]);
420af427bf5SArnaldo Carvalho de Melo 		symbol_name = line + len + 2;
421682b335aSArnaldo Carvalho de Melo 
422682b335aSArnaldo Carvalho de Melo 		err = process_symbol(arg, symbol_name, symbol_type, start);
423682b335aSArnaldo Carvalho de Melo 		if (err)
424682b335aSArnaldo Carvalho de Melo 			break;
425682b335aSArnaldo Carvalho de Melo 	}
426682b335aSArnaldo Carvalho de Melo 
427682b335aSArnaldo Carvalho de Melo 	free(line);
428682b335aSArnaldo Carvalho de Melo 	fclose(file);
429682b335aSArnaldo Carvalho de Melo 	return err;
430682b335aSArnaldo Carvalho de Melo 
431682b335aSArnaldo Carvalho de Melo out_failure:
432682b335aSArnaldo Carvalho de Melo 	return -1;
433682b335aSArnaldo Carvalho de Melo }
434682b335aSArnaldo Carvalho de Melo 
435682b335aSArnaldo Carvalho de Melo struct process_kallsyms_args {
436682b335aSArnaldo Carvalho de Melo 	struct map *map;
437682b335aSArnaldo Carvalho de Melo 	struct dso *dso;
438682b335aSArnaldo Carvalho de Melo };
439682b335aSArnaldo Carvalho de Melo 
440682b335aSArnaldo Carvalho de Melo static int map__process_kallsym_symbol(void *arg, const char *name,
441682b335aSArnaldo Carvalho de Melo 				       char type, u64 start)
442682b335aSArnaldo Carvalho de Melo {
443682b335aSArnaldo Carvalho de Melo 	struct symbol *sym;
444682b335aSArnaldo Carvalho de Melo 	struct process_kallsyms_args *a = arg;
445682b335aSArnaldo Carvalho de Melo 	struct rb_root *root = &a->dso->symbols[a->map->type];
446682b335aSArnaldo Carvalho de Melo 
447682b335aSArnaldo Carvalho de Melo 	if (!symbol_type__is_a(type, a->map->type))
448682b335aSArnaldo Carvalho de Melo 		return 0;
449682b335aSArnaldo Carvalho de Melo 
4502e538c4aSArnaldo Carvalho de Melo 	/*
4512e538c4aSArnaldo Carvalho de Melo 	 * Will fix up the end later, when we have all symbols sorted.
4522e538c4aSArnaldo Carvalho de Melo 	 */
453682b335aSArnaldo Carvalho de Melo 	sym = symbol__new(start, 0, name);
454af427bf5SArnaldo Carvalho de Melo 
4552e538c4aSArnaldo Carvalho de Melo 	if (sym == NULL)
456682b335aSArnaldo Carvalho de Melo 		return -ENOMEM;
45782164161SArnaldo Carvalho de Melo 	/*
45882164161SArnaldo Carvalho de Melo 	 * We will pass the symbols to the filter later, in
4594e06255fSArnaldo Carvalho de Melo 	 * map__split_kallsyms, when we have split the maps per module
46082164161SArnaldo Carvalho de Melo 	 */
4614e06255fSArnaldo Carvalho de Melo 	symbols__insert(root, sym);
462682b335aSArnaldo Carvalho de Melo 	return 0;
4632e538c4aSArnaldo Carvalho de Melo }
4642e538c4aSArnaldo Carvalho de Melo 
465682b335aSArnaldo Carvalho de Melo /*
466682b335aSArnaldo Carvalho de Melo  * Loads the function entries in /proc/kallsyms into kernel_map->dso,
467682b335aSArnaldo Carvalho de Melo  * so that we can in the next step set the symbol ->end address and then
468682b335aSArnaldo Carvalho de Melo  * call kernel_maps__split_kallsyms.
469682b335aSArnaldo Carvalho de Melo  */
4709e201442SArnaldo Carvalho de Melo static int dso__load_all_kallsyms(struct dso *self, const char *filename,
4719e201442SArnaldo Carvalho de Melo 				  struct map *map)
472682b335aSArnaldo Carvalho de Melo {
473682b335aSArnaldo Carvalho de Melo 	struct process_kallsyms_args args = { .map = map, .dso = self, };
4749e201442SArnaldo Carvalho de Melo 	return kallsyms__parse(filename, &args, map__process_kallsym_symbol);
4752e538c4aSArnaldo Carvalho de Melo }
4762e538c4aSArnaldo Carvalho de Melo 
4772e538c4aSArnaldo Carvalho de Melo /*
4782e538c4aSArnaldo Carvalho de Melo  * Split the symbols into maps, making sure there are no overlaps, i.e. the
4792e538c4aSArnaldo Carvalho de Melo  * kernel range is broken in several maps, named [kernel].N, as we don't have
4802e538c4aSArnaldo Carvalho de Melo  * the original ELF section names vmlinux have.
4812e538c4aSArnaldo Carvalho de Melo  */
4829958e1f0SArnaldo Carvalho de Melo static int dso__split_kallsyms(struct dso *self, struct map *map,
4834aa65636SArnaldo Carvalho de Melo 			       struct perf_session *session, symbol_filter_t filter)
4842e538c4aSArnaldo Carvalho de Melo {
4854e06255fSArnaldo Carvalho de Melo 	struct map *curr_map = map;
4862e538c4aSArnaldo Carvalho de Melo 	struct symbol *pos;
4872e538c4aSArnaldo Carvalho de Melo 	int count = 0;
4884e06255fSArnaldo Carvalho de Melo 	struct rb_root *root = &self->symbols[map->type];
4894e06255fSArnaldo Carvalho de Melo 	struct rb_node *next = rb_first(root);
4902e538c4aSArnaldo Carvalho de Melo 	int kernel_range = 0;
4912e538c4aSArnaldo Carvalho de Melo 
4922e538c4aSArnaldo Carvalho de Melo 	while (next) {
4932e538c4aSArnaldo Carvalho de Melo 		char *module;
4942e538c4aSArnaldo Carvalho de Melo 
4952e538c4aSArnaldo Carvalho de Melo 		pos = rb_entry(next, struct symbol, rb_node);
4962e538c4aSArnaldo Carvalho de Melo 		next = rb_next(&pos->rb_node);
4972e538c4aSArnaldo Carvalho de Melo 
4982e538c4aSArnaldo Carvalho de Melo 		module = strchr(pos->name, '\t');
4992e538c4aSArnaldo Carvalho de Melo 		if (module) {
50075be6cf4SArnaldo Carvalho de Melo 			if (!symbol_conf.use_modules)
5011de8e245SArnaldo Carvalho de Melo 				goto discard_symbol;
5021de8e245SArnaldo Carvalho de Melo 
5032e538c4aSArnaldo Carvalho de Melo 			*module++ = '\0';
5042e538c4aSArnaldo Carvalho de Melo 
505b7cece76SArnaldo Carvalho de Melo 			if (strcmp(curr_map->dso->short_name, module)) {
5064aa65636SArnaldo Carvalho de Melo 				curr_map = map_groups__find_by_name(&session->kmaps, map->type, module);
5074e06255fSArnaldo Carvalho de Melo 				if (curr_map == NULL) {
50895011c60SArnaldo Carvalho de Melo 					pr_debug("/proc/{kallsyms,modules} "
509b7cece76SArnaldo Carvalho de Melo 					         "inconsistency while looking "
510b7cece76SArnaldo Carvalho de Melo 						 "for \"%s\" module!\n", module);
511af427bf5SArnaldo Carvalho de Melo 					return -1;
512af427bf5SArnaldo Carvalho de Melo 				}
513b7cece76SArnaldo Carvalho de Melo 
514b7cece76SArnaldo Carvalho de Melo 				if (curr_map->dso->loaded)
515b7cece76SArnaldo Carvalho de Melo 					goto discard_symbol;
516af427bf5SArnaldo Carvalho de Melo 			}
51786470930SIngo Molnar 			/*
5182e538c4aSArnaldo Carvalho de Melo 			 * So that we look just like we get from .ko files,
5192e538c4aSArnaldo Carvalho de Melo 			 * i.e. not prelinked, relative to map->start.
52086470930SIngo Molnar 			 */
5214e06255fSArnaldo Carvalho de Melo 			pos->start = curr_map->map_ip(curr_map, pos->start);
5224e06255fSArnaldo Carvalho de Melo 			pos->end   = curr_map->map_ip(curr_map, pos->end);
5234e06255fSArnaldo Carvalho de Melo 		} else if (curr_map != map) {
5242e538c4aSArnaldo Carvalho de Melo 			char dso_name[PATH_MAX];
5252e538c4aSArnaldo Carvalho de Melo 			struct dso *dso;
52686470930SIngo Molnar 
5272e538c4aSArnaldo Carvalho de Melo 			snprintf(dso_name, sizeof(dso_name), "[kernel].%d",
5282e538c4aSArnaldo Carvalho de Melo 				 kernel_range++);
52986470930SIngo Molnar 
53000a192b3SArnaldo Carvalho de Melo 			dso = dso__new(dso_name);
5312e538c4aSArnaldo Carvalho de Melo 			if (dso == NULL)
5322e538c4aSArnaldo Carvalho de Melo 				return -1;
5332e538c4aSArnaldo Carvalho de Melo 
5344e06255fSArnaldo Carvalho de Melo 			curr_map = map__new2(pos->start, dso, map->type);
5352e538c4aSArnaldo Carvalho de Melo 			if (map == NULL) {
5362e538c4aSArnaldo Carvalho de Melo 				dso__delete(dso);
5372e538c4aSArnaldo Carvalho de Melo 				return -1;
5382e538c4aSArnaldo Carvalho de Melo 			}
5392e538c4aSArnaldo Carvalho de Melo 
5404e06255fSArnaldo Carvalho de Melo 			curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
5414aa65636SArnaldo Carvalho de Melo 			map_groups__insert(&session->kmaps, curr_map);
5422e538c4aSArnaldo Carvalho de Melo 			++kernel_range;
5432e538c4aSArnaldo Carvalho de Melo 		}
5442e538c4aSArnaldo Carvalho de Melo 
5454e06255fSArnaldo Carvalho de Melo 		if (filter && filter(curr_map, pos)) {
5461de8e245SArnaldo Carvalho de Melo discard_symbol:		rb_erase(&pos->rb_node, root);
54700a192b3SArnaldo Carvalho de Melo 			symbol__delete(pos);
5482e538c4aSArnaldo Carvalho de Melo 		} else {
5494e06255fSArnaldo Carvalho de Melo 			if (curr_map != map) {
5504e06255fSArnaldo Carvalho de Melo 				rb_erase(&pos->rb_node, root);
5514e06255fSArnaldo Carvalho de Melo 				symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
5522e538c4aSArnaldo Carvalho de Melo 			}
5539974f496SMike Galbraith 			count++;
5549974f496SMike Galbraith 		}
55586470930SIngo Molnar 	}
55686470930SIngo Molnar 
5579974f496SMike Galbraith 	return count;
55886470930SIngo Molnar }
55986470930SIngo Molnar 
5602e538c4aSArnaldo Carvalho de Melo 
5619e201442SArnaldo Carvalho de Melo static int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map,
5624aa65636SArnaldo Carvalho de Melo 			      struct perf_session *session, symbol_filter_t filter)
5632e538c4aSArnaldo Carvalho de Melo {
5649e201442SArnaldo Carvalho de Melo 	if (dso__load_all_kallsyms(self, filename, map) < 0)
5652e538c4aSArnaldo Carvalho de Melo 		return -1;
5662e538c4aSArnaldo Carvalho de Melo 
5674e06255fSArnaldo Carvalho de Melo 	symbols__fixup_end(&self->symbols[map->type]);
5684e06255fSArnaldo Carvalho de Melo 	self->origin = DSO__ORIG_KERNEL;
5692e538c4aSArnaldo Carvalho de Melo 
5704aa65636SArnaldo Carvalho de Melo 	return dso__split_kallsyms(self, map, session, filter);
571af427bf5SArnaldo Carvalho de Melo }
572af427bf5SArnaldo Carvalho de Melo 
573439d473bSArnaldo Carvalho de Melo static int dso__load_perf_map(struct dso *self, struct map *map,
5746beba7adSArnaldo Carvalho de Melo 			      symbol_filter_t filter)
57580d496beSPekka Enberg {
57680d496beSPekka Enberg 	char *line = NULL;
57780d496beSPekka Enberg 	size_t n;
57880d496beSPekka Enberg 	FILE *file;
57980d496beSPekka Enberg 	int nr_syms = 0;
58080d496beSPekka Enberg 
581439d473bSArnaldo Carvalho de Melo 	file = fopen(self->long_name, "r");
58280d496beSPekka Enberg 	if (file == NULL)
58380d496beSPekka Enberg 		goto out_failure;
58480d496beSPekka Enberg 
58580d496beSPekka Enberg 	while (!feof(file)) {
5869cffa8d5SPaul Mackerras 		u64 start, size;
58780d496beSPekka Enberg 		struct symbol *sym;
58880d496beSPekka Enberg 		int line_len, len;
58980d496beSPekka Enberg 
59080d496beSPekka Enberg 		line_len = getline(&line, &n, file);
59180d496beSPekka Enberg 		if (line_len < 0)
59280d496beSPekka Enberg 			break;
59380d496beSPekka Enberg 
59480d496beSPekka Enberg 		if (!line)
59580d496beSPekka Enberg 			goto out_failure;
59680d496beSPekka Enberg 
59780d496beSPekka Enberg 		line[--line_len] = '\0'; /* \n */
59880d496beSPekka Enberg 
59980d496beSPekka Enberg 		len = hex2u64(line, &start);
60080d496beSPekka Enberg 
60180d496beSPekka Enberg 		len++;
60280d496beSPekka Enberg 		if (len + 2 >= line_len)
60380d496beSPekka Enberg 			continue;
60480d496beSPekka Enberg 
60580d496beSPekka Enberg 		len += hex2u64(line + len, &size);
60680d496beSPekka Enberg 
60780d496beSPekka Enberg 		len++;
60880d496beSPekka Enberg 		if (len + 2 >= line_len)
60980d496beSPekka Enberg 			continue;
61080d496beSPekka Enberg 
61100a192b3SArnaldo Carvalho de Melo 		sym = symbol__new(start, size, line + len);
61280d496beSPekka Enberg 
61380d496beSPekka Enberg 		if (sym == NULL)
61480d496beSPekka Enberg 			goto out_delete_line;
61580d496beSPekka Enberg 
616439d473bSArnaldo Carvalho de Melo 		if (filter && filter(map, sym))
61700a192b3SArnaldo Carvalho de Melo 			symbol__delete(sym);
61880d496beSPekka Enberg 		else {
6196a4694a4SArnaldo Carvalho de Melo 			symbols__insert(&self->symbols[map->type], sym);
62080d496beSPekka Enberg 			nr_syms++;
62180d496beSPekka Enberg 		}
62280d496beSPekka Enberg 	}
62380d496beSPekka Enberg 
62480d496beSPekka Enberg 	free(line);
62580d496beSPekka Enberg 	fclose(file);
62680d496beSPekka Enberg 
62780d496beSPekka Enberg 	return nr_syms;
62880d496beSPekka Enberg 
62980d496beSPekka Enberg out_delete_line:
63080d496beSPekka Enberg 	free(line);
63180d496beSPekka Enberg out_failure:
63280d496beSPekka Enberg 	return -1;
63380d496beSPekka Enberg }
63480d496beSPekka Enberg 
63586470930SIngo Molnar /**
63686470930SIngo Molnar  * elf_symtab__for_each_symbol - iterate thru all the symbols
63786470930SIngo Molnar  *
63886470930SIngo Molnar  * @self: struct elf_symtab instance to iterate
63983a0944fSIngo Molnar  * @idx: uint32_t idx
64086470930SIngo Molnar  * @sym: GElf_Sym iterator
64186470930SIngo Molnar  */
64283a0944fSIngo Molnar #define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \
64383a0944fSIngo Molnar 	for (idx = 0, gelf_getsym(syms, idx, &sym);\
64483a0944fSIngo Molnar 	     idx < nr_syms; \
64583a0944fSIngo Molnar 	     idx++, gelf_getsym(syms, idx, &sym))
64686470930SIngo Molnar 
64786470930SIngo Molnar static inline uint8_t elf_sym__type(const GElf_Sym *sym)
64886470930SIngo Molnar {
64986470930SIngo Molnar 	return GELF_ST_TYPE(sym->st_info);
65086470930SIngo Molnar }
65186470930SIngo Molnar 
65286470930SIngo Molnar static inline int elf_sym__is_function(const GElf_Sym *sym)
65386470930SIngo Molnar {
65486470930SIngo Molnar 	return elf_sym__type(sym) == STT_FUNC &&
65586470930SIngo Molnar 	       sym->st_name != 0 &&
65681833130SArnaldo Carvalho de Melo 	       sym->st_shndx != SHN_UNDEF;
65786470930SIngo Molnar }
65886470930SIngo Molnar 
659f1dfa0b1SArnaldo Carvalho de Melo static inline bool elf_sym__is_object(const GElf_Sym *sym)
660f1dfa0b1SArnaldo Carvalho de Melo {
661f1dfa0b1SArnaldo Carvalho de Melo 	return elf_sym__type(sym) == STT_OBJECT &&
662f1dfa0b1SArnaldo Carvalho de Melo 		sym->st_name != 0 &&
663f1dfa0b1SArnaldo Carvalho de Melo 		sym->st_shndx != SHN_UNDEF;
664f1dfa0b1SArnaldo Carvalho de Melo }
665f1dfa0b1SArnaldo Carvalho de Melo 
6666cfcc53eSMike Galbraith static inline int elf_sym__is_label(const GElf_Sym *sym)
6676cfcc53eSMike Galbraith {
6686cfcc53eSMike Galbraith 	return elf_sym__type(sym) == STT_NOTYPE &&
6696cfcc53eSMike Galbraith 		sym->st_name != 0 &&
6706cfcc53eSMike Galbraith 		sym->st_shndx != SHN_UNDEF &&
6716cfcc53eSMike Galbraith 		sym->st_shndx != SHN_ABS;
6726cfcc53eSMike Galbraith }
6736cfcc53eSMike Galbraith 
6746cfcc53eSMike Galbraith static inline const char *elf_sec__name(const GElf_Shdr *shdr,
6756cfcc53eSMike Galbraith 					const Elf_Data *secstrs)
6766cfcc53eSMike Galbraith {
6776cfcc53eSMike Galbraith 	return secstrs->d_buf + shdr->sh_name;
6786cfcc53eSMike Galbraith }
6796cfcc53eSMike Galbraith 
6806cfcc53eSMike Galbraith static inline int elf_sec__is_text(const GElf_Shdr *shdr,
6816cfcc53eSMike Galbraith 					const Elf_Data *secstrs)
6826cfcc53eSMike Galbraith {
6836cfcc53eSMike Galbraith 	return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
6846cfcc53eSMike Galbraith }
6856cfcc53eSMike Galbraith 
686f1dfa0b1SArnaldo Carvalho de Melo static inline bool elf_sec__is_data(const GElf_Shdr *shdr,
687f1dfa0b1SArnaldo Carvalho de Melo 				    const Elf_Data *secstrs)
688f1dfa0b1SArnaldo Carvalho de Melo {
689f1dfa0b1SArnaldo Carvalho de Melo 	return strstr(elf_sec__name(shdr, secstrs), "data") != NULL;
690f1dfa0b1SArnaldo Carvalho de Melo }
691f1dfa0b1SArnaldo Carvalho de Melo 
69286470930SIngo Molnar static inline const char *elf_sym__name(const GElf_Sym *sym,
69386470930SIngo Molnar 					const Elf_Data *symstrs)
69486470930SIngo Molnar {
69586470930SIngo Molnar 	return symstrs->d_buf + sym->st_name;
69686470930SIngo Molnar }
69786470930SIngo Molnar 
69886470930SIngo Molnar static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
69986470930SIngo Molnar 				    GElf_Shdr *shp, const char *name,
70083a0944fSIngo Molnar 				    size_t *idx)
70186470930SIngo Molnar {
70286470930SIngo Molnar 	Elf_Scn *sec = NULL;
70386470930SIngo Molnar 	size_t cnt = 1;
70486470930SIngo Molnar 
70586470930SIngo Molnar 	while ((sec = elf_nextscn(elf, sec)) != NULL) {
70686470930SIngo Molnar 		char *str;
70786470930SIngo Molnar 
70886470930SIngo Molnar 		gelf_getshdr(sec, shp);
70986470930SIngo Molnar 		str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
71086470930SIngo Molnar 		if (!strcmp(name, str)) {
71183a0944fSIngo Molnar 			if (idx)
71283a0944fSIngo Molnar 				*idx = cnt;
71386470930SIngo Molnar 			break;
71486470930SIngo Molnar 		}
71586470930SIngo Molnar 		++cnt;
71686470930SIngo Molnar 	}
71786470930SIngo Molnar 
71886470930SIngo Molnar 	return sec;
71986470930SIngo Molnar }
72086470930SIngo Molnar 
72186470930SIngo Molnar #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
72286470930SIngo Molnar 	for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
72386470930SIngo Molnar 	     idx < nr_entries; \
72486470930SIngo Molnar 	     ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))
72586470930SIngo Molnar 
72686470930SIngo Molnar #define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
72786470930SIngo Molnar 	for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
72886470930SIngo Molnar 	     idx < nr_entries; \
72986470930SIngo Molnar 	     ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
73086470930SIngo Molnar 
731a25e46c4SArnaldo Carvalho de Melo /*
732a25e46c4SArnaldo Carvalho de Melo  * We need to check if we have a .dynsym, so that we can handle the
733a25e46c4SArnaldo Carvalho de Melo  * .plt, synthesizing its symbols, that aren't on the symtabs (be it
734a25e46c4SArnaldo Carvalho de Melo  * .dynsym or .symtab).
735a25e46c4SArnaldo Carvalho de Melo  * And always look at the original dso, not at debuginfo packages, that
736a25e46c4SArnaldo Carvalho de Melo  * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
737a25e46c4SArnaldo Carvalho de Melo  */
73882164161SArnaldo Carvalho de Melo static int dso__synthesize_plt_symbols(struct  dso *self, struct map *map,
73982164161SArnaldo Carvalho de Melo 				       symbol_filter_t filter)
74086470930SIngo Molnar {
74186470930SIngo Molnar 	uint32_t nr_rel_entries, idx;
74286470930SIngo Molnar 	GElf_Sym sym;
7439cffa8d5SPaul Mackerras 	u64 plt_offset;
74486470930SIngo Molnar 	GElf_Shdr shdr_plt;
74586470930SIngo Molnar 	struct symbol *f;
746a25e46c4SArnaldo Carvalho de Melo 	GElf_Shdr shdr_rel_plt, shdr_dynsym;
74786470930SIngo Molnar 	Elf_Data *reldata, *syms, *symstrs;
748a25e46c4SArnaldo Carvalho de Melo 	Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
749a25e46c4SArnaldo Carvalho de Melo 	size_t dynsym_idx;
750a25e46c4SArnaldo Carvalho de Melo 	GElf_Ehdr ehdr;
75186470930SIngo Molnar 	char sympltname[1024];
752a25e46c4SArnaldo Carvalho de Melo 	Elf *elf;
753a25e46c4SArnaldo Carvalho de Melo 	int nr = 0, symidx, fd, err = 0;
75486470930SIngo Molnar 
755439d473bSArnaldo Carvalho de Melo 	fd = open(self->long_name, O_RDONLY);
756a25e46c4SArnaldo Carvalho de Melo 	if (fd < 0)
757a25e46c4SArnaldo Carvalho de Melo 		goto out;
758a25e46c4SArnaldo Carvalho de Melo 
75984087126SMarti Raudsepp 	elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
760a25e46c4SArnaldo Carvalho de Melo 	if (elf == NULL)
761a25e46c4SArnaldo Carvalho de Melo 		goto out_close;
762a25e46c4SArnaldo Carvalho de Melo 
763a25e46c4SArnaldo Carvalho de Melo 	if (gelf_getehdr(elf, &ehdr) == NULL)
764a25e46c4SArnaldo Carvalho de Melo 		goto out_elf_end;
765a25e46c4SArnaldo Carvalho de Melo 
766a25e46c4SArnaldo Carvalho de Melo 	scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
767a25e46c4SArnaldo Carvalho de Melo 					 ".dynsym", &dynsym_idx);
768a25e46c4SArnaldo Carvalho de Melo 	if (scn_dynsym == NULL)
769a25e46c4SArnaldo Carvalho de Melo 		goto out_elf_end;
770a25e46c4SArnaldo Carvalho de Melo 
771a25e46c4SArnaldo Carvalho de Melo 	scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
77286470930SIngo Molnar 					  ".rela.plt", NULL);
77386470930SIngo Molnar 	if (scn_plt_rel == NULL) {
774a25e46c4SArnaldo Carvalho de Melo 		scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
77586470930SIngo Molnar 						  ".rel.plt", NULL);
77686470930SIngo Molnar 		if (scn_plt_rel == NULL)
777a25e46c4SArnaldo Carvalho de Melo 			goto out_elf_end;
77886470930SIngo Molnar 	}
77986470930SIngo Molnar 
780a25e46c4SArnaldo Carvalho de Melo 	err = -1;
78186470930SIngo Molnar 
782a25e46c4SArnaldo Carvalho de Melo 	if (shdr_rel_plt.sh_link != dynsym_idx)
783a25e46c4SArnaldo Carvalho de Melo 		goto out_elf_end;
784a25e46c4SArnaldo Carvalho de Melo 
785a25e46c4SArnaldo Carvalho de Melo 	if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
786a25e46c4SArnaldo Carvalho de Melo 		goto out_elf_end;
78786470930SIngo Molnar 
78886470930SIngo Molnar 	/*
78983a0944fSIngo Molnar 	 * Fetch the relocation section to find the idxes to the GOT
79086470930SIngo Molnar 	 * and the symbols in the .dynsym they refer to.
79186470930SIngo Molnar 	 */
79286470930SIngo Molnar 	reldata = elf_getdata(scn_plt_rel, NULL);
79386470930SIngo Molnar 	if (reldata == NULL)
794a25e46c4SArnaldo Carvalho de Melo 		goto out_elf_end;
79586470930SIngo Molnar 
79686470930SIngo Molnar 	syms = elf_getdata(scn_dynsym, NULL);
79786470930SIngo Molnar 	if (syms == NULL)
798a25e46c4SArnaldo Carvalho de Melo 		goto out_elf_end;
79986470930SIngo Molnar 
800a25e46c4SArnaldo Carvalho de Melo 	scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
80186470930SIngo Molnar 	if (scn_symstrs == NULL)
802a25e46c4SArnaldo Carvalho de Melo 		goto out_elf_end;
80386470930SIngo Molnar 
80486470930SIngo Molnar 	symstrs = elf_getdata(scn_symstrs, NULL);
80586470930SIngo Molnar 	if (symstrs == NULL)
806a25e46c4SArnaldo Carvalho de Melo 		goto out_elf_end;
80786470930SIngo Molnar 
80886470930SIngo Molnar 	nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
80986470930SIngo Molnar 	plt_offset = shdr_plt.sh_offset;
81086470930SIngo Molnar 
81186470930SIngo Molnar 	if (shdr_rel_plt.sh_type == SHT_RELA) {
81286470930SIngo Molnar 		GElf_Rela pos_mem, *pos;
81386470930SIngo Molnar 
81486470930SIngo Molnar 		elf_section__for_each_rela(reldata, pos, pos_mem, idx,
81586470930SIngo Molnar 					   nr_rel_entries) {
81686470930SIngo Molnar 			symidx = GELF_R_SYM(pos->r_info);
81786470930SIngo Molnar 			plt_offset += shdr_plt.sh_entsize;
81886470930SIngo Molnar 			gelf_getsym(syms, symidx, &sym);
81986470930SIngo Molnar 			snprintf(sympltname, sizeof(sympltname),
82086470930SIngo Molnar 				 "%s@plt", elf_sym__name(&sym, symstrs));
82186470930SIngo Molnar 
82286470930SIngo Molnar 			f = symbol__new(plt_offset, shdr_plt.sh_entsize,
82300a192b3SArnaldo Carvalho de Melo 					sympltname);
82486470930SIngo Molnar 			if (!f)
825a25e46c4SArnaldo Carvalho de Melo 				goto out_elf_end;
82686470930SIngo Molnar 
82782164161SArnaldo Carvalho de Melo 			if (filter && filter(map, f))
82882164161SArnaldo Carvalho de Melo 				symbol__delete(f);
82982164161SArnaldo Carvalho de Melo 			else {
8306a4694a4SArnaldo Carvalho de Melo 				symbols__insert(&self->symbols[map->type], f);
83186470930SIngo Molnar 				++nr;
83286470930SIngo Molnar 			}
83382164161SArnaldo Carvalho de Melo 		}
83486470930SIngo Molnar 	} else if (shdr_rel_plt.sh_type == SHT_REL) {
83586470930SIngo Molnar 		GElf_Rel pos_mem, *pos;
83686470930SIngo Molnar 		elf_section__for_each_rel(reldata, pos, pos_mem, idx,
83786470930SIngo Molnar 					  nr_rel_entries) {
83886470930SIngo Molnar 			symidx = GELF_R_SYM(pos->r_info);
83986470930SIngo Molnar 			plt_offset += shdr_plt.sh_entsize;
84086470930SIngo Molnar 			gelf_getsym(syms, symidx, &sym);
84186470930SIngo Molnar 			snprintf(sympltname, sizeof(sympltname),
84286470930SIngo Molnar 				 "%s@plt", elf_sym__name(&sym, symstrs));
84386470930SIngo Molnar 
84486470930SIngo Molnar 			f = symbol__new(plt_offset, shdr_plt.sh_entsize,
84500a192b3SArnaldo Carvalho de Melo 					sympltname);
84686470930SIngo Molnar 			if (!f)
847a25e46c4SArnaldo Carvalho de Melo 				goto out_elf_end;
84886470930SIngo Molnar 
84982164161SArnaldo Carvalho de Melo 			if (filter && filter(map, f))
85082164161SArnaldo Carvalho de Melo 				symbol__delete(f);
85182164161SArnaldo Carvalho de Melo 			else {
8526a4694a4SArnaldo Carvalho de Melo 				symbols__insert(&self->symbols[map->type], f);
85386470930SIngo Molnar 				++nr;
85486470930SIngo Molnar 			}
85586470930SIngo Molnar 		}
85682164161SArnaldo Carvalho de Melo 	}
85786470930SIngo Molnar 
858a25e46c4SArnaldo Carvalho de Melo 	err = 0;
859a25e46c4SArnaldo Carvalho de Melo out_elf_end:
860a25e46c4SArnaldo Carvalho de Melo 	elf_end(elf);
861a25e46c4SArnaldo Carvalho de Melo out_close:
862a25e46c4SArnaldo Carvalho de Melo 	close(fd);
863a25e46c4SArnaldo Carvalho de Melo 
864a25e46c4SArnaldo Carvalho de Melo 	if (err == 0)
86586470930SIngo Molnar 		return nr;
866a25e46c4SArnaldo Carvalho de Melo out:
8676beba7adSArnaldo Carvalho de Melo 	pr_warning("%s: problems reading %s PLT info.\n",
868439d473bSArnaldo Carvalho de Melo 		   __func__, self->long_name);
869a25e46c4SArnaldo Carvalho de Melo 	return 0;
87086470930SIngo Molnar }
87186470930SIngo Molnar 
872d45868d3SArnaldo Carvalho de Melo static bool elf_sym__is_a(GElf_Sym *self, enum map_type type)
873d45868d3SArnaldo Carvalho de Melo {
874d45868d3SArnaldo Carvalho de Melo 	switch (type) {
875d45868d3SArnaldo Carvalho de Melo 	case MAP__FUNCTION:
876d45868d3SArnaldo Carvalho de Melo 		return elf_sym__is_function(self);
877f1dfa0b1SArnaldo Carvalho de Melo 	case MAP__VARIABLE:
878f1dfa0b1SArnaldo Carvalho de Melo 		return elf_sym__is_object(self);
879d45868d3SArnaldo Carvalho de Melo 	default:
880d45868d3SArnaldo Carvalho de Melo 		return false;
881d45868d3SArnaldo Carvalho de Melo 	}
882d45868d3SArnaldo Carvalho de Melo }
883d45868d3SArnaldo Carvalho de Melo 
884d45868d3SArnaldo Carvalho de Melo static bool elf_sec__is_a(GElf_Shdr *self, Elf_Data *secstrs, enum map_type type)
885d45868d3SArnaldo Carvalho de Melo {
886d45868d3SArnaldo Carvalho de Melo 	switch (type) {
887d45868d3SArnaldo Carvalho de Melo 	case MAP__FUNCTION:
888d45868d3SArnaldo Carvalho de Melo 		return elf_sec__is_text(self, secstrs);
889f1dfa0b1SArnaldo Carvalho de Melo 	case MAP__VARIABLE:
890f1dfa0b1SArnaldo Carvalho de Melo 		return elf_sec__is_data(self, secstrs);
891d45868d3SArnaldo Carvalho de Melo 	default:
892d45868d3SArnaldo Carvalho de Melo 		return false;
893d45868d3SArnaldo Carvalho de Melo 	}
894d45868d3SArnaldo Carvalho de Melo }
895d45868d3SArnaldo Carvalho de Melo 
89695011c60SArnaldo Carvalho de Melo static int dso__load_sym(struct dso *self, struct map *map,
8974aa65636SArnaldo Carvalho de Melo 			 struct perf_session *session, const char *name, int fd,
89895011c60SArnaldo Carvalho de Melo 			 symbol_filter_t filter, int kernel, int kmodule)
89986470930SIngo Molnar {
9002e538c4aSArnaldo Carvalho de Melo 	struct map *curr_map = map;
9012e538c4aSArnaldo Carvalho de Melo 	struct dso *curr_dso = self;
9022e538c4aSArnaldo Carvalho de Melo 	size_t dso_name_len = strlen(self->short_name);
9036cfcc53eSMike Galbraith 	Elf_Data *symstrs, *secstrs;
90486470930SIngo Molnar 	uint32_t nr_syms;
90586470930SIngo Molnar 	int err = -1;
90683a0944fSIngo Molnar 	uint32_t idx;
90786470930SIngo Molnar 	GElf_Ehdr ehdr;
90886470930SIngo Molnar 	GElf_Shdr shdr;
90986470930SIngo Molnar 	Elf_Data *syms;
91086470930SIngo Molnar 	GElf_Sym sym;
911a25e46c4SArnaldo Carvalho de Melo 	Elf_Scn *sec, *sec_strndx;
91286470930SIngo Molnar 	Elf *elf;
913439d473bSArnaldo Carvalho de Melo 	int nr = 0;
91486470930SIngo Molnar 
91584087126SMarti Raudsepp 	elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
91686470930SIngo Molnar 	if (elf == NULL) {
9176beba7adSArnaldo Carvalho de Melo 		pr_err("%s: cannot read %s ELF file.\n", __func__, name);
91886470930SIngo Molnar 		goto out_close;
91986470930SIngo Molnar 	}
92086470930SIngo Molnar 
92186470930SIngo Molnar 	if (gelf_getehdr(elf, &ehdr) == NULL) {
9226beba7adSArnaldo Carvalho de Melo 		pr_err("%s: cannot get elf header.\n", __func__);
92386470930SIngo Molnar 		goto out_elf_end;
92486470930SIngo Molnar 	}
92586470930SIngo Molnar 
92686470930SIngo Molnar 	sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
92786470930SIngo Molnar 	if (sec == NULL) {
928a25e46c4SArnaldo Carvalho de Melo 		sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
929a25e46c4SArnaldo Carvalho de Melo 		if (sec == NULL)
93086470930SIngo Molnar 			goto out_elf_end;
93186470930SIngo Molnar 	}
93286470930SIngo Molnar 
93386470930SIngo Molnar 	syms = elf_getdata(sec, NULL);
93486470930SIngo Molnar 	if (syms == NULL)
93586470930SIngo Molnar 		goto out_elf_end;
93686470930SIngo Molnar 
93786470930SIngo Molnar 	sec = elf_getscn(elf, shdr.sh_link);
93886470930SIngo Molnar 	if (sec == NULL)
93986470930SIngo Molnar 		goto out_elf_end;
94086470930SIngo Molnar 
94186470930SIngo Molnar 	symstrs = elf_getdata(sec, NULL);
94286470930SIngo Molnar 	if (symstrs == NULL)
94386470930SIngo Molnar 		goto out_elf_end;
94486470930SIngo Molnar 
9456cfcc53eSMike Galbraith 	sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
9466cfcc53eSMike Galbraith 	if (sec_strndx == NULL)
9476cfcc53eSMike Galbraith 		goto out_elf_end;
9486cfcc53eSMike Galbraith 
9496cfcc53eSMike Galbraith 	secstrs = elf_getdata(sec_strndx, NULL);
9509b30a26bSStoyan Gaydarov 	if (secstrs == NULL)
9516cfcc53eSMike Galbraith 		goto out_elf_end;
9526cfcc53eSMike Galbraith 
95386470930SIngo Molnar 	nr_syms = shdr.sh_size / shdr.sh_entsize;
95486470930SIngo Molnar 
955e9fbc9dcSArjan van de Ven 	memset(&sym, 0, sizeof(sym));
956d20ff6bdSMike Galbraith 	if (!kernel) {
95730d7a77dSArnaldo Carvalho de Melo 		self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
95830d7a77dSArnaldo Carvalho de Melo 				elf_section_by_name(elf, &ehdr, &shdr,
959f5812a7aSArnaldo Carvalho de Melo 						     ".gnu.prelink_undo",
96030d7a77dSArnaldo Carvalho de Melo 						     NULL) != NULL);
961d20ff6bdSMike Galbraith 	} else self->adjust_symbols = 0;
962d20ff6bdSMike Galbraith 
96383a0944fSIngo Molnar 	elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
96486470930SIngo Molnar 		struct symbol *f;
96556b03f3cSArnaldo Carvalho de Melo 		const char *elf_name = elf_sym__name(&sym, symstrs);
9662e538c4aSArnaldo Carvalho de Melo 		char *demangled = NULL;
9676cfcc53eSMike Galbraith 		int is_label = elf_sym__is_label(&sym);
9686cfcc53eSMike Galbraith 		const char *section_name;
96986470930SIngo Molnar 
97056b03f3cSArnaldo Carvalho de Melo 		if (kernel && session->ref_reloc_sym.name != NULL &&
97156b03f3cSArnaldo Carvalho de Melo 		    strcmp(elf_name, session->ref_reloc_sym.name) == 0)
97256b03f3cSArnaldo Carvalho de Melo 			perf_session__reloc_vmlinux_maps(session, sym.st_value);
97356b03f3cSArnaldo Carvalho de Melo 
974d45868d3SArnaldo Carvalho de Melo 		if (!is_label && !elf_sym__is_a(&sym, map->type))
97586470930SIngo Molnar 			continue;
97686470930SIngo Molnar 
97786470930SIngo Molnar 		sec = elf_getscn(elf, sym.st_shndx);
97886470930SIngo Molnar 		if (!sec)
97986470930SIngo Molnar 			goto out_elf_end;
98086470930SIngo Molnar 
98186470930SIngo Molnar 		gelf_getshdr(sec, &shdr);
9826cfcc53eSMike Galbraith 
983d45868d3SArnaldo Carvalho de Melo 		if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type))
9846cfcc53eSMike Galbraith 			continue;
9856cfcc53eSMike Galbraith 
9866cfcc53eSMike Galbraith 		section_name = elf_sec__name(&shdr, secstrs);
98786470930SIngo Molnar 
9882e538c4aSArnaldo Carvalho de Melo 		if (kernel || kmodule) {
9892e538c4aSArnaldo Carvalho de Melo 			char dso_name[PATH_MAX];
9902e538c4aSArnaldo Carvalho de Melo 
9912e538c4aSArnaldo Carvalho de Melo 			if (strcmp(section_name,
9922e538c4aSArnaldo Carvalho de Melo 				   curr_dso->short_name + dso_name_len) == 0)
9932e538c4aSArnaldo Carvalho de Melo 				goto new_symbol;
9942e538c4aSArnaldo Carvalho de Melo 
9952e538c4aSArnaldo Carvalho de Melo 			if (strcmp(section_name, ".text") == 0) {
9962e538c4aSArnaldo Carvalho de Melo 				curr_map = map;
9972e538c4aSArnaldo Carvalho de Melo 				curr_dso = self;
9982e538c4aSArnaldo Carvalho de Melo 				goto new_symbol;
999af427bf5SArnaldo Carvalho de Melo 			}
1000af427bf5SArnaldo Carvalho de Melo 
10012e538c4aSArnaldo Carvalho de Melo 			snprintf(dso_name, sizeof(dso_name),
10022e538c4aSArnaldo Carvalho de Melo 				 "%s%s", self->short_name, section_name);
10032e538c4aSArnaldo Carvalho de Melo 
10044aa65636SArnaldo Carvalho de Melo 			curr_map = map_groups__find_by_name(&session->kmaps, map->type, dso_name);
10052e538c4aSArnaldo Carvalho de Melo 			if (curr_map == NULL) {
10062e538c4aSArnaldo Carvalho de Melo 				u64 start = sym.st_value;
10072e538c4aSArnaldo Carvalho de Melo 
10082e538c4aSArnaldo Carvalho de Melo 				if (kmodule)
10092e538c4aSArnaldo Carvalho de Melo 					start += map->start + shdr.sh_offset;
10102e538c4aSArnaldo Carvalho de Melo 
101100a192b3SArnaldo Carvalho de Melo 				curr_dso = dso__new(dso_name);
10122e538c4aSArnaldo Carvalho de Melo 				if (curr_dso == NULL)
10132e538c4aSArnaldo Carvalho de Melo 					goto out_elf_end;
10143610583cSArnaldo Carvalho de Melo 				curr_map = map__new2(start, curr_dso,
10153610583cSArnaldo Carvalho de Melo 						     MAP__FUNCTION);
10162e538c4aSArnaldo Carvalho de Melo 				if (curr_map == NULL) {
10172e538c4aSArnaldo Carvalho de Melo 					dso__delete(curr_dso);
10182e538c4aSArnaldo Carvalho de Melo 					goto out_elf_end;
10192e538c4aSArnaldo Carvalho de Melo 				}
1020ed52ce2eSArnaldo Carvalho de Melo 				curr_map->map_ip = identity__map_ip;
1021ed52ce2eSArnaldo Carvalho de Melo 				curr_map->unmap_ip = identity__map_ip;
10222e538c4aSArnaldo Carvalho de Melo 				curr_dso->origin = DSO__ORIG_KERNEL;
10234aa65636SArnaldo Carvalho de Melo 				map_groups__insert(&session->kmaps, curr_map);
1024b0da954aSArnaldo Carvalho de Melo 				dsos__add(&dsos__kernel, curr_dso);
10252e538c4aSArnaldo Carvalho de Melo 			} else
10262e538c4aSArnaldo Carvalho de Melo 				curr_dso = curr_map->dso;
10272e538c4aSArnaldo Carvalho de Melo 
10282e538c4aSArnaldo Carvalho de Melo 			goto new_symbol;
10292e538c4aSArnaldo Carvalho de Melo 		}
10302e538c4aSArnaldo Carvalho de Melo 
10312e538c4aSArnaldo Carvalho de Melo 		if (curr_dso->adjust_symbols) {
10326beba7adSArnaldo Carvalho de Melo 			pr_debug2("adjusting symbol: st_value: %Lx sh_addr: "
10336beba7adSArnaldo Carvalho de Melo 				  "%Lx sh_offset: %Lx\n", (u64)sym.st_value,
10346beba7adSArnaldo Carvalho de Melo 				  (u64)shdr.sh_addr, (u64)shdr.sh_offset);
103586470930SIngo Molnar 			sym.st_value -= shdr.sh_addr - shdr.sh_offset;
1036af427bf5SArnaldo Carvalho de Melo 		}
103728ac909bSArnaldo Carvalho de Melo 		/*
103828ac909bSArnaldo Carvalho de Melo 		 * We need to figure out if the object was created from C++ sources
103928ac909bSArnaldo Carvalho de Melo 		 * DWARF DW_compile_unit has this, but we don't always have access
104028ac909bSArnaldo Carvalho de Melo 		 * to it...
104128ac909bSArnaldo Carvalho de Melo 		 */
104283a0944fSIngo Molnar 		demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
104328ac909bSArnaldo Carvalho de Melo 		if (demangled != NULL)
104483a0944fSIngo Molnar 			elf_name = demangled;
10452e538c4aSArnaldo Carvalho de Melo new_symbol:
104600a192b3SArnaldo Carvalho de Melo 		f = symbol__new(sym.st_value, sym.st_size, elf_name);
104728ac909bSArnaldo Carvalho de Melo 		free(demangled);
104886470930SIngo Molnar 		if (!f)
104986470930SIngo Molnar 			goto out_elf_end;
105086470930SIngo Molnar 
10512e538c4aSArnaldo Carvalho de Melo 		if (filter && filter(curr_map, f))
105200a192b3SArnaldo Carvalho de Melo 			symbol__delete(f);
105386470930SIngo Molnar 		else {
10546a4694a4SArnaldo Carvalho de Melo 			symbols__insert(&curr_dso->symbols[curr_map->type], f);
105586470930SIngo Molnar 			nr++;
105686470930SIngo Molnar 		}
105786470930SIngo Molnar 	}
105886470930SIngo Molnar 
10592e538c4aSArnaldo Carvalho de Melo 	/*
10602e538c4aSArnaldo Carvalho de Melo 	 * For misannotated, zeroed, ASM function sizes.
10612e538c4aSArnaldo Carvalho de Melo 	 */
10622e538c4aSArnaldo Carvalho de Melo 	if (nr > 0)
10636a4694a4SArnaldo Carvalho de Melo 		symbols__fixup_end(&self->symbols[map->type]);
106486470930SIngo Molnar 	err = nr;
106586470930SIngo Molnar out_elf_end:
106686470930SIngo Molnar 	elf_end(elf);
106786470930SIngo Molnar out_close:
106886470930SIngo Molnar 	return err;
106986470930SIngo Molnar }
107086470930SIngo Molnar 
107178075caaSArnaldo Carvalho de Melo static bool dso__build_id_equal(const struct dso *self, u8 *build_id)
107278075caaSArnaldo Carvalho de Melo {
107378075caaSArnaldo Carvalho de Melo 	return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0;
107478075caaSArnaldo Carvalho de Melo }
107578075caaSArnaldo Carvalho de Melo 
1076b0da954aSArnaldo Carvalho de Melo static bool __dsos__read_build_ids(struct list_head *head)
107757f395a7SFrederic Weisbecker {
1078e30a3d12SArnaldo Carvalho de Melo 	bool have_build_id = false;
107957f395a7SFrederic Weisbecker 	struct dso *pos;
108057f395a7SFrederic Weisbecker 
1081b0da954aSArnaldo Carvalho de Melo 	list_for_each_entry(pos, head, node)
1082e30a3d12SArnaldo Carvalho de Melo 		if (filename__read_build_id(pos->long_name, pos->build_id,
1083e30a3d12SArnaldo Carvalho de Melo 					    sizeof(pos->build_id)) > 0) {
1084e30a3d12SArnaldo Carvalho de Melo 			have_build_id	  = true;
1085e30a3d12SArnaldo Carvalho de Melo 			pos->has_build_id = true;
108657f395a7SFrederic Weisbecker 		}
108757f395a7SFrederic Weisbecker 
1088e30a3d12SArnaldo Carvalho de Melo 	return have_build_id;
108957f395a7SFrederic Weisbecker }
109057f395a7SFrederic Weisbecker 
1091b0da954aSArnaldo Carvalho de Melo bool dsos__read_build_ids(void)
1092b0da954aSArnaldo Carvalho de Melo {
10938b4825bfSArnaldo Carvalho de Melo 	bool kbuildids = __dsos__read_build_ids(&dsos__kernel),
10948b4825bfSArnaldo Carvalho de Melo 	     ubuildids = __dsos__read_build_ids(&dsos__user);
10958b4825bfSArnaldo Carvalho de Melo 	return kbuildids || ubuildids;
1096b0da954aSArnaldo Carvalho de Melo }
1097b0da954aSArnaldo Carvalho de Melo 
1098fd7a346eSArnaldo Carvalho de Melo /*
1099fd7a346eSArnaldo Carvalho de Melo  * Align offset to 4 bytes as needed for note name and descriptor data.
1100fd7a346eSArnaldo Carvalho de Melo  */
1101fd7a346eSArnaldo Carvalho de Melo #define NOTE_ALIGN(n) (((n) + 3) & -4U)
1102fd7a346eSArnaldo Carvalho de Melo 
11032643ce11SArnaldo Carvalho de Melo int filename__read_build_id(const char *filename, void *bf, size_t size)
11044d1e00a8SArnaldo Carvalho de Melo {
11052643ce11SArnaldo Carvalho de Melo 	int fd, err = -1;
11064d1e00a8SArnaldo Carvalho de Melo 	GElf_Ehdr ehdr;
11074d1e00a8SArnaldo Carvalho de Melo 	GElf_Shdr shdr;
1108fd7a346eSArnaldo Carvalho de Melo 	Elf_Data *data;
11094d1e00a8SArnaldo Carvalho de Melo 	Elf_Scn *sec;
1110e57cfcdaSPekka Enberg 	Elf_Kind ek;
1111fd7a346eSArnaldo Carvalho de Melo 	void *ptr;
11124d1e00a8SArnaldo Carvalho de Melo 	Elf *elf;
11134d1e00a8SArnaldo Carvalho de Melo 
11142643ce11SArnaldo Carvalho de Melo 	if (size < BUILD_ID_SIZE)
11152643ce11SArnaldo Carvalho de Melo 		goto out;
11162643ce11SArnaldo Carvalho de Melo 
11172643ce11SArnaldo Carvalho de Melo 	fd = open(filename, O_RDONLY);
11184d1e00a8SArnaldo Carvalho de Melo 	if (fd < 0)
11194d1e00a8SArnaldo Carvalho de Melo 		goto out;
11204d1e00a8SArnaldo Carvalho de Melo 
112184087126SMarti Raudsepp 	elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
11224d1e00a8SArnaldo Carvalho de Melo 	if (elf == NULL) {
11238d06367fSArnaldo Carvalho de Melo 		pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
11244d1e00a8SArnaldo Carvalho de Melo 		goto out_close;
11254d1e00a8SArnaldo Carvalho de Melo 	}
11264d1e00a8SArnaldo Carvalho de Melo 
1127e57cfcdaSPekka Enberg 	ek = elf_kind(elf);
1128e57cfcdaSPekka Enberg 	if (ek != ELF_K_ELF)
1129e57cfcdaSPekka Enberg 		goto out_elf_end;
1130e57cfcdaSPekka Enberg 
11314d1e00a8SArnaldo Carvalho de Melo 	if (gelf_getehdr(elf, &ehdr) == NULL) {
11326beba7adSArnaldo Carvalho de Melo 		pr_err("%s: cannot get elf header.\n", __func__);
11334d1e00a8SArnaldo Carvalho de Melo 		goto out_elf_end;
11344d1e00a8SArnaldo Carvalho de Melo 	}
11354d1e00a8SArnaldo Carvalho de Melo 
11362643ce11SArnaldo Carvalho de Melo 	sec = elf_section_by_name(elf, &ehdr, &shdr,
11372643ce11SArnaldo Carvalho de Melo 				  ".note.gnu.build-id", NULL);
1138fd7a346eSArnaldo Carvalho de Melo 	if (sec == NULL) {
1139fd7a346eSArnaldo Carvalho de Melo 		sec = elf_section_by_name(elf, &ehdr, &shdr,
1140fd7a346eSArnaldo Carvalho de Melo 					  ".notes", NULL);
11414d1e00a8SArnaldo Carvalho de Melo 		if (sec == NULL)
11424d1e00a8SArnaldo Carvalho de Melo 			goto out_elf_end;
1143fd7a346eSArnaldo Carvalho de Melo 	}
11444d1e00a8SArnaldo Carvalho de Melo 
1145fd7a346eSArnaldo Carvalho de Melo 	data = elf_getdata(sec, NULL);
1146fd7a346eSArnaldo Carvalho de Melo 	if (data == NULL)
11474d1e00a8SArnaldo Carvalho de Melo 		goto out_elf_end;
1148fd7a346eSArnaldo Carvalho de Melo 
1149fd7a346eSArnaldo Carvalho de Melo 	ptr = data->d_buf;
1150fd7a346eSArnaldo Carvalho de Melo 	while (ptr < (data->d_buf + data->d_size)) {
1151fd7a346eSArnaldo Carvalho de Melo 		GElf_Nhdr *nhdr = ptr;
1152fd7a346eSArnaldo Carvalho de Melo 		int namesz = NOTE_ALIGN(nhdr->n_namesz),
1153fd7a346eSArnaldo Carvalho de Melo 		    descsz = NOTE_ALIGN(nhdr->n_descsz);
1154fd7a346eSArnaldo Carvalho de Melo 		const char *name;
1155fd7a346eSArnaldo Carvalho de Melo 
1156fd7a346eSArnaldo Carvalho de Melo 		ptr += sizeof(*nhdr);
1157fd7a346eSArnaldo Carvalho de Melo 		name = ptr;
1158fd7a346eSArnaldo Carvalho de Melo 		ptr += namesz;
1159fd7a346eSArnaldo Carvalho de Melo 		if (nhdr->n_type == NT_GNU_BUILD_ID &&
1160fd7a346eSArnaldo Carvalho de Melo 		    nhdr->n_namesz == sizeof("GNU")) {
1161fd7a346eSArnaldo Carvalho de Melo 			if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
1162fd7a346eSArnaldo Carvalho de Melo 				memcpy(bf, ptr, BUILD_ID_SIZE);
11632643ce11SArnaldo Carvalho de Melo 				err = BUILD_ID_SIZE;
1164fd7a346eSArnaldo Carvalho de Melo 				break;
1165fd7a346eSArnaldo Carvalho de Melo 			}
1166fd7a346eSArnaldo Carvalho de Melo 		}
1167fd7a346eSArnaldo Carvalho de Melo 		ptr += descsz;
1168fd7a346eSArnaldo Carvalho de Melo 	}
11692643ce11SArnaldo Carvalho de Melo out_elf_end:
11702643ce11SArnaldo Carvalho de Melo 	elf_end(elf);
11712643ce11SArnaldo Carvalho de Melo out_close:
11722643ce11SArnaldo Carvalho de Melo 	close(fd);
11732643ce11SArnaldo Carvalho de Melo out:
11742643ce11SArnaldo Carvalho de Melo 	return err;
11752643ce11SArnaldo Carvalho de Melo }
11762643ce11SArnaldo Carvalho de Melo 
1177f1617b40SArnaldo Carvalho de Melo int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
1178f1617b40SArnaldo Carvalho de Melo {
1179f1617b40SArnaldo Carvalho de Melo 	int fd, err = -1;
1180f1617b40SArnaldo Carvalho de Melo 
1181f1617b40SArnaldo Carvalho de Melo 	if (size < BUILD_ID_SIZE)
1182f1617b40SArnaldo Carvalho de Melo 		goto out;
1183f1617b40SArnaldo Carvalho de Melo 
1184f1617b40SArnaldo Carvalho de Melo 	fd = open(filename, O_RDONLY);
1185f1617b40SArnaldo Carvalho de Melo 	if (fd < 0)
1186f1617b40SArnaldo Carvalho de Melo 		goto out;
1187f1617b40SArnaldo Carvalho de Melo 
1188f1617b40SArnaldo Carvalho de Melo 	while (1) {
1189f1617b40SArnaldo Carvalho de Melo 		char bf[BUFSIZ];
1190f1617b40SArnaldo Carvalho de Melo 		GElf_Nhdr nhdr;
1191f1617b40SArnaldo Carvalho de Melo 		int namesz, descsz;
1192f1617b40SArnaldo Carvalho de Melo 
1193f1617b40SArnaldo Carvalho de Melo 		if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
1194f1617b40SArnaldo Carvalho de Melo 			break;
1195f1617b40SArnaldo Carvalho de Melo 
1196fd7a346eSArnaldo Carvalho de Melo 		namesz = NOTE_ALIGN(nhdr.n_namesz);
1197fd7a346eSArnaldo Carvalho de Melo 		descsz = NOTE_ALIGN(nhdr.n_descsz);
1198f1617b40SArnaldo Carvalho de Melo 		if (nhdr.n_type == NT_GNU_BUILD_ID &&
1199f1617b40SArnaldo Carvalho de Melo 		    nhdr.n_namesz == sizeof("GNU")) {
1200f1617b40SArnaldo Carvalho de Melo 			if (read(fd, bf, namesz) != namesz)
1201f1617b40SArnaldo Carvalho de Melo 				break;
1202f1617b40SArnaldo Carvalho de Melo 			if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
1203f1617b40SArnaldo Carvalho de Melo 				if (read(fd, build_id,
1204f1617b40SArnaldo Carvalho de Melo 				    BUILD_ID_SIZE) == BUILD_ID_SIZE) {
1205f1617b40SArnaldo Carvalho de Melo 					err = 0;
1206f1617b40SArnaldo Carvalho de Melo 					break;
1207f1617b40SArnaldo Carvalho de Melo 				}
1208f1617b40SArnaldo Carvalho de Melo 			} else if (read(fd, bf, descsz) != descsz)
1209f1617b40SArnaldo Carvalho de Melo 				break;
1210f1617b40SArnaldo Carvalho de Melo 		} else {
1211f1617b40SArnaldo Carvalho de Melo 			int n = namesz + descsz;
1212f1617b40SArnaldo Carvalho de Melo 			if (read(fd, bf, n) != n)
1213f1617b40SArnaldo Carvalho de Melo 				break;
1214f1617b40SArnaldo Carvalho de Melo 		}
1215f1617b40SArnaldo Carvalho de Melo 	}
1216f1617b40SArnaldo Carvalho de Melo 	close(fd);
1217f1617b40SArnaldo Carvalho de Melo out:
1218f1617b40SArnaldo Carvalho de Melo 	return err;
1219f1617b40SArnaldo Carvalho de Melo }
1220f1617b40SArnaldo Carvalho de Melo 
122194cb9e38SArnaldo Carvalho de Melo char dso__symtab_origin(const struct dso *self)
122294cb9e38SArnaldo Carvalho de Melo {
122394cb9e38SArnaldo Carvalho de Melo 	static const char origin[] = {
122494cb9e38SArnaldo Carvalho de Melo 		[DSO__ORIG_KERNEL] =   'k',
122594cb9e38SArnaldo Carvalho de Melo 		[DSO__ORIG_JAVA_JIT] = 'j',
12264cf40131SArnaldo Carvalho de Melo 		[DSO__ORIG_BUILD_ID_CACHE] = 'B',
122794cb9e38SArnaldo Carvalho de Melo 		[DSO__ORIG_FEDORA] =   'f',
122894cb9e38SArnaldo Carvalho de Melo 		[DSO__ORIG_UBUNTU] =   'u',
122994cb9e38SArnaldo Carvalho de Melo 		[DSO__ORIG_BUILDID] =  'b',
123094cb9e38SArnaldo Carvalho de Melo 		[DSO__ORIG_DSO] =      'd',
1231439d473bSArnaldo Carvalho de Melo 		[DSO__ORIG_KMODULE] =  'K',
123294cb9e38SArnaldo Carvalho de Melo 	};
123394cb9e38SArnaldo Carvalho de Melo 
123494cb9e38SArnaldo Carvalho de Melo 	if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
123594cb9e38SArnaldo Carvalho de Melo 		return '!';
123694cb9e38SArnaldo Carvalho de Melo 	return origin[self->origin];
123794cb9e38SArnaldo Carvalho de Melo }
123894cb9e38SArnaldo Carvalho de Melo 
12394aa65636SArnaldo Carvalho de Melo int dso__load(struct dso *self, struct map *map, struct perf_session *session,
12404aa65636SArnaldo Carvalho de Melo 	      symbol_filter_t filter)
124186470930SIngo Molnar {
12424d1e00a8SArnaldo Carvalho de Melo 	int size = PATH_MAX;
1243c338aee8SArnaldo Carvalho de Melo 	char *name;
1244d3379ab9SArnaldo Carvalho de Melo 	u8 build_id[BUILD_ID_SIZE];
12454cf40131SArnaldo Carvalho de Melo 	char build_id_hex[BUILD_ID_SIZE * 2 + 1];
124686470930SIngo Molnar 	int ret = -1;
124786470930SIngo Molnar 	int fd;
124886470930SIngo Molnar 
12493610583cSArnaldo Carvalho de Melo 	dso__set_loaded(self, map->type);
125066bd8424SArnaldo Carvalho de Melo 
1251c338aee8SArnaldo Carvalho de Melo 	if (self->kernel)
12524aa65636SArnaldo Carvalho de Melo 		return dso__load_kernel_sym(self, map, session, filter);
1253c338aee8SArnaldo Carvalho de Melo 
1254c338aee8SArnaldo Carvalho de Melo 	name = malloc(size);
125586470930SIngo Molnar 	if (!name)
125686470930SIngo Molnar 		return -1;
125786470930SIngo Molnar 
125830d7a77dSArnaldo Carvalho de Melo 	self->adjust_symbols = 0;
1259f5812a7aSArnaldo Carvalho de Melo 
126094cb9e38SArnaldo Carvalho de Melo 	if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
12616beba7adSArnaldo Carvalho de Melo 		ret = dso__load_perf_map(self, map, filter);
126294cb9e38SArnaldo Carvalho de Melo 		self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
126394cb9e38SArnaldo Carvalho de Melo 					 DSO__ORIG_NOT_FOUND;
126494cb9e38SArnaldo Carvalho de Melo 		return ret;
126594cb9e38SArnaldo Carvalho de Melo 	}
126694cb9e38SArnaldo Carvalho de Melo 
12674cf40131SArnaldo Carvalho de Melo 	self->origin = DSO__ORIG_BUILD_ID_CACHE;
126880d496beSPekka Enberg 
12694cf40131SArnaldo Carvalho de Melo 	if (self->has_build_id) {
12704cf40131SArnaldo Carvalho de Melo 		build_id__sprintf(self->build_id, sizeof(self->build_id),
12714cf40131SArnaldo Carvalho de Melo 				  build_id_hex);
12724cf40131SArnaldo Carvalho de Melo 		snprintf(name, size, "%s/%s/.build-id/%.2s/%s",
12734cf40131SArnaldo Carvalho de Melo 			 getenv("HOME"), DEBUG_CACHE_DIR,
12744cf40131SArnaldo Carvalho de Melo 			 build_id_hex, build_id_hex + 2);
12754cf40131SArnaldo Carvalho de Melo 		goto open_file;
12764cf40131SArnaldo Carvalho de Melo 	}
127786470930SIngo Molnar more:
127886470930SIngo Molnar 	do {
127994cb9e38SArnaldo Carvalho de Melo 		self->origin++;
128094cb9e38SArnaldo Carvalho de Melo 		switch (self->origin) {
128194cb9e38SArnaldo Carvalho de Melo 		case DSO__ORIG_FEDORA:
1282439d473bSArnaldo Carvalho de Melo 			snprintf(name, size, "/usr/lib/debug%s.debug",
1283439d473bSArnaldo Carvalho de Melo 				 self->long_name);
128486470930SIngo Molnar 			break;
128594cb9e38SArnaldo Carvalho de Melo 		case DSO__ORIG_UBUNTU:
1286439d473bSArnaldo Carvalho de Melo 			snprintf(name, size, "/usr/lib/debug%s",
1287439d473bSArnaldo Carvalho de Melo 				 self->long_name);
128886470930SIngo Molnar 			break;
128994cb9e38SArnaldo Carvalho de Melo 		case DSO__ORIG_BUILDID:
1290d3379ab9SArnaldo Carvalho de Melo 			if (filename__read_build_id(self->long_name, build_id,
1291d3379ab9SArnaldo Carvalho de Melo 						    sizeof(build_id))) {
1292d3379ab9SArnaldo Carvalho de Melo 				build_id__sprintf(build_id, sizeof(build_id),
1293d3379ab9SArnaldo Carvalho de Melo 						  build_id_hex);
12944d1e00a8SArnaldo Carvalho de Melo 				snprintf(name, size,
12954d1e00a8SArnaldo Carvalho de Melo 					 "/usr/lib/debug/.build-id/%.2s/%s.debug",
1296d3379ab9SArnaldo Carvalho de Melo 					build_id_hex, build_id_hex + 2);
1297d3379ab9SArnaldo Carvalho de Melo 				if (self->has_build_id)
12988d06367fSArnaldo Carvalho de Melo 					goto compare_build_id;
1299d3379ab9SArnaldo Carvalho de Melo 				break;
13004d1e00a8SArnaldo Carvalho de Melo 			}
130194cb9e38SArnaldo Carvalho de Melo 			self->origin++;
13024d1e00a8SArnaldo Carvalho de Melo 			/* Fall thru */
130394cb9e38SArnaldo Carvalho de Melo 		case DSO__ORIG_DSO:
1304439d473bSArnaldo Carvalho de Melo 			snprintf(name, size, "%s", self->long_name);
130586470930SIngo Molnar 			break;
130686470930SIngo Molnar 
130786470930SIngo Molnar 		default:
130886470930SIngo Molnar 			goto out;
130986470930SIngo Molnar 		}
131086470930SIngo Molnar 
13118d06367fSArnaldo Carvalho de Melo 		if (self->has_build_id) {
1312d3379ab9SArnaldo Carvalho de Melo 			if (filename__read_build_id(name, build_id,
1313d3379ab9SArnaldo Carvalho de Melo 						    sizeof(build_id)) < 0)
13148d06367fSArnaldo Carvalho de Melo 				goto more;
13158d06367fSArnaldo Carvalho de Melo compare_build_id:
131678075caaSArnaldo Carvalho de Melo 			if (!dso__build_id_equal(self, build_id))
13178d06367fSArnaldo Carvalho de Melo 				goto more;
13188d06367fSArnaldo Carvalho de Melo 		}
13194cf40131SArnaldo Carvalho de Melo open_file:
132086470930SIngo Molnar 		fd = open(name, O_RDONLY);
132186470930SIngo Molnar 	} while (fd < 0);
132286470930SIngo Molnar 
132395011c60SArnaldo Carvalho de Melo 	ret = dso__load_sym(self, map, NULL, name, fd, filter, 0, 0);
132486470930SIngo Molnar 	close(fd);
132586470930SIngo Molnar 
132686470930SIngo Molnar 	/*
132786470930SIngo Molnar 	 * Some people seem to have debuginfo files _WITHOUT_ debug info!?!?
132886470930SIngo Molnar 	 */
132986470930SIngo Molnar 	if (!ret)
133086470930SIngo Molnar 		goto more;
133186470930SIngo Molnar 
1332a25e46c4SArnaldo Carvalho de Melo 	if (ret > 0) {
133382164161SArnaldo Carvalho de Melo 		int nr_plt = dso__synthesize_plt_symbols(self, map, filter);
1334a25e46c4SArnaldo Carvalho de Melo 		if (nr_plt > 0)
1335a25e46c4SArnaldo Carvalho de Melo 			ret += nr_plt;
1336a25e46c4SArnaldo Carvalho de Melo 	}
133786470930SIngo Molnar out:
133886470930SIngo Molnar 	free(name);
13391340e6bbSArnaldo Carvalho de Melo 	if (ret < 0 && strstr(self->name, " (deleted)") != NULL)
13401340e6bbSArnaldo Carvalho de Melo 		return 0;
134186470930SIngo Molnar 	return ret;
134286470930SIngo Molnar }
134386470930SIngo Molnar 
134479406cd7SArnaldo Carvalho de Melo struct map *map_groups__find_by_name(struct map_groups *self,
134579406cd7SArnaldo Carvalho de Melo 				     enum map_type type, const char *name)
1346439d473bSArnaldo Carvalho de Melo {
1347439d473bSArnaldo Carvalho de Melo 	struct rb_node *nd;
1348439d473bSArnaldo Carvalho de Melo 
134979406cd7SArnaldo Carvalho de Melo 	for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
1350439d473bSArnaldo Carvalho de Melo 		struct map *map = rb_entry(nd, struct map, rb_node);
1351439d473bSArnaldo Carvalho de Melo 
1352b7cece76SArnaldo Carvalho de Melo 		if (map->dso && strcmp(map->dso->short_name, name) == 0)
1353439d473bSArnaldo Carvalho de Melo 			return map;
1354439d473bSArnaldo Carvalho de Melo 	}
1355439d473bSArnaldo Carvalho de Melo 
1356439d473bSArnaldo Carvalho de Melo 	return NULL;
1357439d473bSArnaldo Carvalho de Melo }
1358439d473bSArnaldo Carvalho de Melo 
1359b7cece76SArnaldo Carvalho de Melo static int dso__kernel_module_get_build_id(struct dso *self)
1360b7cece76SArnaldo Carvalho de Melo {
1361b7cece76SArnaldo Carvalho de Melo 	char filename[PATH_MAX];
1362b7cece76SArnaldo Carvalho de Melo 	/*
1363b7cece76SArnaldo Carvalho de Melo 	 * kernel module short names are of the form "[module]" and
1364b7cece76SArnaldo Carvalho de Melo 	 * we need just "module" here.
1365b7cece76SArnaldo Carvalho de Melo 	 */
1366b7cece76SArnaldo Carvalho de Melo 	const char *name = self->short_name + 1;
1367b7cece76SArnaldo Carvalho de Melo 
1368b7cece76SArnaldo Carvalho de Melo 	snprintf(filename, sizeof(filename),
1369b7cece76SArnaldo Carvalho de Melo 		 "/sys/module/%.*s/notes/.note.gnu.build-id",
1370b7cece76SArnaldo Carvalho de Melo 		 (int)strlen(name - 1), name);
1371b7cece76SArnaldo Carvalho de Melo 
1372b7cece76SArnaldo Carvalho de Melo 	if (sysfs__read_build_id(filename, self->build_id,
1373b7cece76SArnaldo Carvalho de Melo 				 sizeof(self->build_id)) == 0)
1374b7cece76SArnaldo Carvalho de Melo 		self->has_build_id = true;
1375b7cece76SArnaldo Carvalho de Melo 
1376b7cece76SArnaldo Carvalho de Melo 	return 0;
1377b7cece76SArnaldo Carvalho de Melo }
1378b7cece76SArnaldo Carvalho de Melo 
13794aa65636SArnaldo Carvalho de Melo static int perf_session__set_modules_path_dir(struct perf_session *self, char *dirname)
13806cfcc53eSMike Galbraith {
1381439d473bSArnaldo Carvalho de Melo 	struct dirent *dent;
1382439d473bSArnaldo Carvalho de Melo 	DIR *dir = opendir(dirname);
13836cfcc53eSMike Galbraith 
1384439d473bSArnaldo Carvalho de Melo 	if (!dir) {
138587f8ea4cSArnaldo Carvalho de Melo 		pr_debug("%s: cannot open %s dir\n", __func__, dirname);
1386439d473bSArnaldo Carvalho de Melo 		return -1;
1387439d473bSArnaldo Carvalho de Melo 	}
13886cfcc53eSMike Galbraith 
1389439d473bSArnaldo Carvalho de Melo 	while ((dent = readdir(dir)) != NULL) {
1390439d473bSArnaldo Carvalho de Melo 		char path[PATH_MAX];
1391439d473bSArnaldo Carvalho de Melo 
1392439d473bSArnaldo Carvalho de Melo 		if (dent->d_type == DT_DIR) {
1393439d473bSArnaldo Carvalho de Melo 			if (!strcmp(dent->d_name, ".") ||
1394439d473bSArnaldo Carvalho de Melo 			    !strcmp(dent->d_name, ".."))
1395439d473bSArnaldo Carvalho de Melo 				continue;
1396439d473bSArnaldo Carvalho de Melo 
1397439d473bSArnaldo Carvalho de Melo 			snprintf(path, sizeof(path), "%s/%s",
1398439d473bSArnaldo Carvalho de Melo 				 dirname, dent->d_name);
13994aa65636SArnaldo Carvalho de Melo 			if (perf_session__set_modules_path_dir(self, path) < 0)
1400439d473bSArnaldo Carvalho de Melo 				goto failure;
1401439d473bSArnaldo Carvalho de Melo 		} else {
1402439d473bSArnaldo Carvalho de Melo 			char *dot = strrchr(dent->d_name, '.'),
1403439d473bSArnaldo Carvalho de Melo 			     dso_name[PATH_MAX];
1404439d473bSArnaldo Carvalho de Melo 			struct map *map;
1405cfc10d3bSArnaldo Carvalho de Melo 			char *long_name;
1406439d473bSArnaldo Carvalho de Melo 
1407439d473bSArnaldo Carvalho de Melo 			if (dot == NULL || strcmp(dot, ".ko"))
1408439d473bSArnaldo Carvalho de Melo 				continue;
1409439d473bSArnaldo Carvalho de Melo 			snprintf(dso_name, sizeof(dso_name), "[%.*s]",
1410439d473bSArnaldo Carvalho de Melo 				 (int)(dot - dent->d_name), dent->d_name);
1411439d473bSArnaldo Carvalho de Melo 
1412a2a99e8eSArnaldo Carvalho de Melo 			strxfrchar(dso_name, '-', '_');
14134aa65636SArnaldo Carvalho de Melo 			map = map_groups__find_by_name(&self->kmaps, MAP__FUNCTION, dso_name);
1414439d473bSArnaldo Carvalho de Melo 			if (map == NULL)
1415439d473bSArnaldo Carvalho de Melo 				continue;
1416439d473bSArnaldo Carvalho de Melo 
1417439d473bSArnaldo Carvalho de Melo 			snprintf(path, sizeof(path), "%s/%s",
1418439d473bSArnaldo Carvalho de Melo 				 dirname, dent->d_name);
1419439d473bSArnaldo Carvalho de Melo 
1420cfc10d3bSArnaldo Carvalho de Melo 			long_name = strdup(path);
1421cfc10d3bSArnaldo Carvalho de Melo 			if (long_name == NULL)
1422439d473bSArnaldo Carvalho de Melo 				goto failure;
1423cfc10d3bSArnaldo Carvalho de Melo 			dso__set_long_name(map->dso, long_name);
1424b7cece76SArnaldo Carvalho de Melo 			dso__kernel_module_get_build_id(map->dso);
1425439d473bSArnaldo Carvalho de Melo 		}
1426439d473bSArnaldo Carvalho de Melo 	}
1427439d473bSArnaldo Carvalho de Melo 
1428c338aee8SArnaldo Carvalho de Melo 	return 0;
1429439d473bSArnaldo Carvalho de Melo failure:
1430439d473bSArnaldo Carvalho de Melo 	closedir(dir);
1431439d473bSArnaldo Carvalho de Melo 	return -1;
1432439d473bSArnaldo Carvalho de Melo }
1433439d473bSArnaldo Carvalho de Melo 
14344aa65636SArnaldo Carvalho de Melo static int perf_session__set_modules_path(struct perf_session *self)
1435439d473bSArnaldo Carvalho de Melo {
1436439d473bSArnaldo Carvalho de Melo 	struct utsname uts;
1437439d473bSArnaldo Carvalho de Melo 	char modules_path[PATH_MAX];
1438439d473bSArnaldo Carvalho de Melo 
1439439d473bSArnaldo Carvalho de Melo 	if (uname(&uts) < 0)
1440439d473bSArnaldo Carvalho de Melo 		return -1;
1441439d473bSArnaldo Carvalho de Melo 
1442439d473bSArnaldo Carvalho de Melo 	snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel",
1443439d473bSArnaldo Carvalho de Melo 		 uts.release);
1444439d473bSArnaldo Carvalho de Melo 
14454aa65636SArnaldo Carvalho de Melo 	return perf_session__set_modules_path_dir(self, modules_path);
1446439d473bSArnaldo Carvalho de Melo }
14476cfcc53eSMike Galbraith 
14486cfcc53eSMike Galbraith /*
1449439d473bSArnaldo Carvalho de Melo  * Constructor variant for modules (where we know from /proc/modules where
1450439d473bSArnaldo Carvalho de Melo  * they are loaded) and for vmlinux, where only after we load all the
1451439d473bSArnaldo Carvalho de Melo  * symbols we'll know where it starts and ends.
14526cfcc53eSMike Galbraith  */
14533610583cSArnaldo Carvalho de Melo static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
1454439d473bSArnaldo Carvalho de Melo {
1455439d473bSArnaldo Carvalho de Melo 	struct map *self = malloc(sizeof(*self));
14566cfcc53eSMike Galbraith 
1457439d473bSArnaldo Carvalho de Melo 	if (self != NULL) {
1458439d473bSArnaldo Carvalho de Melo 		/*
1459afb7b4f0SArnaldo Carvalho de Melo 		 * ->end will be filled after we load all the symbols
1460439d473bSArnaldo Carvalho de Melo 		 */
14613610583cSArnaldo Carvalho de Melo 		map__init(self, type, start, 0, 0, dso);
1462439d473bSArnaldo Carvalho de Melo 	}
1463afb7b4f0SArnaldo Carvalho de Melo 
1464439d473bSArnaldo Carvalho de Melo 	return self;
1465439d473bSArnaldo Carvalho de Melo }
1466439d473bSArnaldo Carvalho de Melo 
1467b7cece76SArnaldo Carvalho de Melo struct map *perf_session__new_module_map(struct perf_session *self, u64 start,
1468b7cece76SArnaldo Carvalho de Melo 					 const char *filename)
1469b7cece76SArnaldo Carvalho de Melo {
1470b7cece76SArnaldo Carvalho de Melo 	struct map *map;
1471b7cece76SArnaldo Carvalho de Melo 	struct dso *dso = __dsos__findnew(&dsos__kernel, filename);
1472b7cece76SArnaldo Carvalho de Melo 
1473b7cece76SArnaldo Carvalho de Melo 	if (dso == NULL)
1474b7cece76SArnaldo Carvalho de Melo 		return NULL;
1475b7cece76SArnaldo Carvalho de Melo 
1476b7cece76SArnaldo Carvalho de Melo 	map = map__new2(start, dso, MAP__FUNCTION);
1477b7cece76SArnaldo Carvalho de Melo 	if (map == NULL)
1478b7cece76SArnaldo Carvalho de Melo 		return NULL;
1479b7cece76SArnaldo Carvalho de Melo 
1480b7cece76SArnaldo Carvalho de Melo 	dso->origin = DSO__ORIG_KMODULE;
1481b7cece76SArnaldo Carvalho de Melo 	map_groups__insert(&self->kmaps, map);
1482b7cece76SArnaldo Carvalho de Melo 	return map;
1483b7cece76SArnaldo Carvalho de Melo }
1484b7cece76SArnaldo Carvalho de Melo 
14854aa65636SArnaldo Carvalho de Melo static int perf_session__create_module_maps(struct perf_session *self)
1486439d473bSArnaldo Carvalho de Melo {
1487439d473bSArnaldo Carvalho de Melo 	char *line = NULL;
1488439d473bSArnaldo Carvalho de Melo 	size_t n;
1489439d473bSArnaldo Carvalho de Melo 	FILE *file = fopen("/proc/modules", "r");
1490439d473bSArnaldo Carvalho de Melo 	struct map *map;
1491439d473bSArnaldo Carvalho de Melo 
1492439d473bSArnaldo Carvalho de Melo 	if (file == NULL)
1493439d473bSArnaldo Carvalho de Melo 		return -1;
1494439d473bSArnaldo Carvalho de Melo 
1495439d473bSArnaldo Carvalho de Melo 	while (!feof(file)) {
1496439d473bSArnaldo Carvalho de Melo 		char name[PATH_MAX];
1497439d473bSArnaldo Carvalho de Melo 		u64 start;
1498439d473bSArnaldo Carvalho de Melo 		char *sep;
1499439d473bSArnaldo Carvalho de Melo 		int line_len;
1500439d473bSArnaldo Carvalho de Melo 
1501439d473bSArnaldo Carvalho de Melo 		line_len = getline(&line, &n, file);
1502439d473bSArnaldo Carvalho de Melo 		if (line_len < 0)
15036cfcc53eSMike Galbraith 			break;
15046cfcc53eSMike Galbraith 
1505439d473bSArnaldo Carvalho de Melo 		if (!line)
1506439d473bSArnaldo Carvalho de Melo 			goto out_failure;
1507439d473bSArnaldo Carvalho de Melo 
1508439d473bSArnaldo Carvalho de Melo 		line[--line_len] = '\0'; /* \n */
1509439d473bSArnaldo Carvalho de Melo 
1510439d473bSArnaldo Carvalho de Melo 		sep = strrchr(line, 'x');
1511439d473bSArnaldo Carvalho de Melo 		if (sep == NULL)
1512439d473bSArnaldo Carvalho de Melo 			continue;
1513439d473bSArnaldo Carvalho de Melo 
1514439d473bSArnaldo Carvalho de Melo 		hex2u64(sep + 1, &start);
1515439d473bSArnaldo Carvalho de Melo 
1516439d473bSArnaldo Carvalho de Melo 		sep = strchr(line, ' ');
1517439d473bSArnaldo Carvalho de Melo 		if (sep == NULL)
1518439d473bSArnaldo Carvalho de Melo 			continue;
1519439d473bSArnaldo Carvalho de Melo 
1520439d473bSArnaldo Carvalho de Melo 		*sep = '\0';
1521439d473bSArnaldo Carvalho de Melo 
1522439d473bSArnaldo Carvalho de Melo 		snprintf(name, sizeof(name), "[%s]", line);
1523b7cece76SArnaldo Carvalho de Melo 		map = perf_session__new_module_map(self, start, name);
1524b7cece76SArnaldo Carvalho de Melo 		if (map == NULL)
1525439d473bSArnaldo Carvalho de Melo 			goto out_delete_line;
1526b7cece76SArnaldo Carvalho de Melo 		dso__kernel_module_get_build_id(map->dso);
15276cfcc53eSMike Galbraith 	}
15286cfcc53eSMike Galbraith 
1529439d473bSArnaldo Carvalho de Melo 	free(line);
1530439d473bSArnaldo Carvalho de Melo 	fclose(file);
1531439d473bSArnaldo Carvalho de Melo 
15324aa65636SArnaldo Carvalho de Melo 	return perf_session__set_modules_path(self);
1533439d473bSArnaldo Carvalho de Melo 
1534439d473bSArnaldo Carvalho de Melo out_delete_line:
1535439d473bSArnaldo Carvalho de Melo 	free(line);
1536439d473bSArnaldo Carvalho de Melo out_failure:
1537439d473bSArnaldo Carvalho de Melo 	return -1;
15386cfcc53eSMike Galbraith }
15396cfcc53eSMike Galbraith 
15409958e1f0SArnaldo Carvalho de Melo static int dso__load_vmlinux(struct dso *self, struct map *map,
15414aa65636SArnaldo Carvalho de Melo 			     struct perf_session *session,
15426beba7adSArnaldo Carvalho de Melo 			     const char *vmlinux, symbol_filter_t filter)
154386470930SIngo Molnar {
1544fbd733b8SArnaldo Carvalho de Melo 	int err = -1, fd;
154586470930SIngo Molnar 
1546fbd733b8SArnaldo Carvalho de Melo 	if (self->has_build_id) {
1547fbd733b8SArnaldo Carvalho de Melo 		u8 build_id[BUILD_ID_SIZE];
154866bd8424SArnaldo Carvalho de Melo 
1549fbd733b8SArnaldo Carvalho de Melo 		if (filename__read_build_id(vmlinux, build_id,
1550fbd733b8SArnaldo Carvalho de Melo 					    sizeof(build_id)) < 0) {
1551fbd733b8SArnaldo Carvalho de Melo 			pr_debug("No build_id in %s, ignoring it\n", vmlinux);
1552fbd733b8SArnaldo Carvalho de Melo 			return -1;
1553fbd733b8SArnaldo Carvalho de Melo 		}
1554fbd733b8SArnaldo Carvalho de Melo 		if (!dso__build_id_equal(self, build_id)) {
1555fbd733b8SArnaldo Carvalho de Melo 			char expected_build_id[BUILD_ID_SIZE * 2 + 1],
1556fbd733b8SArnaldo Carvalho de Melo 			     vmlinux_build_id[BUILD_ID_SIZE * 2 + 1];
1557fbd733b8SArnaldo Carvalho de Melo 
1558fbd733b8SArnaldo Carvalho de Melo 			build_id__sprintf(self->build_id,
1559fbd733b8SArnaldo Carvalho de Melo 					  sizeof(self->build_id),
1560fbd733b8SArnaldo Carvalho de Melo 					  expected_build_id);
1561fbd733b8SArnaldo Carvalho de Melo 			build_id__sprintf(build_id, sizeof(build_id),
1562fbd733b8SArnaldo Carvalho de Melo 					  vmlinux_build_id);
1563fbd733b8SArnaldo Carvalho de Melo 			pr_debug("build_id in %s is %s while expected is %s, "
1564fbd733b8SArnaldo Carvalho de Melo 				 "ignoring it\n", vmlinux, vmlinux_build_id,
1565fbd733b8SArnaldo Carvalho de Melo 				 expected_build_id);
1566fbd733b8SArnaldo Carvalho de Melo 			return -1;
1567fbd733b8SArnaldo Carvalho de Melo 		}
1568fbd733b8SArnaldo Carvalho de Melo 	}
1569fbd733b8SArnaldo Carvalho de Melo 
1570fbd733b8SArnaldo Carvalho de Melo 	fd = open(vmlinux, O_RDONLY);
157186470930SIngo Molnar 	if (fd < 0)
157286470930SIngo Molnar 		return -1;
157386470930SIngo Molnar 
15743610583cSArnaldo Carvalho de Melo 	dso__set_loaded(self, map->type);
1575dc8d6ab2SArnaldo Carvalho de Melo 	err = dso__load_sym(self, map, session, vmlinux, fd, filter, 1, 0);
157686470930SIngo Molnar 	close(fd);
157786470930SIngo Molnar 
157886470930SIngo Molnar 	return err;
157986470930SIngo Molnar }
158086470930SIngo Molnar 
1581c338aee8SArnaldo Carvalho de Melo static int dso__load_kernel_sym(struct dso *self, struct map *map,
15824aa65636SArnaldo Carvalho de Melo 				struct perf_session *session, symbol_filter_t filter)
158386470930SIngo Molnar {
1584cc612d81SArnaldo Carvalho de Melo 	int err;
15859e201442SArnaldo Carvalho de Melo 	const char *kallsyms_filename = NULL;
15869e201442SArnaldo Carvalho de Melo 	char *kallsyms_allocated_filename = NULL;
1587dc8d6ab2SArnaldo Carvalho de Melo 	/*
1588dc8d6ab2SArnaldo Carvalho de Melo 	 * Step 1: if the user specified a vmlinux filename, use it and only
1589dc8d6ab2SArnaldo Carvalho de Melo 	 * it, reporting errors to the user if it cannot be used.
1590dc8d6ab2SArnaldo Carvalho de Melo 	 *
1591dc8d6ab2SArnaldo Carvalho de Melo 	 * For instance, try to analyse an ARM perf.data file _without_ a
1592dc8d6ab2SArnaldo Carvalho de Melo 	 * build-id, or if the user specifies the wrong path to the right
1593dc8d6ab2SArnaldo Carvalho de Melo 	 * vmlinux file, obviously we can't fallback to another vmlinux (a
1594dc8d6ab2SArnaldo Carvalho de Melo 	 * x86_86 one, on the machine where analysis is being performed, say),
1595dc8d6ab2SArnaldo Carvalho de Melo 	 * or worse, /proc/kallsyms.
1596dc8d6ab2SArnaldo Carvalho de Melo 	 *
1597dc8d6ab2SArnaldo Carvalho de Melo 	 * If the specified file _has_ a build-id and there is a build-id
1598dc8d6ab2SArnaldo Carvalho de Melo 	 * section in the perf.data file, we will still do the expected
1599dc8d6ab2SArnaldo Carvalho de Melo 	 * validation in dso__load_vmlinux and will bail out if they don't
1600dc8d6ab2SArnaldo Carvalho de Melo 	 * match.
1601dc8d6ab2SArnaldo Carvalho de Melo 	 */
1602dc8d6ab2SArnaldo Carvalho de Melo 	if (symbol_conf.vmlinux_name != NULL) {
1603dc8d6ab2SArnaldo Carvalho de Melo 		err = dso__load_vmlinux(self, map, session,
1604dc8d6ab2SArnaldo Carvalho de Melo 					symbol_conf.vmlinux_name, filter);
1605dc8d6ab2SArnaldo Carvalho de Melo 		goto out_try_fixup;
1606dc8d6ab2SArnaldo Carvalho de Melo 	}
1607439d473bSArnaldo Carvalho de Melo 
1608cc612d81SArnaldo Carvalho de Melo 	if (vmlinux_path != NULL) {
1609cc612d81SArnaldo Carvalho de Melo 		int i;
1610cc612d81SArnaldo Carvalho de Melo 		pr_debug("Looking at the vmlinux_path (%d entries long)\n",
1611cc612d81SArnaldo Carvalho de Melo 			 vmlinux_path__nr_entries);
1612cc612d81SArnaldo Carvalho de Melo 		for (i = 0; i < vmlinux_path__nr_entries; ++i) {
16134aa65636SArnaldo Carvalho de Melo 			err = dso__load_vmlinux(self, map, session,
161495011c60SArnaldo Carvalho de Melo 						vmlinux_path[i], filter);
1615cc612d81SArnaldo Carvalho de Melo 			if (err > 0) {
1616cc612d81SArnaldo Carvalho de Melo 				pr_debug("Using %s for symbols\n",
1617cc612d81SArnaldo Carvalho de Melo 					 vmlinux_path[i]);
1618cc612d81SArnaldo Carvalho de Melo 				dso__set_long_name(self,
1619cc612d81SArnaldo Carvalho de Melo 						   strdup(vmlinux_path[i]));
1620cc612d81SArnaldo Carvalho de Melo 				goto out_fixup;
1621cc612d81SArnaldo Carvalho de Melo 			}
1622cc612d81SArnaldo Carvalho de Melo 		}
1623cc612d81SArnaldo Carvalho de Melo 	}
1624cc612d81SArnaldo Carvalho de Melo 
1625b7cece76SArnaldo Carvalho de Melo 	/*
1626b7cece76SArnaldo Carvalho de Melo 	 * Say the kernel DSO was created when processing the build-id header table,
1627b7cece76SArnaldo Carvalho de Melo 	 * we have a build-id, so check if it is the same as the running kernel,
1628b7cece76SArnaldo Carvalho de Melo 	 * using it if it is.
1629b7cece76SArnaldo Carvalho de Melo 	 */
1630b7cece76SArnaldo Carvalho de Melo 	if (self->has_build_id) {
1631b7cece76SArnaldo Carvalho de Melo 		u8 kallsyms_build_id[BUILD_ID_SIZE];
16329e201442SArnaldo Carvalho de Melo 		char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1633b7cece76SArnaldo Carvalho de Melo 
1634b7cece76SArnaldo Carvalho de Melo 		if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id,
16358d0591f6SArnaldo Carvalho de Melo 					 sizeof(kallsyms_build_id)) == 0) {
16369e201442SArnaldo Carvalho de Melo 			if (dso__build_id_equal(self, kallsyms_build_id)) {
16379e201442SArnaldo Carvalho de Melo 				kallsyms_filename = "/proc/kallsyms";
1638b7cece76SArnaldo Carvalho de Melo 				goto do_kallsyms;
16398d0591f6SArnaldo Carvalho de Melo 			}
16409e201442SArnaldo Carvalho de Melo 		}
1641dc8d6ab2SArnaldo Carvalho de Melo 		/*
1642dc8d6ab2SArnaldo Carvalho de Melo 		 * Now look if we have it on the build-id cache in
1643dc8d6ab2SArnaldo Carvalho de Melo 		 * $HOME/.debug/[kernel.kallsyms].
1644dc8d6ab2SArnaldo Carvalho de Melo 		 */
16459e201442SArnaldo Carvalho de Melo 		build_id__sprintf(self->build_id, sizeof(self->build_id),
16469e201442SArnaldo Carvalho de Melo 				  sbuild_id);
16479e201442SArnaldo Carvalho de Melo 
16489e201442SArnaldo Carvalho de Melo 		if (asprintf(&kallsyms_allocated_filename,
16499e201442SArnaldo Carvalho de Melo 			     "%s/.debug/[kernel.kallsyms]/%s",
1650dc8d6ab2SArnaldo Carvalho de Melo 			     getenv("HOME"), sbuild_id) == -1)
16518d0591f6SArnaldo Carvalho de Melo 			return -1;
16528d0591f6SArnaldo Carvalho de Melo 
1653dc8d6ab2SArnaldo Carvalho de Melo 		if (access(kallsyms_filename, F_OK)) {
16549e201442SArnaldo Carvalho de Melo 			free(kallsyms_allocated_filename);
1655dc8d6ab2SArnaldo Carvalho de Melo 			return -1;
1656ef6ae724SArnaldo Carvalho de Melo 		}
165786470930SIngo Molnar 
1658dc8d6ab2SArnaldo Carvalho de Melo 		kallsyms_filename = kallsyms_allocated_filename;
1659dc8d6ab2SArnaldo Carvalho de Melo 	} else {
1660dc8d6ab2SArnaldo Carvalho de Melo 		/*
1661dc8d6ab2SArnaldo Carvalho de Melo 		 * Last resort, if we don't have a build-id and couldn't find
1662dc8d6ab2SArnaldo Carvalho de Melo 		 * any vmlinux file, try the running kernel kallsyms table.
1663dc8d6ab2SArnaldo Carvalho de Melo 		 */
1664dc8d6ab2SArnaldo Carvalho de Melo 		kallsyms_filename = "/proc/kallsyms";
1665dc8d6ab2SArnaldo Carvalho de Melo 	}
1666dc8d6ab2SArnaldo Carvalho de Melo 
1667dc8d6ab2SArnaldo Carvalho de Melo do_kallsyms:
1668dc8d6ab2SArnaldo Carvalho de Melo 	err = dso__load_kallsyms(self, kallsyms_filename, map, session, filter);
1669dc8d6ab2SArnaldo Carvalho de Melo 	free(kallsyms_allocated_filename);
1670dc8d6ab2SArnaldo Carvalho de Melo 
1671dc8d6ab2SArnaldo Carvalho de Melo out_try_fixup:
1672439d473bSArnaldo Carvalho de Melo 	if (err > 0) {
1673cc612d81SArnaldo Carvalho de Melo out_fixup:
1674*e1c7c6a4SArnaldo Carvalho de Melo 		if (kallsyms_filename != NULL)
1675dc8d6ab2SArnaldo Carvalho de Melo 			dso__set_long_name(self, strdup("[kernel.kallsyms]"));
16766a4694a4SArnaldo Carvalho de Melo 		map__fixup_start(map);
16776a4694a4SArnaldo Carvalho de Melo 		map__fixup_end(map);
1678439d473bSArnaldo Carvalho de Melo 	}
167994cb9e38SArnaldo Carvalho de Melo 
168086470930SIngo Molnar 	return err;
168186470930SIngo Molnar }
168286470930SIngo Molnar 
1683b0da954aSArnaldo Carvalho de Melo LIST_HEAD(dsos__user);
1684b0da954aSArnaldo Carvalho de Melo LIST_HEAD(dsos__kernel);
1685cd84c2acSFrederic Weisbecker struct dso *vdso;
1686cd84c2acSFrederic Weisbecker 
1687b0da954aSArnaldo Carvalho de Melo static void dsos__add(struct list_head *head, struct dso *dso)
1688cd84c2acSFrederic Weisbecker {
1689b0da954aSArnaldo Carvalho de Melo 	list_add_tail(&dso->node, head);
1690cd84c2acSFrederic Weisbecker }
1691cd84c2acSFrederic Weisbecker 
1692b0da954aSArnaldo Carvalho de Melo static struct dso *dsos__find(struct list_head *head, const char *name)
1693cd84c2acSFrederic Weisbecker {
1694cd84c2acSFrederic Weisbecker 	struct dso *pos;
1695cd84c2acSFrederic Weisbecker 
1696b0da954aSArnaldo Carvalho de Melo 	list_for_each_entry(pos, head, node)
1697cf4e5b08SArnaldo Carvalho de Melo 		if (strcmp(pos->long_name, name) == 0)
1698cd84c2acSFrederic Weisbecker 			return pos;
1699cd84c2acSFrederic Weisbecker 	return NULL;
1700cd84c2acSFrederic Weisbecker }
1701cd84c2acSFrederic Weisbecker 
1702a89e5abeSArnaldo Carvalho de Melo struct dso *__dsos__findnew(struct list_head *head, const char *name)
1703cd84c2acSFrederic Weisbecker {
1704a89e5abeSArnaldo Carvalho de Melo 	struct dso *dso = dsos__find(head, name);
1705cd84c2acSFrederic Weisbecker 
1706e4204992SArnaldo Carvalho de Melo 	if (!dso) {
170700a192b3SArnaldo Carvalho de Melo 		dso = dso__new(name);
1708cfc10d3bSArnaldo Carvalho de Melo 		if (dso != NULL) {
1709a89e5abeSArnaldo Carvalho de Melo 			dsos__add(head, dso);
1710cfc10d3bSArnaldo Carvalho de Melo 			dso__set_basename(dso);
1711cfc10d3bSArnaldo Carvalho de Melo 		}
1712e4204992SArnaldo Carvalho de Melo 	}
1713cd84c2acSFrederic Weisbecker 
1714cd84c2acSFrederic Weisbecker 	return dso;
1715cd84c2acSFrederic Weisbecker }
1716cd84c2acSFrederic Weisbecker 
1717b0da954aSArnaldo Carvalho de Melo static void __dsos__fprintf(struct list_head *head, FILE *fp)
1718cd84c2acSFrederic Weisbecker {
1719cd84c2acSFrederic Weisbecker 	struct dso *pos;
1720cd84c2acSFrederic Weisbecker 
172195011c60SArnaldo Carvalho de Melo 	list_for_each_entry(pos, head, node) {
172295011c60SArnaldo Carvalho de Melo 		int i;
172395011c60SArnaldo Carvalho de Melo 		for (i = 0; i < MAP__NR_TYPES; ++i)
172495011c60SArnaldo Carvalho de Melo 			dso__fprintf(pos, i, fp);
172595011c60SArnaldo Carvalho de Melo 	}
1726cd84c2acSFrederic Weisbecker }
1727cd84c2acSFrederic Weisbecker 
1728b0da954aSArnaldo Carvalho de Melo void dsos__fprintf(FILE *fp)
1729b0da954aSArnaldo Carvalho de Melo {
1730b0da954aSArnaldo Carvalho de Melo 	__dsos__fprintf(&dsos__kernel, fp);
1731b0da954aSArnaldo Carvalho de Melo 	__dsos__fprintf(&dsos__user, fp);
1732b0da954aSArnaldo Carvalho de Melo }
1733b0da954aSArnaldo Carvalho de Melo 
173488d3d9b7SArnaldo Carvalho de Melo static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
173588d3d9b7SArnaldo Carvalho de Melo 				      bool with_hits)
17369e03eb2dSArnaldo Carvalho de Melo {
17379e03eb2dSArnaldo Carvalho de Melo 	struct dso *pos;
17389e03eb2dSArnaldo Carvalho de Melo 	size_t ret = 0;
17399e03eb2dSArnaldo Carvalho de Melo 
1740b0da954aSArnaldo Carvalho de Melo 	list_for_each_entry(pos, head, node) {
174188d3d9b7SArnaldo Carvalho de Melo 		if (with_hits && !pos->hit)
174288d3d9b7SArnaldo Carvalho de Melo 			continue;
17439e03eb2dSArnaldo Carvalho de Melo 		ret += dso__fprintf_buildid(pos, fp);
17449e03eb2dSArnaldo Carvalho de Melo 		ret += fprintf(fp, " %s\n", pos->long_name);
17459e03eb2dSArnaldo Carvalho de Melo 	}
17469e03eb2dSArnaldo Carvalho de Melo 	return ret;
17479e03eb2dSArnaldo Carvalho de Melo }
17489e03eb2dSArnaldo Carvalho de Melo 
174988d3d9b7SArnaldo Carvalho de Melo size_t dsos__fprintf_buildid(FILE *fp, bool with_hits)
1750b0da954aSArnaldo Carvalho de Melo {
175188d3d9b7SArnaldo Carvalho de Melo 	return (__dsos__fprintf_buildid(&dsos__kernel, fp, with_hits) +
175288d3d9b7SArnaldo Carvalho de Melo 		__dsos__fprintf_buildid(&dsos__user, fp, with_hits));
1753b0da954aSArnaldo Carvalho de Melo }
1754b0da954aSArnaldo Carvalho de Melo 
1755f1dfa0b1SArnaldo Carvalho de Melo static struct dso *dsos__create_kernel(const char *vmlinux)
1756cd84c2acSFrederic Weisbecker {
175795011c60SArnaldo Carvalho de Melo 	struct dso *kernel = dso__new(vmlinux ?: "[kernel.kallsyms]");
1758cd84c2acSFrederic Weisbecker 
17592446042cSArnaldo Carvalho de Melo 	if (kernel == NULL)
1760f1dfa0b1SArnaldo Carvalho de Melo 		return NULL;
1761c338aee8SArnaldo Carvalho de Melo 
17622446042cSArnaldo Carvalho de Melo 	kernel->short_name = "[kernel]";
1763c338aee8SArnaldo Carvalho de Melo 	kernel->kernel	   = 1;
1764cc612d81SArnaldo Carvalho de Melo 
176500a192b3SArnaldo Carvalho de Melo 	vdso = dso__new("[vdso]");
1766c338aee8SArnaldo Carvalho de Melo 	if (vdso == NULL)
1767f1dfa0b1SArnaldo Carvalho de Melo 		goto out_delete_kernel_dso;
17683610583cSArnaldo Carvalho de Melo 	dso__set_loaded(vdso, MAP__FUNCTION);
1769cd84c2acSFrederic Weisbecker 
17702446042cSArnaldo Carvalho de Melo 	if (sysfs__read_build_id("/sys/kernel/notes", kernel->build_id,
17712446042cSArnaldo Carvalho de Melo 				 sizeof(kernel->build_id)) == 0)
17722446042cSArnaldo Carvalho de Melo 		kernel->has_build_id = true;
17732446042cSArnaldo Carvalho de Melo 
1774b0da954aSArnaldo Carvalho de Melo 	dsos__add(&dsos__kernel, kernel);
1775b0da954aSArnaldo Carvalho de Melo 	dsos__add(&dsos__user, vdso);
1776cd84c2acSFrederic Weisbecker 
1777f1dfa0b1SArnaldo Carvalho de Melo 	return kernel;
1778c338aee8SArnaldo Carvalho de Melo 
1779c338aee8SArnaldo Carvalho de Melo out_delete_kernel_dso:
1780c338aee8SArnaldo Carvalho de Melo 	dso__delete(kernel);
1781f1dfa0b1SArnaldo Carvalho de Melo 	return NULL;
1782f1dfa0b1SArnaldo Carvalho de Melo }
1783f1dfa0b1SArnaldo Carvalho de Melo 
1784b7cece76SArnaldo Carvalho de Melo int __map_groups__create_kernel_maps(struct map_groups *self,
1785de176489SArnaldo Carvalho de Melo 				     struct map *vmlinux_maps[MAP__NR_TYPES],
1786b7cece76SArnaldo Carvalho de Melo 				     struct dso *kernel)
1787f1dfa0b1SArnaldo Carvalho de Melo {
1788de176489SArnaldo Carvalho de Melo 	enum map_type type;
1789f1dfa0b1SArnaldo Carvalho de Melo 
1790de176489SArnaldo Carvalho de Melo 	for (type = 0; type < MAP__NR_TYPES; ++type) {
1791de176489SArnaldo Carvalho de Melo 		vmlinux_maps[type] = map__new2(0, kernel, type);
1792de176489SArnaldo Carvalho de Melo 		if (vmlinux_maps[type] == NULL)
1793f1dfa0b1SArnaldo Carvalho de Melo 			return -1;
1794f1dfa0b1SArnaldo Carvalho de Melo 
1795de176489SArnaldo Carvalho de Melo 		vmlinux_maps[type]->map_ip =
1796de176489SArnaldo Carvalho de Melo 			vmlinux_maps[type]->unmap_ip = identity__map_ip;
1797de176489SArnaldo Carvalho de Melo 		map_groups__insert(self, vmlinux_maps[type]);
1798f1dfa0b1SArnaldo Carvalho de Melo 	}
1799f1dfa0b1SArnaldo Carvalho de Melo 
1800f1dfa0b1SArnaldo Carvalho de Melo 	return 0;
18012446042cSArnaldo Carvalho de Melo }
18022446042cSArnaldo Carvalho de Melo 
1803b7cece76SArnaldo Carvalho de Melo static int map_groups__create_kernel_maps(struct map_groups *self,
1804b7cece76SArnaldo Carvalho de Melo 					  struct map *vmlinux_maps[MAP__NR_TYPES],
1805b7cece76SArnaldo Carvalho de Melo 					  const char *vmlinux)
1806b7cece76SArnaldo Carvalho de Melo {
1807b7cece76SArnaldo Carvalho de Melo 	struct dso *kernel = dsos__create_kernel(vmlinux);
1808b7cece76SArnaldo Carvalho de Melo 
1809b7cece76SArnaldo Carvalho de Melo 	if (kernel == NULL)
1810b7cece76SArnaldo Carvalho de Melo 		return -1;
1811b7cece76SArnaldo Carvalho de Melo 
1812b7cece76SArnaldo Carvalho de Melo 	return __map_groups__create_kernel_maps(self, vmlinux_maps, kernel);
1813b7cece76SArnaldo Carvalho de Melo }
1814b7cece76SArnaldo Carvalho de Melo 
1815cc612d81SArnaldo Carvalho de Melo static void vmlinux_path__exit(void)
18162446042cSArnaldo Carvalho de Melo {
1817cc612d81SArnaldo Carvalho de Melo 	while (--vmlinux_path__nr_entries >= 0) {
1818cc612d81SArnaldo Carvalho de Melo 		free(vmlinux_path[vmlinux_path__nr_entries]);
1819cc612d81SArnaldo Carvalho de Melo 		vmlinux_path[vmlinux_path__nr_entries] = NULL;
1820cc612d81SArnaldo Carvalho de Melo 	}
1821cc612d81SArnaldo Carvalho de Melo 
1822cc612d81SArnaldo Carvalho de Melo 	free(vmlinux_path);
1823cc612d81SArnaldo Carvalho de Melo 	vmlinux_path = NULL;
1824cc612d81SArnaldo Carvalho de Melo }
1825cc612d81SArnaldo Carvalho de Melo 
1826cc612d81SArnaldo Carvalho de Melo static int vmlinux_path__init(void)
1827cc612d81SArnaldo Carvalho de Melo {
1828cc612d81SArnaldo Carvalho de Melo 	struct utsname uts;
1829cc612d81SArnaldo Carvalho de Melo 	char bf[PATH_MAX];
1830cc612d81SArnaldo Carvalho de Melo 
1831cc612d81SArnaldo Carvalho de Melo 	if (uname(&uts) < 0)
18322446042cSArnaldo Carvalho de Melo 		return -1;
18332446042cSArnaldo Carvalho de Melo 
1834cc612d81SArnaldo Carvalho de Melo 	vmlinux_path = malloc(sizeof(char *) * 5);
1835cc612d81SArnaldo Carvalho de Melo 	if (vmlinux_path == NULL)
1836cc612d81SArnaldo Carvalho de Melo 		return -1;
1837cc612d81SArnaldo Carvalho de Melo 
1838cc612d81SArnaldo Carvalho de Melo 	vmlinux_path[vmlinux_path__nr_entries] = strdup("vmlinux");
1839cc612d81SArnaldo Carvalho de Melo 	if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1840cc612d81SArnaldo Carvalho de Melo 		goto out_fail;
1841cc612d81SArnaldo Carvalho de Melo 	++vmlinux_path__nr_entries;
1842cc612d81SArnaldo Carvalho de Melo 	vmlinux_path[vmlinux_path__nr_entries] = strdup("/boot/vmlinux");
1843cc612d81SArnaldo Carvalho de Melo 	if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1844cc612d81SArnaldo Carvalho de Melo 		goto out_fail;
1845cc612d81SArnaldo Carvalho de Melo 	++vmlinux_path__nr_entries;
1846cc612d81SArnaldo Carvalho de Melo 	snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);
1847cc612d81SArnaldo Carvalho de Melo 	vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1848cc612d81SArnaldo Carvalho de Melo 	if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1849cc612d81SArnaldo Carvalho de Melo 		goto out_fail;
1850cc612d81SArnaldo Carvalho de Melo 	++vmlinux_path__nr_entries;
1851cc612d81SArnaldo Carvalho de Melo 	snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release);
1852cc612d81SArnaldo Carvalho de Melo 	vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1853cc612d81SArnaldo Carvalho de Melo 	if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1854cc612d81SArnaldo Carvalho de Melo 		goto out_fail;
1855cc612d81SArnaldo Carvalho de Melo 	++vmlinux_path__nr_entries;
1856cc612d81SArnaldo Carvalho de Melo 	snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux",
1857cc612d81SArnaldo Carvalho de Melo 		 uts.release);
1858cc612d81SArnaldo Carvalho de Melo 	vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1859cc612d81SArnaldo Carvalho de Melo 	if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1860cc612d81SArnaldo Carvalho de Melo 		goto out_fail;
1861cc612d81SArnaldo Carvalho de Melo 	++vmlinux_path__nr_entries;
1862cc612d81SArnaldo Carvalho de Melo 
1863cc612d81SArnaldo Carvalho de Melo 	return 0;
1864cc612d81SArnaldo Carvalho de Melo 
1865cc612d81SArnaldo Carvalho de Melo out_fail:
1866cc612d81SArnaldo Carvalho de Melo 	vmlinux_path__exit();
1867cc612d81SArnaldo Carvalho de Melo 	return -1;
1868cc612d81SArnaldo Carvalho de Melo }
1869cc612d81SArnaldo Carvalho de Melo 
1870655000e7SArnaldo Carvalho de Melo static int setup_list(struct strlist **list, const char *list_str,
1871655000e7SArnaldo Carvalho de Melo 		      const char *list_name)
1872655000e7SArnaldo Carvalho de Melo {
1873655000e7SArnaldo Carvalho de Melo 	if (list_str == NULL)
1874655000e7SArnaldo Carvalho de Melo 		return 0;
1875655000e7SArnaldo Carvalho de Melo 
1876655000e7SArnaldo Carvalho de Melo 	*list = strlist__new(true, list_str);
1877655000e7SArnaldo Carvalho de Melo 	if (!*list) {
1878655000e7SArnaldo Carvalho de Melo 		pr_err("problems parsing %s list\n", list_name);
1879655000e7SArnaldo Carvalho de Melo 		return -1;
1880655000e7SArnaldo Carvalho de Melo 	}
1881655000e7SArnaldo Carvalho de Melo 	return 0;
1882655000e7SArnaldo Carvalho de Melo }
1883655000e7SArnaldo Carvalho de Melo 
188475be6cf4SArnaldo Carvalho de Melo int symbol__init(void)
1885cc612d81SArnaldo Carvalho de Melo {
188695011c60SArnaldo Carvalho de Melo 	elf_version(EV_CURRENT);
188775be6cf4SArnaldo Carvalho de Melo 	if (symbol_conf.sort_by_name)
188875be6cf4SArnaldo Carvalho de Melo 		symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
188979406cd7SArnaldo Carvalho de Melo 					  sizeof(struct symbol));
1890b32d133aSArnaldo Carvalho de Melo 
189175be6cf4SArnaldo Carvalho de Melo 	if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0)
1892cc612d81SArnaldo Carvalho de Melo 		return -1;
1893cc612d81SArnaldo Carvalho de Melo 
1894c410a338SArnaldo Carvalho de Melo 	if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') {
1895c410a338SArnaldo Carvalho de Melo 		pr_err("'.' is the only non valid --field-separator argument\n");
1896c410a338SArnaldo Carvalho de Melo 		return -1;
1897c410a338SArnaldo Carvalho de Melo 	}
1898c410a338SArnaldo Carvalho de Melo 
1899655000e7SArnaldo Carvalho de Melo 	if (setup_list(&symbol_conf.dso_list,
1900655000e7SArnaldo Carvalho de Melo 		       symbol_conf.dso_list_str, "dso") < 0)
1901655000e7SArnaldo Carvalho de Melo 		return -1;
1902655000e7SArnaldo Carvalho de Melo 
1903655000e7SArnaldo Carvalho de Melo 	if (setup_list(&symbol_conf.comm_list,
1904655000e7SArnaldo Carvalho de Melo 		       symbol_conf.comm_list_str, "comm") < 0)
1905655000e7SArnaldo Carvalho de Melo 		goto out_free_dso_list;
1906655000e7SArnaldo Carvalho de Melo 
1907655000e7SArnaldo Carvalho de Melo 	if (setup_list(&symbol_conf.sym_list,
1908655000e7SArnaldo Carvalho de Melo 		       symbol_conf.sym_list_str, "symbol") < 0)
1909655000e7SArnaldo Carvalho de Melo 		goto out_free_comm_list;
1910655000e7SArnaldo Carvalho de Melo 
19114aa65636SArnaldo Carvalho de Melo 	return 0;
1912655000e7SArnaldo Carvalho de Melo 
1913655000e7SArnaldo Carvalho de Melo out_free_dso_list:
1914655000e7SArnaldo Carvalho de Melo 	strlist__delete(symbol_conf.dso_list);
1915655000e7SArnaldo Carvalho de Melo out_free_comm_list:
1916655000e7SArnaldo Carvalho de Melo 	strlist__delete(symbol_conf.comm_list);
1917655000e7SArnaldo Carvalho de Melo 	return -1;
1918cc612d81SArnaldo Carvalho de Melo }
1919cc612d81SArnaldo Carvalho de Melo 
192075be6cf4SArnaldo Carvalho de Melo int perf_session__create_kernel_maps(struct perf_session *self)
19214aa65636SArnaldo Carvalho de Melo {
1922de176489SArnaldo Carvalho de Melo 	if (map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps,
192375be6cf4SArnaldo Carvalho de Melo 					   symbol_conf.vmlinux_name) < 0)
19244aa65636SArnaldo Carvalho de Melo 		return -1;
19254aa65636SArnaldo Carvalho de Melo 
192675be6cf4SArnaldo Carvalho de Melo 	if (symbol_conf.use_modules &&
192775be6cf4SArnaldo Carvalho de Melo 	    perf_session__create_module_maps(self) < 0)
19284aa65636SArnaldo Carvalho de Melo 		pr_debug("Failed to load list of modules for session %s, "
19294aa65636SArnaldo Carvalho de Melo 			 "continuing...\n", self->filename);
193090c83218SArnaldo Carvalho de Melo 	/*
193190c83218SArnaldo Carvalho de Melo 	 * Now that we have all the maps created, just set the ->end of them:
193290c83218SArnaldo Carvalho de Melo 	 */
19334aa65636SArnaldo Carvalho de Melo 	map_groups__fixup_end(&self->kmaps);
19346671cb16SArnaldo Carvalho de Melo 	return 0;
1935cd84c2acSFrederic Weisbecker }
1936