map.c 15.1 KB
Newer Older
1
#include "symbol.h"
2
#include <errno.h>
3
#include <inttypes.h>
4
#include <limits.h>
5 6 7
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
8
#include <unistd.h>
9
#include "map.h"
10

11 12 13 14 15
const char *map_type__name[MAP__NR_TYPES] = {
	[MAP__FUNCTION] = "Functions",
	[MAP__VARIABLE] = "Variables",
};

16 17 18 19 20
static inline int is_anon_memory(const char *filename)
{
	return strcmp(filename, "//anon") == 0;
}

21 22 23 24 25 26 27
static inline int is_no_dso_memory(const char *filename)
{
	return !strcmp(filename, "[stack]") ||
	       !strcmp(filename, "[vdso]")  ||
	       !strcmp(filename, "[heap]");
}

28 29
void map__init(struct map *self, enum map_type type,
	       u64 start, u64 end, u64 pgoff, struct dso *dso)
30
{
31
	self->type     = type;
32 33 34 35 36 37 38
	self->start    = start;
	self->end      = end;
	self->pgoff    = pgoff;
	self->dso      = dso;
	self->map_ip   = map__map_ip;
	self->unmap_ip = map__unmap_ip;
	RB_CLEAR_NODE(&self->rb_node);
39
	self->groups   = NULL;
40
	self->referenced = false;
41 42
}

43 44
struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
		     u64 pgoff, u32 pid, char *filename,
45
		     enum map_type type)
46 47 48 49 50
{
	struct map *self = malloc(sizeof(*self));

	if (self != NULL) {
		char newfilename[PATH_MAX];
51
		struct dso *dso;
52
		int anon, no_dso;
53 54

		anon = is_anon_memory(filename);
55
		no_dso = is_no_dso_memory(filename);
56 57

		if (anon) {
58
			snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
59 60 61
			filename = newfilename;
		}

62
		dso = __dsos__findnew(dsos__list, filename);
63
		if (dso == NULL)
64 65
			goto out_delete;

66
		map__init(self, type, start, start + len, pgoff, dso);
67

68
		if (anon || no_dso) {
69
			self->map_ip = self->unmap_ip = identity__map_ip;
70 71 72 73 74 75 76 77

			/*
			 * Set memory without DSO as loaded. All map__find_*
			 * functions still return NULL, and we avoid the
			 * unnecessary map__load warning.
			 */
			if (no_dso)
				dso__set_loaded(dso, self->type);
78
		}
79 80 81 82 83 84 85
	}
	return self;
out_delete:
	free(self);
	return NULL;
}

86 87 88 89 90
void map__delete(struct map *self)
{
	free(self);
}

91
void map__fixup_start(struct map *self)
92
{
93
	struct rb_root *symbols = &self->dso->symbols[self->type];
94
	struct rb_node *nd = rb_first(symbols);
95 96 97 98 99 100
	if (nd != NULL) {
		struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
		self->start = sym->start;
	}
}

101
void map__fixup_end(struct map *self)
102
{
103
	struct rb_root *symbols = &self->dso->symbols[self->type];
104
	struct rb_node *nd = rb_last(symbols);
105 106 107 108 109 110
	if (nd != NULL) {
		struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
		self->end = sym->end;
	}
}

111 112
#define DSO__DELETED "(deleted)"

113
int map__load(struct map *self, symbol_filter_t filter)
114
{
115
	const char *name = self->dso->long_name;
116
	int nr;
117

118 119 120
	if (dso__loaded(self->dso, self->type))
		return 0;

121
	nr = dso__load(self->dso, self, filter);
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
	if (nr < 0) {
		if (self->dso->has_build_id) {
			char sbuild_id[BUILD_ID_SIZE * 2 + 1];

			build_id__sprintf(self->dso->build_id,
					  sizeof(self->dso->build_id),
					  sbuild_id);
			pr_warning("%s with build id %s not found",
				   name, sbuild_id);
		} else
			pr_warning("Failed to open %s", name);

		pr_warning(", continuing without symbols\n");
		return -1;
	} else if (nr == 0) {
		const size_t len = strlen(name);
		const size_t real_len = len - sizeof(DSO__DELETED);

		if (len > sizeof(DSO__DELETED) &&
		    strcmp(name + real_len + 1, DSO__DELETED) == 0) {
			pr_warning("%.*s was updated, restart the long "
				   "running apps that use it!\n",
				   (int)real_len, name);
		} else {
			pr_warning("no symbols found in %s, maybe install "
				   "a debug package?\n", name);
148
		}
149 150

		return -1;
151
	}
152 153 154 155 156 157
	/*
	 * Only applies to the kernel, as its symtabs aren't relative like the
	 * module ones.
	 */
	if (self->dso->kernel)
		map__reloc_vmlinux(self);
158

159 160 161
	return 0;
}

162 163
struct symbol *map__find_symbol(struct map *self, u64 addr,
				symbol_filter_t filter)
164
{
165
	if (map__load(self, filter) < 0)
166 167
		return NULL;

168
	return dso__find_symbol(self->dso, self->type, addr);
169 170
}

171 172 173
struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
					symbol_filter_t filter)
{
174
	if (map__load(self, filter) < 0)
175 176 177 178 179 180 181 182
		return NULL;

	if (!dso__sorted_by_name(self->dso, self->type))
		dso__sort_by_name(self->dso, self->type);

	return dso__find_symbol_by_name(self->dso, self->type, name);
}

183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
struct map *map__clone(struct map *self)
{
	struct map *map = malloc(sizeof(*self));

	if (!map)
		return NULL;

	memcpy(map, self, sizeof(*self));

	return map;
}

int map__overlap(struct map *l, struct map *r)
{
	if (l->start > r->start) {
		struct map *t = l;
		l = r;
		r = t;
	}

	if (l->end > r->start)
		return 1;

	return 0;
}

size_t map__fprintf(struct map *self, FILE *fp)
{
211
	return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n",
212 213
		       self->start, self->end, self->pgoff, self->dso->name);
}
214 215 216 217 218 219 220 221 222 223 224 225

/*
 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
 * map->dso->adjust_symbols==1 for ET_EXEC-like cases.
 */
u64 map__rip_2objdump(struct map *map, u64 rip)
{
	u64 addr = map->dso->adjust_symbols ?
			map->unmap_ip(map, rip) :	/* RIP -> IP */
			rip;
	return addr;
}
226 227 228 229 230 231 232 233

u64 map__objdump_2ip(struct map *map, u64 addr)
{
	u64 ip = map->dso->adjust_symbols ?
			addr :
			map->unmap_ip(map, addr);	/* RIP -> IP */
	return ip;
}
234

235
void map_groups__init(struct map_groups *mg)
236 237 238
{
	int i;
	for (i = 0; i < MAP__NR_TYPES; ++i) {
239 240
		mg->maps[i] = RB_ROOT;
		INIT_LIST_HEAD(&mg->removed_maps[i]);
241
	}
242
	mg->machine = NULL;
243 244
}

245
static void maps__delete(struct rb_root *maps)
246
{
247
	struct rb_node *next = rb_first(maps);
248 249 250 251 252

	while (next) {
		struct map *pos = rb_entry(next, struct map, rb_node);

		next = rb_next(&pos->rb_node);
253
		rb_erase(&pos->rb_node, maps);
254 255 256 257
		map__delete(pos);
	}
}

258
static void maps__delete_removed(struct list_head *maps)
259 260 261
{
	struct map *pos, *n;

262
	list_for_each_entry_safe(pos, n, maps, node) {
263 264 265 266 267
		list_del(&pos->node);
		map__delete(pos);
	}
}

268
void map_groups__exit(struct map_groups *mg)
269 270 271 272
{
	int i;

	for (i = 0; i < MAP__NR_TYPES; ++i) {
273 274
		maps__delete(&mg->maps[i]);
		maps__delete_removed(&mg->removed_maps[i]);
275 276 277
	}
}

278
void map_groups__flush(struct map_groups *mg)
279 280 281 282
{
	int type;

	for (type = 0; type < MAP__NR_TYPES; type++) {
283
		struct rb_root *root = &mg->maps[type];
284 285 286 287 288 289 290 291 292 293 294
		struct rb_node *next = rb_first(root);

		while (next) {
			struct map *pos = rb_entry(next, struct map, rb_node);
			next = rb_next(&pos->rb_node);
			rb_erase(&pos->rb_node, root);
			/*
			 * We may have references to this map, for
			 * instance in some hist_entry instances, so
			 * just move them to a separate list.
			 */
295
			list_add_tail(&pos->node, &mg->removed_maps[pos->type]);
296 297 298 299
		}
	}
}

300
struct symbol *map_groups__find_symbol(struct map_groups *mg,
301
				       enum map_type type, u64 addr,
302
				       struct map **mapp,
303 304
				       symbol_filter_t filter)
{
305
	struct map *map = map_groups__find(mg, type, addr);
306

307 308 309
	if (map != NULL) {
		if (mapp != NULL)
			*mapp = map;
310
		return map__find_symbol(map, map->map_ip(map, addr), filter);
311 312 313 314 315
	}

	return NULL;
}

316
struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
317 318 319 320 321 322 323
					       enum map_type type,
					       const char *name,
					       struct map **mapp,
					       symbol_filter_t filter)
{
	struct rb_node *nd;

324
	for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) {
325 326 327 328 329 330 331 332 333
		struct map *pos = rb_entry(nd, struct map, rb_node);
		struct symbol *sym = map__find_symbol_by_name(pos, name, filter);

		if (sym == NULL)
			continue;
		if (mapp != NULL)
			*mapp = pos;
		return sym;
	}
334 335 336 337

	return NULL;
}

338
size_t __map_groups__fprintf_maps(struct map_groups *mg,
339 340 341 342 343
				  enum map_type type, int verbose, FILE *fp)
{
	size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
	struct rb_node *nd;

344
	for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) {
345 346 347 348 349 350 351 352 353 354 355 356
		struct map *pos = rb_entry(nd, struct map, rb_node);
		printed += fprintf(fp, "Map:");
		printed += map__fprintf(pos, fp);
		if (verbose > 2) {
			printed += dso__fprintf(pos->dso, type, fp);
			printed += fprintf(fp, "--\n");
		}
	}

	return printed;
}

357
size_t map_groups__fprintf_maps(struct map_groups *mg, int verbose, FILE *fp)
358 359 360
{
	size_t printed = 0, i;
	for (i = 0; i < MAP__NR_TYPES; ++i)
361
		printed += __map_groups__fprintf_maps(mg, i, verbose, fp);
362 363 364
	return printed;
}

365
static size_t __map_groups__fprintf_removed_maps(struct map_groups *mg,
366 367 368 369 370 371
						 enum map_type type,
						 int verbose, FILE *fp)
{
	struct map *pos;
	size_t printed = 0;

372
	list_for_each_entry(pos, &mg->removed_maps[type], node) {
373 374 375 376 377 378 379 380 381 382
		printed += fprintf(fp, "Map:");
		printed += map__fprintf(pos, fp);
		if (verbose > 1) {
			printed += dso__fprintf(pos->dso, type, fp);
			printed += fprintf(fp, "--\n");
		}
	}
	return printed;
}

383
static size_t map_groups__fprintf_removed_maps(struct map_groups *mg,
384 385 386 387
					       int verbose, FILE *fp)
{
	size_t printed = 0, i;
	for (i = 0; i < MAP__NR_TYPES; ++i)
388
		printed += __map_groups__fprintf_removed_maps(mg, i, verbose, fp);
389 390 391
	return printed;
}

392
size_t map_groups__fprintf(struct map_groups *mg, int verbose, FILE *fp)
393
{
394
	size_t printed = map_groups__fprintf_maps(mg, verbose, fp);
395
	printed += fprintf(fp, "Removed maps:\n");
396
	return printed + map_groups__fprintf_removed_maps(mg, verbose, fp);
397 398
}

399
int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
400 401
				   int verbose, FILE *fp)
{
402
	struct rb_root *root = &mg->maps[map->type];
403
	struct rb_node *next = rb_first(root);
404
	int err = 0;
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426

	while (next) {
		struct map *pos = rb_entry(next, struct map, rb_node);
		next = rb_next(&pos->rb_node);

		if (!map__overlap(pos, map))
			continue;

		if (verbose >= 2) {
			fputs("overlapping maps:\n", fp);
			map__fprintf(map, fp);
			map__fprintf(pos, fp);
		}

		rb_erase(&pos->rb_node, root);
		/*
		 * Now check if we need to create new maps for areas not
		 * overlapped by the new map:
		 */
		if (map->start > pos->start) {
			struct map *before = map__clone(pos);

427 428 429 430
			if (before == NULL) {
				err = -ENOMEM;
				goto move_map;
			}
431 432

			before->end = map->start - 1;
433
			map_groups__insert(mg, before);
434 435 436 437 438 439 440
			if (verbose >= 2)
				map__fprintf(before, fp);
		}

		if (map->end < pos->end) {
			struct map *after = map__clone(pos);

441 442 443 444
			if (after == NULL) {
				err = -ENOMEM;
				goto move_map;
			}
445 446

			after->start = map->end + 1;
447
			map_groups__insert(mg, after);
448 449 450
			if (verbose >= 2)
				map__fprintf(after, fp);
		}
451 452 453 454 455
move_map:
		/*
		 * If we have references, just move them to a separate list.
		 */
		if (pos->referenced)
456
			list_add_tail(&pos->node, &mg->removed_maps[map->type]);
457 458 459 460 461
		else
			map__delete(pos);

		if (err)
			return err;
462 463 464 465 466 467 468 469
	}

	return 0;
}

/*
 * XXX This should not really _copy_ te maps, but refcount them.
 */
470
int map_groups__clone(struct map_groups *mg,
471 472 473 474 475 476 477 478
		      struct map_groups *parent, enum map_type type)
{
	struct rb_node *nd;
	for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) {
		struct map *map = rb_entry(nd, struct map, rb_node);
		struct map *new = map__clone(map);
		if (new == NULL)
			return -ENOMEM;
479
		map_groups__insert(mg, new);
480 481 482 483
	}
	return 0;
}

484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
static u64 map__reloc_map_ip(struct map *map, u64 ip)
{
	return ip + (s64)map->pgoff;
}

static u64 map__reloc_unmap_ip(struct map *map, u64 ip)
{
	return ip - (s64)map->pgoff;
}

void map__reloc_vmlinux(struct map *self)
{
	struct kmap *kmap = map__kmap(self);
	s64 reloc;

	if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->unrelocated_addr)
		return;

	reloc = (kmap->ref_reloc_sym->unrelocated_addr -
		 kmap->ref_reloc_sym->addr);

	if (!reloc)
		return;

	self->map_ip   = map__reloc_map_ip;
	self->unmap_ip = map__reloc_unmap_ip;
	self->pgoff    = reloc;
}

void maps__insert(struct rb_root *maps, struct map *map)
{
	struct rb_node **p = &maps->rb_node;
	struct rb_node *parent = NULL;
	const u64 ip = map->start;
	struct map *m;

	while (*p != NULL) {
		parent = *p;
		m = rb_entry(parent, struct map, rb_node);
		if (ip < m->start)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

	rb_link_node(&map->rb_node, parent, p);
	rb_insert_color(&map->rb_node, maps);
}

533 534 535 536 537
void maps__remove(struct rb_root *self, struct map *map)
{
	rb_erase(&map->rb_node, self);
}

538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
struct map *maps__find(struct rb_root *maps, u64 ip)
{
	struct rb_node **p = &maps->rb_node;
	struct rb_node *parent = NULL;
	struct map *m;

	while (*p != NULL) {
		parent = *p;
		m = rb_entry(parent, struct map, rb_node);
		if (ip < m->start)
			p = &(*p)->rb_left;
		else if (ip > m->end)
			p = &(*p)->rb_right;
		else
			return m;
	}

	return NULL;
}
557

558 559 560 561 562 563 564 565 566 567 568 569 570
int machine__init(struct machine *self, const char *root_dir, pid_t pid)
{
	map_groups__init(&self->kmaps);
	RB_CLEAR_NODE(&self->rb_node);
	INIT_LIST_HEAD(&self->user_dsos);
	INIT_LIST_HEAD(&self->kernel_dsos);

	self->kmaps.machine = self;
	self->pid	    = pid;
	self->root_dir      = strdup(root_dir);
	return self->root_dir == NULL ? -ENOMEM : 0;
}

571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
static void dsos__delete(struct list_head *self)
{
	struct dso *pos, *n;

	list_for_each_entry_safe(pos, n, self, node) {
		list_del(&pos->node);
		dso__delete(pos);
	}
}

void machine__exit(struct machine *self)
{
	map_groups__exit(&self->kmaps);
	dsos__delete(&self->user_dsos);
	dsos__delete(&self->kernel_dsos);
	free(self->root_dir);
	self->root_dir = NULL;
}

590 591 592 593 594 595
void machine__delete(struct machine *self)
{
	machine__exit(self);
	free(self);
}

596 597
struct machine *machines__add(struct rb_root *self, pid_t pid,
			      const char *root_dir)
598
{
599
	struct rb_node **p = &self->rb_node;
600
	struct rb_node *parent = NULL;
601
	struct machine *pos, *machine = malloc(sizeof(*machine));
602

603
	if (!machine)
604 605
		return NULL;

606 607 608 609
	if (machine__init(machine, root_dir, pid) != 0) {
		free(machine);
		return NULL;
	}
610 611 612

	while (*p != NULL) {
		parent = *p;
613
		pos = rb_entry(parent, struct machine, rb_node);
614 615 616 617 618 619
		if (pid < pos->pid)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

620 621
	rb_link_node(&machine->rb_node, parent, p);
	rb_insert_color(&machine->rb_node, self);
622

623
	return machine;
624 625
}

626
struct machine *machines__find(struct rb_root *self, pid_t pid)
627
{
628
	struct rb_node **p = &self->rb_node;
629
	struct rb_node *parent = NULL;
630 631
	struct machine *machine;
	struct machine *default_machine = NULL;
632 633 634

	while (*p != NULL) {
		parent = *p;
635 636
		machine = rb_entry(parent, struct machine, rb_node);
		if (pid < machine->pid)
637
			p = &(*p)->rb_left;
638
		else if (pid > machine->pid)
639 640
			p = &(*p)->rb_right;
		else
641 642 643
			return machine;
		if (!machine->pid)
			default_machine = machine;
644 645
	}

646
	return default_machine;
647 648
}

649
struct machine *machines__findnew(struct rb_root *self, pid_t pid)
650 651 652
{
	char path[PATH_MAX];
	const char *root_dir;
653
	struct machine *machine = machines__find(self, pid);
654

655
	if (!machine || machine->pid != pid) {
656 657 658 659 660 661
		if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID)
			root_dir = "";
		else {
			if (!symbol_conf.guestmount)
				goto out;
			sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
662
			if (access(path, R_OK)) {
663 664 665 666 667
				pr_err("Can't access file %s\n", path);
				goto out;
			}
			root_dir = path;
		}
668
		machine = machines__add(self, pid, root_dir);
669 670 671
	}

out:
672
	return machine;
673 674
}

675
void machines__process(struct rb_root *self, machine__process_t process, void *data)
676 677 678
{
	struct rb_node *nd;

679 680
	for (nd = rb_first(self); nd; nd = rb_next(nd)) {
		struct machine *pos = rb_entry(nd, struct machine, rb_node);
681 682 683 684
		process(pos, data);
	}
}

685
char *machine__mmap_name(struct machine *self, char *bf, size_t size)
686
{
687
	if (machine__is_host(self))
688
		snprintf(bf, size, "[%s]", "kernel.kallsyms");
689
	else if (machine__is_default_guest(self))
690
		snprintf(bf, size, "[%s]", "guest.kernel.kallsyms");
691
	else
692
		snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms", self->pid);
693

694
	return bf;
695
}