blob: ab34ef2c661f85c2362bd6cee83b0aaba56c4b8b [file] [log] [blame]
David Brazdil0f672f62019-12-10 10:32:29 +00001// SPDX-License-Identifier: GPL-2.0-or-later
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002/*
3 * dwarf-aux.c : libdw auxiliary interfaces
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004 */
5
6#include <errno.h>
7#include <inttypes.h>
8#include <stdbool.h>
David Brazdil0f672f62019-12-10 10:32:29 +00009#include <stdlib.h>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000010#include "debug.h"
11#include "dwarf-aux.h"
David Brazdil0f672f62019-12-10 10:32:29 +000012#include "strbuf.h"
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000013#include "string2.h"
14
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
89static 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
122/**
123 * 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/**
139 * 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;
148
149 name = dwarf_diename(dw_die);
150 return name ? (strcmp(tname, name) == 0) : false;
151}
152
153/**
154 * die_match_name - Match diename/linkage name and glob
155 * @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.
159 * This also match linkage name.
160 */
161bool die_match_name(Dwarf_Die *dw_die, const char *glob)
162{
163 const char *name;
164
165 name = dwarf_diename(dw_die);
166 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;
174}
175
176/**
177 * 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
264/* 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
277/**
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/**
296 * 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/**
Olivier Deprez0e641232021-09-23 10:07:05 +0200311 * die_entrypc - Returns entry PC (the lowest address) of a DIE
312 * @dw_die: a DIE
313 * @addr: where to store entry PC
314 *
315 * Since dwarf_entrypc() does not return entry PC if the DIE has only address
316 * range, we have to use this to retrieve the lowest address from the address
317 * range attribute.
318 */
319int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr)
320{
321 Dwarf_Addr base, end;
322 Dwarf_Attribute attr;
323
324 if (!addr)
325 return -EINVAL;
326
327 if (dwarf_entrypc(dw_die, addr) == 0)
328 return 0;
329
330 /*
331 * Since the dwarf_ranges() will return 0 if there is no
332 * DW_AT_ranges attribute, we should check it first.
333 */
334 if (!dwarf_attr(dw_die, DW_AT_ranges, &attr))
335 return -ENOENT;
336
337 return dwarf_ranges(dw_die, 0, &base, addr, &end) < 0 ? -ENOENT : 0;
338}
339
340/**
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000341 * die_is_func_instance - Ensure that this DIE is an instance of a subprogram
342 * @dw_die: a DIE
343 *
344 * Ensure that this DIE is an instance (which has an entry address).
Olivier Deprez0e641232021-09-23 10:07:05 +0200345 * This returns true if @dw_die is a function instance. If not, the @dw_die
346 * must be a prototype. You can use die_walk_instances() to find actual
347 * instances.
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000348 **/
349bool die_is_func_instance(Dwarf_Die *dw_die)
350{
351 Dwarf_Addr tmp;
Olivier Deprez0e641232021-09-23 10:07:05 +0200352 Dwarf_Attribute attr_mem;
353 int tag = dwarf_tag(dw_die);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000354
Olivier Deprez0e641232021-09-23 10:07:05 +0200355 if (tag != DW_TAG_subprogram &&
356 tag != DW_TAG_inlined_subroutine)
357 return false;
358
359 return dwarf_entrypc(dw_die, &tmp) == 0 ||
360 dwarf_attr(dw_die, DW_AT_ranges, &attr_mem) != NULL;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000361}
Olivier Deprez0e641232021-09-23 10:07:05 +0200362
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000363/**
364 * die_get_data_member_location - Get the data-member offset
365 * @mb_die: a DIE of a member of a data structure
366 * @offs: The offset of the member in the data structure
367 *
368 * Get the offset of @mb_die in the data structure including @mb_die, and
369 * stores result offset to @offs. If any error occurs this returns errno.
370 */
371int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
372{
373 Dwarf_Attribute attr;
374 Dwarf_Op *expr;
375 size_t nexpr;
376 int ret;
377
378 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
379 return -ENOENT;
380
381 if (dwarf_formudata(&attr, offs) != 0) {
382 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
383 ret = dwarf_getlocation(&attr, &expr, &nexpr);
384 if (ret < 0 || nexpr == 0)
385 return -ENOENT;
386
387 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
388 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
389 expr[0].atom, nexpr);
390 return -ENOTSUP;
391 }
392 *offs = (Dwarf_Word)expr[0].number;
393 }
394 return 0;
395}
396
397/* Get the call file index number in CU DIE */
398static int die_get_call_fileno(Dwarf_Die *in_die)
399{
400 Dwarf_Sword idx;
401
402 if (die_get_attr_sdata(in_die, DW_AT_call_file, &idx) == 0)
403 return (int)idx;
404 else
405 return -ENOENT;
406}
407
408/* Get the declared file index number in CU DIE */
409static int die_get_decl_fileno(Dwarf_Die *pdie)
410{
411 Dwarf_Sword idx;
412
413 if (die_get_attr_sdata(pdie, DW_AT_decl_file, &idx) == 0)
414 return (int)idx;
415 else
416 return -ENOENT;
417}
418
419/**
420 * die_get_call_file - Get callsite file name of inlined function instance
421 * @in_die: a DIE of an inlined function instance
422 *
423 * Get call-site file name of @in_die. This means from which file the inline
424 * function is called.
425 */
426const char *die_get_call_file(Dwarf_Die *in_die)
427{
428 Dwarf_Die cu_die;
429 Dwarf_Files *files;
430 int idx;
431
432 idx = die_get_call_fileno(in_die);
433 if (idx < 0 || !dwarf_diecu(in_die, &cu_die, NULL, NULL) ||
434 dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
435 return NULL;
436
437 return dwarf_filesrc(files, idx, NULL, NULL);
438}
439
440
441/**
442 * die_find_child - Generic DIE search function in DIE tree
443 * @rt_die: a root DIE
444 * @callback: a callback function
445 * @data: a user data passed to the callback function
446 * @die_mem: a buffer for result DIE
447 *
448 * Trace DIE tree from @rt_die and call @callback for each child DIE.
449 * If @callback returns DIE_FIND_CB_END, this stores the DIE into
450 * @die_mem and returns it. If @callback returns DIE_FIND_CB_CONTINUE,
451 * this continues to trace the tree. Optionally, @callback can return
452 * DIE_FIND_CB_CHILD and DIE_FIND_CB_SIBLING, those means trace only
453 * the children and trace only the siblings respectively.
454 * Returns NULL if @callback can't find any appropriate DIE.
455 */
456Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
457 int (*callback)(Dwarf_Die *, void *),
458 void *data, Dwarf_Die *die_mem)
459{
460 Dwarf_Die child_die;
461 int ret;
462
463 ret = dwarf_child(rt_die, die_mem);
464 if (ret != 0)
465 return NULL;
466
467 do {
468 ret = callback(die_mem, data);
469 if (ret == DIE_FIND_CB_END)
470 return die_mem;
471
472 if ((ret & DIE_FIND_CB_CHILD) &&
473 die_find_child(die_mem, callback, data, &child_die)) {
474 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
475 return die_mem;
476 }
477 } while ((ret & DIE_FIND_CB_SIBLING) &&
478 dwarf_siblingof(die_mem, die_mem) == 0);
479
480 return NULL;
481}
482
483struct __addr_die_search_param {
484 Dwarf_Addr addr;
485 Dwarf_Die *die_mem;
486};
487
488static int __die_search_func_tail_cb(Dwarf_Die *fn_die, void *data)
489{
490 struct __addr_die_search_param *ad = data;
491 Dwarf_Addr addr = 0;
492
493 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
494 !dwarf_highpc(fn_die, &addr) &&
495 addr == ad->addr) {
496 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
497 return DWARF_CB_ABORT;
498 }
499 return DWARF_CB_OK;
500}
501
502/**
503 * die_find_tailfunc - Search for a non-inlined function with tail call at
504 * given address
505 * @cu_die: a CU DIE which including @addr
506 * @addr: target address
507 * @die_mem: a buffer for result DIE
508 *
509 * Search for a non-inlined function DIE with tail call at @addr. Stores the
510 * DIE to @die_mem and returns it if found. Returns NULL if failed.
511 */
512Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
513 Dwarf_Die *die_mem)
514{
515 struct __addr_die_search_param ad;
516 ad.addr = addr;
517 ad.die_mem = die_mem;
518 /* dwarf_getscopes can't find subprogram. */
519 if (!dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0))
520 return NULL;
521 else
522 return die_mem;
523}
524
525/* die_find callback for non-inlined function search */
526static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
527{
528 struct __addr_die_search_param *ad = data;
529
530 /*
531 * Since a declaration entry doesn't has given pc, this always returns
532 * function definition entry.
533 */
534 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
535 dwarf_haspc(fn_die, ad->addr)) {
536 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
537 return DWARF_CB_ABORT;
538 }
539 return DWARF_CB_OK;
540}
541
542/**
543 * die_find_realfunc - Search a non-inlined function at given address
544 * @cu_die: a CU DIE which including @addr
545 * @addr: target address
546 * @die_mem: a buffer for result DIE
547 *
548 * Search a non-inlined function DIE which includes @addr. Stores the
549 * DIE to @die_mem and returns it if found. Returns NULL if failed.
550 */
551Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
552 Dwarf_Die *die_mem)
553{
554 struct __addr_die_search_param ad;
555 ad.addr = addr;
556 ad.die_mem = die_mem;
557 /* dwarf_getscopes can't find subprogram. */
558 if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
559 return NULL;
560 else
561 return die_mem;
562}
563
564/* die_find callback for inline function search */
565static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
566{
567 Dwarf_Addr *addr = data;
568
569 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
570 dwarf_haspc(die_mem, *addr))
571 return DIE_FIND_CB_END;
572
573 return DIE_FIND_CB_CONTINUE;
574}
575
576/**
577 * die_find_top_inlinefunc - Search the top inlined function at given address
578 * @sp_die: a subprogram DIE which including @addr
579 * @addr: target address
580 * @die_mem: a buffer for result DIE
581 *
582 * Search an inlined function DIE which includes @addr. Stores the
583 * DIE to @die_mem and returns it if found. Returns NULL if failed.
584 * Even if several inlined functions are expanded recursively, this
585 * doesn't trace it down, and returns the topmost one.
586 */
587Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
588 Dwarf_Die *die_mem)
589{
590 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
591}
592
593/**
594 * die_find_inlinefunc - Search an inlined function at given address
595 * @sp_die: a subprogram DIE which including @addr
596 * @addr: target address
597 * @die_mem: a buffer for result DIE
598 *
599 * Search an inlined function DIE which includes @addr. Stores the
600 * DIE to @die_mem and returns it if found. Returns NULL if failed.
601 * If several inlined functions are expanded recursively, this trace
602 * it down and returns deepest one.
603 */
604Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
605 Dwarf_Die *die_mem)
606{
607 Dwarf_Die tmp_die;
608
609 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
610 if (!sp_die)
611 return NULL;
612
613 /* Inlined function could be recursive. Trace it until fail */
614 while (sp_die) {
615 memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
616 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
617 &tmp_die);
618 }
619
620 return die_mem;
621}
622
623struct __instance_walk_param {
624 void *addr;
625 int (*callback)(Dwarf_Die *, void *);
626 void *data;
627 int retval;
628};
629
630static int __die_walk_instances_cb(Dwarf_Die *inst, void *data)
631{
632 struct __instance_walk_param *iwp = data;
633 Dwarf_Attribute attr_mem;
634 Dwarf_Die origin_mem;
635 Dwarf_Attribute *attr;
636 Dwarf_Die *origin;
637 int tmp;
638
Olivier Deprez0e641232021-09-23 10:07:05 +0200639 if (!die_is_func_instance(inst))
640 return DIE_FIND_CB_CONTINUE;
641
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000642 attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem);
643 if (attr == NULL)
644 return DIE_FIND_CB_CONTINUE;
645
646 origin = dwarf_formref_die(attr, &origin_mem);
647 if (origin == NULL || origin->addr != iwp->addr)
648 return DIE_FIND_CB_CONTINUE;
649
650 /* Ignore redundant instances */
651 if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) {
652 dwarf_decl_line(origin, &tmp);
653 if (die_get_call_lineno(inst) == tmp) {
654 tmp = die_get_decl_fileno(origin);
655 if (die_get_call_fileno(inst) == tmp)
656 return DIE_FIND_CB_CONTINUE;
657 }
658 }
659
660 iwp->retval = iwp->callback(inst, iwp->data);
661
662 return (iwp->retval) ? DIE_FIND_CB_END : DIE_FIND_CB_CONTINUE;
663}
664
665/**
666 * die_walk_instances - Walk on instances of given DIE
667 * @or_die: an abstract original DIE
668 * @callback: a callback function which is called with instance DIE
669 * @data: user data
670 *
671 * Walk on the instances of give @in_die. @in_die must be an inlined function
672 * declartion. This returns the return value of @callback if it returns
673 * non-zero value, or -ENOENT if there is no instance.
674 */
675int die_walk_instances(Dwarf_Die *or_die, int (*callback)(Dwarf_Die *, void *),
676 void *data)
677{
678 Dwarf_Die cu_die;
679 Dwarf_Die die_mem;
680 struct __instance_walk_param iwp = {
681 .addr = or_die->addr,
682 .callback = callback,
683 .data = data,
684 .retval = -ENOENT,
685 };
686
687 if (dwarf_diecu(or_die, &cu_die, NULL, NULL) == NULL)
688 return -ENOENT;
689
690 die_find_child(&cu_die, __die_walk_instances_cb, &iwp, &die_mem);
691
692 return iwp.retval;
693}
694
695/* Line walker internal parameters */
696struct __line_walk_param {
697 bool recursive;
698 line_walk_callback_t callback;
699 void *data;
700 int retval;
701};
702
703static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
704{
705 struct __line_walk_param *lw = data;
706 Dwarf_Addr addr = 0;
707 const char *fname;
708 int lineno;
709
710 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
711 fname = die_get_call_file(in_die);
712 lineno = die_get_call_lineno(in_die);
Olivier Deprez0e641232021-09-23 10:07:05 +0200713 if (fname && lineno > 0 && die_entrypc(in_die, &addr) == 0) {
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000714 lw->retval = lw->callback(fname, lineno, addr, lw->data);
715 if (lw->retval != 0)
716 return DIE_FIND_CB_END;
717 }
Olivier Deprez0e641232021-09-23 10:07:05 +0200718 if (!lw->recursive)
719 return DIE_FIND_CB_SIBLING;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000720 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000721
722 if (addr) {
723 fname = dwarf_decl_file(in_die);
724 if (fname && dwarf_decl_line(in_die, &lineno) == 0) {
725 lw->retval = lw->callback(fname, lineno, addr, lw->data);
726 if (lw->retval != 0)
727 return DIE_FIND_CB_END;
728 }
729 }
730
731 /* Continue to search nested inlined function call-sites */
732 return DIE_FIND_CB_CONTINUE;
733}
734
735/* Walk on lines of blocks included in given DIE */
736static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive,
737 line_walk_callback_t callback, void *data)
738{
739 struct __line_walk_param lw = {
740 .recursive = recursive,
741 .callback = callback,
742 .data = data,
743 .retval = 0,
744 };
745 Dwarf_Die die_mem;
746 Dwarf_Addr addr;
747 const char *fname;
748 int lineno;
749
750 /* Handle function declaration line */
751 fname = dwarf_decl_file(sp_die);
752 if (fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
Olivier Deprez0e641232021-09-23 10:07:05 +0200753 die_entrypc(sp_die, &addr) == 0) {
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000754 lw.retval = callback(fname, lineno, addr, data);
755 if (lw.retval != 0)
756 goto done;
757 }
758 die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
759done:
760 return lw.retval;
761}
762
763static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
764{
765 struct __line_walk_param *lw = data;
766
Olivier Deprez0e641232021-09-23 10:07:05 +0200767 /*
768 * Since inlined function can include another inlined function in
769 * the same file, we need to walk in it recursively.
770 */
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000771 lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data);
772 if (lw->retval != 0)
773 return DWARF_CB_ABORT;
774
775 return DWARF_CB_OK;
776}
777
778/**
779 * die_walk_lines - Walk on lines inside given DIE
780 * @rt_die: a root DIE (CU, subprogram or inlined_subroutine)
781 * @callback: callback routine
782 * @data: user data
783 *
784 * Walk on all lines inside given @rt_die and call @callback on each line.
785 * If the @rt_die is a function, walk only on the lines inside the function,
786 * otherwise @rt_die must be a CU DIE.
787 * Note that this walks not only dwarf line list, but also function entries
788 * and inline call-site.
789 */
790int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
791{
792 Dwarf_Lines *lines;
793 Dwarf_Line *line;
794 Dwarf_Addr addr;
Olivier Deprez0e641232021-09-23 10:07:05 +0200795 const char *fname, *decf = NULL, *inf = NULL;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000796 int lineno, ret = 0;
797 int decl = 0, inl;
798 Dwarf_Die die_mem, *cu_die;
799 size_t nlines, i;
Olivier Deprez0e641232021-09-23 10:07:05 +0200800 bool flag;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000801
802 /* Get the CU die */
803 if (dwarf_tag(rt_die) != DW_TAG_compile_unit) {
804 cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
805 dwarf_decl_line(rt_die, &decl);
806 decf = dwarf_decl_file(rt_die);
807 } else
808 cu_die = rt_die;
809 if (!cu_die) {
810 pr_debug2("Failed to get CU from given DIE.\n");
811 return -EINVAL;
812 }
813
814 /* Get lines list in the CU */
815 if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
816 pr_debug2("Failed to get source lines on this CU.\n");
817 return -ENOENT;
818 }
819 pr_debug2("Get %zd lines from this CU\n", nlines);
820
821 /* Walk on the lines on lines list */
822 for (i = 0; i < nlines; i++) {
823 line = dwarf_onesrcline(lines, i);
824 if (line == NULL ||
825 dwarf_lineno(line, &lineno) != 0 ||
826 dwarf_lineaddr(line, &addr) != 0) {
827 pr_debug2("Failed to get line info. "
828 "Possible error in debuginfo.\n");
829 continue;
830 }
Olivier Deprez0e641232021-09-23 10:07:05 +0200831 /* Skip end-of-sequence */
832 if (dwarf_lineendsequence(line, &flag) != 0 || flag)
833 continue;
834 /* Skip Non statement line-info */
835 if (dwarf_linebeginstatement(line, &flag) != 0 || !flag)
836 continue;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000837 /* Filter lines based on address */
838 if (rt_die != cu_die) {
839 /*
840 * Address filtering
841 * The line is included in given function, and
842 * no inline block includes it.
843 */
844 if (!dwarf_haspc(rt_die, addr))
845 continue;
Olivier Deprez0e641232021-09-23 10:07:05 +0200846
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000847 if (die_find_inlinefunc(rt_die, addr, &die_mem)) {
Olivier Deprez0e641232021-09-23 10:07:05 +0200848 /* Call-site check */
849 inf = die_get_call_file(&die_mem);
850 if ((inf && !strcmp(inf, decf)) &&
851 die_get_call_lineno(&die_mem) == lineno)
852 goto found;
853
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000854 dwarf_decl_line(&die_mem, &inl);
855 if (inl != decl ||
856 decf != dwarf_decl_file(&die_mem))
857 continue;
858 }
859 }
Olivier Deprez0e641232021-09-23 10:07:05 +0200860found:
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000861 /* Get source line */
862 fname = dwarf_linesrc(line, NULL, NULL);
863
864 ret = callback(fname, lineno, addr, data);
865 if (ret != 0)
866 return ret;
867 }
868
869 /*
870 * Dwarf lines doesn't include function declarations and inlined
871 * subroutines. We have to check functions list or given function.
872 */
873 if (rt_die != cu_die)
874 /*
Olivier Deprez0e641232021-09-23 10:07:05 +0200875 * Don't need walk inlined functions recursively, because
876 * inner inlined functions don't have the lines of the
877 * specified function.
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000878 */
879 ret = __die_walk_funclines(rt_die, false, callback, data);
880 else {
881 struct __line_walk_param param = {
882 .callback = callback,
883 .data = data,
884 .retval = 0,
885 };
886 dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
887 ret = param.retval;
888 }
889
890 return ret;
891}
892
893struct __find_variable_param {
894 const char *name;
895 Dwarf_Addr addr;
896};
897
898static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
899{
900 struct __find_variable_param *fvp = data;
901 Dwarf_Attribute attr;
902 int tag;
903
904 tag = dwarf_tag(die_mem);
905 if ((tag == DW_TAG_formal_parameter ||
906 tag == DW_TAG_variable) &&
907 die_compare_name(die_mem, fvp->name) &&
908 /* Does the DIE have location information or external instance? */
909 (dwarf_attr(die_mem, DW_AT_external, &attr) ||
910 dwarf_attr(die_mem, DW_AT_location, &attr)))
911 return DIE_FIND_CB_END;
912 if (dwarf_haspc(die_mem, fvp->addr))
913 return DIE_FIND_CB_CONTINUE;
914 else
915 return DIE_FIND_CB_SIBLING;
916}
917
918/**
919 * die_find_variable_at - Find a given name variable at given address
920 * @sp_die: a function DIE
921 * @name: variable name
922 * @addr: address
923 * @die_mem: a buffer for result DIE
924 *
925 * Find a variable DIE called @name at @addr in @sp_die.
926 */
927Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
928 Dwarf_Addr addr, Dwarf_Die *die_mem)
929{
930 struct __find_variable_param fvp = { .name = name, .addr = addr};
931
932 return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
933 die_mem);
934}
935
936static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
937{
938 const char *name = data;
939
940 if (dwarf_tag(die_mem) == DW_TAG_member) {
941 if (die_compare_name(die_mem, name))
942 return DIE_FIND_CB_END;
943 else if (!dwarf_diename(die_mem)) { /* Unnamed structure */
944 Dwarf_Die type_die, tmp_die;
945 if (die_get_type(die_mem, &type_die) &&
946 die_find_member(&type_die, name, &tmp_die))
947 return DIE_FIND_CB_END;
948 }
949 }
950 return DIE_FIND_CB_SIBLING;
951}
952
953/**
954 * die_find_member - Find a given name member in a data structure
955 * @st_die: a data structure type DIE
956 * @name: member name
957 * @die_mem: a buffer for result DIE
958 *
959 * Find a member DIE called @name in @st_die.
960 */
961Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
962 Dwarf_Die *die_mem)
963{
964 return die_find_child(st_die, __die_find_member_cb, (void *)name,
965 die_mem);
966}
967
968/**
969 * die_get_typename - Get the name of given variable DIE
970 * @vr_die: a variable DIE
971 * @buf: a strbuf for result type name
972 *
973 * Get the name of @vr_die and stores it to @buf. Return 0 if succeeded.
974 * and Return -ENOENT if failed to find type name.
975 * Note that the result will stores typedef name if possible, and stores
976 * "*(function_type)" if the type is a function pointer.
977 */
978int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
979{
980 Dwarf_Die type;
981 int tag, ret;
982 const char *tmp = "";
983
984 if (__die_get_real_type(vr_die, &type) == NULL)
985 return -ENOENT;
986
987 tag = dwarf_tag(&type);
988 if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
989 tmp = "*";
990 else if (tag == DW_TAG_subroutine_type) {
991 /* Function pointer */
992 return strbuf_add(buf, "(function_type)", 15);
993 } else {
994 if (!dwarf_diename(&type))
995 return -ENOENT;
996 if (tag == DW_TAG_union_type)
997 tmp = "union ";
998 else if (tag == DW_TAG_structure_type)
999 tmp = "struct ";
1000 else if (tag == DW_TAG_enumeration_type)
1001 tmp = "enum ";
1002 /* Write a base name */
1003 return strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type));
1004 }
1005 ret = die_get_typename(&type, buf);
1006 return ret ? ret : strbuf_addstr(buf, tmp);
1007}
1008
1009/**
1010 * die_get_varname - Get the name and type of given variable DIE
1011 * @vr_die: a variable DIE
1012 * @buf: a strbuf for type and variable name
1013 *
1014 * Get the name and type of @vr_die and stores it in @buf as "type\tname".
1015 */
1016int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
1017{
1018 int ret;
1019
1020 ret = die_get_typename(vr_die, buf);
1021 if (ret < 0) {
1022 pr_debug("Failed to get type, make it unknown.\n");
1023 ret = strbuf_add(buf, " (unknown_type)", 14);
1024 }
1025
1026 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
1027}
1028
1029#ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT
1030/**
1031 * die_get_var_innermost_scope - Get innermost scope range of given variable DIE
1032 * @sp_die: a subprogram DIE
1033 * @vr_die: a variable DIE
1034 * @buf: a strbuf for variable byte offset range
1035 *
1036 * Get the innermost scope range of @vr_die and stores it in @buf as
1037 * "@<function_name+[NN-NN,NN-NN]>".
1038 */
1039static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die,
1040 struct strbuf *buf)
1041{
1042 Dwarf_Die *scopes;
1043 int count;
1044 size_t offset = 0;
1045 Dwarf_Addr base;
1046 Dwarf_Addr start, end;
1047 Dwarf_Addr entry;
1048 int ret;
1049 bool first = true;
1050 const char *name;
1051
Olivier Deprez0e641232021-09-23 10:07:05 +02001052 ret = die_entrypc(sp_die, &entry);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001053 if (ret)
1054 return ret;
1055
1056 name = dwarf_diename(sp_die);
1057 if (!name)
1058 return -ENOENT;
1059
1060 count = dwarf_getscopes_die(vr_die, &scopes);
1061
1062 /* (*SCOPES)[1] is the DIE for the scope containing that scope */
1063 if (count <= 1) {
1064 ret = -EINVAL;
1065 goto out;
1066 }
1067
1068 while ((offset = dwarf_ranges(&scopes[1], offset, &base,
1069 &start, &end)) > 0) {
1070 start -= entry;
1071 end -= entry;
1072
1073 if (first) {
1074 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1075 name, start, end);
1076 first = false;
1077 } else {
1078 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1079 start, end);
1080 }
1081 if (ret < 0)
1082 goto out;
1083 }
1084
1085 if (!first)
1086 ret = strbuf_add(buf, "]>", 2);
1087
1088out:
1089 free(scopes);
1090 return ret;
1091}
1092
1093/**
1094 * die_get_var_range - Get byte offset range of given variable DIE
1095 * @sp_die: a subprogram DIE
1096 * @vr_die: a variable DIE
1097 * @buf: a strbuf for type and variable name and byte offset range
1098 *
1099 * Get the byte offset range of @vr_die and stores it in @buf as
1100 * "@<function_name+[NN-NN,NN-NN]>".
1101 */
1102int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf)
1103{
1104 int ret = 0;
1105 Dwarf_Addr base;
1106 Dwarf_Addr start, end;
1107 Dwarf_Addr entry;
1108 Dwarf_Op *op;
1109 size_t nops;
1110 size_t offset = 0;
1111 Dwarf_Attribute attr;
1112 bool first = true;
1113 const char *name;
1114
Olivier Deprez0e641232021-09-23 10:07:05 +02001115 ret = die_entrypc(sp_die, &entry);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001116 if (ret)
1117 return ret;
1118
1119 name = dwarf_diename(sp_die);
1120 if (!name)
1121 return -ENOENT;
1122
1123 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
1124 return -EINVAL;
1125
1126 while ((offset = dwarf_getlocations(&attr, offset, &base,
1127 &start, &end, &op, &nops)) > 0) {
1128 if (start == 0) {
1129 /* Single Location Descriptions */
1130 ret = die_get_var_innermost_scope(sp_die, vr_die, buf);
1131 goto out;
1132 }
1133
1134 /* Location Lists */
1135 start -= entry;
1136 end -= entry;
1137 if (first) {
1138 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1139 name, start, end);
1140 first = false;
1141 } else {
1142 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1143 start, end);
1144 }
1145 if (ret < 0)
1146 goto out;
1147 }
1148
1149 if (!first)
1150 ret = strbuf_add(buf, "]>", 2);
1151out:
1152 return ret;
1153}
1154#else
1155int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
1156 Dwarf_Die *vr_die __maybe_unused,
1157 struct strbuf *buf __maybe_unused)
1158{
1159 return -ENOTSUP;
1160}
1161#endif
1162
1163/*
1164 * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
1165 * @vr_die: a variable DIE
1166 */
1167static bool die_has_loclist(Dwarf_Die *vr_die)
1168{
1169 Dwarf_Attribute loc;
1170 int tag = dwarf_tag(vr_die);
1171
1172 if (tag != DW_TAG_formal_parameter &&
1173 tag != DW_TAG_variable)
1174 return false;
1175
1176 return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
1177 dwarf_whatform(&loc) == DW_FORM_sec_offset);
1178}
1179
1180/*
1181 * die_is_optimized_target - Check if target program is compiled with
1182 * optimization
1183 * @cu_die: a CU DIE
1184 *
1185 * For any object in given CU whose DW_AT_location is a location list,
1186 * target program is compiled with optimization. This is applicable to
1187 * clang as well.
1188 */
1189bool die_is_optimized_target(Dwarf_Die *cu_die)
1190{
1191 Dwarf_Die tmp_die;
1192
1193 if (die_has_loclist(cu_die))
1194 return true;
1195
1196 if (!dwarf_child(cu_die, &tmp_die) &&
1197 die_is_optimized_target(&tmp_die))
1198 return true;
1199
1200 if (!dwarf_siblingof(cu_die, &tmp_die) &&
1201 die_is_optimized_target(&tmp_die))
1202 return true;
1203
1204 return false;
1205}
1206
1207/*
1208 * die_search_idx - Search index of given line address
1209 * @lines: Line records of single CU
1210 * @nr_lines: Number of @lines
1211 * @addr: address we are looking for
1212 * @idx: index to be set by this function (return value)
1213 *
1214 * Search for @addr by looping over every lines of CU. If address
1215 * matches, set index of that line in @idx. Note that single source
1216 * line can have multiple line records. i.e. single source line can
1217 * have multiple index.
1218 */
1219static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
1220 Dwarf_Addr addr, unsigned long *idx)
1221{
1222 unsigned long i;
1223 Dwarf_Addr tmp;
1224
1225 for (i = 0; i < nr_lines; i++) {
1226 if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
1227 return false;
1228
1229 if (tmp == addr) {
1230 *idx = i;
1231 return true;
1232 }
1233 }
1234 return false;
1235}
1236
1237/*
1238 * die_get_postprologue_addr - Search next address after function prologue
1239 * @entrypc_idx: entrypc index
1240 * @lines: Line records of single CU
1241 * @nr_lines: Number of @lines
1242 * @hignpc: high PC address of function
1243 * @postprologue_addr: Next address after function prologue (return value)
1244 *
1245 * Look for prologue-end marker. If there is no explicit marker, return
1246 * address of next line record or next source line.
1247 */
1248static bool die_get_postprologue_addr(unsigned long entrypc_idx,
1249 Dwarf_Lines *lines,
1250 unsigned long nr_lines,
1251 Dwarf_Addr highpc,
1252 Dwarf_Addr *postprologue_addr)
1253{
1254 unsigned long i;
1255 int entrypc_lno, lno;
1256 Dwarf_Line *line;
1257 Dwarf_Addr addr;
1258 bool p_end;
1259
1260 /* entrypc_lno is actual source line number */
1261 line = dwarf_onesrcline(lines, entrypc_idx);
1262 if (dwarf_lineno(line, &entrypc_lno))
1263 return false;
1264
1265 for (i = entrypc_idx; i < nr_lines; i++) {
1266 line = dwarf_onesrcline(lines, i);
1267
1268 if (dwarf_lineaddr(line, &addr) ||
1269 dwarf_lineno(line, &lno) ||
1270 dwarf_lineprologueend(line, &p_end))
1271 return false;
1272
1273 /* highpc is exclusive. [entrypc,highpc) */
1274 if (addr >= highpc)
1275 break;
1276
1277 /* clang supports prologue-end marker */
1278 if (p_end)
1279 break;
1280
1281 /* Actual next line in source */
1282 if (lno != entrypc_lno)
1283 break;
1284
1285 /*
1286 * Single source line can have multiple line records.
1287 * For Example,
1288 * void foo() { printf("hello\n"); }
1289 * contains two line records. One points to declaration and
1290 * other points to printf() line. Variable 'lno' won't get
1291 * incremented in this case but 'i' will.
1292 */
1293 if (i != entrypc_idx)
1294 break;
1295 }
1296
1297 dwarf_lineaddr(line, postprologue_addr);
1298 if (*postprologue_addr >= highpc)
1299 dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
1300 postprologue_addr);
1301
1302 return true;
1303}
1304
1305/*
1306 * die_skip_prologue - Use next address after prologue as probe location
1307 * @sp_die: a subprogram DIE
1308 * @cu_die: a CU DIE
1309 * @entrypc: entrypc of the function
1310 *
1311 * Function prologue prepares stack and registers before executing function
1312 * logic. When target program is compiled without optimization, function
1313 * parameter information is only valid after prologue. When we probe entrypc
1314 * of the function, and try to record function parameter, it contains
1315 * garbage value.
1316 */
1317void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
1318 Dwarf_Addr *entrypc)
1319{
1320 size_t nr_lines = 0;
1321 unsigned long entrypc_idx = 0;
1322 Dwarf_Lines *lines = NULL;
1323 Dwarf_Addr postprologue_addr;
1324 Dwarf_Addr highpc;
1325
1326 if (dwarf_highpc(sp_die, &highpc))
1327 return;
1328
1329 if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
1330 return;
1331
1332 if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
1333 return;
1334
1335 if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
1336 highpc, &postprologue_addr))
1337 return;
1338
1339 *entrypc = postprologue_addr;
1340}