1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "symbol.h"
2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <errno.h>
3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <inttypes.h>
4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <limits.h>
5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdlib.h>
6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <string.h>
7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdio.h>
8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <unistd.h>
9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "map.h"
10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengconst char *map_type__name[MAP__NR_TYPES] = {
12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	[MAP__FUNCTION] = "Functions",
13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	[MAP__VARIABLE] = "Variables",
14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic inline int is_anon_memory(const char *filename)
17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return strcmp(filename, "//anon") == 0;
19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map__init(struct map *self, enum map_type type,
22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	       u64 start, u64 end, u64 pgoff, struct dso *dso)
23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->type     = type;
25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->start    = start;
26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->end      = end;
27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->pgoff    = pgoff;
28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->dso      = dso;
29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->map_ip   = map__map_ip;
30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->unmap_ip = map__unmap_ip;
31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	RB_CLEAR_NODE(&self->rb_node);
32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->groups   = NULL;
33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->referenced = false;
34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		     u64 pgoff, u32 pid, char *filename,
38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		     enum map_type type)
39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct map *self = malloc(sizeof(*self));
41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (self != NULL) {
43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		char newfilename[PATH_MAX];
44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct dso *dso;
45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		int anon;
46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		anon = is_anon_memory(filename);
48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (anon) {
50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			filename = newfilename;
52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		dso = __dsos__findnew(dsos__list, filename);
55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (dso == NULL)
56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto out_delete;
57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		map__init(self, type, start, start + len, pgoff, dso);
59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (anon) {
61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengset_identity:
62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			self->map_ip = self->unmap_ip = identity__map_ip;
63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		} else if (strcmp(filename, "[vdso]") == 0) {
64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			dso__set_loaded(dso, self->type);
65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto set_identity;
66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return self;
69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout_delete:
70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(self);
71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return NULL;
72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map__delete(struct map *self)
75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(self);
77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map__fixup_start(struct map *self)
80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_root *symbols = &self->dso->symbols[self->type];
82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *nd = rb_first(symbols);
83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (nd != NULL) {
84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		self->start = sym->start;
86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map__fixup_end(struct map *self)
90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_root *symbols = &self->dso->symbols[self->type];
92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *nd = rb_last(symbols);
93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (nd != NULL) {
94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		self->end = sym->end;
96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define DSO__DELETED "(deleted)"
100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint map__load(struct map *self, symbol_filter_t filter)
102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *name = self->dso->long_name;
104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int nr;
105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (dso__loaded(self->dso, self->type))
107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return 0;
108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	nr = dso__load(self->dso, self, filter);
110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (nr < 0) {
111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (self->dso->has_build_id) {
112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			char sbuild_id[BUILD_ID_SIZE * 2 + 1];
113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			build_id__sprintf(self->dso->build_id,
115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					  sizeof(self->dso->build_id),
116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					  sbuild_id);
117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_warning("%s with build id %s not found",
118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				   name, sbuild_id);
119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		} else
120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_warning("Failed to open %s", name);
121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning(", continuing without symbols\n");
123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -1;
124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} else if (nr == 0) {
125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		const size_t len = strlen(name);
126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		const size_t real_len = len - sizeof(DSO__DELETED);
127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (len > sizeof(DSO__DELETED) &&
129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		    strcmp(name + real_len + 1, DSO__DELETED) == 0) {
130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_warning("%.*s was updated, restart the long "
131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				   "running apps that use it!\n",
132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				   (int)real_len, name);
133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		} else {
134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_warning("no symbols found in %s, maybe install "
135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				   "a debug package?\n", name);
136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -1;
139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/*
141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * Only applies to the kernel, as its symtabs aren't relative like the
142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * module ones.
143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 */
144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (self->dso->kernel)
145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		map__reloc_vmlinux(self);
146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct symbol *map__find_symbol(struct map *self, u64 addr,
151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				symbol_filter_t filter)
152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (map__load(self, filter) < 0)
154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return NULL;
155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return dso__find_symbol(self->dso, self->type, addr);
157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct symbol *map__find_symbol_by_name(struct map *self, const char *name,
160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					symbol_filter_t filter)
161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (map__load(self, filter) < 0)
163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return NULL;
164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!dso__sorted_by_name(self->dso, self->type))
166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		dso__sort_by_name(self->dso, self->type);
167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return dso__find_symbol_by_name(self->dso, self->type, name);
169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct map *map__clone(struct map *self)
172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct map *map = malloc(sizeof(*self));
174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!map)
176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return NULL;
177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	memcpy(map, self, sizeof(*self));
179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return map;
181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint map__overlap(struct map *l, struct map *r)
184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (l->start > r->start) {
186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct map *t = l;
187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		l = r;
188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		r = t;
189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (l->end > r->start)
192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return 1;
193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengsize_t map__fprintf(struct map *self, FILE *fp)
198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n",
200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		       self->start, self->end, self->pgoff, self->dso->name);
201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*
204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * map->dso->adjust_symbols==1 for ET_EXEC-like cases.
206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */
207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengu64 map__rip_2objdump(struct map *map, u64 rip)
208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	u64 addr = map->dso->adjust_symbols ?
210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			map->unmap_ip(map, rip) :	/* RIP -> IP */
211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			rip;
212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return addr;
213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengu64 map__objdump_2ip(struct map *map, u64 addr)
216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	u64 ip = map->dso->adjust_symbols ?
218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			addr :
219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			map->unmap_ip(map, addr);	/* RIP -> IP */
220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ip;
221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map_groups__init(struct map_groups *self)
224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i;
226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < MAP__NR_TYPES; ++i) {
227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		self->maps[i] = RB_ROOT;
228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		INIT_LIST_HEAD(&self->removed_maps[i]);
229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->machine = NULL;
231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void maps__delete(struct rb_root *self)
234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *next = rb_first(self);
236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (next) {
238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct map *pos = rb_entry(next, struct map, rb_node);
239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		next = rb_next(&pos->rb_node);
241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		rb_erase(&pos->rb_node, self);
242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		map__delete(pos);
243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void maps__delete_removed(struct list_head *self)
247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct map *pos, *n;
249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	list_for_each_entry_safe(pos, n, self, node) {
251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		list_del(&pos->node);
252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		map__delete(pos);
253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map_groups__exit(struct map_groups *self)
257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i;
259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < MAP__NR_TYPES; ++i) {
261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		maps__delete(&self->maps[i]);
262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		maps__delete_removed(&self->removed_maps[i]);
263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map_groups__flush(struct map_groups *self)
267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int type;
269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (type = 0; type < MAP__NR_TYPES; type++) {
271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct rb_root *root = &self->maps[type];
272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct rb_node *next = rb_first(root);
273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		while (next) {
275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			struct map *pos = rb_entry(next, struct map, rb_node);
276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			next = rb_next(&pos->rb_node);
277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			rb_erase(&pos->rb_node, root);
278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			/*
279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 * We may have references to this map, for
280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 * instance in some hist_entry instances, so
281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 * just move them to a separate list.
282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 */
283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			list_add_tail(&pos->node, &self->removed_maps[pos->type]);
284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct symbol *map_groups__find_symbol(struct map_groups *self,
289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				       enum map_type type, u64 addr,
290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				       struct map **mapp,
291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				       symbol_filter_t filter)
292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct map *map = map_groups__find(self, type, addr);
294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (map != NULL) {
296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (mapp != NULL)
297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			*mapp = map;
298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return map__find_symbol(map, map->map_ip(map, addr), filter);
299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return NULL;
302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
303e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
304e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct symbol *map_groups__find_symbol_by_name(struct map_groups *self,
305e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					       enum map_type type,
306e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					       const char *name,
307e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					       struct map **mapp,
308e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					       symbol_filter_t filter)
309e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
310e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *nd;
311e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
312e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
313e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct map *pos = rb_entry(nd, struct map, rb_node);
314e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct symbol *sym = map__find_symbol_by_name(pos, name, filter);
315e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
316e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (sym == NULL)
317e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			continue;
318e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (mapp != NULL)
319e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			*mapp = pos;
320e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return sym;
321e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
322e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
323e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return NULL;
324e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
325e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
326e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengsize_t __map_groups__fprintf_maps(struct map_groups *self,
327e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				  enum map_type type, int verbose, FILE *fp)
328e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
329e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
330e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *nd;
331e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
332e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
333e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct map *pos = rb_entry(nd, struct map, rb_node);
334e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printed += fprintf(fp, "Map:");
335e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printed += map__fprintf(pos, fp);
336e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (verbose > 2) {
337e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			printed += dso__fprintf(pos->dso, type, fp);
338e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			printed += fprintf(fp, "--\n");
339e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
340e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
341e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
342e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return printed;
343e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
344e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
345e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengsize_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp)
346e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
347e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	size_t printed = 0, i;
348e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < MAP__NR_TYPES; ++i)
349e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printed += __map_groups__fprintf_maps(self, i, verbose, fp);
350e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return printed;
351e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
352e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
353e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic size_t __map_groups__fprintf_removed_maps(struct map_groups *self,
354e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						 enum map_type type,
355e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						 int verbose, FILE *fp)
356e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
357e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct map *pos;
358e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	size_t printed = 0;
359e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
360e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	list_for_each_entry(pos, &self->removed_maps[type], node) {
361e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printed += fprintf(fp, "Map:");
362e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printed += map__fprintf(pos, fp);
363e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (verbose > 1) {
364e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			printed += dso__fprintf(pos->dso, type, fp);
365e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			printed += fprintf(fp, "--\n");
366e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
367e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
368e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return printed;
369e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
370e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
371e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic size_t map_groups__fprintf_removed_maps(struct map_groups *self,
372e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					       int verbose, FILE *fp)
373e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
374e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	size_t printed = 0, i;
375e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < MAP__NR_TYPES; ++i)
376e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printed += __map_groups__fprintf_removed_maps(self, i, verbose, fp);
377e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return printed;
378e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
379e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
380e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengsize_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp)
381e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
382e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	size_t printed = map_groups__fprintf_maps(self, verbose, fp);
383e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	printed += fprintf(fp, "Removed maps:\n");
384e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return printed + map_groups__fprintf_removed_maps(self, verbose, fp);
385e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
386e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
387e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
388e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				   int verbose, FILE *fp)
389e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
390e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_root *root = &self->maps[map->type];
391e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *next = rb_first(root);
392e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int err = 0;
393e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
394e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (next) {
395e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct map *pos = rb_entry(next, struct map, rb_node);
396e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		next = rb_next(&pos->rb_node);
397e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
398e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!map__overlap(pos, map))
399e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			continue;
400e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
401e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (verbose >= 2) {
402e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			fputs("overlapping maps:\n", fp);
403e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			map__fprintf(map, fp);
404e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			map__fprintf(pos, fp);
405e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
406e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
407e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		rb_erase(&pos->rb_node, root);
408e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/*
409e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 * Now check if we need to create new maps for areas not
410e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 * overlapped by the new map:
411e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 */
412e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (map->start > pos->start) {
413e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			struct map *before = map__clone(pos);
414e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
415e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (before == NULL) {
416e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				err = -ENOMEM;
417e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				goto move_map;
418e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
419e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
420e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			before->end = map->start - 1;
421e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			map_groups__insert(self, before);
422e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (verbose >= 2)
423e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				map__fprintf(before, fp);
424e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
425e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
426e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (map->end < pos->end) {
427e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			struct map *after = map__clone(pos);
428e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
429e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (after == NULL) {
430e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				err = -ENOMEM;
431e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				goto move_map;
432e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
433e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
434e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			after->start = map->end + 1;
435e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			map_groups__insert(self, after);
436e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (verbose >= 2)
437e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				map__fprintf(after, fp);
438e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
439e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengmove_map:
440e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/*
441e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 * If we have references, just move them to a separate list.
442e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 */
443e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pos->referenced)
444e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			list_add_tail(&pos->node, &self->removed_maps[map->type]);
445e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
446e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			map__delete(pos);
447e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
448e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (err)
449e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return err;
450e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
451e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
452e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
453e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
454e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
455e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*
456e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * XXX This should not really _copy_ te maps, but refcount them.
457e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */
458e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint map_groups__clone(struct map_groups *self,
459e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		      struct map_groups *parent, enum map_type type)
460e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
461e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *nd;
462e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) {
463e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct map *map = rb_entry(nd, struct map, rb_node);
464e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct map *new = map__clone(map);
465e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (new == NULL)
466e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ENOMEM;
467e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		map_groups__insert(self, new);
468e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
469e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
470e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
471e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
472e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic u64 map__reloc_map_ip(struct map *map, u64 ip)
473e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
474e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ip + (s64)map->pgoff;
475e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
476e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
477e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic u64 map__reloc_unmap_ip(struct map *map, u64 ip)
478e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
479e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ip - (s64)map->pgoff;
480e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
481e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
482e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map__reloc_vmlinux(struct map *self)
483e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
484e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct kmap *kmap = map__kmap(self);
485e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	s64 reloc;
486e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
487e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->unrelocated_addr)
488e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return;
489e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
490e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	reloc = (kmap->ref_reloc_sym->unrelocated_addr -
491e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 kmap->ref_reloc_sym->addr);
492e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
493e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!reloc)
494e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return;
495e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
496e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->map_ip   = map__reloc_map_ip;
497e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->unmap_ip = map__reloc_unmap_ip;
498e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->pgoff    = reloc;
499e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
500e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
501e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid maps__insert(struct rb_root *maps, struct map *map)
502e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
503e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node **p = &maps->rb_node;
504e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *parent = NULL;
505e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const u64 ip = map->start;
506e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct map *m;
507e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
508e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (*p != NULL) {
509e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		parent = *p;
510e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		m = rb_entry(parent, struct map, rb_node);
511e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ip < m->start)
512e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			p = &(*p)->rb_left;
513e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
514e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			p = &(*p)->rb_right;
515e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
516e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
517e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	rb_link_node(&map->rb_node, parent, p);
518e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	rb_insert_color(&map->rb_node, maps);
519e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
520e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
521e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid maps__remove(struct rb_root *self, struct map *map)
522e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
523e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	rb_erase(&map->rb_node, self);
524e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
525e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
526e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct map *maps__find(struct rb_root *maps, u64 ip)
527e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
528e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node **p = &maps->rb_node;
529e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *parent = NULL;
530e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct map *m;
531e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
532e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (*p != NULL) {
533e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		parent = *p;
534e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		m = rb_entry(parent, struct map, rb_node);
535e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ip < m->start)
536e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			p = &(*p)->rb_left;
537e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else if (ip > m->end)
538e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			p = &(*p)->rb_right;
539e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
540e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return m;
541e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
542e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
543e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return NULL;
544e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
545e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
546e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint machine__init(struct machine *self, const char *root_dir, pid_t pid)
547e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
548e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	map_groups__init(&self->kmaps);
549e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	RB_CLEAR_NODE(&self->rb_node);
550e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	INIT_LIST_HEAD(&self->user_dsos);
551e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	INIT_LIST_HEAD(&self->kernel_dsos);
552e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
553e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->kmaps.machine = self;
554e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->pid	    = pid;
555e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->root_dir      = strdup(root_dir);
556e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return self->root_dir == NULL ? -ENOMEM : 0;
557e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
558e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
559e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void dsos__delete(struct list_head *self)
560e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
561e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct dso *pos, *n;
562e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
563e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	list_for_each_entry_safe(pos, n, self, node) {
564e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		list_del(&pos->node);
565e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		dso__delete(pos);
566e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
567e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
568e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
569e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid machine__exit(struct machine *self)
570e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
571e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	map_groups__exit(&self->kmaps);
572e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	dsos__delete(&self->user_dsos);
573e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	dsos__delete(&self->kernel_dsos);
574e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(self->root_dir);
575e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->root_dir = NULL;
576e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
577e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
578e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid machine__delete(struct machine *self)
579e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
580e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	machine__exit(self);
581e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(self);
582e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
583e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
584e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct machine *machines__add(struct rb_root *self, pid_t pid,
585e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			      const char *root_dir)
586e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
587e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node **p = &self->rb_node;
588e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *parent = NULL;
589e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct machine *pos, *machine = malloc(sizeof(*machine));
590e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
591e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!machine)
592e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return NULL;
593e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
594e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (machine__init(machine, root_dir, pid) != 0) {
595e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(machine);
596e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return NULL;
597e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
598e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
599e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (*p != NULL) {
600e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		parent = *p;
601e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pos = rb_entry(parent, struct machine, rb_node);
602e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pid < pos->pid)
603e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			p = &(*p)->rb_left;
604e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
605e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			p = &(*p)->rb_right;
606e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
607e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
608e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	rb_link_node(&machine->rb_node, parent, p);
609e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	rb_insert_color(&machine->rb_node, self);
610e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
611e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return machine;
612e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
613e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
614e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct machine *machines__find(struct rb_root *self, pid_t pid)
615e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
616e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node **p = &self->rb_node;
617e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *parent = NULL;
618e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct machine *machine;
619e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct machine *default_machine = NULL;
620e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
621e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (*p != NULL) {
622e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		parent = *p;
623e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		machine = rb_entry(parent, struct machine, rb_node);
624e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pid < machine->pid)
625e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			p = &(*p)->rb_left;
626e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else if (pid > machine->pid)
627e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			p = &(*p)->rb_right;
628e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
629e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return machine;
630e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!machine->pid)
631e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			default_machine = machine;
632e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
633e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
634e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return default_machine;
635e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
636e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
637e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct machine *machines__findnew(struct rb_root *self, pid_t pid)
638e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
639e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char path[PATH_MAX];
640e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *root_dir;
641e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct machine *machine = machines__find(self, pid);
642e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
643e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!machine || machine->pid != pid) {
644e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID)
645e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			root_dir = "";
646e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else {
647e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (!symbol_conf.guestmount)
648e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				goto out;
649e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
650e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (access(path, R_OK)) {
651e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				pr_err("Can't access file %s\n", path);
652e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				goto out;
653e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
654e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			root_dir = path;
655e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
656e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		machine = machines__add(self, pid, root_dir);
657e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
658e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
659e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout:
660e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return machine;
661e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
662e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
663e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid machines__process(struct rb_root *self, machine__process_t process, void *data)
664e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
665e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *nd;
666e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
667e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (nd = rb_first(self); nd; nd = rb_next(nd)) {
668e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct machine *pos = rb_entry(nd, struct machine, rb_node);
669e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		process(pos, data);
670e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
671e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
672e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
673e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengchar *machine__mmap_name(struct machine *self, char *bf, size_t size)
674e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
675e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (machine__is_host(self))
676e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		snprintf(bf, size, "[%s]", "kernel.kallsyms");
677e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else if (machine__is_default_guest(self))
678e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		snprintf(bf, size, "[%s]", "guest.kernel.kallsyms");
679e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else
680e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms", self->pid);
681e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
682e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return bf;
683e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
684