~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to tools/perf/util/probe-finder.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
#include <ctype.h>
34
34
#include <dwarf-regs.h>
35
35
 
 
36
#include <linux/bitops.h>
36
37
#include "event.h"
37
38
#include "debug.h"
38
39
#include "util.h"
272
273
        return dwarf_formstring(&attr);
273
274
}
274
275
 
 
276
/* Get a line number and file name for given address */
 
277
static int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
 
278
                            const char **fname, int *lineno)
 
279
{
 
280
        Dwarf_Line *line;
 
281
        Dwarf_Addr laddr;
 
282
 
 
283
        line = dwarf_getsrc_die(cudie, (Dwarf_Addr)addr);
 
284
        if (line && dwarf_lineaddr(line, &laddr) == 0 &&
 
285
            addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
 
286
                *fname = dwarf_linesrc(line, NULL, NULL);
 
287
                if (!*fname)
 
288
                        /* line number is useless without filename */
 
289
                        *lineno = 0;
 
290
        }
 
291
 
 
292
        return *lineno ?: -ENOENT;
 
293
}
 
294
 
275
295
/* Compare diename and tname */
276
296
static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
277
297
{
280
300
        return name ? (strcmp(tname, name) == 0) : false;
281
301
}
282
302
 
 
303
/* Get callsite line number of inline-function instance */
 
304
static int die_get_call_lineno(Dwarf_Die *in_die)
 
305
{
 
306
        Dwarf_Attribute attr;
 
307
        Dwarf_Word ret;
 
308
 
 
309
        if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
 
310
                return -ENOENT;
 
311
 
 
312
        dwarf_formudata(&attr, &ret);
 
313
        return (int)ret;
 
314
}
 
315
 
283
316
/* Get type die */
284
317
static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
285
318
{
320
353
        return vr_die;
321
354
}
322
355
 
 
356
static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
 
357
                              Dwarf_Word *result)
 
358
{
 
359
        Dwarf_Attribute attr;
 
360
 
 
361
        if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
 
362
            dwarf_formudata(&attr, result) != 0)
 
363
                return -ENOENT;
 
364
 
 
365
        return 0;
 
366
}
 
367
 
323
368
static bool die_is_signed_type(Dwarf_Die *tp_die)
324
369
{
325
 
        Dwarf_Attribute attr;
326
370
        Dwarf_Word ret;
327
371
 
328
 
        if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL ||
329
 
            dwarf_formudata(&attr, &ret) != 0)
 
372
        if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
330
373
                return false;
331
374
 
332
375
        return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
335
378
 
336
379
static int die_get_byte_size(Dwarf_Die *tp_die)
337
380
{
338
 
        Dwarf_Attribute attr;
339
 
        Dwarf_Word ret;
340
 
 
341
 
        if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL ||
342
 
            dwarf_formudata(&attr, &ret) != 0)
 
381
        Dwarf_Word ret;
 
382
 
 
383
        if (die_get_attr_udata(tp_die, DW_AT_byte_size, &ret))
 
384
                return 0;
 
385
 
 
386
        return (int)ret;
 
387
}
 
388
 
 
389
static int die_get_bit_size(Dwarf_Die *tp_die)
 
390
{
 
391
        Dwarf_Word ret;
 
392
 
 
393
        if (die_get_attr_udata(tp_die, DW_AT_bit_size, &ret))
 
394
                return 0;
 
395
 
 
396
        return (int)ret;
 
397
}
 
398
 
 
399
static int die_get_bit_offset(Dwarf_Die *tp_die)
 
400
{
 
401
        Dwarf_Word ret;
 
402
 
 
403
        if (die_get_attr_udata(tp_die, DW_AT_bit_offset, &ret))
343
404
                return 0;
344
405
 
345
406
        return (int)ret;
455
516
static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
456
517
                                      Dwarf_Die *die_mem)
457
518
{
458
 
        return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
 
519
        Dwarf_Die tmp_die;
 
520
 
 
521
        sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
 
522
        if (!sp_die)
 
523
                return NULL;
 
524
 
 
525
        /* Inlined function could be recursive. Trace it until fail */
 
526
        while (sp_die) {
 
527
                memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
 
528
                sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
 
529
                                        &tmp_die);
 
530
        }
 
531
 
 
532
        return die_mem;
 
533
}
 
534
 
 
535
/* Walker on lines (Note: line number will not be sorted) */
 
536
typedef int (* line_walk_handler_t) (const char *fname, int lineno,
 
537
                                     Dwarf_Addr addr, void *data);
 
538
 
 
539
struct __line_walk_param {
 
540
        const char *fname;
 
541
        line_walk_handler_t handler;
 
542
        void *data;
 
543
        int retval;
 
544
};
 
545
 
 
546
static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
 
547
{
 
548
        struct __line_walk_param *lw = data;
 
549
        Dwarf_Addr addr;
 
550
        int lineno;
 
551
 
 
552
        if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
 
553
                lineno = die_get_call_lineno(in_die);
 
554
                if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
 
555
                        lw->retval = lw->handler(lw->fname, lineno, addr,
 
556
                                                 lw->data);
 
557
                        if (lw->retval != 0)
 
558
                                return DIE_FIND_CB_FOUND;
 
559
                }
 
560
        }
 
561
        return DIE_FIND_CB_SIBLING;
 
562
}
 
563
 
 
564
/* Walk on lines of blocks included in given DIE */
 
565
static int __die_walk_funclines(Dwarf_Die *sp_die,
 
566
                                line_walk_handler_t handler, void *data)
 
567
{
 
568
        struct __line_walk_param lw = {
 
569
                .handler = handler,
 
570
                .data = data,
 
571
                .retval = 0,
 
572
        };
 
573
        Dwarf_Die die_mem;
 
574
        Dwarf_Addr addr;
 
575
        int lineno;
 
576
 
 
577
        /* Handle function declaration line */
 
578
        lw.fname = dwarf_decl_file(sp_die);
 
579
        if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
 
580
            dwarf_entrypc(sp_die, &addr) == 0) {
 
581
                lw.retval = handler(lw.fname, lineno, addr, data);
 
582
                if (lw.retval != 0)
 
583
                        goto done;
 
584
        }
 
585
        die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
 
586
done:
 
587
        return lw.retval;
 
588
}
 
589
 
 
590
static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
 
591
{
 
592
        struct __line_walk_param *lw = data;
 
593
 
 
594
        lw->retval = __die_walk_funclines(sp_die, lw->handler, lw->data);
 
595
        if (lw->retval != 0)
 
596
                return DWARF_CB_ABORT;
 
597
 
 
598
        return DWARF_CB_OK;
 
599
}
 
600
 
 
601
/*
 
602
 * Walk on lines inside given PDIE. If the PDIE is subprogram, walk only on
 
603
 * the lines inside the subprogram, otherwise PDIE must be a CU DIE.
 
604
 */
 
605
static int die_walk_lines(Dwarf_Die *pdie, line_walk_handler_t handler,
 
606
                          void *data)
 
607
{
 
608
        Dwarf_Lines *lines;
 
609
        Dwarf_Line *line;
 
610
        Dwarf_Addr addr;
 
611
        const char *fname;
 
612
        int lineno, ret = 0;
 
613
        Dwarf_Die die_mem, *cu_die;
 
614
        size_t nlines, i;
 
615
 
 
616
        /* Get the CU die */
 
617
        if (dwarf_tag(pdie) == DW_TAG_subprogram)
 
618
                cu_die = dwarf_diecu(pdie, &die_mem, NULL, NULL);
 
619
        else
 
620
                cu_die = pdie;
 
621
        if (!cu_die) {
 
622
                pr_debug2("Failed to get CU from subprogram\n");
 
623
                return -EINVAL;
 
624
        }
 
625
 
 
626
        /* Get lines list in the CU */
 
627
        if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
 
628
                pr_debug2("Failed to get source lines on this CU.\n");
 
629
                return -ENOENT;
 
630
        }
 
631
        pr_debug2("Get %zd lines from this CU\n", nlines);
 
632
 
 
633
        /* Walk on the lines on lines list */
 
634
        for (i = 0; i < nlines; i++) {
 
635
                line = dwarf_onesrcline(lines, i);
 
636
                if (line == NULL ||
 
637
                    dwarf_lineno(line, &lineno) != 0 ||
 
638
                    dwarf_lineaddr(line, &addr) != 0) {
 
639
                        pr_debug2("Failed to get line info. "
 
640
                                  "Possible error in debuginfo.\n");
 
641
                        continue;
 
642
                }
 
643
                /* Filter lines based on address */
 
644
                if (pdie != cu_die)
 
645
                        /*
 
646
                         * Address filtering
 
647
                         * The line is included in given function, and
 
648
                         * no inline block includes it.
 
649
                         */
 
650
                        if (!dwarf_haspc(pdie, addr) ||
 
651
                            die_find_inlinefunc(pdie, addr, &die_mem))
 
652
                                continue;
 
653
                /* Get source line */
 
654
                fname = dwarf_linesrc(line, NULL, NULL);
 
655
 
 
656
                ret = handler(fname, lineno, addr, data);
 
657
                if (ret != 0)
 
658
                        return ret;
 
659
        }
 
660
 
 
661
        /*
 
662
         * Dwarf lines doesn't include function declarations and inlined
 
663
         * subroutines. We have to check functions list or given function.
 
664
         */
 
665
        if (pdie != cu_die)
 
666
                ret = __die_walk_funclines(pdie, handler, data);
 
667
        else {
 
668
                struct __line_walk_param param = {
 
669
                        .handler = handler,
 
670
                        .data = data,
 
671
                        .retval = 0,
 
672
                };
 
673
                dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
 
674
                ret = param.retval;
 
675
        }
 
676
 
 
677
        return ret;
459
678
}
460
679
 
461
680
struct __find_variable_param {
669
888
        return 0;
670
889
}
671
890
 
 
891
#define BYTES_TO_BITS(nb)       ((nb) * BITS_PER_LONG / sizeof(long))
 
892
 
672
893
static int convert_variable_type(Dwarf_Die *vr_die,
673
894
                                 struct probe_trace_arg *tvar,
674
895
                                 const char *cast)
685
906
                return (tvar->type == NULL) ? -ENOMEM : 0;
686
907
        }
687
908
 
 
909
        if (die_get_bit_size(vr_die) != 0) {
 
910
                /* This is a bitfield */
 
911
                ret = snprintf(buf, 16, "b%d@%d/%zd", die_get_bit_size(vr_die),
 
912
                                die_get_bit_offset(vr_die),
 
913
                                BYTES_TO_BITS(die_get_byte_size(vr_die)));
 
914
                goto formatted;
 
915
        }
 
916
 
688
917
        if (die_get_real_type(vr_die, &type) == NULL) {
689
918
                pr_warning("Failed to get a type information of %s.\n",
690
919
                           dwarf_diename(vr_die));
729
958
                return (tvar->type == NULL) ? -ENOMEM : 0;
730
959
        }
731
960
 
732
 
        ret = die_get_byte_size(&type) * 8;
733
 
        if (ret) {
734
 
                /* Check the bitwidth */
735
 
                if (ret > MAX_BASIC_TYPE_BITS) {
736
 
                        pr_info("%s exceeds max-bitwidth."
737
 
                                " Cut down to %d bits.\n",
738
 
                                dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
739
 
                        ret = MAX_BASIC_TYPE_BITS;
740
 
                }
741
 
 
742
 
                ret = snprintf(buf, 16, "%c%d",
743
 
                               die_is_signed_type(&type) ? 's' : 'u', ret);
744
 
                if (ret < 0 || ret >= 16) {
745
 
                        if (ret >= 16)
746
 
                                ret = -E2BIG;
747
 
                        pr_warning("Failed to convert variable type: %s\n",
748
 
                                   strerror(-ret));
749
 
                        return ret;
750
 
                }
751
 
                tvar->type = strdup(buf);
752
 
                if (tvar->type == NULL)
753
 
                        return -ENOMEM;
754
 
        }
 
961
        ret = BYTES_TO_BITS(die_get_byte_size(&type));
 
962
        if (!ret)
 
963
                /* No size ... try to use default type */
 
964
                return 0;
 
965
 
 
966
        /* Check the bitwidth */
 
967
        if (ret > MAX_BASIC_TYPE_BITS) {
 
968
                pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n",
 
969
                        dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
 
970
                ret = MAX_BASIC_TYPE_BITS;
 
971
        }
 
972
        ret = snprintf(buf, 16, "%c%d",
 
973
                       die_is_signed_type(&type) ? 's' : 'u', ret);
 
974
 
 
975
formatted:
 
976
        if (ret < 0 || ret >= 16) {
 
977
                if (ret >= 16)
 
978
                        ret = -E2BIG;
 
979
                pr_warning("Failed to convert variable type: %s\n",
 
980
                           strerror(-ret));
 
981
                return ret;
 
982
        }
 
983
        tvar->type = strdup(buf);
 
984
        if (tvar->type == NULL)
 
985
                return -ENOMEM;
755
986
        return 0;
756
987
}
757
988
 
1050
1281
        return ret;
1051
1282
}
1052
1283
 
 
1284
static int probe_point_line_walker(const char *fname, int lineno,
 
1285
                                   Dwarf_Addr addr, void *data)
 
1286
{
 
1287
        struct probe_finder *pf = data;
 
1288
        int ret;
 
1289
 
 
1290
        if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
 
1291
                return 0;
 
1292
 
 
1293
        pf->addr = addr;
 
1294
        ret = call_probe_finder(NULL, pf);
 
1295
 
 
1296
        /* Continue if no error, because the line will be in inline function */
 
1297
        return ret < 0 ? ret : 0;
 
1298
}
 
1299
 
1053
1300
/* Find probe point from its line number */
1054
1301
static int find_probe_point_by_line(struct probe_finder *pf)
1055
1302
{
1056
 
        Dwarf_Lines *lines;
1057
 
        Dwarf_Line *line;
1058
 
        size_t nlines, i;
1059
 
        Dwarf_Addr addr;
1060
 
        int lineno;
1061
 
        int ret = 0;
1062
 
 
1063
 
        if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1064
 
                pr_warning("No source lines found.\n");
1065
 
                return -ENOENT;
1066
 
        }
1067
 
 
1068
 
        for (i = 0; i < nlines && ret == 0; i++) {
1069
 
                line = dwarf_onesrcline(lines, i);
1070
 
                if (dwarf_lineno(line, &lineno) != 0 ||
1071
 
                    lineno != pf->lno)
1072
 
                        continue;
1073
 
 
1074
 
                /* TODO: Get fileno from line, but how? */
1075
 
                if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
1076
 
                        continue;
1077
 
 
1078
 
                if (dwarf_lineaddr(line, &addr) != 0) {
1079
 
                        pr_warning("Failed to get the address of the line.\n");
1080
 
                        return -ENOENT;
1081
 
                }
1082
 
                pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
1083
 
                         (int)i, lineno, (uintmax_t)addr);
1084
 
                pf->addr = addr;
1085
 
 
1086
 
                ret = call_probe_finder(NULL, pf);
1087
 
                /* Continuing, because target line might be inlined. */
1088
 
        }
1089
 
        return ret;
 
1303
        return die_walk_lines(&pf->cu_die, probe_point_line_walker, pf);
1090
1304
}
1091
1305
 
1092
1306
/* Find lines which match lazy pattern */
1093
1307
static int find_lazy_match_lines(struct list_head *head,
1094
1308
                                 const char *fname, const char *pat)
1095
1309
{
1096
 
        char *fbuf, *p1, *p2;
1097
 
        int fd, line, nlines = -1;
1098
 
        struct stat st;
 
1310
        FILE *fp;
 
1311
        char *line = NULL;
 
1312
        size_t line_len;
 
1313
        ssize_t len;
 
1314
        int count = 0, linenum = 1;
1099
1315
 
1100
 
        fd = open(fname, O_RDONLY);
1101
 
        if (fd < 0) {
1102
 
                pr_warning("Failed to open %s: %s\n", fname, strerror(-fd));
 
1316
        fp = fopen(fname, "r");
 
1317
        if (!fp) {
 
1318
                pr_warning("Failed to open %s: %s\n", fname, strerror(errno));
1103
1319
                return -errno;
1104
1320
        }
1105
1321
 
1106
 
        if (fstat(fd, &st) < 0) {
1107
 
                pr_warning("Failed to get the size of %s: %s\n",
1108
 
                           fname, strerror(errno));
1109
 
                nlines = -errno;
1110
 
                goto out_close;
1111
 
        }
1112
 
 
1113
 
        nlines = -ENOMEM;
1114
 
        fbuf = malloc(st.st_size + 2);
1115
 
        if (fbuf == NULL)
1116
 
                goto out_close;
1117
 
        if (read(fd, fbuf, st.st_size) < 0) {
1118
 
                pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
1119
 
                nlines = -errno;
1120
 
                goto out_free_fbuf;
1121
 
        }
1122
 
        fbuf[st.st_size] = '\n';        /* Dummy line */
1123
 
        fbuf[st.st_size + 1] = '\0';
1124
 
        p1 = fbuf;
1125
 
        line = 1;
1126
 
        nlines = 0;
1127
 
        while ((p2 = strchr(p1, '\n')) != NULL) {
1128
 
                *p2 = '\0';
1129
 
                if (strlazymatch(p1, pat)) {
1130
 
                        line_list__add_line(head, line);
1131
 
                        nlines++;
 
1322
        while ((len = getline(&line, &line_len, fp)) > 0) {
 
1323
 
 
1324
                if (line[len - 1] == '\n')
 
1325
                        line[len - 1] = '\0';
 
1326
 
 
1327
                if (strlazymatch(line, pat)) {
 
1328
                        line_list__add_line(head, linenum);
 
1329
                        count++;
1132
1330
                }
1133
 
                line++;
1134
 
                p1 = p2 + 1;
 
1331
                linenum++;
1135
1332
        }
1136
 
out_free_fbuf:
1137
 
        free(fbuf);
1138
 
out_close:
1139
 
        close(fd);
1140
 
        return nlines;
 
1333
 
 
1334
        if (ferror(fp))
 
1335
                count = -errno;
 
1336
        free(line);
 
1337
        fclose(fp);
 
1338
 
 
1339
        if (count == 0)
 
1340
                pr_debug("No matched lines found in %s.\n", fname);
 
1341
        return count;
 
1342
}
 
1343
 
 
1344
static int probe_point_lazy_walker(const char *fname, int lineno,
 
1345
                                   Dwarf_Addr addr, void *data)
 
1346
{
 
1347
        struct probe_finder *pf = data;
 
1348
        int ret;
 
1349
 
 
1350
        if (!line_list__has_line(&pf->lcache, lineno) ||
 
1351
            strtailcmp(fname, pf->fname) != 0)
 
1352
                return 0;
 
1353
 
 
1354
        pr_debug("Probe line found: line:%d addr:0x%llx\n",
 
1355
                 lineno, (unsigned long long)addr);
 
1356
        pf->addr = addr;
 
1357
        ret = call_probe_finder(NULL, pf);
 
1358
 
 
1359
        /*
 
1360
         * Continue if no error, because the lazy pattern will match
 
1361
         * to other lines
 
1362
         */
 
1363
        return ret < 0 ? ret : 0;
1141
1364
}
1142
1365
 
1143
1366
/* Find probe points from lazy pattern  */
1144
1367
static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
1145
1368
{
1146
 
        Dwarf_Lines *lines;
1147
 
        Dwarf_Line *line;
1148
 
        size_t nlines, i;
1149
 
        Dwarf_Addr addr;
1150
 
        Dwarf_Die die_mem;
1151
 
        int lineno;
1152
1369
        int ret = 0;
1153
1370
 
1154
1371
        if (list_empty(&pf->lcache)) {
1155
1372
                /* Matching lazy line pattern */
1156
1373
                ret = find_lazy_match_lines(&pf->lcache, pf->fname,
1157
1374
                                            pf->pev->point.lazy_line);
1158
 
                if (ret == 0) {
1159
 
                        pr_debug("No matched lines found in %s.\n", pf->fname);
1160
 
                        return 0;
1161
 
                } else if (ret < 0)
 
1375
                if (ret <= 0)
1162
1376
                        return ret;
1163
1377
        }
1164
1378
 
1165
 
        if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1166
 
                pr_warning("No source lines found.\n");
1167
 
                return -ENOENT;
1168
 
        }
1169
 
 
1170
 
        for (i = 0; i < nlines && ret >= 0; i++) {
1171
 
                line = dwarf_onesrcline(lines, i);
1172
 
 
1173
 
                if (dwarf_lineno(line, &lineno) != 0 ||
1174
 
                    !line_list__has_line(&pf->lcache, lineno))
1175
 
                        continue;
1176
 
 
1177
 
                /* TODO: Get fileno from line, but how? */
1178
 
                if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
1179
 
                        continue;
1180
 
 
1181
 
                if (dwarf_lineaddr(line, &addr) != 0) {
1182
 
                        pr_debug("Failed to get the address of line %d.\n",
1183
 
                                 lineno);
1184
 
                        continue;
1185
 
                }
1186
 
                if (sp_die) {
1187
 
                        /* Address filtering 1: does sp_die include addr? */
1188
 
                        if (!dwarf_haspc(sp_die, addr))
1189
 
                                continue;
1190
 
                        /* Address filtering 2: No child include addr? */
1191
 
                        if (die_find_inlinefunc(sp_die, addr, &die_mem))
1192
 
                                continue;
1193
 
                }
1194
 
 
1195
 
                pr_debug("Probe line found: line[%d]:%d addr:0x%llx\n",
1196
 
                         (int)i, lineno, (unsigned long long)addr);
1197
 
                pf->addr = addr;
1198
 
 
1199
 
                ret = call_probe_finder(sp_die, pf);
1200
 
                /* Continuing, because target line might be inlined. */
1201
 
        }
1202
 
        /* TODO: deallocate lines, but how? */
1203
 
        return ret;
 
1379
        return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
1204
1380
}
1205
1381
 
1206
1382
/* Callback parameter with return value */
1251
1427
            !die_compare_name(sp_die, pp->function))
1252
1428
                return DWARF_CB_OK;
1253
1429
 
 
1430
        /* Check declared file */
 
1431
        if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
 
1432
                return DWARF_CB_OK;
 
1433
 
1254
1434
        pf->fname = dwarf_decl_file(sp_die);
1255
1435
        if (pp->line) { /* Function relative line */
1256
1436
                dwarf_decl_line(sp_die, &pf->lno);
1291
1471
        return _param.retval;
1292
1472
}
1293
1473
 
 
1474
struct pubname_callback_param {
 
1475
        char *function;
 
1476
        char *file;
 
1477
        Dwarf_Die *cu_die;
 
1478
        Dwarf_Die *sp_die;
 
1479
        int found;
 
1480
};
 
1481
 
 
1482
static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
 
1483
{
 
1484
        struct pubname_callback_param *param = data;
 
1485
 
 
1486
        if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) {
 
1487
                if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
 
1488
                        return DWARF_CB_OK;
 
1489
 
 
1490
                if (die_compare_name(param->sp_die, param->function)) {
 
1491
                        if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
 
1492
                                return DWARF_CB_OK;
 
1493
 
 
1494
                        if (param->file &&
 
1495
                            strtailcmp(param->file, dwarf_decl_file(param->sp_die)))
 
1496
                                return DWARF_CB_OK;
 
1497
 
 
1498
                        param->found = 1;
 
1499
                        return DWARF_CB_ABORT;
 
1500
                }
 
1501
        }
 
1502
 
 
1503
        return DWARF_CB_OK;
 
1504
}
 
1505
 
1294
1506
/* Find probe points from debuginfo */
1295
1507
static int find_probes(int fd, struct probe_finder *pf)
1296
1508
{
1307
1519
        if (!dbg) {
1308
1520
                pr_warning("No debug information found in the vmlinux - "
1309
1521
                        "please rebuild with CONFIG_DEBUG_INFO=y.\n");
 
1522
                close(fd);      /* Without dwfl_end(), fd isn't closed. */
1310
1523
                return -EBADF;
1311
1524
        }
1312
1525
 
1317
1530
 
1318
1531
        off = 0;
1319
1532
        line_list__init(&pf->lcache);
 
1533
 
 
1534
        /* Fastpath: lookup by function name from .debug_pubnames section */
 
1535
        if (pp->function) {
 
1536
                struct pubname_callback_param pubname_param = {
 
1537
                        .function = pp->function,
 
1538
                        .file     = pp->file,
 
1539
                        .cu_die   = &pf->cu_die,
 
1540
                        .sp_die   = &pf->sp_die,
 
1541
                        .found    = 0,
 
1542
                };
 
1543
                struct dwarf_callback_param probe_param = {
 
1544
                        .data = pf,
 
1545
                };
 
1546
 
 
1547
                dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0);
 
1548
                if (pubname_param.found) {
 
1549
                        ret = probe_point_search_cb(&pf->sp_die, &probe_param);
 
1550
                        if (ret)
 
1551
                                goto found;
 
1552
                }
 
1553
        }
 
1554
 
1320
1555
        /* Loop on CUs (Compilation Unit) */
1321
 
        while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
1322
 
               ret >= 0) {
 
1556
        while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
1323
1557
                /* Get the DIE(Debugging Information Entry) of this CU */
1324
1558
                diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die);
1325
1559
                if (!diep)
1340
1574
                                pf->lno = pp->line;
1341
1575
                                ret = find_probe_point_by_line(pf);
1342
1576
                        }
 
1577
                        if (ret < 0)
 
1578
                                break;
1343
1579
                }
1344
1580
                off = noff;
1345
1581
        }
 
1582
 
 
1583
found:
1346
1584
        line_list__free(&pf->lcache);
1347
1585
        if (dwfl)
1348
1586
                dwfl_end(dwfl);
1541
1779
        Dwarf_Die cudie, spdie, indie;
1542
1780
        Dwarf *dbg = NULL;
1543
1781
        Dwfl *dwfl = NULL;
1544
 
        Dwarf_Line *line;
1545
 
        Dwarf_Addr laddr, eaddr, bias = 0;
1546
 
        const char *tmp;
1547
 
        int lineno, ret = 0;
1548
 
        bool found = false;
 
1782
        Dwarf_Addr _addr, baseaddr, bias = 0;
 
1783
        const char *fname = NULL, *func = NULL, *tmp;
 
1784
        int baseline = 0, lineno = 0, ret = 0;
1549
1785
 
1550
1786
        /* Open the live linux kernel */
1551
1787
        dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
1566
1802
                goto end;
1567
1803
        }
1568
1804
 
1569
 
        /* Find a corresponding line */
1570
 
        line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr);
1571
 
        if (line) {
1572
 
                if (dwarf_lineaddr(line, &laddr) == 0 &&
1573
 
                    (Dwarf_Addr)addr == laddr &&
1574
 
                    dwarf_lineno(line, &lineno) == 0) {
1575
 
                        tmp = dwarf_linesrc(line, NULL, NULL);
1576
 
                        if (tmp) {
1577
 
                                ppt->line = lineno;
1578
 
                                ppt->file = strdup(tmp);
1579
 
                                if (ppt->file == NULL) {
1580
 
                                        ret = -ENOMEM;
1581
 
                                        goto end;
1582
 
                                }
1583
 
                                found = true;
1584
 
                        }
1585
 
                }
1586
 
        }
 
1805
        /* Find a corresponding line (filename and lineno) */
 
1806
        cu_find_lineinfo(&cudie, addr, &fname, &lineno);
 
1807
        /* Don't care whether it failed or not */
1587
1808
 
1588
 
        /* Find a corresponding function */
 
1809
        /* Find a corresponding function (name, baseline and baseaddr) */
1589
1810
        if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
 
1811
                /* Get function entry information */
1590
1812
                tmp = dwarf_diename(&spdie);
1591
 
                if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0)
1592
 
                        goto end;
 
1813
                if (!tmp ||
 
1814
                    dwarf_entrypc(&spdie, &baseaddr) != 0 ||
 
1815
                    dwarf_decl_line(&spdie, &baseline) != 0)
 
1816
                        goto post;
 
1817
                func = tmp;
1593
1818
 
1594
 
                if (ppt->line) {
1595
 
                        if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
1596
 
                                                &indie)) {
1597
 
                                /* addr in an inline function */
 
1819
                if (addr == (unsigned long)baseaddr)
 
1820
                        /* Function entry - Relative line number is 0 */
 
1821
                        lineno = baseline;
 
1822
                else if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
 
1823
                                             &indie)) {
 
1824
                        if (dwarf_entrypc(&indie, &_addr) == 0 &&
 
1825
                            _addr == addr)
 
1826
                                /*
 
1827
                                 * addr is at an inline function entry.
 
1828
                                 * In this case, lineno should be the call-site
 
1829
                                 * line number.
 
1830
                                 */
 
1831
                                lineno = die_get_call_lineno(&indie);
 
1832
                        else {
 
1833
                                /*
 
1834
                                 * addr is in an inline function body.
 
1835
                                 * Since lineno points one of the lines
 
1836
                                 * of the inline function, baseline should
 
1837
                                 * be the entry line of the inline function.
 
1838
                                 */
1598
1839
                                tmp = dwarf_diename(&indie);
1599
 
                                if (!tmp)
1600
 
                                        goto end;
1601
 
                                ret = dwarf_decl_line(&indie, &lineno);
1602
 
                        } else {
1603
 
                                if (eaddr == addr) {    /* Function entry */
1604
 
                                        lineno = ppt->line;
1605
 
                                        ret = 0;
1606
 
                                } else
1607
 
                                        ret = dwarf_decl_line(&spdie, &lineno);
1608
 
                        }
1609
 
                        if (ret == 0) {
1610
 
                                /* Make a relative line number */
1611
 
                                ppt->line -= lineno;
1612
 
                                goto found;
 
1840
                                if (tmp &&
 
1841
                                    dwarf_decl_line(&spdie, &baseline) == 0)
 
1842
                                        func = tmp;
1613
1843
                        }
1614
1844
                }
1615
 
                /* We don't have a line number, let's use offset */
1616
 
                ppt->offset = addr - (unsigned long)eaddr;
1617
 
found:
1618
 
                ppt->function = strdup(tmp);
 
1845
        }
 
1846
 
 
1847
post:
 
1848
        /* Make a relative line number or an offset */
 
1849
        if (lineno)
 
1850
                ppt->line = lineno - baseline;
 
1851
        else if (func)
 
1852
                ppt->offset = addr - (unsigned long)baseaddr;
 
1853
 
 
1854
        /* Duplicate strings */
 
1855
        if (func) {
 
1856
                ppt->function = strdup(func);
1619
1857
                if (ppt->function == NULL) {
1620
1858
                        ret = -ENOMEM;
1621
1859
                        goto end;
1622
1860
                }
1623
 
                found = true;
1624
 
        }
1625
 
 
 
1861
        }
 
1862
        if (fname) {
 
1863
                ppt->file = strdup(fname);
 
1864
                if (ppt->file == NULL) {
 
1865
                        if (ppt->function) {
 
1866
                                free(ppt->function);
 
1867
                                ppt->function = NULL;
 
1868
                        }
 
1869
                        ret = -ENOMEM;
 
1870
                        goto end;
 
1871
                }
 
1872
        }
1626
1873
end:
1627
1874
        if (dwfl)
1628
1875
                dwfl_end(dwfl);
1629
 
        if (ret >= 0)
1630
 
                ret = found ? 1 : 0;
 
1876
        if (ret == 0 && (fname || func))
 
1877
                ret = 1;        /* Found a point */
1631
1878
        return ret;
1632
1879
}
1633
1880
 
1644
1891
        return line_list__add_line(&lr->line_list, lineno);
1645
1892
}
1646
1893
 
1647
 
/* Search function declaration lines */
1648
 
static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data)
 
1894
static int line_range_walk_cb(const char *fname, int lineno,
 
1895
                              Dwarf_Addr addr __used,
 
1896
                              void *data)
1649
1897
{
1650
 
        struct dwarf_callback_param *param = data;
1651
 
        struct line_finder *lf = param->data;
1652
 
        const char *src;
1653
 
        int lineno;
1654
 
 
1655
 
        src = dwarf_decl_file(sp_die);
1656
 
        if (src && strtailcmp(src, lf->fname) != 0)
1657
 
                return DWARF_CB_OK;
1658
 
 
1659
 
        if (dwarf_decl_line(sp_die, &lineno) != 0 ||
 
1898
        struct line_finder *lf = data;
 
1899
 
 
1900
        if ((strtailcmp(fname, lf->fname) != 0) ||
1660
1901
            (lf->lno_s > lineno || lf->lno_e < lineno))
1661
 
                return DWARF_CB_OK;
1662
 
 
1663
 
        param->retval = line_range_add_line(src, lineno, lf->lr);
1664
 
        if (param->retval < 0)
1665
 
                return DWARF_CB_ABORT;
1666
 
        return DWARF_CB_OK;
1667
 
}
1668
 
 
1669
 
static int find_line_range_func_decl_lines(struct line_finder *lf)
1670
 
{
1671
 
        struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1672
 
        dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, &param, 0);
1673
 
        return param.retval;
 
1902
                return 0;
 
1903
 
 
1904
        if (line_range_add_line(fname, lineno, lf->lr) < 0)
 
1905
                return -EINVAL;
 
1906
 
 
1907
        return 0;
1674
1908
}
1675
1909
 
1676
1910
/* Find line range from its line number */
1677
1911
static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1678
1912
{
1679
 
        Dwarf_Lines *lines;
1680
 
        Dwarf_Line *line;
1681
 
        size_t nlines, i;
1682
 
        Dwarf_Addr addr;
1683
 
        int lineno, ret = 0;
1684
 
        const char *src;
1685
 
        Dwarf_Die die_mem;
1686
 
 
1687
 
        line_list__init(&lf->lr->line_list);
1688
 
        if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
1689
 
                pr_warning("No source lines found.\n");
1690
 
                return -ENOENT;
1691
 
        }
1692
 
 
1693
 
        /* Search probable lines on lines list */
1694
 
        for (i = 0; i < nlines; i++) {
1695
 
                line = dwarf_onesrcline(lines, i);
1696
 
                if (dwarf_lineno(line, &lineno) != 0 ||
1697
 
                    (lf->lno_s > lineno || lf->lno_e < lineno))
1698
 
                        continue;
1699
 
 
1700
 
                if (sp_die) {
1701
 
                        /* Address filtering 1: does sp_die include addr? */
1702
 
                        if (dwarf_lineaddr(line, &addr) != 0 ||
1703
 
                            !dwarf_haspc(sp_die, addr))
1704
 
                                continue;
1705
 
 
1706
 
                        /* Address filtering 2: No child include addr? */
1707
 
                        if (die_find_inlinefunc(sp_die, addr, &die_mem))
1708
 
                                continue;
1709
 
                }
1710
 
 
1711
 
                /* TODO: Get fileno from line, but how? */
1712
 
                src = dwarf_linesrc(line, NULL, NULL);
1713
 
                if (strtailcmp(src, lf->fname) != 0)
1714
 
                        continue;
1715
 
 
1716
 
                ret = line_range_add_line(src, lineno, lf->lr);
1717
 
                if (ret < 0)
1718
 
                        return ret;
1719
 
        }
1720
 
 
1721
 
        /*
1722
 
         * Dwarf lines doesn't include function declarations. We have to
1723
 
         * check functions list or given function.
1724
 
         */
1725
 
        if (sp_die) {
1726
 
                src = dwarf_decl_file(sp_die);
1727
 
                if (src && dwarf_decl_line(sp_die, &lineno) == 0 &&
1728
 
                    (lf->lno_s <= lineno && lf->lno_e >= lineno))
1729
 
                        ret = line_range_add_line(src, lineno, lf->lr);
1730
 
        } else
1731
 
                ret = find_line_range_func_decl_lines(lf);
 
1913
        int ret;
 
1914
 
 
1915
        ret = die_walk_lines(sp_die ?: &lf->cu_die, line_range_walk_cb, lf);
1732
1916
 
1733
1917
        /* Update status */
1734
1918
        if (ret >= 0)
1758
1942
        struct line_finder *lf = param->data;
1759
1943
        struct line_range *lr = lf->lr;
1760
1944
 
1761
 
        pr_debug("find (%llx) %s\n",
1762
 
                 (unsigned long long)dwarf_dieoffset(sp_die),
1763
 
                 dwarf_diename(sp_die));
 
1945
        /* Check declared file */
 
1946
        if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
 
1947
                return DWARF_CB_OK;
 
1948
 
1764
1949
        if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
1765
1950
            die_compare_name(sp_die, lr->function)) {
1766
1951
                lf->fname = dwarf_decl_file(sp_die);
1813
1998
        if (!dbg) {
1814
1999
                pr_warning("No debug information found in the vmlinux - "
1815
2000
                        "please rebuild with CONFIG_DEBUG_INFO=y.\n");
 
2001
                close(fd);      /* Without dwfl_end(), fd isn't closed. */
1816
2002
                return -EBADF;
1817
2003
        }
1818
2004
 
 
2005
        /* Fastpath: lookup by function name from .debug_pubnames section */
 
2006
        if (lr->function) {
 
2007
                struct pubname_callback_param pubname_param = {
 
2008
                        .function = lr->function, .file = lr->file,
 
2009
                        .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0};
 
2010
                struct dwarf_callback_param line_range_param = {
 
2011
                        .data = (void *)&lf, .retval = 0};
 
2012
 
 
2013
                dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0);
 
2014
                if (pubname_param.found) {
 
2015
                        line_range_search_cb(&lf.sp_die, &line_range_param);
 
2016
                        if (lf.found)
 
2017
                                goto found;
 
2018
                }
 
2019
        }
 
2020
 
1819
2021
        /* Loop on CUs (Compilation Unit) */
1820
2022
        while (!lf.found && ret >= 0) {
1821
2023
                if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
1844
2046
                off = noff;
1845
2047
        }
1846
2048
 
 
2049
found:
1847
2050
        /* Store comp_dir */
1848
2051
        if (lf.found) {
1849
2052
                comp_dir = cu_get_comp_dir(&lf.cu_die);