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