aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-annotate.c135
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/util/event.c4
-rw-r--r--tools/perf/util/probe-event.c3
-rw-r--r--tools/perf/util/thread.c34
5 files changed, 148 insertions, 30 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index e47dd1587e39..5ec5de995872 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -145,21 +145,58 @@ static int process_sample_event(event_t *event, struct perf_session *session)
145 return 0; 145 return 0;
146} 146}
147 147
148static int parse_line(FILE *file, struct hist_entry *he, u64 len) 148struct objdump_line {
149 struct list_head node;
150 s64 offset;
151 char *line;
152};
153
154static struct objdump_line *objdump_line__new(s64 offset, char *line)
155{
156 struct objdump_line *self = malloc(sizeof(*self));
157
158 if (self != NULL) {
159 self->offset = offset;
160 self->line = line;
161 }
162
163 return self;
164}
165
166static void objdump_line__free(struct objdump_line *self)
167{
168 free(self->line);
169 free(self);
170}
171
172static void objdump__add_line(struct list_head *head, struct objdump_line *line)
173{
174 list_add_tail(&line->node, head);
175}
176
177static struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
178 struct objdump_line *pos)
179{
180 list_for_each_entry_continue(pos, head, node)
181 if (pos->offset >= 0)
182 return pos;
183
184 return NULL;
185}
186
187static int parse_line(FILE *file, struct hist_entry *he,
188 struct list_head *head)
149{ 189{
150 struct symbol *sym = he->sym; 190 struct symbol *sym = he->sym;
191 struct objdump_line *objdump_line;
151 char *line = NULL, *tmp, *tmp2; 192 char *line = NULL, *tmp, *tmp2;
152 static const char *prev_line;
153 static const char *prev_color;
154 unsigned int offset;
155 size_t line_len; 193 size_t line_len;
156 u64 start; 194 s64 line_ip, offset = -1;
157 s64 line_ip;
158 int ret;
159 char *c; 195 char *c;
160 196
161 if (getline(&line, &line_len, file) < 0) 197 if (getline(&line, &line_len, file) < 0)
162 return -1; 198 return -1;
199
163 if (!line) 200 if (!line)
164 return -1; 201 return -1;
165 202
@@ -168,8 +205,6 @@ static int parse_line(FILE *file, struct hist_entry *he, u64 len)
168 *c = 0; 205 *c = 0;
169 206
170 line_ip = -1; 207 line_ip = -1;
171 offset = 0;
172 ret = -2;
173 208
174 /* 209 /*
175 * Strip leading spaces: 210 * Strip leading spaces:
@@ -190,9 +225,30 @@ static int parse_line(FILE *file, struct hist_entry *he, u64 len)
190 line_ip = -1; 225 line_ip = -1;
191 } 226 }
192 227
193 start = map__rip_2objdump(he->map, sym->start);
194
195 if (line_ip != -1) { 228 if (line_ip != -1) {
229 u64 start = map__rip_2objdump(he->map, sym->start);
230 offset = line_ip - start;
231 }
232
233 objdump_line = objdump_line__new(offset, line);
234 if (objdump_line == NULL) {
235 free(line);
236 return -1;
237 }
238 objdump__add_line(head, objdump_line);
239
240 return 0;
241}
242
243static int objdump_line__print(struct objdump_line *self,
244 struct list_head *head,
245 struct hist_entry *he, u64 len)
246{
247 struct symbol *sym = he->sym;
248 static const char *prev_line;
249 static const char *prev_color;
250
251 if (self->offset != -1) {
196 const char *path = NULL; 252 const char *path = NULL;
197 unsigned int hits = 0; 253 unsigned int hits = 0;
198 double percent = 0.0; 254 double percent = 0.0;
@@ -200,15 +256,22 @@ static int parse_line(FILE *file, struct hist_entry *he, u64 len)
200 struct sym_priv *priv = symbol__priv(sym); 256 struct sym_priv *priv = symbol__priv(sym);
201 struct sym_ext *sym_ext = priv->ext; 257 struct sym_ext *sym_ext = priv->ext;
202 struct sym_hist *h = priv->hist; 258 struct sym_hist *h = priv->hist;
259 s64 offset = self->offset;
260 struct objdump_line *next = objdump__get_next_ip_line(head, self);
261
262 while (offset < (s64)len &&
263 (next == NULL || offset < next->offset)) {
264 if (sym_ext) {
265 if (path == NULL)
266 path = sym_ext[offset].path;
267 percent += sym_ext[offset].percent;
268 } else
269 hits += h->ip[offset];
270
271 ++offset;
272 }
203 273
204 offset = line_ip - start; 274 if (sym_ext == NULL && h->sum)
205 if (offset < len)
206 hits = h->ip[offset];
207
208 if (offset < len && sym_ext) {
209 path = sym_ext[offset].path;
210 percent = sym_ext[offset].percent;
211 } else if (h->sum)
212 percent = 100.0 * hits / h->sum; 275 percent = 100.0 * hits / h->sum;
213 276
214 color = get_percent_color(percent); 277 color = get_percent_color(percent);
@@ -229,12 +292,12 @@ static int parse_line(FILE *file, struct hist_entry *he, u64 len)
229 292
230 color_fprintf(stdout, color, " %7.2f", percent); 293 color_fprintf(stdout, color, " %7.2f", percent);
231 printf(" : "); 294 printf(" : ");
232 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", line); 295 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", self->line);
233 } else { 296 } else {
234 if (!*line) 297 if (!*self->line)
235 printf(" :\n"); 298 printf(" :\n");
236 else 299 else
237 printf(" : %s\n", line); 300 printf(" : %s\n", self->line);
238 } 301 }
239 302
240 return 0; 303 return 0;
@@ -360,6 +423,20 @@ static void print_summary(const char *filename)
360 } 423 }
361} 424}
362 425
426static void hist_entry__print_hits(struct hist_entry *self)
427{
428 struct symbol *sym = self->sym;
429 struct sym_priv *priv = symbol__priv(sym);
430 struct sym_hist *h = priv->hist;
431 u64 len = sym->end - sym->start, offset;
432
433 for (offset = 0; offset < len; ++offset)
434 if (h->ip[offset] != 0)
435 printf("%*Lx: %Lu\n", BITS_PER_LONG / 2,
436 sym->start + offset, h->ip[offset]);
437 printf("%*s: %Lu\n", BITS_PER_LONG / 2, "h->sum", h->sum);
438}
439
363static void annotate_sym(struct hist_entry *he) 440static void annotate_sym(struct hist_entry *he)
364{ 441{
365 struct map *map = he->map; 442 struct map *map = he->map;
@@ -369,6 +446,8 @@ static void annotate_sym(struct hist_entry *he)
369 u64 len; 446 u64 len;
370 char command[PATH_MAX*2]; 447 char command[PATH_MAX*2];
371 FILE *file; 448 FILE *file;
449 LIST_HEAD(head);
450 struct objdump_line *pos, *n;
372 451
373 if (!filename) 452 if (!filename)
374 return; 453 return;
@@ -410,11 +489,21 @@ static void annotate_sym(struct hist_entry *he)
410 return; 489 return;
411 490
412 while (!feof(file)) { 491 while (!feof(file)) {
413 if (parse_line(file, he, len) < 0) 492 if (parse_line(file, he, &head) < 0)
414 break; 493 break;
415 } 494 }
416 495
417 pclose(file); 496 pclose(file);
497
498 if (verbose)
499 hist_entry__print_hits(he);
500
501 list_for_each_entry_safe(pos, n, &head, node) {
502 objdump_line__print(pos, &head, he, len);
503 list_del(&pos->node);
504 objdump_line__free(pos);
505 }
506
418 if (print_line) 507 if (print_line)
419 free_source_line(he, len); 508 free_source_line(he, len);
420} 509}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c6706984b7b3..31f2e597800c 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -706,7 +706,7 @@ static void print_mapped_keys(void)
706 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); 706 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
707 707
708 fprintf(stdout, 708 fprintf(stdout,
709 "\t[K] hide kernel_symbols symbols. \t(%s)\n", 709 "\t[K] hide kernel_symbols symbols. \t(%s)\n",
710 hide_kernel_symbols ? "yes" : "no"); 710 hide_kernel_symbols ? "yes" : "no");
711 fprintf(stdout, 711 fprintf(stdout,
712 "\t[U] hide user symbols. \t(%s)\n", 712 "\t[U] hide user symbols. \t(%s)\n",
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 9eb7005bc6d6..705ec63548b4 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -442,10 +442,10 @@ void thread__find_addr_map(struct thread *self,
442 al->thread = self; 442 al->thread = self;
443 al->addr = addr; 443 al->addr = addr;
444 444
445 if (cpumode & PERF_RECORD_MISC_KERNEL) { 445 if (cpumode == PERF_RECORD_MISC_KERNEL) {
446 al->level = 'k'; 446 al->level = 'k';
447 mg = &session->kmaps; 447 mg = &session->kmaps;
448 } else if (cpumode & PERF_RECORD_MISC_USER) 448 } else if (cpumode == PERF_RECORD_MISC_USER)
449 al->level = '.'; 449 al->level = '.';
450 else { 450 else {
451 al->level = 'H'; 451 al->level = 'H';
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index fa156f008e0b..c971e81e9cbf 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -320,6 +320,7 @@ int synthesize_perf_probe_point(struct probe_point *pp)
320 int ret; 320 int ret;
321 321
322 pp->probes[0] = buf = zalloc(MAX_CMDLEN); 322 pp->probes[0] = buf = zalloc(MAX_CMDLEN);
323 pp->found = 1;
323 if (!buf) 324 if (!buf)
324 die("Failed to allocate memory by zalloc."); 325 die("Failed to allocate memory by zalloc.");
325 if (pp->offset) { 326 if (pp->offset) {
@@ -342,6 +343,7 @@ int synthesize_perf_probe_point(struct probe_point *pp)
342error: 343error:
343 free(pp->probes[0]); 344 free(pp->probes[0]);
344 pp->probes[0] = NULL; 345 pp->probes[0] = NULL;
346 pp->found = 0;
345 } 347 }
346 return ret; 348 return ret;
347} 349}
@@ -507,6 +509,7 @@ void show_perf_probe_events(void)
507 509
508 setup_pager(); 510 setup_pager();
509 511
512 memset(&pp, 0, sizeof(pp));
510 fd = open_kprobe_events(O_RDONLY, 0); 513 fd = open_kprobe_events(O_RDONLY, 0);
511 rawlist = get_trace_kprobe_event_rawlist(fd); 514 rawlist = get_trace_kprobe_event_rawlist(fd);
512 close(fd); 515 close(fd);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index c090654cb6c0..21b92162282b 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -31,15 +31,41 @@ static struct thread *thread__new(pid_t pid)
31 return self; 31 return self;
32} 32}
33 33
34static void map_groups__flush(struct map_groups *self)
35{
36 int type;
37
38 for (type = 0; type < MAP__NR_TYPES; type++) {
39 struct rb_root *root = &self->maps[type];
40 struct rb_node *next = rb_first(root);
41
42 while (next) {
43 struct map *pos = rb_entry(next, struct map, rb_node);
44 next = rb_next(&pos->rb_node);
45 rb_erase(&pos->rb_node, root);
46 /*
47 * We may have references to this map, for
48 * instance in some hist_entry instances, so
49 * just move them to a separate list.
50 */
51 list_add_tail(&pos->node, &self->removed_maps[pos->type]);
52 }
53 }
54}
55
34int thread__set_comm(struct thread *self, const char *comm) 56int thread__set_comm(struct thread *self, const char *comm)
35{ 57{
58 int err;
59
36 if (self->comm) 60 if (self->comm)
37 free(self->comm); 61 free(self->comm);
38 self->comm = strdup(comm); 62 self->comm = strdup(comm);
39 if (self->comm == NULL) 63 err = self->comm == NULL ? -ENOMEM : 0;
40 return -ENOMEM; 64 if (!err) {
41 self->comm_set = true; 65 self->comm_set = true;
42 return 0; 66 map_groups__flush(&self->mg);
67 }
68 return err;
43} 69}
44 70
45int thread__comm_len(struct thread *self) 71int thread__comm_len(struct thread *self)