• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "symbol.h"
2 #include <errno.h>
3 #include <inttypes.h>
4 #include <limits.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include "map.h"
10 
11 const char *map_type__name[MAP__NR_TYPES] = {
12 	[MAP__FUNCTION] = "Functions",
13 	[MAP__VARIABLE] = "Variables",
14 };
15 
is_anon_memory(const char * filename)16 static inline int is_anon_memory(const char *filename)
17 {
18 	return strcmp(filename, "//anon") == 0;
19 }
20 
map__init(struct map * self,enum map_type type,u64 start,u64 end,u64 pgoff,struct dso * dso)21 void map__init(struct map *self, enum map_type type,
22 	       u64 start, u64 end, u64 pgoff, struct dso *dso)
23 {
24 	self->type     = type;
25 	self->start    = start;
26 	self->end      = end;
27 	self->pgoff    = pgoff;
28 	self->dso      = dso;
29 	self->map_ip   = map__map_ip;
30 	self->unmap_ip = map__unmap_ip;
31 	RB_CLEAR_NODE(&self->rb_node);
32 	self->groups   = NULL;
33 	self->referenced = false;
34 }
35 
map__new(struct list_head * dsos__list,u64 start,u64 len,u64 pgoff,u32 pid,char * filename,enum map_type type)36 struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
37 		     u64 pgoff, u32 pid, char *filename,
38 		     enum map_type type)
39 {
40 	struct map *self = malloc(sizeof(*self));
41 
42 	if (self != NULL) {
43 		char newfilename[PATH_MAX];
44 		struct dso *dso;
45 		int anon;
46 
47 		anon = is_anon_memory(filename);
48 
49 		if (anon) {
50 			snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
51 			filename = newfilename;
52 		}
53 
54 		dso = __dsos__findnew(dsos__list, filename);
55 		if (dso == NULL)
56 			goto out_delete;
57 
58 		map__init(self, type, start, start + len, pgoff, dso);
59 
60 		if (anon) {
61 set_identity:
62 			self->map_ip = self->unmap_ip = identity__map_ip;
63 		} else if (strcmp(filename, "[vdso]") == 0) {
64 			dso__set_loaded(dso, self->type);
65 			goto set_identity;
66 		}
67 	}
68 	return self;
69 out_delete:
70 	free(self);
71 	return NULL;
72 }
73 
map__delete(struct map * self)74 void map__delete(struct map *self)
75 {
76 	free(self);
77 }
78 
map__fixup_start(struct map * self)79 void map__fixup_start(struct map *self)
80 {
81 	struct rb_root *symbols = &self->dso->symbols[self->type];
82 	struct rb_node *nd = rb_first(symbols);
83 	if (nd != NULL) {
84 		struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
85 		self->start = sym->start;
86 	}
87 }
88 
map__fixup_end(struct map * self)89 void map__fixup_end(struct map *self)
90 {
91 	struct rb_root *symbols = &self->dso->symbols[self->type];
92 	struct rb_node *nd = rb_last(symbols);
93 	if (nd != NULL) {
94 		struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
95 		self->end = sym->end;
96 	}
97 }
98 
99 #define DSO__DELETED "(deleted)"
100 
map__load(struct map * self,symbol_filter_t filter)101 int map__load(struct map *self, symbol_filter_t filter)
102 {
103 	const char *name = self->dso->long_name;
104 	int nr;
105 
106 	if (dso__loaded(self->dso, self->type))
107 		return 0;
108 
109 	nr = dso__load(self->dso, self, filter);
110 	if (nr < 0) {
111 		if (self->dso->has_build_id) {
112 			char sbuild_id[BUILD_ID_SIZE * 2 + 1];
113 
114 			build_id__sprintf(self->dso->build_id,
115 					  sizeof(self->dso->build_id),
116 					  sbuild_id);
117 			pr_warning("%s with build id %s not found",
118 				   name, sbuild_id);
119 		} else
120 			pr_warning("Failed to open %s", name);
121 
122 		pr_warning(", continuing without symbols\n");
123 		return -1;
124 	} else if (nr == 0) {
125 		const size_t len = strlen(name);
126 		const size_t real_len = len - sizeof(DSO__DELETED);
127 
128 		if (len > sizeof(DSO__DELETED) &&
129 		    strcmp(name + real_len + 1, DSO__DELETED) == 0) {
130 			pr_warning("%.*s was updated, restart the long "
131 				   "running apps that use it!\n",
132 				   (int)real_len, name);
133 		} else {
134 			pr_warning("no symbols found in %s, maybe install "
135 				   "a debug package?\n", name);
136 		}
137 
138 		return -1;
139 	}
140 	/*
141 	 * Only applies to the kernel, as its symtabs aren't relative like the
142 	 * module ones.
143 	 */
144 	if (self->dso->kernel)
145 		map__reloc_vmlinux(self);
146 
147 	return 0;
148 }
149 
map__find_symbol(struct map * self,u64 addr,symbol_filter_t filter)150 struct symbol *map__find_symbol(struct map *self, u64 addr,
151 				symbol_filter_t filter)
152 {
153 	if (map__load(self, filter) < 0)
154 		return NULL;
155 
156 	return dso__find_symbol(self->dso, self->type, addr);
157 }
158 
map__find_symbol_by_name(struct map * self,const char * name,symbol_filter_t filter)159 struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
160 					symbol_filter_t filter)
161 {
162 	if (map__load(self, filter) < 0)
163 		return NULL;
164 
165 	if (!dso__sorted_by_name(self->dso, self->type))
166 		dso__sort_by_name(self->dso, self->type);
167 
168 	return dso__find_symbol_by_name(self->dso, self->type, name);
169 }
170 
map__clone(struct map * self)171 struct map *map__clone(struct map *self)
172 {
173 	struct map *map = malloc(sizeof(*self));
174 
175 	if (!map)
176 		return NULL;
177 
178 	memcpy(map, self, sizeof(*self));
179 
180 	return map;
181 }
182 
map__overlap(struct map * l,struct map * r)183 int map__overlap(struct map *l, struct map *r)
184 {
185 	if (l->start > r->start) {
186 		struct map *t = l;
187 		l = r;
188 		r = t;
189 	}
190 
191 	if (l->end > r->start)
192 		return 1;
193 
194 	return 0;
195 }
196 
map__fprintf(struct map * self,FILE * fp)197 size_t map__fprintf(struct map *self, FILE *fp)
198 {
199 	return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n",
200 		       self->start, self->end, self->pgoff, self->dso->name);
201 }
202 
203 /*
204  * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
205  * map->dso->adjust_symbols==1 for ET_EXEC-like cases.
206  */
map__rip_2objdump(struct map * map,u64 rip)207 u64 map__rip_2objdump(struct map *map, u64 rip)
208 {
209 	u64 addr = map->dso->adjust_symbols ?
210 			map->unmap_ip(map, rip) :	/* RIP -> IP */
211 			rip;
212 	return addr;
213 }
214 
map__objdump_2ip(struct map * map,u64 addr)215 u64 map__objdump_2ip(struct map *map, u64 addr)
216 {
217 	u64 ip = map->dso->adjust_symbols ?
218 			addr :
219 			map->unmap_ip(map, addr);	/* RIP -> IP */
220 	return ip;
221 }
222 
map_groups__init(struct map_groups * self)223 void map_groups__init(struct map_groups *self)
224 {
225 	int i;
226 	for (i = 0; i < MAP__NR_TYPES; ++i) {
227 		self->maps[i] = RB_ROOT;
228 		INIT_LIST_HEAD(&self->removed_maps[i]);
229 	}
230 	self->machine = NULL;
231 }
232 
maps__delete(struct rb_root * self)233 static void maps__delete(struct rb_root *self)
234 {
235 	struct rb_node *next = rb_first(self);
236 
237 	while (next) {
238 		struct map *pos = rb_entry(next, struct map, rb_node);
239 
240 		next = rb_next(&pos->rb_node);
241 		rb_erase(&pos->rb_node, self);
242 		map__delete(pos);
243 	}
244 }
245 
maps__delete_removed(struct list_head * self)246 static void maps__delete_removed(struct list_head *self)
247 {
248 	struct map *pos, *n;
249 
250 	list_for_each_entry_safe(pos, n, self, node) {
251 		list_del(&pos->node);
252 		map__delete(pos);
253 	}
254 }
255 
map_groups__exit(struct map_groups * self)256 void map_groups__exit(struct map_groups *self)
257 {
258 	int i;
259 
260 	for (i = 0; i < MAP__NR_TYPES; ++i) {
261 		maps__delete(&self->maps[i]);
262 		maps__delete_removed(&self->removed_maps[i]);
263 	}
264 }
265 
map_groups__flush(struct map_groups * self)266 void map_groups__flush(struct map_groups *self)
267 {
268 	int type;
269 
270 	for (type = 0; type < MAP__NR_TYPES; type++) {
271 		struct rb_root *root = &self->maps[type];
272 		struct rb_node *next = rb_first(root);
273 
274 		while (next) {
275 			struct map *pos = rb_entry(next, struct map, rb_node);
276 			next = rb_next(&pos->rb_node);
277 			rb_erase(&pos->rb_node, root);
278 			/*
279 			 * We may have references to this map, for
280 			 * instance in some hist_entry instances, so
281 			 * just move them to a separate list.
282 			 */
283 			list_add_tail(&pos->node, &self->removed_maps[pos->type]);
284 		}
285 	}
286 }
287 
map_groups__find_symbol(struct map_groups * self,enum map_type type,u64 addr,struct map ** mapp,symbol_filter_t filter)288 struct symbol *map_groups__find_symbol(struct map_groups *self,
289 				       enum map_type type, u64 addr,
290 				       struct map **mapp,
291 				       symbol_filter_t filter)
292 {
293 	struct map *map = map_groups__find(self, type, addr);
294 
295 	if (map != NULL) {
296 		if (mapp != NULL)
297 			*mapp = map;
298 		return map__find_symbol(map, map->map_ip(map, addr), filter);
299 	}
300 
301 	return NULL;
302 }
303 
map_groups__find_symbol_by_name(struct map_groups * self,enum map_type type,const char * name,struct map ** mapp,symbol_filter_t filter)304 struct symbol *map_groups__find_symbol_by_name(struct map_groups *self,
305 					       enum map_type type,
306 					       const char *name,
307 					       struct map **mapp,
308 					       symbol_filter_t filter)
309 {
310 	struct rb_node *nd;
311 
312 	for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
313 		struct map *pos = rb_entry(nd, struct map, rb_node);
314 		struct symbol *sym = map__find_symbol_by_name(pos, name, filter);
315 
316 		if (sym == NULL)
317 			continue;
318 		if (mapp != NULL)
319 			*mapp = pos;
320 		return sym;
321 	}
322 
323 	return NULL;
324 }
325 
__map_groups__fprintf_maps(struct map_groups * self,enum map_type type,int verbose,FILE * fp)326 size_t __map_groups__fprintf_maps(struct map_groups *self,
327 				  enum map_type type, int verbose, FILE *fp)
328 {
329 	size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
330 	struct rb_node *nd;
331 
332 	for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
333 		struct map *pos = rb_entry(nd, struct map, rb_node);
334 		printed += fprintf(fp, "Map:");
335 		printed += map__fprintf(pos, fp);
336 		if (verbose > 2) {
337 			printed += dso__fprintf(pos->dso, type, fp);
338 			printed += fprintf(fp, "--\n");
339 		}
340 	}
341 
342 	return printed;
343 }
344 
map_groups__fprintf_maps(struct map_groups * self,int verbose,FILE * fp)345 size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp)
346 {
347 	size_t printed = 0, i;
348 	for (i = 0; i < MAP__NR_TYPES; ++i)
349 		printed += __map_groups__fprintf_maps(self, i, verbose, fp);
350 	return printed;
351 }
352 
__map_groups__fprintf_removed_maps(struct map_groups * self,enum map_type type,int verbose,FILE * fp)353 static size_t __map_groups__fprintf_removed_maps(struct map_groups *self,
354 						 enum map_type type,
355 						 int verbose, FILE *fp)
356 {
357 	struct map *pos;
358 	size_t printed = 0;
359 
360 	list_for_each_entry(pos, &self->removed_maps[type], node) {
361 		printed += fprintf(fp, "Map:");
362 		printed += map__fprintf(pos, fp);
363 		if (verbose > 1) {
364 			printed += dso__fprintf(pos->dso, type, fp);
365 			printed += fprintf(fp, "--\n");
366 		}
367 	}
368 	return printed;
369 }
370 
map_groups__fprintf_removed_maps(struct map_groups * self,int verbose,FILE * fp)371 static size_t map_groups__fprintf_removed_maps(struct map_groups *self,
372 					       int verbose, FILE *fp)
373 {
374 	size_t printed = 0, i;
375 	for (i = 0; i < MAP__NR_TYPES; ++i)
376 		printed += __map_groups__fprintf_removed_maps(self, i, verbose, fp);
377 	return printed;
378 }
379 
map_groups__fprintf(struct map_groups * self,int verbose,FILE * fp)380 size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp)
381 {
382 	size_t printed = map_groups__fprintf_maps(self, verbose, fp);
383 	printed += fprintf(fp, "Removed maps:\n");
384 	return printed + map_groups__fprintf_removed_maps(self, verbose, fp);
385 }
386 
map_groups__fixup_overlappings(struct map_groups * self,struct map * map,int verbose,FILE * fp)387 int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
388 				   int verbose, FILE *fp)
389 {
390 	struct rb_root *root = &self->maps[map->type];
391 	struct rb_node *next = rb_first(root);
392 	int err = 0;
393 
394 	while (next) {
395 		struct map *pos = rb_entry(next, struct map, rb_node);
396 		next = rb_next(&pos->rb_node);
397 
398 		if (!map__overlap(pos, map))
399 			continue;
400 
401 		if (verbose >= 2) {
402 			fputs("overlapping maps:\n", fp);
403 			map__fprintf(map, fp);
404 			map__fprintf(pos, fp);
405 		}
406 
407 		rb_erase(&pos->rb_node, root);
408 		/*
409 		 * Now check if we need to create new maps for areas not
410 		 * overlapped by the new map:
411 		 */
412 		if (map->start > pos->start) {
413 			struct map *before = map__clone(pos);
414 
415 			if (before == NULL) {
416 				err = -ENOMEM;
417 				goto move_map;
418 			}
419 
420 			before->end = map->start - 1;
421 			map_groups__insert(self, before);
422 			if (verbose >= 2)
423 				map__fprintf(before, fp);
424 		}
425 
426 		if (map->end < pos->end) {
427 			struct map *after = map__clone(pos);
428 
429 			if (after == NULL) {
430 				err = -ENOMEM;
431 				goto move_map;
432 			}
433 
434 			after->start = map->end + 1;
435 			map_groups__insert(self, after);
436 			if (verbose >= 2)
437 				map__fprintf(after, fp);
438 		}
439 move_map:
440 		/*
441 		 * If we have references, just move them to a separate list.
442 		 */
443 		if (pos->referenced)
444 			list_add_tail(&pos->node, &self->removed_maps[map->type]);
445 		else
446 			map__delete(pos);
447 
448 		if (err)
449 			return err;
450 	}
451 
452 	return 0;
453 }
454 
455 /*
456  * XXX This should not really _copy_ te maps, but refcount them.
457  */
map_groups__clone(struct map_groups * self,struct map_groups * parent,enum map_type type)458 int map_groups__clone(struct map_groups *self,
459 		      struct map_groups *parent, enum map_type type)
460 {
461 	struct rb_node *nd;
462 	for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) {
463 		struct map *map = rb_entry(nd, struct map, rb_node);
464 		struct map *new = map__clone(map);
465 		if (new == NULL)
466 			return -ENOMEM;
467 		map_groups__insert(self, new);
468 	}
469 	return 0;
470 }
471 
map__reloc_map_ip(struct map * map,u64 ip)472 static u64 map__reloc_map_ip(struct map *map, u64 ip)
473 {
474 	return ip + (s64)map->pgoff;
475 }
476 
map__reloc_unmap_ip(struct map * map,u64 ip)477 static u64 map__reloc_unmap_ip(struct map *map, u64 ip)
478 {
479 	return ip - (s64)map->pgoff;
480 }
481 
map__reloc_vmlinux(struct map * self)482 void map__reloc_vmlinux(struct map *self)
483 {
484 	struct kmap *kmap = map__kmap(self);
485 	s64 reloc;
486 
487 	if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->unrelocated_addr)
488 		return;
489 
490 	reloc = (kmap->ref_reloc_sym->unrelocated_addr -
491 		 kmap->ref_reloc_sym->addr);
492 
493 	if (!reloc)
494 		return;
495 
496 	self->map_ip   = map__reloc_map_ip;
497 	self->unmap_ip = map__reloc_unmap_ip;
498 	self->pgoff    = reloc;
499 }
500 
maps__insert(struct rb_root * maps,struct map * map)501 void maps__insert(struct rb_root *maps, struct map *map)
502 {
503 	struct rb_node **p = &maps->rb_node;
504 	struct rb_node *parent = NULL;
505 	const u64 ip = map->start;
506 	struct map *m;
507 
508 	while (*p != NULL) {
509 		parent = *p;
510 		m = rb_entry(parent, struct map, rb_node);
511 		if (ip < m->start)
512 			p = &(*p)->rb_left;
513 		else
514 			p = &(*p)->rb_right;
515 	}
516 
517 	rb_link_node(&map->rb_node, parent, p);
518 	rb_insert_color(&map->rb_node, maps);
519 }
520 
maps__remove(struct rb_root * self,struct map * map)521 void maps__remove(struct rb_root *self, struct map *map)
522 {
523 	rb_erase(&map->rb_node, self);
524 }
525 
maps__find(struct rb_root * maps,u64 ip)526 struct map *maps__find(struct rb_root *maps, u64 ip)
527 {
528 	struct rb_node **p = &maps->rb_node;
529 	struct rb_node *parent = NULL;
530 	struct map *m;
531 
532 	while (*p != NULL) {
533 		parent = *p;
534 		m = rb_entry(parent, struct map, rb_node);
535 		if (ip < m->start)
536 			p = &(*p)->rb_left;
537 		else if (ip > m->end)
538 			p = &(*p)->rb_right;
539 		else
540 			return m;
541 	}
542 
543 	return NULL;
544 }
545 
machine__init(struct machine * self,const char * root_dir,pid_t pid)546 int machine__init(struct machine *self, const char *root_dir, pid_t pid)
547 {
548 	map_groups__init(&self->kmaps);
549 	RB_CLEAR_NODE(&self->rb_node);
550 	INIT_LIST_HEAD(&self->user_dsos);
551 	INIT_LIST_HEAD(&self->kernel_dsos);
552 
553 	self->kmaps.machine = self;
554 	self->pid	    = pid;
555 	self->root_dir      = strdup(root_dir);
556 	return self->root_dir == NULL ? -ENOMEM : 0;
557 }
558 
dsos__delete(struct list_head * self)559 static void dsos__delete(struct list_head *self)
560 {
561 	struct dso *pos, *n;
562 
563 	list_for_each_entry_safe(pos, n, self, node) {
564 		list_del(&pos->node);
565 		dso__delete(pos);
566 	}
567 }
568 
machine__exit(struct machine * self)569 void machine__exit(struct machine *self)
570 {
571 	map_groups__exit(&self->kmaps);
572 	dsos__delete(&self->user_dsos);
573 	dsos__delete(&self->kernel_dsos);
574 	free(self->root_dir);
575 	self->root_dir = NULL;
576 }
577 
machine__delete(struct machine * self)578 void machine__delete(struct machine *self)
579 {
580 	machine__exit(self);
581 	free(self);
582 }
583 
machines__add(struct rb_root * self,pid_t pid,const char * root_dir)584 struct machine *machines__add(struct rb_root *self, pid_t pid,
585 			      const char *root_dir)
586 {
587 	struct rb_node **p = &self->rb_node;
588 	struct rb_node *parent = NULL;
589 	struct machine *pos, *machine = malloc(sizeof(*machine));
590 
591 	if (!machine)
592 		return NULL;
593 
594 	if (machine__init(machine, root_dir, pid) != 0) {
595 		free(machine);
596 		return NULL;
597 	}
598 
599 	while (*p != NULL) {
600 		parent = *p;
601 		pos = rb_entry(parent, struct machine, rb_node);
602 		if (pid < pos->pid)
603 			p = &(*p)->rb_left;
604 		else
605 			p = &(*p)->rb_right;
606 	}
607 
608 	rb_link_node(&machine->rb_node, parent, p);
609 	rb_insert_color(&machine->rb_node, self);
610 
611 	return machine;
612 }
613 
machines__find(struct rb_root * self,pid_t pid)614 struct machine *machines__find(struct rb_root *self, pid_t pid)
615 {
616 	struct rb_node **p = &self->rb_node;
617 	struct rb_node *parent = NULL;
618 	struct machine *machine;
619 	struct machine *default_machine = NULL;
620 
621 	while (*p != NULL) {
622 		parent = *p;
623 		machine = rb_entry(parent, struct machine, rb_node);
624 		if (pid < machine->pid)
625 			p = &(*p)->rb_left;
626 		else if (pid > machine->pid)
627 			p = &(*p)->rb_right;
628 		else
629 			return machine;
630 		if (!machine->pid)
631 			default_machine = machine;
632 	}
633 
634 	return default_machine;
635 }
636 
machines__findnew(struct rb_root * self,pid_t pid)637 struct machine *machines__findnew(struct rb_root *self, pid_t pid)
638 {
639 	char path[PATH_MAX];
640 	const char *root_dir;
641 	struct machine *machine = machines__find(self, pid);
642 
643 	if (!machine || machine->pid != pid) {
644 		if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID)
645 			root_dir = "";
646 		else {
647 			if (!symbol_conf.guestmount)
648 				goto out;
649 			sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
650 			if (access(path, R_OK)) {
651 				pr_err("Can't access file %s\n", path);
652 				goto out;
653 			}
654 			root_dir = path;
655 		}
656 		machine = machines__add(self, pid, root_dir);
657 	}
658 
659 out:
660 	return machine;
661 }
662 
machines__process(struct rb_root * self,machine__process_t process,void * data)663 void machines__process(struct rb_root *self, machine__process_t process, void *data)
664 {
665 	struct rb_node *nd;
666 
667 	for (nd = rb_first(self); nd; nd = rb_next(nd)) {
668 		struct machine *pos = rb_entry(nd, struct machine, rb_node);
669 		process(pos, data);
670 	}
671 }
672 
machine__mmap_name(struct machine * self,char * bf,size_t size)673 char *machine__mmap_name(struct machine *self, char *bf, size_t size)
674 {
675 	if (machine__is_host(self))
676 		snprintf(bf, size, "[%s]", "kernel.kallsyms");
677 	else if (machine__is_default_guest(self))
678 		snprintf(bf, size, "[%s]", "guest.kernel.kallsyms");
679 	else
680 		snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms", self->pid);
681 
682 	return bf;
683 }
684