diff options
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r-- | tools/perf/builtin-annotate.c | 459 |
1 files changed, 54 insertions, 405 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 5e17de984dc8..4ac618b34254 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -17,16 +17,13 @@ | |||
17 | #include "util/string.h" | 17 | #include "util/string.h" |
18 | 18 | ||
19 | #include "perf.h" | 19 | #include "perf.h" |
20 | #include "util/debug.h" | ||
20 | 21 | ||
21 | #include "util/parse-options.h" | 22 | #include "util/parse-options.h" |
22 | #include "util/parse-events.h" | 23 | #include "util/parse-events.h" |
23 | 24 | #include "util/thread.h" | |
24 | #define SHOW_KERNEL 1 | ||
25 | #define SHOW_USER 2 | ||
26 | #define SHOW_HV 4 | ||
27 | 25 | ||
28 | static char const *input_name = "perf.data"; | 26 | static char const *input_name = "perf.data"; |
29 | static char *vmlinux = "vmlinux"; | ||
30 | 27 | ||
31 | static char default_sort_order[] = "comm,symbol"; | 28 | static char default_sort_order[] = "comm,symbol"; |
32 | static char *sort_order = default_sort_order; | 29 | static char *sort_order = default_sort_order; |
@@ -35,13 +32,6 @@ static int force; | |||
35 | static int input; | 32 | static int input; |
36 | static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; | 33 | static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; |
37 | 34 | ||
38 | static int dump_trace = 0; | ||
39 | #define dprintf(x...) do { if (dump_trace) printf(x); } while (0) | ||
40 | |||
41 | static int verbose; | ||
42 | |||
43 | static int modules; | ||
44 | |||
45 | static int full_paths; | 35 | static int full_paths; |
46 | 36 | ||
47 | static int print_line; | 37 | static int print_line; |
@@ -49,39 +39,8 @@ static int print_line; | |||
49 | static unsigned long page_size; | 39 | static unsigned long page_size; |
50 | static unsigned long mmap_window = 32; | 40 | static unsigned long mmap_window = 32; |
51 | 41 | ||
52 | struct ip_event { | 42 | static struct rb_root threads; |
53 | struct perf_event_header header; | 43 | static struct thread *last_match; |
54 | u64 ip; | ||
55 | u32 pid, tid; | ||
56 | }; | ||
57 | |||
58 | struct mmap_event { | ||
59 | struct perf_event_header header; | ||
60 | u32 pid, tid; | ||
61 | u64 start; | ||
62 | u64 len; | ||
63 | u64 pgoff; | ||
64 | char filename[PATH_MAX]; | ||
65 | }; | ||
66 | |||
67 | struct comm_event { | ||
68 | struct perf_event_header header; | ||
69 | u32 pid, tid; | ||
70 | char comm[16]; | ||
71 | }; | ||
72 | |||
73 | struct fork_event { | ||
74 | struct perf_event_header header; | ||
75 | u32 pid, ppid; | ||
76 | }; | ||
77 | |||
78 | typedef union event_union { | ||
79 | struct perf_event_header header; | ||
80 | struct ip_event ip; | ||
81 | struct mmap_event mmap; | ||
82 | struct comm_event comm; | ||
83 | struct fork_event fork; | ||
84 | } event_t; | ||
85 | 44 | ||
86 | 45 | ||
87 | struct sym_ext { | 46 | struct sym_ext { |
@@ -90,323 +49,6 @@ struct sym_ext { | |||
90 | char *path; | 49 | char *path; |
91 | }; | 50 | }; |
92 | 51 | ||
93 | static LIST_HEAD(dsos); | ||
94 | static struct dso *kernel_dso; | ||
95 | static struct dso *vdso; | ||
96 | |||
97 | |||
98 | static void dsos__add(struct dso *dso) | ||
99 | { | ||
100 | list_add_tail(&dso->node, &dsos); | ||
101 | } | ||
102 | |||
103 | static struct dso *dsos__find(const char *name) | ||
104 | { | ||
105 | struct dso *pos; | ||
106 | |||
107 | list_for_each_entry(pos, &dsos, node) | ||
108 | if (strcmp(pos->name, name) == 0) | ||
109 | return pos; | ||
110 | return NULL; | ||
111 | } | ||
112 | |||
113 | static struct dso *dsos__findnew(const char *name) | ||
114 | { | ||
115 | struct dso *dso = dsos__find(name); | ||
116 | int nr; | ||
117 | |||
118 | if (dso) | ||
119 | return dso; | ||
120 | |||
121 | dso = dso__new(name, 0); | ||
122 | if (!dso) | ||
123 | goto out_delete_dso; | ||
124 | |||
125 | nr = dso__load(dso, NULL, verbose); | ||
126 | if (nr < 0) { | ||
127 | if (verbose) | ||
128 | fprintf(stderr, "Failed to open: %s\n", name); | ||
129 | goto out_delete_dso; | ||
130 | } | ||
131 | if (!nr && verbose) { | ||
132 | fprintf(stderr, | ||
133 | "No symbols found in: %s, maybe install a debug package?\n", | ||
134 | name); | ||
135 | } | ||
136 | |||
137 | dsos__add(dso); | ||
138 | |||
139 | return dso; | ||
140 | |||
141 | out_delete_dso: | ||
142 | dso__delete(dso); | ||
143 | return NULL; | ||
144 | } | ||
145 | |||
146 | static void dsos__fprintf(FILE *fp) | ||
147 | { | ||
148 | struct dso *pos; | ||
149 | |||
150 | list_for_each_entry(pos, &dsos, node) | ||
151 | dso__fprintf(pos, fp); | ||
152 | } | ||
153 | |||
154 | static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) | ||
155 | { | ||
156 | return dso__find_symbol(dso, ip); | ||
157 | } | ||
158 | |||
159 | static int load_kernel(void) | ||
160 | { | ||
161 | int err; | ||
162 | |||
163 | kernel_dso = dso__new("[kernel]", 0); | ||
164 | if (!kernel_dso) | ||
165 | return -1; | ||
166 | |||
167 | err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules); | ||
168 | if (err <= 0) { | ||
169 | dso__delete(kernel_dso); | ||
170 | kernel_dso = NULL; | ||
171 | } else | ||
172 | dsos__add(kernel_dso); | ||
173 | |||
174 | vdso = dso__new("[vdso]", 0); | ||
175 | if (!vdso) | ||
176 | return -1; | ||
177 | |||
178 | vdso->find_symbol = vdso__find_symbol; | ||
179 | |||
180 | dsos__add(vdso); | ||
181 | |||
182 | return err; | ||
183 | } | ||
184 | |||
185 | struct map { | ||
186 | struct list_head node; | ||
187 | u64 start; | ||
188 | u64 end; | ||
189 | u64 pgoff; | ||
190 | u64 (*map_ip)(struct map *, u64); | ||
191 | struct dso *dso; | ||
192 | }; | ||
193 | |||
194 | static u64 map__map_ip(struct map *map, u64 ip) | ||
195 | { | ||
196 | return ip - map->start + map->pgoff; | ||
197 | } | ||
198 | |||
199 | static u64 vdso__map_ip(struct map *map __used, u64 ip) | ||
200 | { | ||
201 | return ip; | ||
202 | } | ||
203 | |||
204 | static struct map *map__new(struct mmap_event *event) | ||
205 | { | ||
206 | struct map *self = malloc(sizeof(*self)); | ||
207 | |||
208 | if (self != NULL) { | ||
209 | const char *filename = event->filename; | ||
210 | |||
211 | self->start = event->start; | ||
212 | self->end = event->start + event->len; | ||
213 | self->pgoff = event->pgoff; | ||
214 | |||
215 | self->dso = dsos__findnew(filename); | ||
216 | if (self->dso == NULL) | ||
217 | goto out_delete; | ||
218 | |||
219 | if (self->dso == vdso) | ||
220 | self->map_ip = vdso__map_ip; | ||
221 | else | ||
222 | self->map_ip = map__map_ip; | ||
223 | } | ||
224 | return self; | ||
225 | out_delete: | ||
226 | free(self); | ||
227 | return NULL; | ||
228 | } | ||
229 | |||
230 | static struct map *map__clone(struct map *self) | ||
231 | { | ||
232 | struct map *map = malloc(sizeof(*self)); | ||
233 | |||
234 | if (!map) | ||
235 | return NULL; | ||
236 | |||
237 | memcpy(map, self, sizeof(*self)); | ||
238 | |||
239 | return map; | ||
240 | } | ||
241 | |||
242 | static int map__overlap(struct map *l, struct map *r) | ||
243 | { | ||
244 | if (l->start > r->start) { | ||
245 | struct map *t = l; | ||
246 | l = r; | ||
247 | r = t; | ||
248 | } | ||
249 | |||
250 | if (l->end > r->start) | ||
251 | return 1; | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static size_t map__fprintf(struct map *self, FILE *fp) | ||
257 | { | ||
258 | return fprintf(fp, " %Lx-%Lx %Lx %s\n", | ||
259 | self->start, self->end, self->pgoff, self->dso->name); | ||
260 | } | ||
261 | |||
262 | |||
263 | struct thread { | ||
264 | struct rb_node rb_node; | ||
265 | struct list_head maps; | ||
266 | pid_t pid; | ||
267 | char *comm; | ||
268 | }; | ||
269 | |||
270 | static struct thread *thread__new(pid_t pid) | ||
271 | { | ||
272 | struct thread *self = malloc(sizeof(*self)); | ||
273 | |||
274 | if (self != NULL) { | ||
275 | self->pid = pid; | ||
276 | self->comm = malloc(32); | ||
277 | if (self->comm) | ||
278 | snprintf(self->comm, 32, ":%d", self->pid); | ||
279 | INIT_LIST_HEAD(&self->maps); | ||
280 | } | ||
281 | |||
282 | return self; | ||
283 | } | ||
284 | |||
285 | static int thread__set_comm(struct thread *self, const char *comm) | ||
286 | { | ||
287 | if (self->comm) | ||
288 | free(self->comm); | ||
289 | self->comm = strdup(comm); | ||
290 | return self->comm ? 0 : -ENOMEM; | ||
291 | } | ||
292 | |||
293 | static size_t thread__fprintf(struct thread *self, FILE *fp) | ||
294 | { | ||
295 | struct map *pos; | ||
296 | size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); | ||
297 | |||
298 | list_for_each_entry(pos, &self->maps, node) | ||
299 | ret += map__fprintf(pos, fp); | ||
300 | |||
301 | return ret; | ||
302 | } | ||
303 | |||
304 | |||
305 | static struct rb_root threads; | ||
306 | static struct thread *last_match; | ||
307 | |||
308 | static struct thread *threads__findnew(pid_t pid) | ||
309 | { | ||
310 | struct rb_node **p = &threads.rb_node; | ||
311 | struct rb_node *parent = NULL; | ||
312 | struct thread *th; | ||
313 | |||
314 | /* | ||
315 | * Font-end cache - PID lookups come in blocks, | ||
316 | * so most of the time we dont have to look up | ||
317 | * the full rbtree: | ||
318 | */ | ||
319 | if (last_match && last_match->pid == pid) | ||
320 | return last_match; | ||
321 | |||
322 | while (*p != NULL) { | ||
323 | parent = *p; | ||
324 | th = rb_entry(parent, struct thread, rb_node); | ||
325 | |||
326 | if (th->pid == pid) { | ||
327 | last_match = th; | ||
328 | return th; | ||
329 | } | ||
330 | |||
331 | if (pid < th->pid) | ||
332 | p = &(*p)->rb_left; | ||
333 | else | ||
334 | p = &(*p)->rb_right; | ||
335 | } | ||
336 | |||
337 | th = thread__new(pid); | ||
338 | if (th != NULL) { | ||
339 | rb_link_node(&th->rb_node, parent, p); | ||
340 | rb_insert_color(&th->rb_node, &threads); | ||
341 | last_match = th; | ||
342 | } | ||
343 | |||
344 | return th; | ||
345 | } | ||
346 | |||
347 | static void thread__insert_map(struct thread *self, struct map *map) | ||
348 | { | ||
349 | struct map *pos, *tmp; | ||
350 | |||
351 | list_for_each_entry_safe(pos, tmp, &self->maps, node) { | ||
352 | if (map__overlap(pos, map)) { | ||
353 | list_del_init(&pos->node); | ||
354 | /* XXX leaks dsos */ | ||
355 | free(pos); | ||
356 | } | ||
357 | } | ||
358 | |||
359 | list_add_tail(&map->node, &self->maps); | ||
360 | } | ||
361 | |||
362 | static int thread__fork(struct thread *self, struct thread *parent) | ||
363 | { | ||
364 | struct map *map; | ||
365 | |||
366 | if (self->comm) | ||
367 | free(self->comm); | ||
368 | self->comm = strdup(parent->comm); | ||
369 | if (!self->comm) | ||
370 | return -ENOMEM; | ||
371 | |||
372 | list_for_each_entry(map, &parent->maps, node) { | ||
373 | struct map *new = map__clone(map); | ||
374 | if (!new) | ||
375 | return -ENOMEM; | ||
376 | thread__insert_map(self, new); | ||
377 | } | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static struct map *thread__find_map(struct thread *self, u64 ip) | ||
383 | { | ||
384 | struct map *pos; | ||
385 | |||
386 | if (self == NULL) | ||
387 | return NULL; | ||
388 | |||
389 | list_for_each_entry(pos, &self->maps, node) | ||
390 | if (ip >= pos->start && ip <= pos->end) | ||
391 | return pos; | ||
392 | |||
393 | return NULL; | ||
394 | } | ||
395 | |||
396 | static size_t threads__fprintf(FILE *fp) | ||
397 | { | ||
398 | size_t ret = 0; | ||
399 | struct rb_node *nd; | ||
400 | |||
401 | for (nd = rb_first(&threads); nd; nd = rb_next(nd)) { | ||
402 | struct thread *pos = rb_entry(nd, struct thread, rb_node); | ||
403 | |||
404 | ret += thread__fprintf(pos, fp); | ||
405 | } | ||
406 | |||
407 | return ret; | ||
408 | } | ||
409 | |||
410 | /* | 52 | /* |
411 | * histogram, sorted on item, collects counts | 53 | * histogram, sorted on item, collects counts |
412 | */ | 54 | */ |
@@ -433,7 +75,7 @@ struct hist_entry { | |||
433 | struct sort_entry { | 75 | struct sort_entry { |
434 | struct list_head list; | 76 | struct list_head list; |
435 | 77 | ||
436 | char *header; | 78 | const char *header; |
437 | 79 | ||
438 | int64_t (*cmp)(struct hist_entry *, struct hist_entry *); | 80 | int64_t (*cmp)(struct hist_entry *, struct hist_entry *); |
439 | int64_t (*collapse)(struct hist_entry *, struct hist_entry *); | 81 | int64_t (*collapse)(struct hist_entry *, struct hist_entry *); |
@@ -577,7 +219,7 @@ static struct sort_entry sort_sym = { | |||
577 | static int sort__need_collapse = 0; | 219 | static int sort__need_collapse = 0; |
578 | 220 | ||
579 | struct sort_dimension { | 221 | struct sort_dimension { |
580 | char *name; | 222 | const char *name; |
581 | struct sort_entry *entry; | 223 | struct sort_entry *entry; |
582 | int taken; | 224 | int taken; |
583 | }; | 225 | }; |
@@ -832,7 +474,7 @@ static void output__resort(void) | |||
832 | 474 | ||
833 | static void register_idle_thread(void) | 475 | static void register_idle_thread(void) |
834 | { | 476 | { |
835 | struct thread *thread = threads__findnew(0); | 477 | struct thread *thread = threads__findnew(0, &threads, &last_match); |
836 | 478 | ||
837 | if (thread == NULL || | 479 | if (thread == NULL || |
838 | thread__set_comm(thread, "[idle]")) { | 480 | thread__set_comm(thread, "[idle]")) { |
@@ -853,18 +495,20 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) | |||
853 | char level; | 495 | char level; |
854 | int show = 0; | 496 | int show = 0; |
855 | struct dso *dso = NULL; | 497 | struct dso *dso = NULL; |
856 | struct thread *thread = threads__findnew(event->ip.pid); | 498 | struct thread *thread; |
857 | u64 ip = event->ip.ip; | 499 | u64 ip = event->ip.ip; |
858 | struct map *map = NULL; | 500 | struct map *map = NULL; |
859 | 501 | ||
860 | dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", | 502 | thread = threads__findnew(event->ip.pid, &threads, &last_match); |
503 | |||
504 | dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", | ||
861 | (void *)(offset + head), | 505 | (void *)(offset + head), |
862 | (void *)(long)(event->header.size), | 506 | (void *)(long)(event->header.size), |
863 | event->header.misc, | 507 | event->header.misc, |
864 | event->ip.pid, | 508 | event->ip.pid, |
865 | (void *)(long)ip); | 509 | (void *)(long)ip); |
866 | 510 | ||
867 | dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid); | 511 | dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); |
868 | 512 | ||
869 | if (thread == NULL) { | 513 | if (thread == NULL) { |
870 | fprintf(stderr, "problem processing %d event, skipping it.\n", | 514 | fprintf(stderr, "problem processing %d event, skipping it.\n", |
@@ -878,7 +522,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) | |||
878 | 522 | ||
879 | dso = kernel_dso; | 523 | dso = kernel_dso; |
880 | 524 | ||
881 | dprintf(" ...... dso: %s\n", dso->name); | 525 | dump_printf(" ...... dso: %s\n", dso->name); |
882 | 526 | ||
883 | } else if (event->header.misc & PERF_EVENT_MISC_USER) { | 527 | } else if (event->header.misc & PERF_EVENT_MISC_USER) { |
884 | 528 | ||
@@ -899,12 +543,12 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) | |||
899 | if ((long long)ip < 0) | 543 | if ((long long)ip < 0) |
900 | dso = kernel_dso; | 544 | dso = kernel_dso; |
901 | } | 545 | } |
902 | dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); | 546 | dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); |
903 | 547 | ||
904 | } else { | 548 | } else { |
905 | show = SHOW_HV; | 549 | show = SHOW_HV; |
906 | level = 'H'; | 550 | level = 'H'; |
907 | dprintf(" ...... dso: [hypervisor]\n"); | 551 | dump_printf(" ...... dso: [hypervisor]\n"); |
908 | } | 552 | } |
909 | 553 | ||
910 | if (show & show_mask) { | 554 | if (show & show_mask) { |
@@ -927,10 +571,12 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) | |||
927 | static int | 571 | static int |
928 | process_mmap_event(event_t *event, unsigned long offset, unsigned long head) | 572 | process_mmap_event(event_t *event, unsigned long offset, unsigned long head) |
929 | { | 573 | { |
930 | struct thread *thread = threads__findnew(event->mmap.pid); | 574 | struct thread *thread; |
931 | struct map *map = map__new(&event->mmap); | 575 | struct map *map = map__new(&event->mmap, NULL, 0); |
576 | |||
577 | thread = threads__findnew(event->mmap.pid, &threads, &last_match); | ||
932 | 578 | ||
933 | dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", | 579 | dump_printf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", |
934 | (void *)(offset + head), | 580 | (void *)(offset + head), |
935 | (void *)(long)(event->header.size), | 581 | (void *)(long)(event->header.size), |
936 | event->mmap.pid, | 582 | event->mmap.pid, |
@@ -940,7 +586,7 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head) | |||
940 | event->mmap.filename); | 586 | event->mmap.filename); |
941 | 587 | ||
942 | if (thread == NULL || map == NULL) { | 588 | if (thread == NULL || map == NULL) { |
943 | dprintf("problem processing PERF_EVENT_MMAP, skipping event.\n"); | 589 | dump_printf("problem processing PERF_EVENT_MMAP, skipping event.\n"); |
944 | return 0; | 590 | return 0; |
945 | } | 591 | } |
946 | 592 | ||
@@ -953,16 +599,17 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head) | |||
953 | static int | 599 | static int |
954 | process_comm_event(event_t *event, unsigned long offset, unsigned long head) | 600 | process_comm_event(event_t *event, unsigned long offset, unsigned long head) |
955 | { | 601 | { |
956 | struct thread *thread = threads__findnew(event->comm.pid); | 602 | struct thread *thread; |
957 | 603 | ||
958 | dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n", | 604 | thread = threads__findnew(event->comm.pid, &threads, &last_match); |
605 | dump_printf("%p [%p]: PERF_EVENT_COMM: %s:%d\n", | ||
959 | (void *)(offset + head), | 606 | (void *)(offset + head), |
960 | (void *)(long)(event->header.size), | 607 | (void *)(long)(event->header.size), |
961 | event->comm.comm, event->comm.pid); | 608 | event->comm.comm, event->comm.pid); |
962 | 609 | ||
963 | if (thread == NULL || | 610 | if (thread == NULL || |
964 | thread__set_comm(thread, event->comm.comm)) { | 611 | thread__set_comm(thread, event->comm.comm)) { |
965 | dprintf("problem processing PERF_EVENT_COMM, skipping event.\n"); | 612 | dump_printf("problem processing PERF_EVENT_COMM, skipping event.\n"); |
966 | return -1; | 613 | return -1; |
967 | } | 614 | } |
968 | total_comm++; | 615 | total_comm++; |
@@ -973,10 +620,12 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head) | |||
973 | static int | 620 | static int |
974 | process_fork_event(event_t *event, unsigned long offset, unsigned long head) | 621 | process_fork_event(event_t *event, unsigned long offset, unsigned long head) |
975 | { | 622 | { |
976 | struct thread *thread = threads__findnew(event->fork.pid); | 623 | struct thread *thread; |
977 | struct thread *parent = threads__findnew(event->fork.ppid); | 624 | struct thread *parent; |
978 | 625 | ||
979 | dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n", | 626 | thread = threads__findnew(event->fork.pid, &threads, &last_match); |
627 | parent = threads__findnew(event->fork.ppid, &threads, &last_match); | ||
628 | dump_printf("%p [%p]: PERF_EVENT_FORK: %d:%d\n", | ||
980 | (void *)(offset + head), | 629 | (void *)(offset + head), |
981 | (void *)(long)(event->header.size), | 630 | (void *)(long)(event->header.size), |
982 | event->fork.pid, event->fork.ppid); | 631 | event->fork.pid, event->fork.ppid); |
@@ -989,7 +638,7 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head) | |||
989 | return 0; | 638 | return 0; |
990 | 639 | ||
991 | if (!thread || !parent || thread__fork(thread, parent)) { | 640 | if (!thread || !parent || thread__fork(thread, parent)) { |
992 | dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); | 641 | dump_printf("problem processing PERF_EVENT_FORK, skipping event.\n"); |
993 | return -1; | 642 | return -1; |
994 | } | 643 | } |
995 | total_fork++; | 644 | total_fork++; |
@@ -1075,7 +724,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) | |||
1075 | const char *path = NULL; | 724 | const char *path = NULL; |
1076 | unsigned int hits = 0; | 725 | unsigned int hits = 0; |
1077 | double percent = 0.0; | 726 | double percent = 0.0; |
1078 | char *color; | 727 | const char *color; |
1079 | struct sym_ext *sym_ext = sym->priv; | 728 | struct sym_ext *sym_ext = sym->priv; |
1080 | 729 | ||
1081 | offset = line_ip - start; | 730 | offset = line_ip - start; |
@@ -1157,7 +806,7 @@ static void free_source_line(struct symbol *sym, int len) | |||
1157 | 806 | ||
1158 | /* Get the filename:line for the colored entries */ | 807 | /* Get the filename:line for the colored entries */ |
1159 | static void | 808 | static void |
1160 | get_source_line(struct symbol *sym, u64 start, int len, char *filename) | 809 | get_source_line(struct symbol *sym, u64 start, int len, const char *filename) |
1161 | { | 810 | { |
1162 | int i; | 811 | int i; |
1163 | char cmd[PATH_MAX * 2]; | 812 | char cmd[PATH_MAX * 2]; |
@@ -1203,7 +852,7 @@ get_source_line(struct symbol *sym, u64 start, int len, char *filename) | |||
1203 | } | 852 | } |
1204 | } | 853 | } |
1205 | 854 | ||
1206 | static void print_summary(char *filename) | 855 | static void print_summary(const char *filename) |
1207 | { | 856 | { |
1208 | struct sym_ext *sym_ext; | 857 | struct sym_ext *sym_ext; |
1209 | struct rb_node *node; | 858 | struct rb_node *node; |
@@ -1219,7 +868,7 @@ static void print_summary(char *filename) | |||
1219 | node = rb_first(&root_sym_ext); | 868 | node = rb_first(&root_sym_ext); |
1220 | while (node) { | 869 | while (node) { |
1221 | double percent; | 870 | double percent; |
1222 | char *color; | 871 | const char *color; |
1223 | char *path; | 872 | char *path; |
1224 | 873 | ||
1225 | sym_ext = rb_entry(node, struct sym_ext, node); | 874 | sym_ext = rb_entry(node, struct sym_ext, node); |
@@ -1234,7 +883,7 @@ static void print_summary(char *filename) | |||
1234 | 883 | ||
1235 | static void annotate_sym(struct dso *dso, struct symbol *sym) | 884 | static void annotate_sym(struct dso *dso, struct symbol *sym) |
1236 | { | 885 | { |
1237 | char *filename = dso->name, *d_filename; | 886 | const char *filename = dso->name, *d_filename; |
1238 | u64 start, end, len; | 887 | u64 start, end, len; |
1239 | char command[PATH_MAX*2]; | 888 | char command[PATH_MAX*2]; |
1240 | FILE *file; | 889 | FILE *file; |
@@ -1244,7 +893,7 @@ static void annotate_sym(struct dso *dso, struct symbol *sym) | |||
1244 | if (sym->module) | 893 | if (sym->module) |
1245 | filename = sym->module->path; | 894 | filename = sym->module->path; |
1246 | else if (dso == kernel_dso) | 895 | else if (dso == kernel_dso) |
1247 | filename = vmlinux; | 896 | filename = vmlinux_name; |
1248 | 897 | ||
1249 | start = sym->obj_start; | 898 | start = sym->obj_start; |
1250 | if (!start) | 899 | if (!start) |
@@ -1316,7 +965,7 @@ static int __cmd_annotate(void) | |||
1316 | int ret, rc = EXIT_FAILURE; | 965 | int ret, rc = EXIT_FAILURE; |
1317 | unsigned long offset = 0; | 966 | unsigned long offset = 0; |
1318 | unsigned long head = 0; | 967 | unsigned long head = 0; |
1319 | struct stat stat; | 968 | struct stat input_stat; |
1320 | event_t *event; | 969 | event_t *event; |
1321 | uint32_t size; | 970 | uint32_t size; |
1322 | char *buf; | 971 | char *buf; |
@@ -1329,18 +978,18 @@ static int __cmd_annotate(void) | |||
1329 | exit(-1); | 978 | exit(-1); |
1330 | } | 979 | } |
1331 | 980 | ||
1332 | ret = fstat(input, &stat); | 981 | ret = fstat(input, &input_stat); |
1333 | if (ret < 0) { | 982 | if (ret < 0) { |
1334 | perror("failed to stat file"); | 983 | perror("failed to stat file"); |
1335 | exit(-1); | 984 | exit(-1); |
1336 | } | 985 | } |
1337 | 986 | ||
1338 | if (!force && (stat.st_uid != geteuid())) { | 987 | if (!force && (input_stat.st_uid != geteuid())) { |
1339 | fprintf(stderr, "file: %s not owned by current user\n", input_name); | 988 | fprintf(stderr, "file: %s not owned by current user\n", input_name); |
1340 | exit(-1); | 989 | exit(-1); |
1341 | } | 990 | } |
1342 | 991 | ||
1343 | if (!stat.st_size) { | 992 | if (!input_stat.st_size) { |
1344 | fprintf(stderr, "zero-sized file, nothing to do!\n"); | 993 | fprintf(stderr, "zero-sized file, nothing to do!\n"); |
1345 | exit(0); | 994 | exit(0); |
1346 | } | 995 | } |
@@ -1367,10 +1016,10 @@ more: | |||
1367 | 1016 | ||
1368 | if (head + event->header.size >= page_size * mmap_window) { | 1017 | if (head + event->header.size >= page_size * mmap_window) { |
1369 | unsigned long shift = page_size * (head / page_size); | 1018 | unsigned long shift = page_size * (head / page_size); |
1370 | int ret; | 1019 | int munmap_ret; |
1371 | 1020 | ||
1372 | ret = munmap(buf, page_size * mmap_window); | 1021 | munmap_ret = munmap(buf, page_size * mmap_window); |
1373 | assert(ret == 0); | 1022 | assert(munmap_ret == 0); |
1374 | 1023 | ||
1375 | offset += shift; | 1024 | offset += shift; |
1376 | head -= shift; | 1025 | head -= shift; |
@@ -1379,14 +1028,14 @@ more: | |||
1379 | 1028 | ||
1380 | size = event->header.size; | 1029 | size = event->header.size; |
1381 | 1030 | ||
1382 | dprintf("%p [%p]: event: %d\n", | 1031 | dump_printf("%p [%p]: event: %d\n", |
1383 | (void *)(offset + head), | 1032 | (void *)(offset + head), |
1384 | (void *)(long)event->header.size, | 1033 | (void *)(long)event->header.size, |
1385 | event->header.type); | 1034 | event->header.type); |
1386 | 1035 | ||
1387 | if (!size || process_event(event, offset, head) < 0) { | 1036 | if (!size || process_event(event, offset, head) < 0) { |
1388 | 1037 | ||
1389 | dprintf("%p [%p]: skipping unknown header type: %d\n", | 1038 | dump_printf("%p [%p]: skipping unknown header type: %d\n", |
1390 | (void *)(offset + head), | 1039 | (void *)(offset + head), |
1391 | (void *)(long)(event->header.size), | 1040 | (void *)(long)(event->header.size), |
1392 | event->header.type); | 1041 | event->header.type); |
@@ -1406,23 +1055,23 @@ more: | |||
1406 | 1055 | ||
1407 | head += size; | 1056 | head += size; |
1408 | 1057 | ||
1409 | if (offset + head < (unsigned long)stat.st_size) | 1058 | if (offset + head < (unsigned long)input_stat.st_size) |
1410 | goto more; | 1059 | goto more; |
1411 | 1060 | ||
1412 | rc = EXIT_SUCCESS; | 1061 | rc = EXIT_SUCCESS; |
1413 | close(input); | 1062 | close(input); |
1414 | 1063 | ||
1415 | dprintf(" IP events: %10ld\n", total); | 1064 | dump_printf(" IP events: %10ld\n", total); |
1416 | dprintf(" mmap events: %10ld\n", total_mmap); | 1065 | dump_printf(" mmap events: %10ld\n", total_mmap); |
1417 | dprintf(" comm events: %10ld\n", total_comm); | 1066 | dump_printf(" comm events: %10ld\n", total_comm); |
1418 | dprintf(" fork events: %10ld\n", total_fork); | 1067 | dump_printf(" fork events: %10ld\n", total_fork); |
1419 | dprintf(" unknown events: %10ld\n", total_unknown); | 1068 | dump_printf(" unknown events: %10ld\n", total_unknown); |
1420 | 1069 | ||
1421 | if (dump_trace) | 1070 | if (dump_trace) |
1422 | return 0; | 1071 | return 0; |
1423 | 1072 | ||
1424 | if (verbose >= 3) | 1073 | if (verbose >= 3) |
1425 | threads__fprintf(stdout); | 1074 | threads__fprintf(stdout, &threads); |
1426 | 1075 | ||
1427 | if (verbose >= 2) | 1076 | if (verbose >= 2) |
1428 | dsos__fprintf(stdout); | 1077 | dsos__fprintf(stdout); |
@@ -1450,7 +1099,7 @@ static const struct option options[] = { | |||
1450 | "be more verbose (show symbol address, etc)"), | 1099 | "be more verbose (show symbol address, etc)"), |
1451 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, | 1100 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, |
1452 | "dump raw trace in ASCII"), | 1101 | "dump raw trace in ASCII"), |
1453 | OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), | 1102 | OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"), |
1454 | OPT_BOOLEAN('m', "modules", &modules, | 1103 | OPT_BOOLEAN('m', "modules", &modules, |
1455 | "load module symbols - WARNING: use only with -k and LIVE kernel"), | 1104 | "load module symbols - WARNING: use only with -k and LIVE kernel"), |
1456 | OPT_BOOLEAN('l', "print-line", &print_line, | 1105 | OPT_BOOLEAN('l', "print-line", &print_line, |