struct perf_event_header header;
__u64 ip;
__u32 pid, tid;
+ __u64 period;
};
struct mmap_event {
dso__fprintf(pos, fp);
}
-static struct symbol *vdso__find_symbol(struct dso *dso, uint64_t ip)
+static struct symbol *vdso__find_symbol(struct dso *dso, __u64 ip)
{
return dso__find_symbol(kernel_dso, ip);
}
struct map {
struct list_head node;
- uint64_t start;
- uint64_t end;
- uint64_t pgoff;
- uint64_t (*map_ip)(struct map *, uint64_t);
+ __u64 start;
+ __u64 end;
+ __u64 pgoff;
+ __u64 (*map_ip)(struct map *, __u64);
struct dso *dso;
};
-static uint64_t map__map_ip(struct map *map, uint64_t ip)
+static __u64 map__map_ip(struct map *map, __u64 ip)
{
return ip - map->start + map->pgoff;
}
-static uint64_t vdso__map_ip(struct map *map, uint64_t ip)
+static __u64 vdso__map_ip(struct map *map, __u64 ip)
{
return ip;
}
+static inline int is_anon_memory(const char *filename)
+{
+ return strcmp(filename, "//anon") == 0;
+}
+
static struct map *map__new(struct mmap_event *event)
{
struct map *self = malloc(sizeof(*self));
if (self != NULL) {
const char *filename = event->filename;
char newfilename[PATH_MAX];
+ int anon;
if (cwd) {
int n = strcommon(filename);
}
}
+ anon = is_anon_memory(filename);
+
+ if (anon) {
+ snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid);
+ filename = newfilename;
+ }
+
self->start = event->start;
self->end = event->start + event->len;
self->pgoff = event->pgoff;
if (self->dso == NULL)
goto out_delete;
- if (self->dso == vdso)
+ if (self->dso == vdso || anon)
self->map_ip = vdso__map_ip;
else
self->map_ip = map__map_ip;
static size_t map__fprintf(struct map *self, FILE *fp)
{
- return fprintf(fp, " %"PRIx64"-%"PRIx64" %"PRIx64" %s\n",
+ return fprintf(fp, " %Lx-%Lx %Lx %s\n",
self->start, self->end, self->pgoff, self->dso->name);
}
return 0;
}
-static struct map *thread__find_map(struct thread *self, uint64_t ip)
+static struct map *thread__find_map(struct thread *self, __u64 ip)
{
struct map *pos;
struct map *map;
struct dso *dso;
struct symbol *sym;
- uint64_t ip;
+ __u64 ip;
char level;
- uint32_t count;
+ __u64 count;
};
/*
static int64_t
sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
{
- uint64_t ip_l, ip_r;
+ __u64 ip_l, ip_r;
if (left->sym == right->sym)
return 0;
}
static size_t
-hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
+hist_entry__fprintf(FILE *fp, struct hist_entry *self, __u64 total_samples)
{
struct sort_entry *se;
size_t ret;
char *color = PERF_COLOR_NORMAL;
/*
- * We color high-overhead entries in red, low-overhead
- * entries in green - and keep the middle ground normal:
+ * We color high-overhead entries in red, mid-overhead
+ * entries in green - and keep the low overhead places
+ * normal:
*/
- if (percent >= 5.0)
+ if (percent >= 5.0) {
color = PERF_COLOR_RED;
- if (percent < 0.5)
- color = PERF_COLOR_GREEN;
+ } else {
+ if (percent >= 0.5)
+ color = PERF_COLOR_GREEN;
+ }
ret = color_fprintf(fp, color, " %6.2f%%",
(self->count * 100.0) / total_samples);
} else
- ret = fprintf(fp, "%12d ", self->count);
+ ret = fprintf(fp, "%12Ld ", self->count);
list_for_each_entry(se, &hist_entry__sort_list, list) {
fprintf(fp, " ");
static int
hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
- struct symbol *sym, uint64_t ip, char level)
+ struct symbol *sym, __u64 ip, char level, __u64 count)
{
struct rb_node **p = &hist.rb_node;
struct rb_node *parent = NULL;
.sym = sym,
.ip = ip,
.level = level,
- .count = 1,
+ .count = count,
};
int cmp;
cmp = hist_entry__cmp(&entry, he);
if (!cmp) {
- he->count++;
+ he->count += count;
return 0;
}
}
}
-static size_t output__fprintf(FILE *fp, uint64_t total_samples)
+static size_t output__fprintf(FILE *fp, __u64 total_samples)
{
struct hist_entry *pos;
struct sort_entry *se;
int show = 0;
struct dso *dso = NULL;
struct thread *thread = threads__findnew(event->ip.pid);
- uint64_t ip = event->ip.ip;
+ __u64 ip = event->ip.ip;
+ __u64 period = 1;
struct map *map = NULL;
- dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
+ if (event->header.type & PERF_SAMPLE_PERIOD)
+ period = event->ip.period;
+
+ dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p period: %Ld\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->header.misc,
event->ip.pid,
- (void *)(long)ip);
+ (void *)(long)ip,
+ (long long)period);
dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid);
if (dso)
sym = dso->find_symbol(dso, ip);
- if (hist_entry__add(thread, map, dso, sym, ip, level)) {
+ if (hist_entry__add(thread, map, dso, sym, ip, level, period)) {
fprintf(stderr,
"problem incrementing symbol count, skipping event\n");
return -1;
}
}
- total++;
+ total += period;
return 0;
}