blob: 2b718cfd62d930243a6c1ccc82f0513456cb5d23 [file] [log] [blame]
Thomas Gleixner1a59d1b82019-05-27 08:55:05 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Masami Hiramatsue0d153c2011-06-27 16:27:27 +09002/*
3 * dwarf-aux.c : libdw auxiliary interfaces
Masami Hiramatsue0d153c2011-06-27 16:27:27 +09004 */
5
Arnaldo Carvalho de Meloa43783a2017-04-18 10:46:11 -03006#include <errno.h>
Arnaldo Carvalho de Melofd20e812017-04-17 15:23:08 -03007#include <inttypes.h>
Masami Hiramatsue0d153c2011-06-27 16:27:27 +09008#include <stdbool.h>
Arnaldo Carvalho de Melo215a0d32019-07-04 11:21:24 -03009#include <stdlib.h>
Masami Hiramatsue0d153c2011-06-27 16:27:27 +090010#include "debug.h"
11#include "dwarf-aux.h"
Arnaldo Carvalho de Melo8520a982019-08-29 16:18:59 -030012#include "strbuf.h"
Arnaldo Carvalho de Meloa0675582017-04-17 16:51:59 -030013#include "string2.h"
Masami Hiramatsue0d153c2011-06-27 16:27:27 +090014
15/**
16 * cu_find_realpath - Find the realpath of the target file
17 * @cu_die: A DIE(dwarf information entry) of CU(compilation Unit)
18 * @fname: The tail filename of the target file
19 *
20 * Find the real(long) path of @fname in @cu_die.
21 */
22const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
23{
24 Dwarf_Files *files;
25 size_t nfiles, i;
26 const char *src = NULL;
27 int ret;
28
29 if (!fname)
30 return NULL;
31
32 ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
33 if (ret != 0)
34 return NULL;
35
36 for (i = 0; i < nfiles; i++) {
37 src = dwarf_filesrc(files, i, NULL, NULL);
38 if (strtailcmp(src, fname) == 0)
39 break;
40 }
41 if (i == nfiles)
42 return NULL;
43 return src;
44}
45
46/**
47 * cu_get_comp_dir - Get the path of compilation directory
48 * @cu_die: a CU DIE
49 *
50 * Get the path of compilation directory of given @cu_die.
51 * Since this depends on DW_AT_comp_dir, older gcc will not
52 * embedded it. In that case, this returns NULL.
53 */
54const char *cu_get_comp_dir(Dwarf_Die *cu_die)
55{
56 Dwarf_Attribute attr;
57 if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
58 return NULL;
59 return dwarf_formstring(&attr);
60}
61
62/**
63 * cu_find_lineinfo - Get a line number and file name for given address
64 * @cu_die: a CU DIE
65 * @addr: An address
66 * @fname: a pointer which returns the file name string
67 * @lineno: a pointer which returns the line number
68 *
69 * Find a line number and file name for @addr in @cu_die.
70 */
71int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr,
72 const char **fname, int *lineno)
73{
74 Dwarf_Line *line;
75 Dwarf_Addr laddr;
76
77 line = dwarf_getsrc_die(cu_die, (Dwarf_Addr)addr);
78 if (line && dwarf_lineaddr(line, &laddr) == 0 &&
79 addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
80 *fname = dwarf_linesrc(line, NULL, NULL);
81 if (!*fname)
82 /* line number is useless without filename */
83 *lineno = 0;
84 }
85
86 return *lineno ?: -ENOENT;
87}
88
Masami Hiramatsu221d0612011-08-11 20:02:59 +090089static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data);
90
91/**
92 * cu_walk_functions_at - Walk on function DIEs at given address
93 * @cu_die: A CU DIE
94 * @addr: An address
95 * @callback: A callback which called with found DIEs
96 * @data: A user data
97 *
98 * Walk on function DIEs at given @addr in @cu_die. Passed DIEs
99 * should be subprogram or inlined-subroutines.
100 */
101int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
102 int (*callback)(Dwarf_Die *, void *), void *data)
103{
104 Dwarf_Die die_mem;
105 Dwarf_Die *sc_die;
106 int ret = -ENOENT;
107
108 /* Inlined function could be recursive. Trace it until fail */
109 for (sc_die = die_find_realfunc(cu_die, addr, &die_mem);
110 sc_die != NULL;
111 sc_die = die_find_child(sc_die, __die_find_inline_cb, &addr,
112 &die_mem)) {
113 ret = callback(sc_die, data);
114 if (ret)
115 break;
116 }
117
118 return ret;
119
120}
121
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900122/**
Masami Hiramatsud5a00292016-09-24 00:35:31 +0900123 * die_get_linkage_name - Get the linkage name of the object
124 * @dw_die: A DIE of the object
125 *
126 * Get the linkage name attiribute of given @dw_die.
127 * For C++ binary, the linkage name will be the mangled symbol.
128 */
129const char *die_get_linkage_name(Dwarf_Die *dw_die)
130{
131 Dwarf_Attribute attr;
132
133 if (dwarf_attr_integrate(dw_die, DW_AT_linkage_name, &attr) == NULL)
134 return NULL;
135 return dwarf_formstring(&attr);
136}
137
138/**
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900139 * die_compare_name - Compare diename and tname
140 * @dw_die: a DIE
141 * @tname: a string of target name
142 *
143 * Compare the name of @dw_die and @tname. Return false if @dw_die has no name.
144 */
145bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
146{
147 const char *name;
Masami Hiramatsu4c859352015-05-08 10:03:35 +0900148
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900149 name = dwarf_diename(dw_die);
150 return name ? (strcmp(tname, name) == 0) : false;
151}
152
153/**
Masami Hiramatsud5a00292016-09-24 00:35:31 +0900154 * die_match_name - Match diename/linkage name and glob
Masami Hiramatsu4c859352015-05-08 10:03:35 +0900155 * @dw_die: a DIE
156 * @glob: a string of target glob pattern
157 *
158 * Glob matching the name of @dw_die and @glob. Return false if matching fail.
Masami Hiramatsud5a00292016-09-24 00:35:31 +0900159 * This also match linkage name.
Masami Hiramatsu4c859352015-05-08 10:03:35 +0900160 */
161bool die_match_name(Dwarf_Die *dw_die, const char *glob)
162{
163 const char *name;
164
165 name = dwarf_diename(dw_die);
Masami Hiramatsud5a00292016-09-24 00:35:31 +0900166 if (name && strglobmatch(name, glob))
167 return true;
168 /* fall back to check linkage name */
169 name = die_get_linkage_name(dw_die);
170 if (name && strglobmatch(name, glob))
171 return true;
172
173 return false;
Masami Hiramatsu4c859352015-05-08 10:03:35 +0900174}
175
176/**
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900177 * die_get_call_lineno - Get callsite line number of inline-function instance
178 * @in_die: a DIE of an inlined function instance
179 *
180 * Get call-site line number of @in_die. This means from where the inline
181 * function is called.
182 */
183int die_get_call_lineno(Dwarf_Die *in_die)
184{
185 Dwarf_Attribute attr;
186 Dwarf_Word ret;
187
188 if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
189 return -ENOENT;
190
191 dwarf_formudata(&attr, &ret);
192 return (int)ret;
193}
194
195/**
196 * die_get_type - Get type DIE
197 * @vr_die: a DIE of a variable
198 * @die_mem: where to store a type DIE
199 *
200 * Get a DIE of the type of given variable (@vr_die), and store
201 * it to die_mem. Return NULL if fails to get a type DIE.
202 */
203Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
204{
205 Dwarf_Attribute attr;
206
207 if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
208 dwarf_formref_die(&attr, die_mem))
209 return die_mem;
210 else
211 return NULL;
212}
213
214/* Get a type die, but skip qualifiers */
215static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
216{
217 int tag;
218
219 do {
220 vr_die = die_get_type(vr_die, die_mem);
221 if (!vr_die)
222 break;
223 tag = dwarf_tag(vr_die);
224 } while (tag == DW_TAG_const_type ||
225 tag == DW_TAG_restrict_type ||
226 tag == DW_TAG_volatile_type ||
227 tag == DW_TAG_shared_type);
228
229 return vr_die;
230}
231
232/**
233 * die_get_real_type - Get a type die, but skip qualifiers and typedef
234 * @vr_die: a DIE of a variable
235 * @die_mem: where to store a type DIE
236 *
237 * Get a DIE of the type of given variable (@vr_die), and store
238 * it to die_mem. Return NULL if fails to get a type DIE.
239 * If the type is qualifiers (e.g. const) or typedef, this skips it
240 * and tries to find real type (structure or basic types, e.g. int).
241 */
242Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
243{
244 do {
245 vr_die = __die_get_real_type(vr_die, die_mem);
246 } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
247
248 return vr_die;
249}
250
251/* Get attribute and translate it as a udata */
252static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
253 Dwarf_Word *result)
254{
255 Dwarf_Attribute attr;
256
257 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
258 dwarf_formudata(&attr, result) != 0)
259 return -ENOENT;
260
261 return 0;
262}
263
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900264/* Get attribute and translate it as a sdata */
265static int die_get_attr_sdata(Dwarf_Die *tp_die, unsigned int attr_name,
266 Dwarf_Sword *result)
267{
268 Dwarf_Attribute attr;
269
270 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
271 dwarf_formsdata(&attr, result) != 0)
272 return -ENOENT;
273
274 return 0;
275}
276
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900277/**
278 * die_is_signed_type - Check whether a type DIE is signed or not
279 * @tp_die: a DIE of a type
280 *
281 * Get the encoding of @tp_die and return true if the encoding
282 * is signed.
283 */
284bool die_is_signed_type(Dwarf_Die *tp_die)
285{
286 Dwarf_Word ret;
287
288 if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
289 return false;
290
291 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
292 ret == DW_ATE_signed_fixed);
293}
294
295/**
Masami Hiramatsu0dbb1ca2012-04-23 12:24:36 +0900296 * die_is_func_def - Ensure that this DIE is a subprogram and definition
297 * @dw_die: a DIE
298 *
299 * Ensure that this DIE is a subprogram and NOT a declaration. This
300 * returns true if @dw_die is a function definition.
301 **/
302bool die_is_func_def(Dwarf_Die *dw_die)
303{
304 Dwarf_Attribute attr;
305
306 return (dwarf_tag(dw_die) == DW_TAG_subprogram &&
307 dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL);
308}
309
310/**
Masami Hiramatsue1ecbbc2015-01-30 18:37:44 +0900311 * die_is_func_instance - Ensure that this DIE is an instance of a subprogram
312 * @dw_die: a DIE
313 *
314 * Ensure that this DIE is an instance (which has an entry address).
315 * This returns true if @dw_die is a function instance. If not, you need to
316 * call die_walk_instances() to find actual instances.
317 **/
318bool die_is_func_instance(Dwarf_Die *dw_die)
319{
320 Dwarf_Addr tmp;
Masami Hiramatsubb3e5a42019-10-24 18:12:36 +0900321 Dwarf_Attribute attr_mem;
Masami Hiramatsue1ecbbc2015-01-30 18:37:44 +0900322
323 /* Actually gcc optimizes non-inline as like as inlined */
Masami Hiramatsubb3e5a42019-10-24 18:12:36 +0900324 return !dwarf_func_inline(dw_die) &&
325 (dwarf_entrypc(dw_die, &tmp) == 0 ||
326 dwarf_attr(dw_die, DW_AT_ranges, &attr_mem) != NULL);
Masami Hiramatsue1ecbbc2015-01-30 18:37:44 +0900327}
Masami Hiramatsubb3e5a42019-10-24 18:12:36 +0900328
Masami Hiramatsue1ecbbc2015-01-30 18:37:44 +0900329/**
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900330 * die_get_data_member_location - Get the data-member offset
331 * @mb_die: a DIE of a member of a data structure
332 * @offs: The offset of the member in the data structure
333 *
334 * Get the offset of @mb_die in the data structure including @mb_die, and
335 * stores result offset to @offs. If any error occurs this returns errno.
336 */
337int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
338{
339 Dwarf_Attribute attr;
340 Dwarf_Op *expr;
341 size_t nexpr;
342 int ret;
343
344 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
345 return -ENOENT;
346
347 if (dwarf_formudata(&attr, offs) != 0) {
348 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
349 ret = dwarf_getlocation(&attr, &expr, &nexpr);
350 if (ret < 0 || nexpr == 0)
351 return -ENOENT;
352
353 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
354 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
355 expr[0].atom, nexpr);
356 return -ENOTSUP;
357 }
358 *offs = (Dwarf_Word)expr[0].number;
359 }
360 return 0;
361}
362
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900363/* Get the call file index number in CU DIE */
364static int die_get_call_fileno(Dwarf_Die *in_die)
365{
366 Dwarf_Sword idx;
367
368 if (die_get_attr_sdata(in_die, DW_AT_call_file, &idx) == 0)
369 return (int)idx;
370 else
371 return -ENOENT;
372}
373
Masami Hiramatsu3f4460a2011-08-11 20:03:18 +0900374/* Get the declared file index number in CU DIE */
375static int die_get_decl_fileno(Dwarf_Die *pdie)
376{
377 Dwarf_Sword idx;
378
379 if (die_get_attr_sdata(pdie, DW_AT_decl_file, &idx) == 0)
380 return (int)idx;
381 else
382 return -ENOENT;
383}
384
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900385/**
386 * die_get_call_file - Get callsite file name of inlined function instance
387 * @in_die: a DIE of an inlined function instance
388 *
389 * Get call-site file name of @in_die. This means from which file the inline
390 * function is called.
391 */
392const char *die_get_call_file(Dwarf_Die *in_die)
393{
394 Dwarf_Die cu_die;
395 Dwarf_Files *files;
396 int idx;
397
398 idx = die_get_call_fileno(in_die);
399 if (idx < 0 || !dwarf_diecu(in_die, &cu_die, NULL, NULL) ||
400 dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
401 return NULL;
402
403 return dwarf_filesrc(files, idx, NULL, NULL);
404}
405
406
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900407/**
408 * die_find_child - Generic DIE search function in DIE tree
409 * @rt_die: a root DIE
410 * @callback: a callback function
411 * @data: a user data passed to the callback function
412 * @die_mem: a buffer for result DIE
413 *
414 * Trace DIE tree from @rt_die and call @callback for each child DIE.
415 * If @callback returns DIE_FIND_CB_END, this stores the DIE into
416 * @die_mem and returns it. If @callback returns DIE_FIND_CB_CONTINUE,
417 * this continues to trace the tree. Optionally, @callback can return
418 * DIE_FIND_CB_CHILD and DIE_FIND_CB_SIBLING, those means trace only
419 * the children and trace only the siblings respectively.
420 * Returns NULL if @callback can't find any appropriate DIE.
421 */
422Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
423 int (*callback)(Dwarf_Die *, void *),
424 void *data, Dwarf_Die *die_mem)
425{
426 Dwarf_Die child_die;
427 int ret;
428
429 ret = dwarf_child(rt_die, die_mem);
430 if (ret != 0)
431 return NULL;
432
433 do {
434 ret = callback(die_mem, data);
435 if (ret == DIE_FIND_CB_END)
436 return die_mem;
437
438 if ((ret & DIE_FIND_CB_CHILD) &&
439 die_find_child(die_mem, callback, data, &child_die)) {
440 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
441 return die_mem;
442 }
443 } while ((ret & DIE_FIND_CB_SIBLING) &&
444 dwarf_siblingof(die_mem, die_mem) == 0);
445
446 return NULL;
447}
448
449struct __addr_die_search_param {
450 Dwarf_Addr addr;
451 Dwarf_Die *die_mem;
452};
453
Naveen N. Raod4c537e2015-04-30 17:12:31 +0530454static int __die_search_func_tail_cb(Dwarf_Die *fn_die, void *data)
455{
456 struct __addr_die_search_param *ad = data;
457 Dwarf_Addr addr = 0;
458
459 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
460 !dwarf_highpc(fn_die, &addr) &&
461 addr == ad->addr) {
462 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
463 return DWARF_CB_ABORT;
464 }
465 return DWARF_CB_OK;
466}
467
468/**
469 * die_find_tailfunc - Search for a non-inlined function with tail call at
470 * given address
471 * @cu_die: a CU DIE which including @addr
472 * @addr: target address
473 * @die_mem: a buffer for result DIE
474 *
475 * Search for a non-inlined function DIE with tail call at @addr. Stores the
476 * DIE to @die_mem and returns it if found. Returns NULL if failed.
477 */
478Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
479 Dwarf_Die *die_mem)
480{
481 struct __addr_die_search_param ad;
482 ad.addr = addr;
483 ad.die_mem = die_mem;
484 /* dwarf_getscopes can't find subprogram. */
485 if (!dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0))
486 return NULL;
487 else
488 return die_mem;
489}
490
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900491/* die_find callback for non-inlined function search */
492static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
493{
494 struct __addr_die_search_param *ad = data;
495
Masami Hiramatsu0dbb1ca2012-04-23 12:24:36 +0900496 /*
497 * Since a declaration entry doesn't has given pc, this always returns
498 * function definition entry.
499 */
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900500 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
501 dwarf_haspc(fn_die, ad->addr)) {
502 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
503 return DWARF_CB_ABORT;
504 }
505 return DWARF_CB_OK;
506}
507
508/**
509 * die_find_realfunc - Search a non-inlined function at given address
510 * @cu_die: a CU DIE which including @addr
511 * @addr: target address
512 * @die_mem: a buffer for result DIE
513 *
514 * Search a non-inlined function DIE which includes @addr. Stores the
Masami Hiramatsue08cfd42013-09-30 18:21:44 +0900515 * DIE to @die_mem and returns it if found. Returns NULL if failed.
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900516 */
517Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
518 Dwarf_Die *die_mem)
519{
520 struct __addr_die_search_param ad;
521 ad.addr = addr;
522 ad.die_mem = die_mem;
523 /* dwarf_getscopes can't find subprogram. */
524 if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
525 return NULL;
526 else
527 return die_mem;
528}
529
530/* die_find callback for inline function search */
531static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
532{
533 Dwarf_Addr *addr = data;
534
535 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
536 dwarf_haspc(die_mem, *addr))
537 return DIE_FIND_CB_END;
538
539 return DIE_FIND_CB_CONTINUE;
540}
541
542/**
Masami Hiramatsue08cfd42013-09-30 18:21:44 +0900543 * die_find_top_inlinefunc - Search the top inlined function at given address
544 * @sp_die: a subprogram DIE which including @addr
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900545 * @addr: target address
546 * @die_mem: a buffer for result DIE
547 *
548 * Search an inlined function DIE which includes @addr. Stores the
Masami Hiramatsue08cfd42013-09-30 18:21:44 +0900549 * DIE to @die_mem and returns it if found. Returns NULL if failed.
550 * Even if several inlined functions are expanded recursively, this
551 * doesn't trace it down, and returns the topmost one.
552 */
553Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
554 Dwarf_Die *die_mem)
555{
556 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
557}
558
559/**
560 * die_find_inlinefunc - Search an inlined function at given address
561 * @sp_die: a subprogram DIE which including @addr
562 * @addr: target address
563 * @die_mem: a buffer for result DIE
564 *
565 * Search an inlined function DIE which includes @addr. Stores the
566 * DIE to @die_mem and returns it if found. Returns NULL if failed.
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900567 * If several inlined functions are expanded recursively, this trace
Masami Hiramatsue08cfd42013-09-30 18:21:44 +0900568 * it down and returns deepest one.
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900569 */
570Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
571 Dwarf_Die *die_mem)
572{
573 Dwarf_Die tmp_die;
574
575 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
576 if (!sp_die)
577 return NULL;
578
579 /* Inlined function could be recursive. Trace it until fail */
580 while (sp_die) {
581 memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
582 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
583 &tmp_die);
584 }
585
586 return die_mem;
587}
588
Masami Hiramatsudb0d2c62011-08-11 20:03:11 +0900589struct __instance_walk_param {
590 void *addr;
591 int (*callback)(Dwarf_Die *, void *);
592 void *data;
593 int retval;
594};
595
596static int __die_walk_instances_cb(Dwarf_Die *inst, void *data)
597{
598 struct __instance_walk_param *iwp = data;
599 Dwarf_Attribute attr_mem;
600 Dwarf_Die origin_mem;
601 Dwarf_Attribute *attr;
602 Dwarf_Die *origin;
Masami Hiramatsu3f4460a2011-08-11 20:03:18 +0900603 int tmp;
Masami Hiramatsudb0d2c62011-08-11 20:03:11 +0900604
605 attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem);
606 if (attr == NULL)
607 return DIE_FIND_CB_CONTINUE;
608
609 origin = dwarf_formref_die(attr, &origin_mem);
610 if (origin == NULL || origin->addr != iwp->addr)
611 return DIE_FIND_CB_CONTINUE;
612
Masami Hiramatsu3f4460a2011-08-11 20:03:18 +0900613 /* Ignore redundant instances */
614 if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) {
615 dwarf_decl_line(origin, &tmp);
616 if (die_get_call_lineno(inst) == tmp) {
617 tmp = die_get_decl_fileno(origin);
618 if (die_get_call_fileno(inst) == tmp)
619 return DIE_FIND_CB_CONTINUE;
620 }
621 }
622
Masami Hiramatsudb0d2c62011-08-11 20:03:11 +0900623 iwp->retval = iwp->callback(inst, iwp->data);
624
625 return (iwp->retval) ? DIE_FIND_CB_END : DIE_FIND_CB_CONTINUE;
626}
627
628/**
629 * die_walk_instances - Walk on instances of given DIE
630 * @or_die: an abstract original DIE
631 * @callback: a callback function which is called with instance DIE
632 * @data: user data
633 *
634 * Walk on the instances of give @in_die. @in_die must be an inlined function
635 * declartion. This returns the return value of @callback if it returns
636 * non-zero value, or -ENOENT if there is no instance.
637 */
638int die_walk_instances(Dwarf_Die *or_die, int (*callback)(Dwarf_Die *, void *),
639 void *data)
640{
641 Dwarf_Die cu_die;
642 Dwarf_Die die_mem;
643 struct __instance_walk_param iwp = {
644 .addr = or_die->addr,
645 .callback = callback,
646 .data = data,
647 .retval = -ENOENT,
648 };
649
650 if (dwarf_diecu(or_die, &cu_die, NULL, NULL) == NULL)
651 return -ENOENT;
652
653 die_find_child(&cu_die, __die_walk_instances_cb, &iwp, &die_mem);
654
655 return iwp.retval;
656}
657
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900658/* Line walker internal parameters */
659struct __line_walk_param {
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900660 bool recursive;
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900661 line_walk_callback_t callback;
662 void *data;
663 int retval;
664};
665
666static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
667{
668 struct __line_walk_param *lw = data;
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900669 Dwarf_Addr addr = 0;
670 const char *fname;
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900671 int lineno;
672
673 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900674 fname = die_get_call_file(in_die);
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900675 lineno = die_get_call_lineno(in_die);
Masami Hiramatsu3be8c5c2019-10-25 17:47:01 +0900676 if (fname && lineno > 0 && die_entrypc(in_die, &addr) == 0) {
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900677 lw->retval = lw->callback(fname, lineno, addr, lw->data);
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900678 if (lw->retval != 0)
679 return DIE_FIND_CB_END;
680 }
Masami Hiramatsu8c5d03e2019-10-24 18:12:45 +0900681 if (!lw->recursive)
682 return DIE_FIND_CB_SIBLING;
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900683 }
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900684
685 if (addr) {
686 fname = dwarf_decl_file(in_die);
687 if (fname && dwarf_decl_line(in_die, &lineno) == 0) {
688 lw->retval = lw->callback(fname, lineno, addr, lw->data);
689 if (lw->retval != 0)
690 return DIE_FIND_CB_END;
691 }
692 }
693
694 /* Continue to search nested inlined function call-sites */
695 return DIE_FIND_CB_CONTINUE;
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900696}
697
698/* Walk on lines of blocks included in given DIE */
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900699static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive,
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900700 line_walk_callback_t callback, void *data)
701{
702 struct __line_walk_param lw = {
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900703 .recursive = recursive,
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900704 .callback = callback,
705 .data = data,
706 .retval = 0,
707 };
708 Dwarf_Die die_mem;
709 Dwarf_Addr addr;
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900710 const char *fname;
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900711 int lineno;
712
713 /* Handle function declaration line */
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900714 fname = dwarf_decl_file(sp_die);
715 if (fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900716 dwarf_entrypc(sp_die, &addr) == 0) {
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900717 lw.retval = callback(fname, lineno, addr, data);
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900718 if (lw.retval != 0)
719 goto done;
720 }
721 die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
722done:
723 return lw.retval;
724}
725
726static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
727{
728 struct __line_walk_param *lw = data;
729
Masami Hiramatsu8c5d03e2019-10-24 18:12:45 +0900730 /*
731 * Since inlined function can include another inlined function in
732 * the same file, we need to walk in it recursively.
733 */
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900734 lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data);
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900735 if (lw->retval != 0)
736 return DWARF_CB_ABORT;
737
738 return DWARF_CB_OK;
739}
740
741/**
742 * die_walk_lines - Walk on lines inside given DIE
Masami Hiramatsua1284052011-08-11 20:02:35 +0900743 * @rt_die: a root DIE (CU, subprogram or inlined_subroutine)
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900744 * @callback: callback routine
745 * @data: user data
746 *
747 * Walk on all lines inside given @rt_die and call @callback on each line.
748 * If the @rt_die is a function, walk only on the lines inside the function,
749 * otherwise @rt_die must be a CU DIE.
750 * Note that this walks not only dwarf line list, but also function entries
751 * and inline call-site.
752 */
753int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
754{
755 Dwarf_Lines *lines;
756 Dwarf_Line *line;
757 Dwarf_Addr addr;
Masami Hiramatsu62152ad2019-10-30 16:09:40 +0900758 const char *fname, *decf = NULL, *inf = NULL;
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900759 int lineno, ret = 0;
Masami Hiramatsu75186a92015-08-12 10:24:07 +0900760 int decl = 0, inl;
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900761 Dwarf_Die die_mem, *cu_die;
762 size_t nlines, i;
763
764 /* Get the CU die */
Masami Hiramatsu75186a92015-08-12 10:24:07 +0900765 if (dwarf_tag(rt_die) != DW_TAG_compile_unit) {
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900766 cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
Masami Hiramatsu75186a92015-08-12 10:24:07 +0900767 dwarf_decl_line(rt_die, &decl);
768 decf = dwarf_decl_file(rt_die);
769 } else
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900770 cu_die = rt_die;
771 if (!cu_die) {
Masami Hiramatsua1284052011-08-11 20:02:35 +0900772 pr_debug2("Failed to get CU from given DIE.\n");
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900773 return -EINVAL;
774 }
775
776 /* Get lines list in the CU */
777 if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
778 pr_debug2("Failed to get source lines on this CU.\n");
779 return -ENOENT;
780 }
781 pr_debug2("Get %zd lines from this CU\n", nlines);
782
783 /* Walk on the lines on lines list */
784 for (i = 0; i < nlines; i++) {
785 line = dwarf_onesrcline(lines, i);
786 if (line == NULL ||
787 dwarf_lineno(line, &lineno) != 0 ||
788 dwarf_lineaddr(line, &addr) != 0) {
789 pr_debug2("Failed to get line info. "
790 "Possible error in debuginfo.\n");
791 continue;
792 }
793 /* Filter lines based on address */
Masami Hiramatsu86a76022015-08-13 06:55:41 +0900794 if (rt_die != cu_die) {
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900795 /*
796 * Address filtering
797 * The line is included in given function, and
798 * no inline block includes it.
799 */
Masami Hiramatsu75186a92015-08-12 10:24:07 +0900800 if (!dwarf_haspc(rt_die, addr))
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900801 continue;
Masami Hiramatsu62152ad2019-10-30 16:09:40 +0900802
Masami Hiramatsu75186a92015-08-12 10:24:07 +0900803 if (die_find_inlinefunc(rt_die, addr, &die_mem)) {
Masami Hiramatsu62152ad2019-10-30 16:09:40 +0900804 /* Call-site check */
805 inf = die_get_call_file(&die_mem);
806 if ((inf && !strcmp(inf, decf)) &&
807 die_get_call_lineno(&die_mem) == lineno)
808 goto found;
809
Masami Hiramatsu75186a92015-08-12 10:24:07 +0900810 dwarf_decl_line(&die_mem, &inl);
811 if (inl != decl ||
812 decf != dwarf_decl_file(&die_mem))
813 continue;
814 }
Masami Hiramatsu86a76022015-08-13 06:55:41 +0900815 }
Masami Hiramatsu62152ad2019-10-30 16:09:40 +0900816found:
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900817 /* Get source line */
818 fname = dwarf_linesrc(line, NULL, NULL);
819
820 ret = callback(fname, lineno, addr, data);
821 if (ret != 0)
822 return ret;
823 }
824
825 /*
826 * Dwarf lines doesn't include function declarations and inlined
827 * subroutines. We have to check functions list or given function.
828 */
829 if (rt_die != cu_die)
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900830 /*
Masami Hiramatsu8c5d03e2019-10-24 18:12:45 +0900831 * Don't need walk inlined functions recursively, because
832 * inner inlined functions don't have the lines of the
833 * specified function.
Masami Hiramatsub0e9cb22011-08-11 20:02:41 +0900834 */
835 ret = __die_walk_funclines(rt_die, false, callback, data);
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900836 else {
837 struct __line_walk_param param = {
838 .callback = callback,
839 .data = data,
840 .retval = 0,
841 };
842 dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
843 ret = param.retval;
844 }
845
846 return ret;
847}
848
849struct __find_variable_param {
850 const char *name;
851 Dwarf_Addr addr;
852};
853
854static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
855{
856 struct __find_variable_param *fvp = data;
Masami Hiramatsu082f96a2014-05-29 21:19:30 +0900857 Dwarf_Attribute attr;
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900858 int tag;
859
860 tag = dwarf_tag(die_mem);
861 if ((tag == DW_TAG_formal_parameter ||
862 tag == DW_TAG_variable) &&
Masami Hiramatsu082f96a2014-05-29 21:19:30 +0900863 die_compare_name(die_mem, fvp->name) &&
864 /* Does the DIE have location information or external instance? */
865 (dwarf_attr(die_mem, DW_AT_external, &attr) ||
866 dwarf_attr(die_mem, DW_AT_location, &attr)))
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900867 return DIE_FIND_CB_END;
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900868 if (dwarf_haspc(die_mem, fvp->addr))
869 return DIE_FIND_CB_CONTINUE;
870 else
871 return DIE_FIND_CB_SIBLING;
872}
873
874/**
875 * die_find_variable_at - Find a given name variable at given address
876 * @sp_die: a function DIE
877 * @name: variable name
878 * @addr: address
879 * @die_mem: a buffer for result DIE
880 *
881 * Find a variable DIE called @name at @addr in @sp_die.
882 */
883Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
884 Dwarf_Addr addr, Dwarf_Die *die_mem)
885{
886 struct __find_variable_param fvp = { .name = name, .addr = addr};
887
888 return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
889 die_mem);
890}
891
892static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
893{
894 const char *name = data;
895
Masami Hiramatsuc7273832015-04-02 16:33:12 +0900896 if (dwarf_tag(die_mem) == DW_TAG_member) {
897 if (die_compare_name(die_mem, name))
898 return DIE_FIND_CB_END;
899 else if (!dwarf_diename(die_mem)) { /* Unnamed structure */
900 Dwarf_Die type_die, tmp_die;
901 if (die_get_type(die_mem, &type_die) &&
902 die_find_member(&type_die, name, &tmp_die))
903 return DIE_FIND_CB_END;
904 }
905 }
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900906 return DIE_FIND_CB_SIBLING;
907}
908
909/**
910 * die_find_member - Find a given name member in a data structure
911 * @st_die: a data structure type DIE
912 * @name: member name
913 * @die_mem: a buffer for result DIE
914 *
915 * Find a member DIE called @name in @st_die.
916 */
917Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
918 Dwarf_Die *die_mem)
919{
920 return die_find_child(st_die, __die_find_member_cb, (void *)name,
921 die_mem);
922}
923
924/**
925 * die_get_typename - Get the name of given variable DIE
926 * @vr_die: a variable DIE
He Kuangfb9596d2015-05-11 09:25:02 +0000927 * @buf: a strbuf for result type name
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900928 *
He Kuangfb9596d2015-05-11 09:25:02 +0000929 * Get the name of @vr_die and stores it to @buf. Return 0 if succeeded.
930 * and Return -ENOENT if failed to find type name.
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900931 * Note that the result will stores typedef name if possible, and stores
932 * "*(function_type)" if the type is a function pointer.
933 */
He Kuangfb9596d2015-05-11 09:25:02 +0000934int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900935{
936 Dwarf_Die type;
He Kuangfb9596d2015-05-11 09:25:02 +0000937 int tag, ret;
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900938 const char *tmp = "";
939
940 if (__die_get_real_type(vr_die, &type) == NULL)
941 return -ENOENT;
942
943 tag = dwarf_tag(&type);
944 if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
945 tmp = "*";
946 else if (tag == DW_TAG_subroutine_type) {
947 /* Function pointer */
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +0900948 return strbuf_add(buf, "(function_type)", 15);
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900949 } else {
950 if (!dwarf_diename(&type))
951 return -ENOENT;
952 if (tag == DW_TAG_union_type)
953 tmp = "union ";
954 else if (tag == DW_TAG_structure_type)
955 tmp = "struct ";
Hyeoncheol Leebb2d17a2012-09-27 11:36:39 +0900956 else if (tag == DW_TAG_enumeration_type)
957 tmp = "enum ";
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900958 /* Write a base name */
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +0900959 return strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type));
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900960 }
He Kuangfb9596d2015-05-11 09:25:02 +0000961 ret = die_get_typename(&type, buf);
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +0900962 return ret ? ret : strbuf_addstr(buf, tmp);
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900963}
964
965/**
966 * die_get_varname - Get the name and type of given variable DIE
967 * @vr_die: a variable DIE
He Kuangfb9596d2015-05-11 09:25:02 +0000968 * @buf: a strbuf for type and variable name
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900969 *
970 * Get the name and type of @vr_die and stores it in @buf as "type\tname".
971 */
He Kuangfb9596d2015-05-11 09:25:02 +0000972int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900973{
He Kuangfb9596d2015-05-11 09:25:02 +0000974 int ret;
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900975
He Kuangfb9596d2015-05-11 09:25:02 +0000976 ret = die_get_typename(vr_die, buf);
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900977 if (ret < 0) {
978 pr_debug("Failed to get type, make it unknown.\n");
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +0900979 ret = strbuf_add(buf, " (unknown_type)", 14);
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900980 }
He Kuangfb9596d2015-05-11 09:25:02 +0000981
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +0900982 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
Masami Hiramatsue0d153c2011-06-27 16:27:27 +0900983}
984
Jin Yaoa36ebe42018-03-30 17:27:13 +0800985#ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT
He Kuang349e8d22015-05-11 09:25:03 +0000986/**
987 * die_get_var_innermost_scope - Get innermost scope range of given variable DIE
988 * @sp_die: a subprogram DIE
989 * @vr_die: a variable DIE
990 * @buf: a strbuf for variable byte offset range
991 *
992 * Get the innermost scope range of @vr_die and stores it in @buf as
993 * "@<function_name+[NN-NN,NN-NN]>".
994 */
995static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die,
996 struct strbuf *buf)
997{
998 Dwarf_Die *scopes;
999 int count;
1000 size_t offset = 0;
1001 Dwarf_Addr base;
1002 Dwarf_Addr start, end;
1003 Dwarf_Addr entry;
1004 int ret;
1005 bool first = true;
1006 const char *name;
1007
Masami Hiramatsub61ffc92019-10-25 17:47:10 +09001008 ret = die_entrypc(sp_die, &entry);
He Kuang349e8d22015-05-11 09:25:03 +00001009 if (ret)
1010 return ret;
1011
1012 name = dwarf_diename(sp_die);
1013 if (!name)
1014 return -ENOENT;
1015
1016 count = dwarf_getscopes_die(vr_die, &scopes);
1017
1018 /* (*SCOPES)[1] is the DIE for the scope containing that scope */
1019 if (count <= 1) {
1020 ret = -EINVAL;
1021 goto out;
1022 }
1023
1024 while ((offset = dwarf_ranges(&scopes[1], offset, &base,
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +09001025 &start, &end)) > 0) {
He Kuang349e8d22015-05-11 09:25:03 +00001026 start -= entry;
1027 end -= entry;
1028
1029 if (first) {
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +09001030 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1031 name, start, end);
He Kuang349e8d22015-05-11 09:25:03 +00001032 first = false;
1033 } else {
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +09001034 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1035 start, end);
He Kuang349e8d22015-05-11 09:25:03 +00001036 }
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +09001037 if (ret < 0)
1038 goto out;
He Kuang349e8d22015-05-11 09:25:03 +00001039 }
1040
1041 if (!first)
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +09001042 ret = strbuf_add(buf, "]>", 2);
He Kuang349e8d22015-05-11 09:25:03 +00001043
1044out:
1045 free(scopes);
1046 return ret;
1047}
1048
1049/**
1050 * die_get_var_range - Get byte offset range of given variable DIE
1051 * @sp_die: a subprogram DIE
1052 * @vr_die: a variable DIE
1053 * @buf: a strbuf for type and variable name and byte offset range
1054 *
1055 * Get the byte offset range of @vr_die and stores it in @buf as
1056 * "@<function_name+[NN-NN,NN-NN]>".
1057 */
1058int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf)
1059{
1060 int ret = 0;
1061 Dwarf_Addr base;
1062 Dwarf_Addr start, end;
1063 Dwarf_Addr entry;
1064 Dwarf_Op *op;
1065 size_t nops;
1066 size_t offset = 0;
1067 Dwarf_Attribute attr;
1068 bool first = true;
1069 const char *name;
1070
Masami Hiramatsub61ffc92019-10-25 17:47:10 +09001071 ret = die_entrypc(sp_die, &entry);
He Kuang349e8d22015-05-11 09:25:03 +00001072 if (ret)
1073 return ret;
1074
1075 name = dwarf_diename(sp_die);
1076 if (!name)
1077 return -ENOENT;
1078
1079 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
1080 return -EINVAL;
1081
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +09001082 while ((offset = dwarf_getlocations(&attr, offset, &base,
1083 &start, &end, &op, &nops)) > 0) {
He Kuang349e8d22015-05-11 09:25:03 +00001084 if (start == 0) {
1085 /* Single Location Descriptions */
1086 ret = die_get_var_innermost_scope(sp_die, vr_die, buf);
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +09001087 goto out;
He Kuang349e8d22015-05-11 09:25:03 +00001088 }
1089
1090 /* Location Lists */
1091 start -= entry;
1092 end -= entry;
1093 if (first) {
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +09001094 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1095 name, start, end);
He Kuang349e8d22015-05-11 09:25:03 +00001096 first = false;
1097 } else {
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +09001098 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1099 start, end);
He Kuang349e8d22015-05-11 09:25:03 +00001100 }
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +09001101 if (ret < 0)
1102 goto out;
He Kuang349e8d22015-05-11 09:25:03 +00001103 }
1104
1105 if (!first)
Masami Hiramatsubf4d5f22016-05-10 14:47:07 +09001106 ret = strbuf_add(buf, "]>", 2);
1107out:
He Kuang349e8d22015-05-11 09:25:03 +00001108 return ret;
1109}
Arnaldo Carvalho de Melobd0419e2016-04-05 11:33:41 -03001110#else
1111int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
1112 Dwarf_Die *vr_die __maybe_unused,
1113 struct strbuf *buf __maybe_unused)
1114{
1115 return -ENOTSUP;
1116}
1117#endif
Ravi Bangoria6243b9d2016-08-30 14:09:37 +05301118
1119/*
1120 * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
1121 * @vr_die: a variable DIE
1122 */
1123static bool die_has_loclist(Dwarf_Die *vr_die)
1124{
1125 Dwarf_Attribute loc;
1126 int tag = dwarf_tag(vr_die);
1127
1128 if (tag != DW_TAG_formal_parameter &&
1129 tag != DW_TAG_variable)
1130 return false;
1131
1132 return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
1133 dwarf_whatform(&loc) == DW_FORM_sec_offset);
1134}
1135
1136/*
1137 * die_is_optimized_target - Check if target program is compiled with
1138 * optimization
1139 * @cu_die: a CU DIE
1140 *
1141 * For any object in given CU whose DW_AT_location is a location list,
1142 * target program is compiled with optimization. This is applicable to
1143 * clang as well.
1144 */
1145bool die_is_optimized_target(Dwarf_Die *cu_die)
1146{
1147 Dwarf_Die tmp_die;
1148
1149 if (die_has_loclist(cu_die))
1150 return true;
1151
1152 if (!dwarf_child(cu_die, &tmp_die) &&
1153 die_is_optimized_target(&tmp_die))
1154 return true;
1155
1156 if (!dwarf_siblingof(cu_die, &tmp_die) &&
1157 die_is_optimized_target(&tmp_die))
1158 return true;
1159
1160 return false;
1161}
1162
1163/*
1164 * die_search_idx - Search index of given line address
1165 * @lines: Line records of single CU
1166 * @nr_lines: Number of @lines
1167 * @addr: address we are looking for
1168 * @idx: index to be set by this function (return value)
1169 *
1170 * Search for @addr by looping over every lines of CU. If address
1171 * matches, set index of that line in @idx. Note that single source
1172 * line can have multiple line records. i.e. single source line can
1173 * have multiple index.
1174 */
1175static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
1176 Dwarf_Addr addr, unsigned long *idx)
1177{
1178 unsigned long i;
1179 Dwarf_Addr tmp;
1180
1181 for (i = 0; i < nr_lines; i++) {
1182 if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
1183 return false;
1184
1185 if (tmp == addr) {
1186 *idx = i;
1187 return true;
1188 }
1189 }
1190 return false;
1191}
1192
1193/*
1194 * die_get_postprologue_addr - Search next address after function prologue
1195 * @entrypc_idx: entrypc index
1196 * @lines: Line records of single CU
1197 * @nr_lines: Number of @lines
1198 * @hignpc: high PC address of function
1199 * @postprologue_addr: Next address after function prologue (return value)
1200 *
1201 * Look for prologue-end marker. If there is no explicit marker, return
1202 * address of next line record or next source line.
1203 */
1204static bool die_get_postprologue_addr(unsigned long entrypc_idx,
1205 Dwarf_Lines *lines,
1206 unsigned long nr_lines,
1207 Dwarf_Addr highpc,
1208 Dwarf_Addr *postprologue_addr)
1209{
1210 unsigned long i;
1211 int entrypc_lno, lno;
1212 Dwarf_Line *line;
1213 Dwarf_Addr addr;
1214 bool p_end;
1215
1216 /* entrypc_lno is actual source line number */
1217 line = dwarf_onesrcline(lines, entrypc_idx);
1218 if (dwarf_lineno(line, &entrypc_lno))
1219 return false;
1220
1221 for (i = entrypc_idx; i < nr_lines; i++) {
1222 line = dwarf_onesrcline(lines, i);
1223
1224 if (dwarf_lineaddr(line, &addr) ||
1225 dwarf_lineno(line, &lno) ||
1226 dwarf_lineprologueend(line, &p_end))
1227 return false;
1228
1229 /* highpc is exclusive. [entrypc,highpc) */
1230 if (addr >= highpc)
1231 break;
1232
1233 /* clang supports prologue-end marker */
1234 if (p_end)
1235 break;
1236
1237 /* Actual next line in source */
1238 if (lno != entrypc_lno)
1239 break;
1240
1241 /*
1242 * Single source line can have multiple line records.
1243 * For Example,
1244 * void foo() { printf("hello\n"); }
1245 * contains two line records. One points to declaration and
1246 * other points to printf() line. Variable 'lno' won't get
1247 * incremented in this case but 'i' will.
1248 */
1249 if (i != entrypc_idx)
1250 break;
1251 }
1252
1253 dwarf_lineaddr(line, postprologue_addr);
1254 if (*postprologue_addr >= highpc)
1255 dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
1256 postprologue_addr);
1257
1258 return true;
1259}
1260
1261/*
1262 * die_skip_prologue - Use next address after prologue as probe location
1263 * @sp_die: a subprogram DIE
1264 * @cu_die: a CU DIE
1265 * @entrypc: entrypc of the function
1266 *
1267 * Function prologue prepares stack and registers before executing function
1268 * logic. When target program is compiled without optimization, function
1269 * parameter information is only valid after prologue. When we probe entrypc
1270 * of the function, and try to record function parameter, it contains
1271 * garbage value.
1272 */
1273void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
1274 Dwarf_Addr *entrypc)
1275{
1276 size_t nr_lines = 0;
1277 unsigned long entrypc_idx = 0;
1278 Dwarf_Lines *lines = NULL;
1279 Dwarf_Addr postprologue_addr;
1280 Dwarf_Addr highpc;
1281
1282 if (dwarf_highpc(sp_die, &highpc))
1283 return;
1284
1285 if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
1286 return;
1287
1288 if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
1289 return;
1290
1291 if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
1292 highpc, &postprologue_addr))
1293 return;
1294
1295 *entrypc = postprologue_addr;
1296}