diff options
Diffstat (limited to 'tools/perf/builtin-script.c')
| -rw-r--r-- | tools/perf/builtin-script.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 3ea98fe72f7f..3728b50e52e2 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
| @@ -96,6 +96,7 @@ enum perf_output_field { | |||
| 96 | PERF_OUTPUT_UREGS = 1U << 27, | 96 | PERF_OUTPUT_UREGS = 1U << 27, |
| 97 | PERF_OUTPUT_METRIC = 1U << 28, | 97 | PERF_OUTPUT_METRIC = 1U << 28, |
| 98 | PERF_OUTPUT_MISC = 1U << 29, | 98 | PERF_OUTPUT_MISC = 1U << 29, |
| 99 | PERF_OUTPUT_SRCCODE = 1U << 30, | ||
| 99 | }; | 100 | }; |
| 100 | 101 | ||
| 101 | struct output_option { | 102 | struct output_option { |
| @@ -132,6 +133,7 @@ struct output_option { | |||
| 132 | {.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR}, | 133 | {.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR}, |
| 133 | {.str = "metric", .field = PERF_OUTPUT_METRIC}, | 134 | {.str = "metric", .field = PERF_OUTPUT_METRIC}, |
| 134 | {.str = "misc", .field = PERF_OUTPUT_MISC}, | 135 | {.str = "misc", .field = PERF_OUTPUT_MISC}, |
| 136 | {.str = "srccode", .field = PERF_OUTPUT_SRCCODE}, | ||
| 135 | }; | 137 | }; |
| 136 | 138 | ||
| 137 | enum { | 139 | enum { |
| @@ -424,7 +426,7 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, | |||
| 424 | pr_err("Display of DSO requested but no address to convert.\n"); | 426 | pr_err("Display of DSO requested but no address to convert.\n"); |
| 425 | return -EINVAL; | 427 | return -EINVAL; |
| 426 | } | 428 | } |
| 427 | if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) { | 429 | if ((PRINT_FIELD(SRCLINE) || PRINT_FIELD(SRCCODE)) && !PRINT_FIELD(IP)) { |
| 428 | pr_err("Display of source line number requested but sample IP is not\n" | 430 | pr_err("Display of source line number requested but sample IP is not\n" |
| 429 | "selected. Hence, no address to lookup the source line number.\n"); | 431 | "selected. Hence, no address to lookup the source line number.\n"); |
| 430 | return -EINVAL; | 432 | return -EINVAL; |
| @@ -907,6 +909,22 @@ static int grab_bb(u8 *buffer, u64 start, u64 end, | |||
| 907 | return len; | 909 | return len; |
| 908 | } | 910 | } |
| 909 | 911 | ||
| 912 | static int print_srccode(struct thread *thread, u8 cpumode, uint64_t addr) | ||
| 913 | { | ||
| 914 | struct addr_location al; | ||
| 915 | int ret = 0; | ||
| 916 | |||
| 917 | memset(&al, 0, sizeof(al)); | ||
| 918 | thread__find_map(thread, cpumode, addr, &al); | ||
| 919 | if (!al.map) | ||
| 920 | return 0; | ||
| 921 | ret = map__fprintf_srccode(al.map, al.addr, stdout, | ||
| 922 | &thread->srccode_state); | ||
| 923 | if (ret) | ||
| 924 | ret += printf("\n"); | ||
| 925 | return ret; | ||
| 926 | } | ||
| 927 | |||
| 910 | static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en, | 928 | static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en, |
| 911 | struct perf_insn *x, u8 *inbuf, int len, | 929 | struct perf_insn *x, u8 *inbuf, int len, |
| 912 | int insn, FILE *fp, int *total_cycles) | 930 | int insn, FILE *fp, int *total_cycles) |
| @@ -998,6 +1016,8 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, | |||
| 998 | x.cpumode, x.cpu, &lastsym, attr, fp); | 1016 | x.cpumode, x.cpu, &lastsym, attr, fp); |
| 999 | printed += ip__fprintf_jump(br->entries[nr - 1].from, &br->entries[nr - 1], | 1017 | printed += ip__fprintf_jump(br->entries[nr - 1].from, &br->entries[nr - 1], |
| 1000 | &x, buffer, len, 0, fp, &total_cycles); | 1018 | &x, buffer, len, 0, fp, &total_cycles); |
| 1019 | if (PRINT_FIELD(SRCCODE)) | ||
| 1020 | printed += print_srccode(thread, x.cpumode, br->entries[nr - 1].from); | ||
| 1001 | } | 1021 | } |
| 1002 | 1022 | ||
| 1003 | /* Print all blocks */ | 1023 | /* Print all blocks */ |
| @@ -1027,12 +1047,16 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, | |||
| 1027 | if (ip == end) { | 1047 | if (ip == end) { |
| 1028 | printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp, | 1048 | printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp, |
| 1029 | &total_cycles); | 1049 | &total_cycles); |
| 1050 | if (PRINT_FIELD(SRCCODE)) | ||
| 1051 | printed += print_srccode(thread, x.cpumode, ip); | ||
| 1030 | break; | 1052 | break; |
| 1031 | } else { | 1053 | } else { |
| 1032 | printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip, | 1054 | printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip, |
| 1033 | dump_insn(&x, ip, buffer + off, len - off, &ilen)); | 1055 | dump_insn(&x, ip, buffer + off, len - off, &ilen)); |
| 1034 | if (ilen == 0) | 1056 | if (ilen == 0) |
| 1035 | break; | 1057 | break; |
| 1058 | if (PRINT_FIELD(SRCCODE)) | ||
| 1059 | print_srccode(thread, x.cpumode, ip); | ||
| 1036 | insn++; | 1060 | insn++; |
| 1037 | } | 1061 | } |
| 1038 | } | 1062 | } |
| @@ -1063,6 +1087,8 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, | |||
| 1063 | 1087 | ||
| 1064 | printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", sample->ip, | 1088 | printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", sample->ip, |
| 1065 | dump_insn(&x, sample->ip, buffer, len, NULL)); | 1089 | dump_insn(&x, sample->ip, buffer, len, NULL)); |
| 1090 | if (PRINT_FIELD(SRCCODE)) | ||
| 1091 | print_srccode(thread, x.cpumode, sample->ip); | ||
| 1066 | goto out; | 1092 | goto out; |
| 1067 | } | 1093 | } |
| 1068 | for (off = 0; off <= end - start; off += ilen) { | 1094 | for (off = 0; off <= end - start; off += ilen) { |
| @@ -1070,6 +1096,8 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, | |||
| 1070 | dump_insn(&x, start + off, buffer + off, len - off, &ilen)); | 1096 | dump_insn(&x, start + off, buffer + off, len - off, &ilen)); |
| 1071 | if (ilen == 0) | 1097 | if (ilen == 0) |
| 1072 | break; | 1098 | break; |
| 1099 | if (PRINT_FIELD(SRCCODE)) | ||
| 1100 | print_srccode(thread, x.cpumode, start + off); | ||
| 1073 | } | 1101 | } |
| 1074 | out: | 1102 | out: |
| 1075 | return printed; | 1103 | return printed; |
| @@ -1252,7 +1280,16 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample, | |||
| 1252 | printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp); | 1280 | printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp); |
| 1253 | 1281 | ||
| 1254 | printed += perf_sample__fprintf_insn(sample, attr, thread, machine, fp); | 1282 | printed += perf_sample__fprintf_insn(sample, attr, thread, machine, fp); |
| 1255 | return printed + fprintf(fp, "\n"); | 1283 | printed += fprintf(fp, "\n"); |
| 1284 | if (PRINT_FIELD(SRCCODE)) { | ||
| 1285 | int ret = map__fprintf_srccode(al->map, al->addr, stdout, | ||
| 1286 | &thread->srccode_state); | ||
| 1287 | if (ret) { | ||
| 1288 | printed += ret; | ||
| 1289 | printed += printf("\n"); | ||
| 1290 | } | ||
| 1291 | } | ||
| 1292 | return printed; | ||
| 1256 | } | 1293 | } |
| 1257 | 1294 | ||
| 1258 | static struct { | 1295 | static struct { |
| @@ -1792,6 +1829,12 @@ static void process_event(struct perf_script *script, | |||
| 1792 | fprintf(fp, "%16" PRIx64, sample->phys_addr); | 1829 | fprintf(fp, "%16" PRIx64, sample->phys_addr); |
| 1793 | fprintf(fp, "\n"); | 1830 | fprintf(fp, "\n"); |
| 1794 | 1831 | ||
| 1832 | if (PRINT_FIELD(SRCCODE)) { | ||
| 1833 | if (map__fprintf_srccode(al->map, al->addr, stdout, | ||
| 1834 | &thread->srccode_state)) | ||
| 1835 | printf("\n"); | ||
| 1836 | } | ||
| 1837 | |||
| 1795 | if (PRINT_FIELD(METRIC)) | 1838 | if (PRINT_FIELD(METRIC)) |
| 1796 | perf_sample__fprint_metric(script, thread, evsel, sample, fp); | 1839 | perf_sample__fprint_metric(script, thread, evsel, sample, fp); |
| 1797 | 1840 | ||
