diff options
Diffstat (limited to 'tools/perf/util/annotate.c')
-rw-r--r-- | tools/perf/util/annotate.c | 63 |
1 files changed, 44 insertions, 19 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 809b4c50beae..79999ceaf2be 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 | ||
23 | const char *disassembler_style; | 24 | const char *disassembler_style; |
24 | const char *objdump_path; | 25 | const char *objdump_path; |
26 | static regex_t file_lineno; | ||
25 | 27 | ||
26 | static struct ins *ins__find(const char *name); | 28 | static struct ins *ins__find(const char *name); |
27 | static int disasm_line__parse(char *line, char **namep, char **rawp); | 29 | static int disasm_line__parse(char *line, char **namep, char **rawp); |
@@ -232,9 +234,16 @@ static int mov__parse(struct ins_operands *ops) | |||
232 | return -1; | 234 | return -1; |
233 | 235 | ||
234 | target = ++s; | 236 | target = ++s; |
237 | comment = strchr(s, '#'); | ||
235 | 238 | ||
236 | while (s[0] != '\0' && !isspace(s[0])) | 239 | if (comment != NULL) |
237 | ++s; | 240 | s = comment - 1; |
241 | else | ||
242 | s = strchr(s, '\0') - 1; | ||
243 | |||
244 | while (s > target && isspace(s[0])) | ||
245 | --s; | ||
246 | s++; | ||
238 | prev = *s; | 247 | prev = *s; |
239 | *s = '\0'; | 248 | *s = '\0'; |
240 | 249 | ||
@@ -244,7 +253,6 @@ static int mov__parse(struct ins_operands *ops) | |||
244 | if (ops->target.raw == NULL) | 253 | if (ops->target.raw == NULL) |
245 | goto out_free_source; | 254 | goto out_free_source; |
246 | 255 | ||
247 | comment = strchr(s, '#'); | ||
248 | if (comment == NULL) | 256 | if (comment == NULL) |
249 | return 0; | 257 | return 0; |
250 | 258 | ||
@@ -472,7 +480,7 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, | |||
472 | 480 | ||
473 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); | 481 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); |
474 | 482 | ||
475 | if (addr < sym->start || addr > sym->end) | 483 | if (addr < sym->start || addr >= sym->end) |
476 | return -ERANGE; | 484 | return -ERANGE; |
477 | 485 | ||
478 | offset = addr - sym->start; | 486 | offset = addr - sym->start; |
@@ -564,13 +572,15 @@ out_free_name: | |||
564 | return -1; | 572 | return -1; |
565 | } | 573 | } |
566 | 574 | ||
567 | static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize) | 575 | static struct disasm_line *disasm_line__new(s64 offset, char *line, |
576 | size_t privsize, int line_nr) | ||
568 | { | 577 | { |
569 | struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); | 578 | struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); |
570 | 579 | ||
571 | if (dl != NULL) { | 580 | if (dl != NULL) { |
572 | dl->offset = offset; | 581 | dl->offset = offset; |
573 | dl->line = strdup(line); | 582 | dl->line = strdup(line); |
583 | dl->line_nr = line_nr; | ||
574 | if (dl->line == NULL) | 584 | if (dl->line == NULL) |
575 | goto out_delete; | 585 | goto out_delete; |
576 | 586 | ||
@@ -782,13 +792,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st | |||
782 | * 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. |
783 | */ | 793 | */ |
784 | static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | 794 | static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, |
785 | FILE *file, size_t privsize) | 795 | FILE *file, size_t privsize, |
796 | int *line_nr) | ||
786 | { | 797 | { |
787 | struct annotation *notes = symbol__annotation(sym); | 798 | struct annotation *notes = symbol__annotation(sym); |
788 | struct disasm_line *dl; | 799 | struct disasm_line *dl; |
789 | char *line = NULL, *parsed_line, *tmp, *tmp2, *c; | 800 | char *line = NULL, *parsed_line, *tmp, *tmp2, *c; |
790 | size_t line_len; | 801 | size_t line_len; |
791 | s64 line_ip, offset = -1; | 802 | s64 line_ip, offset = -1; |
803 | regmatch_t match[2]; | ||
792 | 804 | ||
793 | if (getline(&line, &line_len, file) < 0) | 805 | if (getline(&line, &line_len, file) < 0) |
794 | return -1; | 806 | return -1; |
@@ -806,6 +818,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | |||
806 | line_ip = -1; | 818 | line_ip = -1; |
807 | parsed_line = line; | 819 | parsed_line = line; |
808 | 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 | |||
809 | /* | 827 | /* |
810 | * Strip leading spaces: | 828 | * Strip leading spaces: |
811 | */ | 829 | */ |
@@ -830,14 +848,15 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | |||
830 | end = map__rip_2objdump(map, sym->end); | 848 | end = map__rip_2objdump(map, sym->end); |
831 | 849 | ||
832 | offset = line_ip - start; | 850 | offset = line_ip - start; |
833 | if ((u64)line_ip < start || (u64)line_ip > end) | 851 | if ((u64)line_ip < start || (u64)line_ip >= end) |
834 | offset = -1; | 852 | offset = -1; |
835 | else | 853 | else |
836 | parsed_line = tmp2 + 1; | 854 | parsed_line = tmp2 + 1; |
837 | } | 855 | } |
838 | 856 | ||
839 | dl = disasm_line__new(offset, parsed_line, privsize); | 857 | dl = disasm_line__new(offset, parsed_line, privsize, *line_nr); |
840 | free(line); | 858 | free(line); |
859 | (*line_nr)++; | ||
841 | 860 | ||
842 | if (dl == NULL) | 861 | if (dl == NULL) |
843 | return -1; | 862 | return -1; |
@@ -863,6 +882,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | |||
863 | return 0; | 882 | return 0; |
864 | } | 883 | } |
865 | 884 | ||
885 | static __attribute__((constructor)) void symbol__init_regexpr(void) | ||
886 | { | ||
887 | regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED); | ||
888 | } | ||
889 | |||
866 | static void delete_last_nop(struct symbol *sym) | 890 | static void delete_last_nop(struct symbol *sym) |
867 | { | 891 | { |
868 | struct annotation *notes = symbol__annotation(sym); | 892 | struct annotation *notes = symbol__annotation(sym); |
@@ -898,11 +922,10 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) | |||
898 | char symfs_filename[PATH_MAX]; | 922 | char symfs_filename[PATH_MAX]; |
899 | struct kcore_extract kce; | 923 | struct kcore_extract kce; |
900 | bool delete_extract = false; | 924 | bool delete_extract = false; |
925 | int lineno = 0; | ||
901 | 926 | ||
902 | if (filename) { | 927 | if (filename) |
903 | snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", | 928 | symbol__join_symfs(symfs_filename, filename); |
904 | symbol_conf.symfs, filename); | ||
905 | } | ||
906 | 929 | ||
907 | if (filename == NULL) { | 930 | if (filename == NULL) { |
908 | if (dso->has_build_id) { | 931 | if (dso->has_build_id) { |
@@ -911,6 +934,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) | |||
911 | return -ENOMEM; | 934 | return -ENOMEM; |
912 | } | 935 | } |
913 | goto fallback; | 936 | goto fallback; |
937 | } else if (dso__is_kcore(dso)) { | ||
938 | goto fallback; | ||
914 | } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || | 939 | } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || |
915 | strstr(command, "[kernel.kallsyms]") || | 940 | strstr(command, "[kernel.kallsyms]") || |
916 | access(symfs_filename, R_OK)) { | 941 | access(symfs_filename, R_OK)) { |
@@ -922,8 +947,7 @@ fallback: | |||
922 | * DSO is the same as when 'perf record' ran. | 947 | * DSO is the same as when 'perf record' ran. |
923 | */ | 948 | */ |
924 | filename = (char *)dso->long_name; | 949 | filename = (char *)dso->long_name; |
925 | snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", | 950 | symbol__join_symfs(symfs_filename, filename); |
926 | symbol_conf.symfs, filename); | ||
927 | free_filename = false; | 951 | free_filename = false; |
928 | } | 952 | } |
929 | 953 | ||
@@ -963,7 +987,7 @@ fallback: | |||
963 | kce.kcore_filename = symfs_filename; | 987 | kce.kcore_filename = symfs_filename; |
964 | kce.addr = map__rip_2objdump(map, sym->start); | 988 | kce.addr = map__rip_2objdump(map, sym->start); |
965 | kce.offs = sym->start; | 989 | kce.offs = sym->start; |
966 | kce.len = sym->end + 1 - sym->start; | 990 | kce.len = sym->end - sym->start; |
967 | if (!kcore_extract__create(&kce)) { | 991 | if (!kcore_extract__create(&kce)) { |
968 | delete_extract = true; | 992 | delete_extract = true; |
969 | strlcpy(symfs_filename, kce.extract_filename, | 993 | strlcpy(symfs_filename, kce.extract_filename, |
@@ -979,12 +1003,12 @@ fallback: | |||
979 | snprintf(command, sizeof(command), | 1003 | snprintf(command, sizeof(command), |
980 | "%s %s%s --start-address=0x%016" PRIx64 | 1004 | "%s %s%s --start-address=0x%016" PRIx64 |
981 | " --stop-address=0x%016" PRIx64 | 1005 | " --stop-address=0x%016" PRIx64 |
982 | " -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", |
983 | objdump_path ? objdump_path : "objdump", | 1007 | objdump_path ? objdump_path : "objdump", |
984 | disassembler_style ? "-M " : "", | 1008 | disassembler_style ? "-M " : "", |
985 | disassembler_style ? disassembler_style : "", | 1009 | disassembler_style ? disassembler_style : "", |
986 | map__rip_2objdump(map, sym->start), | 1010 | map__rip_2objdump(map, sym->start), |
987 | map__rip_2objdump(map, sym->end+1), | 1011 | map__rip_2objdump(map, sym->end), |
988 | symbol_conf.annotate_asm_raw ? "" : "--no-show-raw", | 1012 | symbol_conf.annotate_asm_raw ? "" : "--no-show-raw", |
989 | symbol_conf.annotate_src ? "-S" : "", | 1013 | symbol_conf.annotate_src ? "-S" : "", |
990 | symfs_filename, filename); | 1014 | symfs_filename, filename); |
@@ -996,7 +1020,8 @@ fallback: | |||
996 | goto out_free_filename; | 1020 | goto out_free_filename; |
997 | 1021 | ||
998 | while (!feof(file)) | 1022 | while (!feof(file)) |
999 | if (symbol__parse_objdump_line(sym, map, file, privsize) < 0) | 1023 | if (symbol__parse_objdump_line(sym, map, file, privsize, |
1024 | &lineno) < 0) | ||
1000 | break; | 1025 | break; |
1001 | 1026 | ||
1002 | /* | 1027 | /* |
@@ -1167,7 +1192,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, | |||
1167 | goto next; | 1192 | goto next; |
1168 | 1193 | ||
1169 | offset = start + i; | 1194 | offset = start + i; |
1170 | src_line->path = get_srcline(map->dso, offset); | 1195 | src_line->path = get_srcline(map->dso, offset, NULL, false); |
1171 | insert_source_line(&tmp_root, src_line); | 1196 | insert_source_line(&tmp_root, src_line); |
1172 | 1197 | ||
1173 | next: | 1198 | next: |