1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "symbol.h"
2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <errno.h>
3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <inttypes.h>
4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <limits.h>
5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdlib.h>
6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <string.h>
7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdio.h>
8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <unistd.h>
9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "map.h"
10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "thread.h"
11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "strlist.h"
12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "vdso.h"
13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "build-id.h"
14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <linux/string.h>
15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengconst char *map_type__name[MAP__NR_TYPES] = {
17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[MAP__FUNCTION] = "Functions",
18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[MAP__VARIABLE] = "Variables",
19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic inline int is_anon_memory(const char *filename)
22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return !strcmp(filename, "//anon") ||
24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	       !strcmp(filename, "/dev/zero (deleted)") ||
25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	       !strcmp(filename, "/anon_hugepage (deleted)");
26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic inline int is_no_dso_memory(const char *filename)
29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return !strncmp(filename, "[stack", 6) ||
31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	       !strcmp(filename, "[heap]");
32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map__init(struct map *map, enum map_type type,
35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	       u64 start, u64 end, u64 pgoff, struct dso *dso)
36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	map->type     = type;
38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	map->start    = start;
39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	map->end      = end;
40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	map->pgoff    = pgoff;
41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	map->dso      = dso;
42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	map->map_ip   = map__map_ip;
43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	map->unmap_ip = map__unmap_ip;
44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	RB_CLEAR_NODE(&map->rb_node);
45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	map->groups   = NULL;
46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	map->referenced = false;
47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	map->erange_warned = false;
48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		     u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		     u64 ino_gen, char *filename,
53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		     enum map_type type)
54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct map *map = malloc(sizeof(*map));
56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (map != NULL) {
58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		char newfilename[PATH_MAX];
59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct dso *dso;
60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		int anon, no_dso, vdso;
61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		anon = is_anon_memory(filename);
63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		vdso = is_vdso_map(filename);
64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		no_dso = is_no_dso_memory(filename);
65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		map->maj = d_maj;
67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		map->min = d_min;
68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		map->ino = ino;
69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		map->ino_generation = ino_gen;
70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (anon) {
72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			filename = newfilename;
74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (vdso) {
77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pgoff = 0;
78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			dso = vdso__dso_findnew(dsos__list);
79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		} else
80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			dso = __dsos__findnew(dsos__list, filename);
81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (dso == NULL)
83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out_delete;
84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		map__init(map, type, start, start + len, pgoff, dso);
86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (anon || no_dso) {
88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			map->map_ip = map->unmap_ip = identity__map_ip;
89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			/*
91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 * Set memory without DSO as loaded. All map__find_*
92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 * functions still return NULL, and we avoid the
93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 * unnecessary map__load warning.
94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 */
95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (no_dso)
96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				dso__set_loaded(dso, map->type);
97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return map;
100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_delete:
101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	free(map);
102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return NULL;
103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/*
106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Constructor variant for modules (where we know from /proc/modules where
107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * they are loaded) and for vmlinux, where only after we load all the
108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * symbols we'll know where it starts and ends.
109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */
110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct map *map__new2(u64 start, struct dso *dso, enum map_type type)
111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct map *map = calloc(1, (sizeof(*map) +
113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				     (dso->kernel ? sizeof(struct kmap) : 0)));
114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (map != NULL) {
115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/*
116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * ->end will be filled after we load all the symbols
117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 */
118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		map__init(map, type, start, 0, 0, dso);
119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return map;
122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map__delete(struct map *map)
125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	free(map);
127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map__fixup_start(struct map *map)
130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_root *symbols = &map->dso->symbols[map->type];
132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *nd = rb_first(symbols);
133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (nd != NULL) {
134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		map->start = sym->start;
136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map__fixup_end(struct map *map)
140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_root *symbols = &map->dso->symbols[map->type];
142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *nd = rb_last(symbols);
143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (nd != NULL) {
144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		map->end = sym->end;
146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define DSO__DELETED "(deleted)"
150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint map__load(struct map *map, symbol_filter_t filter)
152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *name = map->dso->long_name;
154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int nr;
155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (dso__loaded(map->dso, map->type))
157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	nr = dso__load(map->dso, map, filter);
160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (nr < 0) {
161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (map->dso->has_build_id) {
162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			char sbuild_id[BUILD_ID_SIZE * 2 + 1];
163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			build_id__sprintf(map->dso->build_id,
165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					  sizeof(map->dso->build_id),
166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					  sbuild_id);
167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pr_warning("%s with build id %s not found",
168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				   name, sbuild_id);
169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		} else
170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pr_warning("Failed to open %s", name);
171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_warning(", continuing without symbols\n");
173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	} else if (nr == 0) {
175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#ifdef LIBELF_SUPPORT
176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		const size_t len = strlen(name);
177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		const size_t real_len = len - sizeof(DSO__DELETED);
178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (len > sizeof(DSO__DELETED) &&
180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    strcmp(name + real_len + 1, DSO__DELETED) == 0) {
181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pr_warning("%.*s was updated (is prelink enabled?). "
182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				"Restart the long running apps that use it!\n",
183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				   (int)real_len, name);
184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		} else {
185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pr_warning("no symbols found in %s, maybe install "
186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				   "a debug package?\n", name);
187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#endif
189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct symbol *map__find_symbol(struct map *map, u64 addr,
196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				symbol_filter_t filter)
197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (map__load(map, filter) < 0)
199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return NULL;
200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return dso__find_symbol(map->dso, map->type, addr);
202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct symbol *map__find_symbol_by_name(struct map *map, const char *name,
205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					symbol_filter_t filter)
206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (map__load(map, filter) < 0)
208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return NULL;
209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!dso__sorted_by_name(map->dso, map->type))
211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		dso__sort_by_name(map->dso, map->type);
212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return dso__find_symbol_by_name(map->dso, map->type, name);
214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct map *map__clone(struct map *map)
217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return memdup(map, sizeof(*map));
219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint map__overlap(struct map *l, struct map *r)
222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (l->start > r->start) {
224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct map *t = l;
225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		l = r;
226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		r = t;
227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (l->end > r->start)
230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 1;
231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t map__fprintf(struct map *map, FILE *fp)
236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n",
238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		       map->start, map->end, map->pgoff, map->dso->name);
239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t map__fprintf_dsoname(struct map *map, FILE *fp)
242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *dsoname = "[unknown]";
244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (map && map->dso && (map->dso->name || map->dso->long_name)) {
246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (symbol_conf.show_kernel_path && map->dso->long_name)
247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			dsoname = map->dso->long_name;
248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else if (map->dso->name)
249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			dsoname = map->dso->name;
250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return fprintf(fp, "%s", dsoname);
253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/*
256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is
258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * relative to section start.
259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */
260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengu64 map__rip_2objdump(struct map *map, u64 rip)
261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!map->dso->adjust_symbols)
263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return rip;
264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (map->dso->rel)
266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return rip - map->pgoff;
267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return map->unmap_ip(map, rip);
269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map_groups__init(struct map_groups *mg)
272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < MAP__NR_TYPES; ++i) {
275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		mg->maps[i] = RB_ROOT;
276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		INIT_LIST_HEAD(&mg->removed_maps[i]);
277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	mg->machine = NULL;
279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void maps__delete(struct rb_root *maps)
282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *next = rb_first(maps);
284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (next) {
286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct map *pos = rb_entry(next, struct map, rb_node);
287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		next = rb_next(&pos->rb_node);
289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		rb_erase(&pos->rb_node, maps);
290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		map__delete(pos);
291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void maps__delete_removed(struct list_head *maps)
295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct map *pos, *n;
297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	list_for_each_entry_safe(pos, n, maps, node) {
299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		list_del(&pos->node);
300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		map__delete(pos);
301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map_groups__exit(struct map_groups *mg)
305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < MAP__NR_TYPES; ++i) {
309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		maps__delete(&mg->maps[i]);
310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		maps__delete_removed(&mg->removed_maps[i]);
311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
314e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map_groups__flush(struct map_groups *mg)
315e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
316e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int type;
317e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
318e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (type = 0; type < MAP__NR_TYPES; type++) {
319e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct rb_root *root = &mg->maps[type];
320e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct rb_node *next = rb_first(root);
321e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
322e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		while (next) {
323e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			struct map *pos = rb_entry(next, struct map, rb_node);
324e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			next = rb_next(&pos->rb_node);
325e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			rb_erase(&pos->rb_node, root);
326e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			/*
327e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 * We may have references to this map, for
328e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 * instance in some hist_entry instances, so
329e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 * just move them to a separate list.
330e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 */
331e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			list_add_tail(&pos->node, &mg->removed_maps[pos->type]);
332e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
333e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
334e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
335e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
336e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct symbol *map_groups__find_symbol(struct map_groups *mg,
337e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				       enum map_type type, u64 addr,
338e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				       struct map **mapp,
339e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				       symbol_filter_t filter)
340e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
341e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct map *map = map_groups__find(mg, type, addr);
342e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
343e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (map != NULL) {
344e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (mapp != NULL)
345e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			*mapp = map;
346e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return map__find_symbol(map, map->map_ip(map, addr), filter);
347e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
348e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
349e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return NULL;
350e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
351e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
352e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
353e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					       enum map_type type,
354e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					       const char *name,
355e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					       struct map **mapp,
356e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					       symbol_filter_t filter)
357e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
358e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *nd;
359e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
360e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) {
361e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct map *pos = rb_entry(nd, struct map, rb_node);
362e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct symbol *sym = map__find_symbol_by_name(pos, name, filter);
363e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
364e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (sym == NULL)
365e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
366e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (mapp != NULL)
367e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			*mapp = pos;
368e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return sym;
369e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
370e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
371e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return NULL;
372e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
373e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
374e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t __map_groups__fprintf_maps(struct map_groups *mg,
375e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				  enum map_type type, int verbose, FILE *fp)
376e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
377e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
378e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *nd;
379e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
380e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) {
381e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct map *pos = rb_entry(nd, struct map, rb_node);
382e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		printed += fprintf(fp, "Map:");
383e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		printed += map__fprintf(pos, fp);
384e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (verbose > 2) {
385e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			printed += dso__fprintf(pos->dso, type, fp);
386e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			printed += fprintf(fp, "--\n");
387e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
388e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
389e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
390e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return printed;
391e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
392e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
393e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t map_groups__fprintf_maps(struct map_groups *mg, int verbose, FILE *fp)
394e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
395e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t printed = 0, i;
396e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < MAP__NR_TYPES; ++i)
397e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		printed += __map_groups__fprintf_maps(mg, i, verbose, fp);
398e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return printed;
399e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
400e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
401e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t __map_groups__fprintf_removed_maps(struct map_groups *mg,
402e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						 enum map_type type,
403e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						 int verbose, FILE *fp)
404e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
405e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct map *pos;
406e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t printed = 0;
407e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
408e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	list_for_each_entry(pos, &mg->removed_maps[type], node) {
409e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		printed += fprintf(fp, "Map:");
410e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		printed += map__fprintf(pos, fp);
411e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (verbose > 1) {
412e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			printed += dso__fprintf(pos->dso, type, fp);
413e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			printed += fprintf(fp, "--\n");
414e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
415e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
416e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return printed;
417e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
418e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
419e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t map_groups__fprintf_removed_maps(struct map_groups *mg,
420e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					       int verbose, FILE *fp)
421e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
422e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t printed = 0, i;
423e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < MAP__NR_TYPES; ++i)
424e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		printed += __map_groups__fprintf_removed_maps(mg, i, verbose, fp);
425e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return printed;
426e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
427e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
428e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t map_groups__fprintf(struct map_groups *mg, int verbose, FILE *fp)
429e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
430e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t printed = map_groups__fprintf_maps(mg, verbose, fp);
431e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	printed += fprintf(fp, "Removed maps:\n");
432e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return printed + map_groups__fprintf_removed_maps(mg, verbose, fp);
433e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
434e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
435e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
436e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				   int verbose, FILE *fp)
437e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
438e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_root *root = &mg->maps[map->type];
439e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *next = rb_first(root);
440e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int err = 0;
441e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
442e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (next) {
443e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct map *pos = rb_entry(next, struct map, rb_node);
444e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		next = rb_next(&pos->rb_node);
445e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
446e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!map__overlap(pos, map))
447e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
448e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
449e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (verbose >= 2) {
450e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			fputs("overlapping maps:\n", fp);
451e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			map__fprintf(map, fp);
452e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			map__fprintf(pos, fp);
453e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
454e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
455e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		rb_erase(&pos->rb_node, root);
456e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/*
457e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * Now check if we need to create new maps for areas not
458e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * overlapped by the new map:
459e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 */
460e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (map->start > pos->start) {
461e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			struct map *before = map__clone(pos);
462e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
463e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (before == NULL) {
464e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				err = -ENOMEM;
465e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				goto move_map;
466e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			}
467e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
468e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			before->end = map->start - 1;
469e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			map_groups__insert(mg, before);
470e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (verbose >= 2)
471e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				map__fprintf(before, fp);
472e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
473e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
474e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (map->end < pos->end) {
475e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			struct map *after = map__clone(pos);
476e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
477e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (after == NULL) {
478e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				err = -ENOMEM;
479e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				goto move_map;
480e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			}
481e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
482e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			after->start = map->end + 1;
483e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			map_groups__insert(mg, after);
484e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (verbose >= 2)
485e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				map__fprintf(after, fp);
486e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
487e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengmove_map:
488e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/*
489e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * If we have references, just move them to a separate list.
490e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 */
491e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (pos->referenced)
492e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			list_add_tail(&pos->node, &mg->removed_maps[map->type]);
493e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
494e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			map__delete(pos);
495e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
496e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (err)
497e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			return err;
498e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
499e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
500e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
501e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
502e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
503e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/*
504e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * XXX This should not really _copy_ te maps, but refcount them.
505e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */
506e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint map_groups__clone(struct map_groups *mg,
507e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		      struct map_groups *parent, enum map_type type)
508e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
509e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *nd;
510e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) {
511e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct map *map = rb_entry(nd, struct map, rb_node);
512e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct map *new = map__clone(map);
513e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (new == NULL)
514e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			return -ENOMEM;
515e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		map_groups__insert(mg, new);
516e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
517e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
518e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
519e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
520e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid maps__insert(struct rb_root *maps, struct map *map)
521e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
522e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node **p = &maps->rb_node;
523e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *parent = NULL;
524e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const u64 ip = map->start;
525e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct map *m;
526e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
527e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (*p != NULL) {
528e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		parent = *p;
529e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		m = rb_entry(parent, struct map, rb_node);
530e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (ip < m->start)
531e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			p = &(*p)->rb_left;
532e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
533e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			p = &(*p)->rb_right;
534e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
535e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
536e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	rb_link_node(&map->rb_node, parent, p);
537e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	rb_insert_color(&map->rb_node, maps);
538e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
539e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
540e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid maps__remove(struct rb_root *maps, struct map *map)
541e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
542e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	rb_erase(&map->rb_node, maps);
543e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
544e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
545e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct map *maps__find(struct rb_root *maps, u64 ip)
546e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
547e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node **p = &maps->rb_node;
548e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *parent = NULL;
549e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct map *m;
550e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
551e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (*p != NULL) {
552e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		parent = *p;
553e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		m = rb_entry(parent, struct map, rb_node);
554e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (ip < m->start)
555e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			p = &(*p)->rb_left;
556e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else if (ip > m->end)
557e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			p = &(*p)->rb_right;
558e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
559e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			return m;
560e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
561e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
562e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return NULL;
563e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
564e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
565e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct map *maps__first(struct rb_root *maps)
566e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
567e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *first = rb_first(maps);
568e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
569e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (first)
570e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return rb_entry(first, struct map, rb_node);
571e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return NULL;
572e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
573e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
574e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct map *maps__next(struct map *map)
575e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
576e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *next = rb_next(&map->rb_node);
577e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
578e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (next)
579e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return rb_entry(next, struct map, rb_node);
580e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return NULL;
581e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
582