1 #include "util.h" 2 #include "../perf.h" 3 #include "string.h" 4 #include "symbol.h" 5 6 #include <libelf.h> 7 #include <gelf.h> 8 #include <elf.h> 9 10 #ifndef NO_DEMANGLE 11 #include <bfd.h> 12 #else 13 static inline 14 char *bfd_demangle(void __used *v, const char __used *c, int __used i) 15 { 16 return NULL; 17 } 18 #endif 19 20 const char *sym_hist_filter; 21 22 #ifndef DMGL_PARAMS 23 #define DMGL_PARAMS (1 << 0) /* Include function args */ 24 #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ 25 #endif 26 27 static struct symbol *symbol__new(u64 start, u64 len, 28 const char *name, unsigned int priv_size, 29 u64 obj_start, int verbose) 30 { 31 size_t namelen = strlen(name) + 1; 32 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); 33 34 if (!self) 35 return NULL; 36 37 if (verbose >= 2) 38 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n", 39 (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start); 40 41 self->obj_start= obj_start; 42 self->hist = NULL; 43 self->hist_sum = 0; 44 45 if (sym_hist_filter && !strcmp(name, sym_hist_filter)) 46 self->hist = calloc(sizeof(u64), len); 47 48 if (priv_size) { 49 memset(self, 0, priv_size); 50 self = ((void *)self) + priv_size; 51 } 52 self->start = start; 53 self->end = len ? start + len - 1 : start; 54 memcpy(self->name, name, namelen); 55 56 return self; 57 } 58 59 static void symbol__delete(struct symbol *self, unsigned int priv_size) 60 { 61 free(((void *)self) - priv_size); 62 } 63 64 static size_t symbol__fprintf(struct symbol *self, FILE *fp) 65 { 66 if (!self->module) 67 return fprintf(fp, " %llx-%llx %s\n", 68 self->start, self->end, self->name); 69 else 70 return fprintf(fp, " %llx-%llx %s \t[%s]\n", 71 self->start, self->end, self->name, self->module->name); 72 } 73 74 struct dso *dso__new(const char *name, unsigned int sym_priv_size) 75 { 76 struct dso *self = malloc(sizeof(*self) + strlen(name) + 1); 77 78 if (self != NULL) { 79 strcpy(self->name, name); 80 self->syms = RB_ROOT; 81 self->sym_priv_size = sym_priv_size; 82 self->find_symbol = dso__find_symbol; 83 self->slen_calculated = 0; 84 } 85 86 return self; 87 } 88 89 static void dso__delete_symbols(struct dso *self) 90 { 91 struct symbol *pos; 92 struct rb_node *next = rb_first(&self->syms); 93 94 while (next) { 95 pos = rb_entry(next, struct symbol, rb_node); 96 next = rb_next(&pos->rb_node); 97 rb_erase(&pos->rb_node, &self->syms); 98 symbol__delete(pos, self->sym_priv_size); 99 } 100 } 101 102 void dso__delete(struct dso *self) 103 { 104 dso__delete_symbols(self); 105 free(self); 106 } 107 108 static void dso__insert_symbol(struct dso *self, struct symbol *sym) 109 { 110 struct rb_node **p = &self->syms.rb_node; 111 struct rb_node *parent = NULL; 112 const u64 ip = sym->start; 113 struct symbol *s; 114 115 while (*p != NULL) { 116 parent = *p; 117 s = rb_entry(parent, struct symbol, rb_node); 118 if (ip < s->start) 119 p = &(*p)->rb_left; 120 else 121 p = &(*p)->rb_right; 122 } 123 rb_link_node(&sym->rb_node, parent, p); 124 rb_insert_color(&sym->rb_node, &self->syms); 125 } 126 127 struct symbol *dso__find_symbol(struct dso *self, u64 ip) 128 { 129 struct rb_node *n; 130 131 if (self == NULL) 132 return NULL; 133 134 n = self->syms.rb_node; 135 136 while (n) { 137 struct symbol *s = rb_entry(n, struct symbol, rb_node); 138 139 if (ip < s->start) 140 n = n->rb_left; 141 else if (ip > s->end) 142 n = n->rb_right; 143 else 144 return s; 145 } 146 147 return NULL; 148 } 149 150 size_t dso__fprintf(struct dso *self, FILE *fp) 151 { 152 size_t ret = fprintf(fp, "dso: %s\n", self->name); 153 154 struct rb_node *nd; 155 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) { 156 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 157 ret += symbol__fprintf(pos, fp); 158 } 159 160 return ret; 161 } 162 163 static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verbose) 164 { 165 struct rb_node *nd, *prevnd; 166 char *line = NULL; 167 size_t n; 168 FILE *file = fopen("/proc/kallsyms", "r"); 169 int count = 0; 170 171 if (file == NULL) 172 goto out_failure; 173 174 while (!feof(file)) { 175 u64 start; 176 struct symbol *sym; 177 int line_len, len; 178 char symbol_type; 179 180 line_len = getline(&line, &n, file); 181 if (line_len < 0) 182 break; 183 184 if (!line) 185 goto out_failure; 186 187 line[--line_len] = '\0'; /* \n */ 188 189 len = hex2u64(line, &start); 190 191 len++; 192 if (len + 2 >= line_len) 193 continue; 194 195 symbol_type = toupper(line[len]); 196 /* 197 * We're interested only in code ('T'ext) 198 */ 199 if (symbol_type != 'T' && symbol_type != 'W') 200 continue; 201 /* 202 * Well fix up the end later, when we have all sorted. 203 */ 204 sym = symbol__new(start, 0xdead, line + len + 2, 205 self->sym_priv_size, 0, verbose); 206 207 if (sym == NULL) 208 goto out_delete_line; 209 210 if (filter && filter(self, sym)) 211 symbol__delete(sym, self->sym_priv_size); 212 else { 213 dso__insert_symbol(self, sym); 214 count++; 215 } 216 } 217 218 /* 219 * Now that we have all sorted out, just set the ->end of all 220 * symbols 221 */ 222 prevnd = rb_first(&self->syms); 223 224 if (prevnd == NULL) 225 goto out_delete_line; 226 227 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 228 struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node), 229 *curr = rb_entry(nd, struct symbol, rb_node); 230 231 prev->end = curr->start - 1; 232 prevnd = nd; 233 } 234 235 free(line); 236 fclose(file); 237 238 return count; 239 240 out_delete_line: 241 free(line); 242 out_failure: 243 return -1; 244 } 245 246 static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int verbose) 247 { 248 char *line = NULL; 249 size_t n; 250 FILE *file; 251 int nr_syms = 0; 252 253 file = fopen(self->name, "r"); 254 if (file == NULL) 255 goto out_failure; 256 257 while (!feof(file)) { 258 u64 start, size; 259 struct symbol *sym; 260 int line_len, len; 261 262 line_len = getline(&line, &n, file); 263 if (line_len < 0) 264 break; 265 266 if (!line) 267 goto out_failure; 268 269 line[--line_len] = '\0'; /* \n */ 270 271 len = hex2u64(line, &start); 272 273 len++; 274 if (len + 2 >= line_len) 275 continue; 276 277 len += hex2u64(line + len, &size); 278 279 len++; 280 if (len + 2 >= line_len) 281 continue; 282 283 sym = symbol__new(start, size, line + len, 284 self->sym_priv_size, start, verbose); 285 286 if (sym == NULL) 287 goto out_delete_line; 288 289 if (filter && filter(self, sym)) 290 symbol__delete(sym, self->sym_priv_size); 291 else { 292 dso__insert_symbol(self, sym); 293 nr_syms++; 294 } 295 } 296 297 free(line); 298 fclose(file); 299 300 return nr_syms; 301 302 out_delete_line: 303 free(line); 304 out_failure: 305 return -1; 306 } 307 308 /** 309 * elf_symtab__for_each_symbol - iterate thru all the symbols 310 * 311 * @self: struct elf_symtab instance to iterate 312 * @index: uint32_t index 313 * @sym: GElf_Sym iterator 314 */ 315 #define elf_symtab__for_each_symbol(syms, nr_syms, index, sym) \ 316 for (index = 0, gelf_getsym(syms, index, &sym);\ 317 index < nr_syms; \ 318 index++, gelf_getsym(syms, index, &sym)) 319 320 static inline uint8_t elf_sym__type(const GElf_Sym *sym) 321 { 322 return GELF_ST_TYPE(sym->st_info); 323 } 324 325 static inline int elf_sym__is_function(const GElf_Sym *sym) 326 { 327 return elf_sym__type(sym) == STT_FUNC && 328 sym->st_name != 0 && 329 sym->st_shndx != SHN_UNDEF && 330 sym->st_size != 0; 331 } 332 333 static inline int elf_sym__is_label(const GElf_Sym *sym) 334 { 335 return elf_sym__type(sym) == STT_NOTYPE && 336 sym->st_name != 0 && 337 sym->st_shndx != SHN_UNDEF && 338 sym->st_shndx != SHN_ABS; 339 } 340 341 static inline const char *elf_sec__name(const GElf_Shdr *shdr, 342 const Elf_Data *secstrs) 343 { 344 return secstrs->d_buf + shdr->sh_name; 345 } 346 347 static inline int elf_sec__is_text(const GElf_Shdr *shdr, 348 const Elf_Data *secstrs) 349 { 350 return strstr(elf_sec__name(shdr, secstrs), "text") != NULL; 351 } 352 353 static inline const char *elf_sym__name(const GElf_Sym *sym, 354 const Elf_Data *symstrs) 355 { 356 return symstrs->d_buf + sym->st_name; 357 } 358 359 static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, 360 GElf_Shdr *shp, const char *name, 361 size_t *index) 362 { 363 Elf_Scn *sec = NULL; 364 size_t cnt = 1; 365 366 while ((sec = elf_nextscn(elf, sec)) != NULL) { 367 char *str; 368 369 gelf_getshdr(sec, shp); 370 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); 371 if (!strcmp(name, str)) { 372 if (index) 373 *index = cnt; 374 break; 375 } 376 ++cnt; 377 } 378 379 return sec; 380 } 381 382 #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \ 383 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \ 384 idx < nr_entries; \ 385 ++idx, pos = gelf_getrel(reldata, idx, &pos_mem)) 386 387 #define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \ 388 for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \ 389 idx < nr_entries; \ 390 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) 391 392 /* 393 * We need to check if we have a .dynsym, so that we can handle the 394 * .plt, synthesizing its symbols, that aren't on the symtabs (be it 395 * .dynsym or .symtab). 396 * And always look at the original dso, not at debuginfo packages, that 397 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). 398 */ 399 static int dso__synthesize_plt_symbols(struct dso *self, int verbose) 400 { 401 uint32_t nr_rel_entries, idx; 402 GElf_Sym sym; 403 u64 plt_offset; 404 GElf_Shdr shdr_plt; 405 struct symbol *f; 406 GElf_Shdr shdr_rel_plt, shdr_dynsym; 407 Elf_Data *reldata, *syms, *symstrs; 408 Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym; 409 size_t dynsym_idx; 410 GElf_Ehdr ehdr; 411 char sympltname[1024]; 412 Elf *elf; 413 int nr = 0, symidx, fd, err = 0; 414 415 fd = open(self->name, O_RDONLY); 416 if (fd < 0) 417 goto out; 418 419 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 420 if (elf == NULL) 421 goto out_close; 422 423 if (gelf_getehdr(elf, &ehdr) == NULL) 424 goto out_elf_end; 425 426 scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym, 427 ".dynsym", &dynsym_idx); 428 if (scn_dynsym == NULL) 429 goto out_elf_end; 430 431 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, 432 ".rela.plt", NULL); 433 if (scn_plt_rel == NULL) { 434 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, 435 ".rel.plt", NULL); 436 if (scn_plt_rel == NULL) 437 goto out_elf_end; 438 } 439 440 err = -1; 441 442 if (shdr_rel_plt.sh_link != dynsym_idx) 443 goto out_elf_end; 444 445 if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL) 446 goto out_elf_end; 447 448 /* 449 * Fetch the relocation section to find the indexes to the GOT 450 * and the symbols in the .dynsym they refer to. 451 */ 452 reldata = elf_getdata(scn_plt_rel, NULL); 453 if (reldata == NULL) 454 goto out_elf_end; 455 456 syms = elf_getdata(scn_dynsym, NULL); 457 if (syms == NULL) 458 goto out_elf_end; 459 460 scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link); 461 if (scn_symstrs == NULL) 462 goto out_elf_end; 463 464 symstrs = elf_getdata(scn_symstrs, NULL); 465 if (symstrs == NULL) 466 goto out_elf_end; 467 468 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; 469 plt_offset = shdr_plt.sh_offset; 470 471 if (shdr_rel_plt.sh_type == SHT_RELA) { 472 GElf_Rela pos_mem, *pos; 473 474 elf_section__for_each_rela(reldata, pos, pos_mem, idx, 475 nr_rel_entries) { 476 symidx = GELF_R_SYM(pos->r_info); 477 plt_offset += shdr_plt.sh_entsize; 478 gelf_getsym(syms, symidx, &sym); 479 snprintf(sympltname, sizeof(sympltname), 480 "%s@plt", elf_sym__name(&sym, symstrs)); 481 482 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 483 sympltname, self->sym_priv_size, 0, verbose); 484 if (!f) 485 goto out_elf_end; 486 487 dso__insert_symbol(self, f); 488 ++nr; 489 } 490 } else if (shdr_rel_plt.sh_type == SHT_REL) { 491 GElf_Rel pos_mem, *pos; 492 elf_section__for_each_rel(reldata, pos, pos_mem, idx, 493 nr_rel_entries) { 494 symidx = GELF_R_SYM(pos->r_info); 495 plt_offset += shdr_plt.sh_entsize; 496 gelf_getsym(syms, symidx, &sym); 497 snprintf(sympltname, sizeof(sympltname), 498 "%s@plt", elf_sym__name(&sym, symstrs)); 499 500 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 501 sympltname, self->sym_priv_size, 0, verbose); 502 if (!f) 503 goto out_elf_end; 504 505 dso__insert_symbol(self, f); 506 ++nr; 507 } 508 } 509 510 err = 0; 511 out_elf_end: 512 elf_end(elf); 513 out_close: 514 close(fd); 515 516 if (err == 0) 517 return nr; 518 out: 519 fprintf(stderr, "%s: problems reading %s PLT info.\n", 520 __func__, self->name); 521 return 0; 522 } 523 524 static int dso__load_sym(struct dso *self, int fd, const char *name, 525 symbol_filter_t filter, int verbose, struct module *mod) 526 { 527 Elf_Data *symstrs, *secstrs; 528 uint32_t nr_syms; 529 int err = -1; 530 uint32_t index; 531 GElf_Ehdr ehdr; 532 GElf_Shdr shdr; 533 Elf_Data *syms; 534 GElf_Sym sym; 535 Elf_Scn *sec, *sec_strndx; 536 Elf *elf; 537 int nr = 0, kernel = !strcmp("[kernel]", self->name); 538 539 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 540 if (elf == NULL) { 541 if (verbose) 542 fprintf(stderr, "%s: cannot read %s ELF file.\n", 543 __func__, name); 544 goto out_close; 545 } 546 547 if (gelf_getehdr(elf, &ehdr) == NULL) { 548 if (verbose) 549 fprintf(stderr, "%s: cannot get elf header.\n", __func__); 550 goto out_elf_end; 551 } 552 553 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); 554 if (sec == NULL) { 555 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); 556 if (sec == NULL) 557 goto out_elf_end; 558 } 559 560 syms = elf_getdata(sec, NULL); 561 if (syms == NULL) 562 goto out_elf_end; 563 564 sec = elf_getscn(elf, shdr.sh_link); 565 if (sec == NULL) 566 goto out_elf_end; 567 568 symstrs = elf_getdata(sec, NULL); 569 if (symstrs == NULL) 570 goto out_elf_end; 571 572 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); 573 if (sec_strndx == NULL) 574 goto out_elf_end; 575 576 secstrs = elf_getdata(sec_strndx, NULL); 577 if (secstrs == NULL) 578 goto out_elf_end; 579 580 nr_syms = shdr.sh_size / shdr.sh_entsize; 581 582 memset(&sym, 0, sizeof(sym)); 583 if (!kernel) { 584 self->adjust_symbols = (ehdr.e_type == ET_EXEC || 585 elf_section_by_name(elf, &ehdr, &shdr, 586 ".gnu.prelink_undo", 587 NULL) != NULL); 588 } else self->adjust_symbols = 0; 589 590 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 591 struct symbol *f; 592 const char *name; 593 char *demangled; 594 u64 obj_start; 595 struct section *section = NULL; 596 int is_label = elf_sym__is_label(&sym); 597 const char *section_name; 598 599 if (!is_label && !elf_sym__is_function(&sym)) 600 continue; 601 602 sec = elf_getscn(elf, sym.st_shndx); 603 if (!sec) 604 goto out_elf_end; 605 606 gelf_getshdr(sec, &shdr); 607 608 if (is_label && !elf_sec__is_text(&shdr, secstrs)) 609 continue; 610 611 section_name = elf_sec__name(&shdr, secstrs); 612 obj_start = sym.st_value; 613 614 if (self->adjust_symbols) { 615 if (verbose >= 2) 616 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", 617 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 618 619 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 620 } 621 622 if (mod) { 623 section = mod->sections->find_section(mod->sections, section_name); 624 if (section) 625 sym.st_value += section->vma; 626 else { 627 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n", 628 mod->name, section_name); 629 goto out_elf_end; 630 } 631 } 632 /* 633 * We need to figure out if the object was created from C++ sources 634 * DWARF DW_compile_unit has this, but we don't always have access 635 * to it... 636 */ 637 name = elf_sym__name(&sym, symstrs); 638 demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI); 639 if (demangled != NULL) 640 name = demangled; 641 642 f = symbol__new(sym.st_value, sym.st_size, name, 643 self->sym_priv_size, obj_start, verbose); 644 free(demangled); 645 if (!f) 646 goto out_elf_end; 647 648 if (filter && filter(self, f)) 649 symbol__delete(f, self->sym_priv_size); 650 else { 651 f->module = mod; 652 dso__insert_symbol(self, f); 653 nr++; 654 } 655 } 656 657 err = nr; 658 out_elf_end: 659 elf_end(elf); 660 out_close: 661 return err; 662 } 663 664 #define BUILD_ID_SIZE 128 665 666 static char *dso__read_build_id(struct dso *self, int verbose) 667 { 668 int i; 669 GElf_Ehdr ehdr; 670 GElf_Shdr shdr; 671 Elf_Data *build_id_data; 672 Elf_Scn *sec; 673 char *build_id = NULL, *bid; 674 unsigned char *raw; 675 Elf *elf; 676 int fd = open(self->name, O_RDONLY); 677 678 if (fd < 0) 679 goto out; 680 681 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 682 if (elf == NULL) { 683 if (verbose) 684 fprintf(stderr, "%s: cannot read %s ELF file.\n", 685 __func__, self->name); 686 goto out_close; 687 } 688 689 if (gelf_getehdr(elf, &ehdr) == NULL) { 690 if (verbose) 691 fprintf(stderr, "%s: cannot get elf header.\n", __func__); 692 goto out_elf_end; 693 } 694 695 sec = elf_section_by_name(elf, &ehdr, &shdr, ".note.gnu.build-id", NULL); 696 if (sec == NULL) 697 goto out_elf_end; 698 699 build_id_data = elf_getdata(sec, NULL); 700 if (build_id_data == NULL) 701 goto out_elf_end; 702 build_id = malloc(BUILD_ID_SIZE); 703 if (build_id == NULL) 704 goto out_elf_end; 705 raw = build_id_data->d_buf + 16; 706 bid = build_id; 707 708 for (i = 0; i < 20; ++i) { 709 sprintf(bid, "%02x", *raw); 710 ++raw; 711 bid += 2; 712 } 713 if (verbose) 714 printf("%s(%s): %s\n", __func__, self->name, build_id); 715 out_elf_end: 716 elf_end(elf); 717 out_close: 718 close(fd); 719 out: 720 return build_id; 721 } 722 723 int dso__load(struct dso *self, symbol_filter_t filter, int verbose) 724 { 725 int size = PATH_MAX; 726 char *name = malloc(size), *build_id = NULL; 727 int variant = 0; 728 int ret = -1; 729 int fd; 730 731 if (!name) 732 return -1; 733 734 self->adjust_symbols = 0; 735 736 if (strncmp(self->name, "/tmp/perf-", 10) == 0) 737 return dso__load_perf_map(self, filter, verbose); 738 739 more: 740 do { 741 switch (variant) { 742 case 0: /* Fedora */ 743 snprintf(name, size, "/usr/lib/debug%s.debug", self->name); 744 break; 745 case 1: /* Ubuntu */ 746 snprintf(name, size, "/usr/lib/debug%s", self->name); 747 break; 748 case 2: 749 build_id = dso__read_build_id(self, verbose); 750 if (build_id != NULL) { 751 snprintf(name, size, 752 "/usr/lib/debug/.build-id/%.2s/%s.debug", 753 build_id, build_id + 2); 754 free(build_id); 755 break; 756 } 757 variant++; 758 /* Fall thru */ 759 case 3: /* Sane people */ 760 snprintf(name, size, "%s", self->name); 761 break; 762 763 default: 764 goto out; 765 } 766 variant++; 767 768 fd = open(name, O_RDONLY); 769 } while (fd < 0); 770 771 ret = dso__load_sym(self, fd, name, filter, verbose, NULL); 772 close(fd); 773 774 /* 775 * Some people seem to have debuginfo files _WITHOUT_ debug info!?!? 776 */ 777 if (!ret) 778 goto more; 779 780 if (ret > 0) { 781 int nr_plt = dso__synthesize_plt_symbols(self, verbose); 782 if (nr_plt > 0) 783 ret += nr_plt; 784 } 785 out: 786 free(name); 787 return ret; 788 } 789 790 static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, 791 symbol_filter_t filter, int verbose) 792 { 793 struct module *mod = mod_dso__find_module(mods, name); 794 int err = 0, fd; 795 796 if (mod == NULL || !mod->active) 797 return err; 798 799 fd = open(mod->path, O_RDONLY); 800 801 if (fd < 0) 802 return err; 803 804 err = dso__load_sym(self, fd, name, filter, verbose, mod); 805 close(fd); 806 807 return err; 808 } 809 810 int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose) 811 { 812 struct mod_dso *mods = mod_dso__new_dso("modules"); 813 struct module *pos; 814 struct rb_node *next; 815 int err; 816 817 err = mod_dso__load_modules(mods); 818 819 if (err <= 0) 820 return err; 821 822 /* 823 * Iterate over modules, and load active symbols. 824 */ 825 next = rb_first(&mods->mods); 826 while (next) { 827 pos = rb_entry(next, struct module, rb_node); 828 err = dso__load_module(self, mods, pos->name, filter, verbose); 829 830 if (err < 0) 831 break; 832 833 next = rb_next(&pos->rb_node); 834 } 835 836 if (err < 0) { 837 mod_dso__delete_modules(mods); 838 mod_dso__delete_self(mods); 839 } 840 841 return err; 842 } 843 844 static inline void dso__fill_symbol_holes(struct dso *self) 845 { 846 struct symbol *prev = NULL; 847 struct rb_node *nd; 848 849 for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) { 850 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 851 852 if (prev) { 853 u64 hole = 0; 854 int alias = pos->start == prev->start; 855 856 if (!alias) 857 hole = prev->start - pos->end - 1; 858 859 if (hole || alias) { 860 if (alias) 861 pos->end = prev->end; 862 else if (hole) 863 pos->end = prev->start - 1; 864 } 865 } 866 prev = pos; 867 } 868 } 869 870 static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 871 symbol_filter_t filter, int verbose) 872 { 873 int err, fd = open(vmlinux, O_RDONLY); 874 875 if (fd < 0) 876 return -1; 877 878 err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL); 879 880 if (err > 0) 881 dso__fill_symbol_holes(self); 882 883 close(fd); 884 885 return err; 886 } 887 888 int dso__load_kernel(struct dso *self, const char *vmlinux, 889 symbol_filter_t filter, int verbose, int modules) 890 { 891 int err = -1; 892 893 if (vmlinux) { 894 err = dso__load_vmlinux(self, vmlinux, filter, verbose); 895 if (err > 0 && modules) 896 err = dso__load_modules(self, filter, verbose); 897 } 898 899 if (err <= 0) 900 err = dso__load_kallsyms(self, filter, verbose); 901 902 return err; 903 } 904 905 void symbol__init(void) 906 { 907 elf_version(EV_CURRENT); 908 } 909