aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-annotate.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r--tools/perf/builtin-annotate.c100
1 files changed, 38 insertions, 62 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 722c0f54e549..343e7b14bf01 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
32static char const *input_name = "perf.data"; 28static char const *input_name = "perf.data";
33static char *vmlinux = "vmlinux"; 29static char *vmlinux = "vmlinux";
34 30
@@ -43,6 +39,10 @@ static int dump_trace = 0;
43 39
44static int verbose; 40static int verbose;
45 41
42static int modules;
43
44static int full_paths;
45
46static int print_line; 46static int print_line;
47 47
48static unsigned long page_size; 48static unsigned long page_size;
@@ -74,20 +74,12 @@ struct fork_event {
74 u32 pid, ppid; 74 u32 pid, ppid;
75}; 75};
76 76
77struct period_event {
78 struct perf_event_header header;
79 u64 time;
80 u64 id;
81 u64 sample_period;
82};
83
84typedef union event_union { 77typedef 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
161static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 153static 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
166static int load_kernel(void) 158static 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
206static u64 vdso__map_ip(struct map *map, u64 ip) 198static 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
601static int sort_dimension__add(char *tok) 593static 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];
@@ -988,6 +980,13 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
988 (void *)(long)(event->header.size), 980 (void *)(long)(event->header.size),
989 event->fork.pid, event->fork.ppid); 981 event->fork.pid, event->fork.ppid);
990 982
983 /*
984 * A thread clone will have the same PID for both
985 * parent and child.
986 */
987 if (thread == parent)
988 return 0;
989
991 if (!thread || !parent || thread__fork(thread, parent)) { 990 if (!thread || !parent || thread__fork(thread, parent)) {
992 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); 991 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
993 return -1; 992 return -1;
@@ -998,19 +997,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
998} 997}
999 998
1000static int 999static int
1001process_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
1013static int
1014process_event(event_t *event, unsigned long offset, unsigned long head) 1000process_event(event_t *event, unsigned long offset, unsigned long head)
1015{ 1001{
1016 switch (event->header.type) { 1002 switch (event->header.type) {
@@ -1025,9 +1011,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1025 1011
1026 case PERF_EVENT_FORK: 1012 case PERF_EVENT_FORK:
1027 return process_fork_event(event, offset, head); 1013 return process_fork_event(event, offset, head);
1028
1029 case PERF_EVENT_PERIOD:
1030 return process_period_event(event, offset, head);
1031 /* 1014 /*
1032 * We dont process them right now but they are fine: 1015 * We dont process them right now but they are fine:
1033 */ 1016 */
@@ -1043,24 +1026,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1043 return 0; 1026 return 0;
1044} 1027}
1045 1028
1046static 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
1064static int 1029static int
1065parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) 1030parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1066{ 1031{
@@ -1069,7 +1034,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1069 static const char *prev_color; 1034 static const char *prev_color;
1070 unsigned int offset; 1035 unsigned int offset;
1071 size_t line_len; 1036 size_t line_len;
1072 u64 line_ip; 1037 s64 line_ip;
1073 int ret; 1038 int ret;
1074 char *c; 1039 char *c;
1075 1040
@@ -1122,7 +1087,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1122 } else if (sym->hist_sum) 1087 } else if (sym->hist_sum)
1123 percent = 100.0 * hits / sym->hist_sum; 1088 percent = 100.0 * hits / sym->hist_sum;
1124 1089
1125 color = get_color(percent); 1090 color = get_percent_color(percent);
1126 1091
1127 /* 1092 /*
1128 * Also color the filename and line if needed, with 1093 * Also color the filename and line if needed, with
@@ -1258,7 +1223,7 @@ static void print_summary(char *filename)
1258 1223
1259 sym_ext = rb_entry(node, struct sym_ext, node); 1224 sym_ext = rb_entry(node, struct sym_ext, node);
1260 percent = sym_ext->percent; 1225 percent = sym_ext->percent;
1261 color = get_color(percent); 1226 color = get_percent_color(percent);
1262 path = sym_ext->path; 1227 path = sym_ext->path;
1263 1228
1264 color_fprintf(stdout, color, " %7.2f %s", percent, path); 1229 color_fprintf(stdout, color, " %7.2f %s", percent, path);
@@ -1268,19 +1233,25 @@ static void print_summary(char *filename)
1268 1233
1269static void annotate_sym(struct dso *dso, struct symbol *sym) 1234static void annotate_sym(struct dso *dso, struct symbol *sym)
1270{ 1235{
1271 char *filename = dso->name; 1236 char *filename = dso->name, *d_filename;
1272 u64 start, end, len; 1237 u64 start, end, len;
1273 char command[PATH_MAX*2]; 1238 char command[PATH_MAX*2];
1274 FILE *file; 1239 FILE *file;
1275 1240
1276 if (!filename) 1241 if (!filename)
1277 return; 1242 return;
1278 if (dso == kernel_dso) 1243 if (sym->module)
1244 filename = sym->module->path;
1245 else if (dso == kernel_dso)
1279 filename = vmlinux; 1246 filename = vmlinux;
1280 1247
1281 start = sym->obj_start; 1248 start = sym->obj_start;
1282 if (!start) 1249 if (!start)
1283 start = sym->start; 1250 start = sym->start;
1251 if (full_paths)
1252 d_filename = filename;
1253 else
1254 d_filename = basename(filename);
1284 1255
1285 end = start + sym->end - sym->start + 1; 1256 end = start + sym->end - sym->start + 1;
1286 len = sym->end - sym->start; 1257 len = sym->end - sym->start;
@@ -1291,13 +1262,14 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
1291 } 1262 }
1292 1263
1293 printf("\n\n------------------------------------------------\n"); 1264 printf("\n\n------------------------------------------------\n");
1294 printf(" Percent | Source code & Disassembly of %s\n", filename); 1265 printf(" Percent | Source code & Disassembly of %s\n", d_filename);
1295 printf("------------------------------------------------\n"); 1266 printf("------------------------------------------------\n");
1296 1267
1297 if (verbose >= 2) 1268 if (verbose >= 2)
1298 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 1269 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);
1299 1270
1300 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (u64)start, (u64)end, filename); 1271 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
1272 (u64)start, (u64)end, filename, filename);
1301 1273
1302 if (verbose >= 3) 1274 if (verbose >= 3)
1303 printf("doing: %s\n", command); 1275 printf("doing: %s\n", command);
@@ -1428,7 +1400,7 @@ more:
1428 1400
1429 head += size; 1401 head += size;
1430 1402
1431 if (offset + head < stat.st_size) 1403 if (offset + head < (unsigned long)stat.st_size)
1432 goto more; 1404 goto more;
1433 1405
1434 rc = EXIT_SUCCESS; 1406 rc = EXIT_SUCCESS;
@@ -1472,8 +1444,12 @@ static const struct option options[] = {
1472 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1444 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1473 "dump raw trace in ASCII"), 1445 "dump raw trace in ASCII"),
1474 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1446 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1447 OPT_BOOLEAN('m', "modules", &modules,
1448 "load module symbols - WARNING: use only with -k and LIVE kernel"),
1475 OPT_BOOLEAN('l', "print-line", &print_line, 1449 OPT_BOOLEAN('l', "print-line", &print_line,
1476 "print matching source lines (may be slow)"), 1450 "print matching source lines (may be slow)"),
1451 OPT_BOOLEAN('P', "full-paths", &full_paths,
1452 "Don't shorten the displayed pathnames"),
1477 OPT_END() 1453 OPT_END()
1478}; 1454};
1479 1455
@@ -1492,7 +1468,7 @@ static void setup_sorting(void)
1492 free(str); 1468 free(str);
1493} 1469}
1494 1470
1495int cmd_annotate(int argc, const char **argv, const char *prefix) 1471int cmd_annotate(int argc, const char **argv, const char *prefix __used)
1496{ 1472{
1497 symbol__init(); 1473 symbol__init();
1498 1474