0001
0002
0003
0004
0005
0006 #include <errno.h>
0007 #include <inttypes.h>
0008 #include <stdbool.h>
0009 #include <stdlib.h>
0010 #include "debug.h"
0011 #include "dwarf-aux.h"
0012 #include "strbuf.h"
0013 #include "string2.h"
0014
0015
0016
0017
0018
0019
0020
0021
0022 const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
0023 {
0024 Dwarf_Files *files;
0025 size_t nfiles, i;
0026 const char *src = NULL;
0027 int ret;
0028
0029 if (!fname)
0030 return NULL;
0031
0032 ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
0033 if (ret != 0)
0034 return NULL;
0035
0036 for (i = 0; i < nfiles; i++) {
0037 src = dwarf_filesrc(files, i, NULL, NULL);
0038 if (strtailcmp(src, fname) == 0)
0039 break;
0040 }
0041 if (i == nfiles)
0042 return NULL;
0043 return src;
0044 }
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 const char *cu_get_comp_dir(Dwarf_Die *cu_die)
0055 {
0056 Dwarf_Attribute attr;
0057 if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
0058 return NULL;
0059 return dwarf_formstring(&attr);
0060 }
0061
0062
0063 static Dwarf_Line *cu_getsrc_die(Dwarf_Die *cu_die, Dwarf_Addr addr)
0064 {
0065 Dwarf_Addr laddr;
0066 Dwarf_Lines *lines;
0067 Dwarf_Line *line;
0068 size_t nlines, l, u, n;
0069 bool flag;
0070
0071 if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0 ||
0072 nlines == 0)
0073 return NULL;
0074
0075
0076 l = 0; u = nlines - 1;
0077 while (l < u) {
0078 n = u - (u - l) / 2;
0079 line = dwarf_onesrcline(lines, n);
0080 if (!line || dwarf_lineaddr(line, &laddr) != 0)
0081 return NULL;
0082 if (addr < laddr)
0083 u = n - 1;
0084 else
0085 l = n;
0086 }
0087
0088 do {
0089 line = dwarf_onesrcline(lines, --l);
0090 if (!line || dwarf_lineaddr(line, &laddr) != 0)
0091 return NULL;
0092 } while (laddr == addr);
0093 l++;
0094
0095 do {
0096 line = dwarf_onesrcline(lines, l++);
0097 if (!line || dwarf_lineaddr(line, &laddr) != 0 ||
0098 dwarf_linebeginstatement(line, &flag) != 0)
0099 return NULL;
0100 if (laddr > addr)
0101 return NULL;
0102 } while (!flag);
0103
0104 return line;
0105 }
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116 int cu_find_lineinfo(Dwarf_Die *cu_die, Dwarf_Addr addr,
0117 const char **fname, int *lineno)
0118 {
0119 Dwarf_Line *line;
0120 Dwarf_Die die_mem;
0121 Dwarf_Addr faddr;
0122
0123 if (die_find_realfunc(cu_die, addr, &die_mem)
0124 && die_entrypc(&die_mem, &faddr) == 0 &&
0125 faddr == addr) {
0126 *fname = dwarf_decl_file(&die_mem);
0127 dwarf_decl_line(&die_mem, lineno);
0128 goto out;
0129 }
0130
0131 line = cu_getsrc_die(cu_die, addr);
0132 if (line && dwarf_lineno(line, lineno) == 0) {
0133 *fname = dwarf_linesrc(line, NULL, NULL);
0134 if (!*fname)
0135
0136 *lineno = 0;
0137 }
0138
0139 out:
0140 return *lineno ?: -ENOENT;
0141 }
0142
0143 static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data);
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
0156 int (*callback)(Dwarf_Die *, void *), void *data)
0157 {
0158 Dwarf_Die die_mem;
0159 Dwarf_Die *sc_die;
0160 int ret = -ENOENT;
0161
0162
0163 for (sc_die = die_find_realfunc(cu_die, addr, &die_mem);
0164 sc_die != NULL;
0165 sc_die = die_find_child(sc_die, __die_find_inline_cb, &addr,
0166 &die_mem)) {
0167 ret = callback(sc_die, data);
0168 if (ret)
0169 break;
0170 }
0171
0172 return ret;
0173
0174 }
0175
0176
0177
0178
0179
0180
0181
0182
0183 const char *die_get_linkage_name(Dwarf_Die *dw_die)
0184 {
0185 Dwarf_Attribute attr;
0186
0187 if (dwarf_attr_integrate(dw_die, DW_AT_linkage_name, &attr) == NULL)
0188 return NULL;
0189 return dwarf_formstring(&attr);
0190 }
0191
0192
0193
0194
0195
0196
0197
0198
0199 bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
0200 {
0201 const char *name;
0202
0203 name = dwarf_diename(dw_die);
0204 return name ? (strcmp(tname, name) == 0) : false;
0205 }
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 bool die_match_name(Dwarf_Die *dw_die, const char *glob)
0216 {
0217 const char *name;
0218
0219 name = dwarf_diename(dw_die);
0220 if (name && strglobmatch(name, glob))
0221 return true;
0222
0223 name = die_get_linkage_name(dw_die);
0224 if (name && strglobmatch(name, glob))
0225 return true;
0226
0227 return false;
0228 }
0229
0230
0231
0232
0233
0234
0235
0236
0237 int die_get_call_lineno(Dwarf_Die *in_die)
0238 {
0239 Dwarf_Attribute attr;
0240 Dwarf_Word ret;
0241
0242 if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
0243 return -ENOENT;
0244
0245 dwarf_formudata(&attr, &ret);
0246 return (int)ret;
0247 }
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
0258 {
0259 Dwarf_Attribute attr;
0260
0261 if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
0262 dwarf_formref_die(&attr, die_mem))
0263 return die_mem;
0264 else
0265 return NULL;
0266 }
0267
0268
0269 static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
0270 {
0271 int tag;
0272
0273 do {
0274 vr_die = die_get_type(vr_die, die_mem);
0275 if (!vr_die)
0276 break;
0277 tag = dwarf_tag(vr_die);
0278 } while (tag == DW_TAG_const_type ||
0279 tag == DW_TAG_restrict_type ||
0280 tag == DW_TAG_volatile_type ||
0281 tag == DW_TAG_shared_type);
0282
0283 return vr_die;
0284 }
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296 Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
0297 {
0298 do {
0299 vr_die = __die_get_real_type(vr_die, die_mem);
0300 } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
0301
0302 return vr_die;
0303 }
0304
0305
0306 static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
0307 Dwarf_Word *result)
0308 {
0309 Dwarf_Attribute attr;
0310
0311 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
0312 dwarf_formudata(&attr, result) != 0)
0313 return -ENOENT;
0314
0315 return 0;
0316 }
0317
0318
0319 static int die_get_attr_sdata(Dwarf_Die *tp_die, unsigned int attr_name,
0320 Dwarf_Sword *result)
0321 {
0322 Dwarf_Attribute attr;
0323
0324 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
0325 dwarf_formsdata(&attr, result) != 0)
0326 return -ENOENT;
0327
0328 return 0;
0329 }
0330
0331
0332
0333
0334
0335
0336
0337
0338 bool die_is_signed_type(Dwarf_Die *tp_die)
0339 {
0340 Dwarf_Word ret;
0341
0342 if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
0343 return false;
0344
0345 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
0346 ret == DW_ATE_signed_fixed);
0347 }
0348
0349
0350
0351
0352
0353
0354
0355
0356 bool die_is_func_def(Dwarf_Die *dw_die)
0357 {
0358 Dwarf_Attribute attr;
0359 Dwarf_Addr addr = 0;
0360
0361 if (dwarf_tag(dw_die) != DW_TAG_subprogram)
0362 return false;
0363
0364 if (dwarf_attr(dw_die, DW_AT_declaration, &attr))
0365 return false;
0366
0367
0368
0369
0370
0371
0372
0373 if (!dwarf_attr(dw_die, DW_AT_inline, &attr) &&
0374 die_entrypc(dw_die, &addr) < 0)
0375 return false;
0376
0377 return true;
0378 }
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389 int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr)
0390 {
0391 Dwarf_Addr base, end;
0392 Dwarf_Attribute attr;
0393
0394 if (!addr)
0395 return -EINVAL;
0396
0397 if (dwarf_entrypc(dw_die, addr) == 0)
0398 return 0;
0399
0400
0401
0402
0403
0404 if (!dwarf_attr(dw_die, DW_AT_ranges, &attr))
0405 return -ENOENT;
0406
0407 return dwarf_ranges(dw_die, 0, &base, addr, &end) < 0 ? -ENOENT : 0;
0408 }
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419 bool die_is_func_instance(Dwarf_Die *dw_die)
0420 {
0421 Dwarf_Addr tmp;
0422 Dwarf_Attribute attr_mem;
0423 int tag = dwarf_tag(dw_die);
0424
0425 if (tag != DW_TAG_subprogram &&
0426 tag != DW_TAG_inlined_subroutine)
0427 return false;
0428
0429 return dwarf_entrypc(dw_die, &tmp) == 0 ||
0430 dwarf_attr(dw_die, DW_AT_ranges, &attr_mem) != NULL;
0431 }
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441 int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
0442 {
0443 Dwarf_Attribute attr;
0444 Dwarf_Op *expr;
0445 size_t nexpr;
0446 int ret;
0447
0448 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
0449 return -ENOENT;
0450
0451 if (dwarf_formudata(&attr, offs) != 0) {
0452
0453 ret = dwarf_getlocation(&attr, &expr, &nexpr);
0454 if (ret < 0 || nexpr == 0)
0455 return -ENOENT;
0456
0457 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
0458 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
0459 expr[0].atom, nexpr);
0460 return -ENOTSUP;
0461 }
0462 *offs = (Dwarf_Word)expr[0].number;
0463 }
0464 return 0;
0465 }
0466
0467
0468 static int die_get_call_fileno(Dwarf_Die *in_die)
0469 {
0470 Dwarf_Sword idx;
0471
0472 if (die_get_attr_sdata(in_die, DW_AT_call_file, &idx) == 0)
0473 return (int)idx;
0474 else
0475 return -ENOENT;
0476 }
0477
0478
0479 static int die_get_decl_fileno(Dwarf_Die *pdie)
0480 {
0481 Dwarf_Sword idx;
0482
0483 if (die_get_attr_sdata(pdie, DW_AT_decl_file, &idx) == 0)
0484 return (int)idx;
0485 else
0486 return -ENOENT;
0487 }
0488
0489
0490
0491
0492
0493
0494
0495
0496 const char *die_get_call_file(Dwarf_Die *in_die)
0497 {
0498 Dwarf_Die cu_die;
0499 Dwarf_Files *files;
0500 int idx;
0501
0502 idx = die_get_call_fileno(in_die);
0503 if (idx < 0 || !dwarf_diecu(in_die, &cu_die, NULL, NULL) ||
0504 dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
0505 return NULL;
0506
0507 return dwarf_filesrc(files, idx, NULL, NULL);
0508 }
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526 Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
0527 int (*callback)(Dwarf_Die *, void *),
0528 void *data, Dwarf_Die *die_mem)
0529 {
0530 Dwarf_Die child_die;
0531 int ret;
0532
0533 ret = dwarf_child(rt_die, die_mem);
0534 if (ret != 0)
0535 return NULL;
0536
0537 do {
0538 ret = callback(die_mem, data);
0539 if (ret == DIE_FIND_CB_END)
0540 return die_mem;
0541
0542 if ((ret & DIE_FIND_CB_CHILD) &&
0543 die_find_child(die_mem, callback, data, &child_die)) {
0544 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
0545 return die_mem;
0546 }
0547 } while ((ret & DIE_FIND_CB_SIBLING) &&
0548 dwarf_siblingof(die_mem, die_mem) == 0);
0549
0550 return NULL;
0551 }
0552
0553 struct __addr_die_search_param {
0554 Dwarf_Addr addr;
0555 Dwarf_Die *die_mem;
0556 };
0557
0558 static int __die_search_func_tail_cb(Dwarf_Die *fn_die, void *data)
0559 {
0560 struct __addr_die_search_param *ad = data;
0561 Dwarf_Addr addr = 0;
0562
0563 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
0564 !dwarf_highpc(fn_die, &addr) &&
0565 addr == ad->addr) {
0566 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
0567 return DWARF_CB_ABORT;
0568 }
0569 return DWARF_CB_OK;
0570 }
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582 Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
0583 Dwarf_Die *die_mem)
0584 {
0585 struct __addr_die_search_param ad;
0586 ad.addr = addr;
0587 ad.die_mem = die_mem;
0588
0589 if (!dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0))
0590 return NULL;
0591 else
0592 return die_mem;
0593 }
0594
0595
0596 static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
0597 {
0598 struct __addr_die_search_param *ad = data;
0599
0600
0601
0602
0603
0604 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
0605 dwarf_haspc(fn_die, ad->addr)) {
0606 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
0607 return DWARF_CB_ABORT;
0608 }
0609 return DWARF_CB_OK;
0610 }
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621 Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
0622 Dwarf_Die *die_mem)
0623 {
0624 struct __addr_die_search_param ad;
0625 ad.addr = addr;
0626 ad.die_mem = die_mem;
0627
0628 if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
0629 return NULL;
0630 else
0631 return die_mem;
0632 }
0633
0634
0635 static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
0636 {
0637 Dwarf_Addr *addr = data;
0638
0639 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
0640 dwarf_haspc(die_mem, *addr))
0641 return DIE_FIND_CB_END;
0642
0643 return DIE_FIND_CB_CONTINUE;
0644 }
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657 Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
0658 Dwarf_Die *die_mem)
0659 {
0660 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
0661 }
0662
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674 Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
0675 Dwarf_Die *die_mem)
0676 {
0677 Dwarf_Die tmp_die;
0678
0679 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
0680 if (!sp_die)
0681 return NULL;
0682
0683
0684 while (sp_die) {
0685 memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
0686 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
0687 &tmp_die);
0688 }
0689
0690 return die_mem;
0691 }
0692
0693 struct __instance_walk_param {
0694 void *addr;
0695 int (*callback)(Dwarf_Die *, void *);
0696 void *data;
0697 int retval;
0698 };
0699
0700 static int __die_walk_instances_cb(Dwarf_Die *inst, void *data)
0701 {
0702 struct __instance_walk_param *iwp = data;
0703 Dwarf_Attribute attr_mem;
0704 Dwarf_Die origin_mem;
0705 Dwarf_Attribute *attr;
0706 Dwarf_Die *origin;
0707 int tmp;
0708
0709 if (!die_is_func_instance(inst))
0710 return DIE_FIND_CB_CONTINUE;
0711
0712 attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem);
0713 if (attr == NULL)
0714 return DIE_FIND_CB_CONTINUE;
0715
0716 origin = dwarf_formref_die(attr, &origin_mem);
0717 if (origin == NULL || origin->addr != iwp->addr)
0718 return DIE_FIND_CB_CONTINUE;
0719
0720
0721 if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) {
0722 dwarf_decl_line(origin, &tmp);
0723 if (die_get_call_lineno(inst) == tmp) {
0724 tmp = die_get_decl_fileno(origin);
0725 if (die_get_call_fileno(inst) == tmp)
0726 return DIE_FIND_CB_CONTINUE;
0727 }
0728 }
0729
0730 iwp->retval = iwp->callback(inst, iwp->data);
0731
0732 return (iwp->retval) ? DIE_FIND_CB_END : DIE_FIND_CB_CONTINUE;
0733 }
0734
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745 int die_walk_instances(Dwarf_Die *or_die, int (*callback)(Dwarf_Die *, void *),
0746 void *data)
0747 {
0748 Dwarf_Die cu_die;
0749 Dwarf_Die die_mem;
0750 struct __instance_walk_param iwp = {
0751 .addr = or_die->addr,
0752 .callback = callback,
0753 .data = data,
0754 .retval = -ENOENT,
0755 };
0756
0757 if (dwarf_diecu(or_die, &cu_die, NULL, NULL) == NULL)
0758 return -ENOENT;
0759
0760 die_find_child(&cu_die, __die_walk_instances_cb, &iwp, &die_mem);
0761
0762 return iwp.retval;
0763 }
0764
0765
0766 struct __line_walk_param {
0767 bool recursive;
0768 line_walk_callback_t callback;
0769 void *data;
0770 int retval;
0771 };
0772
0773 static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
0774 {
0775 struct __line_walk_param *lw = data;
0776 Dwarf_Addr addr = 0;
0777 const char *fname;
0778 int lineno;
0779
0780 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
0781 fname = die_get_call_file(in_die);
0782 lineno = die_get_call_lineno(in_die);
0783 if (fname && lineno > 0 && die_entrypc(in_die, &addr) == 0) {
0784 lw->retval = lw->callback(fname, lineno, addr, lw->data);
0785 if (lw->retval != 0)
0786 return DIE_FIND_CB_END;
0787 }
0788 if (!lw->recursive)
0789 return DIE_FIND_CB_SIBLING;
0790 }
0791
0792 if (addr) {
0793 fname = dwarf_decl_file(in_die);
0794 if (fname && dwarf_decl_line(in_die, &lineno) == 0) {
0795 lw->retval = lw->callback(fname, lineno, addr, lw->data);
0796 if (lw->retval != 0)
0797 return DIE_FIND_CB_END;
0798 }
0799 }
0800
0801
0802 return DIE_FIND_CB_CONTINUE;
0803 }
0804
0805
0806 static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive,
0807 line_walk_callback_t callback, void *data)
0808 {
0809 struct __line_walk_param lw = {
0810 .recursive = recursive,
0811 .callback = callback,
0812 .data = data,
0813 .retval = 0,
0814 };
0815 Dwarf_Die die_mem;
0816 Dwarf_Addr addr;
0817 const char *fname;
0818 int lineno;
0819
0820
0821 fname = dwarf_decl_file(sp_die);
0822 if (fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
0823 die_entrypc(sp_die, &addr) == 0) {
0824 lw.retval = callback(fname, lineno, addr, data);
0825 if (lw.retval != 0)
0826 goto done;
0827 }
0828 die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
0829 done:
0830 return lw.retval;
0831 }
0832
0833 static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
0834 {
0835 struct __line_walk_param *lw = data;
0836
0837
0838
0839
0840
0841 lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data);
0842 if (lw->retval != 0)
0843 return DWARF_CB_ABORT;
0844
0845 return DWARF_CB_OK;
0846 }
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860 int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
0861 {
0862 Dwarf_Lines *lines;
0863 Dwarf_Line *line;
0864 Dwarf_Addr addr;
0865 const char *fname, *decf = NULL, *inf = NULL;
0866 int lineno, ret = 0;
0867 int decl = 0, inl;
0868 Dwarf_Die die_mem, *cu_die;
0869 size_t nlines, i;
0870 bool flag;
0871
0872
0873 if (dwarf_tag(rt_die) != DW_TAG_compile_unit) {
0874 cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
0875 dwarf_decl_line(rt_die, &decl);
0876 decf = dwarf_decl_file(rt_die);
0877 } else
0878 cu_die = rt_die;
0879 if (!cu_die) {
0880 pr_debug2("Failed to get CU from given DIE.\n");
0881 return -EINVAL;
0882 }
0883
0884
0885 if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
0886 pr_debug2("Failed to get source lines on this CU.\n");
0887 return -ENOENT;
0888 }
0889 pr_debug2("Get %zd lines from this CU\n", nlines);
0890
0891
0892 for (i = 0; i < nlines; i++) {
0893 line = dwarf_onesrcline(lines, i);
0894 if (line == NULL ||
0895 dwarf_lineno(line, &lineno) != 0 ||
0896 dwarf_lineaddr(line, &addr) != 0) {
0897 pr_debug2("Failed to get line info. "
0898 "Possible error in debuginfo.\n");
0899 continue;
0900 }
0901
0902 if (dwarf_lineendsequence(line, &flag) != 0 || flag)
0903 continue;
0904
0905 if (dwarf_linebeginstatement(line, &flag) != 0 || !flag)
0906 continue;
0907
0908 if (rt_die != cu_die) {
0909
0910
0911
0912
0913
0914 if (!dwarf_haspc(rt_die, addr))
0915 continue;
0916
0917 if (die_find_inlinefunc(rt_die, addr, &die_mem)) {
0918
0919 inf = die_get_call_file(&die_mem);
0920 if ((inf && !strcmp(inf, decf)) &&
0921 die_get_call_lineno(&die_mem) == lineno)
0922 goto found;
0923
0924 dwarf_decl_line(&die_mem, &inl);
0925 if (inl != decl ||
0926 decf != dwarf_decl_file(&die_mem))
0927 continue;
0928 }
0929 }
0930 found:
0931
0932 fname = dwarf_linesrc(line, NULL, NULL);
0933
0934 ret = callback(fname, lineno, addr, data);
0935 if (ret != 0)
0936 return ret;
0937 }
0938
0939
0940
0941
0942
0943 if (rt_die != cu_die)
0944
0945
0946
0947
0948
0949 ret = __die_walk_funclines(rt_die, false, callback, data);
0950 else {
0951 struct __line_walk_param param = {
0952 .callback = callback,
0953 .data = data,
0954 .retval = 0,
0955 };
0956 dwarf_getfuncs(cu_die, __die_walk_culines_cb, ¶m, 0);
0957 ret = param.retval;
0958 }
0959
0960 return ret;
0961 }
0962
0963 struct __find_variable_param {
0964 const char *name;
0965 Dwarf_Addr addr;
0966 };
0967
0968 static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
0969 {
0970 struct __find_variable_param *fvp = data;
0971 Dwarf_Attribute attr;
0972 int tag;
0973
0974 tag = dwarf_tag(die_mem);
0975 if ((tag == DW_TAG_formal_parameter ||
0976 tag == DW_TAG_variable) &&
0977 die_compare_name(die_mem, fvp->name) &&
0978
0979
0980
0981
0982 (dwarf_attr(die_mem, DW_AT_external, &attr) ||
0983 dwarf_attr(die_mem, DW_AT_location, &attr) ||
0984 dwarf_attr(die_mem, DW_AT_const_value, &attr)))
0985 return DIE_FIND_CB_END;
0986 if (dwarf_haspc(die_mem, fvp->addr))
0987 return DIE_FIND_CB_CONTINUE;
0988 else
0989 return DIE_FIND_CB_SIBLING;
0990 }
0991
0992
0993
0994
0995
0996
0997
0998
0999
1000
1001 Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
1002 Dwarf_Addr addr, Dwarf_Die *die_mem)
1003 {
1004 struct __find_variable_param fvp = { .name = name, .addr = addr};
1005
1006 return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
1007 die_mem);
1008 }
1009
1010 static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
1011 {
1012 const char *name = data;
1013
1014 if (dwarf_tag(die_mem) == DW_TAG_member) {
1015 if (die_compare_name(die_mem, name))
1016 return DIE_FIND_CB_END;
1017 else if (!dwarf_diename(die_mem)) {
1018 Dwarf_Die type_die, tmp_die;
1019 if (die_get_type(die_mem, &type_die) &&
1020 die_find_member(&type_die, name, &tmp_die))
1021 return DIE_FIND_CB_END;
1022 }
1023 }
1024 return DIE_FIND_CB_SIBLING;
1025 }
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035 Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
1036 Dwarf_Die *die_mem)
1037 {
1038 return die_find_child(st_die, __die_find_member_cb, (void *)name,
1039 die_mem);
1040 }
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052 int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
1053 {
1054 Dwarf_Die type;
1055 int tag, ret;
1056 const char *tmp = "";
1057
1058 if (__die_get_real_type(vr_die, &type) == NULL)
1059 return -ENOENT;
1060
1061 tag = dwarf_tag(&type);
1062 if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
1063 tmp = "*";
1064 else if (tag == DW_TAG_subroutine_type) {
1065
1066 return strbuf_add(buf, "(function_type)", 15);
1067 } else {
1068 if (!dwarf_diename(&type))
1069 return -ENOENT;
1070 if (tag == DW_TAG_union_type)
1071 tmp = "union ";
1072 else if (tag == DW_TAG_structure_type)
1073 tmp = "struct ";
1074 else if (tag == DW_TAG_enumeration_type)
1075 tmp = "enum ";
1076
1077 return strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type));
1078 }
1079 ret = die_get_typename(&type, buf);
1080 return ret ? ret : strbuf_addstr(buf, tmp);
1081 }
1082
1083
1084
1085
1086
1087
1088
1089
1090 int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
1091 {
1092 int ret;
1093
1094 ret = die_get_typename(vr_die, buf);
1095 if (ret < 0) {
1096 pr_debug("Failed to get type, make it unknown.\n");
1097 ret = strbuf_add(buf, " (unknown_type)", 14);
1098 }
1099
1100 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
1101 }
1102
1103 #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113 static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die,
1114 struct strbuf *buf)
1115 {
1116 Dwarf_Die *scopes;
1117 int count;
1118 size_t offset = 0;
1119 Dwarf_Addr base;
1120 Dwarf_Addr start, end;
1121 Dwarf_Addr entry;
1122 int ret;
1123 bool first = true;
1124 const char *name;
1125
1126 ret = die_entrypc(sp_die, &entry);
1127 if (ret)
1128 return ret;
1129
1130 name = dwarf_diename(sp_die);
1131 if (!name)
1132 return -ENOENT;
1133
1134 count = dwarf_getscopes_die(vr_die, &scopes);
1135
1136
1137 if (count <= 1) {
1138 ret = -EINVAL;
1139 goto out;
1140 }
1141
1142 while ((offset = dwarf_ranges(&scopes[1], offset, &base,
1143 &start, &end)) > 0) {
1144 start -= entry;
1145 end -= entry;
1146
1147 if (first) {
1148 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1149 name, start, end);
1150 first = false;
1151 } else {
1152 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1153 start, end);
1154 }
1155 if (ret < 0)
1156 goto out;
1157 }
1158
1159 if (!first)
1160 ret = strbuf_add(buf, "]>", 2);
1161
1162 out:
1163 free(scopes);
1164 return ret;
1165 }
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176 int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf)
1177 {
1178 int ret = 0;
1179 Dwarf_Addr base;
1180 Dwarf_Addr start, end;
1181 Dwarf_Addr entry;
1182 Dwarf_Op *op;
1183 size_t nops;
1184 size_t offset = 0;
1185 Dwarf_Attribute attr;
1186 bool first = true;
1187 const char *name;
1188
1189 ret = die_entrypc(sp_die, &entry);
1190 if (ret)
1191 return ret;
1192
1193 name = dwarf_diename(sp_die);
1194 if (!name)
1195 return -ENOENT;
1196
1197 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
1198 return -EINVAL;
1199
1200 while ((offset = dwarf_getlocations(&attr, offset, &base,
1201 &start, &end, &op, &nops)) > 0) {
1202 if (start == 0) {
1203
1204 ret = die_get_var_innermost_scope(sp_die, vr_die, buf);
1205 goto out;
1206 }
1207
1208
1209 start -= entry;
1210 end -= entry;
1211 if (first) {
1212 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1213 name, start, end);
1214 first = false;
1215 } else {
1216 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1217 start, end);
1218 }
1219 if (ret < 0)
1220 goto out;
1221 }
1222
1223 if (!first)
1224 ret = strbuf_add(buf, "]>", 2);
1225 out:
1226 return ret;
1227 }
1228 #else
1229 int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
1230 Dwarf_Die *vr_die __maybe_unused,
1231 struct strbuf *buf __maybe_unused)
1232 {
1233 return -ENOTSUP;
1234 }
1235 #endif
1236
1237
1238
1239
1240
1241 static bool die_has_loclist(Dwarf_Die *vr_die)
1242 {
1243 Dwarf_Attribute loc;
1244 int tag = dwarf_tag(vr_die);
1245
1246 if (tag != DW_TAG_formal_parameter &&
1247 tag != DW_TAG_variable)
1248 return false;
1249
1250 return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
1251 dwarf_whatform(&loc) == DW_FORM_sec_offset);
1252 }
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263 bool die_is_optimized_target(Dwarf_Die *cu_die)
1264 {
1265 Dwarf_Die tmp_die;
1266
1267 if (die_has_loclist(cu_die))
1268 return true;
1269
1270 if (!dwarf_child(cu_die, &tmp_die) &&
1271 die_is_optimized_target(&tmp_die))
1272 return true;
1273
1274 if (!dwarf_siblingof(cu_die, &tmp_die) &&
1275 die_is_optimized_target(&tmp_die))
1276 return true;
1277
1278 return false;
1279 }
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293 static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
1294 Dwarf_Addr addr, unsigned long *idx)
1295 {
1296 unsigned long i;
1297 Dwarf_Addr tmp;
1298
1299 for (i = 0; i < nr_lines; i++) {
1300 if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
1301 return false;
1302
1303 if (tmp == addr) {
1304 *idx = i;
1305 return true;
1306 }
1307 }
1308 return false;
1309 }
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322 static bool die_get_postprologue_addr(unsigned long entrypc_idx,
1323 Dwarf_Lines *lines,
1324 unsigned long nr_lines,
1325 Dwarf_Addr highpc,
1326 Dwarf_Addr *postprologue_addr)
1327 {
1328 unsigned long i;
1329 int entrypc_lno, lno;
1330 Dwarf_Line *line;
1331 Dwarf_Addr addr;
1332 bool p_end;
1333
1334
1335 line = dwarf_onesrcline(lines, entrypc_idx);
1336 if (dwarf_lineno(line, &entrypc_lno))
1337 return false;
1338
1339 for (i = entrypc_idx; i < nr_lines; i++) {
1340 line = dwarf_onesrcline(lines, i);
1341
1342 if (dwarf_lineaddr(line, &addr) ||
1343 dwarf_lineno(line, &lno) ||
1344 dwarf_lineprologueend(line, &p_end))
1345 return false;
1346
1347
1348 if (addr >= highpc)
1349 break;
1350
1351
1352 if (p_end)
1353 break;
1354
1355
1356 if (lno != entrypc_lno)
1357 break;
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367 if (i != entrypc_idx)
1368 break;
1369 }
1370
1371 dwarf_lineaddr(line, postprologue_addr);
1372 if (*postprologue_addr >= highpc)
1373 dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
1374 postprologue_addr);
1375
1376 return true;
1377 }
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391 void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
1392 Dwarf_Addr *entrypc)
1393 {
1394 size_t nr_lines = 0;
1395 unsigned long entrypc_idx = 0;
1396 Dwarf_Lines *lines = NULL;
1397 Dwarf_Addr postprologue_addr;
1398 Dwarf_Addr highpc;
1399
1400 if (dwarf_highpc(sp_die, &highpc))
1401 return;
1402
1403 if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
1404 return;
1405
1406 if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
1407 return;
1408
1409 if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
1410 highpc, &postprologue_addr))
1411 return;
1412
1413 *entrypc = postprologue_addr;
1414 }