symbol.c 21.1 KB
Newer Older
1 2
#include "util.h"
#include "../perf.h"
3
#include "string.h"
4 5 6 7 8
#include "symbol.h"

#include <libelf.h>
#include <gelf.h>
#include <elf.h>
P
Peter Zijlstra 已提交
9

10 11
const char *sym_hist_filter;

12 13 14 15 16 17 18 19 20 21
enum dso_origin {
	DSO__ORIG_KERNEL = 0,
	DSO__ORIG_JAVA_JIT,
	DSO__ORIG_FEDORA,
	DSO__ORIG_UBUNTU,
	DSO__ORIG_BUILDID,
	DSO__ORIG_DSO,
	DSO__ORIG_NOT_FOUND,
};

22
static struct symbol *symbol__new(u64 start, u64 len,
23
				  const char *name, unsigned int priv_size,
24
				  u64 obj_start, int v)
25
{
26
	size_t namelen = strlen(name) + 1;
27
	struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen);
28

29 30 31
	if (!self)
		return NULL;

32
	if (v >= 2)
33
		printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n",
34
			(u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start);
35 36 37 38 39 40

	self->obj_start= obj_start;
	self->hist = NULL;
	self->hist_sum = 0;

	if (sym_hist_filter && !strcmp(name, sym_hist_filter))
41
		self->hist = calloc(sizeof(u64), len);
42 43 44 45

	if (priv_size) {
		memset(self, 0, priv_size);
		self = ((void *)self) + priv_size;
46
	}
47
	self->start = start;
48
	self->end   = len ? start + len - 1 : start;
49
	memcpy(self->name, name, namelen);
50 51 52 53

	return self;
}

54
static void symbol__delete(struct symbol *self, unsigned int priv_size)
55
{
56
	free(((void *)self) - priv_size);
57 58 59 60
}

static size_t symbol__fprintf(struct symbol *self, FILE *fp)
{
61 62
	if (!self->module)
		return fprintf(fp, " %llx-%llx %s\n",
63
		       self->start, self->end, self->name);
64 65 66
	else
		return fprintf(fp, " %llx-%llx %s \t[%s]\n",
		       self->start, self->end, self->name, self->module->name);
67 68
}

69
struct dso *dso__new(const char *name, unsigned int sym_priv_size)
70 71 72 73 74 75
{
	struct dso *self = malloc(sizeof(*self) + strlen(name) + 1);

	if (self != NULL) {
		strcpy(self->name, name);
		self->syms = RB_ROOT;
76
		self->sym_priv_size = sym_priv_size;
P
Peter Zijlstra 已提交
77
		self->find_symbol = dso__find_symbol;
78
		self->slen_calculated = 0;
79
		self->origin = DSO__ORIG_NOT_FOUND;
80 81 82 83 84 85 86 87 88 89 90 91 92
	}

	return self;
}

static void dso__delete_symbols(struct dso *self)
{
	struct symbol *pos;
	struct rb_node *next = rb_first(&self->syms);

	while (next) {
		pos = rb_entry(next, struct symbol, rb_node);
		next = rb_next(&pos->rb_node);
93
		rb_erase(&pos->rb_node, &self->syms);
94
		symbol__delete(pos, self->sym_priv_size);
95 96 97 98 99 100 101 102 103 104 105 106 107
	}
}

void dso__delete(struct dso *self)
{
	dso__delete_symbols(self);
	free(self);
}

static void dso__insert_symbol(struct dso *self, struct symbol *sym)
{
	struct rb_node **p = &self->syms.rb_node;
	struct rb_node *parent = NULL;
108
	const u64 ip = sym->start;
109 110 111 112 113 114 115 116 117 118 119 120 121 122
	struct symbol *s;

	while (*p != NULL) {
		parent = *p;
		s = rb_entry(parent, struct symbol, rb_node);
		if (ip < s->start)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}
	rb_link_node(&sym->rb_node, parent, p);
	rb_insert_color(&sym->rb_node, &self->syms);
}

123
struct symbol *dso__find_symbol(struct dso *self, u64 ip)
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
{
	struct rb_node *n;

	if (self == NULL)
		return NULL;

	n = self->syms.rb_node;

	while (n) {
		struct symbol *s = rb_entry(n, struct symbol, rb_node);

		if (ip < s->start)
			n = n->rb_left;
		else if (ip > s->end)
			n = n->rb_right;
		else
			return s;
	}

	return NULL;
}

size_t dso__fprintf(struct dso *self, FILE *fp)
{
	size_t ret = fprintf(fp, "dso: %s\n", self->name);

	struct rb_node *nd;
	for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
		struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
		ret += symbol__fprintf(pos, fp);
	}

	return ret;
}

159
static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v)
160 161 162 163 164
{
	struct rb_node *nd, *prevnd;
	char *line = NULL;
	size_t n;
	FILE *file = fopen("/proc/kallsyms", "r");
165
	int count = 0;
166 167 168 169 170

	if (file == NULL)
		goto out_failure;

	while (!feof(file)) {
171
		u64 start;
172 173 174 175 176 177 178 179 180 181 182 183 184
		struct symbol *sym;
		int line_len, len;
		char symbol_type;

		line_len = getline(&line, &n, file);
		if (line_len < 0)
			break;

		if (!line)
			goto out_failure;

		line[--line_len] = '\0'; /* \n */

185
		len = hex2u64(line, &start);
186 187 188 189 190 191 192 193 194 195 196 197 198 199

		len++;
		if (len + 2 >= line_len)
			continue;

		symbol_type = toupper(line[len]);
		/*
		 * We're interested only in code ('T'ext)
		 */
		if (symbol_type != 'T' && symbol_type != 'W')
			continue;
		/*
		 * Well fix up the end later, when we have all sorted.
		 */
200
		sym = symbol__new(start, 0xdead, line + len + 2,
201
				  self->sym_priv_size, 0, v);
202 203 204 205

		if (sym == NULL)
			goto out_delete_line;

206 207
		if (filter && filter(self, sym))
			symbol__delete(sym, self->sym_priv_size);
208
		else {
209
			dso__insert_symbol(self, sym);
210 211
			count++;
		}
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
	}

	/*
	 * Now that we have all sorted out, just set the ->end of all
	 * symbols
	 */
	prevnd = rb_first(&self->syms);

	if (prevnd == NULL)
		goto out_delete_line;

	for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
		struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node),
			      *curr = rb_entry(nd, struct symbol, rb_node);

		prev->end = curr->start - 1;
		prevnd = nd;
	}

	free(line);
	fclose(file);

234
	return count;
235 236 237 238 239 240 241

out_delete_line:
	free(line);
out_failure:
	return -1;
}

242
static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v)
243 244 245 246 247 248 249 250 251 252 253
{
	char *line = NULL;
	size_t n;
	FILE *file;
	int nr_syms = 0;

	file = fopen(self->name, "r");
	if (file == NULL)
		goto out_failure;

	while (!feof(file)) {
254
		u64 start, size;
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
		struct symbol *sym;
		int line_len, len;

		line_len = getline(&line, &n, file);
		if (line_len < 0)
			break;

		if (!line)
			goto out_failure;

		line[--line_len] = '\0'; /* \n */

		len = hex2u64(line, &start);

		len++;
		if (len + 2 >= line_len)
			continue;

		len += hex2u64(line + len, &size);

		len++;
		if (len + 2 >= line_len)
			continue;

		sym = symbol__new(start, size, line + len,
280
				  self->sym_priv_size, start, v);
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303

		if (sym == NULL)
			goto out_delete_line;

		if (filter && filter(self, sym))
			symbol__delete(sym, self->sym_priv_size);
		else {
			dso__insert_symbol(self, sym);
			nr_syms++;
		}
	}

	free(line);
	fclose(file);

	return nr_syms;

out_delete_line:
	free(line);
out_failure:
	return -1;
}

304 305 306 307
/**
 * elf_symtab__for_each_symbol - iterate thru all the symbols
 *
 * @self: struct elf_symtab instance to iterate
308
 * @idx: uint32_t idx
309 310
 * @sym: GElf_Sym iterator
 */
311 312 313 314
#define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \
	for (idx = 0, gelf_getsym(syms, idx, &sym);\
	     idx < nr_syms; \
	     idx++, gelf_getsym(syms, idx, &sym))
315 316 317 318 319 320 321 322 323 324 325 326 327 328

static inline uint8_t elf_sym__type(const GElf_Sym *sym)
{
	return GELF_ST_TYPE(sym->st_info);
}

static inline int elf_sym__is_function(const GElf_Sym *sym)
{
	return elf_sym__type(sym) == STT_FUNC &&
	       sym->st_name != 0 &&
	       sym->st_shndx != SHN_UNDEF &&
	       sym->st_size != 0;
}

329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
static inline int elf_sym__is_label(const GElf_Sym *sym)
{
	return elf_sym__type(sym) == STT_NOTYPE &&
		sym->st_name != 0 &&
		sym->st_shndx != SHN_UNDEF &&
		sym->st_shndx != SHN_ABS;
}

static inline const char *elf_sec__name(const GElf_Shdr *shdr,
					const Elf_Data *secstrs)
{
	return secstrs->d_buf + shdr->sh_name;
}

static inline int elf_sec__is_text(const GElf_Shdr *shdr,
					const Elf_Data *secstrs)
{
	return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
}

349 350 351 352 353 354 355 356
static inline const char *elf_sym__name(const GElf_Sym *sym,
					const Elf_Data *symstrs)
{
	return symstrs->d_buf + sym->st_name;
}

static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
				    GElf_Shdr *shp, const char *name,
357
				    size_t *idx)
358 359 360 361 362 363 364 365 366 367
{
	Elf_Scn *sec = NULL;
	size_t cnt = 1;

	while ((sec = elf_nextscn(elf, sec)) != NULL) {
		char *str;

		gelf_getshdr(sec, shp);
		str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
		if (!strcmp(name, str)) {
368 369
			if (idx)
				*idx = cnt;
370 371 372 373 374 375 376 377
			break;
		}
		++cnt;
	}

	return sec;
}

378 379 380 381 382 383 384 385 386 387
#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
	for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
	     idx < nr_entries; \
	     ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))

#define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
	for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
	     idx < nr_entries; \
	     ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))

388 389 390 391 392 393 394
/*
 * We need to check if we have a .dynsym, so that we can handle the
 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
 * .dynsym or .symtab).
 * And always look at the original dso, not at debuginfo packages, that
 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
 */
395
static int dso__synthesize_plt_symbols(struct  dso *self, int v)
396 397 398
{
	uint32_t nr_rel_entries, idx;
	GElf_Sym sym;
399
	u64 plt_offset;
400 401
	GElf_Shdr shdr_plt;
	struct symbol *f;
402
	GElf_Shdr shdr_rel_plt, shdr_dynsym;
403
	Elf_Data *reldata, *syms, *symstrs;
404 405 406
	Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
	size_t dynsym_idx;
	GElf_Ehdr ehdr;
407
	char sympltname[1024];
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
	Elf *elf;
	int nr = 0, symidx, fd, err = 0;

	fd = open(self->name, O_RDONLY);
	if (fd < 0)
		goto out;

	elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
	if (elf == NULL)
		goto out_close;

	if (gelf_getehdr(elf, &ehdr) == NULL)
		goto out_elf_end;

	scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
					 ".dynsym", &dynsym_idx);
	if (scn_dynsym == NULL)
		goto out_elf_end;
426

427
	scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
428 429
					  ".rela.plt", NULL);
	if (scn_plt_rel == NULL) {
430
		scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
431 432
						  ".rel.plt", NULL);
		if (scn_plt_rel == NULL)
433
			goto out_elf_end;
434 435
	}

436 437
	err = -1;

438
	if (shdr_rel_plt.sh_link != dynsym_idx)
439
		goto out_elf_end;
440

441 442
	if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
		goto out_elf_end;
443 444

	/*
445
	 * Fetch the relocation section to find the idxes to the GOT
446 447 448 449
	 * and the symbols in the .dynsym they refer to.
	 */
	reldata = elf_getdata(scn_plt_rel, NULL);
	if (reldata == NULL)
450
		goto out_elf_end;
451 452 453

	syms = elf_getdata(scn_dynsym, NULL);
	if (syms == NULL)
454
		goto out_elf_end;
455

456
	scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
457
	if (scn_symstrs == NULL)
458
		goto out_elf_end;
459 460 461

	symstrs = elf_getdata(scn_symstrs, NULL);
	if (symstrs == NULL)
462
		goto out_elf_end;
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478

	nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
	plt_offset = shdr_plt.sh_offset;

	if (shdr_rel_plt.sh_type == SHT_RELA) {
		GElf_Rela pos_mem, *pos;

		elf_section__for_each_rela(reldata, pos, pos_mem, idx,
					   nr_rel_entries) {
			symidx = GELF_R_SYM(pos->r_info);
			plt_offset += shdr_plt.sh_entsize;
			gelf_getsym(syms, symidx, &sym);
			snprintf(sympltname, sizeof(sympltname),
				 "%s@plt", elf_sym__name(&sym, symstrs));

			f = symbol__new(plt_offset, shdr_plt.sh_entsize,
479
					sympltname, self->sym_priv_size, 0, v);
480
			if (!f)
481
				goto out_elf_end;
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496

			dso__insert_symbol(self, f);
			++nr;
		}
	} else if (shdr_rel_plt.sh_type == SHT_REL) {
		GElf_Rel pos_mem, *pos;
		elf_section__for_each_rel(reldata, pos, pos_mem, idx,
					  nr_rel_entries) {
			symidx = GELF_R_SYM(pos->r_info);
			plt_offset += shdr_plt.sh_entsize;
			gelf_getsym(syms, symidx, &sym);
			snprintf(sympltname, sizeof(sympltname),
				 "%s@plt", elf_sym__name(&sym, symstrs));

			f = symbol__new(plt_offset, shdr_plt.sh_entsize,
497
					sympltname, self->sym_priv_size, 0, v);
498
			if (!f)
499
				goto out_elf_end;
500 501 502 503 504 505

			dso__insert_symbol(self, f);
			++nr;
		}
	}

506 507 508 509 510 511 512 513 514 515 516 517
	err = 0;
out_elf_end:
	elf_end(elf);
out_close:
	close(fd);

	if (err == 0)
		return nr;
out:
	fprintf(stderr, "%s: problems reading %s PLT info.\n",
		__func__, self->name);
	return 0;
518 519
}

520
static int dso__load_sym(struct dso *self, int fd, const char *name,
521
			 symbol_filter_t filter, int v, struct module *mod)
522
{
523
	Elf_Data *symstrs, *secstrs;
524 525
	uint32_t nr_syms;
	int err = -1;
526
	uint32_t idx;
527 528 529 530
	GElf_Ehdr ehdr;
	GElf_Shdr shdr;
	Elf_Data *syms;
	GElf_Sym sym;
531
	Elf_Scn *sec, *sec_strndx;
532
	Elf *elf;
533
	int nr = 0, kernel = !strcmp("[kernel]", self->name);
534 535 536

	elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
	if (elf == NULL) {
537
		if (v)
538 539
			fprintf(stderr, "%s: cannot read %s ELF file.\n",
				__func__, name);
540 541 542 543
		goto out_close;
	}

	if (gelf_getehdr(elf, &ehdr) == NULL) {
544
		if (v)
545
			fprintf(stderr, "%s: cannot get elf header.\n", __func__);
546 547 548 549
		goto out_elf_end;
	}

	sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
550
	if (sec == NULL) {
551 552
		sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
		if (sec == NULL)
553 554
			goto out_elf_end;
	}
555 556 557 558 559 560 561 562 563 564 565 566 567

	syms = elf_getdata(sec, NULL);
	if (syms == NULL)
		goto out_elf_end;

	sec = elf_getscn(elf, shdr.sh_link);
	if (sec == NULL)
		goto out_elf_end;

	symstrs = elf_getdata(sec, NULL);
	if (symstrs == NULL)
		goto out_elf_end;

568 569 570 571 572
	sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
	if (sec_strndx == NULL)
		goto out_elf_end;

	secstrs = elf_getdata(sec_strndx, NULL);
S
Stoyan Gaydarov 已提交
573
	if (secstrs == NULL)
574 575
		goto out_elf_end;

576 577
	nr_syms = shdr.sh_size / shdr.sh_entsize;

578
	memset(&sym, 0, sizeof(sym));
579 580
	if (!kernel) {
		self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
581 582 583
				elf_section_by_name(elf, &ehdr, &shdr,
						     ".gnu.prelink_undo",
						     NULL) != NULL);
584 585
	} else self->adjust_symbols = 0;

586
	elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
587
		struct symbol *f;
588
		const char *elf_name;
589
		char *demangled;
590
		u64 obj_start;
591 592 593
		struct section *section = NULL;
		int is_label = elf_sym__is_label(&sym);
		const char *section_name;
594

595
		if (!is_label && !elf_sym__is_function(&sym))
596 597 598 599 600 601 602
			continue;

		sec = elf_getscn(elf, sym.st_shndx);
		if (!sec)
			goto out_elf_end;

		gelf_getshdr(sec, &shdr);
603 604 605 606 607

		if (is_label && !elf_sec__is_text(&shdr, secstrs))
			continue;

		section_name = elf_sec__name(&shdr, secstrs);
608 609
		obj_start = sym.st_value;

610
		if (self->adjust_symbols) {
611
			if (v >= 2)
612 613
				printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
					(u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
614

615 616
			sym.st_value -= shdr.sh_addr - shdr.sh_offset;
		}
617

618 619 620 621 622 623 624 625 626 627
		if (mod) {
			section = mod->sections->find_section(mod->sections, section_name);
			if (section)
				sym.st_value += section->vma;
			else {
				fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
					mod->name, section_name);
				goto out_elf_end;
			}
		}
628 629 630 631 632
		/*
		 * We need to figure out if the object was created from C++ sources
		 * DWARF DW_compile_unit has this, but we don't always have access
		 * to it...
		 */
633 634
		elf_name = elf_sym__name(&sym, symstrs);
		demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
635
		if (demangled != NULL)
636
			elf_name = demangled;
637

638 639
		f = symbol__new(sym.st_value, sym.st_size, elf_name,
				self->sym_priv_size, obj_start, v);
640
		free(demangled);
641 642 643
		if (!f)
			goto out_elf_end;

644 645 646
		if (filter && filter(self, f))
			symbol__delete(f, self->sym_priv_size);
		else {
647
			f->module = mod;
648 649 650
			dso__insert_symbol(self, f);
			nr++;
		}
651 652 653 654 655 656 657 658 659
	}

	err = nr;
out_elf_end:
	elf_end(elf);
out_close:
	return err;
}

660 661
#define BUILD_ID_SIZE 128

662
static char *dso__read_build_id(struct dso *self, int v)
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
{
	int i;
	GElf_Ehdr ehdr;
	GElf_Shdr shdr;
	Elf_Data *build_id_data;
	Elf_Scn *sec;
	char *build_id = NULL, *bid;
	unsigned char *raw;
	Elf *elf;
	int fd = open(self->name, O_RDONLY);

	if (fd < 0)
		goto out;

	elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
	if (elf == NULL) {
679
		if (v)
680 681 682 683 684 685
			fprintf(stderr, "%s: cannot read %s ELF file.\n",
				__func__, self->name);
		goto out_close;
	}

	if (gelf_getehdr(elf, &ehdr) == NULL) {
686
		if (v)
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
			fprintf(stderr, "%s: cannot get elf header.\n", __func__);
		goto out_elf_end;
	}

	sec = elf_section_by_name(elf, &ehdr, &shdr, ".note.gnu.build-id", NULL);
	if (sec == NULL)
		goto out_elf_end;

	build_id_data = elf_getdata(sec, NULL);
	if (build_id_data == NULL)
		goto out_elf_end;
	build_id = malloc(BUILD_ID_SIZE);
	if (build_id == NULL)
		goto out_elf_end;
	raw = build_id_data->d_buf + 16;
	bid = build_id;

	for (i = 0; i < 20; ++i) {
		sprintf(bid, "%02x", *raw);
		++raw;
		bid += 2;
	}
709
	if (v >= 2)
710 711 712 713 714 715 716 717 718
		printf("%s(%s): %s\n", __func__, self->name, build_id);
out_elf_end:
	elf_end(elf);
out_close:
	close(fd);
out:
	return build_id;
}

719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
char dso__symtab_origin(const struct dso *self)
{
	static const char origin[] = {
		[DSO__ORIG_KERNEL] =   'k',
		[DSO__ORIG_JAVA_JIT] = 'j',
		[DSO__ORIG_FEDORA] =   'f',
		[DSO__ORIG_UBUNTU] =   'u',
		[DSO__ORIG_BUILDID] =  'b',
		[DSO__ORIG_DSO] =      'd',
	};

	if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
		return '!';
	return origin[self->origin];
}

735
int dso__load(struct dso *self, symbol_filter_t filter, int v)
736
{
737 738
	int size = PATH_MAX;
	char *name = malloc(size), *build_id = NULL;
739 740 741 742 743 744
	int ret = -1;
	int fd;

	if (!name)
		return -1;

745
	self->adjust_symbols = 0;
746

747
	if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
748
		ret = dso__load_perf_map(self, filter, v);
749 750 751 752 753 754
		self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
					 DSO__ORIG_NOT_FOUND;
		return ret;
	}

	self->origin = DSO__ORIG_FEDORA - 1;
755

756 757
more:
	do {
758 759 760
		self->origin++;
		switch (self->origin) {
		case DSO__ORIG_FEDORA:
761 762
			snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
			break;
763
		case DSO__ORIG_UBUNTU:
764 765
			snprintf(name, size, "/usr/lib/debug%s", self->name);
			break;
766
		case DSO__ORIG_BUILDID:
767
			build_id = dso__read_build_id(self, v);
768 769 770 771 772 773 774
			if (build_id != NULL) {
				snprintf(name, size,
					 "/usr/lib/debug/.build-id/%.2s/%s.debug",
					build_id, build_id + 2);
				free(build_id);
				break;
			}
775
			self->origin++;
776
			/* Fall thru */
777
		case DSO__ORIG_DSO:
778 779 780 781 782 783 784 785 786 787
			snprintf(name, size, "%s", self->name);
			break;

		default:
			goto out;
		}

		fd = open(name, O_RDONLY);
	} while (fd < 0);

788
	ret = dso__load_sym(self, fd, name, filter, v, NULL);
789 790 791 792 793 794 795 796
	close(fd);

	/*
	 * Some people seem to have debuginfo files _WITHOUT_ debug info!?!?
	 */
	if (!ret)
		goto more;

797
	if (ret > 0) {
798
		int nr_plt = dso__synthesize_plt_symbols(self, v);
799 800 801
		if (nr_plt > 0)
			ret += nr_plt;
	}
802 803
out:
	free(name);
804 805
	if (ret < 0 && strstr(self->name, " (deleted)") != NULL)
		return 0;
806 807 808
	return ret;
}

809
static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name,
810
			     symbol_filter_t filter, int v)
811 812 813 814 815 816 817 818 819 820 821 822
{
	struct module *mod = mod_dso__find_module(mods, name);
	int err = 0, fd;

	if (mod == NULL || !mod->active)
		return err;

	fd = open(mod->path, O_RDONLY);

	if (fd < 0)
		return err;

823
	err = dso__load_sym(self, fd, name, filter, v, mod);
824 825 826 827 828
	close(fd);

	return err;
}

829
int dso__load_modules(struct dso *self, symbol_filter_t filter, int v)
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
{
	struct mod_dso *mods = mod_dso__new_dso("modules");
	struct module *pos;
	struct rb_node *next;
	int err;

	err = mod_dso__load_modules(mods);

	if (err <= 0)
		return err;

	/*
	 * Iterate over modules, and load active symbols.
	 */
	next = rb_first(&mods->mods);
	while (next) {
		pos = rb_entry(next, struct module, rb_node);
847
		err = dso__load_module(self, mods, pos->name, filter, v);
848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888

		if (err < 0)
			break;

		next = rb_next(&pos->rb_node);
	}

	if (err < 0) {
		mod_dso__delete_modules(mods);
		mod_dso__delete_self(mods);
	}

	return err;
}

static inline void dso__fill_symbol_holes(struct dso *self)
{
	struct symbol *prev = NULL;
	struct rb_node *nd;

	for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) {
		struct symbol *pos = rb_entry(nd, struct symbol, rb_node);

		if (prev) {
			u64 hole = 0;
			int alias = pos->start == prev->start;

			if (!alias)
				hole = prev->start - pos->end - 1;

			if (hole || alias) {
				if (alias)
					pos->end = prev->end;
				else if (hole)
					pos->end = prev->start - 1;
			}
		}
		prev = pos;
	}
}

889
static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
890
			     symbol_filter_t filter, int v)
891 892 893 894 895 896
{
	int err, fd = open(vmlinux, O_RDONLY);

	if (fd < 0)
		return -1;

897
	err = dso__load_sym(self, fd, vmlinux, filter, v, NULL);
898 899 900 901

	if (err > 0)
		dso__fill_symbol_holes(self);

902 903 904 905 906
	close(fd);

	return err;
}

907
int dso__load_kernel(struct dso *self, const char *vmlinux,
908
		     symbol_filter_t filter, int v, int use_modules)
909 910 911
{
	int err = -1;

912
	if (vmlinux) {
913 914 915
		err = dso__load_vmlinux(self, vmlinux, filter, v);
		if (err > 0 && use_modules)
			err = dso__load_modules(self, filter, v);
916
	}
917

918
	if (err <= 0)
919
		err = dso__load_kallsyms(self, filter, v);
920

921 922 923
	if (err > 0)
		self->origin = DSO__ORIG_KERNEL;

924 925 926
	return err;
}

927 928 929 930 931
LIST_HEAD(dsos);
struct dso	*kernel_dso;
struct dso	*vdso;
struct dso	*hypervisor_dso;

932
const char	*vmlinux_name = "vmlinux";
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999
int		modules;

static void dsos__add(struct dso *dso)
{
	list_add_tail(&dso->node, &dsos);
}

static struct dso *dsos__find(const char *name)
{
	struct dso *pos;

	list_for_each_entry(pos, &dsos, node)
		if (strcmp(pos->name, name) == 0)
			return pos;
	return NULL;
}

struct dso *dsos__findnew(const char *name)
{
	struct dso *dso = dsos__find(name);
	int nr;

	if (dso)
		return dso;

	dso = dso__new(name, 0);
	if (!dso)
		goto out_delete_dso;

	nr = dso__load(dso, NULL, verbose);
	if (nr < 0) {
		eprintf("Failed to open: %s\n", name);
		goto out_delete_dso;
	}
	if (!nr)
		eprintf("No symbols found in: %s, maybe install a debug package?\n", name);

	dsos__add(dso);

	return dso;

out_delete_dso:
	dso__delete(dso);
	return NULL;
}

void dsos__fprintf(FILE *fp)
{
	struct dso *pos;

	list_for_each_entry(pos, &dsos, node)
		dso__fprintf(pos, fp);
}

static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
{
	return dso__find_symbol(dso, ip);
}

int load_kernel(void)
{
	int err;

	kernel_dso = dso__new("[kernel]", 0);
	if (!kernel_dso)
		return -1;

1000
	err = dso__load_kernel(kernel_dso, vmlinux_name, NULL, verbose, modules);
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
	if (err <= 0) {
		dso__delete(kernel_dso);
		kernel_dso = NULL;
	} else
		dsos__add(kernel_dso);

	vdso = dso__new("[vdso]", 0);
	if (!vdso)
		return -1;

	vdso->find_symbol = vdso__find_symbol;

	dsos__add(vdso);

	hypervisor_dso = dso__new("[hypervisor]", 0);
	if (!hypervisor_dso)
		return -1;
	dsos__add(hypervisor_dso);

	return err;
}


1024 1025 1026 1027
void symbol__init(void)
{
	elf_version(EV_CURRENT);
}