aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-finder.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2010-04-12 13:17:35 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-04-14 16:28:30 -0400
commitb55a87ade3839c33ab94768a0b5955734073f987 (patch)
tree7e4d2f9e49b4c4a99257bdf1ee61164d12e3ba7e /tools/perf/util/probe-finder.c
parenta34a985499895a46a4dacff727d0fbc63cdc75e8 (diff)
perf probe: Remove die() from probe-finder code
Remove die() and DIE_IF() code from util/probe-finder.c since these 'sudden death' in utility functions make reusing it from other code (especially tui/gui) difficult. Cc: Ingo Molnar <mingo@elte.hu> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20100412171735.3790.88853.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/probe-finder.c')
-rw-r--r--tools/perf/util/probe-finder.c517
1 files changed, 320 insertions, 197 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 1f4528555d42..54daa91e901d 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -196,19 +196,7 @@ static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
196{ 196{
197 const char *name; 197 const char *name;
198 name = dwarf_diename(dw_die); 198 name = dwarf_diename(dw_die);
199 DIE_IF(name == NULL); 199 return name ? strcmp(tname, name) : -1;
200 return strcmp(tname, name);
201}
202
203/* Get entry pc(or low pc, 1st entry of ranges) of the die */
204static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
205{
206 Dwarf_Addr epc;
207 int ret;
208
209 ret = dwarf_entrypc(dw_die, &epc);
210 DIE_IF(ret == -1);
211 return epc;
212} 200}
213 201
214/* Get type die, but skip qualifiers and typedef */ 202/* Get type die, but skip qualifiers and typedef */
@@ -390,7 +378,7 @@ static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
390 */ 378 */
391 379
392/* Show a location */ 380/* Show a location */
393static void convert_location(Dwarf_Op *op, struct probe_finder *pf) 381static int convert_location(Dwarf_Op *op, struct probe_finder *pf)
394{ 382{
395 unsigned int regn; 383 unsigned int regn;
396 Dwarf_Word offs = 0; 384 Dwarf_Word offs = 0;
@@ -400,8 +388,11 @@ static void convert_location(Dwarf_Op *op, struct probe_finder *pf)
400 388
401 /* If this is based on frame buffer, set the offset */ 389 /* If this is based on frame buffer, set the offset */
402 if (op->atom == DW_OP_fbreg) { 390 if (op->atom == DW_OP_fbreg) {
403 if (pf->fb_ops == NULL) 391 if (pf->fb_ops == NULL) {
404 die("The attribute of frame base is not supported.\n"); 392 pr_warning("The attribute of frame base is not "
393 "supported.\n");
394 return -ENOTSUP;
395 }
405 ref = true; 396 ref = true;
406 offs = op->number; 397 offs = op->number;
407 op = &pf->fb_ops[0]; 398 op = &pf->fb_ops[0];
@@ -419,50 +410,63 @@ static void convert_location(Dwarf_Op *op, struct probe_finder *pf)
419 ref = true; 410 ref = true;
420 } else if (op->atom == DW_OP_regx) { 411 } else if (op->atom == DW_OP_regx) {
421 regn = op->number; 412 regn = op->number;
422 } else 413 } else {
423 die("DW_OP %d is not supported.", op->atom); 414 pr_warning("DW_OP %x is not supported.\n", op->atom);
415 return -ENOTSUP;
416 }
424 417
425 regs = get_arch_regstr(regn); 418 regs = get_arch_regstr(regn);
426 if (!regs) 419 if (!regs) {
427 die("%u exceeds max register number.", regn); 420 pr_warning("%u exceeds max register number.\n", regn);
421 return -ERANGE;
422 }
428 423
429 tvar->value = xstrdup(regs); 424 tvar->value = xstrdup(regs);
430 if (ref) { 425 if (ref) {
431 tvar->ref = xzalloc(sizeof(struct kprobe_trace_arg_ref)); 426 tvar->ref = xzalloc(sizeof(struct kprobe_trace_arg_ref));
432 tvar->ref->offset = (long)offs; 427 tvar->ref->offset = (long)offs;
433 } 428 }
429 return 0;
434} 430}
435 431
436static void convert_variable_type(Dwarf_Die *vr_die, 432static int convert_variable_type(Dwarf_Die *vr_die,
437 struct kprobe_trace_arg *targ) 433 struct kprobe_trace_arg *targ)
438{ 434{
439 Dwarf_Die type; 435 Dwarf_Die type;
440 char buf[16]; 436 char buf[16];
441 int ret; 437 int ret;
442 438
443 if (die_get_real_type(vr_die, &type) == NULL) 439 if (die_get_real_type(vr_die, &type) == NULL) {
444 die("Failed to get a type information of %s.", 440 pr_warning("Failed to get a type information of %s.\n",
445 dwarf_diename(vr_die)); 441 dwarf_diename(vr_die));
442 return -ENOENT;
443 }
446 444
447 ret = die_get_byte_size(&type) * 8; 445 ret = die_get_byte_size(&type) * 8;
448 if (ret) { 446 if (ret) {
449 /* Check the bitwidth */ 447 /* Check the bitwidth */
450 if (ret > MAX_BASIC_TYPE_BITS) { 448 if (ret > MAX_BASIC_TYPE_BITS) {
451 pr_warning(" Warning: %s exceeds max-bitwidth." 449 pr_info("%s exceeds max-bitwidth."
452 " Cut down to %d bits.\n", 450 " Cut down to %d bits.\n",
453 dwarf_diename(&type), MAX_BASIC_TYPE_BITS); 451 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
454 ret = MAX_BASIC_TYPE_BITS; 452 ret = MAX_BASIC_TYPE_BITS;
455 } 453 }
456 454
457 ret = snprintf(buf, 16, "%c%d", 455 ret = snprintf(buf, 16, "%c%d",
458 die_is_signed_type(&type) ? 's' : 'u', ret); 456 die_is_signed_type(&type) ? 's' : 'u', ret);
459 if (ret < 0 || ret >= 16) 457 if (ret < 0 || ret >= 16) {
460 die("Failed to convert variable type."); 458 if (ret >= 16)
459 ret = -E2BIG;
460 pr_warning("Failed to convert variable type: %s\n",
461 strerror(-ret));
462 return ret;
463 }
461 targ->type = xstrdup(buf); 464 targ->type = xstrdup(buf);
462 } 465 }
466 return 0;
463} 467}
464 468
465static void convert_variable_fields(Dwarf_Die *vr_die, const char *varname, 469static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
466 struct perf_probe_arg_field *field, 470 struct perf_probe_arg_field *field,
467 struct kprobe_trace_arg_ref **ref_ptr, 471 struct kprobe_trace_arg_ref **ref_ptr,
468 Dwarf_Die *die_mem) 472 Dwarf_Die *die_mem)
@@ -473,21 +477,28 @@ static void convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
473 Dwarf_Word offs; 477 Dwarf_Word offs;
474 478
475 pr_debug("converting %s in %s\n", field->name, varname); 479 pr_debug("converting %s in %s\n", field->name, varname);
476 if (die_get_real_type(vr_die, &type) == NULL) 480 if (die_get_real_type(vr_die, &type) == NULL) {
477 die("Failed to get a type information of %s.", varname); 481 pr_warning("Failed to get the type of %s.\n", varname);
482 return -ENOENT;
483 }
478 484
479 /* Check the pointer and dereference */ 485 /* Check the pointer and dereference */
480 if (dwarf_tag(&type) == DW_TAG_pointer_type) { 486 if (dwarf_tag(&type) == DW_TAG_pointer_type) {
481 if (!field->ref) 487 if (!field->ref) {
482 die("Semantic error: %s must be referred by '->'", 488 pr_err("Semantic error: %s must be referred by '->'\n",
483 field->name); 489 field->name);
490 return -EINVAL;
491 }
484 /* Get the type pointed by this pointer */ 492 /* Get the type pointed by this pointer */
485 if (die_get_real_type(&type, &type) == NULL) 493 if (die_get_real_type(&type, &type) == NULL) {
486 die("Failed to get a type information of %s.", varname); 494 pr_warning("Failed to get the type of %s.\n", varname);
487 495 return -ENOENT;
496 }
488 /* Verify it is a data structure */ 497 /* Verify it is a data structure */
489 if (dwarf_tag(&type) != DW_TAG_structure_type) 498 if (dwarf_tag(&type) != DW_TAG_structure_type) {
490 die("%s is not a data structure.", varname); 499 pr_warning("%s is not a data structure.\n", varname);
500 return -EINVAL;
501 }
491 502
492 ref = xzalloc(sizeof(struct kprobe_trace_arg_ref)); 503 ref = xzalloc(sizeof(struct kprobe_trace_arg_ref));
493 if (*ref_ptr) 504 if (*ref_ptr)
@@ -496,34 +507,46 @@ static void convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
496 *ref_ptr = ref; 507 *ref_ptr = ref;
497 } else { 508 } else {
498 /* Verify it is a data structure */ 509 /* Verify it is a data structure */
499 if (dwarf_tag(&type) != DW_TAG_structure_type) 510 if (dwarf_tag(&type) != DW_TAG_structure_type) {
500 die("%s is not a data structure.", varname); 511 pr_warning("%s is not a data structure.\n", varname);
501 512 return -EINVAL;
502 if (field->ref) 513 }
503 die("Semantic error: %s must be referred by '.'", 514 if (field->ref) {
504 field->name); 515 pr_err("Semantic error: %s must be referred by '.'\n",
505 if (!ref) 516 field->name);
506 die("Structure on a register is not supported yet."); 517 return -EINVAL;
518 }
519 if (!ref) {
520 pr_warning("Structure on a register is not "
521 "supported yet.\n");
522 return -ENOTSUP;
523 }
507 } 524 }
508 525
509 if (die_find_member(&type, field->name, die_mem) == NULL) 526 if (die_find_member(&type, field->name, die_mem) == NULL) {
510 die("%s(tyep:%s) has no member %s.", varname, 527 pr_warning("%s(tyep:%s) has no member %s.\n", varname,
511 dwarf_diename(&type), field->name); 528 dwarf_diename(&type), field->name);
529 return -EINVAL;
530 }
512 531
513 /* Get the offset of the field */ 532 /* Get the offset of the field */
514 if (dwarf_attr(die_mem, DW_AT_data_member_location, &attr) == NULL || 533 if (dwarf_attr(die_mem, DW_AT_data_member_location, &attr) == NULL ||
515 dwarf_formudata(&attr, &offs) != 0) 534 dwarf_formudata(&attr, &offs) != 0) {
516 die("Failed to get the offset of %s.", field->name); 535 pr_warning("Failed to get the offset of %s.\n", field->name);
536 return -ENOENT;
537 }
517 ref->offset += (long)offs; 538 ref->offset += (long)offs;
518 539
519 /* Converting next field */ 540 /* Converting next field */
520 if (field->next) 541 if (field->next)
521 convert_variable_fields(die_mem, field->name, field->next, 542 return convert_variable_fields(die_mem, field->name,
522 &ref, die_mem); 543 field->next, &ref, die_mem);
544 else
545 return 0;
523} 546}
524 547
525/* Show a variables in kprobe event format */ 548/* Show a variables in kprobe event format */
526static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) 549static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
527{ 550{
528 Dwarf_Attribute attr; 551 Dwarf_Attribute attr;
529 Dwarf_Die die_mem; 552 Dwarf_Die die_mem;
@@ -538,28 +561,30 @@ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
538 if (ret <= 0 || nexpr == 0) 561 if (ret <= 0 || nexpr == 0)
539 goto error; 562 goto error;
540 563
541 convert_location(expr, pf); 564 ret = convert_location(expr, pf);
542 565 if (ret == 0 && pf->pvar->field) {
543 if (pf->pvar->field) { 566 ret = convert_variable_fields(vr_die, pf->pvar->var,
544 convert_variable_fields(vr_die, pf->pvar->var, 567 pf->pvar->field, &pf->tvar->ref,
545 pf->pvar->field, &pf->tvar->ref, 568 &die_mem);
546 &die_mem);
547 vr_die = &die_mem; 569 vr_die = &die_mem;
548 } 570 }
549 if (pf->pvar->type) 571 if (ret == 0) {
550 pf->tvar->type = xstrdup(pf->pvar->type); 572 if (pf->pvar->type)
551 else 573 pf->tvar->type = xstrdup(pf->pvar->type);
552 convert_variable_type(vr_die, pf->tvar); 574 else
575 ret = convert_variable_type(vr_die, pf->tvar);
576 }
553 /* *expr will be cached in libdw. Don't free it. */ 577 /* *expr will be cached in libdw. Don't free it. */
554 return ; 578 return ret;
555error: 579error:
556 /* TODO: Support const_value */ 580 /* TODO: Support const_value */
557 die("Failed to find the location of %s at this address.\n" 581 pr_err("Failed to find the location of %s at this address.\n"
558 " Perhaps, it has been optimized out.", pf->pvar->var); 582 " Perhaps, it has been optimized out.\n", pf->pvar->var);
583 return -ENOENT;
559} 584}
560 585
561/* Find a variable in a subprogram die */ 586/* Find a variable in a subprogram die */
562static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) 587static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
563{ 588{
564 Dwarf_Die vr_die; 589 Dwarf_Die vr_die;
565 char buf[32], *ptr; 590 char buf[32], *ptr;
@@ -578,19 +603,22 @@ static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
578 if (!is_c_varname(pf->pvar->var)) { 603 if (!is_c_varname(pf->pvar->var)) {
579 /* Copy raw parameters */ 604 /* Copy raw parameters */
580 pf->tvar->value = xstrdup(pf->pvar->var); 605 pf->tvar->value = xstrdup(pf->pvar->var);
581 } else { 606 return 0;
582 pr_debug("Searching '%s' variable in context.\n",
583 pf->pvar->var);
584 /* Search child die for local variables and parameters. */
585 if (!die_find_variable(sp_die, pf->pvar->var, &vr_die))
586 die("Failed to find '%s' in this function.",
587 pf->pvar->var);
588 convert_variable(&vr_die, pf);
589 } 607 }
608
609 pr_debug("Searching '%s' variable in context.\n",
610 pf->pvar->var);
611 /* Search child die for local variables and parameters. */
612 if (!die_find_variable(sp_die, pf->pvar->var, &vr_die)) {
613 pr_warning("Failed to find '%s' in this function.\n",
614 pf->pvar->var);
615 return -ENOENT;
616 }
617 return convert_variable(&vr_die, pf);
590} 618}
591 619
592/* Show a probe point to output buffer */ 620/* Show a probe point to output buffer */
593static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) 621static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
594{ 622{
595 struct kprobe_trace_event *tev; 623 struct kprobe_trace_event *tev;
596 Dwarf_Addr eaddr; 624 Dwarf_Addr eaddr;
@@ -600,22 +628,31 @@ static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
600 Dwarf_Attribute fb_attr; 628 Dwarf_Attribute fb_attr;
601 size_t nops; 629 size_t nops;
602 630
603 if (pf->ntevs == MAX_PROBES) 631 if (pf->ntevs == MAX_PROBES) {
604 die("Too many( > %d) probe point found.\n", MAX_PROBES); 632 pr_warning("Too many( > %d) probe point found.\n", MAX_PROBES);
633 return -ERANGE;
634 }
605 tev = &pf->tevs[pf->ntevs++]; 635 tev = &pf->tevs[pf->ntevs++];
606 636
607 /* If no real subprogram, find a real one */ 637 /* If no real subprogram, find a real one */
608 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) { 638 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
609 sp_die = die_find_real_subprogram(&pf->cu_die, 639 sp_die = die_find_real_subprogram(&pf->cu_die,
610 pf->addr, &die_mem); 640 pf->addr, &die_mem);
611 if (!sp_die) 641 if (!sp_die) {
612 die("Probe point is not found in subprograms."); 642 pr_warning("Failed to find probe point in any "
643 "functions.\n");
644 return -ENOENT;
645 }
613 } 646 }
614 647
615 /* Copy the name of probe point */ 648 /* Copy the name of probe point */
616 name = dwarf_diename(sp_die); 649 name = dwarf_diename(sp_die);
617 if (name) { 650 if (name) {
618 dwarf_entrypc(sp_die, &eaddr); 651 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
652 pr_warning("Failed to get entry pc of %s\n",
653 dwarf_diename(sp_die));
654 return -ENOENT;
655 }
619 tev->point.symbol = xstrdup(name); 656 tev->point.symbol = xstrdup(name);
620 tev->point.offset = (unsigned long)(pf->addr - eaddr); 657 tev->point.offset = (unsigned long)(pf->addr - eaddr);
621 } else 658 } else
@@ -633,9 +670,12 @@ static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
633 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && 670 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
634 pf->cfi != NULL) { 671 pf->cfi != NULL) {
635 Dwarf_Frame *frame; 672 Dwarf_Frame *frame;
636 ret = dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame); 673 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
637 DIE_IF(ret != 0); 674 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
638 dwarf_frame_cfa(frame, &pf->fb_ops, &nops); 675 pr_warning("Failed to get CFA on 0x%jx\n",
676 (uintmax_t)pf->addr);
677 return -ENOENT;
678 }
639 } 679 }
640 680
641 /* Find each argument */ 681 /* Find each argument */
@@ -644,45 +684,53 @@ static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
644 for (i = 0; i < pf->pev->nargs; i++) { 684 for (i = 0; i < pf->pev->nargs; i++) {
645 pf->pvar = &pf->pev->args[i]; 685 pf->pvar = &pf->pev->args[i];
646 pf->tvar = &tev->args[i]; 686 pf->tvar = &tev->args[i];
647 find_variable(sp_die, pf); 687 ret = find_variable(sp_die, pf);
688 if (ret != 0)
689 return ret;
648 } 690 }
649 691
650 /* *pf->fb_ops will be cached in libdw. Don't free it. */ 692 /* *pf->fb_ops will be cached in libdw. Don't free it. */
651 pf->fb_ops = NULL; 693 pf->fb_ops = NULL;
694 return 0;
652} 695}
653 696
654/* Find probe point from its line number */ 697/* Find probe point from its line number */
655static void find_probe_point_by_line(struct probe_finder *pf) 698static int find_probe_point_by_line(struct probe_finder *pf)
656{ 699{
657 Dwarf_Lines *lines; 700 Dwarf_Lines *lines;
658 Dwarf_Line *line; 701 Dwarf_Line *line;
659 size_t nlines, i; 702 size_t nlines, i;
660 Dwarf_Addr addr; 703 Dwarf_Addr addr;
661 int lineno; 704 int lineno;
662 int ret; 705 int ret = 0;
663 706
664 ret = dwarf_getsrclines(&pf->cu_die, &lines, &nlines); 707 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
665 DIE_IF(ret != 0); 708 pr_warning("No source lines found in this CU.\n");
709 return -ENOENT;
710 }
666 711
667 for (i = 0; i < nlines; i++) { 712 for (i = 0; i < nlines && ret == 0; i++) {
668 line = dwarf_onesrcline(lines, i); 713 line = dwarf_onesrcline(lines, i);
669 dwarf_lineno(line, &lineno); 714 if (dwarf_lineno(line, &lineno) != 0 ||
670 if (lineno != pf->lno) 715 lineno != pf->lno)
671 continue; 716 continue;
672 717
673 /* TODO: Get fileno from line, but how? */ 718 /* TODO: Get fileno from line, but how? */
674 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0) 719 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
675 continue; 720 continue;
676 721
677 ret = dwarf_lineaddr(line, &addr); 722 if (dwarf_lineaddr(line, &addr) != 0) {
678 DIE_IF(ret != 0); 723 pr_warning("Failed to get the address of the line.\n");
724 return -ENOENT;
725 }
679 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n", 726 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
680 (int)i, lineno, (uintmax_t)addr); 727 (int)i, lineno, (uintmax_t)addr);
681 pf->addr = addr; 728 pf->addr = addr;
682 729
683 convert_probe_point(NULL, pf); 730 ret = convert_probe_point(NULL, pf);
684 /* Continuing, because target line might be inlined. */ 731 /* Continuing, because target line might be inlined. */
685 } 732 }
733 return ret;
686} 734}
687 735
688/* Find lines which match lazy pattern */ 736/* Find lines which match lazy pattern */
@@ -690,15 +738,27 @@ static int find_lazy_match_lines(struct list_head *head,
690 const char *fname, const char *pat) 738 const char *fname, const char *pat)
691{ 739{
692 char *fbuf, *p1, *p2; 740 char *fbuf, *p1, *p2;
693 int fd, line, nlines = 0; 741 int fd, ret, line, nlines = 0;
694 struct stat st; 742 struct stat st;
695 743
696 fd = open(fname, O_RDONLY); 744 fd = open(fname, O_RDONLY);
697 if (fd < 0) 745 if (fd < 0) {
698 die("failed to open %s", fname); 746 pr_warning("Failed to open %s: %s\n", fname, strerror(-fd));
699 DIE_IF(fstat(fd, &st) < 0); 747 return fd;
748 }
749
750 ret = fstat(fd, &st);
751 if (ret < 0) {
752 pr_warning("Failed to get the size of %s: %s\n",
753 fname, strerror(errno));
754 return ret;
755 }
700 fbuf = xmalloc(st.st_size + 2); 756 fbuf = xmalloc(st.st_size + 2);
701 DIE_IF(read(fd, fbuf, st.st_size) < 0); 757 ret = read(fd, fbuf, st.st_size);
758 if (ret < 0) {
759 pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
760 return ret;
761 }
702 close(fd); 762 close(fd);
703 fbuf[st.st_size] = '\n'; /* Dummy line */ 763 fbuf[st.st_size] = '\n'; /* Dummy line */
704 fbuf[st.st_size + 1] = '\0'; 764 fbuf[st.st_size + 1] = '\0';
@@ -718,7 +778,7 @@ static int find_lazy_match_lines(struct list_head *head,
718} 778}
719 779
720/* Find probe points from lazy pattern */ 780/* Find probe points from lazy pattern */
721static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) 781static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
722{ 782{
723 Dwarf_Lines *lines; 783 Dwarf_Lines *lines;
724 Dwarf_Line *line; 784 Dwarf_Line *line;
@@ -726,31 +786,40 @@ static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
726 Dwarf_Addr addr; 786 Dwarf_Addr addr;
727 Dwarf_Die die_mem; 787 Dwarf_Die die_mem;
728 int lineno; 788 int lineno;
729 int ret; 789 int ret = 0;
730 790
731 if (list_empty(&pf->lcache)) { 791 if (list_empty(&pf->lcache)) {
732 /* Matching lazy line pattern */ 792 /* Matching lazy line pattern */
733 ret = find_lazy_match_lines(&pf->lcache, pf->fname, 793 ret = find_lazy_match_lines(&pf->lcache, pf->fname,
734 pf->pev->point.lazy_line); 794 pf->pev->point.lazy_line);
735 if (ret <= 0) 795 if (ret == 0) {
736 die("No matched lines found in %s.", pf->fname); 796 pr_debug("No matched lines found in %s.\n", pf->fname);
797 return 0;
798 } else if (ret < 0)
799 return ret;
737 } 800 }
738 801
739 ret = dwarf_getsrclines(&pf->cu_die, &lines, &nlines); 802 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
740 DIE_IF(ret != 0); 803 pr_warning("No source lines found in this CU.\n");
741 for (i = 0; i < nlines; i++) { 804 return -ENOENT;
805 }
806
807 for (i = 0; i < nlines && ret >= 0; i++) {
742 line = dwarf_onesrcline(lines, i); 808 line = dwarf_onesrcline(lines, i);
743 809
744 dwarf_lineno(line, &lineno); 810 if (dwarf_lineno(line, &lineno) != 0 ||
745 if (!line_list__has_line(&pf->lcache, lineno)) 811 !line_list__has_line(&pf->lcache, lineno))
746 continue; 812 continue;
747 813
748 /* TODO: Get fileno from line, but how? */ 814 /* TODO: Get fileno from line, but how? */
749 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0) 815 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
750 continue; 816 continue;
751 817
752 ret = dwarf_lineaddr(line, &addr); 818 if (dwarf_lineaddr(line, &addr) != 0) {
753 DIE_IF(ret != 0); 819 pr_debug("Failed to get the address of line %d.\n",
820 lineno);
821 continue;
822 }
754 if (sp_die) { 823 if (sp_die) {
755 /* Address filtering 1: does sp_die include addr? */ 824 /* Address filtering 1: does sp_die include addr? */
756 if (!dwarf_haspc(sp_die, addr)) 825 if (!dwarf_haspc(sp_die, addr))
@@ -764,27 +833,42 @@ static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
764 (int)i, lineno, (unsigned long long)addr); 833 (int)i, lineno, (unsigned long long)addr);
765 pf->addr = addr; 834 pf->addr = addr;
766 835
767 convert_probe_point(sp_die, pf); 836 ret = convert_probe_point(sp_die, pf);
768 /* Continuing, because target line might be inlined. */ 837 /* Continuing, because target line might be inlined. */
769 } 838 }
770 /* TODO: deallocate lines, but how? */ 839 /* TODO: deallocate lines, but how? */
840 return ret;
771} 841}
772 842
843/* Callback parameter with return value */
844struct dwarf_callback_param {
845 void *data;
846 int retval;
847};
848
773static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) 849static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
774{ 850{
775 struct probe_finder *pf = (struct probe_finder *)data; 851 struct dwarf_callback_param *param = data;
852 struct probe_finder *pf = param->data;
776 struct perf_probe_point *pp = &pf->pev->point; 853 struct perf_probe_point *pp = &pf->pev->point;
854 Dwarf_Addr addr;
777 855
778 if (pp->lazy_line) 856 if (pp->lazy_line)
779 find_probe_point_lazy(in_die, pf); 857 param->retval = find_probe_point_lazy(in_die, pf);
780 else { 858 else {
781 /* Get probe address */ 859 /* Get probe address */
782 pf->addr = die_get_entrypc(in_die); 860 if (dwarf_entrypc(in_die, &addr) != 0) {
861 pr_warning("Failed to get entry pc of %s.\n",
862 dwarf_diename(in_die));
863 param->retval = -ENOENT;
864 return DWARF_CB_ABORT;
865 }
866 pf->addr = addr;
783 pf->addr += pp->offset; 867 pf->addr += pp->offset;
784 pr_debug("found inline addr: 0x%jx\n", 868 pr_debug("found inline addr: 0x%jx\n",
785 (uintmax_t)pf->addr); 869 (uintmax_t)pf->addr);
786 870
787 convert_probe_point(in_die, pf); 871 param->retval = convert_probe_point(in_die, pf);
788 } 872 }
789 873
790 return DWARF_CB_OK; 874 return DWARF_CB_OK;
@@ -793,39 +877,53 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
793/* Search function from function name */ 877/* Search function from function name */
794static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) 878static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
795{ 879{
796 struct probe_finder *pf = (struct probe_finder *)data; 880 struct dwarf_callback_param *param = data;
881 struct probe_finder *pf = param->data;
797 struct perf_probe_point *pp = &pf->pev->point; 882 struct perf_probe_point *pp = &pf->pev->point;
798 883
799 /* Check tag and diename */ 884 /* Check tag and diename */
800 if (dwarf_tag(sp_die) != DW_TAG_subprogram || 885 if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
801 die_compare_name(sp_die, pp->function) != 0) 886 die_compare_name(sp_die, pp->function) != 0)
802 return 0; 887 return DWARF_CB_OK;
803 888
804 pf->fname = dwarf_decl_file(sp_die); 889 pf->fname = dwarf_decl_file(sp_die);
805 if (pp->line) { /* Function relative line */ 890 if (pp->line) { /* Function relative line */
806 dwarf_decl_line(sp_die, &pf->lno); 891 dwarf_decl_line(sp_die, &pf->lno);
807 pf->lno += pp->line; 892 pf->lno += pp->line;
808 find_probe_point_by_line(pf); 893 param->retval = find_probe_point_by_line(pf);
809 } else if (!dwarf_func_inline(sp_die)) { 894 } else if (!dwarf_func_inline(sp_die)) {
810 /* Real function */ 895 /* Real function */
811 if (pp->lazy_line) 896 if (pp->lazy_line)
812 find_probe_point_lazy(sp_die, pf); 897 param->retval = find_probe_point_lazy(sp_die, pf);
813 else { 898 else {
814 pf->addr = die_get_entrypc(sp_die); 899 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
900 pr_warning("Failed to get entry pc of %s.\n",
901 dwarf_diename(sp_die));
902 param->retval = -ENOENT;
903 return DWARF_CB_ABORT;
904 }
815 pf->addr += pp->offset; 905 pf->addr += pp->offset;
816 /* TODO: Check the address in this function */ 906 /* TODO: Check the address in this function */
817 convert_probe_point(sp_die, pf); 907 param->retval = convert_probe_point(sp_die, pf);
818 } 908 }
819 } else 909 } else {
910 struct dwarf_callback_param _param = {.data = (void *)pf,
911 .retval = 0};
820 /* Inlined function: search instances */ 912 /* Inlined function: search instances */
821 dwarf_func_inline_instances(sp_die, probe_point_inline_cb, pf); 913 dwarf_func_inline_instances(sp_die, probe_point_inline_cb,
914 &_param);
915 param->retval = _param.retval;
916 }
822 917
823 return 1; /* Exit; no same symbol in this CU. */ 918 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
824} 919}
825 920
826static void find_probe_point_by_func(struct probe_finder *pf) 921static int find_probe_point_by_func(struct probe_finder *pf)
827{ 922{
828 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, pf, 0); 923 struct dwarf_callback_param _param = {.data = (void *)pf,
924 .retval = 0};
925 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
926 return _param.retval;
829} 927}
830 928
831/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ 929/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
@@ -838,14 +936,18 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
838 size_t cuhl; 936 size_t cuhl;
839 Dwarf_Die *diep; 937 Dwarf_Die *diep;
840 Dwarf *dbg; 938 Dwarf *dbg;
939 int ret = 0;
841 940
842 pf.tevs = xzalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES); 941 pf.tevs = xzalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES);
843 *tevs = pf.tevs; 942 *tevs = pf.tevs;
844 pf.ntevs = 0; 943 pf.ntevs = 0;
845 944
846 dbg = dwarf_begin(fd, DWARF_C_READ); 945 dbg = dwarf_begin(fd, DWARF_C_READ);
847 if (!dbg) 946 if (!dbg) {
848 return -ENOENT; 947 pr_warning("No dwarf info found in the vmlinux - "
948 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
949 return -EBADF;
950 }
849 951
850 /* Get the call frame information from this dwarf */ 952 /* Get the call frame information from this dwarf */
851 pf.cfi = dwarf_getcfi(dbg); 953 pf.cfi = dwarf_getcfi(dbg);
@@ -853,7 +955,8 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
853 off = 0; 955 off = 0;
854 line_list__init(&pf.lcache); 956 line_list__init(&pf.lcache);
855 /* Loop on CUs (Compilation Unit) */ 957 /* Loop on CUs (Compilation Unit) */
856 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { 958 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
959 ret >= 0) {
857 /* Get the DIE(Debugging Information Entry) of this CU */ 960 /* Get the DIE(Debugging Information Entry) of this CU */
858 diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die); 961 diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die);
859 if (!diep) 962 if (!diep)
@@ -867,12 +970,12 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
867 970
868 if (!pp->file || pf.fname) { 971 if (!pp->file || pf.fname) {
869 if (pp->function) 972 if (pp->function)
870 find_probe_point_by_func(&pf); 973 ret = find_probe_point_by_func(&pf);
871 else if (pp->lazy_line) 974 else if (pp->lazy_line)
872 find_probe_point_lazy(NULL, &pf); 975 ret = find_probe_point_lazy(NULL, &pf);
873 else { 976 else {
874 pf.lno = pp->line; 977 pf.lno = pp->line;
875 find_probe_point_by_line(&pf); 978 ret = find_probe_point_by_line(&pf);
876 } 979 }
877 } 980 }
878 off = noff; 981 off = noff;
@@ -880,7 +983,7 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
880 line_list__free(&pf.lcache); 983 line_list__free(&pf.lcache);
881 dwarf_end(dbg); 984 dwarf_end(dbg);
882 985
883 return pf.ntevs; 986 return (ret < 0) ? ret : pf.ntevs;
884} 987}
885 988
886/* Reverse search */ 989/* Reverse search */
@@ -893,10 +996,11 @@ int find_perf_probe_point(int fd, unsigned long addr,
893 Dwarf_Addr laddr, eaddr; 996 Dwarf_Addr laddr, eaddr;
894 const char *tmp; 997 const char *tmp;
895 int lineno, ret = 0; 998 int lineno, ret = 0;
999 bool found = false;
896 1000
897 dbg = dwarf_begin(fd, DWARF_C_READ); 1001 dbg = dwarf_begin(fd, DWARF_C_READ);
898 if (!dbg) 1002 if (!dbg)
899 return -ENOENT; 1003 return -EBADF;
900 1004
901 /* Find cu die */ 1005 /* Find cu die */
902 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) { 1006 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) {
@@ -907,82 +1011,87 @@ int find_perf_probe_point(int fd, unsigned long addr,
907 /* Find a corresponding line */ 1011 /* Find a corresponding line */
908 line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr); 1012 line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr);
909 if (line) { 1013 if (line) {
910 dwarf_lineaddr(line, &laddr); 1014 if (dwarf_lineaddr(line, &laddr) == 0 &&
911 if ((Dwarf_Addr)addr == laddr) { 1015 (Dwarf_Addr)addr == laddr &&
912 dwarf_lineno(line, &lineno); 1016 dwarf_lineno(line, &lineno) == 0) {
913 ppt->line = lineno;
914
915 tmp = dwarf_linesrc(line, NULL, NULL); 1017 tmp = dwarf_linesrc(line, NULL, NULL);
916 DIE_IF(!tmp); 1018 if (tmp) {
917 ppt->file = xstrdup(tmp); 1019 ppt->line = lineno;
918 ret = 1; 1020 ppt->file = xstrdup(tmp);
1021 found = true;
1022 }
919 } 1023 }
920 } 1024 }
921 1025
922 /* Find a corresponding function */ 1026 /* Find a corresponding function */
923 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { 1027 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
924 tmp = dwarf_diename(&spdie); 1028 tmp = dwarf_diename(&spdie);
925 if (!tmp) 1029 if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0)
926 goto end; 1030 goto end;
927 1031
928 dwarf_entrypc(&spdie, &eaddr); 1032 if (ppt->line) {
929 if (!lineno) { 1033 if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
930 /* We don't have a line number, let's use offset */ 1034 &indie)) {
931 ppt->function = xstrdup(tmp); 1035 /* addr in an inline function */
932 ppt->offset = addr - (unsigned long)eaddr; 1036 tmp = dwarf_diename(&indie);
933 ret = 1; 1037 if (!tmp)
934 goto end; 1038 goto end;
935 } 1039 ret = dwarf_decl_line(&indie, &lineno);
936 if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, &indie)) { 1040 } else {
937 /* addr in an inline function */ 1041 if (eaddr == addr) { /* Function entry */
938 tmp = dwarf_diename(&indie); 1042 lineno = ppt->line;
939 if (!tmp) 1043 ret = 0;
940 goto end; 1044 } else
941 dwarf_decl_line(&indie, &lineno); 1045 ret = dwarf_decl_line(&spdie, &lineno);
942 } else { 1046 }
943 if (eaddr == addr) /* No offset: function entry */ 1047 if (ret == 0) {
944 lineno = ppt->line; 1048 /* Make a relative line number */
945 else 1049 ppt->line -= lineno;
946 dwarf_decl_line(&spdie, &lineno); 1050 goto found;
1051 }
947 } 1052 }
1053 /* We don't have a line number, let's use offset */
1054 ppt->offset = addr - (unsigned long)eaddr;
1055found:
948 ppt->function = xstrdup(tmp); 1056 ppt->function = xstrdup(tmp);
949 ppt->line -= lineno; /* Make a relative line number */ 1057 found = true;
950 } 1058 }
951 1059
952end: 1060end:
953 dwarf_end(dbg); 1061 dwarf_end(dbg);
1062 if (ret >= 0)
1063 ret = found ? 1 : 0;
954 return ret; 1064 return ret;
955} 1065}
956 1066
957 1067
958/* Find line range from its line number */ 1068/* Find line range from its line number */
959static void find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) 1069static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
960{ 1070{
961 Dwarf_Lines *lines; 1071 Dwarf_Lines *lines;
962 Dwarf_Line *line; 1072 Dwarf_Line *line;
963 size_t nlines, i; 1073 size_t nlines, i;
964 Dwarf_Addr addr; 1074 Dwarf_Addr addr;
965 int lineno; 1075 int lineno;
966 int ret;
967 const char *src; 1076 const char *src;
968 Dwarf_Die die_mem; 1077 Dwarf_Die die_mem;
969 1078
970 line_list__init(&lf->lr->line_list); 1079 line_list__init(&lf->lr->line_list);
971 ret = dwarf_getsrclines(&lf->cu_die, &lines, &nlines); 1080 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
972 DIE_IF(ret != 0); 1081 pr_warning("No source lines found in this CU.\n");
1082 return -ENOENT;
1083 }
973 1084
974 for (i = 0; i < nlines; i++) { 1085 for (i = 0; i < nlines; i++) {
975 line = dwarf_onesrcline(lines, i); 1086 line = dwarf_onesrcline(lines, i);
976 ret = dwarf_lineno(line, &lineno); 1087 if (dwarf_lineno(line, &lineno) != 0 ||
977 DIE_IF(ret != 0); 1088 (lf->lno_s > lineno || lf->lno_e < lineno))
978 if (lf->lno_s > lineno || lf->lno_e < lineno)
979 continue; 1089 continue;
980 1090
981 if (sp_die) { 1091 if (sp_die) {
982 /* Address filtering 1: does sp_die include addr? */ 1092 /* Address filtering 1: does sp_die include addr? */
983 ret = dwarf_lineaddr(line, &addr); 1093 if (dwarf_lineaddr(line, &addr) != 0 ||
984 DIE_IF(ret != 0); 1094 !dwarf_haspc(sp_die, addr))
985 if (!dwarf_haspc(sp_die, addr))
986 continue; 1095 continue;
987 1096
988 /* Address filtering 2: No child include addr? */ 1097 /* Address filtering 2: No child include addr? */
@@ -1007,18 +1116,22 @@ static void find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1007 free(lf->lr->path); 1116 free(lf->lr->path);
1008 lf->lr->path = NULL; 1117 lf->lr->path = NULL;
1009 } 1118 }
1119 return lf->found;
1010} 1120}
1011 1121
1012static int line_range_inline_cb(Dwarf_Die *in_die, void *data) 1122static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
1013{ 1123{
1014 find_line_range_by_line(in_die, (struct line_finder *)data); 1124 struct dwarf_callback_param *param = data;
1125
1126 param->retval = find_line_range_by_line(in_die, param->data);
1015 return DWARF_CB_ABORT; /* No need to find other instances */ 1127 return DWARF_CB_ABORT; /* No need to find other instances */
1016} 1128}
1017 1129
1018/* Search function from function name */ 1130/* Search function from function name */
1019static int line_range_search_cb(Dwarf_Die *sp_die, void *data) 1131static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1020{ 1132{
1021 struct line_finder *lf = (struct line_finder *)data; 1133 struct dwarf_callback_param *param = data;
1134 struct line_finder *lf = param->data;
1022 struct line_range *lr = lf->lr; 1135 struct line_range *lr = lf->lr;
1023 1136
1024 if (dwarf_tag(sp_die) == DW_TAG_subprogram && 1137 if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
@@ -1033,38 +1146,47 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1033 lf->lno_e = lr->offset + lr->end; 1146 lf->lno_e = lr->offset + lr->end;
1034 lr->start = lf->lno_s; 1147 lr->start = lf->lno_s;
1035 lr->end = lf->lno_e; 1148 lr->end = lf->lno_e;
1036 if (dwarf_func_inline(sp_die)) 1149 if (dwarf_func_inline(sp_die)) {
1150 struct dwarf_callback_param _param;
1151 _param.data = (void *)lf;
1152 _param.retval = 0;
1037 dwarf_func_inline_instances(sp_die, 1153 dwarf_func_inline_instances(sp_die,
1038 line_range_inline_cb, lf); 1154 line_range_inline_cb,
1039 else 1155 &_param);
1040 find_line_range_by_line(sp_die, lf); 1156 param->retval = _param.retval;
1041 return 1; 1157 } else
1158 param->retval = find_line_range_by_line(sp_die, lf);
1159 return DWARF_CB_ABORT;
1042 } 1160 }
1043 return 0; 1161 return DWARF_CB_OK;
1044} 1162}
1045 1163
1046static void find_line_range_by_func(struct line_finder *lf) 1164static int find_line_range_by_func(struct line_finder *lf)
1047{ 1165{
1048 dwarf_getfuncs(&lf->cu_die, line_range_search_cb, lf, 0); 1166 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1167 dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
1168 return param.retval;
1049} 1169}
1050 1170
1051int find_line_range(int fd, struct line_range *lr) 1171int find_line_range(int fd, struct line_range *lr)
1052{ 1172{
1053 struct line_finder lf = {.lr = lr, .found = 0}; 1173 struct line_finder lf = {.lr = lr, .found = 0};
1054 int ret; 1174 int ret = 0;
1055 Dwarf_Off off = 0, noff; 1175 Dwarf_Off off = 0, noff;
1056 size_t cuhl; 1176 size_t cuhl;
1057 Dwarf_Die *diep; 1177 Dwarf_Die *diep;
1058 Dwarf *dbg; 1178 Dwarf *dbg;
1059 1179
1060 dbg = dwarf_begin(fd, DWARF_C_READ); 1180 dbg = dwarf_begin(fd, DWARF_C_READ);
1061 if (!dbg) 1181 if (!dbg) {
1062 return -ENOENT; 1182 pr_warning("No dwarf info found in the vmlinux - "
1183 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1184 return -EBADF;
1185 }
1063 1186
1064 /* Loop on CUs (Compilation Unit) */ 1187 /* Loop on CUs (Compilation Unit) */
1065 while (!lf.found) { 1188 while (!lf.found && ret >= 0) {
1066 ret = dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL); 1189 if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
1067 if (ret != 0)
1068 break; 1190 break;
1069 1191
1070 /* Get the DIE(Debugging Information Entry) of this CU */ 1192 /* Get the DIE(Debugging Information Entry) of this CU */
@@ -1080,20 +1202,21 @@ int find_line_range(int fd, struct line_range *lr)
1080 1202
1081 if (!lr->file || lf.fname) { 1203 if (!lr->file || lf.fname) {
1082 if (lr->function) 1204 if (lr->function)
1083 find_line_range_by_func(&lf); 1205 ret = find_line_range_by_func(&lf);
1084 else { 1206 else {
1085 lf.lno_s = lr->start; 1207 lf.lno_s = lr->start;
1086 if (!lr->end) 1208 if (!lr->end)
1087 lf.lno_e = INT_MAX; 1209 lf.lno_e = INT_MAX;
1088 else 1210 else
1089 lf.lno_e = lr->end; 1211 lf.lno_e = lr->end;
1090 find_line_range_by_line(NULL, &lf); 1212 ret = find_line_range_by_line(NULL, &lf);
1091 } 1213 }
1092 } 1214 }
1093 off = noff; 1215 off = noff;
1094 } 1216 }
1095 pr_debug("path: %lx\n", (unsigned long)lr->path); 1217 pr_debug("path: %lx\n", (unsigned long)lr->path);
1096 dwarf_end(dbg); 1218 dwarf_end(dbg);
1097 return lf.found; 1219
1220 return (ret < 0) ? ret : lf.found;
1098} 1221}
1099 1222