diff options
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/builtin-report.c | 15 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 65 |
2 files changed, 79 insertions, 1 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index f053a7463dcf..61d871849b44 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -209,6 +209,11 @@ static uint64_t vdso__map_ip(struct map *map, uint64_t 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)); @@ -216,6 +221,7 @@ static struct map *map__new(struct mmap_event *event) if (self != NULL) { const char *filename = event->filename; char newfilename[PATH_MAX]; + int anon; if (cwd) { int n = strcommon(filename); @@ -227,6 +233,13 @@ static struct map *map__new(struct mmap_event *event) } } + 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; @@ -235,7 +248,7 @@ static struct map *map__new(struct mmap_event *event) 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; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 158588c7f6b1..32dd47d60d9c 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -220,6 +220,68 @@ out_failure: return -1; } +static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int verbose) +{ + char *line = NULL; + size_t n; + FILE *file; + int nr_syms = 0; + + file = fopen(self->name, "r"); + if (file == NULL) + goto out_failure; + + while (!feof(file)) { + __u64 start, size; + struct symbol *sym; + int line_len, len; + + line_len = getline(&line, &n, file); + if (line_len < 0) + break; + + if (!line) + goto out_failure; + + line[--line_len] = '\0'; /* \n */ + + len = hex2u64(line, &start); + + len++; + if (len + 2 >= line_len) + continue; + + len += hex2u64(line + len, &size); + + len++; + if (len + 2 >= line_len) + continue; + + sym = symbol__new(start, size, line + len, + self->sym_priv_size, start, verbose); + + if (sym == NULL) + goto out_delete_line; + + if (filter && filter(self, sym)) + symbol__delete(sym, self->sym_priv_size); + else { + dso__insert_symbol(self, sym); + nr_syms++; + } + } + + free(line); + fclose(file); + + return nr_syms; + +out_delete_line: + free(line); +out_failure: + return -1; +} + /** * elf_symtab__for_each_symbol - iterate thru all the symbols * @@ -507,6 +569,9 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose) if (!name) return -1; + if (strncmp(self->name, "/tmp/perf-", 10) == 0) + return dso__load_perf_map(self, filter, verbose); + more: do { switch (variant) { |