aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2010-05-10 05:59:37 -0400
committerThomas Gleixner <tglx@linutronix.de>2010-05-10 08:20:42 -0400
commitdbb6be6d5e974c42bbecd183effaa0df69e1dd8b (patch)
tree5735cb47e70853d057a9881dd0ce44b83e88fa63 /tools/perf/util
parent6a867a395558a7f882d041783e4cdea6744ca2bf (diff)
parentb57f95a38233a2e73b679bea4a5453a1cc2a1cc9 (diff)
Merge branch 'linus' into timers/core
Reason: Further posix_cpu_timer patches depend on mainline changes Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/cpumap.c59
-rw-r--r--tools/perf/util/cpumap.h7
-rw-r--r--tools/perf/util/event.h9
-rw-r--r--tools/perf/util/hist.c50
-rw-r--r--tools/perf/util/hist.h12
-rw-r--r--tools/perf/util/probe-event.c2
-rw-r--r--tools/perf/util/probe-finder.c20
-rw-r--r--tools/perf/util/probe-finder.h1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c17
-rw-r--r--tools/perf/util/session.c1
-rw-r--r--tools/perf/util/session.h1
-rw-r--r--tools/perf/util/symbol.c18
-rw-r--r--tools/perf/util/symbol.h3
-rw-r--r--tools/perf/util/thread.c41
-rw-r--r--tools/perf/util/thread.h3
15 files changed, 186 insertions, 58 deletions
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
new file mode 100644
index 000000000000..4e01490e51e5
--- /dev/null
+++ b/tools/perf/util/cpumap.c
@@ -0,0 +1,59 @@
1#include "util.h"
2#include "../perf.h"
3#include "cpumap.h"
4#include <assert.h>
5#include <stdio.h>
6
7int cpumap[MAX_NR_CPUS];
8
9static int default_cpu_map(void)
10{
11 int nr_cpus, i;
12
13 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
14 assert(nr_cpus <= MAX_NR_CPUS);
15 assert((int)nr_cpus >= 0);
16
17 for (i = 0; i < nr_cpus; ++i)
18 cpumap[i] = i;
19
20 return nr_cpus;
21}
22
23int read_cpu_map(void)
24{
25 FILE *onlnf;
26 int nr_cpus = 0;
27 int n, cpu, prev;
28 char sep;
29
30 onlnf = fopen("/sys/devices/system/cpu/online", "r");
31 if (!onlnf)
32 return default_cpu_map();
33
34 sep = 0;
35 prev = -1;
36 for (;;) {
37 n = fscanf(onlnf, "%u%c", &cpu, &sep);
38 if (n <= 0)
39 break;
40 if (prev >= 0) {
41 assert(nr_cpus + cpu - prev - 1 < MAX_NR_CPUS);
42 while (++prev < cpu)
43 cpumap[nr_cpus++] = prev;
44 }
45 assert (nr_cpus < MAX_NR_CPUS);
46 cpumap[nr_cpus++] = cpu;
47 if (n == 2 && sep == '-')
48 prev = cpu;
49 else
50 prev = -1;
51 if (n == 1 || sep == '\n')
52 break;
53 }
54 fclose(onlnf);
55 if (nr_cpus > 0)
56 return nr_cpus;
57
58 return default_cpu_map();
59}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
new file mode 100644
index 000000000000..86c78bb33098
--- /dev/null
+++ b/tools/perf/util/cpumap.h
@@ -0,0 +1,7 @@
1#ifndef __PERF_CPUMAP_H
2#define __PERF_CPUMAP_H
3
4extern int read_cpu_map(void);
5extern int cpumap[];
6
7#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 50a7132887f5..a33b94952e34 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -99,6 +99,15 @@ struct events_stats {
99 u64 lost; 99 u64 lost;
100}; 100};
101 101
102struct event_stat_id {
103 struct rb_node rb_node;
104 struct rb_root hists;
105 struct events_stats stats;
106 u64 config;
107 u64 event_stream;
108 u32 type;
109};
110
102void event__print_totals(void); 111void event__print_totals(void);
103 112
104struct perf_session; 113struct perf_session;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 44408c2621cf..2be33c7dbf03 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -12,12 +12,12 @@ struct callchain_param callchain_param = {
12 * histogram, sorted on item, collects counts 12 * histogram, sorted on item, collects counts
13 */ 13 */
14 14
15struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self, 15struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
16 struct addr_location *al, 16 struct addr_location *al,
17 struct symbol *sym_parent, 17 struct symbol *sym_parent,
18 u64 count, bool *hit) 18 u64 count, bool *hit)
19{ 19{
20 struct rb_node **p = &self->hists.rb_node; 20 struct rb_node **p = &hists->rb_node;
21 struct rb_node *parent = NULL; 21 struct rb_node *parent = NULL;
22 struct hist_entry *he; 22 struct hist_entry *he;
23 struct hist_entry entry = { 23 struct hist_entry entry = {
@@ -53,7 +53,7 @@ struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self,
53 return NULL; 53 return NULL;
54 *he = entry; 54 *he = entry;
55 rb_link_node(&he->rb_node, parent, p); 55 rb_link_node(&he->rb_node, parent, p);
56 rb_insert_color(&he->rb_node, &self->hists); 56 rb_insert_color(&he->rb_node, hists);
57 *hit = false; 57 *hit = false;
58 return he; 58 return he;
59} 59}
@@ -130,7 +130,7 @@ static void collapse__insert_entry(struct rb_root *root, struct hist_entry *he)
130 rb_insert_color(&he->rb_node, root); 130 rb_insert_color(&he->rb_node, root);
131} 131}
132 132
133void perf_session__collapse_resort(struct perf_session *self) 133void perf_session__collapse_resort(struct rb_root *hists)
134{ 134{
135 struct rb_root tmp; 135 struct rb_root tmp;
136 struct rb_node *next; 136 struct rb_node *next;
@@ -140,17 +140,17 @@ void perf_session__collapse_resort(struct perf_session *self)
140 return; 140 return;
141 141
142 tmp = RB_ROOT; 142 tmp = RB_ROOT;
143 next = rb_first(&self->hists); 143 next = rb_first(hists);
144 144
145 while (next) { 145 while (next) {
146 n = rb_entry(next, struct hist_entry, rb_node); 146 n = rb_entry(next, struct hist_entry, rb_node);
147 next = rb_next(&n->rb_node); 147 next = rb_next(&n->rb_node);
148 148
149 rb_erase(&n->rb_node, &self->hists); 149 rb_erase(&n->rb_node, hists);
150 collapse__insert_entry(&tmp, n); 150 collapse__insert_entry(&tmp, n);
151 } 151 }
152 152
153 self->hists = tmp; 153 *hists = tmp;
154} 154}
155 155
156/* 156/*
@@ -183,7 +183,7 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root,
183 rb_insert_color(&he->rb_node, root); 183 rb_insert_color(&he->rb_node, root);
184} 184}
185 185
186void perf_session__output_resort(struct perf_session *self, u64 total_samples) 186void perf_session__output_resort(struct rb_root *hists, u64 total_samples)
187{ 187{
188 struct rb_root tmp; 188 struct rb_root tmp;
189 struct rb_node *next; 189 struct rb_node *next;
@@ -194,18 +194,18 @@ void perf_session__output_resort(struct perf_session *self, u64 total_samples)
194 total_samples * (callchain_param.min_percent / 100); 194 total_samples * (callchain_param.min_percent / 100);
195 195
196 tmp = RB_ROOT; 196 tmp = RB_ROOT;
197 next = rb_first(&self->hists); 197 next = rb_first(hists);
198 198
199 while (next) { 199 while (next) {
200 n = rb_entry(next, struct hist_entry, rb_node); 200 n = rb_entry(next, struct hist_entry, rb_node);
201 next = rb_next(&n->rb_node); 201 next = rb_next(&n->rb_node);
202 202
203 rb_erase(&n->rb_node, &self->hists); 203 rb_erase(&n->rb_node, hists);
204 perf_session__insert_output_hist_entry(&tmp, n, 204 perf_session__insert_output_hist_entry(&tmp, n,
205 min_callchain_hits); 205 min_callchain_hits);
206 } 206 }
207 207
208 self->hists = tmp; 208 *hists = tmp;
209} 209}
210 210
211static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) 211static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
@@ -456,10 +456,10 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
456} 456}
457 457
458static size_t hist_entry__fprintf(struct hist_entry *self, 458static size_t hist_entry__fprintf(struct hist_entry *self,
459 struct perf_session *session,
460 struct perf_session *pair_session, 459 struct perf_session *pair_session,
461 bool show_displacement, 460 bool show_displacement,
462 long displacement, FILE *fp) 461 long displacement, FILE *fp,
462 u64 session_total)
463{ 463{
464 struct sort_entry *se; 464 struct sort_entry *se;
465 u64 count, total; 465 u64 count, total;
@@ -474,7 +474,7 @@ static size_t hist_entry__fprintf(struct hist_entry *self,
474 total = pair_session->events_stats.total; 474 total = pair_session->events_stats.total;
475 } else { 475 } else {
476 count = self->count; 476 count = self->count;
477 total = session->events_stats.total; 477 total = session_total;
478 } 478 }
479 479
480 if (total) 480 if (total)
@@ -496,8 +496,8 @@ static size_t hist_entry__fprintf(struct hist_entry *self,
496 496
497 if (total > 0) 497 if (total > 0)
498 old_percent = (count * 100.0) / total; 498 old_percent = (count * 100.0) / total;
499 if (session->events_stats.total > 0) 499 if (session_total > 0)
500 new_percent = (self->count * 100.0) / session->events_stats.total; 500 new_percent = (self->count * 100.0) / session_total;
501 501
502 diff = new_percent - old_percent; 502 diff = new_percent - old_percent;
503 503
@@ -544,16 +544,17 @@ static size_t hist_entry__fprintf(struct hist_entry *self,
544 left_margin -= thread__comm_len(self->thread); 544 left_margin -= thread__comm_len(self->thread);
545 } 545 }
546 546
547 hist_entry_callchain__fprintf(fp, self, session->events_stats.total, 547 hist_entry_callchain__fprintf(fp, self, session_total,
548 left_margin); 548 left_margin);
549 } 549 }
550 550
551 return ret; 551 return ret;
552} 552}
553 553
554size_t perf_session__fprintf_hists(struct perf_session *self, 554size_t perf_session__fprintf_hists(struct rb_root *hists,
555 struct perf_session *pair, 555 struct perf_session *pair,
556 bool show_displacement, FILE *fp) 556 bool show_displacement, FILE *fp,
557 u64 session_total)
557{ 558{
558 struct sort_entry *se; 559 struct sort_entry *se;
559 struct rb_node *nd; 560 struct rb_node *nd;
@@ -641,7 +642,7 @@ size_t perf_session__fprintf_hists(struct perf_session *self,
641 fprintf(fp, "\n#\n"); 642 fprintf(fp, "\n#\n");
642 643
643print_entries: 644print_entries:
644 for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) { 645 for (nd = rb_first(hists); nd; nd = rb_next(nd)) {
645 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 646 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
646 647
647 if (show_displacement) { 648 if (show_displacement) {
@@ -652,8 +653,13 @@ print_entries:
652 displacement = 0; 653 displacement = 0;
653 ++position; 654 ++position;
654 } 655 }
655 ret += hist_entry__fprintf(h, self, pair, show_displacement, 656 ret += hist_entry__fprintf(h, pair, show_displacement,
656 displacement, fp); 657 displacement, fp, session_total);
658 if (h->map == NULL && verbose > 1) {
659 __map_groups__fprintf_maps(&h->thread->mg,
660 MAP__FUNCTION, fp);
661 fprintf(fp, "%.10s end\n", graph_dotted_line);
662 }
657 } 663 }
658 664
659 free(rem_sq_bracket); 665 free(rem_sq_bracket);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index e5f99b24048b..16f360cce5bf 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -10,8 +10,9 @@ struct perf_session;
10struct hist_entry; 10struct hist_entry;
11struct addr_location; 11struct addr_location;
12struct symbol; 12struct symbol;
13struct rb_root;
13 14
14struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self, 15struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
15 struct addr_location *al, 16 struct addr_location *al,
16 struct symbol *parent, 17 struct symbol *parent,
17 u64 count, bool *hit); 18 u64 count, bool *hit);
@@ -19,9 +20,10 @@ extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
19extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); 20extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
20void hist_entry__free(struct hist_entry *); 21void hist_entry__free(struct hist_entry *);
21 22
22void perf_session__output_resort(struct perf_session *self, u64 total_samples); 23void perf_session__output_resort(struct rb_root *hists, u64 total_samples);
23void perf_session__collapse_resort(struct perf_session *self); 24void perf_session__collapse_resort(struct rb_root *hists);
24size_t perf_session__fprintf_hists(struct perf_session *self, 25size_t perf_session__fprintf_hists(struct rb_root *hists,
25 struct perf_session *pair, 26 struct perf_session *pair,
26 bool show_displacement, FILE *fp); 27 bool show_displacement, FILE *fp,
28 u64 session_total);
27#endif /* __PERF_HIST_H */ 29#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 53181dbfe4a8..7c004b6ef24f 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -242,7 +242,7 @@ void parse_perf_probe_event(const char *str, struct probe_point *pp,
242 242
243 /* Parse probe point */ 243 /* Parse probe point */
244 parse_perf_probe_probepoint(argv[0], pp); 244 parse_perf_probe_probepoint(argv[0], pp);
245 if (pp->file || pp->line) 245 if (pp->file || pp->line || pp->lazy_line)
246 *need_dwarf = true; 246 *need_dwarf = true;
247 247
248 /* Copy arguments and ensure return probe has no C argument */ 248 /* Copy arguments and ensure return probe has no C argument */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index e77dc886760e..c171a243d05b 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -169,7 +169,7 @@ static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
169{ 169{
170 Dwarf_Files *files; 170 Dwarf_Files *files;
171 size_t nfiles, i; 171 size_t nfiles, i;
172 const char *src; 172 const char *src = NULL;
173 int ret; 173 int ret;
174 174
175 if (!fname) 175 if (!fname)
@@ -333,8 +333,8 @@ static void show_location(Dwarf_Op *op, struct probe_finder *pf)
333 die("%u exceeds max register number.", regn); 333 die("%u exceeds max register number.", regn);
334 334
335 if (deref) 335 if (deref)
336 ret = snprintf(pf->buf, pf->len, " %s=+%ju(%s)", 336 ret = snprintf(pf->buf, pf->len, " %s=%+jd(%s)",
337 pf->var, (uintmax_t)offs, regs); 337 pf->var, (intmax_t)offs, regs);
338 else 338 else
339 ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs); 339 ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs);
340 DIE_IF(ret < 0); 340 DIE_IF(ret < 0);
@@ -352,8 +352,7 @@ static void show_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
352 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL) 352 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
353 goto error; 353 goto error;
354 /* TODO: handle more than 1 exprs */ 354 /* TODO: handle more than 1 exprs */
355 ret = dwarf_getlocation_addr(&attr, (pf->addr - pf->cu_base), 355 ret = dwarf_getlocation_addr(&attr, pf->addr, &expr, &nexpr, 1);
356 &expr, &nexpr, 1);
357 if (ret <= 0 || nexpr == 0) 356 if (ret <= 0 || nexpr == 0)
358 goto error; 357 goto error;
359 358
@@ -437,8 +436,7 @@ static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
437 436
438 /* Get the frame base attribute/ops */ 437 /* Get the frame base attribute/ops */
439 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr); 438 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
440 ret = dwarf_getlocation_addr(&fb_attr, (pf->addr - pf->cu_base), 439 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
441 &pf->fb_ops, &nops, 1);
442 if (ret <= 0 || nops == 0) 440 if (ret <= 0 || nops == 0)
443 pf->fb_ops = NULL; 441 pf->fb_ops = NULL;
444 442
@@ -455,6 +453,9 @@ static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
455 /* *pf->fb_ops will be cached in libdw. Don't free it. */ 453 /* *pf->fb_ops will be cached in libdw. Don't free it. */
456 pf->fb_ops = NULL; 454 pf->fb_ops = NULL;
457 455
456 if (pp->found == MAX_PROBES)
457 die("Too many( > %d) probe point found.\n", MAX_PROBES);
458
458 pp->probes[pp->found] = strdup(tmp); 459 pp->probes[pp->found] = strdup(tmp);
459 pp->found++; 460 pp->found++;
460} 461}
@@ -641,7 +642,6 @@ static void find_probe_point_by_func(struct probe_finder *pf)
641int find_probe_point(int fd, struct probe_point *pp) 642int find_probe_point(int fd, struct probe_point *pp)
642{ 643{
643 struct probe_finder pf = {.pp = pp}; 644 struct probe_finder pf = {.pp = pp};
644 int ret;
645 Dwarf_Off off, noff; 645 Dwarf_Off off, noff;
646 size_t cuhl; 646 size_t cuhl;
647 Dwarf_Die *diep; 647 Dwarf_Die *diep;
@@ -668,10 +668,6 @@ int find_probe_point(int fd, struct probe_point *pp)
668 pf.fname = NULL; 668 pf.fname = NULL;
669 669
670 if (!pp->file || pf.fname) { 670 if (!pp->file || pf.fname) {
671 /* Save CU base address (for frame_base) */
672 ret = dwarf_lowpc(&pf.cu_die, &pf.cu_base);
673 if (ret != 0)
674 pf.cu_base = 0;
675 if (pp->function) 671 if (pp->function)
676 find_probe_point_by_func(&pf); 672 find_probe_point_by_func(&pf);
677 else if (pp->lazy_line) 673 else if (pp->lazy_line)
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index d1a651793ba6..21f7354397b4 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -71,7 +71,6 @@ struct probe_finder {
71 71
72 /* For variable searching */ 72 /* For variable searching */
73 Dwarf_Op *fb_ops; /* Frame base attribute */ 73 Dwarf_Op *fb_ops; /* Frame base attribute */
74 Dwarf_Addr cu_base; /* Current CU base address */
75 const char *var; /* Current variable name */ 74 const char *var; /* Current variable name */
76 char *buf; /* Current output buffer */ 75 char *buf; /* Current output buffer */
77 int len; /* Length of output buffer */ 76 int len; /* Length of output buffer */
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 33a414bbba3e..6a72f14c5986 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -208,7 +208,7 @@ static void python_process_event(int cpu, void *data,
208 int size __unused, 208 int size __unused,
209 unsigned long long nsecs, char *comm) 209 unsigned long long nsecs, char *comm)
210{ 210{
211 PyObject *handler, *retval, *context, *t; 211 PyObject *handler, *retval, *context, *t, *obj;
212 static char handler_name[256]; 212 static char handler_name[256];
213 struct format_field *field; 213 struct format_field *field;
214 unsigned long long val; 214 unsigned long long val;
@@ -256,16 +256,23 @@ static void python_process_event(int cpu, void *data,
256 offset &= 0xffff; 256 offset &= 0xffff;
257 } else 257 } else
258 offset = field->offset; 258 offset = field->offset;
259 PyTuple_SetItem(t, n++, 259 obj = PyString_FromString((char *)data + offset);
260 PyString_FromString((char *)data + offset));
261 } else { /* FIELD_IS_NUMERIC */ 260 } else { /* FIELD_IS_NUMERIC */
262 val = read_size(data + field->offset, field->size); 261 val = read_size(data + field->offset, field->size);
263 if (field->flags & FIELD_IS_SIGNED) { 262 if (field->flags & FIELD_IS_SIGNED) {
264 PyTuple_SetItem(t, n++, PyInt_FromLong(val)); 263 if ((long long)val >= LONG_MIN &&
264 (long long)val <= LONG_MAX)
265 obj = PyInt_FromLong(val);
266 else
267 obj = PyLong_FromLongLong(val);
265 } else { 268 } else {
266 PyTuple_SetItem(t, n++, PyInt_FromLong(val)); 269 if (val <= LONG_MAX)
270 obj = PyInt_FromLong(val);
271 else
272 obj = PyLong_FromUnsignedLongLong(val);
267 } 273 }
268 } 274 }
275 PyTuple_SetItem(t, n++, obj);
269 } 276 }
270 277
271 if (_PyTuple_Resize(&t, n) == -1) 278 if (_PyTuple_Resize(&t, n) == -1)
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0de7258e70a5..eed1cb889008 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -70,6 +70,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
70 70
71 memcpy(self->filename, filename, len); 71 memcpy(self->filename, filename, len);
72 self->threads = RB_ROOT; 72 self->threads = RB_ROOT;
73 self->stats_by_id = RB_ROOT;
73 self->last_match = NULL; 74 self->last_match = NULL;
74 self->mmap_window = 32; 75 self->mmap_window = 32;
75 self->cwd = NULL; 76 self->cwd = NULL;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 31950fcd8a4d..5c33417eebb3 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -20,6 +20,7 @@ struct perf_session {
20 struct thread *last_match; 20 struct thread *last_match;
21 struct map *vmlinux_maps[MAP__NR_TYPES]; 21 struct map *vmlinux_maps[MAP__NR_TYPES];
22 struct events_stats events_stats; 22 struct events_stats events_stats;
23 struct rb_root stats_by_id;
23 unsigned long event_total[PERF_RECORD_MAX]; 24 unsigned long event_total[PERF_RECORD_MAX];
24 unsigned long unknown_events; 25 unsigned long unknown_events;
25 struct rb_root hists; 26 struct rb_root hists;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 323c0aea0a91..c458c4a371d1 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -163,9 +163,17 @@ void dso__set_long_name(struct dso *self, char *name)
163 self->long_name_len = strlen(name); 163 self->long_name_len = strlen(name);
164} 164}
165 165
166static void dso__set_short_name(struct dso *self, const char *name)
167{
168 if (name == NULL)
169 return;
170 self->short_name = name;
171 self->short_name_len = strlen(name);
172}
173
166static void dso__set_basename(struct dso *self) 174static void dso__set_basename(struct dso *self)
167{ 175{
168 self->short_name = basename(self->long_name); 176 dso__set_short_name(self, basename(self->long_name));
169} 177}
170 178
171struct dso *dso__new(const char *name) 179struct dso *dso__new(const char *name)
@@ -176,7 +184,7 @@ struct dso *dso__new(const char *name)
176 int i; 184 int i;
177 strcpy(self->name, name); 185 strcpy(self->name, name);
178 dso__set_long_name(self, self->name); 186 dso__set_long_name(self, self->name);
179 self->short_name = self->name; 187 dso__set_short_name(self, self->name);
180 for (i = 0; i < MAP__NR_TYPES; ++i) 188 for (i = 0; i < MAP__NR_TYPES; ++i)
181 self->symbols[i] = self->symbol_names[i] = RB_ROOT; 189 self->symbols[i] = self->symbol_names[i] = RB_ROOT;
182 self->slen_calculated = 0; 190 self->slen_calculated = 0;
@@ -897,7 +905,6 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
897 struct kmap *kmap = self->kernel ? map__kmap(map) : NULL; 905 struct kmap *kmap = self->kernel ? map__kmap(map) : NULL;
898 struct map *curr_map = map; 906 struct map *curr_map = map;
899 struct dso *curr_dso = self; 907 struct dso *curr_dso = self;
900 size_t dso_name_len = strlen(self->short_name);
901 Elf_Data *symstrs, *secstrs; 908 Elf_Data *symstrs, *secstrs;
902 uint32_t nr_syms; 909 uint32_t nr_syms;
903 int err = -1; 910 int err = -1;
@@ -987,7 +994,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
987 char dso_name[PATH_MAX]; 994 char dso_name[PATH_MAX];
988 995
989 if (strcmp(section_name, 996 if (strcmp(section_name,
990 curr_dso->short_name + dso_name_len) == 0) 997 (curr_dso->short_name +
998 self->short_name_len)) == 0)
991 goto new_symbol; 999 goto new_symbol;
992 1000
993 if (strcmp(section_name, ".text") == 0) { 1001 if (strcmp(section_name, ".text") == 0) {
@@ -1782,7 +1790,7 @@ struct dso *dso__new_kernel(const char *name)
1782 struct dso *self = dso__new(name ?: "[kernel.kallsyms]"); 1790 struct dso *self = dso__new(name ?: "[kernel.kallsyms]");
1783 1791
1784 if (self != NULL) { 1792 if (self != NULL) {
1785 self->short_name = "[kernel]"; 1793 dso__set_short_name(self, "[kernel]");
1786 self->kernel = 1; 1794 self->kernel = 1;
1787 } 1795 }
1788 1796
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 280dadd32a08..f30a37428919 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -110,9 +110,10 @@ struct dso {
110 u8 sorted_by_name; 110 u8 sorted_by_name;
111 u8 loaded; 111 u8 loaded;
112 u8 build_id[BUILD_ID_SIZE]; 112 u8 build_id[BUILD_ID_SIZE];
113 u16 long_name_len;
114 const char *short_name; 113 const char *short_name;
115 char *long_name; 114 char *long_name;
115 u16 long_name_len;
116 u16 short_name_len;
116 char name[0]; 117 char name[0];
117}; 118};
118 119
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 21b92162282b..fa968312ee7d 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -79,8 +79,8 @@ int thread__comm_len(struct thread *self)
79 return self->comm_len; 79 return self->comm_len;
80} 80}
81 81
82static size_t __map_groups__fprintf_maps(struct map_groups *self, 82size_t __map_groups__fprintf_maps(struct map_groups *self,
83 enum map_type type, FILE *fp) 83 enum map_type type, FILE *fp)
84{ 84{
85 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); 85 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
86 struct rb_node *nd; 86 struct rb_node *nd;
@@ -89,7 +89,7 @@ static size_t __map_groups__fprintf_maps(struct map_groups *self,
89 struct map *pos = rb_entry(nd, struct map, rb_node); 89 struct map *pos = rb_entry(nd, struct map, rb_node);
90 printed += fprintf(fp, "Map:"); 90 printed += fprintf(fp, "Map:");
91 printed += map__fprintf(pos, fp); 91 printed += map__fprintf(pos, fp);
92 if (verbose > 1) { 92 if (verbose > 2) {
93 printed += dso__fprintf(pos->dso, type, fp); 93 printed += dso__fprintf(pos->dso, type, fp);
94 printed += fprintf(fp, "--\n"); 94 printed += fprintf(fp, "--\n");
95 } 95 }
@@ -183,8 +183,8 @@ struct thread *perf_session__findnew(struct perf_session *self, pid_t pid)
183 return th; 183 return th;
184} 184}
185 185
186static void map_groups__remove_overlappings(struct map_groups *self, 186static int map_groups__fixup_overlappings(struct map_groups *self,
187 struct map *map) 187 struct map *map)
188{ 188{
189 struct rb_root *root = &self->maps[map->type]; 189 struct rb_root *root = &self->maps[map->type];
190 struct rb_node *next = rb_first(root); 190 struct rb_node *next = rb_first(root);
@@ -209,7 +209,36 @@ static void map_groups__remove_overlappings(struct map_groups *self,
209 * list. 209 * list.
210 */ 210 */
211 list_add_tail(&pos->node, &self->removed_maps[map->type]); 211 list_add_tail(&pos->node, &self->removed_maps[map->type]);
212 /*
213 * Now check if we need to create new maps for areas not
214 * overlapped by the new map:
215 */
216 if (map->start > pos->start) {
217 struct map *before = map__clone(pos);
218
219 if (before == NULL)
220 return -ENOMEM;
221
222 before->end = map->start - 1;
223 map_groups__insert(self, before);
224 if (verbose >= 2)
225 map__fprintf(before, stderr);
226 }
227
228 if (map->end < pos->end) {
229 struct map *after = map__clone(pos);
230
231 if (after == NULL)
232 return -ENOMEM;
233
234 after->start = map->end + 1;
235 map_groups__insert(self, after);
236 if (verbose >= 2)
237 map__fprintf(after, stderr);
238 }
212 } 239 }
240
241 return 0;
213} 242}
214 243
215void maps__insert(struct rb_root *maps, struct map *map) 244void maps__insert(struct rb_root *maps, struct map *map)
@@ -254,7 +283,7 @@ struct map *maps__find(struct rb_root *maps, u64 ip)
254 283
255void thread__insert_map(struct thread *self, struct map *map) 284void thread__insert_map(struct thread *self, struct map *map)
256{ 285{
257 map_groups__remove_overlappings(&self->mg, map); 286 map_groups__fixup_overlappings(&self->mg, map);
258 map_groups__insert(&self->mg, map); 287 map_groups__insert(&self->mg, map);
259} 288}
260 289
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 0a28f39de545..dcf70303e58e 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -10,6 +10,9 @@ struct map_groups {
10 struct list_head removed_maps[MAP__NR_TYPES]; 10 struct list_head removed_maps[MAP__NR_TYPES];
11}; 11};
12 12
13size_t __map_groups__fprintf_maps(struct map_groups *self,
14 enum map_type type, FILE *fp);
15
13struct thread { 16struct thread {
14 struct rb_node rb_node; 17 struct rb_node rb_node;
15 struct map_groups mg; 18 struct map_groups mg;