probe-finder.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. /*
  2. * probe-finder.c : C expression to kprobe event converter
  3. *
  4. * Written by Masami Hiramatsu <mhiramat@redhat.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. *
  20. */
  21. #include <sys/utsname.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #include <fcntl.h>
  25. #include <errno.h>
  26. #include <stdio.h>
  27. #include <unistd.h>
  28. #include <getopt.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <stdarg.h>
  32. #include <ctype.h>
  33. #include "event.h"
  34. #include "debug.h"
  35. #include "util.h"
  36. #include "probe-finder.h"
  37. /* Dwarf_Die Linkage to parent Die */
  38. struct die_link {
  39. struct die_link *parent; /* Parent die */
  40. Dwarf_Die die; /* Current die */
  41. };
  42. static Dwarf_Debug __dw_debug;
  43. static Dwarf_Error __dw_error;
  44. /*
  45. * Generic dwarf analysis helpers
  46. */
  47. #define X86_32_MAX_REGS 8
  48. const char *x86_32_regs_table[X86_32_MAX_REGS] = {
  49. "%ax",
  50. "%cx",
  51. "%dx",
  52. "%bx",
  53. "$stack", /* Stack address instead of %sp */
  54. "%bp",
  55. "%si",
  56. "%di",
  57. };
  58. #define X86_64_MAX_REGS 16
  59. const char *x86_64_regs_table[X86_64_MAX_REGS] = {
  60. "%ax",
  61. "%dx",
  62. "%cx",
  63. "%bx",
  64. "%si",
  65. "%di",
  66. "%bp",
  67. "%sp",
  68. "%r8",
  69. "%r9",
  70. "%r10",
  71. "%r11",
  72. "%r12",
  73. "%r13",
  74. "%r14",
  75. "%r15",
  76. };
  77. /* TODO: switching by dwarf address size */
  78. #ifdef __x86_64__
  79. #define ARCH_MAX_REGS X86_64_MAX_REGS
  80. #define arch_regs_table x86_64_regs_table
  81. #else
  82. #define ARCH_MAX_REGS X86_32_MAX_REGS
  83. #define arch_regs_table x86_32_regs_table
  84. #endif
  85. /* Return architecture dependent register string (for kprobe-tracer) */
  86. static const char *get_arch_regstr(unsigned int n)
  87. {
  88. return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL;
  89. }
  90. /*
  91. * Compare the tail of two strings.
  92. * Return 0 if whole of either string is same as another's tail part.
  93. */
  94. static int strtailcmp(const char *s1, const char *s2)
  95. {
  96. int i1 = strlen(s1);
  97. int i2 = strlen(s2);
  98. while (--i1 > 0 && --i2 > 0) {
  99. if (s1[i1] != s2[i2])
  100. return s1[i1] - s2[i2];
  101. }
  102. return 0;
  103. }
  104. /* Find the fileno of the target file. */
  105. static Dwarf_Unsigned die_get_fileno(Dwarf_Die cu_die, const char *fname)
  106. {
  107. Dwarf_Signed cnt, i;
  108. Dwarf_Unsigned found = 0;
  109. char **srcs;
  110. int ret;
  111. if (!fname)
  112. return 0;
  113. ret = dwarf_srcfiles(cu_die, &srcs, &cnt, &__dw_error);
  114. if (ret == DW_DLV_OK) {
  115. for (i = 0; i < cnt && !found; i++) {
  116. if (strtailcmp(srcs[i], fname) == 0)
  117. found = i + 1;
  118. dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING);
  119. }
  120. for (; i < cnt; i++)
  121. dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING);
  122. dwarf_dealloc(__dw_debug, srcs, DW_DLA_LIST);
  123. }
  124. if (found)
  125. pr_debug("found fno: %d\n", (int)found);
  126. return found;
  127. }
  128. /* Compare diename and tname */
  129. static int die_compare_name(Dwarf_Die dw_die, const char *tname)
  130. {
  131. char *name;
  132. int ret;
  133. ret = dwarf_diename(dw_die, &name, &__dw_error);
  134. DIE_IF(ret == DW_DLV_ERROR);
  135. if (ret == DW_DLV_OK) {
  136. ret = strcmp(tname, name);
  137. dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
  138. } else
  139. ret = -1;
  140. return ret;
  141. }
  142. /* Check the address is in the subprogram(function). */
  143. static int die_within_subprogram(Dwarf_Die sp_die, Dwarf_Addr addr,
  144. Dwarf_Signed *offs)
  145. {
  146. Dwarf_Addr lopc, hipc;
  147. int ret;
  148. /* TODO: check ranges */
  149. ret = dwarf_lowpc(sp_die, &lopc, &__dw_error);
  150. DIE_IF(ret == DW_DLV_ERROR);
  151. if (ret == DW_DLV_NO_ENTRY)
  152. return 0;
  153. ret = dwarf_highpc(sp_die, &hipc, &__dw_error);
  154. DIE_IF(ret != DW_DLV_OK);
  155. if (lopc <= addr && addr < hipc) {
  156. *offs = addr - lopc;
  157. return 1;
  158. } else
  159. return 0;
  160. }
  161. /* Check the die is inlined function */
  162. static Dwarf_Bool die_inlined_subprogram(Dwarf_Die dw_die)
  163. {
  164. /* TODO: check strictly */
  165. Dwarf_Bool inl;
  166. int ret;
  167. ret = dwarf_hasattr(dw_die, DW_AT_inline, &inl, &__dw_error);
  168. DIE_IF(ret == DW_DLV_ERROR);
  169. return inl;
  170. }
  171. /* Get the offset of abstruct_origin */
  172. static Dwarf_Off die_get_abstract_origin(Dwarf_Die dw_die)
  173. {
  174. Dwarf_Attribute attr;
  175. Dwarf_Off cu_offs;
  176. int ret;
  177. ret = dwarf_attr(dw_die, DW_AT_abstract_origin, &attr, &__dw_error);
  178. DIE_IF(ret != DW_DLV_OK);
  179. ret = dwarf_formref(attr, &cu_offs, &__dw_error);
  180. DIE_IF(ret != DW_DLV_OK);
  181. dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
  182. return cu_offs;
  183. }
  184. /* Get entry pc(or low pc, 1st entry of ranges) of the die */
  185. static Dwarf_Addr die_get_entrypc(Dwarf_Die dw_die)
  186. {
  187. Dwarf_Attribute attr;
  188. Dwarf_Addr addr;
  189. Dwarf_Off offs;
  190. Dwarf_Ranges *ranges;
  191. Dwarf_Signed cnt;
  192. int ret;
  193. /* Try to get entry pc */
  194. ret = dwarf_attr(dw_die, DW_AT_entry_pc, &attr, &__dw_error);
  195. DIE_IF(ret == DW_DLV_ERROR);
  196. if (ret == DW_DLV_OK) {
  197. ret = dwarf_formaddr(attr, &addr, &__dw_error);
  198. DIE_IF(ret != DW_DLV_OK);
  199. dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
  200. return addr;
  201. }
  202. /* Try to get low pc */
  203. ret = dwarf_lowpc(dw_die, &addr, &__dw_error);
  204. DIE_IF(ret == DW_DLV_ERROR);
  205. if (ret == DW_DLV_OK)
  206. return addr;
  207. /* Try to get ranges */
  208. ret = dwarf_attr(dw_die, DW_AT_ranges, &attr, &__dw_error);
  209. DIE_IF(ret != DW_DLV_OK);
  210. ret = dwarf_formref(attr, &offs, &__dw_error);
  211. DIE_IF(ret != DW_DLV_OK);
  212. ret = dwarf_get_ranges(__dw_debug, offs, &ranges, &cnt, NULL,
  213. &__dw_error);
  214. DIE_IF(ret != DW_DLV_OK);
  215. addr = ranges[0].dwr_addr1;
  216. dwarf_ranges_dealloc(__dw_debug, ranges, cnt);
  217. return addr;
  218. }
  219. /*
  220. * Search a Die from Die tree.
  221. * Note: cur_link->die should be deallocated in this function.
  222. */
  223. static int __search_die_tree(struct die_link *cur_link,
  224. int (*die_cb)(struct die_link *, void *),
  225. void *data)
  226. {
  227. Dwarf_Die new_die;
  228. struct die_link new_link;
  229. int ret;
  230. if (!die_cb)
  231. return 0;
  232. /* Check current die */
  233. while (!(ret = die_cb(cur_link, data))) {
  234. /* Check child die */
  235. ret = dwarf_child(cur_link->die, &new_die, &__dw_error);
  236. DIE_IF(ret == DW_DLV_ERROR);
  237. if (ret == DW_DLV_OK) {
  238. new_link.parent = cur_link;
  239. new_link.die = new_die;
  240. ret = __search_die_tree(&new_link, die_cb, data);
  241. if (ret)
  242. break;
  243. }
  244. /* Move to next sibling */
  245. ret = dwarf_siblingof(__dw_debug, cur_link->die, &new_die,
  246. &__dw_error);
  247. DIE_IF(ret == DW_DLV_ERROR);
  248. dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE);
  249. cur_link->die = new_die;
  250. if (ret == DW_DLV_NO_ENTRY)
  251. return 0;
  252. }
  253. dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE);
  254. return ret;
  255. }
  256. /* Search a die in its children's die tree */
  257. static int search_die_from_children(Dwarf_Die parent_die,
  258. int (*die_cb)(struct die_link *, void *),
  259. void *data)
  260. {
  261. struct die_link new_link;
  262. int ret;
  263. new_link.parent = NULL;
  264. ret = dwarf_child(parent_die, &new_link.die, &__dw_error);
  265. DIE_IF(ret == DW_DLV_ERROR);
  266. if (ret == DW_DLV_OK)
  267. return __search_die_tree(&new_link, die_cb, data);
  268. else
  269. return 0;
  270. }
  271. /* Find a locdesc corresponding to the address */
  272. static int attr_get_locdesc(Dwarf_Attribute attr, Dwarf_Locdesc *desc,
  273. Dwarf_Addr addr)
  274. {
  275. Dwarf_Signed lcnt;
  276. Dwarf_Locdesc **llbuf;
  277. int ret, i;
  278. ret = dwarf_loclist_n(attr, &llbuf, &lcnt, &__dw_error);
  279. DIE_IF(ret != DW_DLV_OK);
  280. ret = DW_DLV_NO_ENTRY;
  281. for (i = 0; i < lcnt; ++i) {
  282. if (llbuf[i]->ld_lopc <= addr &&
  283. llbuf[i]->ld_hipc > addr) {
  284. memcpy(desc, llbuf[i], sizeof(Dwarf_Locdesc));
  285. desc->ld_s =
  286. malloc(sizeof(Dwarf_Loc) * llbuf[i]->ld_cents);
  287. DIE_IF(desc->ld_s == NULL);
  288. memcpy(desc->ld_s, llbuf[i]->ld_s,
  289. sizeof(Dwarf_Loc) * llbuf[i]->ld_cents);
  290. ret = DW_DLV_OK;
  291. break;
  292. }
  293. dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
  294. dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC);
  295. }
  296. /* Releasing loop */
  297. for (; i < lcnt; ++i) {
  298. dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
  299. dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC);
  300. }
  301. dwarf_dealloc(__dw_debug, llbuf, DW_DLA_LIST);
  302. return ret;
  303. }
  304. /*
  305. * Probe finder related functions
  306. */
  307. /* Show a location */
  308. static void show_location(Dwarf_Loc *loc, struct probe_finder *pf)
  309. {
  310. Dwarf_Small op;
  311. Dwarf_Unsigned regn;
  312. Dwarf_Signed offs;
  313. int deref = 0, ret;
  314. const char *regs;
  315. op = loc->lr_atom;
  316. /* If this is based on frame buffer, set the offset */
  317. if (op == DW_OP_fbreg) {
  318. deref = 1;
  319. offs = (Dwarf_Signed)loc->lr_number;
  320. op = pf->fbloc.ld_s[0].lr_atom;
  321. loc = &pf->fbloc.ld_s[0];
  322. } else
  323. offs = 0;
  324. if (op >= DW_OP_breg0 && op <= DW_OP_breg31) {
  325. regn = op - DW_OP_breg0;
  326. offs += (Dwarf_Signed)loc->lr_number;
  327. deref = 1;
  328. } else if (op >= DW_OP_reg0 && op <= DW_OP_reg31) {
  329. regn = op - DW_OP_reg0;
  330. } else if (op == DW_OP_bregx) {
  331. regn = loc->lr_number;
  332. offs += (Dwarf_Signed)loc->lr_number2;
  333. deref = 1;
  334. } else if (op == DW_OP_regx) {
  335. regn = loc->lr_number;
  336. } else
  337. die("Dwarf_OP %d is not supported.\n", op);
  338. regs = get_arch_regstr(regn);
  339. if (!regs)
  340. die("%lld exceeds max register number.\n", regn);
  341. if (deref)
  342. ret = snprintf(pf->buf, pf->len,
  343. " %s=%+lld(%s)", pf->var, offs, regs);
  344. else
  345. ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs);
  346. DIE_IF(ret < 0);
  347. DIE_IF(ret >= pf->len);
  348. }
  349. /* Show a variables in kprobe event format */
  350. static void show_variable(Dwarf_Die vr_die, struct probe_finder *pf)
  351. {
  352. Dwarf_Attribute attr;
  353. Dwarf_Locdesc ld;
  354. int ret;
  355. ret = dwarf_attr(vr_die, DW_AT_location, &attr, &__dw_error);
  356. if (ret != DW_DLV_OK)
  357. goto error;
  358. ret = attr_get_locdesc(attr, &ld, (pf->addr - pf->cu_base));
  359. if (ret != DW_DLV_OK)
  360. goto error;
  361. /* TODO? */
  362. DIE_IF(ld.ld_cents != 1);
  363. show_location(&ld.ld_s[0], pf);
  364. free(ld.ld_s);
  365. dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
  366. return ;
  367. error:
  368. die("Failed to find the location of %s at this address.\n"
  369. " Perhaps, it has been optimized out.\n", pf->var);
  370. }
  371. static int variable_callback(struct die_link *dlink, void *data)
  372. {
  373. struct probe_finder *pf = (struct probe_finder *)data;
  374. Dwarf_Half tag;
  375. int ret;
  376. ret = dwarf_tag(dlink->die, &tag, &__dw_error);
  377. DIE_IF(ret == DW_DLV_ERROR);
  378. if ((tag == DW_TAG_formal_parameter ||
  379. tag == DW_TAG_variable) &&
  380. (die_compare_name(dlink->die, pf->var) == 0)) {
  381. show_variable(dlink->die, pf);
  382. return 1;
  383. }
  384. /* TODO: Support struct members and arrays */
  385. return 0;
  386. }
  387. /* Find a variable in a subprogram die */
  388. static void find_variable(Dwarf_Die sp_die, struct probe_finder *pf)
  389. {
  390. int ret;
  391. if (!is_c_varname(pf->var)) {
  392. /* Output raw parameters */
  393. ret = snprintf(pf->buf, pf->len, " %s", pf->var);
  394. DIE_IF(ret < 0);
  395. DIE_IF(ret >= pf->len);
  396. return ;
  397. }
  398. pr_debug("Searching '%s' variable in context.\n", pf->var);
  399. /* Search child die for local variables and parameters. */
  400. ret = search_die_from_children(sp_die, variable_callback, pf);
  401. if (!ret)
  402. die("Failed to find '%s' in this function.\n", pf->var);
  403. }
  404. /* Get a frame base on the address */
  405. static void get_current_frame_base(Dwarf_Die sp_die, struct probe_finder *pf)
  406. {
  407. Dwarf_Attribute attr;
  408. int ret;
  409. ret = dwarf_attr(sp_die, DW_AT_frame_base, &attr, &__dw_error);
  410. DIE_IF(ret != DW_DLV_OK);
  411. ret = attr_get_locdesc(attr, &pf->fbloc, (pf->addr - pf->cu_base));
  412. DIE_IF(ret != DW_DLV_OK);
  413. dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
  414. }
  415. static void free_current_frame_base(struct probe_finder *pf)
  416. {
  417. free(pf->fbloc.ld_s);
  418. memset(&pf->fbloc, 0, sizeof(Dwarf_Locdesc));
  419. }
  420. /* Show a probe point to output buffer */
  421. static void show_probepoint(Dwarf_Die sp_die, Dwarf_Signed offs,
  422. struct probe_finder *pf)
  423. {
  424. struct probe_point *pp = pf->pp;
  425. char *name;
  426. char tmp[MAX_PROBE_BUFFER];
  427. int ret, i, len;
  428. /* Output name of probe point */
  429. ret = dwarf_diename(sp_die, &name, &__dw_error);
  430. DIE_IF(ret == DW_DLV_ERROR);
  431. if (ret == DW_DLV_OK) {
  432. ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%u", name,
  433. (unsigned int)offs);
  434. dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
  435. } else {
  436. /* This function has no name. */
  437. ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%llx", pf->addr);
  438. }
  439. DIE_IF(ret < 0);
  440. DIE_IF(ret >= MAX_PROBE_BUFFER);
  441. len = ret;
  442. /* Find each argument */
  443. get_current_frame_base(sp_die, pf);
  444. for (i = 0; i < pp->nr_args; i++) {
  445. pf->var = pp->args[i];
  446. pf->buf = &tmp[len];
  447. pf->len = MAX_PROBE_BUFFER - len;
  448. find_variable(sp_die, pf);
  449. len += strlen(pf->buf);
  450. }
  451. free_current_frame_base(pf);
  452. pp->probes[pp->found] = strdup(tmp);
  453. pp->found++;
  454. }
  455. static int probeaddr_callback(struct die_link *dlink, void *data)
  456. {
  457. struct probe_finder *pf = (struct probe_finder *)data;
  458. Dwarf_Half tag;
  459. Dwarf_Signed offs;
  460. int ret;
  461. ret = dwarf_tag(dlink->die, &tag, &__dw_error);
  462. DIE_IF(ret == DW_DLV_ERROR);
  463. /* Check the address is in this subprogram */
  464. if (tag == DW_TAG_subprogram &&
  465. die_within_subprogram(dlink->die, pf->addr, &offs)) {
  466. show_probepoint(dlink->die, offs, pf);
  467. return 1;
  468. }
  469. return 0;
  470. }
  471. /* Find probe point from its line number */
  472. static void find_by_line(Dwarf_Die cu_die, struct probe_finder *pf)
  473. {
  474. struct probe_point *pp = pf->pp;
  475. Dwarf_Signed cnt, i;
  476. Dwarf_Line *lines;
  477. Dwarf_Unsigned lineno = 0;
  478. Dwarf_Addr addr;
  479. Dwarf_Unsigned fno;
  480. int ret;
  481. ret = dwarf_srclines(cu_die, &lines, &cnt, &__dw_error);
  482. DIE_IF(ret != DW_DLV_OK);
  483. for (i = 0; i < cnt; i++) {
  484. ret = dwarf_line_srcfileno(lines[i], &fno, &__dw_error);
  485. DIE_IF(ret != DW_DLV_OK);
  486. if (fno != pf->fno)
  487. continue;
  488. ret = dwarf_lineno(lines[i], &lineno, &__dw_error);
  489. DIE_IF(ret != DW_DLV_OK);
  490. if (lineno != (Dwarf_Unsigned)pp->line)
  491. continue;
  492. ret = dwarf_lineaddr(lines[i], &addr, &__dw_error);
  493. DIE_IF(ret != DW_DLV_OK);
  494. pr_debug("Probe point found: 0x%llx\n", addr);
  495. pf->addr = addr;
  496. /* Search a real subprogram including this line, */
  497. ret = search_die_from_children(cu_die, probeaddr_callback, pf);
  498. if (ret == 0)
  499. die("Probe point is not found in subprograms.\n");
  500. /* Continuing, because target line might be inlined. */
  501. }
  502. dwarf_srclines_dealloc(__dw_debug, lines, cnt);
  503. }
  504. /* Search function from function name */
  505. static int probefunc_callback(struct die_link *dlink, void *data)
  506. {
  507. struct probe_finder *pf = (struct probe_finder *)data;
  508. struct probe_point *pp = pf->pp;
  509. struct die_link *lk;
  510. Dwarf_Signed offs;
  511. Dwarf_Half tag;
  512. int ret;
  513. ret = dwarf_tag(dlink->die, &tag, &__dw_error);
  514. DIE_IF(ret == DW_DLV_ERROR);
  515. if (tag == DW_TAG_subprogram) {
  516. if (die_compare_name(dlink->die, pp->function) == 0) {
  517. if (die_inlined_subprogram(dlink->die)) {
  518. /* Inlined function, save it. */
  519. ret = dwarf_die_CU_offset(dlink->die,
  520. &pf->inl_offs,
  521. &__dw_error);
  522. DIE_IF(ret != DW_DLV_OK);
  523. pr_debug("inline definition offset %lld\n",
  524. pf->inl_offs);
  525. return 0; /* Continue to search */
  526. }
  527. /* Get probe address */
  528. pf->addr = die_get_entrypc(dlink->die);
  529. pf->addr += pp->offset;
  530. /* TODO: Check the address in this function */
  531. show_probepoint(dlink->die, pp->offset, pf);
  532. return 1; /* Exit; no same symbol in this CU. */
  533. }
  534. } else if (tag == DW_TAG_inlined_subroutine && pf->inl_offs) {
  535. if (die_get_abstract_origin(dlink->die) == pf->inl_offs) {
  536. /* Get probe address */
  537. pf->addr = die_get_entrypc(dlink->die);
  538. pf->addr += pp->offset;
  539. pr_debug("found inline addr: 0x%llx\n", pf->addr);
  540. /* Inlined function. Get a real subprogram */
  541. for (lk = dlink->parent; lk != NULL; lk = lk->parent) {
  542. tag = 0;
  543. dwarf_tag(lk->die, &tag, &__dw_error);
  544. DIE_IF(ret == DW_DLV_ERROR);
  545. if (tag == DW_TAG_subprogram &&
  546. !die_inlined_subprogram(lk->die))
  547. goto found;
  548. }
  549. die("Failed to find real subprogram.\n");
  550. found:
  551. /* Get offset from subprogram */
  552. ret = die_within_subprogram(lk->die, pf->addr, &offs);
  553. DIE_IF(!ret);
  554. show_probepoint(lk->die, offs, pf);
  555. /* Continue to search */
  556. }
  557. }
  558. return 0;
  559. }
  560. static void find_by_func(Dwarf_Die cu_die, struct probe_finder *pf)
  561. {
  562. search_die_from_children(cu_die, probefunc_callback, pf);
  563. }
  564. /* Find a probe point */
  565. int find_probepoint(int fd, struct probe_point *pp)
  566. {
  567. Dwarf_Half addr_size = 0;
  568. Dwarf_Unsigned next_cuh = 0;
  569. Dwarf_Die cu_die = 0;
  570. int cu_number = 0, ret;
  571. struct probe_finder pf = {.pp = pp};
  572. ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
  573. if (ret != DW_DLV_OK)
  574. die("Failed to call dwarf_init(). Maybe, not a dwarf file.\n");
  575. pp->found = 0;
  576. while (++cu_number) {
  577. /* Search CU (Compilation Unit) */
  578. ret = dwarf_next_cu_header(__dw_debug, NULL, NULL, NULL,
  579. &addr_size, &next_cuh, &__dw_error);
  580. DIE_IF(ret == DW_DLV_ERROR);
  581. if (ret == DW_DLV_NO_ENTRY)
  582. break;
  583. /* Get the DIE(Debugging Information Entry) of this CU */
  584. ret = dwarf_siblingof(__dw_debug, 0, &cu_die, &__dw_error);
  585. DIE_IF(ret != DW_DLV_OK);
  586. /* Check if target file is included. */
  587. if (pp->file)
  588. pf.fno = die_get_fileno(cu_die, pp->file);
  589. if (!pp->file || pf.fno) {
  590. /* Save CU base address (for frame_base) */
  591. ret = dwarf_lowpc(cu_die, &pf.cu_base, &__dw_error);
  592. DIE_IF(ret == DW_DLV_ERROR);
  593. if (ret == DW_DLV_NO_ENTRY)
  594. pf.cu_base = 0;
  595. if (pp->line)
  596. find_by_line(cu_die, &pf);
  597. if (pp->function)
  598. find_by_func(cu_die, &pf);
  599. }
  600. dwarf_dealloc(__dw_debug, cu_die, DW_DLA_DIE);
  601. }
  602. ret = dwarf_finish(__dw_debug, &__dw_error);
  603. DIE_IF(ret != DW_DLV_OK);
  604. return pp->found;
  605. }