perf tools: Factorize the map helpers
Factorize the dso mapping helpers into a single purpose common file "util/map.c" Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Brice Goglin <Brice.Goglin@inria.fr>
This commit is contained in:
parent
1fe2c1066c
commit
66e274f3b8
|
@ -340,6 +340,7 @@ LIB_OBJS += util/header.o
|
|||
LIB_OBJS += util/callchain.o
|
||||
LIB_OBJS += util/values.o
|
||||
LIB_OBJS += util/debug.o
|
||||
LIB_OBJS += util/map.o
|
||||
|
||||
BUILTIN_OBJS += builtin-annotate.o
|
||||
BUILTIN_OBJS += builtin-help.o
|
||||
|
|
|
@ -51,83 +51,6 @@ struct sym_ext {
|
|||
char *path;
|
||||
};
|
||||
|
||||
struct map {
|
||||
struct list_head node;
|
||||
u64 start;
|
||||
u64 end;
|
||||
u64 pgoff;
|
||||
u64 (*map_ip)(struct map *, u64);
|
||||
struct dso *dso;
|
||||
};
|
||||
|
||||
static u64 map__map_ip(struct map *map, u64 ip)
|
||||
{
|
||||
return ip - map->start + map->pgoff;
|
||||
}
|
||||
|
||||
static u64 vdso__map_ip(struct map *map __used, u64 ip)
|
||||
{
|
||||
return ip;
|
||||
}
|
||||
|
||||
static struct map *map__new(struct mmap_event *event)
|
||||
{
|
||||
struct map *self = malloc(sizeof(*self));
|
||||
|
||||
if (self != NULL) {
|
||||
const char *filename = event->filename;
|
||||
|
||||
self->start = event->start;
|
||||
self->end = event->start + event->len;
|
||||
self->pgoff = event->pgoff;
|
||||
|
||||
self->dso = dsos__findnew(filename);
|
||||
if (self->dso == NULL)
|
||||
goto out_delete;
|
||||
|
||||
if (self->dso == vdso)
|
||||
self->map_ip = vdso__map_ip;
|
||||
else
|
||||
self->map_ip = map__map_ip;
|
||||
}
|
||||
return self;
|
||||
out_delete:
|
||||
free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct map *map__clone(struct map *self)
|
||||
{
|
||||
struct map *map = malloc(sizeof(*self));
|
||||
|
||||
if (!map)
|
||||
return NULL;
|
||||
|
||||
memcpy(map, self, sizeof(*self));
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
static int map__overlap(struct map *l, struct map *r)
|
||||
{
|
||||
if (l->start > r->start) {
|
||||
struct map *t = l;
|
||||
l = r;
|
||||
r = t;
|
||||
}
|
||||
|
||||
if (l->end > r->start)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t map__fprintf(struct map *self, FILE *fp)
|
||||
{
|
||||
return fprintf(fp, " %Lx-%Lx %Lx %s\n",
|
||||
self->start, self->end, self->pgoff, self->dso->name);
|
||||
}
|
||||
|
||||
|
||||
struct thread {
|
||||
struct rb_node rb_node;
|
||||
|
@ -797,7 +720,7 @@ static int
|
|||
process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
|
||||
{
|
||||
struct thread *thread = threads__findnew(event->mmap.pid);
|
||||
struct map *map = map__new(&event->mmap);
|
||||
struct map *map = map__new(&event->mmap, NULL, 0);
|
||||
|
||||
dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n",
|
||||
(void *)(offset + head),
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "util/string.h"
|
||||
|
||||
#include "util/header.h"
|
||||
#include "util/event.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
|
|
|
@ -67,6 +67,10 @@ static char callchain_default_opt[] = "fractal,0.5";
|
|||
|
||||
static int callchain;
|
||||
|
||||
static char __cwd[PATH_MAX];
|
||||
static char *cwd = __cwd;
|
||||
static int cwdlen;
|
||||
|
||||
static
|
||||
struct callchain_param callchain_param = {
|
||||
.mode = CHAIN_GRAPH_REL,
|
||||
|
@ -102,124 +106,6 @@ static int repsep_fprintf(FILE *fp, const char *fmt, ...)
|
|||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char __cwd[PATH_MAX];
|
||||
static char *cwd = __cwd;
|
||||
static int cwdlen;
|
||||
|
||||
static int strcommon(const char *pathname)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
while (n < cwdlen && pathname[n] == cwd[n])
|
||||
++n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
struct map {
|
||||
struct list_head node;
|
||||
u64 start;
|
||||
u64 end;
|
||||
u64 pgoff;
|
||||
u64 (*map_ip)(struct map *, u64);
|
||||
struct dso *dso;
|
||||
};
|
||||
|
||||
static u64 map__map_ip(struct map *map, u64 ip)
|
||||
{
|
||||
return ip - map->start + map->pgoff;
|
||||
}
|
||||
|
||||
static u64 vdso__map_ip(struct map *map __used, 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);
|
||||
|
||||
if (n == cwdlen) {
|
||||
snprintf(newfilename, sizeof(newfilename),
|
||||
".%s", filename + n);
|
||||
filename = newfilename;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
self->dso = dsos__findnew(filename);
|
||||
if (self->dso == NULL)
|
||||
goto out_delete;
|
||||
|
||||
if (self->dso == vdso || anon)
|
||||
self->map_ip = vdso__map_ip;
|
||||
else
|
||||
self->map_ip = map__map_ip;
|
||||
}
|
||||
return self;
|
||||
out_delete:
|
||||
free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct map *map__clone(struct map *self)
|
||||
{
|
||||
struct map *map = malloc(sizeof(*self));
|
||||
|
||||
if (!map)
|
||||
return NULL;
|
||||
|
||||
memcpy(map, self, sizeof(*self));
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
static int map__overlap(struct map *l, struct map *r)
|
||||
{
|
||||
if (l->start > r->start) {
|
||||
struct map *t = l;
|
||||
l = r;
|
||||
r = t;
|
||||
}
|
||||
|
||||
if (l->end > r->start)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t map__fprintf(struct map *self, FILE *fp)
|
||||
{
|
||||
return fprintf(fp, " %Lx-%Lx %Lx %s\n",
|
||||
self->start, self->end, self->pgoff, self->dso->name);
|
||||
}
|
||||
|
||||
|
||||
struct thread {
|
||||
struct rb_node rb_node;
|
||||
struct list_head maps;
|
||||
|
@ -1474,7 +1360,7 @@ static int
|
|||
process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
|
||||
{
|
||||
struct thread *thread = threads__findnew(event->mmap.pid);
|
||||
struct map *map = map__new(&event->mmap);
|
||||
struct map *map = map__new(&event->mmap, cwd, cwdlen);
|
||||
|
||||
dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n",
|
||||
(void *)(offset + head),
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "../perf.h"
|
||||
#include <linux/list.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include "util.h"
|
||||
#include "symbol.h"
|
||||
|
||||
enum chain_mode {
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
#ifndef __PERF_EVENT_H
|
||||
#define __PERF_EVENT_H
|
||||
#include "../perf.h"
|
||||
#include "util.h"
|
||||
#include <linux/list.h>
|
||||
|
||||
struct ip_event {
|
||||
struct perf_event_header header;
|
||||
|
@ -52,3 +56,29 @@ typedef union event_union {
|
|||
struct lost_event lost;
|
||||
struct read_event read;
|
||||
} event_t;
|
||||
|
||||
struct map {
|
||||
struct list_head node;
|
||||
u64 start;
|
||||
u64 end;
|
||||
u64 pgoff;
|
||||
u64 (*map_ip)(struct map *, u64);
|
||||
struct dso *dso;
|
||||
};
|
||||
|
||||
static inline u64 map__map_ip(struct map *map, u64 ip)
|
||||
{
|
||||
return ip - map->start + map->pgoff;
|
||||
}
|
||||
|
||||
static inline u64 vdso__map_ip(struct map *map __used, u64 ip)
|
||||
{
|
||||
return ip;
|
||||
}
|
||||
|
||||
struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen);
|
||||
struct map *map__clone(struct map *self);
|
||||
int map__overlap(struct map *l, struct map *r);
|
||||
size_t map__fprintf(struct map *self, FILE *fp);
|
||||
|
||||
#endif
|
||||
|
|
97
tools/perf/util/map.c
Normal file
97
tools/perf/util/map.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
#include "event.h"
|
||||
#include "symbol.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static inline int is_anon_memory(const char *filename)
|
||||
{
|
||||
return strcmp(filename, "//anon") == 0;
|
||||
}
|
||||
|
||||
static int strcommon(const char *pathname, char *cwd, int cwdlen)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
while (n < cwdlen && pathname[n] == cwd[n])
|
||||
++n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen)
|
||||
{
|
||||
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, cwd, cwdlen);
|
||||
|
||||
if (n == cwdlen) {
|
||||
snprintf(newfilename, sizeof(newfilename),
|
||||
".%s", filename + n);
|
||||
filename = newfilename;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
self->dso = dsos__findnew(filename);
|
||||
if (self->dso == NULL)
|
||||
goto out_delete;
|
||||
|
||||
if (self->dso == vdso || anon)
|
||||
self->map_ip = vdso__map_ip;
|
||||
else
|
||||
self->map_ip = map__map_ip;
|
||||
}
|
||||
return self;
|
||||
out_delete:
|
||||
free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct map *map__clone(struct map *self)
|
||||
{
|
||||
struct map *map = malloc(sizeof(*self));
|
||||
|
||||
if (!map)
|
||||
return NULL;
|
||||
|
||||
memcpy(map, self, sizeof(*self));
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
int map__overlap(struct map *l, struct map *r)
|
||||
{
|
||||
if (l->start > r->start) {
|
||||
struct map *t = l;
|
||||
l = r;
|
||||
r = t;
|
||||
}
|
||||
|
||||
if (l->end > r->start)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t map__fprintf(struct map *self, FILE *fp)
|
||||
{
|
||||
return fprintf(fp, " %Lx-%Lx %Lx %s\n",
|
||||
self->start, self->end, self->pgoff, self->dso->name);
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
#include <linux/list.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include "module.h"
|
||||
#include "event.h"
|
||||
|
||||
struct symbol {
|
||||
struct rb_node rb_node;
|
||||
|
|
|
@ -83,7 +83,6 @@
|
|||
#include <inttypes.h>
|
||||
#include "../../../include/linux/magic.h"
|
||||
|
||||
#include "event.h"
|
||||
|
||||
#ifndef NO_ICONV
|
||||
#include <iconv.h>
|
||||
|
|
Loading…
Reference in a new issue