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.c107
1 files changed, 45 insertions, 62 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 722c0f54e549..5e17de984dc8 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,16 +25,13 @@
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
35static char default_sort_order[] = "comm,symbol"; 31static char default_sort_order[] = "comm,symbol";
36static char *sort_order = default_sort_order; 32static char *sort_order = default_sort_order;
37 33
34static int force;
38static int input; 35static int input;
39static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; 36static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
40 37
@@ -43,6 +40,10 @@ static int dump_trace = 0;
43 40
44static int verbose; 41static int verbose;
45 42
43static int modules;
44
45static int full_paths;
46
46static int print_line; 47static int print_line;
47 48
48static unsigned long page_size; 49static unsigned long page_size;
@@ -74,20 +75,12 @@ struct fork_event {
74 u32 pid, ppid; 75 u32 pid, ppid;
75}; 76};
76 77
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 { 78typedef union event_union {
85 struct perf_event_header header; 79 struct perf_event_header header;
86 struct ip_event ip; 80 struct ip_event ip;
87 struct mmap_event mmap; 81 struct mmap_event mmap;
88 struct comm_event comm; 82 struct comm_event comm;
89 struct fork_event fork; 83 struct fork_event fork;
90 struct period_event period;
91} event_t; 84} event_t;
92 85
93 86
@@ -160,7 +153,7 @@ static void dsos__fprintf(FILE *fp)
160 153
161static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 154static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
162{ 155{
163 return dso__find_symbol(kernel_dso, ip); 156 return dso__find_symbol(dso, ip);
164} 157}
165 158
166static int load_kernel(void) 159static int load_kernel(void)
@@ -171,8 +164,8 @@ static int load_kernel(void)
171 if (!kernel_dso) 164 if (!kernel_dso)
172 return -1; 165 return -1;
173 166
174 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); 167 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules);
175 if (err) { 168 if (err <= 0) {
176 dso__delete(kernel_dso); 169 dso__delete(kernel_dso);
177 kernel_dso = NULL; 170 kernel_dso = NULL;
178 } else 171 } else
@@ -203,7 +196,7 @@ static u64 map__map_ip(struct map *map, u64 ip)
203 return ip - map->start + map->pgoff; 196 return ip - map->start + map->pgoff;
204} 197}
205 198
206static u64 vdso__map_ip(struct map *map, u64 ip) 199static u64 vdso__map_ip(struct map *map __used, u64 ip)
207{ 200{
208 return ip; 201 return ip;
209} 202}
@@ -600,7 +593,7 @@ static LIST_HEAD(hist_entry__sort_list);
600 593
601static int sort_dimension__add(char *tok) 594static int sort_dimension__add(char *tok)
602{ 595{
603 int i; 596 unsigned int i;
604 597
605 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { 598 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
606 struct sort_dimension *sd = &sort_dimensions[i]; 599 struct sort_dimension *sd = &sort_dimensions[i];
@@ -988,6 +981,13 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
988 (void *)(long)(event->header.size), 981 (void *)(long)(event->header.size),
989 event->fork.pid, event->fork.ppid); 982 event->fork.pid, event->fork.ppid);
990 983
984 /*
985 * A thread clone will have the same PID for both
986 * parent and child.
987 */
988 if (thread == parent)
989 return 0;
990
991 if (!thread || !parent || thread__fork(thread, parent)) { 991 if (!thread || !parent || thread__fork(thread, parent)) {
992 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); 992 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
993 return -1; 993 return -1;
@@ -998,19 +998,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
998} 998}
999 999
1000static int 1000static 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) 1001process_event(event_t *event, unsigned long offset, unsigned long head)
1015{ 1002{
1016 switch (event->header.type) { 1003 switch (event->header.type) {
@@ -1025,9 +1012,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1025 1012
1026 case PERF_EVENT_FORK: 1013 case PERF_EVENT_FORK:
1027 return process_fork_event(event, offset, head); 1014 return process_fork_event(event, offset, head);
1028
1029 case PERF_EVENT_PERIOD:
1030 return process_period_event(event, offset, head);
1031 /* 1015 /*
1032 * We dont process them right now but they are fine: 1016 * We dont process them right now but they are fine:
1033 */ 1017 */
@@ -1043,24 +1027,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1043 return 0; 1027 return 0;
1044} 1028}
1045 1029
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 1030static int
1065parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) 1031parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1066{ 1032{
@@ -1069,7 +1035,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1069 static const char *prev_color; 1035 static const char *prev_color;
1070 unsigned int offset; 1036 unsigned int offset;
1071 size_t line_len; 1037 size_t line_len;
1072 u64 line_ip; 1038 s64 line_ip;
1073 int ret; 1039 int ret;
1074 char *c; 1040 char *c;
1075 1041
@@ -1122,7 +1088,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1122 } else if (sym->hist_sum) 1088 } else if (sym->hist_sum)
1123 percent = 100.0 * hits / sym->hist_sum; 1089 percent = 100.0 * hits / sym->hist_sum;
1124 1090
1125 color = get_color(percent); 1091 color = get_percent_color(percent);
1126 1092
1127 /* 1093 /*
1128 * Also color the filename and line if needed, with 1094 * Also color the filename and line if needed, with
@@ -1258,7 +1224,7 @@ static void print_summary(char *filename)
1258 1224
1259 sym_ext = rb_entry(node, struct sym_ext, node); 1225 sym_ext = rb_entry(node, struct sym_ext, node);
1260 percent = sym_ext->percent; 1226 percent = sym_ext->percent;
1261 color = get_color(percent); 1227 color = get_percent_color(percent);
1262 path = sym_ext->path; 1228 path = sym_ext->path;
1263 1229
1264 color_fprintf(stdout, color, " %7.2f %s", percent, path); 1230 color_fprintf(stdout, color, " %7.2f %s", percent, path);
@@ -1268,19 +1234,25 @@ static void print_summary(char *filename)
1268 1234
1269static void annotate_sym(struct dso *dso, struct symbol *sym) 1235static void annotate_sym(struct dso *dso, struct symbol *sym)
1270{ 1236{
1271 char *filename = dso->name; 1237 char *filename = dso->name, *d_filename;
1272 u64 start, end, len; 1238 u64 start, end, len;
1273 char command[PATH_MAX*2]; 1239 char command[PATH_MAX*2];
1274 FILE *file; 1240 FILE *file;
1275 1241
1276 if (!filename) 1242 if (!filename)
1277 return; 1243 return;
1278 if (dso == kernel_dso) 1244 if (sym->module)
1245 filename = sym->module->path;
1246 else if (dso == kernel_dso)
1279 filename = vmlinux; 1247 filename = vmlinux;
1280 1248
1281 start = sym->obj_start; 1249 start = sym->obj_start;
1282 if (!start) 1250 if (!start)
1283 start = sym->start; 1251 start = sym->start;
1252 if (full_paths)
1253 d_filename = filename;
1254 else
1255 d_filename = basename(filename);
1284 1256
1285 end = start + sym->end - sym->start + 1; 1257 end = start + sym->end - sym->start + 1;
1286 len = sym->end - sym->start; 1258 len = sym->end - sym->start;
@@ -1291,13 +1263,14 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
1291 } 1263 }
1292 1264
1293 printf("\n\n------------------------------------------------\n"); 1265 printf("\n\n------------------------------------------------\n");
1294 printf(" Percent | Source code & Disassembly of %s\n", filename); 1266 printf(" Percent | Source code & Disassembly of %s\n", d_filename);
1295 printf("------------------------------------------------\n"); 1267 printf("------------------------------------------------\n");
1296 1268
1297 if (verbose >= 2) 1269 if (verbose >= 2)
1298 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 1270 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);
1299 1271
1300 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (u64)start, (u64)end, filename); 1272 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
1273 (u64)start, (u64)end, filename, filename);
1301 1274
1302 if (verbose >= 3) 1275 if (verbose >= 3)
1303 printf("doing: %s\n", command); 1276 printf("doing: %s\n", command);
@@ -1362,6 +1335,11 @@ static int __cmd_annotate(void)
1362 exit(-1); 1335 exit(-1);
1363 } 1336 }
1364 1337
1338 if (!force && (stat.st_uid != geteuid())) {
1339 fprintf(stderr, "file: %s not owned by current user\n", input_name);
1340 exit(-1);
1341 }
1342
1365 if (!stat.st_size) { 1343 if (!stat.st_size) {
1366 fprintf(stderr, "zero-sized file, nothing to do!\n"); 1344 fprintf(stderr, "zero-sized file, nothing to do!\n");
1367 exit(0); 1345 exit(0);
@@ -1428,7 +1406,7 @@ more:
1428 1406
1429 head += size; 1407 head += size;
1430 1408
1431 if (offset + head < stat.st_size) 1409 if (offset + head < (unsigned long)stat.st_size)
1432 goto more; 1410 goto more;
1433 1411
1434 rc = EXIT_SUCCESS; 1412 rc = EXIT_SUCCESS;
@@ -1467,13 +1445,18 @@ static const struct option options[] = {
1467 "input file name"), 1445 "input file name"),
1468 OPT_STRING('s', "symbol", &sym_hist_filter, "symbol", 1446 OPT_STRING('s', "symbol", &sym_hist_filter, "symbol",
1469 "symbol to annotate"), 1447 "symbol to annotate"),
1448 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
1470 OPT_BOOLEAN('v', "verbose", &verbose, 1449 OPT_BOOLEAN('v', "verbose", &verbose,
1471 "be more verbose (show symbol address, etc)"), 1450 "be more verbose (show symbol address, etc)"),
1472 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1451 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1473 "dump raw trace in ASCII"), 1452 "dump raw trace in ASCII"),
1474 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1453 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1454 OPT_BOOLEAN('m', "modules", &modules,
1455 "load module symbols - WARNING: use only with -k and LIVE kernel"),
1475 OPT_BOOLEAN('l', "print-line", &print_line, 1456 OPT_BOOLEAN('l', "print-line", &print_line,
1476 "print matching source lines (may be slow)"), 1457 "print matching source lines (may be slow)"),
1458 OPT_BOOLEAN('P', "full-paths", &full_paths,
1459 "Don't shorten the displayed pathnames"),
1477 OPT_END() 1460 OPT_END()
1478}; 1461};
1479 1462
@@ -1492,7 +1475,7 @@ static void setup_sorting(void)
1492 free(str); 1475 free(str);
1493} 1476}
1494 1477
1495int cmd_annotate(int argc, const char **argv, const char *prefix) 1478int cmd_annotate(int argc, const char **argv, const char *prefix __used)
1496{ 1479{
1497 symbol__init(); 1480 symbol__init();
1498 1481