aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/annotate.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2014-11-12 21:05:26 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2014-11-19 10:33:48 -0500
commite592488c01d51763de847fcecb3d969231a483a9 (patch)
tree5d835af0655251082dbca113e98e5df1cd0e413f /tools/perf/util/annotate.c
parent2de217688e8f086bf6d920d530401b56fcbc6eff (diff)
perf annotate: Support source line numbers in annotate
With srcline key/sort'ing it's useful to have line numbers in the annotate window. This patch implements this. Use objdump -l to request the line numbers and save them in the line structure. Then the browser displays them for source lines. The line numbers are not displayed by default, but can be toggled on with 'k' There is one unfortunate problem with this setup. For lines not containing source and which are outside functions objdump -l reports line numbers off by a few: it always reports the first line number in the next function even for lines that are outside the function. I haven't found a nice way to detect/correct this. Probably objdump has to be fixed. See https://sourceware.org/bugzilla/show_bug.cgi?id=16433 The line numbers are still useful even with these problems, as most are correct and the ones which are not are nearby. v2: Fix help text. Handle (discriminator...) output in objdump. Left align the line numbers. Signed-off-by: Andi Kleen <ak@linux.intel.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Link: http://lkml.kernel.org/r/1415844328-4884-9-git-send-email-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/annotate.c')
-rw-r--r--tools/perf/util/annotate.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 873c8778db20..e5670f1af737 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -17,11 +17,13 @@
17#include "debug.h" 17#include "debug.h"
18#include "annotate.h" 18#include "annotate.h"
19#include "evsel.h" 19#include "evsel.h"
20#include <regex.h>
20#include <pthread.h> 21#include <pthread.h>
21#include <linux/bitops.h> 22#include <linux/bitops.h>
22 23
23const char *disassembler_style; 24const char *disassembler_style;
24const char *objdump_path; 25const char *objdump_path;
26static regex_t file_lineno;
25 27
26static struct ins *ins__find(const char *name); 28static struct ins *ins__find(const char *name);
27static int disasm_line__parse(char *line, char **namep, char **rawp); 29static int disasm_line__parse(char *line, char **namep, char **rawp);
@@ -570,13 +572,15 @@ out_free_name:
570 return -1; 572 return -1;
571} 573}
572 574
573static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize) 575static struct disasm_line *disasm_line__new(s64 offset, char *line,
576 size_t privsize, int line_nr)
574{ 577{
575 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); 578 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
576 579
577 if (dl != NULL) { 580 if (dl != NULL) {
578 dl->offset = offset; 581 dl->offset = offset;
579 dl->line = strdup(line); 582 dl->line = strdup(line);
583 dl->line_nr = line_nr;
580 if (dl->line == NULL) 584 if (dl->line == NULL)
581 goto out_delete; 585 goto out_delete;
582 586
@@ -788,13 +792,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
788 * The ops.raw part will be parsed further according to type of the instruction. 792 * The ops.raw part will be parsed further according to type of the instruction.
789 */ 793 */
790static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, 794static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
791 FILE *file, size_t privsize) 795 FILE *file, size_t privsize,
796 int *line_nr)
792{ 797{
793 struct annotation *notes = symbol__annotation(sym); 798 struct annotation *notes = symbol__annotation(sym);
794 struct disasm_line *dl; 799 struct disasm_line *dl;
795 char *line = NULL, *parsed_line, *tmp, *tmp2, *c; 800 char *line = NULL, *parsed_line, *tmp, *tmp2, *c;
796 size_t line_len; 801 size_t line_len;
797 s64 line_ip, offset = -1; 802 s64 line_ip, offset = -1;
803 regmatch_t match[2];
798 804
799 if (getline(&line, &line_len, file) < 0) 805 if (getline(&line, &line_len, file) < 0)
800 return -1; 806 return -1;
@@ -812,6 +818,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
812 line_ip = -1; 818 line_ip = -1;
813 parsed_line = line; 819 parsed_line = line;
814 820
821 /* /filename:linenr ? Save line number and ignore. */
822 if (regexec(&file_lineno, line, 2, match, 0) == 0) {
823 *line_nr = atoi(line + match[1].rm_so);
824 return 0;
825 }
826
815 /* 827 /*
816 * Strip leading spaces: 828 * Strip leading spaces:
817 */ 829 */
@@ -842,8 +854,9 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
842 parsed_line = tmp2 + 1; 854 parsed_line = tmp2 + 1;
843 } 855 }
844 856
845 dl = disasm_line__new(offset, parsed_line, privsize); 857 dl = disasm_line__new(offset, parsed_line, privsize, *line_nr);
846 free(line); 858 free(line);
859 (*line_nr)++;
847 860
848 if (dl == NULL) 861 if (dl == NULL)
849 return -1; 862 return -1;
@@ -869,6 +882,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
869 return 0; 882 return 0;
870} 883}
871 884
885static __attribute__((constructor)) void symbol__init_regexpr(void)
886{
887 regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED);
888}
889
872static void delete_last_nop(struct symbol *sym) 890static void delete_last_nop(struct symbol *sym)
873{ 891{
874 struct annotation *notes = symbol__annotation(sym); 892 struct annotation *notes = symbol__annotation(sym);
@@ -904,6 +922,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
904 char symfs_filename[PATH_MAX]; 922 char symfs_filename[PATH_MAX];
905 struct kcore_extract kce; 923 struct kcore_extract kce;
906 bool delete_extract = false; 924 bool delete_extract = false;
925 int lineno = 0;
907 926
908 if (filename) 927 if (filename)
909 symbol__join_symfs(symfs_filename, filename); 928 symbol__join_symfs(symfs_filename, filename);
@@ -984,7 +1003,7 @@ fallback:
984 snprintf(command, sizeof(command), 1003 snprintf(command, sizeof(command),
985 "%s %s%s --start-address=0x%016" PRIx64 1004 "%s %s%s --start-address=0x%016" PRIx64
986 " --stop-address=0x%016" PRIx64 1005 " --stop-address=0x%016" PRIx64
987 " -d %s %s -C %s 2>/dev/null|grep -v %s|expand", 1006 " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand",
988 objdump_path ? objdump_path : "objdump", 1007 objdump_path ? objdump_path : "objdump",
989 disassembler_style ? "-M " : "", 1008 disassembler_style ? "-M " : "",
990 disassembler_style ? disassembler_style : "", 1009 disassembler_style ? disassembler_style : "",
@@ -1001,7 +1020,8 @@ fallback:
1001 goto out_free_filename; 1020 goto out_free_filename;
1002 1021
1003 while (!feof(file)) 1022 while (!feof(file))
1004 if (symbol__parse_objdump_line(sym, map, file, privsize) < 0) 1023 if (symbol__parse_objdump_line(sym, map, file, privsize,
1024 &lineno) < 0)
1005 break; 1025 break;
1006 1026
1007 /* 1027 /*