~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/util/dwarf-aux.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * dwarf-aux.c : libdw auxiliary interfaces
  4  */
  5 
  6 #include <errno.h>
  7 #include <inttypes.h>
  8 #include <stdbool.h>
  9 #include <stdlib.h>
 10 #include "debug.h"
 11 #include "dwarf-aux.h"
 12 #include "dwarf-regs.h"
 13 #include "strbuf.h"
 14 #include "string2.h"
 15 
 16 /**
 17  * cu_find_realpath - Find the realpath of the target file
 18  * @cu_die: A DIE(dwarf information entry) of CU(compilation Unit)
 19  * @fname:  The tail filename of the target file
 20  *
 21  * Find the real(long) path of @fname in @cu_die.
 22  */
 23 const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
 24 {
 25         Dwarf_Files *files;
 26         size_t nfiles, i;
 27         const char *src = NULL;
 28         int ret;
 29 
 30         if (!fname)
 31                 return NULL;
 32 
 33         ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
 34         if (ret != 0)
 35                 return NULL;
 36 
 37         for (i = 0; i < nfiles; i++) {
 38                 src = dwarf_filesrc(files, i, NULL, NULL);
 39                 if (strtailcmp(src, fname) == 0)
 40                         break;
 41         }
 42         if (i == nfiles)
 43                 return NULL;
 44         return src;
 45 }
 46 
 47 /**
 48  * cu_get_comp_dir - Get the path of compilation directory
 49  * @cu_die: a CU DIE
 50  *
 51  * Get the path of compilation directory of given @cu_die.
 52  * Since this depends on DW_AT_comp_dir, older gcc will not
 53  * embedded it. In that case, this returns NULL.
 54  */
 55 const char *cu_get_comp_dir(Dwarf_Die *cu_die)
 56 {
 57         Dwarf_Attribute attr;
 58         if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
 59                 return NULL;
 60         return dwarf_formstring(&attr);
 61 }
 62 
 63 /* Unlike dwarf_getsrc_die(), cu_getsrc_die() only returns statement line */
 64 static Dwarf_Line *cu_getsrc_die(Dwarf_Die *cu_die, Dwarf_Addr addr)
 65 {
 66         Dwarf_Addr laddr;
 67         Dwarf_Lines *lines;
 68         Dwarf_Line *line;
 69         size_t nlines, l, u, n;
 70         bool flag;
 71 
 72         if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0 ||
 73             nlines == 0)
 74                 return NULL;
 75 
 76         /* Lines are sorted by address, use binary search */
 77         l = 0; u = nlines - 1;
 78         while (l < u) {
 79                 n = u - (u - l) / 2;
 80                 line = dwarf_onesrcline(lines, n);
 81                 if (!line || dwarf_lineaddr(line, &laddr) != 0)
 82                         return NULL;
 83                 if (addr < laddr)
 84                         u = n - 1;
 85                 else
 86                         l = n;
 87         }
 88         /* Going backward to find the lowest line */
 89         do {
 90                 line = dwarf_onesrcline(lines, --l);
 91                 if (!line || dwarf_lineaddr(line, &laddr) != 0)
 92                         return NULL;
 93         } while (laddr == addr);
 94         l++;
 95         /* Going forward to find the statement line */
 96         do {
 97                 line = dwarf_onesrcline(lines, l++);
 98                 if (!line || dwarf_lineaddr(line, &laddr) != 0 ||
 99                     dwarf_linebeginstatement(line, &flag) != 0)
100                         return NULL;
101                 if (laddr > addr)
102                         return NULL;
103         } while (!flag);
104 
105         return line;
106 }
107 
108 /**
109  * cu_find_lineinfo - Get a line number and file name for given address
110  * @cu_die: a CU DIE
111  * @addr: An address
112  * @fname: a pointer which returns the file name string
113  * @lineno: a pointer which returns the line number
114  *
115  * Find a line number and file name for @addr in @cu_die.
116  */
117 int cu_find_lineinfo(Dwarf_Die *cu_die, Dwarf_Addr addr,
118                      const char **fname, int *lineno)
119 {
120         Dwarf_Line *line;
121         Dwarf_Die die_mem;
122         Dwarf_Addr faddr;
123 
124         if (die_find_realfunc(cu_die, addr, &die_mem)
125             && die_entrypc(&die_mem, &faddr) == 0 &&
126             faddr == addr) {
127                 *fname = die_get_decl_file(&die_mem);
128                 dwarf_decl_line(&die_mem, lineno);
129                 goto out;
130         }
131 
132         line = cu_getsrc_die(cu_die, addr);
133         if (line && dwarf_lineno(line, lineno) == 0) {
134                 *fname = dwarf_linesrc(line, NULL, NULL);
135                 if (!*fname)
136                         /* line number is useless without filename */
137                         *lineno = 0;
138         }
139 
140 out:
141         return (*lineno && *fname) ? *lineno : -ENOENT;
142 }
143 
144 static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data);
145 
146 /**
147  * cu_walk_functions_at - Walk on function DIEs at given address
148  * @cu_die: A CU DIE
149  * @addr: An address
150  * @callback: A callback which called with found DIEs
151  * @data: A user data
152  *
153  * Walk on function DIEs at given @addr in @cu_die. Passed DIEs
154  * should be subprogram or inlined-subroutines.
155  */
156 int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
157                     int (*callback)(Dwarf_Die *, void *), void *data)
158 {
159         Dwarf_Die die_mem;
160         Dwarf_Die *sc_die;
161         int ret = -ENOENT;
162 
163         /* Inlined function could be recursive. Trace it until fail */
164         for (sc_die = die_find_realfunc(cu_die, addr, &die_mem);
165              sc_die != NULL;
166              sc_die = die_find_child(sc_die, __die_find_inline_cb, &addr,
167                                      &die_mem)) {
168                 ret = callback(sc_die, data);
169                 if (ret)
170                         break;
171         }
172 
173         return ret;
174 
175 }
176 
177 /**
178  * die_get_linkage_name - Get the linkage name of the object
179  * @dw_die: A DIE of the object
180  *
181  * Get the linkage name attribute of given @dw_die.
182  * For C++ binary, the linkage name will be the mangled symbol.
183  */
184 const char *die_get_linkage_name(Dwarf_Die *dw_die)
185 {
186         Dwarf_Attribute attr;
187 
188         if (dwarf_attr_integrate(dw_die, DW_AT_linkage_name, &attr) == NULL)
189                 return NULL;
190         return dwarf_formstring(&attr);
191 }
192 
193 /**
194  * die_compare_name - Compare diename and tname
195  * @dw_die: a DIE
196  * @tname: a string of target name
197  *
198  * Compare the name of @dw_die and @tname. Return false if @dw_die has no name.
199  */
200 bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
201 {
202         const char *name;
203 
204         name = dwarf_diename(dw_die);
205         return name ? (strcmp(tname, name) == 0) : false;
206 }
207 
208 /**
209  * die_match_name - Match diename/linkage name and glob
210  * @dw_die: a DIE
211  * @glob: a string of target glob pattern
212  *
213  * Glob matching the name of @dw_die and @glob. Return false if matching fail.
214  * This also match linkage name.
215  */
216 bool die_match_name(Dwarf_Die *dw_die, const char *glob)
217 {
218         const char *name;
219 
220         name = dwarf_diename(dw_die);
221         if (name && strglobmatch(name, glob))
222                 return true;
223         /* fall back to check linkage name */
224         name = die_get_linkage_name(dw_die);
225         if (name && strglobmatch(name, glob))
226                 return true;
227 
228         return false;
229 }
230 
231 /**
232  * die_get_call_lineno - Get callsite line number of inline-function instance
233  * @in_die: a DIE of an inlined function instance
234  *
235  * Get call-site line number of @in_die. This means from where the inline
236  * function is called.
237  */
238 int die_get_call_lineno(Dwarf_Die *in_die)
239 {
240         Dwarf_Attribute attr;
241         Dwarf_Word ret;
242 
243         if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
244                 return -ENOENT;
245 
246         dwarf_formudata(&attr, &ret);
247         return (int)ret;
248 }
249 
250 /**
251  * die_get_type - Get type DIE
252  * @vr_die: a DIE of a variable
253  * @die_mem: where to store a type DIE
254  *
255  * Get a DIE of the type of given variable (@vr_die), and store
256  * it to die_mem. Return NULL if fails to get a type DIE.
257  */
258 Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
259 {
260         Dwarf_Attribute attr;
261 
262         if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
263             dwarf_formref_die(&attr, die_mem))
264                 return die_mem;
265         else
266                 return NULL;
267 }
268 
269 /* Get a type die, but skip qualifiers */
270 static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
271 {
272         int tag;
273 
274         do {
275                 vr_die = die_get_type(vr_die, die_mem);
276                 if (!vr_die)
277                         break;
278                 tag = dwarf_tag(vr_die);
279         } while (tag == DW_TAG_const_type ||
280                  tag == DW_TAG_restrict_type ||
281                  tag == DW_TAG_volatile_type ||
282                  tag == DW_TAG_shared_type);
283 
284         return vr_die;
285 }
286 
287 /**
288  * die_get_real_type - Get a type die, but skip qualifiers and typedef
289  * @vr_die: a DIE of a variable
290  * @die_mem: where to store a type DIE
291  *
292  * Get a DIE of the type of given variable (@vr_die), and store
293  * it to die_mem. Return NULL if fails to get a type DIE.
294  * If the type is qualifiers (e.g. const) or typedef, this skips it
295  * and tries to find real type (structure or basic types, e.g. int).
296  */
297 Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
298 {
299         do {
300                 vr_die = __die_get_real_type(vr_die, die_mem);
301         } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
302 
303         return vr_die;
304 }
305 
306 /* Get attribute and translate it as a udata */
307 static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
308                               Dwarf_Word *result)
309 {
310         Dwarf_Attribute attr;
311 
312         if (dwarf_attr_integrate(tp_die, attr_name, &attr) == NULL ||
313             dwarf_formudata(&attr, result) != 0)
314                 return -ENOENT;
315 
316         return 0;
317 }
318 
319 /**
320  * die_is_signed_type - Check whether a type DIE is signed or not
321  * @tp_die: a DIE of a type
322  *
323  * Get the encoding of @tp_die and return true if the encoding
324  * is signed.
325  */
326 bool die_is_signed_type(Dwarf_Die *tp_die)
327 {
328         Dwarf_Word ret;
329 
330         if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
331                 return false;
332 
333         return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
334                 ret == DW_ATE_signed_fixed);
335 }
336 
337 /**
338  * die_is_func_def - Ensure that this DIE is a subprogram and definition
339  * @dw_die: a DIE
340  *
341  * Ensure that this DIE is a subprogram and NOT a declaration. This
342  * returns true if @dw_die is a function definition.
343  **/
344 bool die_is_func_def(Dwarf_Die *dw_die)
345 {
346         Dwarf_Attribute attr;
347         Dwarf_Addr addr = 0;
348 
349         if (dwarf_tag(dw_die) != DW_TAG_subprogram)
350                 return false;
351 
352         if (dwarf_attr(dw_die, DW_AT_declaration, &attr))
353                 return false;
354 
355         /*
356          * DW_AT_declaration can be lost from function declaration
357          * by gcc's bug #97060.
358          * So we need to check this subprogram DIE has DW_AT_inline
359          * or an entry address.
360          */
361         if (!dwarf_attr(dw_die, DW_AT_inline, &attr) &&
362             die_entrypc(dw_die, &addr) < 0)
363                 return false;
364 
365         return true;
366 }
367 
368 /**
369  * die_entrypc - Returns entry PC (the lowest address) of a DIE
370  * @dw_die: a DIE
371  * @addr: where to store entry PC
372  *
373  * Since dwarf_entrypc() does not return entry PC if the DIE has only address
374  * range, we have to use this to retrieve the lowest address from the address
375  * range attribute.
376  */
377 int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr)
378 {
379         Dwarf_Addr base, end;
380         Dwarf_Attribute attr;
381 
382         if (!addr)
383                 return -EINVAL;
384 
385         if (dwarf_entrypc(dw_die, addr) == 0)
386                 return 0;
387 
388         /*
389          *  Since the dwarf_ranges() will return 0 if there is no
390          * DW_AT_ranges attribute, we should check it first.
391          */
392         if (!dwarf_attr(dw_die, DW_AT_ranges, &attr))
393                 return -ENOENT;
394 
395         return dwarf_ranges(dw_die, 0, &base, addr, &end) < 0 ? -ENOENT : 0;
396 }
397 
398 /**
399  * die_is_func_instance - Ensure that this DIE is an instance of a subprogram
400  * @dw_die: a DIE
401  *
402  * Ensure that this DIE is an instance (which has an entry address).
403  * This returns true if @dw_die is a function instance. If not, the @dw_die
404  * must be a prototype. You can use die_walk_instances() to find actual
405  * instances.
406  **/
407 bool die_is_func_instance(Dwarf_Die *dw_die)
408 {
409         Dwarf_Addr tmp;
410         Dwarf_Attribute attr_mem;
411         int tag = dwarf_tag(dw_die);
412 
413         if (tag != DW_TAG_subprogram &&
414             tag != DW_TAG_inlined_subroutine)
415                 return false;
416 
417         return dwarf_entrypc(dw_die, &tmp) == 0 ||
418                 dwarf_attr(dw_die, DW_AT_ranges, &attr_mem) != NULL;
419 }
420 
421 /**
422  * die_get_data_member_location - Get the data-member offset
423  * @mb_die: a DIE of a member of a data structure
424  * @offs: The offset of the member in the data structure
425  *
426  * Get the offset of @mb_die in the data structure including @mb_die, and
427  * stores result offset to @offs. If any error occurs this returns errno.
428  */
429 int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
430 {
431         Dwarf_Attribute attr;
432         Dwarf_Op *expr;
433         size_t nexpr;
434         int ret;
435 
436         if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
437                 return -ENOENT;
438 
439         if (dwarf_formudata(&attr, offs) != 0) {
440                 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
441                 ret = dwarf_getlocation(&attr, &expr, &nexpr);
442                 if (ret < 0 || nexpr == 0)
443                         return -ENOENT;
444 
445                 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
446                         pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
447                                  expr[0].atom, nexpr);
448                         return -ENOTSUP;
449                 }
450                 *offs = (Dwarf_Word)expr[0].number;
451         }
452         return 0;
453 }
454 
455 /* Get the call file index number in CU DIE */
456 static int die_get_call_fileno(Dwarf_Die *in_die)
457 {
458         Dwarf_Word idx;
459 
460         if (die_get_attr_udata(in_die, DW_AT_call_file, &idx) == 0)
461                 return (int)idx;
462         else
463                 return -ENOENT;
464 }
465 
466 /* Get the declared file index number in CU DIE */
467 static int die_get_decl_fileno(Dwarf_Die *pdie)
468 {
469         Dwarf_Word idx;
470 
471         if (die_get_attr_udata(pdie, DW_AT_decl_file, &idx) == 0)
472                 return (int)idx;
473         else
474                 return -ENOENT;
475 }
476 
477 /* Return the file name by index */
478 static const char *die_get_file_name(Dwarf_Die *dw_die, int idx)
479 {
480         Dwarf_Die cu_die;
481         Dwarf_Files *files;
482         Dwarf_Attribute attr_mem;
483 
484         if (idx < 0 || !dwarf_attr_integrate(dw_die, DW_AT_decl_file, &attr_mem) ||
485             !dwarf_cu_die(attr_mem.cu, &cu_die, NULL, NULL, NULL, NULL, NULL, NULL) ||
486             dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
487                 return NULL;
488 
489         return dwarf_filesrc(files, idx, NULL, NULL);
490 }
491 
492 /**
493  * die_get_call_file - Get callsite file name of inlined function instance
494  * @in_die: a DIE of an inlined function instance
495  *
496  * Get call-site file name of @in_die. This means from which file the inline
497  * function is called.
498  */
499 const char *die_get_call_file(Dwarf_Die *in_die)
500 {
501         return die_get_file_name(in_die, die_get_call_fileno(in_die));
502 }
503 
504 /**
505  * die_get_decl_file - Find the declared file name of this DIE
506  * @dw_die: a DIE for something declared.
507  *
508  * Get declared file name of @dw_die.
509  * NOTE: Since some version of clang DWARF5 implementation incorrectly uses
510  * file index 0 for DW_AT_decl_file, die_get_decl_file() will return NULL for
511  * such cases. Use this function instead.
512  */
513 const char *die_get_decl_file(Dwarf_Die *dw_die)
514 {
515         return die_get_file_name(dw_die, die_get_decl_fileno(dw_die));
516 }
517 
518 /**
519  * die_find_child - Generic DIE search function in DIE tree
520  * @rt_die: a root DIE
521  * @callback: a callback function
522  * @data: a user data passed to the callback function
523  * @die_mem: a buffer for result DIE
524  *
525  * Trace DIE tree from @rt_die and call @callback for each child DIE.
526  * If @callback returns DIE_FIND_CB_END, this stores the DIE into
527  * @die_mem and returns it. If @callback returns DIE_FIND_CB_CONTINUE,
528  * this continues to trace the tree. Optionally, @callback can return
529  * DIE_FIND_CB_CHILD and DIE_FIND_CB_SIBLING, those means trace only
530  * the children and trace only the siblings respectively.
531  * Returns NULL if @callback can't find any appropriate DIE.
532  */
533 Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
534                           int (*callback)(Dwarf_Die *, void *),
535                           void *data, Dwarf_Die *die_mem)
536 {
537         Dwarf_Die child_die;
538         int ret;
539 
540         ret = dwarf_child(rt_die, die_mem);
541         if (ret != 0)
542                 return NULL;
543 
544         do {
545                 ret = callback(die_mem, data);
546                 if (ret == DIE_FIND_CB_END)
547                         return die_mem;
548 
549                 if ((ret & DIE_FIND_CB_CHILD) &&
550                     die_find_child(die_mem, callback, data, &child_die)) {
551                         memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
552                         return die_mem;
553                 }
554         } while ((ret & DIE_FIND_CB_SIBLING) &&
555                  dwarf_siblingof(die_mem, die_mem) == 0);
556 
557         return NULL;
558 }
559 
560 struct __addr_die_search_param {
561         Dwarf_Addr      addr;
562         Dwarf_Die       *die_mem;
563 };
564 
565 static int __die_search_func_tail_cb(Dwarf_Die *fn_die, void *data)
566 {
567         struct __addr_die_search_param *ad = data;
568         Dwarf_Addr addr = 0;
569 
570         if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
571             !dwarf_highpc(fn_die, &addr) &&
572             addr == ad->addr) {
573                 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
574                 return DWARF_CB_ABORT;
575         }
576         return DWARF_CB_OK;
577 }
578 
579 /**
580  * die_find_tailfunc - Search for a non-inlined function with tail call at
581  * given address
582  * @cu_die: a CU DIE which including @addr
583  * @addr: target address
584  * @die_mem: a buffer for result DIE
585  *
586  * Search for a non-inlined function DIE with tail call at @addr. Stores the
587  * DIE to @die_mem and returns it if found. Returns NULL if failed.
588  */
589 Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
590                                     Dwarf_Die *die_mem)
591 {
592         struct __addr_die_search_param ad;
593         ad.addr = addr;
594         ad.die_mem = die_mem;
595         /* dwarf_getscopes can't find subprogram. */
596         if (!dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0))
597                 return NULL;
598         else
599                 return die_mem;
600 }
601 
602 /* die_find callback for non-inlined function search */
603 static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
604 {
605         struct __addr_die_search_param *ad = data;
606 
607         /*
608          * Since a declaration entry doesn't has given pc, this always returns
609          * function definition entry.
610          */
611         if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
612             dwarf_haspc(fn_die, ad->addr)) {
613                 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
614                 return DWARF_CB_ABORT;
615         }
616         return DWARF_CB_OK;
617 }
618 
619 /**
620  * die_find_realfunc - Search a non-inlined function at given address
621  * @cu_die: a CU DIE which including @addr
622  * @addr: target address
623  * @die_mem: a buffer for result DIE
624  *
625  * Search a non-inlined function DIE which includes @addr. Stores the
626  * DIE to @die_mem and returns it if found. Returns NULL if failed.
627  */
628 Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
629                                     Dwarf_Die *die_mem)
630 {
631         struct __addr_die_search_param ad;
632         ad.addr = addr;
633         ad.die_mem = die_mem;
634         /* dwarf_getscopes can't find subprogram. */
635         if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
636                 return NULL;
637         else
638                 return die_mem;
639 }
640 
641 /* die_find callback for inline function search */
642 static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
643 {
644         Dwarf_Addr *addr = data;
645 
646         if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
647             dwarf_haspc(die_mem, *addr))
648                 return DIE_FIND_CB_END;
649 
650         return DIE_FIND_CB_CONTINUE;
651 }
652 
653 /**
654  * die_find_top_inlinefunc - Search the top inlined function at given address
655  * @sp_die: a subprogram DIE which including @addr
656  * @addr: target address
657  * @die_mem: a buffer for result DIE
658  *
659  * Search an inlined function DIE which includes @addr. Stores the
660  * DIE to @die_mem and returns it if found. Returns NULL if failed.
661  * Even if several inlined functions are expanded recursively, this
662  * doesn't trace it down, and returns the topmost one.
663  */
664 Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
665                                    Dwarf_Die *die_mem)
666 {
667         return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
668 }
669 
670 /**
671  * die_find_inlinefunc - Search an inlined function at given address
672  * @sp_die: a subprogram DIE which including @addr
673  * @addr: target address
674  * @die_mem: a buffer for result DIE
675  *
676  * Search an inlined function DIE which includes @addr. Stores the
677  * DIE to @die_mem and returns it if found. Returns NULL if failed.
678  * If several inlined functions are expanded recursively, this trace
679  * it down and returns deepest one.
680  */
681 Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
682                                Dwarf_Die *die_mem)
683 {
684         Dwarf_Die tmp_die;
685 
686         sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
687         if (!sp_die)
688                 return NULL;
689 
690         /* Inlined function could be recursive. Trace it until fail */
691         while (sp_die) {
692                 memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
693                 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
694                                         &tmp_die);
695         }
696 
697         return die_mem;
698 }
699 
700 static int __die_find_func_rettype_cb(Dwarf_Die *die_mem, void *data)
701 {
702         const char *func_name;
703 
704         if (dwarf_tag(die_mem) != DW_TAG_subprogram)
705                 return DIE_FIND_CB_SIBLING;
706 
707         func_name = dwarf_diename(die_mem);
708         if (func_name && !strcmp(func_name, data))
709                 return DIE_FIND_CB_END;
710 
711         return DIE_FIND_CB_SIBLING;
712 }
713 
714 /**
715  * die_find_func_rettype - Search a return type of function
716  * @cu_die: a CU DIE
717  * @name: target function name
718  * @die_mem: a buffer for result DIE
719  *
720  * Search a non-inlined function which matches to @name and stores the
721  * return type of the function to @die_mem and returns it if found.
722  * Returns NULL if failed.  Note that it doesn't needs to find a
723  * definition of the function, so it doesn't match with address.
724  * Most likely, it can find a declaration at the top level.  Thus the
725  * callback function continues to sibling entries only.
726  */
727 Dwarf_Die *die_find_func_rettype(Dwarf_Die *cu_die, const char *name,
728                                  Dwarf_Die *die_mem)
729 {
730         Dwarf_Die tmp_die;
731 
732         cu_die = die_find_child(cu_die, __die_find_func_rettype_cb,
733                                 (void *)name, &tmp_die);
734         if (!cu_die)
735                 return NULL;
736 
737         if (die_get_real_type(&tmp_die, die_mem) == NULL)
738                 return NULL;
739 
740         return die_mem;
741 }
742 
743 struct __instance_walk_param {
744         void    *addr;
745         int     (*callback)(Dwarf_Die *, void *);
746         void    *data;
747         int     retval;
748 };
749 
750 static int __die_walk_instances_cb(Dwarf_Die *inst, void *data)
751 {
752         struct __instance_walk_param *iwp = data;
753         Dwarf_Attribute attr_mem;
754         Dwarf_Die origin_mem;
755         Dwarf_Attribute *attr;
756         Dwarf_Die *origin;
757         int tmp;
758 
759         if (!die_is_func_instance(inst))
760                 return DIE_FIND_CB_CONTINUE;
761 
762         attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem);
763         if (attr == NULL)
764                 return DIE_FIND_CB_CONTINUE;
765 
766         origin = dwarf_formref_die(attr, &origin_mem);
767         if (origin == NULL || origin->addr != iwp->addr)
768                 return DIE_FIND_CB_CONTINUE;
769 
770         /* Ignore redundant instances */
771         if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) {
772                 dwarf_decl_line(origin, &tmp);
773                 if (die_get_call_lineno(inst) == tmp) {
774                         tmp = die_get_decl_fileno(origin);
775                         if (die_get_call_fileno(inst) == tmp)
776                                 return DIE_FIND_CB_CONTINUE;
777                 }
778         }
779 
780         iwp->retval = iwp->callback(inst, iwp->data);
781 
782         return (iwp->retval) ? DIE_FIND_CB_END : DIE_FIND_CB_CONTINUE;
783 }
784 
785 /**
786  * die_walk_instances - Walk on instances of given DIE
787  * @or_die: an abstract original DIE
788  * @callback: a callback function which is called with instance DIE
789  * @data: user data
790  *
791  * Walk on the instances of give @in_die. @in_die must be an inlined function
792  * declaration. This returns the return value of @callback if it returns
793  * non-zero value, or -ENOENT if there is no instance.
794  */
795 int die_walk_instances(Dwarf_Die *or_die, int (*callback)(Dwarf_Die *, void *),
796                        void *data)
797 {
798         Dwarf_Die cu_die;
799         Dwarf_Die die_mem;
800         struct __instance_walk_param iwp = {
801                 .addr = or_die->addr,
802                 .callback = callback,
803                 .data = data,
804                 .retval = -ENOENT,
805         };
806 
807         if (dwarf_diecu(or_die, &cu_die, NULL, NULL) == NULL)
808                 return -ENOENT;
809 
810         die_find_child(&cu_die, __die_walk_instances_cb, &iwp, &die_mem);
811 
812         return iwp.retval;
813 }
814 
815 /* Line walker internal parameters */
816 struct __line_walk_param {
817         bool recursive;
818         line_walk_callback_t callback;
819         void *data;
820         int retval;
821 };
822 
823 static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
824 {
825         struct __line_walk_param *lw = data;
826         Dwarf_Addr addr = 0;
827         const char *fname;
828         int lineno;
829 
830         if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
831                 fname = die_get_call_file(in_die);
832                 lineno = die_get_call_lineno(in_die);
833                 if (fname && lineno > 0 && die_entrypc(in_die, &addr) == 0) {
834                         lw->retval = lw->callback(fname, lineno, addr, lw->data);
835                         if (lw->retval != 0)
836                                 return DIE_FIND_CB_END;
837                 }
838                 if (!lw->recursive)
839                         return DIE_FIND_CB_SIBLING;
840         }
841 
842         if (addr) {
843                 fname = die_get_decl_file(in_die);
844                 if (fname && dwarf_decl_line(in_die, &lineno) == 0) {
845                         lw->retval = lw->callback(fname, lineno, addr, lw->data);
846                         if (lw->retval != 0)
847                                 return DIE_FIND_CB_END;
848                 }
849         }
850 
851         /* Continue to search nested inlined function call-sites */
852         return DIE_FIND_CB_CONTINUE;
853 }
854 
855 /* Walk on lines of blocks included in given DIE */
856 static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive,
857                                 line_walk_callback_t callback, void *data)
858 {
859         struct __line_walk_param lw = {
860                 .recursive = recursive,
861                 .callback = callback,
862                 .data = data,
863                 .retval = 0,
864         };
865         Dwarf_Die die_mem;
866         Dwarf_Addr addr;
867         const char *fname;
868         int lineno;
869 
870         /* Handle function declaration line */
871         fname = die_get_decl_file(sp_die);
872         if (fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
873             die_entrypc(sp_die, &addr) == 0) {
874                 lw.retval = callback(fname, lineno, addr, data);
875                 if (lw.retval != 0)
876                         goto done;
877         }
878         die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
879 done:
880         return lw.retval;
881 }
882 
883 static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
884 {
885         struct __line_walk_param *lw = data;
886 
887         /*
888          * Since inlined function can include another inlined function in
889          * the same file, we need to walk in it recursively.
890          */
891         lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data);
892         if (lw->retval != 0)
893                 return DWARF_CB_ABORT;
894 
895         return DWARF_CB_OK;
896 }
897 
898 /**
899  * die_walk_lines - Walk on lines inside given DIE
900  * @rt_die: a root DIE (CU, subprogram or inlined_subroutine)
901  * @callback: callback routine
902  * @data: user data
903  *
904  * Walk on all lines inside given @rt_die and call @callback on each line.
905  * If the @rt_die is a function, walk only on the lines inside the function,
906  * otherwise @rt_die must be a CU DIE.
907  * Note that this walks not only dwarf line list, but also function entries
908  * and inline call-site.
909  */
910 int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
911 {
912         Dwarf_Lines *lines;
913         Dwarf_Line *line;
914         Dwarf_Addr addr;
915         const char *fname, *decf = NULL, *inf = NULL;
916         int lineno, ret = 0;
917         int decl = 0, inl;
918         Dwarf_Die die_mem, *cu_die;
919         size_t nlines, i;
920         bool flag;
921 
922         /* Get the CU die */
923         if (dwarf_tag(rt_die) != DW_TAG_compile_unit) {
924                 cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
925                 dwarf_decl_line(rt_die, &decl);
926                 decf = die_get_decl_file(rt_die);
927                 if (!decf) {
928                         pr_debug2("Failed to get the declared file name of %s\n",
929                                   dwarf_diename(rt_die));
930                         return -EINVAL;
931                 }
932         } else
933                 cu_die = rt_die;
934         if (!cu_die) {
935                 pr_debug2("Failed to get CU from given DIE.\n");
936                 return -EINVAL;
937         }
938 
939         /* Get lines list in the CU */
940         if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
941                 pr_debug2("Failed to get source lines on this CU.\n");
942                 return -ENOENT;
943         }
944         pr_debug2("Get %zd lines from this CU\n", nlines);
945 
946         /* Walk on the lines on lines list */
947         for (i = 0; i < nlines; i++) {
948                 line = dwarf_onesrcline(lines, i);
949                 if (line == NULL ||
950                     dwarf_lineno(line, &lineno) != 0 ||
951                     dwarf_lineaddr(line, &addr) != 0) {
952                         pr_debug2("Failed to get line info. "
953                                   "Possible error in debuginfo.\n");
954                         continue;
955                 }
956                 /* Skip end-of-sequence */
957                 if (dwarf_lineendsequence(line, &flag) != 0 || flag)
958                         continue;
959                 /* Skip Non statement line-info */
960                 if (dwarf_linebeginstatement(line, &flag) != 0 || !flag)
961                         continue;
962                 /* Filter lines based on address */
963                 if (rt_die != cu_die) {
964                         /*
965                          * Address filtering
966                          * The line is included in given function, and
967                          * no inline block includes it.
968                          */
969                         if (!dwarf_haspc(rt_die, addr))
970                                 continue;
971 
972                         if (die_find_inlinefunc(rt_die, addr, &die_mem)) {
973                                 /* Call-site check */
974                                 inf = die_get_call_file(&die_mem);
975                                 if ((inf && !strcmp(inf, decf)) &&
976                                     die_get_call_lineno(&die_mem) == lineno)
977                                         goto found;
978 
979                                 dwarf_decl_line(&die_mem, &inl);
980                                 if (inl != decl ||
981                                     decf != die_get_decl_file(&die_mem))
982                                         continue;
983                         }
984                 }
985 found:
986                 /* Get source line */
987                 fname = dwarf_linesrc(line, NULL, NULL);
988 
989                 ret = callback(fname, lineno, addr, data);
990                 if (ret != 0)
991                         return ret;
992         }
993 
994         /*
995          * Dwarf lines doesn't include function declarations and inlined
996          * subroutines. We have to check functions list or given function.
997          */
998         if (rt_die != cu_die)
999                 /*
1000                  * Don't need walk inlined functions recursively, because
1001                  * inner inlined functions don't have the lines of the
1002                  * specified function.
1003                  */
1004                 ret = __die_walk_funclines(rt_die, false, callback, data);
1005         else {
1006                 struct __line_walk_param param = {
1007                         .callback = callback,
1008                         .data = data,
1009                         .retval = 0,
1010                 };
1011                 dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
1012                 ret = param.retval;
1013         }
1014 
1015         return ret;
1016 }
1017 
1018 struct __find_variable_param {
1019         const char *name;
1020         Dwarf_Addr addr;
1021 };
1022 
1023 static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
1024 {
1025         struct __find_variable_param *fvp = data;
1026         Dwarf_Attribute attr;
1027         int tag;
1028 
1029         tag = dwarf_tag(die_mem);
1030         if ((tag == DW_TAG_formal_parameter ||
1031              tag == DW_TAG_variable) &&
1032             die_compare_name(die_mem, fvp->name) &&
1033         /*
1034          * Does the DIE have location information or const value
1035          * or external instance?
1036          */
1037             (dwarf_attr(die_mem, DW_AT_external, &attr) ||
1038              dwarf_attr(die_mem, DW_AT_location, &attr) ||
1039              dwarf_attr(die_mem, DW_AT_const_value, &attr)))
1040                 return DIE_FIND_CB_END;
1041         if (dwarf_haspc(die_mem, fvp->addr))
1042                 return DIE_FIND_CB_CONTINUE;
1043         else
1044                 return DIE_FIND_CB_SIBLING;
1045 }
1046 
1047 /**
1048  * die_find_variable_at - Find a given name variable at given address
1049  * @sp_die: a function DIE
1050  * @name: variable name
1051  * @addr: address
1052  * @die_mem: a buffer for result DIE
1053  *
1054  * Find a variable DIE called @name at @addr in @sp_die.
1055  */
1056 Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
1057                                 Dwarf_Addr addr, Dwarf_Die *die_mem)
1058 {
1059         struct __find_variable_param fvp = { .name = name, .addr = addr};
1060 
1061         return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
1062                               die_mem);
1063 }
1064 
1065 static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
1066 {
1067         const char *name = data;
1068 
1069         if (dwarf_tag(die_mem) == DW_TAG_member) {
1070                 if (die_compare_name(die_mem, name))
1071                         return DIE_FIND_CB_END;
1072                 else if (!dwarf_diename(die_mem)) {     /* Unnamed structure */
1073                         Dwarf_Die type_die, tmp_die;
1074                         if (die_get_type(die_mem, &type_die) &&
1075                             die_find_member(&type_die, name, &tmp_die))
1076                                 return DIE_FIND_CB_END;
1077                 }
1078         }
1079         return DIE_FIND_CB_SIBLING;
1080 }
1081 
1082 /**
1083  * die_find_member - Find a given name member in a data structure
1084  * @st_die: a data structure type DIE
1085  * @name: member name
1086  * @die_mem: a buffer for result DIE
1087  *
1088  * Find a member DIE called @name in @st_die.
1089  */
1090 Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
1091                            Dwarf_Die *die_mem)
1092 {
1093         return die_find_child(st_die, __die_find_member_cb, (void *)name,
1094                               die_mem);
1095 }
1096 
1097 /**
1098  * die_get_typename_from_type - Get the name of given type DIE
1099  * @type_die: a type DIE
1100  * @buf: a strbuf for result type name
1101  *
1102  * Get the name of @type_die and stores it to @buf. Return 0 if succeeded.
1103  * and Return -ENOENT if failed to find type name.
1104  * Note that the result will stores typedef name if possible, and stores
1105  * "*(function_type)" if the type is a function pointer.
1106  */
1107 int die_get_typename_from_type(Dwarf_Die *type_die, struct strbuf *buf)
1108 {
1109         int tag, ret;
1110         const char *tmp = "";
1111 
1112         tag = dwarf_tag(type_die);
1113         if (tag == DW_TAG_pointer_type)
1114                 tmp = "*";
1115         else if (tag == DW_TAG_array_type)
1116                 tmp = "[]";
1117         else if (tag == DW_TAG_subroutine_type) {
1118                 /* Function pointer */
1119                 return strbuf_add(buf, "(function_type)", 15);
1120         } else {
1121                 const char *name = dwarf_diename(type_die);
1122 
1123                 if (tag == DW_TAG_union_type)
1124                         tmp = "union ";
1125                 else if (tag == DW_TAG_structure_type)
1126                         tmp = "struct ";
1127                 else if (tag == DW_TAG_enumeration_type)
1128                         tmp = "enum ";
1129                 else if (name == NULL)
1130                         return -ENOENT;
1131                 /* Write a base name */
1132                 return strbuf_addf(buf, "%s%s", tmp, name ?: "");
1133         }
1134         ret = die_get_typename(type_die, buf);
1135         if (ret < 0) {
1136                 /* void pointer has no type attribute */
1137                 if (tag == DW_TAG_pointer_type && ret == -ENOENT)
1138                         return strbuf_addf(buf, "void*");
1139 
1140                 return ret;
1141         }
1142         return strbuf_addstr(buf, tmp);
1143 }
1144 
1145 /**
1146  * die_get_typename - Get the name of given variable DIE
1147  * @vr_die: a variable DIE
1148  * @buf: a strbuf for result type name
1149  *
1150  * Get the name of @vr_die and stores it to @buf. Return 0 if succeeded.
1151  * and Return -ENOENT if failed to find type name.
1152  * Note that the result will stores typedef name if possible, and stores
1153  * "*(function_type)" if the type is a function pointer.
1154  */
1155 int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
1156 {
1157         Dwarf_Die type;
1158 
1159         if (__die_get_real_type(vr_die, &type) == NULL)
1160                 return -ENOENT;
1161 
1162         return die_get_typename_from_type(&type, buf);
1163 }
1164 
1165 /**
1166  * die_get_varname - Get the name and type of given variable DIE
1167  * @vr_die: a variable DIE
1168  * @buf: a strbuf for type and variable name
1169  *
1170  * Get the name and type of @vr_die and stores it in @buf as "type\tname".
1171  */
1172 int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
1173 {
1174         int ret;
1175 
1176         ret = die_get_typename(vr_die, buf);
1177         if (ret < 0) {
1178                 pr_debug("Failed to get type, make it unknown.\n");
1179                 ret = strbuf_add(buf, "(unknown_type)", 14);
1180         }
1181 
1182         return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
1183 }
1184 
1185 #if defined(HAVE_DWARF_GETLOCATIONS_SUPPORT) || defined(HAVE_DWARF_CFI_SUPPORT)
1186 static int reg_from_dwarf_op(Dwarf_Op *op)
1187 {
1188         switch (op->atom) {
1189         case DW_OP_reg0 ... DW_OP_reg31:
1190                 return op->atom - DW_OP_reg0;
1191         case DW_OP_breg0 ... DW_OP_breg31:
1192                 return op->atom - DW_OP_breg0;
1193         case DW_OP_regx:
1194         case DW_OP_bregx:
1195                 return op->number;
1196         case DW_OP_fbreg:
1197                 return DWARF_REG_FB;
1198         default:
1199                 break;
1200         }
1201         return -1;
1202 }
1203 
1204 static int offset_from_dwarf_op(Dwarf_Op *op)
1205 {
1206         switch (op->atom) {
1207         case DW_OP_reg0 ... DW_OP_reg31:
1208         case DW_OP_regx:
1209                 return 0;
1210         case DW_OP_breg0 ... DW_OP_breg31:
1211         case DW_OP_fbreg:
1212                 return op->number;
1213         case DW_OP_bregx:
1214                 return op->number2;
1215         default:
1216                 break;
1217         }
1218         return -1;
1219 }
1220 
1221 static bool check_allowed_ops(Dwarf_Op *ops, size_t nops)
1222 {
1223         /* The first op is checked separately */
1224         ops++;
1225         nops--;
1226 
1227         /*
1228          * It needs to make sure if the location expression matches to the given
1229          * register and offset exactly.  Thus it rejects any complex expressions
1230          * and only allows a few of selected operators that doesn't change the
1231          * location.
1232          */
1233         while (nops) {
1234                 switch (ops->atom) {
1235                 case DW_OP_stack_value:
1236                 case DW_OP_deref_size:
1237                 case DW_OP_deref:
1238                 case DW_OP_piece:
1239                         break;
1240                 default:
1241                         return false;
1242                 }
1243                 ops++;
1244                 nops--;
1245         }
1246         return true;
1247 }
1248 #endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT || HAVE_DWARF_CFI_SUPPORT */
1249 
1250 #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT
1251 /**
1252  * die_get_var_innermost_scope - Get innermost scope range of given variable DIE
1253  * @sp_die: a subprogram DIE
1254  * @vr_die: a variable DIE
1255  * @buf: a strbuf for variable byte offset range
1256  *
1257  * Get the innermost scope range of @vr_die and stores it in @buf as
1258  * "@<function_name+[NN-NN,NN-NN]>".
1259  */
1260 static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die,
1261                                 struct strbuf *buf)
1262 {
1263         Dwarf_Die *scopes;
1264         int count;
1265         size_t offset = 0;
1266         Dwarf_Addr base;
1267         Dwarf_Addr start, end;
1268         Dwarf_Addr entry;
1269         int ret;
1270         bool first = true;
1271         const char *name;
1272 
1273         ret = die_entrypc(sp_die, &entry);
1274         if (ret)
1275                 return ret;
1276 
1277         name = dwarf_diename(sp_die);
1278         if (!name)
1279                 return -ENOENT;
1280 
1281         count = dwarf_getscopes_die(vr_die, &scopes);
1282 
1283         /* (*SCOPES)[1] is the DIE for the scope containing that scope */
1284         if (count <= 1) {
1285                 ret = -EINVAL;
1286                 goto out;
1287         }
1288 
1289         while ((offset = dwarf_ranges(&scopes[1], offset, &base,
1290                                         &start, &end)) > 0) {
1291                 start -= entry;
1292                 end -= entry;
1293 
1294                 if (first) {
1295                         ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1296                                           name, start, end);
1297                         first = false;
1298                 } else {
1299                         ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1300                                           start, end);
1301                 }
1302                 if (ret < 0)
1303                         goto out;
1304         }
1305 
1306         if (!first)
1307                 ret = strbuf_add(buf, "]>", 2);
1308 
1309 out:
1310         free(scopes);
1311         return ret;
1312 }
1313 
1314 /**
1315  * die_get_var_range - Get byte offset range of given variable DIE
1316  * @sp_die: a subprogram DIE
1317  * @vr_die: a variable DIE
1318  * @buf: a strbuf for type and variable name and byte offset range
1319  *
1320  * Get the byte offset range of @vr_die and stores it in @buf as
1321  * "@<function_name+[NN-NN,NN-NN]>".
1322  */
1323 int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf)
1324 {
1325         int ret = 0;
1326         Dwarf_Addr base;
1327         Dwarf_Addr start, end;
1328         Dwarf_Addr entry;
1329         Dwarf_Op *op;
1330         size_t nops;
1331         size_t offset = 0;
1332         Dwarf_Attribute attr;
1333         bool first = true;
1334         const char *name;
1335 
1336         ret = die_entrypc(sp_die, &entry);
1337         if (ret)
1338                 return ret;
1339 
1340         name = dwarf_diename(sp_die);
1341         if (!name)
1342                 return -ENOENT;
1343 
1344         if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
1345                 return -EINVAL;
1346 
1347         while ((offset = dwarf_getlocations(&attr, offset, &base,
1348                                         &start, &end, &op, &nops)) > 0) {
1349                 if (start == 0) {
1350                         /* Single Location Descriptions */
1351                         ret = die_get_var_innermost_scope(sp_die, vr_die, buf);
1352                         goto out;
1353                 }
1354 
1355                 /* Location Lists */
1356                 start -= entry;
1357                 end -= entry;
1358                 if (first) {
1359                         ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1360                                           name, start, end);
1361                         first = false;
1362                 } else {
1363                         ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1364                                           start, end);
1365                 }
1366                 if (ret < 0)
1367                         goto out;
1368         }
1369 
1370         if (!first)
1371                 ret = strbuf_add(buf, "]>", 2);
1372 out:
1373         return ret;
1374 }
1375 
1376 /* Interval parameters for __die_find_var_reg_cb() */
1377 struct find_var_data {
1378         /* Target instruction address */
1379         Dwarf_Addr pc;
1380         /* Target memory address (for global data) */
1381         Dwarf_Addr addr;
1382         /* Target register */
1383         unsigned reg;
1384         /* Access offset, set for global data */
1385         int offset;
1386         /* True if the current register is the frame base */
1387         bool is_fbreg;
1388 };
1389 
1390 /* Max number of registers DW_OP_regN supports */
1391 #define DWARF_OP_DIRECT_REGS  32
1392 
1393 static bool match_var_offset(Dwarf_Die *die_mem, struct find_var_data *data,
1394                              u64 addr_offset, u64 addr_type, bool is_pointer)
1395 {
1396         Dwarf_Die type_die;
1397         Dwarf_Word size;
1398 
1399         if (addr_offset == addr_type) {
1400                 /* Update offset relative to the start of the variable */
1401                 data->offset = 0;
1402                 return true;
1403         }
1404 
1405         if (addr_offset < addr_type)
1406                 return false;
1407 
1408         if (die_get_real_type(die_mem, &type_die) == NULL)
1409                 return false;
1410 
1411         if (is_pointer && dwarf_tag(&type_die) == DW_TAG_pointer_type) {
1412                 /* Get the target type of the pointer */
1413                 if (die_get_real_type(&type_die, &type_die) == NULL)
1414                         return false;
1415         }
1416 
1417         if (dwarf_aggregate_size(&type_die, &size) < 0)
1418                 return false;
1419 
1420         if (addr_offset >= addr_type + size)
1421                 return false;
1422 
1423         /* Update offset relative to the start of the variable */
1424         data->offset = addr_offset - addr_type;
1425         return true;
1426 }
1427 
1428 /* Only checks direct child DIEs in the given scope. */
1429 static int __die_find_var_reg_cb(Dwarf_Die *die_mem, void *arg)
1430 {
1431         struct find_var_data *data = arg;
1432         int tag = dwarf_tag(die_mem);
1433         ptrdiff_t off = 0;
1434         Dwarf_Attribute attr;
1435         Dwarf_Addr base, start, end;
1436         Dwarf_Op *ops;
1437         size_t nops;
1438 
1439         if (tag != DW_TAG_variable && tag != DW_TAG_formal_parameter)
1440                 return DIE_FIND_CB_SIBLING;
1441 
1442         if (dwarf_attr(die_mem, DW_AT_location, &attr) == NULL)
1443                 return DIE_FIND_CB_SIBLING;
1444 
1445         while ((off = dwarf_getlocations(&attr, off, &base, &start, &end, &ops, &nops)) > 0) {
1446                 /* Assuming the location list is sorted by address */
1447                 if (end < data->pc)
1448                         continue;
1449                 if (start > data->pc)
1450                         break;
1451 
1452                 /* Local variables accessed using frame base register */
1453                 if (data->is_fbreg && ops->atom == DW_OP_fbreg &&
1454                     check_allowed_ops(ops, nops) &&
1455                     match_var_offset(die_mem, data, data->offset, ops->number,
1456                                      /*is_pointer=*/false))
1457                         return DIE_FIND_CB_END;
1458 
1459                 /* Only match with a simple case */
1460                 if (data->reg < DWARF_OP_DIRECT_REGS) {
1461                         /* pointer variables saved in a register 0 to 31 */
1462                         if (ops->atom == (DW_OP_reg0 + data->reg) &&
1463                             check_allowed_ops(ops, nops) &&
1464                             match_var_offset(die_mem, data, data->offset, 0,
1465                                              /*is_pointer=*/true))
1466                                 return DIE_FIND_CB_END;
1467 
1468                         /* Local variables accessed by a register + offset */
1469                         if (ops->atom == (DW_OP_breg0 + data->reg) &&
1470                             check_allowed_ops(ops, nops) &&
1471                             match_var_offset(die_mem, data, data->offset, ops->number,
1472                                              /*is_pointer=*/false))
1473                                 return DIE_FIND_CB_END;
1474                 } else {
1475                         /* pointer variables saved in a register 32 or above */
1476                         if (ops->atom == DW_OP_regx && ops->number == data->reg &&
1477                             check_allowed_ops(ops, nops) &&
1478                             match_var_offset(die_mem, data, data->offset, 0,
1479                                              /*is_pointer=*/true))
1480                                 return DIE_FIND_CB_END;
1481 
1482                         /* Local variables accessed by a register + offset */
1483                         if (ops->atom == DW_OP_bregx && data->reg == ops->number &&
1484                             check_allowed_ops(ops, nops) &&
1485                             match_var_offset(die_mem, data, data->offset, ops->number2,
1486                                              /*is_poitner=*/false))
1487                                 return DIE_FIND_CB_END;
1488                 }
1489         }
1490         return DIE_FIND_CB_SIBLING;
1491 }
1492 
1493 /**
1494  * die_find_variable_by_reg - Find a variable saved in a register
1495  * @sc_die: a scope DIE
1496  * @pc: the program address to find
1497  * @reg: the register number to find
1498  * @poffset: pointer to offset, will be updated for fbreg case
1499  * @is_fbreg: boolean value if the current register is the frame base
1500  * @die_mem: a buffer to save the resulting DIE
1501  *
1502  * Find the variable DIE accessed by the given register.  It'll update the @offset
1503  * when the variable is in the stack.
1504  */
1505 Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die, Dwarf_Addr pc, int reg,
1506                                     int *poffset, bool is_fbreg,
1507                                     Dwarf_Die *die_mem)
1508 {
1509         struct find_var_data data = {
1510                 .pc = pc,
1511                 .reg = reg,
1512                 .offset = *poffset,
1513                 .is_fbreg = is_fbreg,
1514         };
1515         Dwarf_Die *result;
1516 
1517         result = die_find_child(sc_die, __die_find_var_reg_cb, &data, die_mem);
1518         if (result)
1519                 *poffset = data.offset;
1520         return result;
1521 }
1522 
1523 /* Only checks direct child DIEs in the given scope */
1524 static int __die_find_var_addr_cb(Dwarf_Die *die_mem, void *arg)
1525 {
1526         struct find_var_data *data = arg;
1527         int tag = dwarf_tag(die_mem);
1528         ptrdiff_t off = 0;
1529         Dwarf_Attribute attr;
1530         Dwarf_Addr base, start, end;
1531         Dwarf_Op *ops;
1532         size_t nops;
1533 
1534         if (tag != DW_TAG_variable)
1535                 return DIE_FIND_CB_SIBLING;
1536 
1537         if (dwarf_attr(die_mem, DW_AT_location, &attr) == NULL)
1538                 return DIE_FIND_CB_SIBLING;
1539 
1540         while ((off = dwarf_getlocations(&attr, off, &base, &start, &end, &ops, &nops)) > 0) {
1541                 if (ops->atom != DW_OP_addr)
1542                         continue;
1543 
1544                 if (check_allowed_ops(ops, nops) &&
1545                     match_var_offset(die_mem, data, data->addr, ops->number,
1546                                      /*is_pointer=*/false))
1547                         return DIE_FIND_CB_END;
1548         }
1549         return DIE_FIND_CB_SIBLING;
1550 }
1551 
1552 /**
1553  * die_find_variable_by_addr - Find variable located at given address
1554  * @sc_die: a scope DIE
1555  * @addr: the data address to find
1556  * @die_mem: a buffer to save the resulting DIE
1557  * @offset: the offset in the resulting type
1558  *
1559  * Find the variable DIE located at the given address (in PC-relative mode).
1560  * This is usually for global variables.
1561  */
1562 Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr addr,
1563                                      Dwarf_Die *die_mem, int *offset)
1564 {
1565         struct find_var_data data = {
1566                 .addr = addr,
1567         };
1568         Dwarf_Die *result;
1569 
1570         result = die_find_child(sc_die, __die_find_var_addr_cb, &data, die_mem);
1571         if (result)
1572                 *offset = data.offset;
1573         return result;
1574 }
1575 
1576 static int __die_collect_vars_cb(Dwarf_Die *die_mem, void *arg)
1577 {
1578         struct die_var_type **var_types = arg;
1579         Dwarf_Die type_die;
1580         int tag = dwarf_tag(die_mem);
1581         Dwarf_Attribute attr;
1582         Dwarf_Addr base, start, end;
1583         Dwarf_Op *ops;
1584         size_t nops;
1585         struct die_var_type *vt;
1586 
1587         if (tag != DW_TAG_variable && tag != DW_TAG_formal_parameter)
1588                 return DIE_FIND_CB_SIBLING;
1589 
1590         if (dwarf_attr(die_mem, DW_AT_location, &attr) == NULL)
1591                 return DIE_FIND_CB_SIBLING;
1592 
1593         /*
1594          * Only collect the first location as it can reconstruct the
1595          * remaining state by following the instructions.
1596          * start = 0 means it covers the whole range.
1597          */
1598         if (dwarf_getlocations(&attr, 0, &base, &start, &end, &ops, &nops) <= 0)
1599                 return DIE_FIND_CB_SIBLING;
1600 
1601         if (die_get_real_type(die_mem, &type_die) == NULL)
1602                 return DIE_FIND_CB_SIBLING;
1603 
1604         vt = malloc(sizeof(*vt));
1605         if (vt == NULL)
1606                 return DIE_FIND_CB_END;
1607 
1608         vt->die_off = dwarf_dieoffset(&type_die);
1609         vt->addr = start;
1610         vt->reg = reg_from_dwarf_op(ops);
1611         vt->offset = offset_from_dwarf_op(ops);
1612         vt->next = *var_types;
1613         *var_types = vt;
1614 
1615         return DIE_FIND_CB_SIBLING;
1616 }
1617 
1618 /**
1619  * die_collect_vars - Save all variables and parameters
1620  * @sc_die: a scope DIE
1621  * @var_types: a pointer to save the resulting list
1622  *
1623  * Save all variables and parameters in the @sc_die and save them to @var_types.
1624  * The @var_types is a singly-linked list containing type and location info.
1625  * Actual type can be retrieved using dwarf_offdie() with 'die_off' later.
1626  *
1627  * Callers should free @var_types.
1628  */
1629 void die_collect_vars(Dwarf_Die *sc_die, struct die_var_type **var_types)
1630 {
1631         Dwarf_Die die_mem;
1632 
1633         die_find_child(sc_die, __die_collect_vars_cb, (void *)var_types, &die_mem);
1634 }
1635 
1636 static int __die_collect_global_vars_cb(Dwarf_Die *die_mem, void *arg)
1637 {
1638         struct die_var_type **var_types = arg;
1639         Dwarf_Die type_die;
1640         int tag = dwarf_tag(die_mem);
1641         Dwarf_Attribute attr;
1642         Dwarf_Addr base, start, end;
1643         Dwarf_Op *ops;
1644         size_t nops;
1645         struct die_var_type *vt;
1646 
1647         if (tag != DW_TAG_variable)
1648                 return DIE_FIND_CB_SIBLING;
1649 
1650         if (dwarf_attr(die_mem, DW_AT_location, &attr) == NULL)
1651                 return DIE_FIND_CB_SIBLING;
1652 
1653         /* Only collect the location with an absolute address. */
1654         if (dwarf_getlocations(&attr, 0, &base, &start, &end, &ops, &nops) <= 0)
1655                 return DIE_FIND_CB_SIBLING;
1656 
1657         if (ops->atom != DW_OP_addr)
1658                 return DIE_FIND_CB_SIBLING;
1659 
1660         if (!check_allowed_ops(ops, nops))
1661                 return DIE_FIND_CB_SIBLING;
1662 
1663         if (die_get_real_type(die_mem, &type_die) == NULL)
1664                 return DIE_FIND_CB_SIBLING;
1665 
1666         vt = malloc(sizeof(*vt));
1667         if (vt == NULL)
1668                 return DIE_FIND_CB_END;
1669 
1670         vt->die_off = dwarf_dieoffset(&type_die);
1671         vt->addr = ops->number;
1672         vt->reg = -1;
1673         vt->offset = 0;
1674         vt->next = *var_types;
1675         *var_types = vt;
1676 
1677         return DIE_FIND_CB_SIBLING;
1678 }
1679 
1680 /**
1681  * die_collect_global_vars - Save all global variables
1682  * @cu_die: a CU DIE
1683  * @var_types: a pointer to save the resulting list
1684  *
1685  * Save all global variables in the @cu_die and save them to @var_types.
1686  * The @var_types is a singly-linked list containing type and location info.
1687  * Actual type can be retrieved using dwarf_offdie() with 'die_off' later.
1688  *
1689  * Callers should free @var_types.
1690  */
1691 void die_collect_global_vars(Dwarf_Die *cu_die, struct die_var_type **var_types)
1692 {
1693         Dwarf_Die die_mem;
1694 
1695         die_find_child(cu_die, __die_collect_global_vars_cb, (void *)var_types, &die_mem);
1696 }
1697 #endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */
1698 
1699 #ifdef HAVE_DWARF_CFI_SUPPORT
1700 /**
1701  * die_get_cfa - Get frame base information
1702  * @dwarf: a Dwarf info
1703  * @pc: program address
1704  * @preg: pointer for saved register
1705  * @poffset: pointer for saved offset
1706  *
1707  * This function gets register and offset for CFA (Canonical Frame Address)
1708  * by searching the CIE/FDE info.  The CFA usually points to the start address
1709  * of the current stack frame and local variables can be located using an offset
1710  * from the CFA.  The @preg and @poffset will be updated if it returns 0.
1711  */
1712 int die_get_cfa(Dwarf *dwarf, u64 pc, int *preg, int *poffset)
1713 {
1714         Dwarf_CFI *cfi;
1715         Dwarf_Frame *frame = NULL;
1716         Dwarf_Op *ops = NULL;
1717         size_t nops;
1718 
1719         cfi = dwarf_getcfi(dwarf);
1720         if (cfi == NULL)
1721                 return -1;
1722 
1723         if (!dwarf_cfi_addrframe(cfi, pc, &frame) &&
1724             !dwarf_frame_cfa(frame, &ops, &nops) &&
1725             check_allowed_ops(ops, nops)) {
1726                 *preg = reg_from_dwarf_op(ops);
1727                 *poffset = offset_from_dwarf_op(ops);
1728                 return 0;
1729         }
1730         return -1;
1731 }
1732 #endif /* HAVE_DWARF_CFI_SUPPORT */
1733 
1734 /*
1735  * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
1736  * @vr_die: a variable DIE
1737  */
1738 static bool die_has_loclist(Dwarf_Die *vr_die)
1739 {
1740         Dwarf_Attribute loc;
1741         int tag = dwarf_tag(vr_die);
1742 
1743         if (tag != DW_TAG_formal_parameter &&
1744             tag != DW_TAG_variable)
1745                 return false;
1746 
1747         return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
1748                 dwarf_whatform(&loc) == DW_FORM_sec_offset);
1749 }
1750 
1751 /*
1752  * die_is_optimized_target - Check if target program is compiled with
1753  * optimization
1754  * @cu_die: a CU DIE
1755  *
1756  * For any object in given CU whose DW_AT_location is a location list,
1757  * target program is compiled with optimization. This is applicable to
1758  * clang as well.
1759  */
1760 bool die_is_optimized_target(Dwarf_Die *cu_die)
1761 {
1762         Dwarf_Die tmp_die;
1763 
1764         if (die_has_loclist(cu_die))
1765                 return true;
1766 
1767         if (!dwarf_child(cu_die, &tmp_die) &&
1768             die_is_optimized_target(&tmp_die))
1769                 return true;
1770 
1771         if (!dwarf_siblingof(cu_die, &tmp_die) &&
1772             die_is_optimized_target(&tmp_die))
1773                 return true;
1774 
1775         return false;
1776 }
1777 
1778 /*
1779  * die_search_idx - Search index of given line address
1780  * @lines: Line records of single CU
1781  * @nr_lines: Number of @lines
1782  * @addr: address we are looking for
1783  * @idx: index to be set by this function (return value)
1784  *
1785  * Search for @addr by looping over every lines of CU. If address
1786  * matches, set index of that line in @idx. Note that single source
1787  * line can have multiple line records. i.e. single source line can
1788  * have multiple index.
1789  */
1790 static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
1791                            Dwarf_Addr addr, unsigned long *idx)
1792 {
1793         unsigned long i;
1794         Dwarf_Addr tmp;
1795 
1796         for (i = 0; i < nr_lines; i++) {
1797                 if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
1798                         return false;
1799 
1800                 if (tmp == addr) {
1801                         *idx = i;
1802                         return true;
1803                 }
1804         }
1805         return false;
1806 }
1807 
1808 /*
1809  * die_get_postprologue_addr - Search next address after function prologue
1810  * @entrypc_idx: entrypc index
1811  * @lines: Line records of single CU
1812  * @nr_lines: Number of @lines
1813  * @hignpc: high PC address of function
1814  * @postprologue_addr: Next address after function prologue (return value)
1815  *
1816  * Look for prologue-end marker. If there is no explicit marker, return
1817  * address of next line record or next source line.
1818  */
1819 static bool die_get_postprologue_addr(unsigned long entrypc_idx,
1820                                       Dwarf_Lines *lines,
1821                                       unsigned long nr_lines,
1822                                       Dwarf_Addr highpc,
1823                                       Dwarf_Addr *postprologue_addr)
1824 {
1825         unsigned long i;
1826         int entrypc_lno, lno;
1827         Dwarf_Line *line;
1828         Dwarf_Addr addr;
1829         bool p_end;
1830 
1831         /* entrypc_lno is actual source line number */
1832         line = dwarf_onesrcline(lines, entrypc_idx);
1833         if (dwarf_lineno(line, &entrypc_lno))
1834                 return false;
1835 
1836         for (i = entrypc_idx; i < nr_lines; i++) {
1837                 line = dwarf_onesrcline(lines, i);
1838 
1839                 if (dwarf_lineaddr(line, &addr) ||
1840                     dwarf_lineno(line, &lno)    ||
1841                     dwarf_lineprologueend(line, &p_end))
1842                         return false;
1843 
1844                 /* highpc is exclusive. [entrypc,highpc) */
1845                 if (addr >= highpc)
1846                         break;
1847 
1848                 /* clang supports prologue-end marker */
1849                 if (p_end)
1850                         break;
1851 
1852                 /* Actual next line in source */
1853                 if (lno != entrypc_lno)
1854                         break;
1855 
1856                 /*
1857                  * Single source line can have multiple line records.
1858                  * For Example,
1859                  *     void foo() { printf("hello\n"); }
1860                  * contains two line records. One points to declaration and
1861                  * other points to printf() line. Variable 'lno' won't get
1862                  * incremented in this case but 'i' will.
1863                  */
1864                 if (i != entrypc_idx)
1865                         break;
1866         }
1867 
1868         dwarf_lineaddr(line, postprologue_addr);
1869         if (*postprologue_addr >= highpc)
1870                 dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
1871                                postprologue_addr);
1872 
1873         return true;
1874 }
1875 
1876 /*
1877  * die_skip_prologue - Use next address after prologue as probe location
1878  * @sp_die: a subprogram DIE
1879  * @cu_die: a CU DIE
1880  * @entrypc: entrypc of the function
1881  *
1882  * Function prologue prepares stack and registers before executing function
1883  * logic. When target program is compiled without optimization, function
1884  * parameter information is only valid after prologue. When we probe entrypc
1885  * of the function, and try to record function parameter, it contains
1886  * garbage value.
1887  */
1888 void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
1889                        Dwarf_Addr *entrypc)
1890 {
1891         size_t nr_lines = 0;
1892         unsigned long entrypc_idx = 0;
1893         Dwarf_Lines *lines = NULL;
1894         Dwarf_Addr postprologue_addr;
1895         Dwarf_Addr highpc;
1896 
1897         if (dwarf_highpc(sp_die, &highpc))
1898                 return;
1899 
1900         if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
1901                 return;
1902 
1903         if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
1904                 return;
1905 
1906         if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
1907                                        highpc, &postprologue_addr))
1908                 return;
1909 
1910         *entrypc = postprologue_addr;
1911 }
1912 
1913 /* Internal parameters for __die_find_scope_cb() */
1914 struct find_scope_data {
1915         /* Target instruction address */
1916         Dwarf_Addr pc;
1917         /* Number of scopes found [output] */
1918         int nr;
1919         /* Array of scopes found, 0 for the outermost one. [output] */
1920         Dwarf_Die *scopes;
1921 };
1922 
1923 static int __die_find_scope_cb(Dwarf_Die *die_mem, void *arg)
1924 {
1925         struct find_scope_data *data = arg;
1926 
1927         if (dwarf_haspc(die_mem, data->pc)) {
1928                 Dwarf_Die *tmp;
1929 
1930                 tmp = realloc(data->scopes, (data->nr + 1) * sizeof(*tmp));
1931                 if (tmp == NULL)
1932                         return DIE_FIND_CB_END;
1933 
1934                 memcpy(tmp + data->nr, die_mem, sizeof(*die_mem));
1935                 data->scopes = tmp;
1936                 data->nr++;
1937                 return DIE_FIND_CB_CHILD;
1938         }
1939         return DIE_FIND_CB_SIBLING;
1940 }
1941 
1942 /**
1943  * die_get_scopes - Return a list of scopes including the address
1944  * @cu_die: a compile unit DIE
1945  * @pc: the address to find
1946  * @scopes: the array of DIEs for scopes (result)
1947  *
1948  * This function does the same as the dwarf_getscopes() but doesn't follow
1949  * the origins of inlined functions.  It returns the number of scopes saved
1950  * in the @scopes argument.  The outer scope will be saved first (index 0) and
1951  * the last one is the innermost scope at the @pc.
1952  */
1953 int die_get_scopes(Dwarf_Die *cu_die, Dwarf_Addr pc, Dwarf_Die **scopes)
1954 {
1955         struct find_scope_data data = {
1956                 .pc = pc,
1957         };
1958         Dwarf_Die die_mem;
1959 
1960         die_find_child(cu_die, __die_find_scope_cb, &data, &die_mem);
1961 
1962         *scopes = data.scopes;
1963         return data.nr;
1964 }
1965 
1966 static int __die_find_member_offset_cb(Dwarf_Die *die_mem, void *arg)
1967 {
1968         Dwarf_Die type_die;
1969         Dwarf_Word size, loc;
1970         Dwarf_Word offset = (long)arg;
1971         int tag = dwarf_tag(die_mem);
1972 
1973         if (tag != DW_TAG_member)
1974                 return DIE_FIND_CB_SIBLING;
1975 
1976         /* Unions might not have location */
1977         if (die_get_data_member_location(die_mem, &loc) < 0)
1978                 loc = 0;
1979 
1980         if (offset == loc)
1981                 return DIE_FIND_CB_END;
1982 
1983         if (die_get_real_type(die_mem, &type_die) == NULL) {
1984                 // TODO: add a pr_debug_dtp() later for this unlikely failure
1985                 return DIE_FIND_CB_SIBLING;
1986         }
1987 
1988         if (dwarf_aggregate_size(&type_die, &size) < 0)
1989                 size = 0;
1990 
1991         if (loc < offset && offset < (loc + size))
1992                 return DIE_FIND_CB_END;
1993 
1994         return DIE_FIND_CB_SIBLING;
1995 }
1996 
1997 /**
1998  * die_get_member_type - Return type info of struct member
1999  * @type_die: a type DIE
2000  * @offset: offset in the type
2001  * @die_mem: a buffer to save the resulting DIE
2002  *
2003  * This function returns a type of a member in @type_die where it's located at
2004  * @offset if it's a struct.  For now, it just returns the first matching
2005  * member in a union.  For other types, it'd return the given type directly
2006  * if it's within the size of the type or NULL otherwise.
2007  */
2008 Dwarf_Die *die_get_member_type(Dwarf_Die *type_die, int offset,
2009                                Dwarf_Die *die_mem)
2010 {
2011         Dwarf_Die *member;
2012         Dwarf_Die mb_type;
2013         int tag;
2014 
2015         tag = dwarf_tag(type_die);
2016         /* If it's not a compound type, return the type directly */
2017         if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
2018                 Dwarf_Word size;
2019 
2020                 if (dwarf_aggregate_size(type_die, &size) < 0)
2021                         size = 0;
2022 
2023                 if ((unsigned)offset >= size)
2024                         return NULL;
2025 
2026                 *die_mem = *type_die;
2027                 return die_mem;
2028         }
2029 
2030         mb_type = *type_die;
2031         /* TODO: Handle union types better? */
2032         while (tag == DW_TAG_structure_type || tag == DW_TAG_union_type) {
2033                 member = die_find_child(&mb_type, __die_find_member_offset_cb,
2034                                         (void *)(long)offset, die_mem);
2035                 if (member == NULL)
2036                         return NULL;
2037 
2038                 if (die_get_real_type(member, &mb_type) == NULL)
2039                         return NULL;
2040 
2041                 tag = dwarf_tag(&mb_type);
2042 
2043                 if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type) {
2044                         Dwarf_Word loc;
2045 
2046                         /* Update offset for the start of the member struct */
2047                         if (die_get_data_member_location(member, &loc) == 0)
2048                                 offset -= loc;
2049                 }
2050         }
2051         *die_mem = mb_type;
2052         return die_mem;
2053 }
2054 
2055 /**
2056  * die_deref_ptr_type - Return type info for pointer access
2057  * @ptr_die: a pointer type DIE
2058  * @offset: access offset for the pointer
2059  * @die_mem: a buffer to save the resulting DIE
2060  *
2061  * This function follows the pointer in @ptr_die with given @offset
2062  * and saves the resulting type in @die_mem.  If the pointer points
2063  * a struct type, actual member at the offset would be returned.
2064  */
2065 Dwarf_Die *die_deref_ptr_type(Dwarf_Die *ptr_die, int offset,
2066                               Dwarf_Die *die_mem)
2067 {
2068         Dwarf_Die type_die;
2069 
2070         if (dwarf_tag(ptr_die) != DW_TAG_pointer_type)
2071                 return NULL;
2072 
2073         if (die_get_real_type(ptr_die, &type_die) == NULL)
2074                 return NULL;
2075 
2076         return die_get_member_type(&type_die, offset, die_mem);
2077 }
2078 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php