map.c 2.3 KB
Newer Older
1 2 3 4 5
#include "event.h"
#include "symbol.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
6
#include "debug.h"
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

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;
}

23
struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen,
24
		     unsigned int sym_priv_size)
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
{
	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;

54
		self->dso = dsos__findnew(filename, sym_priv_size);
55 56 57 58
		if (self->dso == NULL)
			goto out_delete;

		if (self->dso == vdso || anon)
59 60
			self->map_ip = self->unmap_ip = identity__map_ip;
		else {
61
			self->map_ip = map__map_ip;
62 63
			self->unmap_ip = map__unmap_ip;
		}
64 65 66 67 68 69 70
	}
	return self;
out_delete:
	free(self);
	return NULL;
}

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
struct symbol *
map__find_symbol(struct map *self, u64 ip, symbol_filter_t filter)
{
	if (!self->dso->loaded) {
		int nr = dso__load(self->dso, self, filter);

		if (nr < 0) {
			pr_warning("Failed to open %s, continuing without symbols\n",
				   self->dso->long_name);
			return NULL;
		} else if (nr == 0) {
			pr_warning("No symbols found in %s, maybe install a debug package?\n",
				   self->dso->long_name);
			return NULL;
		}
	}

	return self->dso->find_symbol(self->dso, ip);
}

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
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);
}