dwarf-aux.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293
  1. /*
  2. * dwarf-aux.c : libdw auxiliary interfaces
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. *
  18. */
  19. #include <errno.h>
  20. #include <inttypes.h>
  21. #include <stdbool.h>
  22. #include "util.h"
  23. #include "debug.h"
  24. #include "dwarf-aux.h"
  25. #include "string2.h"
  26. /**
  27. * cu_find_realpath - Find the realpath of the target file
  28. * @cu_die: A DIE(dwarf information entry) of CU(compilation Unit)
  29. * @fname: The tail filename of the target file
  30. *
  31. * Find the real(long) path of @fname in @cu_die.
  32. */
  33. const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
  34. {
  35. Dwarf_Files *files;
  36. size_t nfiles, i;
  37. const char *src = NULL;
  38. int ret;
  39. if (!fname)
  40. return NULL;
  41. ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
  42. if (ret != 0)
  43. return NULL;
  44. for (i = 0; i < nfiles; i++) {
  45. src = dwarf_filesrc(files, i, NULL, NULL);
  46. if (strtailcmp(src, fname) == 0)
  47. break;
  48. }
  49. if (i == nfiles)
  50. return NULL;
  51. return src;
  52. }
  53. /**
  54. * cu_get_comp_dir - Get the path of compilation directory
  55. * @cu_die: a CU DIE
  56. *
  57. * Get the path of compilation directory of given @cu_die.
  58. * Since this depends on DW_AT_comp_dir, older gcc will not
  59. * embedded it. In that case, this returns NULL.
  60. */
  61. const char *cu_get_comp_dir(Dwarf_Die *cu_die)
  62. {
  63. Dwarf_Attribute attr;
  64. if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
  65. return NULL;
  66. return dwarf_formstring(&attr);
  67. }
  68. /**
  69. * cu_find_lineinfo - Get a line number and file name for given address
  70. * @cu_die: a CU DIE
  71. * @addr: An address
  72. * @fname: a pointer which returns the file name string
  73. * @lineno: a pointer which returns the line number
  74. *
  75. * Find a line number and file name for @addr in @cu_die.
  76. */
  77. int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr,
  78. const char **fname, int *lineno)
  79. {
  80. Dwarf_Line *line;
  81. Dwarf_Addr laddr;
  82. line = dwarf_getsrc_die(cu_die, (Dwarf_Addr)addr);
  83. if (line && dwarf_lineaddr(line, &laddr) == 0 &&
  84. addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
  85. *fname = dwarf_linesrc(line, NULL, NULL);
  86. if (!*fname)
  87. /* line number is useless without filename */
  88. *lineno = 0;
  89. }
  90. return *lineno ?: -ENOENT;
  91. }
  92. static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data);
  93. /**
  94. * cu_walk_functions_at - Walk on function DIEs at given address
  95. * @cu_die: A CU DIE
  96. * @addr: An address
  97. * @callback: A callback which called with found DIEs
  98. * @data: A user data
  99. *
  100. * Walk on function DIEs at given @addr in @cu_die. Passed DIEs
  101. * should be subprogram or inlined-subroutines.
  102. */
  103. int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
  104. int (*callback)(Dwarf_Die *, void *), void *data)
  105. {
  106. Dwarf_Die die_mem;
  107. Dwarf_Die *sc_die;
  108. int ret = -ENOENT;
  109. /* Inlined function could be recursive. Trace it until fail */
  110. for (sc_die = die_find_realfunc(cu_die, addr, &die_mem);
  111. sc_die != NULL;
  112. sc_die = die_find_child(sc_die, __die_find_inline_cb, &addr,
  113. &die_mem)) {
  114. ret = callback(sc_die, data);
  115. if (ret)
  116. break;
  117. }
  118. return ret;
  119. }
  120. /**
  121. * die_get_linkage_name - Get the linkage name of the object
  122. * @dw_die: A DIE of the object
  123. *
  124. * Get the linkage name attiribute of given @dw_die.
  125. * For C++ binary, the linkage name will be the mangled symbol.
  126. */
  127. const char *die_get_linkage_name(Dwarf_Die *dw_die)
  128. {
  129. Dwarf_Attribute attr;
  130. if (dwarf_attr_integrate(dw_die, DW_AT_linkage_name, &attr) == NULL)
  131. return NULL;
  132. return dwarf_formstring(&attr);
  133. }
  134. /**
  135. * die_compare_name - Compare diename and tname
  136. * @dw_die: a DIE
  137. * @tname: a string of target name
  138. *
  139. * Compare the name of @dw_die and @tname. Return false if @dw_die has no name.
  140. */
  141. bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
  142. {
  143. const char *name;
  144. name = dwarf_diename(dw_die);
  145. return name ? (strcmp(tname, name) == 0) : false;
  146. }
  147. /**
  148. * die_match_name - Match diename/linkage name and glob
  149. * @dw_die: a DIE
  150. * @glob: a string of target glob pattern
  151. *
  152. * Glob matching the name of @dw_die and @glob. Return false if matching fail.
  153. * This also match linkage name.
  154. */
  155. bool die_match_name(Dwarf_Die *dw_die, const char *glob)
  156. {
  157. const char *name;
  158. name = dwarf_diename(dw_die);
  159. if (name && strglobmatch(name, glob))
  160. return true;
  161. /* fall back to check linkage name */
  162. name = die_get_linkage_name(dw_die);
  163. if (name && strglobmatch(name, glob))
  164. return true;
  165. return false;
  166. }
  167. /**
  168. * die_get_call_lineno - Get callsite line number of inline-function instance
  169. * @in_die: a DIE of an inlined function instance
  170. *
  171. * Get call-site line number of @in_die. This means from where the inline
  172. * function is called.
  173. */
  174. int die_get_call_lineno(Dwarf_Die *in_die)
  175. {
  176. Dwarf_Attribute attr;
  177. Dwarf_Word ret;
  178. if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
  179. return -ENOENT;
  180. dwarf_formudata(&attr, &ret);
  181. return (int)ret;
  182. }
  183. /**
  184. * die_get_type - Get type DIE
  185. * @vr_die: a DIE of a variable
  186. * @die_mem: where to store a type DIE
  187. *
  188. * Get a DIE of the type of given variable (@vr_die), and store
  189. * it to die_mem. Return NULL if fails to get a type DIE.
  190. */
  191. Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
  192. {
  193. Dwarf_Attribute attr;
  194. if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
  195. dwarf_formref_die(&attr, die_mem))
  196. return die_mem;
  197. else
  198. return NULL;
  199. }
  200. /* Get a type die, but skip qualifiers */
  201. static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
  202. {
  203. int tag;
  204. do {
  205. vr_die = die_get_type(vr_die, die_mem);
  206. if (!vr_die)
  207. break;
  208. tag = dwarf_tag(vr_die);
  209. } while (tag == DW_TAG_const_type ||
  210. tag == DW_TAG_restrict_type ||
  211. tag == DW_TAG_volatile_type ||
  212. tag == DW_TAG_shared_type);
  213. return vr_die;
  214. }
  215. /**
  216. * die_get_real_type - Get a type die, but skip qualifiers and typedef
  217. * @vr_die: a DIE of a variable
  218. * @die_mem: where to store a type DIE
  219. *
  220. * Get a DIE of the type of given variable (@vr_die), and store
  221. * it to die_mem. Return NULL if fails to get a type DIE.
  222. * If the type is qualifiers (e.g. const) or typedef, this skips it
  223. * and tries to find real type (structure or basic types, e.g. int).
  224. */
  225. Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
  226. {
  227. do {
  228. vr_die = __die_get_real_type(vr_die, die_mem);
  229. } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
  230. return vr_die;
  231. }
  232. /* Get attribute and translate it as a udata */
  233. static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
  234. Dwarf_Word *result)
  235. {
  236. Dwarf_Attribute attr;
  237. if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
  238. dwarf_formudata(&attr, result) != 0)
  239. return -ENOENT;
  240. return 0;
  241. }
  242. /* Get attribute and translate it as a sdata */
  243. static int die_get_attr_sdata(Dwarf_Die *tp_die, unsigned int attr_name,
  244. Dwarf_Sword *result)
  245. {
  246. Dwarf_Attribute attr;
  247. if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
  248. dwarf_formsdata(&attr, result) != 0)
  249. return -ENOENT;
  250. return 0;
  251. }
  252. /**
  253. * die_is_signed_type - Check whether a type DIE is signed or not
  254. * @tp_die: a DIE of a type
  255. *
  256. * Get the encoding of @tp_die and return true if the encoding
  257. * is signed.
  258. */
  259. bool die_is_signed_type(Dwarf_Die *tp_die)
  260. {
  261. Dwarf_Word ret;
  262. if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
  263. return false;
  264. return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
  265. ret == DW_ATE_signed_fixed);
  266. }
  267. /**
  268. * die_is_func_def - Ensure that this DIE is a subprogram and definition
  269. * @dw_die: a DIE
  270. *
  271. * Ensure that this DIE is a subprogram and NOT a declaration. This
  272. * returns true if @dw_die is a function definition.
  273. **/
  274. bool die_is_func_def(Dwarf_Die *dw_die)
  275. {
  276. Dwarf_Attribute attr;
  277. return (dwarf_tag(dw_die) == DW_TAG_subprogram &&
  278. dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL);
  279. }
  280. /**
  281. * die_is_func_instance - Ensure that this DIE is an instance of a subprogram
  282. * @dw_die: a DIE
  283. *
  284. * Ensure that this DIE is an instance (which has an entry address).
  285. * This returns true if @dw_die is a function instance. If not, you need to
  286. * call die_walk_instances() to find actual instances.
  287. **/
  288. bool die_is_func_instance(Dwarf_Die *dw_die)
  289. {
  290. Dwarf_Addr tmp;
  291. /* Actually gcc optimizes non-inline as like as inlined */
  292. return !dwarf_func_inline(dw_die) && dwarf_entrypc(dw_die, &tmp) == 0;
  293. }
  294. /**
  295. * die_get_data_member_location - Get the data-member offset
  296. * @mb_die: a DIE of a member of a data structure
  297. * @offs: The offset of the member in the data structure
  298. *
  299. * Get the offset of @mb_die in the data structure including @mb_die, and
  300. * stores result offset to @offs. If any error occurs this returns errno.
  301. */
  302. int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
  303. {
  304. Dwarf_Attribute attr;
  305. Dwarf_Op *expr;
  306. size_t nexpr;
  307. int ret;
  308. if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
  309. return -ENOENT;
  310. if (dwarf_formudata(&attr, offs) != 0) {
  311. /* DW_AT_data_member_location should be DW_OP_plus_uconst */
  312. ret = dwarf_getlocation(&attr, &expr, &nexpr);
  313. if (ret < 0 || nexpr == 0)
  314. return -ENOENT;
  315. if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
  316. pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
  317. expr[0].atom, nexpr);
  318. return -ENOTSUP;
  319. }
  320. *offs = (Dwarf_Word)expr[0].number;
  321. }
  322. return 0;
  323. }
  324. /* Get the call file index number in CU DIE */
  325. static int die_get_call_fileno(Dwarf_Die *in_die)
  326. {
  327. Dwarf_Sword idx;
  328. if (die_get_attr_sdata(in_die, DW_AT_call_file, &idx) == 0)
  329. return (int)idx;
  330. else
  331. return -ENOENT;
  332. }
  333. /* Get the declared file index number in CU DIE */
  334. static int die_get_decl_fileno(Dwarf_Die *pdie)
  335. {
  336. Dwarf_Sword idx;
  337. if (die_get_attr_sdata(pdie, DW_AT_decl_file, &idx) == 0)
  338. return (int)idx;
  339. else
  340. return -ENOENT;
  341. }
  342. /**
  343. * die_get_call_file - Get callsite file name of inlined function instance
  344. * @in_die: a DIE of an inlined function instance
  345. *
  346. * Get call-site file name of @in_die. This means from which file the inline
  347. * function is called.
  348. */
  349. const char *die_get_call_file(Dwarf_Die *in_die)
  350. {
  351. Dwarf_Die cu_die;
  352. Dwarf_Files *files;
  353. int idx;
  354. idx = die_get_call_fileno(in_die);
  355. if (idx < 0 || !dwarf_diecu(in_die, &cu_die, NULL, NULL) ||
  356. dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
  357. return NULL;
  358. return dwarf_filesrc(files, idx, NULL, NULL);
  359. }
  360. /**
  361. * die_find_child - Generic DIE search function in DIE tree
  362. * @rt_die: a root DIE
  363. * @callback: a callback function
  364. * @data: a user data passed to the callback function
  365. * @die_mem: a buffer for result DIE
  366. *
  367. * Trace DIE tree from @rt_die and call @callback for each child DIE.
  368. * If @callback returns DIE_FIND_CB_END, this stores the DIE into
  369. * @die_mem and returns it. If @callback returns DIE_FIND_CB_CONTINUE,
  370. * this continues to trace the tree. Optionally, @callback can return
  371. * DIE_FIND_CB_CHILD and DIE_FIND_CB_SIBLING, those means trace only
  372. * the children and trace only the siblings respectively.
  373. * Returns NULL if @callback can't find any appropriate DIE.
  374. */
  375. Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
  376. int (*callback)(Dwarf_Die *, void *),
  377. void *data, Dwarf_Die *die_mem)
  378. {
  379. Dwarf_Die child_die;
  380. int ret;
  381. ret = dwarf_child(rt_die, die_mem);
  382. if (ret != 0)
  383. return NULL;
  384. do {
  385. ret = callback(die_mem, data);
  386. if (ret == DIE_FIND_CB_END)
  387. return die_mem;
  388. if ((ret & DIE_FIND_CB_CHILD) &&
  389. die_find_child(die_mem, callback, data, &child_die)) {
  390. memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
  391. return die_mem;
  392. }
  393. } while ((ret & DIE_FIND_CB_SIBLING) &&
  394. dwarf_siblingof(die_mem, die_mem) == 0);
  395. return NULL;
  396. }
  397. struct __addr_die_search_param {
  398. Dwarf_Addr addr;
  399. Dwarf_Die *die_mem;
  400. };
  401. static int __die_search_func_tail_cb(Dwarf_Die *fn_die, void *data)
  402. {
  403. struct __addr_die_search_param *ad = data;
  404. Dwarf_Addr addr = 0;
  405. if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
  406. !dwarf_highpc(fn_die, &addr) &&
  407. addr == ad->addr) {
  408. memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
  409. return DWARF_CB_ABORT;
  410. }
  411. return DWARF_CB_OK;
  412. }
  413. /**
  414. * die_find_tailfunc - Search for a non-inlined function with tail call at
  415. * given address
  416. * @cu_die: a CU DIE which including @addr
  417. * @addr: target address
  418. * @die_mem: a buffer for result DIE
  419. *
  420. * Search for a non-inlined function DIE with tail call at @addr. Stores the
  421. * DIE to @die_mem and returns it if found. Returns NULL if failed.
  422. */
  423. Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
  424. Dwarf_Die *die_mem)
  425. {
  426. struct __addr_die_search_param ad;
  427. ad.addr = addr;
  428. ad.die_mem = die_mem;
  429. /* dwarf_getscopes can't find subprogram. */
  430. if (!dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0))
  431. return NULL;
  432. else
  433. return die_mem;
  434. }
  435. /* die_find callback for non-inlined function search */
  436. static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
  437. {
  438. struct __addr_die_search_param *ad = data;
  439. /*
  440. * Since a declaration entry doesn't has given pc, this always returns
  441. * function definition entry.
  442. */
  443. if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
  444. dwarf_haspc(fn_die, ad->addr)) {
  445. memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
  446. return DWARF_CB_ABORT;
  447. }
  448. return DWARF_CB_OK;
  449. }
  450. /**
  451. * die_find_realfunc - Search a non-inlined function at given address
  452. * @cu_die: a CU DIE which including @addr
  453. * @addr: target address
  454. * @die_mem: a buffer for result DIE
  455. *
  456. * Search a non-inlined function DIE which includes @addr. Stores the
  457. * DIE to @die_mem and returns it if found. Returns NULL if failed.
  458. */
  459. Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
  460. Dwarf_Die *die_mem)
  461. {
  462. struct __addr_die_search_param ad;
  463. ad.addr = addr;
  464. ad.die_mem = die_mem;
  465. /* dwarf_getscopes can't find subprogram. */
  466. if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
  467. return NULL;
  468. else
  469. return die_mem;
  470. }
  471. /* die_find callback for inline function search */
  472. static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
  473. {
  474. Dwarf_Addr *addr = data;
  475. if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
  476. dwarf_haspc(die_mem, *addr))
  477. return DIE_FIND_CB_END;
  478. return DIE_FIND_CB_CONTINUE;
  479. }
  480. /**
  481. * die_find_top_inlinefunc - Search the top inlined function at given address
  482. * @sp_die: a subprogram DIE which including @addr
  483. * @addr: target address
  484. * @die_mem: a buffer for result DIE
  485. *
  486. * Search an inlined function DIE which includes @addr. Stores the
  487. * DIE to @die_mem and returns it if found. Returns NULL if failed.
  488. * Even if several inlined functions are expanded recursively, this
  489. * doesn't trace it down, and returns the topmost one.
  490. */
  491. Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
  492. Dwarf_Die *die_mem)
  493. {
  494. return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
  495. }
  496. /**
  497. * die_find_inlinefunc - Search an inlined function at given address
  498. * @sp_die: a subprogram DIE which including @addr
  499. * @addr: target address
  500. * @die_mem: a buffer for result DIE
  501. *
  502. * Search an inlined function DIE which includes @addr. Stores the
  503. * DIE to @die_mem and returns it if found. Returns NULL if failed.
  504. * If several inlined functions are expanded recursively, this trace
  505. * it down and returns deepest one.
  506. */
  507. Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
  508. Dwarf_Die *die_mem)
  509. {
  510. Dwarf_Die tmp_die;
  511. sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
  512. if (!sp_die)
  513. return NULL;
  514. /* Inlined function could be recursive. Trace it until fail */
  515. while (sp_die) {
  516. memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
  517. sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
  518. &tmp_die);
  519. }
  520. return die_mem;
  521. }
  522. struct __instance_walk_param {
  523. void *addr;
  524. int (*callback)(Dwarf_Die *, void *);
  525. void *data;
  526. int retval;
  527. };
  528. static int __die_walk_instances_cb(Dwarf_Die *inst, void *data)
  529. {
  530. struct __instance_walk_param *iwp = data;
  531. Dwarf_Attribute attr_mem;
  532. Dwarf_Die origin_mem;
  533. Dwarf_Attribute *attr;
  534. Dwarf_Die *origin;
  535. int tmp;
  536. attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem);
  537. if (attr == NULL)
  538. return DIE_FIND_CB_CONTINUE;
  539. origin = dwarf_formref_die(attr, &origin_mem);
  540. if (origin == NULL || origin->addr != iwp->addr)
  541. return DIE_FIND_CB_CONTINUE;
  542. /* Ignore redundant instances */
  543. if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) {
  544. dwarf_decl_line(origin, &tmp);
  545. if (die_get_call_lineno(inst) == tmp) {
  546. tmp = die_get_decl_fileno(origin);
  547. if (die_get_call_fileno(inst) == tmp)
  548. return DIE_FIND_CB_CONTINUE;
  549. }
  550. }
  551. iwp->retval = iwp->callback(inst, iwp->data);
  552. return (iwp->retval) ? DIE_FIND_CB_END : DIE_FIND_CB_CONTINUE;
  553. }
  554. /**
  555. * die_walk_instances - Walk on instances of given DIE
  556. * @or_die: an abstract original DIE
  557. * @callback: a callback function which is called with instance DIE
  558. * @data: user data
  559. *
  560. * Walk on the instances of give @in_die. @in_die must be an inlined function
  561. * declartion. This returns the return value of @callback if it returns
  562. * non-zero value, or -ENOENT if there is no instance.
  563. */
  564. int die_walk_instances(Dwarf_Die *or_die, int (*callback)(Dwarf_Die *, void *),
  565. void *data)
  566. {
  567. Dwarf_Die cu_die;
  568. Dwarf_Die die_mem;
  569. struct __instance_walk_param iwp = {
  570. .addr = or_die->addr,
  571. .callback = callback,
  572. .data = data,
  573. .retval = -ENOENT,
  574. };
  575. if (dwarf_diecu(or_die, &cu_die, NULL, NULL) == NULL)
  576. return -ENOENT;
  577. die_find_child(&cu_die, __die_walk_instances_cb, &iwp, &die_mem);
  578. return iwp.retval;
  579. }
  580. /* Line walker internal parameters */
  581. struct __line_walk_param {
  582. bool recursive;
  583. line_walk_callback_t callback;
  584. void *data;
  585. int retval;
  586. };
  587. static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
  588. {
  589. struct __line_walk_param *lw = data;
  590. Dwarf_Addr addr = 0;
  591. const char *fname;
  592. int lineno;
  593. if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
  594. fname = die_get_call_file(in_die);
  595. lineno = die_get_call_lineno(in_die);
  596. if (fname && lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
  597. lw->retval = lw->callback(fname, lineno, addr, lw->data);
  598. if (lw->retval != 0)
  599. return DIE_FIND_CB_END;
  600. }
  601. }
  602. if (!lw->recursive)
  603. /* Don't need to search recursively */
  604. return DIE_FIND_CB_SIBLING;
  605. if (addr) {
  606. fname = dwarf_decl_file(in_die);
  607. if (fname && dwarf_decl_line(in_die, &lineno) == 0) {
  608. lw->retval = lw->callback(fname, lineno, addr, lw->data);
  609. if (lw->retval != 0)
  610. return DIE_FIND_CB_END;
  611. }
  612. }
  613. /* Continue to search nested inlined function call-sites */
  614. return DIE_FIND_CB_CONTINUE;
  615. }
  616. /* Walk on lines of blocks included in given DIE */
  617. static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive,
  618. line_walk_callback_t callback, void *data)
  619. {
  620. struct __line_walk_param lw = {
  621. .recursive = recursive,
  622. .callback = callback,
  623. .data = data,
  624. .retval = 0,
  625. };
  626. Dwarf_Die die_mem;
  627. Dwarf_Addr addr;
  628. const char *fname;
  629. int lineno;
  630. /* Handle function declaration line */
  631. fname = dwarf_decl_file(sp_die);
  632. if (fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
  633. dwarf_entrypc(sp_die, &addr) == 0) {
  634. lw.retval = callback(fname, lineno, addr, data);
  635. if (lw.retval != 0)
  636. goto done;
  637. }
  638. die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
  639. done:
  640. return lw.retval;
  641. }
  642. static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
  643. {
  644. struct __line_walk_param *lw = data;
  645. lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data);
  646. if (lw->retval != 0)
  647. return DWARF_CB_ABORT;
  648. return DWARF_CB_OK;
  649. }
  650. /**
  651. * die_walk_lines - Walk on lines inside given DIE
  652. * @rt_die: a root DIE (CU, subprogram or inlined_subroutine)
  653. * @callback: callback routine
  654. * @data: user data
  655. *
  656. * Walk on all lines inside given @rt_die and call @callback on each line.
  657. * If the @rt_die is a function, walk only on the lines inside the function,
  658. * otherwise @rt_die must be a CU DIE.
  659. * Note that this walks not only dwarf line list, but also function entries
  660. * and inline call-site.
  661. */
  662. int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
  663. {
  664. Dwarf_Lines *lines;
  665. Dwarf_Line *line;
  666. Dwarf_Addr addr;
  667. const char *fname, *decf = NULL;
  668. int lineno, ret = 0;
  669. int decl = 0, inl;
  670. Dwarf_Die die_mem, *cu_die;
  671. size_t nlines, i;
  672. /* Get the CU die */
  673. if (dwarf_tag(rt_die) != DW_TAG_compile_unit) {
  674. cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
  675. dwarf_decl_line(rt_die, &decl);
  676. decf = dwarf_decl_file(rt_die);
  677. } else
  678. cu_die = rt_die;
  679. if (!cu_die) {
  680. pr_debug2("Failed to get CU from given DIE.\n");
  681. return -EINVAL;
  682. }
  683. /* Get lines list in the CU */
  684. if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
  685. pr_debug2("Failed to get source lines on this CU.\n");
  686. return -ENOENT;
  687. }
  688. pr_debug2("Get %zd lines from this CU\n", nlines);
  689. /* Walk on the lines on lines list */
  690. for (i = 0; i < nlines; i++) {
  691. line = dwarf_onesrcline(lines, i);
  692. if (line == NULL ||
  693. dwarf_lineno(line, &lineno) != 0 ||
  694. dwarf_lineaddr(line, &addr) != 0) {
  695. pr_debug2("Failed to get line info. "
  696. "Possible error in debuginfo.\n");
  697. continue;
  698. }
  699. /* Filter lines based on address */
  700. if (rt_die != cu_die) {
  701. /*
  702. * Address filtering
  703. * The line is included in given function, and
  704. * no inline block includes it.
  705. */
  706. if (!dwarf_haspc(rt_die, addr))
  707. continue;
  708. if (die_find_inlinefunc(rt_die, addr, &die_mem)) {
  709. dwarf_decl_line(&die_mem, &inl);
  710. if (inl != decl ||
  711. decf != dwarf_decl_file(&die_mem))
  712. continue;
  713. }
  714. }
  715. /* Get source line */
  716. fname = dwarf_linesrc(line, NULL, NULL);
  717. ret = callback(fname, lineno, addr, data);
  718. if (ret != 0)
  719. return ret;
  720. }
  721. /*
  722. * Dwarf lines doesn't include function declarations and inlined
  723. * subroutines. We have to check functions list or given function.
  724. */
  725. if (rt_die != cu_die)
  726. /*
  727. * Don't need walk functions recursively, because nested
  728. * inlined functions don't have lines of the specified DIE.
  729. */
  730. ret = __die_walk_funclines(rt_die, false, callback, data);
  731. else {
  732. struct __line_walk_param param = {
  733. .callback = callback,
  734. .data = data,
  735. .retval = 0,
  736. };
  737. dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
  738. ret = param.retval;
  739. }
  740. return ret;
  741. }
  742. struct __find_variable_param {
  743. const char *name;
  744. Dwarf_Addr addr;
  745. };
  746. static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
  747. {
  748. struct __find_variable_param *fvp = data;
  749. Dwarf_Attribute attr;
  750. int tag;
  751. tag = dwarf_tag(die_mem);
  752. if ((tag == DW_TAG_formal_parameter ||
  753. tag == DW_TAG_variable) &&
  754. die_compare_name(die_mem, fvp->name) &&
  755. /* Does the DIE have location information or external instance? */
  756. (dwarf_attr(die_mem, DW_AT_external, &attr) ||
  757. dwarf_attr(die_mem, DW_AT_location, &attr)))
  758. return DIE_FIND_CB_END;
  759. if (dwarf_haspc(die_mem, fvp->addr))
  760. return DIE_FIND_CB_CONTINUE;
  761. else
  762. return DIE_FIND_CB_SIBLING;
  763. }
  764. /**
  765. * die_find_variable_at - Find a given name variable at given address
  766. * @sp_die: a function DIE
  767. * @name: variable name
  768. * @addr: address
  769. * @die_mem: a buffer for result DIE
  770. *
  771. * Find a variable DIE called @name at @addr in @sp_die.
  772. */
  773. Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
  774. Dwarf_Addr addr, Dwarf_Die *die_mem)
  775. {
  776. struct __find_variable_param fvp = { .name = name, .addr = addr};
  777. return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
  778. die_mem);
  779. }
  780. static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
  781. {
  782. const char *name = data;
  783. if (dwarf_tag(die_mem) == DW_TAG_member) {
  784. if (die_compare_name(die_mem, name))
  785. return DIE_FIND_CB_END;
  786. else if (!dwarf_diename(die_mem)) { /* Unnamed structure */
  787. Dwarf_Die type_die, tmp_die;
  788. if (die_get_type(die_mem, &type_die) &&
  789. die_find_member(&type_die, name, &tmp_die))
  790. return DIE_FIND_CB_END;
  791. }
  792. }
  793. return DIE_FIND_CB_SIBLING;
  794. }
  795. /**
  796. * die_find_member - Find a given name member in a data structure
  797. * @st_die: a data structure type DIE
  798. * @name: member name
  799. * @die_mem: a buffer for result DIE
  800. *
  801. * Find a member DIE called @name in @st_die.
  802. */
  803. Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
  804. Dwarf_Die *die_mem)
  805. {
  806. return die_find_child(st_die, __die_find_member_cb, (void *)name,
  807. die_mem);
  808. }
  809. /**
  810. * die_get_typename - Get the name of given variable DIE
  811. * @vr_die: a variable DIE
  812. * @buf: a strbuf for result type name
  813. *
  814. * Get the name of @vr_die and stores it to @buf. Return 0 if succeeded.
  815. * and Return -ENOENT if failed to find type name.
  816. * Note that the result will stores typedef name if possible, and stores
  817. * "*(function_type)" if the type is a function pointer.
  818. */
  819. int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
  820. {
  821. Dwarf_Die type;
  822. int tag, ret;
  823. const char *tmp = "";
  824. if (__die_get_real_type(vr_die, &type) == NULL)
  825. return -ENOENT;
  826. tag = dwarf_tag(&type);
  827. if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
  828. tmp = "*";
  829. else if (tag == DW_TAG_subroutine_type) {
  830. /* Function pointer */
  831. return strbuf_add(buf, "(function_type)", 15);
  832. } else {
  833. if (!dwarf_diename(&type))
  834. return -ENOENT;
  835. if (tag == DW_TAG_union_type)
  836. tmp = "union ";
  837. else if (tag == DW_TAG_structure_type)
  838. tmp = "struct ";
  839. else if (tag == DW_TAG_enumeration_type)
  840. tmp = "enum ";
  841. /* Write a base name */
  842. return strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type));
  843. }
  844. ret = die_get_typename(&type, buf);
  845. return ret ? ret : strbuf_addstr(buf, tmp);
  846. }
  847. /**
  848. * die_get_varname - Get the name and type of given variable DIE
  849. * @vr_die: a variable DIE
  850. * @buf: a strbuf for type and variable name
  851. *
  852. * Get the name and type of @vr_die and stores it in @buf as "type\tname".
  853. */
  854. int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
  855. {
  856. int ret;
  857. ret = die_get_typename(vr_die, buf);
  858. if (ret < 0) {
  859. pr_debug("Failed to get type, make it unknown.\n");
  860. ret = strbuf_add(buf, " (unknown_type)", 14);
  861. }
  862. return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
  863. }
  864. #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT
  865. /**
  866. * die_get_var_innermost_scope - Get innermost scope range of given variable DIE
  867. * @sp_die: a subprogram DIE
  868. * @vr_die: a variable DIE
  869. * @buf: a strbuf for variable byte offset range
  870. *
  871. * Get the innermost scope range of @vr_die and stores it in @buf as
  872. * "@<function_name+[NN-NN,NN-NN]>".
  873. */
  874. static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die,
  875. struct strbuf *buf)
  876. {
  877. Dwarf_Die *scopes;
  878. int count;
  879. size_t offset = 0;
  880. Dwarf_Addr base;
  881. Dwarf_Addr start, end;
  882. Dwarf_Addr entry;
  883. int ret;
  884. bool first = true;
  885. const char *name;
  886. ret = dwarf_entrypc(sp_die, &entry);
  887. if (ret)
  888. return ret;
  889. name = dwarf_diename(sp_die);
  890. if (!name)
  891. return -ENOENT;
  892. count = dwarf_getscopes_die(vr_die, &scopes);
  893. /* (*SCOPES)[1] is the DIE for the scope containing that scope */
  894. if (count <= 1) {
  895. ret = -EINVAL;
  896. goto out;
  897. }
  898. while ((offset = dwarf_ranges(&scopes[1], offset, &base,
  899. &start, &end)) > 0) {
  900. start -= entry;
  901. end -= entry;
  902. if (first) {
  903. ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
  904. name, start, end);
  905. first = false;
  906. } else {
  907. ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
  908. start, end);
  909. }
  910. if (ret < 0)
  911. goto out;
  912. }
  913. if (!first)
  914. ret = strbuf_add(buf, "]>", 2);
  915. out:
  916. free(scopes);
  917. return ret;
  918. }
  919. /**
  920. * die_get_var_range - Get byte offset range of given variable DIE
  921. * @sp_die: a subprogram DIE
  922. * @vr_die: a variable DIE
  923. * @buf: a strbuf for type and variable name and byte offset range
  924. *
  925. * Get the byte offset range of @vr_die and stores it in @buf as
  926. * "@<function_name+[NN-NN,NN-NN]>".
  927. */
  928. int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf)
  929. {
  930. int ret = 0;
  931. Dwarf_Addr base;
  932. Dwarf_Addr start, end;
  933. Dwarf_Addr entry;
  934. Dwarf_Op *op;
  935. size_t nops;
  936. size_t offset = 0;
  937. Dwarf_Attribute attr;
  938. bool first = true;
  939. const char *name;
  940. ret = dwarf_entrypc(sp_die, &entry);
  941. if (ret)
  942. return ret;
  943. name = dwarf_diename(sp_die);
  944. if (!name)
  945. return -ENOENT;
  946. if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
  947. return -EINVAL;
  948. while ((offset = dwarf_getlocations(&attr, offset, &base,
  949. &start, &end, &op, &nops)) > 0) {
  950. if (start == 0) {
  951. /* Single Location Descriptions */
  952. ret = die_get_var_innermost_scope(sp_die, vr_die, buf);
  953. goto out;
  954. }
  955. /* Location Lists */
  956. start -= entry;
  957. end -= entry;
  958. if (first) {
  959. ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
  960. name, start, end);
  961. first = false;
  962. } else {
  963. ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
  964. start, end);
  965. }
  966. if (ret < 0)
  967. goto out;
  968. }
  969. if (!first)
  970. ret = strbuf_add(buf, "]>", 2);
  971. out:
  972. return ret;
  973. }
  974. #else
  975. int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
  976. Dwarf_Die *vr_die __maybe_unused,
  977. struct strbuf *buf __maybe_unused)
  978. {
  979. return -ENOTSUP;
  980. }
  981. #endif
  982. /*
  983. * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
  984. * @vr_die: a variable DIE
  985. */
  986. static bool die_has_loclist(Dwarf_Die *vr_die)
  987. {
  988. Dwarf_Attribute loc;
  989. int tag = dwarf_tag(vr_die);
  990. if (tag != DW_TAG_formal_parameter &&
  991. tag != DW_TAG_variable)
  992. return false;
  993. return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
  994. dwarf_whatform(&loc) == DW_FORM_sec_offset);
  995. }
  996. /*
  997. * die_is_optimized_target - Check if target program is compiled with
  998. * optimization
  999. * @cu_die: a CU DIE
  1000. *
  1001. * For any object in given CU whose DW_AT_location is a location list,
  1002. * target program is compiled with optimization. This is applicable to
  1003. * clang as well.
  1004. */
  1005. bool die_is_optimized_target(Dwarf_Die *cu_die)
  1006. {
  1007. Dwarf_Die tmp_die;
  1008. if (die_has_loclist(cu_die))
  1009. return true;
  1010. if (!dwarf_child(cu_die, &tmp_die) &&
  1011. die_is_optimized_target(&tmp_die))
  1012. return true;
  1013. if (!dwarf_siblingof(cu_die, &tmp_die) &&
  1014. die_is_optimized_target(&tmp_die))
  1015. return true;
  1016. return false;
  1017. }
  1018. /*
  1019. * die_search_idx - Search index of given line address
  1020. * @lines: Line records of single CU
  1021. * @nr_lines: Number of @lines
  1022. * @addr: address we are looking for
  1023. * @idx: index to be set by this function (return value)
  1024. *
  1025. * Search for @addr by looping over every lines of CU. If address
  1026. * matches, set index of that line in @idx. Note that single source
  1027. * line can have multiple line records. i.e. single source line can
  1028. * have multiple index.
  1029. */
  1030. static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
  1031. Dwarf_Addr addr, unsigned long *idx)
  1032. {
  1033. unsigned long i;
  1034. Dwarf_Addr tmp;
  1035. for (i = 0; i < nr_lines; i++) {
  1036. if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
  1037. return false;
  1038. if (tmp == addr) {
  1039. *idx = i;
  1040. return true;
  1041. }
  1042. }
  1043. return false;
  1044. }
  1045. /*
  1046. * die_get_postprologue_addr - Search next address after function prologue
  1047. * @entrypc_idx: entrypc index
  1048. * @lines: Line records of single CU
  1049. * @nr_lines: Number of @lines
  1050. * @hignpc: high PC address of function
  1051. * @postprologue_addr: Next address after function prologue (return value)
  1052. *
  1053. * Look for prologue-end marker. If there is no explicit marker, return
  1054. * address of next line record or next source line.
  1055. */
  1056. static bool die_get_postprologue_addr(unsigned long entrypc_idx,
  1057. Dwarf_Lines *lines,
  1058. unsigned long nr_lines,
  1059. Dwarf_Addr highpc,
  1060. Dwarf_Addr *postprologue_addr)
  1061. {
  1062. unsigned long i;
  1063. int entrypc_lno, lno;
  1064. Dwarf_Line *line;
  1065. Dwarf_Addr addr;
  1066. bool p_end;
  1067. /* entrypc_lno is actual source line number */
  1068. line = dwarf_onesrcline(lines, entrypc_idx);
  1069. if (dwarf_lineno(line, &entrypc_lno))
  1070. return false;
  1071. for (i = entrypc_idx; i < nr_lines; i++) {
  1072. line = dwarf_onesrcline(lines, i);
  1073. if (dwarf_lineaddr(line, &addr) ||
  1074. dwarf_lineno(line, &lno) ||
  1075. dwarf_lineprologueend(line, &p_end))
  1076. return false;
  1077. /* highpc is exclusive. [entrypc,highpc) */
  1078. if (addr >= highpc)
  1079. break;
  1080. /* clang supports prologue-end marker */
  1081. if (p_end)
  1082. break;
  1083. /* Actual next line in source */
  1084. if (lno != entrypc_lno)
  1085. break;
  1086. /*
  1087. * Single source line can have multiple line records.
  1088. * For Example,
  1089. * void foo() { printf("hello\n"); }
  1090. * contains two line records. One points to declaration and
  1091. * other points to printf() line. Variable 'lno' won't get
  1092. * incremented in this case but 'i' will.
  1093. */
  1094. if (i != entrypc_idx)
  1095. break;
  1096. }
  1097. dwarf_lineaddr(line, postprologue_addr);
  1098. if (*postprologue_addr >= highpc)
  1099. dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
  1100. postprologue_addr);
  1101. return true;
  1102. }
  1103. /*
  1104. * die_skip_prologue - Use next address after prologue as probe location
  1105. * @sp_die: a subprogram DIE
  1106. * @cu_die: a CU DIE
  1107. * @entrypc: entrypc of the function
  1108. *
  1109. * Function prologue prepares stack and registers before executing function
  1110. * logic. When target program is compiled without optimization, function
  1111. * parameter information is only valid after prologue. When we probe entrypc
  1112. * of the function, and try to record function parameter, it contains
  1113. * garbage value.
  1114. */
  1115. void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
  1116. Dwarf_Addr *entrypc)
  1117. {
  1118. size_t nr_lines = 0;
  1119. unsigned long entrypc_idx = 0;
  1120. Dwarf_Lines *lines = NULL;
  1121. Dwarf_Addr postprologue_addr;
  1122. Dwarf_Addr highpc;
  1123. if (dwarf_highpc(sp_die, &highpc))
  1124. return;
  1125. if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
  1126. return;
  1127. if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
  1128. return;
  1129. if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
  1130. highpc, &postprologue_addr))
  1131. return;
  1132. *entrypc = postprologue_addr;
  1133. }