probe-finder.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  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. /* Copy the function name if possible */
  435. if (!pp->function) {
  436. pp->function = strdup(name);
  437. pp->offset = offs;
  438. }
  439. dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
  440. } else {
  441. /* This function has no name. */
  442. ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%llx", pf->addr);
  443. if (!pp->function) {
  444. /* TODO: Use _stext */
  445. pp->function = strdup("");
  446. pp->offset = (int)pf->addr;
  447. }
  448. }
  449. DIE_IF(ret < 0);
  450. DIE_IF(ret >= MAX_PROBE_BUFFER);
  451. len = ret;
  452. /* Find each argument */
  453. get_current_frame_base(sp_die, pf);
  454. for (i = 0; i < pp->nr_args; i++) {
  455. pf->var = pp->args[i];
  456. pf->buf = &tmp[len];
  457. pf->len = MAX_PROBE_BUFFER - len;
  458. find_variable(sp_die, pf);
  459. len += strlen(pf->buf);
  460. }
  461. free_current_frame_base(pf);
  462. pp->probes[pp->found] = strdup(tmp);
  463. pp->found++;
  464. }
  465. static int probeaddr_callback(struct die_link *dlink, void *data)
  466. {
  467. struct probe_finder *pf = (struct probe_finder *)data;
  468. Dwarf_Half tag;
  469. Dwarf_Signed offs;
  470. int ret;
  471. ret = dwarf_tag(dlink->die, &tag, &__dw_error);
  472. DIE_IF(ret == DW_DLV_ERROR);
  473. /* Check the address is in this subprogram */
  474. if (tag == DW_TAG_subprogram &&
  475. die_within_subprogram(dlink->die, pf->addr, &offs)) {
  476. show_probepoint(dlink->die, offs, pf);
  477. return 1;
  478. }
  479. return 0;
  480. }
  481. /* Find probe point from its line number */
  482. static void find_by_line(Dwarf_Die cu_die, struct probe_finder *pf)
  483. {
  484. struct probe_point *pp = pf->pp;
  485. Dwarf_Signed cnt, i;
  486. Dwarf_Line *lines;
  487. Dwarf_Unsigned lineno = 0;
  488. Dwarf_Addr addr;
  489. Dwarf_Unsigned fno;
  490. int ret;
  491. ret = dwarf_srclines(cu_die, &lines, &cnt, &__dw_error);
  492. DIE_IF(ret != DW_DLV_OK);
  493. for (i = 0; i < cnt; i++) {
  494. ret = dwarf_line_srcfileno(lines[i], &fno, &__dw_error);
  495. DIE_IF(ret != DW_DLV_OK);
  496. if (fno != pf->fno)
  497. continue;
  498. ret = dwarf_lineno(lines[i], &lineno, &__dw_error);
  499. DIE_IF(ret != DW_DLV_OK);
  500. if (lineno != (Dwarf_Unsigned)pp->line)
  501. continue;
  502. ret = dwarf_lineaddr(lines[i], &addr, &__dw_error);
  503. DIE_IF(ret != DW_DLV_OK);
  504. pr_debug("Probe point found: 0x%llx\n", addr);
  505. pf->addr = addr;
  506. /* Search a real subprogram including this line, */
  507. ret = search_die_from_children(cu_die, probeaddr_callback, pf);
  508. if (ret == 0)
  509. die("Probe point is not found in subprograms.\n");
  510. /* Continuing, because target line might be inlined. */
  511. }
  512. dwarf_srclines_dealloc(__dw_debug, lines, cnt);
  513. }
  514. /* Search function from function name */
  515. static int probefunc_callback(struct die_link *dlink, void *data)
  516. {
  517. struct probe_finder *pf = (struct probe_finder *)data;
  518. struct probe_point *pp = pf->pp;
  519. struct die_link *lk;
  520. Dwarf_Signed offs;
  521. Dwarf_Half tag;
  522. int ret;
  523. ret = dwarf_tag(dlink->die, &tag, &__dw_error);
  524. DIE_IF(ret == DW_DLV_ERROR);
  525. if (tag == DW_TAG_subprogram) {
  526. if (die_compare_name(dlink->die, pp->function) == 0) {
  527. if (die_inlined_subprogram(dlink->die)) {
  528. /* Inlined function, save it. */
  529. ret = dwarf_die_CU_offset(dlink->die,
  530. &pf->inl_offs,
  531. &__dw_error);
  532. DIE_IF(ret != DW_DLV_OK);
  533. pr_debug("inline definition offset %lld\n",
  534. pf->inl_offs);
  535. return 0; /* Continue to search */
  536. }
  537. /* Get probe address */
  538. pf->addr = die_get_entrypc(dlink->die);
  539. pf->addr += pp->offset;
  540. /* TODO: Check the address in this function */
  541. show_probepoint(dlink->die, pp->offset, pf);
  542. return 1; /* Exit; no same symbol in this CU. */
  543. }
  544. } else if (tag == DW_TAG_inlined_subroutine && pf->inl_offs) {
  545. if (die_get_abstract_origin(dlink->die) == pf->inl_offs) {
  546. /* Get probe address */
  547. pf->addr = die_get_entrypc(dlink->die);
  548. pf->addr += pp->offset;
  549. pr_debug("found inline addr: 0x%llx\n", pf->addr);
  550. /* Inlined function. Get a real subprogram */
  551. for (lk = dlink->parent; lk != NULL; lk = lk->parent) {
  552. tag = 0;
  553. dwarf_tag(lk->die, &tag, &__dw_error);
  554. DIE_IF(ret == DW_DLV_ERROR);
  555. if (tag == DW_TAG_subprogram &&
  556. !die_inlined_subprogram(lk->die))
  557. goto found;
  558. }
  559. die("Failed to find real subprogram.\n");
  560. found:
  561. /* Get offset from subprogram */
  562. ret = die_within_subprogram(lk->die, pf->addr, &offs);
  563. DIE_IF(!ret);
  564. show_probepoint(lk->die, offs, pf);
  565. /* Continue to search */
  566. }
  567. }
  568. return 0;
  569. }
  570. static void find_by_func(Dwarf_Die cu_die, struct probe_finder *pf)
  571. {
  572. search_die_from_children(cu_die, probefunc_callback, pf);
  573. }
  574. /* Find a probe point */
  575. int find_probepoint(int fd, struct probe_point *pp)
  576. {
  577. Dwarf_Half addr_size = 0;
  578. Dwarf_Unsigned next_cuh = 0;
  579. Dwarf_Die cu_die = 0;
  580. int cu_number = 0, ret;
  581. struct probe_finder pf = {.pp = pp};
  582. ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
  583. if (ret != DW_DLV_OK)
  584. die("Failed to call dwarf_init(). Maybe, not a dwarf file.\n");
  585. pp->found = 0;
  586. while (++cu_number) {
  587. /* Search CU (Compilation Unit) */
  588. ret = dwarf_next_cu_header(__dw_debug, NULL, NULL, NULL,
  589. &addr_size, &next_cuh, &__dw_error);
  590. DIE_IF(ret == DW_DLV_ERROR);
  591. if (ret == DW_DLV_NO_ENTRY)
  592. break;
  593. /* Get the DIE(Debugging Information Entry) of this CU */
  594. ret = dwarf_siblingof(__dw_debug, 0, &cu_die, &__dw_error);
  595. DIE_IF(ret != DW_DLV_OK);
  596. /* Check if target file is included. */
  597. if (pp->file)
  598. pf.fno = die_get_fileno(cu_die, pp->file);
  599. if (!pp->file || pf.fno) {
  600. /* Save CU base address (for frame_base) */
  601. ret = dwarf_lowpc(cu_die, &pf.cu_base, &__dw_error);
  602. DIE_IF(ret == DW_DLV_ERROR);
  603. if (ret == DW_DLV_NO_ENTRY)
  604. pf.cu_base = 0;
  605. if (pp->line)
  606. find_by_line(cu_die, &pf);
  607. if (pp->function)
  608. find_by_func(cu_die, &pf);
  609. }
  610. dwarf_dealloc(__dw_debug, cu_die, DW_DLA_DIE);
  611. }
  612. ret = dwarf_finish(__dw_debug, &__dw_error);
  613. DIE_IF(ret != DW_DLV_OK);
  614. return pp->found;
  615. }