1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <errno.h>
21#include <inttypes.h>
22#include <stdbool.h>
23#include <stdlib.h>
24#include "debug.h"
25#include "dwarf-aux.h"
26#include "strbuf.h"
27#include "string2.h"
28
29
30
31
32
33
34
35
36const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
37{
38 Dwarf_Files *files;
39 size_t nfiles, i;
40 const char *src = NULL;
41 int ret;
42
43 if (!fname)
44 return NULL;
45
46 ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
47 if (ret != 0)
48 return NULL;
49
50 for (i = 0; i < nfiles; i++) {
51 src = dwarf_filesrc(files, i, NULL, NULL);
52 if (strtailcmp(src, fname) == 0)
53 break;
54 }
55 if (i == nfiles)
56 return NULL;
57 return src;
58}
59
60
61
62
63
64
65
66
67
68const char *cu_get_comp_dir(Dwarf_Die *cu_die)
69{
70 Dwarf_Attribute attr;
71 if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
72 return NULL;
73 return dwarf_formstring(&attr);
74}
75
76
77static Dwarf_Line *cu_getsrc_die(Dwarf_Die *cu_die, Dwarf_Addr addr)
78{
79 Dwarf_Addr laddr;
80 Dwarf_Lines *lines;
81 Dwarf_Line *line;
82 size_t nlines, l, u, n;
83 bool flag;
84
85 if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0 ||
86 nlines == 0)
87 return NULL;
88
89
90 l = 0; u = nlines - 1;
91 while (l < u) {
92 n = u - (u - l) / 2;
93 line = dwarf_onesrcline(lines, n);
94 if (!line || dwarf_lineaddr(line, &laddr) != 0)
95 return NULL;
96 if (addr < laddr)
97 u = n - 1;
98 else
99 l = n;
100 }
101
102 do {
103 line = dwarf_onesrcline(lines, --l);
104 if (!line || dwarf_lineaddr(line, &laddr) != 0)
105 return NULL;
106 } while (laddr == addr);
107 l++;
108
109 do {
110 line = dwarf_onesrcline(lines, l++);
111 if (!line || dwarf_lineaddr(line, &laddr) != 0 ||
112 dwarf_linebeginstatement(line, &flag) != 0)
113 return NULL;
114 if (laddr > addr)
115 return NULL;
116 } while (!flag);
117
118 return line;
119}
120
121
122
123
124
125
126
127
128
129
130int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr,
131 const char **fname, int *lineno)
132{
133 Dwarf_Line *line;
134 Dwarf_Die die_mem;
135 Dwarf_Addr faddr;
136
137 if (die_find_realfunc(cu_die, (Dwarf_Addr)addr, &die_mem)
138 && die_entrypc(&die_mem, &faddr) == 0 &&
139 faddr == addr) {
140 *fname = dwarf_decl_file(&die_mem);
141 dwarf_decl_line(&die_mem, lineno);
142 goto out;
143 }
144
145 line = cu_getsrc_die(cu_die, (Dwarf_Addr)addr);
146 if (line && dwarf_lineno(line, lineno) == 0) {
147 *fname = dwarf_linesrc(line, NULL, NULL);
148 if (!*fname)
149
150 *lineno = 0;
151 }
152
153out:
154 return *lineno ?: -ENOENT;
155}
156
157static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data);
158
159
160
161
162
163
164
165
166
167
168
169int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
170 int (*callback)(Dwarf_Die *, void *), void *data)
171{
172 Dwarf_Die die_mem;
173 Dwarf_Die *sc_die;
174 int ret = -ENOENT;
175
176
177 for (sc_die = die_find_realfunc(cu_die, addr, &die_mem);
178 sc_die != NULL;
179 sc_die = die_find_child(sc_die, __die_find_inline_cb, &addr,
180 &die_mem)) {
181 ret = callback(sc_die, data);
182 if (ret)
183 break;
184 }
185
186 return ret;
187
188}
189
190
191
192
193
194
195
196
197const char *die_get_linkage_name(Dwarf_Die *dw_die)
198{
199 Dwarf_Attribute attr;
200
201 if (dwarf_attr_integrate(dw_die, DW_AT_linkage_name, &attr) == NULL)
202 return NULL;
203 return dwarf_formstring(&attr);
204}
205
206
207
208
209
210
211
212
213bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
214{
215 const char *name;
216
217 name = dwarf_diename(dw_die);
218 return name ? (strcmp(tname, name) == 0) : false;
219}
220
221
222
223
224
225
226
227
228
229bool die_match_name(Dwarf_Die *dw_die, const char *glob)
230{
231 const char *name;
232
233 name = dwarf_diename(dw_die);
234 if (name && strglobmatch(name, glob))
235 return true;
236
237 name = die_get_linkage_name(dw_die);
238 if (name && strglobmatch(name, glob))
239 return true;
240
241 return false;
242}
243
244
245
246
247
248
249
250
251int die_get_call_lineno(Dwarf_Die *in_die)
252{
253 Dwarf_Attribute attr;
254 Dwarf_Word ret;
255
256 if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
257 return -ENOENT;
258
259 dwarf_formudata(&attr, &ret);
260 return (int)ret;
261}
262
263
264
265
266
267
268
269
270
271Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
272{
273 Dwarf_Attribute attr;
274
275 if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
276 dwarf_formref_die(&attr, die_mem))
277 return die_mem;
278 else
279 return NULL;
280}
281
282
283static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
284{
285 int tag;
286
287 do {
288 vr_die = die_get_type(vr_die, die_mem);
289 if (!vr_die)
290 break;
291 tag = dwarf_tag(vr_die);
292 } while (tag == DW_TAG_const_type ||
293 tag == DW_TAG_restrict_type ||
294 tag == DW_TAG_volatile_type ||
295 tag == DW_TAG_shared_type);
296
297 return vr_die;
298}
299
300
301
302
303
304
305
306
307
308
309
310Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
311{
312 do {
313 vr_die = __die_get_real_type(vr_die, die_mem);
314 } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
315
316 return vr_die;
317}
318
319
320static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
321 Dwarf_Word *result)
322{
323 Dwarf_Attribute attr;
324
325 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
326 dwarf_formudata(&attr, result) != 0)
327 return -ENOENT;
328
329 return 0;
330}
331
332
333static int die_get_attr_sdata(Dwarf_Die *tp_die, unsigned int attr_name,
334 Dwarf_Sword *result)
335{
336 Dwarf_Attribute attr;
337
338 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
339 dwarf_formsdata(&attr, result) != 0)
340 return -ENOENT;
341
342 return 0;
343}
344
345
346
347
348
349
350
351
352bool die_is_signed_type(Dwarf_Die *tp_die)
353{
354 Dwarf_Word ret;
355
356 if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
357 return false;
358
359 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
360 ret == DW_ATE_signed_fixed);
361}
362
363
364
365
366
367
368
369
370bool die_is_func_def(Dwarf_Die *dw_die)
371{
372 Dwarf_Attribute attr;
373
374 return (dwarf_tag(dw_die) == DW_TAG_subprogram &&
375 dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL);
376}
377
378
379
380
381
382
383
384
385
386
387int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr)
388{
389 Dwarf_Addr base, end;
390
391 if (!addr)
392 return -EINVAL;
393
394 if (dwarf_entrypc(dw_die, addr) == 0)
395 return 0;
396
397 return dwarf_ranges(dw_die, 0, &base, addr, &end) < 0 ? -ENOENT : 0;
398}
399
400
401
402
403
404
405
406
407
408
409bool die_is_func_instance(Dwarf_Die *dw_die)
410{
411 Dwarf_Addr tmp;
412 Dwarf_Attribute attr_mem;
413 int tag = dwarf_tag(dw_die);
414
415 if (tag != DW_TAG_subprogram &&
416 tag != DW_TAG_inlined_subroutine)
417 return false;
418
419 return dwarf_entrypc(dw_die, &tmp) == 0 ||
420 dwarf_attr(dw_die, DW_AT_ranges, &attr_mem) != NULL;
421}
422
423
424
425
426
427
428
429
430
431int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
432{
433 Dwarf_Attribute attr;
434 Dwarf_Op *expr;
435 size_t nexpr;
436 int ret;
437
438 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
439 return -ENOENT;
440
441 if (dwarf_formudata(&attr, offs) != 0) {
442
443 ret = dwarf_getlocation(&attr, &expr, &nexpr);
444 if (ret < 0 || nexpr == 0)
445 return -ENOENT;
446
447 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
448 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
449 expr[0].atom, nexpr);
450 return -ENOTSUP;
451 }
452 *offs = (Dwarf_Word)expr[0].number;
453 }
454 return 0;
455}
456
457
458static int die_get_call_fileno(Dwarf_Die *in_die)
459{
460 Dwarf_Sword idx;
461
462 if (die_get_attr_sdata(in_die, DW_AT_call_file, &idx) == 0)
463 return (int)idx;
464 else
465 return -ENOENT;
466}
467
468
469static int die_get_decl_fileno(Dwarf_Die *pdie)
470{
471 Dwarf_Sword idx;
472
473 if (die_get_attr_sdata(pdie, DW_AT_decl_file, &idx) == 0)
474 return (int)idx;
475 else
476 return -ENOENT;
477}
478
479
480
481
482
483
484
485
486const char *die_get_call_file(Dwarf_Die *in_die)
487{
488 Dwarf_Die cu_die;
489 Dwarf_Files *files;
490 int idx;
491
492 idx = die_get_call_fileno(in_die);
493 if (idx < 0 || !dwarf_diecu(in_die, &cu_die, NULL, NULL) ||
494 dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
495 return NULL;
496
497 return dwarf_filesrc(files, idx, NULL, NULL);
498}
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
517 int (*callback)(Dwarf_Die *, void *),
518 void *data, Dwarf_Die *die_mem)
519{
520 Dwarf_Die child_die;
521 int ret;
522
523 ret = dwarf_child(rt_die, die_mem);
524 if (ret != 0)
525 return NULL;
526
527 do {
528 ret = callback(die_mem, data);
529 if (ret == DIE_FIND_CB_END)
530 return die_mem;
531
532 if ((ret & DIE_FIND_CB_CHILD) &&
533 die_find_child(die_mem, callback, data, &child_die)) {
534 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
535 return die_mem;
536 }
537 } while ((ret & DIE_FIND_CB_SIBLING) &&
538 dwarf_siblingof(die_mem, die_mem) == 0);
539
540 return NULL;
541}
542
543struct __addr_die_search_param {
544 Dwarf_Addr addr;
545 Dwarf_Die *die_mem;
546};
547
548static int __die_search_func_tail_cb(Dwarf_Die *fn_die, void *data)
549{
550 struct __addr_die_search_param *ad = data;
551 Dwarf_Addr addr = 0;
552
553 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
554 !dwarf_highpc(fn_die, &addr) &&
555 addr == ad->addr) {
556 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
557 return DWARF_CB_ABORT;
558 }
559 return DWARF_CB_OK;
560}
561
562
563
564
565
566
567
568
569
570
571
572Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
573 Dwarf_Die *die_mem)
574{
575 struct __addr_die_search_param ad;
576 ad.addr = addr;
577 ad.die_mem = die_mem;
578
579 if (!dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0))
580 return NULL;
581 else
582 return die_mem;
583}
584
585
586static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
587{
588 struct __addr_die_search_param *ad = data;
589
590
591
592
593
594 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
595 dwarf_haspc(fn_die, ad->addr)) {
596 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
597 return DWARF_CB_ABORT;
598 }
599 return DWARF_CB_OK;
600}
601
602
603
604
605
606
607
608
609
610
611Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
612 Dwarf_Die *die_mem)
613{
614 struct __addr_die_search_param ad;
615 ad.addr = addr;
616 ad.die_mem = die_mem;
617
618 if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
619 return NULL;
620 else
621 return die_mem;
622}
623
624
625static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
626{
627 Dwarf_Addr *addr = data;
628
629 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
630 dwarf_haspc(die_mem, *addr))
631 return DIE_FIND_CB_END;
632
633 return DIE_FIND_CB_CONTINUE;
634}
635
636
637
638
639
640
641
642
643
644
645
646
647Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
648 Dwarf_Die *die_mem)
649{
650 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
651}
652
653
654
655
656
657
658
659
660
661
662
663
664Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
665 Dwarf_Die *die_mem)
666{
667 Dwarf_Die tmp_die;
668
669 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
670 if (!sp_die)
671 return NULL;
672
673
674 while (sp_die) {
675 memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
676 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
677 &tmp_die);
678 }
679
680 return die_mem;
681}
682
683struct __instance_walk_param {
684 void *addr;
685 int (*callback)(Dwarf_Die *, void *);
686 void *data;
687 int retval;
688};
689
690static int __die_walk_instances_cb(Dwarf_Die *inst, void *data)
691{
692 struct __instance_walk_param *iwp = data;
693 Dwarf_Attribute attr_mem;
694 Dwarf_Die origin_mem;
695 Dwarf_Attribute *attr;
696 Dwarf_Die *origin;
697 int tmp;
698
699 if (!die_is_func_instance(inst))
700 return DIE_FIND_CB_CONTINUE;
701
702 attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem);
703 if (attr == NULL)
704 return DIE_FIND_CB_CONTINUE;
705
706 origin = dwarf_formref_die(attr, &origin_mem);
707 if (origin == NULL || origin->addr != iwp->addr)
708 return DIE_FIND_CB_CONTINUE;
709
710
711 if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) {
712 dwarf_decl_line(origin, &tmp);
713 if (die_get_call_lineno(inst) == tmp) {
714 tmp = die_get_decl_fileno(origin);
715 if (die_get_call_fileno(inst) == tmp)
716 return DIE_FIND_CB_CONTINUE;
717 }
718 }
719
720 iwp->retval = iwp->callback(inst, iwp->data);
721
722 return (iwp->retval) ? DIE_FIND_CB_END : DIE_FIND_CB_CONTINUE;
723}
724
725
726
727
728
729
730
731
732
733
734
735int die_walk_instances(Dwarf_Die *or_die, int (*callback)(Dwarf_Die *, void *),
736 void *data)
737{
738 Dwarf_Die cu_die;
739 Dwarf_Die die_mem;
740 struct __instance_walk_param iwp = {
741 .addr = or_die->addr,
742 .callback = callback,
743 .data = data,
744 .retval = -ENOENT,
745 };
746
747 if (dwarf_diecu(or_die, &cu_die, NULL, NULL) == NULL)
748 return -ENOENT;
749
750 die_find_child(&cu_die, __die_walk_instances_cb, &iwp, &die_mem);
751
752 return iwp.retval;
753}
754
755
756struct __line_walk_param {
757 bool recursive;
758 line_walk_callback_t callback;
759 void *data;
760 int retval;
761};
762
763static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
764{
765 struct __line_walk_param *lw = data;
766 Dwarf_Addr addr = 0;
767 const char *fname;
768 int lineno;
769
770 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
771 fname = die_get_call_file(in_die);
772 lineno = die_get_call_lineno(in_die);
773 if (fname && lineno > 0 && die_entrypc(in_die, &addr) == 0) {
774 lw->retval = lw->callback(fname, lineno, addr, lw->data);
775 if (lw->retval != 0)
776 return DIE_FIND_CB_END;
777 }
778 if (!lw->recursive)
779 return DIE_FIND_CB_SIBLING;
780 }
781
782 if (addr) {
783 fname = dwarf_decl_file(in_die);
784 if (fname && dwarf_decl_line(in_die, &lineno) == 0) {
785 lw->retval = lw->callback(fname, lineno, addr, lw->data);
786 if (lw->retval != 0)
787 return DIE_FIND_CB_END;
788 }
789 }
790
791
792 return DIE_FIND_CB_CONTINUE;
793}
794
795
796static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive,
797 line_walk_callback_t callback, void *data)
798{
799 struct __line_walk_param lw = {
800 .recursive = recursive,
801 .callback = callback,
802 .data = data,
803 .retval = 0,
804 };
805 Dwarf_Die die_mem;
806 Dwarf_Addr addr;
807 const char *fname;
808 int lineno;
809
810
811 fname = dwarf_decl_file(sp_die);
812 if (fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
813 die_entrypc(sp_die, &addr) == 0) {
814 lw.retval = callback(fname, lineno, addr, data);
815 if (lw.retval != 0)
816 goto done;
817 }
818 die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
819done:
820 return lw.retval;
821}
822
823static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
824{
825 struct __line_walk_param *lw = data;
826
827
828
829
830
831 lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data);
832 if (lw->retval != 0)
833 return DWARF_CB_ABORT;
834
835 return DWARF_CB_OK;
836}
837
838
839
840
841
842
843
844
845
846
847
848
849
850int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
851{
852 Dwarf_Lines *lines;
853 Dwarf_Line *line;
854 Dwarf_Addr addr;
855 const char *fname, *decf = NULL, *inf = NULL;
856 int lineno, ret = 0;
857 int decl = 0, inl;
858 Dwarf_Die die_mem, *cu_die;
859 size_t nlines, i;
860 bool flag;
861
862
863 if (dwarf_tag(rt_die) != DW_TAG_compile_unit) {
864 cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
865 dwarf_decl_line(rt_die, &decl);
866 decf = dwarf_decl_file(rt_die);
867 } else
868 cu_die = rt_die;
869 if (!cu_die) {
870 pr_debug2("Failed to get CU from given DIE.\n");
871 return -EINVAL;
872 }
873
874
875 if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
876 pr_debug2("Failed to get source lines on this CU.\n");
877 return -ENOENT;
878 }
879 pr_debug2("Get %zd lines from this CU\n", nlines);
880
881
882 for (i = 0; i < nlines; i++) {
883 line = dwarf_onesrcline(lines, i);
884 if (line == NULL ||
885 dwarf_lineno(line, &lineno) != 0 ||
886 dwarf_lineaddr(line, &addr) != 0) {
887 pr_debug2("Failed to get line info. "
888 "Possible error in debuginfo.\n");
889 continue;
890 }
891
892 if (dwarf_lineendsequence(line, &flag) != 0 || flag)
893 continue;
894
895 if (dwarf_linebeginstatement(line, &flag) != 0 || !flag)
896 continue;
897
898 if (rt_die != cu_die) {
899
900
901
902
903
904 if (!dwarf_haspc(rt_die, addr))
905 continue;
906
907 if (die_find_inlinefunc(rt_die, addr, &die_mem)) {
908
909 inf = die_get_call_file(&die_mem);
910 if ((inf && !strcmp(inf, decf)) &&
911 die_get_call_lineno(&die_mem) == lineno)
912 goto found;
913
914 dwarf_decl_line(&die_mem, &inl);
915 if (inl != decl ||
916 decf != dwarf_decl_file(&die_mem))
917 continue;
918 }
919 }
920found:
921
922 fname = dwarf_linesrc(line, NULL, NULL);
923
924 ret = callback(fname, lineno, addr, data);
925 if (ret != 0)
926 return ret;
927 }
928
929
930
931
932
933 if (rt_die != cu_die)
934
935
936
937
938
939 ret = __die_walk_funclines(rt_die, false, callback, data);
940 else {
941 struct __line_walk_param param = {
942 .callback = callback,
943 .data = data,
944 .retval = 0,
945 };
946 dwarf_getfuncs(cu_die, __die_walk_culines_cb, ¶m, 0);
947 ret = param.retval;
948 }
949
950 return ret;
951}
952
953struct __find_variable_param {
954 const char *name;
955 Dwarf_Addr addr;
956};
957
958static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
959{
960 struct __find_variable_param *fvp = data;
961 Dwarf_Attribute attr;
962 int tag;
963
964 tag = dwarf_tag(die_mem);
965 if ((tag == DW_TAG_formal_parameter ||
966 tag == DW_TAG_variable) &&
967 die_compare_name(die_mem, fvp->name) &&
968
969 (dwarf_attr(die_mem, DW_AT_external, &attr) ||
970 dwarf_attr(die_mem, DW_AT_location, &attr)))
971 return DIE_FIND_CB_END;
972 if (dwarf_haspc(die_mem, fvp->addr))
973 return DIE_FIND_CB_CONTINUE;
974 else
975 return DIE_FIND_CB_SIBLING;
976}
977
978
979
980
981
982
983
984
985
986
987Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
988 Dwarf_Addr addr, Dwarf_Die *die_mem)
989{
990 struct __find_variable_param fvp = { .name = name, .addr = addr};
991
992 return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
993 die_mem);
994}
995
996static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
997{
998 const char *name = data;
999
1000 if (dwarf_tag(die_mem) == DW_TAG_member) {
1001 if (die_compare_name(die_mem, name))
1002 return DIE_FIND_CB_END;
1003 else if (!dwarf_diename(die_mem)) {
1004 Dwarf_Die type_die, tmp_die;
1005 if (die_get_type(die_mem, &type_die) &&
1006 die_find_member(&type_die, name, &tmp_die))
1007 return DIE_FIND_CB_END;
1008 }
1009 }
1010 return DIE_FIND_CB_SIBLING;
1011}
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
1022 Dwarf_Die *die_mem)
1023{
1024 return die_find_child(st_die, __die_find_member_cb, (void *)name,
1025 die_mem);
1026}
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
1039{
1040 Dwarf_Die type;
1041 int tag, ret;
1042 const char *tmp = "";
1043
1044 if (__die_get_real_type(vr_die, &type) == NULL)
1045 return -ENOENT;
1046
1047 tag = dwarf_tag(&type);
1048 if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
1049 tmp = "*";
1050 else if (tag == DW_TAG_subroutine_type) {
1051
1052 return strbuf_add(buf, "(function_type)", 15);
1053 } else {
1054 if (!dwarf_diename(&type))
1055 return -ENOENT;
1056 if (tag == DW_TAG_union_type)
1057 tmp = "union ";
1058 else if (tag == DW_TAG_structure_type)
1059 tmp = "struct ";
1060 else if (tag == DW_TAG_enumeration_type)
1061 tmp = "enum ";
1062
1063 return strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type));
1064 }
1065 ret = die_get_typename(&type, buf);
1066 return ret ? ret : strbuf_addstr(buf, tmp);
1067}
1068
1069
1070
1071
1072
1073
1074
1075
1076int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
1077{
1078 int ret;
1079
1080 ret = die_get_typename(vr_die, buf);
1081 if (ret < 0) {
1082 pr_debug("Failed to get type, make it unknown.\n");
1083 ret = strbuf_add(buf, " (unknown_type)", 14);
1084 }
1085
1086 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
1087}
1088
1089#ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die,
1100 struct strbuf *buf)
1101{
1102 Dwarf_Die *scopes;
1103 int count;
1104 size_t offset = 0;
1105 Dwarf_Addr base;
1106 Dwarf_Addr start, end;
1107 Dwarf_Addr entry;
1108 int ret;
1109 bool first = true;
1110 const char *name;
1111
1112 ret = die_entrypc(sp_die, &entry);
1113 if (ret)
1114 return ret;
1115
1116 name = dwarf_diename(sp_die);
1117 if (!name)
1118 return -ENOENT;
1119
1120 count = dwarf_getscopes_die(vr_die, &scopes);
1121
1122
1123 if (count <= 1) {
1124 ret = -EINVAL;
1125 goto out;
1126 }
1127
1128 while ((offset = dwarf_ranges(&scopes[1], offset, &base,
1129 &start, &end)) > 0) {
1130 start -= entry;
1131 end -= entry;
1132
1133 if (first) {
1134 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1135 name, start, end);
1136 first = false;
1137 } else {
1138 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1139 start, end);
1140 }
1141 if (ret < 0)
1142 goto out;
1143 }
1144
1145 if (!first)
1146 ret = strbuf_add(buf, "]>", 2);
1147
1148out:
1149 free(scopes);
1150 return ret;
1151}
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf)
1163{
1164 int ret = 0;
1165 Dwarf_Addr base;
1166 Dwarf_Addr start, end;
1167 Dwarf_Addr entry;
1168 Dwarf_Op *op;
1169 size_t nops;
1170 size_t offset = 0;
1171 Dwarf_Attribute attr;
1172 bool first = true;
1173 const char *name;
1174
1175 ret = die_entrypc(sp_die, &entry);
1176 if (ret)
1177 return ret;
1178
1179 name = dwarf_diename(sp_die);
1180 if (!name)
1181 return -ENOENT;
1182
1183 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
1184 return -EINVAL;
1185
1186 while ((offset = dwarf_getlocations(&attr, offset, &base,
1187 &start, &end, &op, &nops)) > 0) {
1188 if (start == 0) {
1189
1190 ret = die_get_var_innermost_scope(sp_die, vr_die, buf);
1191 goto out;
1192 }
1193
1194
1195 start -= entry;
1196 end -= entry;
1197 if (first) {
1198 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1199 name, start, end);
1200 first = false;
1201 } else {
1202 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1203 start, end);
1204 }
1205 if (ret < 0)
1206 goto out;
1207 }
1208
1209 if (!first)
1210 ret = strbuf_add(buf, "]>", 2);
1211out:
1212 return ret;
1213}
1214#else
1215int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
1216 Dwarf_Die *vr_die __maybe_unused,
1217 struct strbuf *buf __maybe_unused)
1218{
1219 return -ENOTSUP;
1220}
1221#endif
1222
1223
1224
1225
1226
1227static bool die_has_loclist(Dwarf_Die *vr_die)
1228{
1229 Dwarf_Attribute loc;
1230 int tag = dwarf_tag(vr_die);
1231
1232 if (tag != DW_TAG_formal_parameter &&
1233 tag != DW_TAG_variable)
1234 return false;
1235
1236 return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
1237 dwarf_whatform(&loc) == DW_FORM_sec_offset);
1238}
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249bool die_is_optimized_target(Dwarf_Die *cu_die)
1250{
1251 Dwarf_Die tmp_die;
1252
1253 if (die_has_loclist(cu_die))
1254 return true;
1255
1256 if (!dwarf_child(cu_die, &tmp_die) &&
1257 die_is_optimized_target(&tmp_die))
1258 return true;
1259
1260 if (!dwarf_siblingof(cu_die, &tmp_die) &&
1261 die_is_optimized_target(&tmp_die))
1262 return true;
1263
1264 return false;
1265}
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
1280 Dwarf_Addr addr, unsigned long *idx)
1281{
1282 unsigned long i;
1283 Dwarf_Addr tmp;
1284
1285 for (i = 0; i < nr_lines; i++) {
1286 if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
1287 return false;
1288
1289 if (tmp == addr) {
1290 *idx = i;
1291 return true;
1292 }
1293 }
1294 return false;
1295}
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308static bool die_get_postprologue_addr(unsigned long entrypc_idx,
1309 Dwarf_Lines *lines,
1310 unsigned long nr_lines,
1311 Dwarf_Addr highpc,
1312 Dwarf_Addr *postprologue_addr)
1313{
1314 unsigned long i;
1315 int entrypc_lno, lno;
1316 Dwarf_Line *line;
1317 Dwarf_Addr addr;
1318 bool p_end;
1319
1320
1321 line = dwarf_onesrcline(lines, entrypc_idx);
1322 if (dwarf_lineno(line, &entrypc_lno))
1323 return false;
1324
1325 for (i = entrypc_idx; i < nr_lines; i++) {
1326 line = dwarf_onesrcline(lines, i);
1327
1328 if (dwarf_lineaddr(line, &addr) ||
1329 dwarf_lineno(line, &lno) ||
1330 dwarf_lineprologueend(line, &p_end))
1331 return false;
1332
1333
1334 if (addr >= highpc)
1335 break;
1336
1337
1338 if (p_end)
1339 break;
1340
1341
1342 if (lno != entrypc_lno)
1343 break;
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353 if (i != entrypc_idx)
1354 break;
1355 }
1356
1357 dwarf_lineaddr(line, postprologue_addr);
1358 if (*postprologue_addr >= highpc)
1359 dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
1360 postprologue_addr);
1361
1362 return true;
1363}
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
1378 Dwarf_Addr *entrypc)
1379{
1380 size_t nr_lines = 0;
1381 unsigned long entrypc_idx = 0;
1382 Dwarf_Lines *lines = NULL;
1383 Dwarf_Addr postprologue_addr;
1384 Dwarf_Addr highpc;
1385
1386 if (dwarf_highpc(sp_die, &highpc))
1387 return;
1388
1389 if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
1390 return;
1391
1392 if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
1393 return;
1394
1395 if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
1396 highpc, &postprologue_addr))
1397 return;
1398
1399 *entrypc = postprologue_addr;
1400}
1401