symbol.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. #include "util.h"
  2. #include "../perf.h"
  3. #include "string.h"
  4. #include "symbol.h"
  5. #include <libelf.h>
  6. #include <gelf.h>
  7. #include <elf.h>
  8. const char *sym_hist_filter;
  9. static struct symbol *symbol__new(u64 start, u64 len,
  10. const char *name, unsigned int priv_size,
  11. u64 obj_start, int verbose)
  12. {
  13. size_t namelen = strlen(name) + 1;
  14. struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen);
  15. if (!self)
  16. return NULL;
  17. if (verbose >= 2)
  18. printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n",
  19. (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start);
  20. self->obj_start= obj_start;
  21. self->hist = NULL;
  22. self->hist_sum = 0;
  23. if (sym_hist_filter && !strcmp(name, sym_hist_filter))
  24. self->hist = calloc(sizeof(u64), len);
  25. if (priv_size) {
  26. memset(self, 0, priv_size);
  27. self = ((void *)self) + priv_size;
  28. }
  29. self->start = start;
  30. self->end = len ? start + len - 1 : start;
  31. memcpy(self->name, name, namelen);
  32. return self;
  33. }
  34. static void symbol__delete(struct symbol *self, unsigned int priv_size)
  35. {
  36. free(((void *)self) - priv_size);
  37. }
  38. static size_t symbol__fprintf(struct symbol *self, FILE *fp)
  39. {
  40. if (!self->module)
  41. return fprintf(fp, " %llx-%llx %s\n",
  42. self->start, self->end, self->name);
  43. else
  44. return fprintf(fp, " %llx-%llx %s \t[%s]\n",
  45. self->start, self->end, self->name, self->module->name);
  46. }
  47. struct dso *dso__new(const char *name, unsigned int sym_priv_size)
  48. {
  49. struct dso *self = malloc(sizeof(*self) + strlen(name) + 1);
  50. if (self != NULL) {
  51. strcpy(self->name, name);
  52. self->syms = RB_ROOT;
  53. self->sym_priv_size = sym_priv_size;
  54. self->find_symbol = dso__find_symbol;
  55. }
  56. return self;
  57. }
  58. static void dso__delete_symbols(struct dso *self)
  59. {
  60. struct symbol *pos;
  61. struct rb_node *next = rb_first(&self->syms);
  62. while (next) {
  63. pos = rb_entry(next, struct symbol, rb_node);
  64. next = rb_next(&pos->rb_node);
  65. rb_erase(&pos->rb_node, &self->syms);
  66. symbol__delete(pos, self->sym_priv_size);
  67. }
  68. }
  69. void dso__delete(struct dso *self)
  70. {
  71. dso__delete_symbols(self);
  72. free(self);
  73. }
  74. static void dso__insert_symbol(struct dso *self, struct symbol *sym)
  75. {
  76. struct rb_node **p = &self->syms.rb_node;
  77. struct rb_node *parent = NULL;
  78. const u64 ip = sym->start;
  79. struct symbol *s;
  80. while (*p != NULL) {
  81. parent = *p;
  82. s = rb_entry(parent, struct symbol, rb_node);
  83. if (ip < s->start)
  84. p = &(*p)->rb_left;
  85. else
  86. p = &(*p)->rb_right;
  87. }
  88. rb_link_node(&sym->rb_node, parent, p);
  89. rb_insert_color(&sym->rb_node, &self->syms);
  90. }
  91. struct symbol *dso__find_symbol(struct dso *self, u64 ip)
  92. {
  93. struct rb_node *n;
  94. if (self == NULL)
  95. return NULL;
  96. n = self->syms.rb_node;
  97. while (n) {
  98. struct symbol *s = rb_entry(n, struct symbol, rb_node);
  99. if (ip < s->start)
  100. n = n->rb_left;
  101. else if (ip > s->end)
  102. n = n->rb_right;
  103. else
  104. return s;
  105. }
  106. return NULL;
  107. }
  108. size_t dso__fprintf(struct dso *self, FILE *fp)
  109. {
  110. size_t ret = fprintf(fp, "dso: %s\n", self->name);
  111. struct rb_node *nd;
  112. for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
  113. struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
  114. ret += symbol__fprintf(pos, fp);
  115. }
  116. return ret;
  117. }
  118. static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verbose)
  119. {
  120. struct rb_node *nd, *prevnd;
  121. char *line = NULL;
  122. size_t n;
  123. FILE *file = fopen("/proc/kallsyms", "r");
  124. int count = 0;
  125. if (file == NULL)
  126. goto out_failure;
  127. while (!feof(file)) {
  128. u64 start;
  129. struct symbol *sym;
  130. int line_len, len;
  131. char symbol_type;
  132. line_len = getline(&line, &n, file);
  133. if (line_len < 0)
  134. break;
  135. if (!line)
  136. goto out_failure;
  137. line[--line_len] = '\0'; /* \n */
  138. len = hex2u64(line, &start);
  139. len++;
  140. if (len + 2 >= line_len)
  141. continue;
  142. symbol_type = toupper(line[len]);
  143. /*
  144. * We're interested only in code ('T'ext)
  145. */
  146. if (symbol_type != 'T' && symbol_type != 'W')
  147. continue;
  148. /*
  149. * Well fix up the end later, when we have all sorted.
  150. */
  151. sym = symbol__new(start, 0xdead, line + len + 2,
  152. self->sym_priv_size, 0, verbose);
  153. if (sym == NULL)
  154. goto out_delete_line;
  155. if (filter && filter(self, sym))
  156. symbol__delete(sym, self->sym_priv_size);
  157. else {
  158. dso__insert_symbol(self, sym);
  159. count++;
  160. }
  161. }
  162. /*
  163. * Now that we have all sorted out, just set the ->end of all
  164. * symbols
  165. */
  166. prevnd = rb_first(&self->syms);
  167. if (prevnd == NULL)
  168. goto out_delete_line;
  169. for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
  170. struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node),
  171. *curr = rb_entry(nd, struct symbol, rb_node);
  172. prev->end = curr->start - 1;
  173. prevnd = nd;
  174. }
  175. free(line);
  176. fclose(file);
  177. return count;
  178. out_delete_line:
  179. free(line);
  180. out_failure:
  181. return -1;
  182. }
  183. static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int verbose)
  184. {
  185. char *line = NULL;
  186. size_t n;
  187. FILE *file;
  188. int nr_syms = 0;
  189. file = fopen(self->name, "r");
  190. if (file == NULL)
  191. goto out_failure;
  192. while (!feof(file)) {
  193. u64 start, size;
  194. struct symbol *sym;
  195. int line_len, len;
  196. line_len = getline(&line, &n, file);
  197. if (line_len < 0)
  198. break;
  199. if (!line)
  200. goto out_failure;
  201. line[--line_len] = '\0'; /* \n */
  202. len = hex2u64(line, &start);
  203. len++;
  204. if (len + 2 >= line_len)
  205. continue;
  206. len += hex2u64(line + len, &size);
  207. len++;
  208. if (len + 2 >= line_len)
  209. continue;
  210. sym = symbol__new(start, size, line + len,
  211. self->sym_priv_size, start, verbose);
  212. if (sym == NULL)
  213. goto out_delete_line;
  214. if (filter && filter(self, sym))
  215. symbol__delete(sym, self->sym_priv_size);
  216. else {
  217. dso__insert_symbol(self, sym);
  218. nr_syms++;
  219. }
  220. }
  221. free(line);
  222. fclose(file);
  223. return nr_syms;
  224. out_delete_line:
  225. free(line);
  226. out_failure:
  227. return -1;
  228. }
  229. /**
  230. * elf_symtab__for_each_symbol - iterate thru all the symbols
  231. *
  232. * @self: struct elf_symtab instance to iterate
  233. * @index: uint32_t index
  234. * @sym: GElf_Sym iterator
  235. */
  236. #define elf_symtab__for_each_symbol(syms, nr_syms, index, sym) \
  237. for (index = 0, gelf_getsym(syms, index, &sym);\
  238. index < nr_syms; \
  239. index++, gelf_getsym(syms, index, &sym))
  240. static inline uint8_t elf_sym__type(const GElf_Sym *sym)
  241. {
  242. return GELF_ST_TYPE(sym->st_info);
  243. }
  244. static inline int elf_sym__is_function(const GElf_Sym *sym)
  245. {
  246. return elf_sym__type(sym) == STT_FUNC &&
  247. sym->st_name != 0 &&
  248. sym->st_shndx != SHN_UNDEF &&
  249. sym->st_size != 0;
  250. }
  251. static inline int elf_sym__is_label(const GElf_Sym *sym)
  252. {
  253. return elf_sym__type(sym) == STT_NOTYPE &&
  254. sym->st_name != 0 &&
  255. sym->st_shndx != SHN_UNDEF &&
  256. sym->st_shndx != SHN_ABS;
  257. }
  258. static inline const char *elf_sec__name(const GElf_Shdr *shdr,
  259. const Elf_Data *secstrs)
  260. {
  261. return secstrs->d_buf + shdr->sh_name;
  262. }
  263. static inline int elf_sec__is_text(const GElf_Shdr *shdr,
  264. const Elf_Data *secstrs)
  265. {
  266. return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
  267. }
  268. static inline const char *elf_sym__name(const GElf_Sym *sym,
  269. const Elf_Data *symstrs)
  270. {
  271. return symstrs->d_buf + sym->st_name;
  272. }
  273. static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
  274. GElf_Shdr *shp, const char *name,
  275. size_t *index)
  276. {
  277. Elf_Scn *sec = NULL;
  278. size_t cnt = 1;
  279. while ((sec = elf_nextscn(elf, sec)) != NULL) {
  280. char *str;
  281. gelf_getshdr(sec, shp);
  282. str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
  283. if (!strcmp(name, str)) {
  284. if (index)
  285. *index = cnt;
  286. break;
  287. }
  288. ++cnt;
  289. }
  290. return sec;
  291. }
  292. #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
  293. for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
  294. idx < nr_entries; \
  295. ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))
  296. #define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
  297. for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
  298. idx < nr_entries; \
  299. ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
  300. static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
  301. GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym,
  302. GElf_Shdr *shdr_dynsym,
  303. size_t dynsym_idx, int verbose)
  304. {
  305. uint32_t nr_rel_entries, idx;
  306. GElf_Sym sym;
  307. u64 plt_offset;
  308. GElf_Shdr shdr_plt;
  309. struct symbol *f;
  310. GElf_Shdr shdr_rel_plt;
  311. Elf_Data *reldata, *syms, *symstrs;
  312. Elf_Scn *scn_plt_rel, *scn_symstrs;
  313. char sympltname[1024];
  314. int nr = 0, symidx;
  315. scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt,
  316. ".rela.plt", NULL);
  317. if (scn_plt_rel == NULL) {
  318. scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt,
  319. ".rel.plt", NULL);
  320. if (scn_plt_rel == NULL)
  321. return 0;
  322. }
  323. if (shdr_rel_plt.sh_link != dynsym_idx)
  324. return 0;
  325. if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL)
  326. return 0;
  327. /*
  328. * Fetch the relocation section to find the indexes to the GOT
  329. * and the symbols in the .dynsym they refer to.
  330. */
  331. reldata = elf_getdata(scn_plt_rel, NULL);
  332. if (reldata == NULL)
  333. return -1;
  334. syms = elf_getdata(scn_dynsym, NULL);
  335. if (syms == NULL)
  336. return -1;
  337. scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link);
  338. if (scn_symstrs == NULL)
  339. return -1;
  340. symstrs = elf_getdata(scn_symstrs, NULL);
  341. if (symstrs == NULL)
  342. return -1;
  343. nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
  344. plt_offset = shdr_plt.sh_offset;
  345. if (shdr_rel_plt.sh_type == SHT_RELA) {
  346. GElf_Rela pos_mem, *pos;
  347. elf_section__for_each_rela(reldata, pos, pos_mem, idx,
  348. nr_rel_entries) {
  349. symidx = GELF_R_SYM(pos->r_info);
  350. plt_offset += shdr_plt.sh_entsize;
  351. gelf_getsym(syms, symidx, &sym);
  352. snprintf(sympltname, sizeof(sympltname),
  353. "%s@plt", elf_sym__name(&sym, symstrs));
  354. f = symbol__new(plt_offset, shdr_plt.sh_entsize,
  355. sympltname, self->sym_priv_size, 0, verbose);
  356. if (!f)
  357. return -1;
  358. dso__insert_symbol(self, f);
  359. ++nr;
  360. }
  361. } else if (shdr_rel_plt.sh_type == SHT_REL) {
  362. GElf_Rel pos_mem, *pos;
  363. elf_section__for_each_rel(reldata, pos, pos_mem, idx,
  364. nr_rel_entries) {
  365. symidx = GELF_R_SYM(pos->r_info);
  366. plt_offset += shdr_plt.sh_entsize;
  367. gelf_getsym(syms, symidx, &sym);
  368. snprintf(sympltname, sizeof(sympltname),
  369. "%s@plt", elf_sym__name(&sym, symstrs));
  370. f = symbol__new(plt_offset, shdr_plt.sh_entsize,
  371. sympltname, self->sym_priv_size, 0, verbose);
  372. if (!f)
  373. return -1;
  374. dso__insert_symbol(self, f);
  375. ++nr;
  376. }
  377. } else {
  378. /*
  379. * TODO: There are still one more shdr_rel_plt.sh_type
  380. * I have to investigate, but probably should be ignored.
  381. */
  382. }
  383. return nr;
  384. }
  385. static int dso__load_sym(struct dso *self, int fd, const char *name,
  386. symbol_filter_t filter, int verbose, struct module *mod)
  387. {
  388. Elf_Data *symstrs, *secstrs;
  389. uint32_t nr_syms;
  390. int err = -1;
  391. uint32_t index;
  392. GElf_Ehdr ehdr;
  393. GElf_Shdr shdr;
  394. Elf_Data *syms;
  395. GElf_Sym sym;
  396. Elf_Scn *sec, *sec_dynsym, *sec_strndx;
  397. Elf *elf;
  398. size_t dynsym_idx;
  399. int nr = 0;
  400. elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
  401. if (elf == NULL) {
  402. if (verbose)
  403. fprintf(stderr, "%s: cannot read %s ELF file.\n",
  404. __func__, name);
  405. goto out_close;
  406. }
  407. if (gelf_getehdr(elf, &ehdr) == NULL) {
  408. if (verbose)
  409. fprintf(stderr, "%s: cannot get elf header.\n", __func__);
  410. goto out_elf_end;
  411. }
  412. /*
  413. * We need to check if we have a .dynsym, so that we can handle the
  414. * .plt, synthesizing its symbols, that aren't on the symtabs (be it
  415. * .dynsym or .symtab)
  416. */
  417. sec_dynsym = elf_section_by_name(elf, &ehdr, &shdr,
  418. ".dynsym", &dynsym_idx);
  419. if (sec_dynsym != NULL) {
  420. nr = dso__synthesize_plt_symbols(self, elf, &ehdr,
  421. sec_dynsym, &shdr,
  422. dynsym_idx, verbose);
  423. if (nr < 0)
  424. goto out_elf_end;
  425. }
  426. /*
  427. * But if we have a full .symtab (that is a superset of .dynsym) we
  428. * should add the symbols not in the .dynsyn
  429. */
  430. sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
  431. if (sec == NULL) {
  432. if (sec_dynsym == NULL)
  433. goto out_elf_end;
  434. sec = sec_dynsym;
  435. gelf_getshdr(sec, &shdr);
  436. }
  437. syms = elf_getdata(sec, NULL);
  438. if (syms == NULL)
  439. goto out_elf_end;
  440. sec = elf_getscn(elf, shdr.sh_link);
  441. if (sec == NULL)
  442. goto out_elf_end;
  443. symstrs = elf_getdata(sec, NULL);
  444. if (symstrs == NULL)
  445. goto out_elf_end;
  446. sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
  447. if (sec_strndx == NULL)
  448. goto out_elf_end;
  449. secstrs = elf_getdata(sec_strndx, NULL);
  450. if (symstrs == NULL)
  451. goto out_elf_end;
  452. nr_syms = shdr.sh_size / shdr.sh_entsize;
  453. memset(&sym, 0, sizeof(sym));
  454. self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
  455. elf_section_by_name(elf, &ehdr, &shdr,
  456. ".gnu.prelink_undo",
  457. NULL) != NULL);
  458. elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
  459. struct symbol *f;
  460. u64 obj_start;
  461. struct section *section = NULL;
  462. int is_label = elf_sym__is_label(&sym);
  463. const char *section_name;
  464. if (!is_label && !elf_sym__is_function(&sym))
  465. continue;
  466. sec = elf_getscn(elf, sym.st_shndx);
  467. if (!sec)
  468. goto out_elf_end;
  469. gelf_getshdr(sec, &shdr);
  470. if (is_label && !elf_sec__is_text(&shdr, secstrs))
  471. continue;
  472. section_name = elf_sec__name(&shdr, secstrs);
  473. obj_start = sym.st_value;
  474. if (self->adjust_symbols) {
  475. if (verbose >= 2)
  476. printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
  477. (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
  478. sym.st_value -= shdr.sh_addr - shdr.sh_offset;
  479. }
  480. if (mod) {
  481. section = mod->sections->find_section(mod->sections, section_name);
  482. if (section)
  483. sym.st_value += section->vma;
  484. else {
  485. fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
  486. mod->name, section_name);
  487. goto out_elf_end;
  488. }
  489. }
  490. f = symbol__new(sym.st_value, sym.st_size,
  491. elf_sym__name(&sym, symstrs),
  492. self->sym_priv_size, obj_start, verbose);
  493. if (!f)
  494. goto out_elf_end;
  495. if (filter && filter(self, f))
  496. symbol__delete(f, self->sym_priv_size);
  497. else {
  498. f->module = mod;
  499. dso__insert_symbol(self, f);
  500. nr++;
  501. }
  502. }
  503. err = nr;
  504. out_elf_end:
  505. elf_end(elf);
  506. out_close:
  507. return err;
  508. }
  509. int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
  510. {
  511. int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug");
  512. char *name = malloc(size);
  513. int variant = 0;
  514. int ret = -1;
  515. int fd;
  516. if (!name)
  517. return -1;
  518. self->adjust_symbols = 0;
  519. if (strncmp(self->name, "/tmp/perf-", 10) == 0)
  520. return dso__load_perf_map(self, filter, verbose);
  521. more:
  522. do {
  523. switch (variant) {
  524. case 0: /* Fedora */
  525. snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
  526. break;
  527. case 1: /* Ubuntu */
  528. snprintf(name, size, "/usr/lib/debug%s", self->name);
  529. break;
  530. case 2: /* Sane people */
  531. snprintf(name, size, "%s", self->name);
  532. break;
  533. default:
  534. goto out;
  535. }
  536. variant++;
  537. fd = open(name, O_RDONLY);
  538. } while (fd < 0);
  539. ret = dso__load_sym(self, fd, name, filter, verbose, NULL);
  540. close(fd);
  541. /*
  542. * Some people seem to have debuginfo files _WITHOUT_ debug info!?!?
  543. */
  544. if (!ret)
  545. goto more;
  546. out:
  547. free(name);
  548. return ret;
  549. }
  550. static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name,
  551. symbol_filter_t filter, int verbose)
  552. {
  553. struct module *mod = mod_dso__find_module(mods, name);
  554. int err = 0, fd;
  555. if (mod == NULL || !mod->active)
  556. return err;
  557. fd = open(mod->path, O_RDONLY);
  558. if (fd < 0)
  559. return err;
  560. err = dso__load_sym(self, fd, name, filter, verbose, mod);
  561. close(fd);
  562. return err;
  563. }
  564. int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose)
  565. {
  566. struct mod_dso *mods = mod_dso__new_dso("modules");
  567. struct module *pos;
  568. struct rb_node *next;
  569. int err;
  570. err = mod_dso__load_modules(mods);
  571. if (err <= 0)
  572. return err;
  573. /*
  574. * Iterate over modules, and load active symbols.
  575. */
  576. next = rb_first(&mods->mods);
  577. while (next) {
  578. pos = rb_entry(next, struct module, rb_node);
  579. err = dso__load_module(self, mods, pos->name, filter, verbose);
  580. if (err < 0)
  581. break;
  582. next = rb_next(&pos->rb_node);
  583. }
  584. if (err < 0) {
  585. mod_dso__delete_modules(mods);
  586. mod_dso__delete_self(mods);
  587. }
  588. return err;
  589. }
  590. static inline void dso__fill_symbol_holes(struct dso *self)
  591. {
  592. struct symbol *prev = NULL;
  593. struct rb_node *nd;
  594. for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) {
  595. struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
  596. if (prev) {
  597. u64 hole = 0;
  598. int alias = pos->start == prev->start;
  599. if (!alias)
  600. hole = prev->start - pos->end - 1;
  601. if (hole || alias) {
  602. if (alias)
  603. pos->end = prev->end;
  604. else if (hole)
  605. pos->end = prev->start - 1;
  606. }
  607. }
  608. prev = pos;
  609. }
  610. }
  611. static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
  612. symbol_filter_t filter, int verbose)
  613. {
  614. int err, fd = open(vmlinux, O_RDONLY);
  615. if (fd < 0)
  616. return -1;
  617. err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL);
  618. if (err > 0)
  619. dso__fill_symbol_holes(self);
  620. close(fd);
  621. return err;
  622. }
  623. int dso__load_kernel(struct dso *self, const char *vmlinux,
  624. symbol_filter_t filter, int verbose, int modules)
  625. {
  626. int err = -1;
  627. if (vmlinux) {
  628. err = dso__load_vmlinux(self, vmlinux, filter, verbose);
  629. if (err > 0 && modules)
  630. err = dso__load_modules(self, filter, verbose);
  631. }
  632. if (err <= 0)
  633. err = dso__load_kallsyms(self, filter, verbose);
  634. return err;
  635. }
  636. void symbol__init(void)
  637. {
  638. elf_version(EV_CURRENT);
  639. }