diff options
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r-- | tools/perf/builtin-annotate.c | 93 |
1 files changed, 31 insertions, 62 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 722c0f54e549..1dba568e1941 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -10,9 +10,9 @@ | |||
10 | #include "util/util.h" | 10 | #include "util/util.h" |
11 | 11 | ||
12 | #include "util/color.h" | 12 | #include "util/color.h" |
13 | #include "util/list.h" | 13 | #include <linux/list.h> |
14 | #include "util/cache.h" | 14 | #include "util/cache.h" |
15 | #include "util/rbtree.h" | 15 | #include <linux/rbtree.h> |
16 | #include "util/symbol.h" | 16 | #include "util/symbol.h" |
17 | #include "util/string.h" | 17 | #include "util/string.h" |
18 | 18 | ||
@@ -25,10 +25,6 @@ | |||
25 | #define SHOW_USER 2 | 25 | #define SHOW_USER 2 |
26 | #define SHOW_HV 4 | 26 | #define SHOW_HV 4 |
27 | 27 | ||
28 | #define MIN_GREEN 0.5 | ||
29 | #define MIN_RED 5.0 | ||
30 | |||
31 | |||
32 | static char const *input_name = "perf.data"; | 28 | static char const *input_name = "perf.data"; |
33 | static char *vmlinux = "vmlinux"; | 29 | static char *vmlinux = "vmlinux"; |
34 | 30 | ||
@@ -43,6 +39,10 @@ static int dump_trace = 0; | |||
43 | 39 | ||
44 | static int verbose; | 40 | static int verbose; |
45 | 41 | ||
42 | static int modules; | ||
43 | |||
44 | static int full_paths; | ||
45 | |||
46 | static int print_line; | 46 | static int print_line; |
47 | 47 | ||
48 | static unsigned long page_size; | 48 | static unsigned long page_size; |
@@ -74,20 +74,12 @@ struct fork_event { | |||
74 | u32 pid, ppid; | 74 | u32 pid, ppid; |
75 | }; | 75 | }; |
76 | 76 | ||
77 | struct period_event { | ||
78 | struct perf_event_header header; | ||
79 | u64 time; | ||
80 | u64 id; | ||
81 | u64 sample_period; | ||
82 | }; | ||
83 | |||
84 | typedef union event_union { | 77 | typedef union event_union { |
85 | struct perf_event_header header; | 78 | struct perf_event_header header; |
86 | struct ip_event ip; | 79 | struct ip_event ip; |
87 | struct mmap_event mmap; | 80 | struct mmap_event mmap; |
88 | struct comm_event comm; | 81 | struct comm_event comm; |
89 | struct fork_event fork; | 82 | struct fork_event fork; |
90 | struct period_event period; | ||
91 | } event_t; | 83 | } event_t; |
92 | 84 | ||
93 | 85 | ||
@@ -160,7 +152,7 @@ static void dsos__fprintf(FILE *fp) | |||
160 | 152 | ||
161 | static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) | 153 | static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) |
162 | { | 154 | { |
163 | return dso__find_symbol(kernel_dso, ip); | 155 | return dso__find_symbol(dso, ip); |
164 | } | 156 | } |
165 | 157 | ||
166 | static int load_kernel(void) | 158 | static int load_kernel(void) |
@@ -171,8 +163,8 @@ static int load_kernel(void) | |||
171 | if (!kernel_dso) | 163 | if (!kernel_dso) |
172 | return -1; | 164 | return -1; |
173 | 165 | ||
174 | err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); | 166 | err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules); |
175 | if (err) { | 167 | if (err <= 0) { |
176 | dso__delete(kernel_dso); | 168 | dso__delete(kernel_dso); |
177 | kernel_dso = NULL; | 169 | kernel_dso = NULL; |
178 | } else | 170 | } else |
@@ -203,7 +195,7 @@ static u64 map__map_ip(struct map *map, u64 ip) | |||
203 | return ip - map->start + map->pgoff; | 195 | return ip - map->start + map->pgoff; |
204 | } | 196 | } |
205 | 197 | ||
206 | static u64 vdso__map_ip(struct map *map, u64 ip) | 198 | static u64 vdso__map_ip(struct map *map __used, u64 ip) |
207 | { | 199 | { |
208 | return ip; | 200 | return ip; |
209 | } | 201 | } |
@@ -600,7 +592,7 @@ static LIST_HEAD(hist_entry__sort_list); | |||
600 | 592 | ||
601 | static int sort_dimension__add(char *tok) | 593 | static int sort_dimension__add(char *tok) |
602 | { | 594 | { |
603 | int i; | 595 | unsigned int i; |
604 | 596 | ||
605 | for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { | 597 | for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { |
606 | struct sort_dimension *sd = &sort_dimensions[i]; | 598 | struct sort_dimension *sd = &sort_dimensions[i]; |
@@ -998,19 +990,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head) | |||
998 | } | 990 | } |
999 | 991 | ||
1000 | static int | 992 | static int |
1001 | process_period_event(event_t *event, unsigned long offset, unsigned long head) | ||
1002 | { | ||
1003 | dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n", | ||
1004 | (void *)(offset + head), | ||
1005 | (void *)(long)(event->header.size), | ||
1006 | event->period.time, | ||
1007 | event->period.id, | ||
1008 | event->period.sample_period); | ||
1009 | |||
1010 | return 0; | ||
1011 | } | ||
1012 | |||
1013 | static int | ||
1014 | process_event(event_t *event, unsigned long offset, unsigned long head) | 993 | process_event(event_t *event, unsigned long offset, unsigned long head) |
1015 | { | 994 | { |
1016 | switch (event->header.type) { | 995 | switch (event->header.type) { |
@@ -1025,9 +1004,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head) | |||
1025 | 1004 | ||
1026 | case PERF_EVENT_FORK: | 1005 | case PERF_EVENT_FORK: |
1027 | return process_fork_event(event, offset, head); | 1006 | return process_fork_event(event, offset, head); |
1028 | |||
1029 | case PERF_EVENT_PERIOD: | ||
1030 | return process_period_event(event, offset, head); | ||
1031 | /* | 1007 | /* |
1032 | * We dont process them right now but they are fine: | 1008 | * We dont process them right now but they are fine: |
1033 | */ | 1009 | */ |
@@ -1043,24 +1019,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head) | |||
1043 | return 0; | 1019 | return 0; |
1044 | } | 1020 | } |
1045 | 1021 | ||
1046 | static char *get_color(double percent) | ||
1047 | { | ||
1048 | char *color = PERF_COLOR_NORMAL; | ||
1049 | |||
1050 | /* | ||
1051 | * We color high-overhead entries in red, mid-overhead | ||
1052 | * entries in green - and keep the low overhead places | ||
1053 | * normal: | ||
1054 | */ | ||
1055 | if (percent >= MIN_RED) | ||
1056 | color = PERF_COLOR_RED; | ||
1057 | else { | ||
1058 | if (percent > MIN_GREEN) | ||
1059 | color = PERF_COLOR_GREEN; | ||
1060 | } | ||
1061 | return color; | ||
1062 | } | ||
1063 | |||
1064 | static int | 1022 | static int |
1065 | parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) | 1023 | parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) |
1066 | { | 1024 | { |
@@ -1069,7 +1027,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) | |||
1069 | static const char *prev_color; | 1027 | static const char *prev_color; |
1070 | unsigned int offset; | 1028 | unsigned int offset; |
1071 | size_t line_len; | 1029 | size_t line_len; |
1072 | u64 line_ip; | 1030 | s64 line_ip; |
1073 | int ret; | 1031 | int ret; |
1074 | char *c; | 1032 | char *c; |
1075 | 1033 | ||
@@ -1122,7 +1080,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) | |||
1122 | } else if (sym->hist_sum) | 1080 | } else if (sym->hist_sum) |
1123 | percent = 100.0 * hits / sym->hist_sum; | 1081 | percent = 100.0 * hits / sym->hist_sum; |
1124 | 1082 | ||
1125 | color = get_color(percent); | 1083 | color = get_percent_color(percent); |
1126 | 1084 | ||
1127 | /* | 1085 | /* |
1128 | * Also color the filename and line if needed, with | 1086 | * Also color the filename and line if needed, with |
@@ -1258,7 +1216,7 @@ static void print_summary(char *filename) | |||
1258 | 1216 | ||
1259 | sym_ext = rb_entry(node, struct sym_ext, node); | 1217 | sym_ext = rb_entry(node, struct sym_ext, node); |
1260 | percent = sym_ext->percent; | 1218 | percent = sym_ext->percent; |
1261 | color = get_color(percent); | 1219 | color = get_percent_color(percent); |
1262 | path = sym_ext->path; | 1220 | path = sym_ext->path; |
1263 | 1221 | ||
1264 | color_fprintf(stdout, color, " %7.2f %s", percent, path); | 1222 | color_fprintf(stdout, color, " %7.2f %s", percent, path); |
@@ -1268,19 +1226,25 @@ static void print_summary(char *filename) | |||
1268 | 1226 | ||
1269 | static void annotate_sym(struct dso *dso, struct symbol *sym) | 1227 | static void annotate_sym(struct dso *dso, struct symbol *sym) |
1270 | { | 1228 | { |
1271 | char *filename = dso->name; | 1229 | char *filename = dso->name, *d_filename; |
1272 | u64 start, end, len; | 1230 | u64 start, end, len; |
1273 | char command[PATH_MAX*2]; | 1231 | char command[PATH_MAX*2]; |
1274 | FILE *file; | 1232 | FILE *file; |
1275 | 1233 | ||
1276 | if (!filename) | 1234 | if (!filename) |
1277 | return; | 1235 | return; |
1278 | if (dso == kernel_dso) | 1236 | if (sym->module) |
1237 | filename = sym->module->path; | ||
1238 | else if (dso == kernel_dso) | ||
1279 | filename = vmlinux; | 1239 | filename = vmlinux; |
1280 | 1240 | ||
1281 | start = sym->obj_start; | 1241 | start = sym->obj_start; |
1282 | if (!start) | 1242 | if (!start) |
1283 | start = sym->start; | 1243 | start = sym->start; |
1244 | if (full_paths) | ||
1245 | d_filename = filename; | ||
1246 | else | ||
1247 | d_filename = basename(filename); | ||
1284 | 1248 | ||
1285 | end = start + sym->end - sym->start + 1; | 1249 | end = start + sym->end - sym->start + 1; |
1286 | len = sym->end - sym->start; | 1250 | len = sym->end - sym->start; |
@@ -1291,13 +1255,14 @@ static void annotate_sym(struct dso *dso, struct symbol *sym) | |||
1291 | } | 1255 | } |
1292 | 1256 | ||
1293 | printf("\n\n------------------------------------------------\n"); | 1257 | printf("\n\n------------------------------------------------\n"); |
1294 | printf(" Percent | Source code & Disassembly of %s\n", filename); | 1258 | printf(" Percent | Source code & Disassembly of %s\n", d_filename); |
1295 | printf("------------------------------------------------\n"); | 1259 | printf("------------------------------------------------\n"); |
1296 | 1260 | ||
1297 | if (verbose >= 2) | 1261 | if (verbose >= 2) |
1298 | printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); | 1262 | printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); |
1299 | 1263 | ||
1300 | sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (u64)start, (u64)end, filename); | 1264 | sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", |
1265 | (u64)start, (u64)end, filename, filename); | ||
1301 | 1266 | ||
1302 | if (verbose >= 3) | 1267 | if (verbose >= 3) |
1303 | printf("doing: %s\n", command); | 1268 | printf("doing: %s\n", command); |
@@ -1428,7 +1393,7 @@ more: | |||
1428 | 1393 | ||
1429 | head += size; | 1394 | head += size; |
1430 | 1395 | ||
1431 | if (offset + head < stat.st_size) | 1396 | if (offset + head < (unsigned long)stat.st_size) |
1432 | goto more; | 1397 | goto more; |
1433 | 1398 | ||
1434 | rc = EXIT_SUCCESS; | 1399 | rc = EXIT_SUCCESS; |
@@ -1472,8 +1437,12 @@ static const struct option options[] = { | |||
1472 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, | 1437 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, |
1473 | "dump raw trace in ASCII"), | 1438 | "dump raw trace in ASCII"), |
1474 | OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), | 1439 | OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), |
1440 | OPT_BOOLEAN('m', "modules", &modules, | ||
1441 | "load module symbols - WARNING: use only with -k and LIVE kernel"), | ||
1475 | OPT_BOOLEAN('l', "print-line", &print_line, | 1442 | OPT_BOOLEAN('l', "print-line", &print_line, |
1476 | "print matching source lines (may be slow)"), | 1443 | "print matching source lines (may be slow)"), |
1444 | OPT_BOOLEAN('P', "full-paths", &full_paths, | ||
1445 | "Don't shorten the displayed pathnames"), | ||
1477 | OPT_END() | 1446 | OPT_END() |
1478 | }; | 1447 | }; |
1479 | 1448 | ||
@@ -1492,7 +1461,7 @@ static void setup_sorting(void) | |||
1492 | free(str); | 1461 | free(str); |
1493 | } | 1462 | } |
1494 | 1463 | ||
1495 | int cmd_annotate(int argc, const char **argv, const char *prefix) | 1464 | int cmd_annotate(int argc, const char **argv, const char *prefix __used) |
1496 | { | 1465 | { |
1497 | symbol__init(); | 1466 | symbol__init(); |
1498 | 1467 | ||