blob: 8af693d9678cefe06ffa322e4913437fb04beb36 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Frederic Weisbecker66e274f2009-08-12 11:07:25 +02002#include "symbol.h"
Steve MacLeanee212d62019-09-28 01:39:00 +00003#include <assert.h>
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -03004#include <errno.h>
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -02005#include <inttypes.h>
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -03006#include <limits.h>
Frederic Weisbecker66e274f2009-08-12 11:07:25 +02007#include <stdlib.h>
8#include <string.h>
9#include <stdio.h>
Zhang, Yanmina1645ce2010-04-19 13:32:50 +080010#include <unistd.h>
Arnaldo Carvalho de Melofbef1032016-09-12 16:47:57 -030011#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
Arnaldo Carvalho de Melo4a3cec82019-08-30 11:11:01 -030012#include "dso.h"
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -030013#include "map.h"
Arnaldo Carvalho de Melod3300a32019-08-30 15:09:54 -030014#include "map_symbol.h"
David Ahern5cd95c22012-07-20 17:25:47 -060015#include "thread.h"
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020016#include "vdso.h"
Jiri Olsaebb296c2012-10-27 23:18:28 +020017#include "build-id.h"
Jiri Olsaacebd402014-07-14 23:46:47 +020018#include "debug.h"
Adrian Hunter2a030682014-07-22 16:17:53 +030019#include "machine.h"
Arnaldo Carvalho de Melo8e160172013-01-24 22:16:43 -030020#include <linux/string.h>
Arnaldo Carvalho de Melo7f7c5362019-07-04 11:32:27 -030021#include <linux/zalloc.h>
Arnaldo Carvalho de Melo632a5ca2017-04-17 16:30:49 -030022#include "srcline.h"
Krister Johansen843ff372017-07-05 18:48:08 -070023#include "namespaces.h"
Jiri Olsa6c502582016-07-04 14:16:23 +020024#include "unwind.h"
Andi Kleendd2e18e2018-12-03 16:18:48 -080025#include "srccode.h"
Arnaldo Carvalho de Melo8520a982019-08-29 16:18:59 -030026#include "ui/ui.h"
Frederic Weisbecker66e274f2009-08-12 11:07:25 +020027
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -030028static void __maps__insert(struct maps *maps, struct map *map);
29
Michael Lentineeca81832014-05-20 11:48:50 +020030static inline int is_android_lib(const char *filename)
31{
Arnaldo Carvalho de Melobdadd642020-03-09 16:53:41 -030032 return strstarts(filename, "/data/app-lib/") ||
33 strstarts(filename, "/system/lib/");
Michael Lentineeca81832014-05-20 11:48:50 +020034}
35
36static inline bool replace_android_lib(const char *filename, char *newfilename)
37{
38 const char *libname;
39 char *app_abi;
40 size_t app_abi_length, new_length;
41 size_t lib_length = 0;
42
43 libname = strrchr(filename, '/');
44 if (libname)
45 lib_length = strlen(libname);
46
47 app_abi = getenv("APP_ABI");
48 if (!app_abi)
49 return false;
50
51 app_abi_length = strlen(app_abi);
52
Arnaldo Carvalho de Melobdadd642020-03-09 16:53:41 -030053 if (strstarts(filename, "/data/app-lib/")) {
Michael Lentineeca81832014-05-20 11:48:50 +020054 char *apk_path;
55
56 if (!app_abi_length)
57 return false;
58
59 new_length = 7 + app_abi_length + lib_length;
60
61 apk_path = getenv("APK_PATH");
62 if (apk_path) {
63 new_length += strlen(apk_path) + 1;
64 if (new_length > PATH_MAX)
65 return false;
66 snprintf(newfilename, new_length,
67 "%s/libs/%s/%s", apk_path, app_abi, libname);
68 } else {
69 if (new_length > PATH_MAX)
70 return false;
71 snprintf(newfilename, new_length,
72 "libs/%s/%s", app_abi, libname);
73 }
74 return true;
75 }
76
Arnaldo Carvalho de Melobdadd642020-03-09 16:53:41 -030077 if (strstarts(filename, "/system/lib/")) {
Michael Lentineeca81832014-05-20 11:48:50 +020078 char *ndk, *app;
79 const char *arch;
Arnaldo Carvalho de Melo77d02bd2021-03-05 10:02:09 -030080 int ndk_length, app_length;
Michael Lentineeca81832014-05-20 11:48:50 +020081
82 ndk = getenv("NDK_ROOT");
83 app = getenv("APP_PLATFORM");
84
85 if (!(ndk && app))
86 return false;
87
88 ndk_length = strlen(ndk);
89 app_length = strlen(app);
90
91 if (!(ndk_length && app_length && app_abi_length))
92 return false;
93
94 arch = !strncmp(app_abi, "arm", 3) ? "arm" :
95 !strncmp(app_abi, "mips", 4) ? "mips" :
96 !strncmp(app_abi, "x86", 3) ? "x86" : NULL;
97
98 if (!arch)
99 return false;
100
101 new_length = 27 + ndk_length +
102 app_length + lib_length
103 + strlen(arch);
104
105 if (new_length > PATH_MAX)
106 return false;
107 snprintf(newfilename, new_length,
Arnaldo Carvalho de Melo77d02bd2021-03-05 10:02:09 -0300108 "%.*s/platforms/%.*s/arch-%s/usr/lib/%s",
109 ndk_length, ndk, app_length, app, arch, libname);
Michael Lentineeca81832014-05-20 11:48:50 +0200110
111 return true;
112 }
113 return false;
114}
115
Arnaldo Carvalho de Melo3183f8c2018-04-26 16:52:34 -0300116void map__init(struct map *map, u64 start, u64 end, u64 pgoff, struct dso *dso)
Arnaldo Carvalho de Meloafb7b4f2009-10-30 16:28:23 -0200117{
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300118 map->start = start;
119 map->end = end;
120 map->pgoff = pgoff;
Adrian Hunter91767532014-01-29 16:14:36 +0200121 map->reloc = 0;
Arnaldo Carvalho de Melod3a7c482015-06-02 11:53:26 -0300122 map->dso = dso__get(dso);
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300123 map->map_ip = map__map_ip;
124 map->unmap_ip = map__unmap_ip;
125 RB_CLEAR_NODE(&map->rb_node);
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300126 map->erange_warned = false;
Elena Reshetovae3a42cd2017-02-21 17:34:59 +0200127 refcount_set(&map->refcnt, 1);
Arnaldo Carvalho de Meloafb7b4f2009-10-30 16:28:23 -0200128}
129
Adrian Hunter2a030682014-07-22 16:17:53 +0300130struct map *map__new(struct machine *machine, u64 start, u64 len,
Arnaldo Carvalho de Melo4a7380a2019-11-19 12:40:29 -0300131 u64 pgoff, struct dso_id *id,
Jiri Olsa1ca6e802020-12-14 11:54:49 +0100132 u32 prot, u32 flags, struct build_id *bid,
133 char *filename, struct thread *thread)
Frederic Weisbecker66e274f2009-08-12 11:07:25 +0200134{
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300135 struct map *map = malloc(sizeof(*map));
Krister Johansenbf2e7102017-07-05 18:48:09 -0700136 struct nsinfo *nsi = NULL;
137 struct nsinfo *nnsi;
Frederic Weisbecker66e274f2009-08-12 11:07:25 +0200138
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300139 if (map != NULL) {
Frederic Weisbecker66e274f2009-08-12 11:07:25 +0200140 char newfilename[PATH_MAX];
Arnaldo Carvalho de Meloafb7b4f2009-10-30 16:28:23 -0200141 struct dso *dso;
Michael Lentineeca81832014-05-20 11:48:50 +0200142 int anon, no_dso, vdso, android;
Frederic Weisbecker66e274f2009-08-12 11:07:25 +0200143
Michael Lentineeca81832014-05-20 11:48:50 +0200144 android = is_android_lib(filename);
Namhyung Kime7b60c52020-10-12 16:02:12 +0900145 anon = is_anon_memory(filename) || flags & MAP_HUGETLB;
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200146 vdso = is_vdso_map(filename);
Jiri Olsa87ffef72011-08-24 15:18:34 +0200147 no_dso = is_no_dso_memory(filename);
Don Zickus7ef80702014-05-19 15:13:49 -0400148 map->prot = prot;
149 map->flags = flags;
Krister Johansenbf2e7102017-07-05 18:48:09 -0700150 nsi = nsinfo__get(thread->nsinfo);
Stephane Eranian5c5e8542013-08-21 12:10:25 +0200151
Arnaldo Carvalho de Melod183b262018-04-26 16:08:38 -0300152 if ((anon || no_dso) && nsi && (prot & PROT_EXEC)) {
Krister Johansenbf2e7102017-07-05 18:48:09 -0700153 snprintf(newfilename, sizeof(newfilename),
154 "/tmp/perf-%d.map", nsi->pid);
Frederic Weisbecker66e274f2009-08-12 11:07:25 +0200155 filename = newfilename;
156 }
157
Michael Lentineeca81832014-05-20 11:48:50 +0200158 if (android) {
159 if (replace_android_lib(filename, newfilename))
160 filename = newfilename;
161 }
162
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200163 if (vdso) {
Krister Johansenbf2e7102017-07-05 18:48:09 -0700164 /* The vdso maps are always on the host and not the
165 * container. Ensure that we don't use setns to look
166 * them up.
167 */
168 nnsi = nsinfo__copy(nsi);
169 if (nnsi) {
170 nsinfo__put(nsi);
171 nnsi->need_setns = false;
172 nsi = nnsi;
173 }
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200174 pgoff = 0;
Arnaldo Carvalho de Melo9a4388c2015-05-29 11:54:08 -0300175 dso = machine__findnew_vdso(machine, thread);
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200176 } else
Arnaldo Carvalho de Melo0e3149f2019-11-19 18:44:22 -0300177 dso = machine__findnew_dso_id(machine, filename, id);
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200178
Arnaldo Carvalho de Meloafb7b4f2009-10-30 16:28:23 -0200179 if (dso == NULL)
Frederic Weisbecker66e274f2009-08-12 11:07:25 +0200180 goto out_delete;
181
Arnaldo Carvalho de Melo3183f8c2018-04-26 16:52:34 -0300182 map__init(map, start, start + len, pgoff, dso);
Arnaldo Carvalho de Meloafb7b4f2009-10-30 16:28:23 -0200183
Jiri Olsa87ffef72011-08-24 15:18:34 +0200184 if (anon || no_dso) {
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300185 map->map_ip = map->unmap_ip = identity__map_ip;
Jiri Olsa87ffef72011-08-24 15:18:34 +0200186
187 /*
188 * Set memory without DSO as loaded. All map__find_*
189 * functions still return NULL, and we avoid the
190 * unnecessary map__load warning.
191 */
Arnaldo Carvalho de Melod183b262018-04-26 16:08:38 -0300192 if (!(prot & PROT_EXEC))
Arnaldo Carvalho de Melo3183f8c2018-04-26 16:52:34 -0300193 dso__set_loaded(dso);
Arnaldo Carvalho de Melo8d92c022010-02-03 16:52:02 -0200194 }
Krister Johansenbf2e7102017-07-05 18:48:09 -0700195 dso->nsinfo = nsi;
Jiri Olsa1ca6e802020-12-14 11:54:49 +0100196
197 if (build_id__is_defined(bid))
198 dso__set_build_id(dso, bid);
199
Arnaldo Carvalho de Melod3a7c482015-06-02 11:53:26 -0300200 dso__put(dso);
Frederic Weisbecker66e274f2009-08-12 11:07:25 +0200201 }
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300202 return map;
Frederic Weisbecker66e274f2009-08-12 11:07:25 +0200203out_delete:
Krister Johansenbf2e7102017-07-05 18:48:09 -0700204 nsinfo__put(nsi);
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300205 free(map);
Frederic Weisbecker66e274f2009-08-12 11:07:25 +0200206 return NULL;
207}
208
Namhyung Kime5a18452012-08-06 13:41:20 +0900209/*
210 * Constructor variant for modules (where we know from /proc/modules where
211 * they are loaded) and for vmlinux, where only after we load all the
212 * symbols we'll know where it starts and ends.
213 */
Arnaldo Carvalho de Melo3183f8c2018-04-26 16:52:34 -0300214struct map *map__new2(u64 start, struct dso *dso)
Namhyung Kime5a18452012-08-06 13:41:20 +0900215{
216 struct map *map = calloc(1, (sizeof(*map) +
217 (dso->kernel ? sizeof(struct kmap) : 0)));
218 if (map != NULL) {
219 /*
220 * ->end will be filled after we load all the symbols
221 */
Arnaldo Carvalho de Melo3183f8c2018-04-26 16:52:34 -0300222 map__init(map, start, 0, 0, dso);
Namhyung Kime5a18452012-08-06 13:41:20 +0900223 }
224
225 return map;
226}
227
Arnaldo Carvalho de Meloe6ce71262015-07-23 11:06:16 -0300228bool __map__is_kernel(const struct map *map)
229{
Arnaldo Carvalho de Melode90d512019-11-04 16:31:33 -0300230 if (!map->dso->kernel)
231 return false;
232 return machine__kernel_map(map__kmaps((struct map *)map)->machine) == map;
Arnaldo Carvalho de Meloe6ce71262015-07-23 11:06:16 -0300233}
234
Adrian Hunter5759a682018-05-22 13:54:35 +0300235bool __map__is_extra_kernel_map(const struct map *map)
236{
237 struct kmap *kmap = __map__kmap((struct map *)map);
238
239 return kmap && kmap->name[0];
240}
241
Song Liua93e0b22019-04-16 18:01:22 +0200242bool __map__is_bpf_prog(const struct map *map)
243{
244 const char *name;
245
246 if (map->dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO)
247 return true;
248
249 /*
250 * If PERF_RECORD_BPF_EVENT is not included, the dso will not have
251 * type of DSO_BINARY_TYPE__BPF_PROG_INFO. In such cases, we can
252 * guess the type based on name.
253 */
254 name = map->dso->short_name;
255 return name && (strstr(name, "bpf_prog_") == name);
256}
257
Jiri Olsa830fadf2020-08-26 23:30:17 +0200258bool __map__is_bpf_image(const struct map *map)
259{
260 const char *name;
261
262 if (map->dso->binary_type == DSO_BINARY_TYPE__BPF_IMAGE)
263 return true;
264
265 /*
266 * If PERF_RECORD_KSYMBOL is not included, the dso will not have
267 * type of DSO_BINARY_TYPE__BPF_IMAGE. In such cases, we can
268 * guess the type based on name.
269 */
270 name = map->dso->short_name;
271 return name && is_bpf_image(name);
272}
273
Adrian Hunter789e2412020-05-12 15:19:19 +0300274bool __map__is_ool(const struct map *map)
275{
276 return map->dso && map->dso->binary_type == DSO_BINARY_TYPE__OOL;
277}
278
Arnaldo Carvalho de Meloe94b8612018-04-23 17:13:49 -0300279bool map__has_symbols(const struct map *map)
280{
Arnaldo Carvalho de Melo3183f8c2018-04-26 16:52:34 -0300281 return dso__has_symbols(map->dso);
Arnaldo Carvalho de Meloe94b8612018-04-23 17:13:49 -0300282}
283
Arnaldo Carvalho de Melod3a7c482015-06-02 11:53:26 -0300284static void map__exit(struct map *map)
Arnaldo Carvalho de Meloc338aee2009-11-20 20:51:27 -0200285{
Arnaldo Carvalho de Meloee2555b2019-10-25 15:14:50 -0300286 BUG_ON(refcount_read(&map->refcnt) != 0);
Arnaldo Carvalho de Melod3a7c482015-06-02 11:53:26 -0300287 dso__zput(map->dso);
288}
289
290void map__delete(struct map *map)
291{
292 map__exit(map);
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300293 free(map);
Arnaldo Carvalho de Meloc338aee2009-11-20 20:51:27 -0200294}
295
Arnaldo Carvalho de Melo84c2caf2015-05-25 16:59:56 -0300296void map__put(struct map *map)
297{
Elena Reshetovae3a42cd2017-02-21 17:34:59 +0200298 if (map && refcount_dec_and_test(&map->refcnt))
Arnaldo Carvalho de Melo84c2caf2015-05-25 16:59:56 -0300299 map__delete(map);
300}
301
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300302void map__fixup_start(struct map *map)
Arnaldo Carvalho de Meloc338aee2009-11-20 20:51:27 -0200303{
Davidlohr Bueso7137ff52018-12-06 11:18:17 -0800304 struct rb_root_cached *symbols = &map->dso->symbols;
305 struct rb_node *nd = rb_first_cached(symbols);
Arnaldo Carvalho de Meloc338aee2009-11-20 20:51:27 -0200306 if (nd != NULL) {
307 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300308 map->start = sym->start;
Arnaldo Carvalho de Meloc338aee2009-11-20 20:51:27 -0200309 }
310}
311
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300312void map__fixup_end(struct map *map)
Arnaldo Carvalho de Meloc338aee2009-11-20 20:51:27 -0200313{
Davidlohr Bueso7137ff52018-12-06 11:18:17 -0800314 struct rb_root_cached *symbols = &map->dso->symbols;
315 struct rb_node *nd = rb_last(&symbols->rb_root);
Arnaldo Carvalho de Meloc338aee2009-11-20 20:51:27 -0200316 if (nd != NULL) {
317 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300318 map->end = sym->end;
Arnaldo Carvalho de Meloc338aee2009-11-20 20:51:27 -0200319 }
320}
321
Arnaldo Carvalho de Melod70a5402009-10-30 16:28:25 -0200322#define DSO__DELETED "(deleted)"
323
Arnaldo Carvalho de Melobe39db92016-09-01 19:25:52 -0300324int map__load(struct map *map)
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200325{
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300326 const char *name = map->dso->long_name;
Masami Hiramatsua1281682009-12-15 10:32:33 -0500327 int nr;
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200328
Arnaldo Carvalho de Melo3183f8c2018-04-26 16:52:34 -0300329 if (dso__loaded(map->dso))
Masami Hiramatsua1281682009-12-15 10:32:33 -0500330 return 0;
331
Arnaldo Carvalho de Melobe39db92016-09-01 19:25:52 -0300332 nr = dso__load(map->dso, map);
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200333 if (nr < 0) {
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300334 if (map->dso->has_build_id) {
Masami Hiramatsub5d8bbe2016-05-11 22:51:59 +0900335 char sbuild_id[SBUILD_ID_SIZE];
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200336
Jiri Olsabf541162020-10-13 21:24:36 +0200337 build_id__sprintf(&map->dso->bid, sbuild_id);
Arnaldo Carvalho de Melod8e75a12018-09-04 10:43:07 -0300338 pr_debug("%s with build id %s not found", name, sbuild_id);
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200339 } else
Arnaldo Carvalho de Melod8e75a12018-09-04 10:43:07 -0300340 pr_debug("Failed to open %s", name);
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200341
Arnaldo Carvalho de Melod8e75a12018-09-04 10:43:07 -0300342 pr_debug(", continuing without symbols\n");
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200343 return -1;
344 } else if (nr == 0) {
Ingo Molnar89fe8082013-09-30 12:07:11 +0200345#ifdef HAVE_LIBELF_SUPPORT
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200346 const size_t len = strlen(name);
347 const size_t real_len = len - sizeof(DSO__DELETED);
348
349 if (len > sizeof(DSO__DELETED) &&
350 strcmp(name + real_len + 1, DSO__DELETED) == 0) {
Arnaldo Carvalho de Melod8e75a12018-09-04 10:43:07 -0300351 pr_debug("%.*s was updated (is prelink enabled?). "
David Aherne77b15b2011-10-18 18:44:45 -0600352 "Restart the long running apps that use it!\n",
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200353 (int)real_len, name);
354 } else {
Arnaldo Carvalho de Melod8e75a12018-09-04 10:43:07 -0300355 pr_debug("no symbols found in %s, maybe install a debug package?\n", name);
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200356 }
Namhyung Kim393be2e2012-08-06 13:41:21 +0900357#endif
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200358 return -1;
359 }
360
361 return 0;
362}
363
Arnaldo Carvalho de Melobe39db92016-09-01 19:25:52 -0300364struct symbol *map__find_symbol(struct map *map, u64 addr)
Arnaldo Carvalho de Melo66bd8422009-10-28 21:51:21 -0200365{
Arnaldo Carvalho de Melobe39db92016-09-01 19:25:52 -0300366 if (map__load(map) < 0)
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200367 return NULL;
Arnaldo Carvalho de Melo66bd8422009-10-28 21:51:21 -0200368
Arnaldo Carvalho de Melo3183f8c2018-04-26 16:52:34 -0300369 return dso__find_symbol(map->dso, addr);
Arnaldo Carvalho de Melo66bd8422009-10-28 21:51:21 -0200370}
371
Arnaldo Carvalho de Melobe39db92016-09-01 19:25:52 -0300372struct symbol *map__find_symbol_by_name(struct map *map, const char *name)
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200373{
Arnaldo Carvalho de Melobe39db92016-09-01 19:25:52 -0300374 if (map__load(map) < 0)
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200375 return NULL;
376
Arnaldo Carvalho de Melo3183f8c2018-04-26 16:52:34 -0300377 if (!dso__sorted_by_name(map->dso))
378 dso__sort_by_name(map->dso);
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200379
Arnaldo Carvalho de Melo3183f8c2018-04-26 16:52:34 -0300380 return dso__find_symbol_by_name(map->dso, name);
Arnaldo Carvalho de Melo79406cd2009-12-11 18:50:22 -0200381}
382
Arnaldo Carvalho de Melo66671d02015-08-18 15:19:50 -0300383struct map *map__clone(struct map *from)
Frederic Weisbecker66e274f2009-08-12 11:07:25 +0200384{
Jiri Olsa7ce66132020-02-10 15:32:17 +0100385 size_t size = sizeof(struct map);
386 struct map *map;
Arnaldo Carvalho de Melo66671d02015-08-18 15:19:50 -0300387
Jiri Olsa7ce66132020-02-10 15:32:17 +0100388 if (from->dso && from->dso->kernel)
389 size += sizeof(struct kmap);
390
391 map = memdup(from, size);
Arnaldo Carvalho de Melo66671d02015-08-18 15:19:50 -0300392 if (map != NULL) {
Elena Reshetovae3a42cd2017-02-21 17:34:59 +0200393 refcount_set(&map->refcnt, 1);
Arnaldo Carvalho de Melo66671d02015-08-18 15:19:50 -0300394 RB_CLEAR_NODE(&map->rb_node);
395 dso__get(map->dso);
Arnaldo Carvalho de Melo66671d02015-08-18 15:19:50 -0300396 }
397
398 return map;
Frederic Weisbecker66e274f2009-08-12 11:07:25 +0200399}
400
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300401size_t map__fprintf(struct map *map, FILE *fp)
Frederic Weisbecker66e274f2009-08-12 11:07:25 +0200402{
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -0200403 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n",
Arnaldo Carvalho de Melo237a7e02013-01-24 21:59:59 -0300404 map->start, map->end, map->pgoff, map->dso->name);
Frederic Weisbecker66e274f2009-08-12 11:07:25 +0200405}
Kirill Smelkov7a2b6202010-02-03 16:52:07 -0200406
Akihiro Nagai547a92e2012-01-30 13:42:57 +0900407size_t map__fprintf_dsoname(struct map *map, FILE *fp)
408{
Jiri Olsa1c492422019-05-08 15:20:05 +0200409 char buf[symbol_conf.pad_output_len_dso + 1];
Feng Tang8f28f192012-08-27 15:38:26 +0800410 const char *dsoname = "[unknown]";
Akihiro Nagai547a92e2012-01-30 13:42:57 +0900411
Arnaldo Carvalho de Melo5eae7d82017-02-13 17:11:03 -0300412 if (map && map->dso) {
Akihiro Nagai0bc8d202012-01-30 13:43:20 +0900413 if (symbol_conf.show_kernel_path && map->dso->long_name)
414 dsoname = map->dso->long_name;
Arnaldo Carvalho de Melo5eae7d82017-02-13 17:11:03 -0300415 else
Akihiro Nagai0bc8d202012-01-30 13:43:20 +0900416 dsoname = map->dso->name;
Feng Tang8f28f192012-08-27 15:38:26 +0800417 }
Akihiro Nagai547a92e2012-01-30 13:42:57 +0900418
Jiri Olsa1c492422019-05-08 15:20:05 +0200419 if (symbol_conf.pad_output_len_dso) {
420 scnprintf_pad(buf, symbol_conf.pad_output_len_dso, "%s", dsoname);
421 dsoname = buf;
422 }
423
Akihiro Nagai547a92e2012-01-30 13:42:57 +0900424 return fprintf(fp, "%s", dsoname);
425}
426
Arnaldo Carvalho de Meloe2d88aa2018-05-28 11:05:20 -0300427char *map__srcline(struct map *map, u64 addr, struct symbol *sym)
428{
429 if (map == NULL)
430 return SRCLINE_UNKNOWN;
431 return get_srcline(map->dso, map__rip_2objdump(map, addr), sym, true, true, addr);
432}
433
Adrian Huntercc8fae12013-12-06 09:42:57 +0200434int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
435 FILE *fp)
436{
Adrian Huntercc8fae12013-12-06 09:42:57 +0200437 int ret = 0;
438
439 if (map && map->dso) {
Arnaldo Carvalho de Meloe2d88aa2018-05-28 11:05:20 -0300440 char *srcline = map__srcline(map, addr, NULL);
Nick Desaulniersc395c352020-02-23 11:34:49 -0800441 if (strncmp(srcline, SRCLINE_UNKNOWN, strlen(SRCLINE_UNKNOWN)) != 0)
Adrian Huntercc8fae12013-12-06 09:42:57 +0200442 ret = fprintf(fp, "%s%s", prefix, srcline);
443 free_srcline(srcline);
444 }
445 return ret;
446}
447
Andi Kleendd2e18e2018-12-03 16:18:48 -0800448void srccode_state_free(struct srccode_state *state)
449{
450 zfree(&state->srcfile);
451 state->line = 0;
452}
453
Adrian Hunter1d5077b2013-10-14 13:43:44 +0300454/**
455 * map__rip_2objdump - convert symbol start address to objdump address.
456 * @map: memory map
457 * @rip: symbol start address
458 *
Kirill Smelkov7a2b6202010-02-03 16:52:07 -0200459 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
Adrian Hunter0131c4e2013-08-07 14:38:50 +0300460 * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is
461 * relative to section start.
Adrian Hunter1d5077b2013-10-14 13:43:44 +0300462 *
463 * Return: Address suitable for passing to "objdump --start-address="
Kirill Smelkov7a2b6202010-02-03 16:52:07 -0200464 */
465u64 map__rip_2objdump(struct map *map, u64 rip)
466{
Adrian Hunter97802f32018-06-05 10:30:00 +0300467 struct kmap *kmap = __map__kmap(map);
468
469 /*
470 * vmlinux does not have program headers for PTI entry trampolines and
471 * kcore may not either. However the trampoline object code is on the
472 * main kernel map, so just use that instead.
473 */
474 if (kmap && is_entry_trampoline(kmap->name) && kmap->kmaps && kmap->kmaps->machine) {
475 struct map *kernel_map = machine__kernel_map(kmap->kmaps->machine);
476
477 if (kernel_map)
478 map = kernel_map;
479 }
480
Adrian Hunter0131c4e2013-08-07 14:38:50 +0300481 if (!map->dso->adjust_symbols)
482 return rip;
483
484 if (map->dso->rel)
485 return rip - map->pgoff;
486
Wang Nana58f7032016-04-07 10:24:30 +0000487 /*
488 * kernel modules also have DSO_TYPE_USER in dso->kernel,
489 * but all kernel modules are ET_REL, so won't get here.
490 */
Jiri Olsa1c695c82020-08-08 14:21:54 +0200491 if (map->dso->kernel == DSO_SPACE__USER)
Wang Nana58f7032016-04-07 10:24:30 +0000492 return rip + map->dso->text_offset;
493
Adrian Hunter91767532014-01-29 16:14:36 +0200494 return map->unmap_ip(map, rip) - map->reloc;
Kirill Smelkov7a2b6202010-02-03 16:52:07 -0200495}
Kirill Smelkovee11b902010-02-07 11:46:15 -0200496
Adrian Hunter1d5077b2013-10-14 13:43:44 +0300497/**
498 * map__objdump_2mem - convert objdump address to a memory address.
499 * @map: memory map
500 * @ip: objdump address
501 *
502 * Closely related to map__rip_2objdump(), this function takes an address from
503 * objdump and converts it to a memory address. Note this assumes that @map
504 * contains the address. To be sure the result is valid, check it forwards
505 * e.g. map__rip_2objdump(map->map_ip(map, map__objdump_2mem(map, ip))) == ip
506 *
507 * Return: Memory address.
508 */
509u64 map__objdump_2mem(struct map *map, u64 ip)
510{
511 if (!map->dso->adjust_symbols)
512 return map->unmap_ip(map, ip);
513
514 if (map->dso->rel)
515 return map->unmap_ip(map, ip + map->pgoff);
516
Wang Nana58f7032016-04-07 10:24:30 +0000517 /*
518 * kernel modules also have DSO_TYPE_USER in dso->kernel,
519 * but all kernel modules are ET_REL, so won't get here.
520 */
Jiri Olsa1c695c82020-08-08 14:21:54 +0200521 if (map->dso->kernel == DSO_SPACE__USER)
Wang Nana58f7032016-04-07 10:24:30 +0000522 return map->unmap_ip(map, ip - map->dso->text_offset);
523
Adrian Hunter91767532014-01-29 16:14:36 +0200524 return ip + map->reloc;
Adrian Hunter1d5077b2013-10-14 13:43:44 +0300525}
526
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300527void maps__init(struct maps *maps, struct machine *machine)
Arnaldo Carvalho de Melo1eee78a2015-05-22 12:58:53 -0300528{
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300529 maps->entries = RB_ROOT;
530 init_rwsem(&maps->lock);
531 maps->machine = machine;
532 maps->last_search_by_name = NULL;
533 maps->nr_maps = 0;
534 maps->maps_by_name = NULL;
535 refcount_set(&maps->refcnt, 1);
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300536}
537
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300538static void __maps__free_maps_by_name(struct maps *maps)
Arnaldo Carvalho de Meloa7c2b572019-11-17 11:38:13 -0300539{
540 /*
541 * Free everything to try to do it from the rbtree in the next search
542 */
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300543 zfree(&maps->maps_by_name);
544 maps->nr_maps_allocated = 0;
Arnaldo Carvalho de Meloa7c2b572019-11-17 11:38:13 -0300545}
546
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300547void maps__insert(struct maps *maps, struct map *map)
Arnaldo Carvalho de Melo41f30912019-01-27 13:44:29 +0100548{
Arnaldo Carvalho de Meloa7c2b572019-11-17 11:38:13 -0300549 down_write(&maps->lock);
550 __maps__insert(maps, map);
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300551 ++maps->nr_maps;
Arnaldo Carvalho de Meloa7c2b572019-11-17 11:38:13 -0300552
Jiri Olsa484214f2020-02-10 15:32:18 +0100553 if (map->dso && map->dso->kernel) {
554 struct kmap *kmap = map__kmap(map);
555
556 if (kmap)
557 kmap->kmaps = maps;
558 else
559 pr_err("Internal error: kernel dso with non kernel map\n");
560 }
561
562
Arnaldo Carvalho de Meloa7c2b572019-11-17 11:38:13 -0300563 /*
564 * If we already performed some search by name, then we need to add the just
565 * inserted map and resort.
566 */
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300567 if (maps->maps_by_name) {
568 if (maps->nr_maps > maps->nr_maps_allocated) {
569 int nr_allocate = maps->nr_maps * 2;
570 struct map **maps_by_name = realloc(maps->maps_by_name, nr_allocate * sizeof(map));
Arnaldo Carvalho de Meloa7c2b572019-11-17 11:38:13 -0300571
572 if (maps_by_name == NULL) {
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300573 __maps__free_maps_by_name(maps);
Cengiz Can85fc95d2020-01-20 17:15:54 +0300574 up_write(&maps->lock);
Arnaldo Carvalho de Meloa7c2b572019-11-17 11:38:13 -0300575 return;
576 }
577
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300578 maps->maps_by_name = maps_by_name;
579 maps->nr_maps_allocated = nr_allocate;
Arnaldo Carvalho de Meloa7c2b572019-11-17 11:38:13 -0300580 }
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300581 maps->maps_by_name[maps->nr_maps - 1] = map;
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300582 __maps__sort_by_name(maps);
Arnaldo Carvalho de Meloa7c2b572019-11-17 11:38:13 -0300583 }
584 up_write(&maps->lock);
Arnaldo Carvalho de Melo41f30912019-01-27 13:44:29 +0100585}
586
Arnaldo Carvalho de Meloa82f15e2019-11-25 10:42:38 -0300587static void __maps__remove(struct maps *maps, struct map *map)
588{
589 rb_erase_init(&map->rb_node, &maps->entries);
590 map__put(map);
591}
592
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300593void maps__remove(struct maps *maps, struct map *map)
Arnaldo Carvalho de Melo1ae14512019-11-13 16:33:33 -0300594{
Arnaldo Carvalho de Meloa7c2b572019-11-17 11:38:13 -0300595 down_write(&maps->lock);
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300596 if (maps->last_search_by_name == map)
597 maps->last_search_by_name = NULL;
Arnaldo Carvalho de Melo1ae14512019-11-13 16:33:33 -0300598
Arnaldo Carvalho de Meloa7c2b572019-11-17 11:38:13 -0300599 __maps__remove(maps, map);
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300600 --maps->nr_maps;
601 if (maps->maps_by_name)
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300602 __maps__free_maps_by_name(maps);
Arnaldo Carvalho de Meloa7c2b572019-11-17 11:38:13 -0300603 up_write(&maps->lock);
Arnaldo Carvalho de Melo1ae14512019-11-13 16:33:33 -0300604}
605
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300606static void __maps__purge(struct maps *maps)
Arnaldo Carvalho de Melo591765f2010-07-30 18:28:42 -0300607{
Arnaldo Carvalho de Melo8efc4f02019-10-28 11:31:38 -0300608 struct map *pos, *next;
Arnaldo Carvalho de Melo591765f2010-07-30 18:28:42 -0300609
Arnaldo Carvalho de Melo8efc4f02019-10-28 11:31:38 -0300610 maps__for_each_entry_safe(maps, pos, next) {
611 rb_erase_init(&pos->rb_node, &maps->entries);
Arnaldo Carvalho de Melo84c2caf2015-05-25 16:59:56 -0300612 map__put(pos);
Changbin Duda3a53a72019-03-16 16:05:51 +0800613 }
614}
615
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300616void maps__exit(struct maps *maps)
Arnaldo Carvalho de Melo1eee78a2015-05-22 12:58:53 -0300617{
Arnaldo Carvalho de Melo0a7c74e2017-04-04 13:15:04 -0300618 down_write(&maps->lock);
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300619 __maps__purge(maps);
Arnaldo Carvalho de Melo0a7c74e2017-04-04 13:15:04 -0300620 up_write(&maps->lock);
Arnaldo Carvalho de Melo1eee78a2015-05-22 12:58:53 -0300621}
622
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300623bool maps__empty(struct maps *maps)
Arnaldo Carvalho de Melo591765f2010-07-30 18:28:42 -0300624{
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300625 return !maps__first(maps);
Arnaldo Carvalho de Melo591765f2010-07-30 18:28:42 -0300626}
627
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300628struct maps *maps__new(struct machine *machine)
Adrian Hunter29ce3612014-07-16 11:07:13 +0300629{
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300630 struct maps *maps = zalloc(sizeof(*maps));
Arnaldo Carvalho de Melo93d57312014-03-21 17:57:01 -0300631
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300632 if (maps != NULL)
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300633 maps__init(maps, machine);
Arnaldo Carvalho de Melo93d57312014-03-21 17:57:01 -0300634
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300635 return maps;
Arnaldo Carvalho de Melo93d57312014-03-21 17:57:01 -0300636}
637
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300638void maps__delete(struct maps *maps)
Arnaldo Carvalho de Melo93d57312014-03-21 17:57:01 -0300639{
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300640 maps__exit(maps);
641 unwind__finish_access(maps);
642 free(maps);
Arnaldo Carvalho de Melo93d57312014-03-21 17:57:01 -0300643}
644
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300645void maps__put(struct maps *maps)
Arnaldo Carvalho de Meloa26ca672014-03-25 15:26:44 -0300646{
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300647 if (maps && refcount_dec_and_test(&maps->refcnt))
648 maps__delete(maps);
Arnaldo Carvalho de Meloa26ca672014-03-25 15:26:44 -0300649}
650
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300651struct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp)
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -0300652{
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300653 struct map *map = maps__find(maps, addr);
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -0300654
Masami Hiramatsu4afc81c2014-01-23 02:29:50 +0000655 /* Ensure map is loaded before using map->map_ip */
Arnaldo Carvalho de Melobe39db92016-09-01 19:25:52 -0300656 if (map != NULL && map__load(map) >= 0) {
Arnaldo Carvalho de Melo7e5e1b142010-03-26 12:30:40 -0300657 if (mapp != NULL)
658 *mapp = map;
Arnaldo Carvalho de Melobe39db92016-09-01 19:25:52 -0300659 return map__find_symbol(map, map->map_ip(map, addr));
Arnaldo Carvalho de Melo7e5e1b142010-03-26 12:30:40 -0300660 }
661
662 return NULL;
663}
664
Adrian Hunter03db8b52018-09-07 11:51:16 +0300665static bool map__contains_symbol(struct map *map, struct symbol *sym)
666{
667 u64 ip = map->unmap_ip(map, sym->start);
668
669 return ip >= map->start && ip < map->end;
670}
671
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300672struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp)
Arnaldo Carvalho de Melo7e5e1b142010-03-26 12:30:40 -0300673{
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300674 struct symbol *sym;
Arnaldo Carvalho de Melo8efc4f02019-10-28 11:31:38 -0300675 struct map *pos;
Arnaldo Carvalho de Melo7e5e1b142010-03-26 12:30:40 -0300676
Arnaldo Carvalho de Melo0a7c74e2017-04-04 13:15:04 -0300677 down_read(&maps->lock);
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300678
Arnaldo Carvalho de Melo8efc4f02019-10-28 11:31:38 -0300679 maps__for_each_entry(maps, pos) {
Arnaldo Carvalho de Melobe39db92016-09-01 19:25:52 -0300680 sym = map__find_symbol_by_name(pos, name);
Arnaldo Carvalho de Melo7e5e1b142010-03-26 12:30:40 -0300681
682 if (sym == NULL)
683 continue;
Adrian Hunter03db8b52018-09-07 11:51:16 +0300684 if (!map__contains_symbol(pos, sym)) {
685 sym = NULL;
686 continue;
687 }
Arnaldo Carvalho de Melo7e5e1b142010-03-26 12:30:40 -0300688 if (mapp != NULL)
689 *mapp = pos;
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300690 goto out;
Arnaldo Carvalho de Melo7e5e1b142010-03-26 12:30:40 -0300691 }
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -0300692
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300693 sym = NULL;
694out:
Arnaldo Carvalho de Melo0a7c74e2017-04-04 13:15:04 -0300695 up_read(&maps->lock);
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300696 return sym;
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -0300697}
698
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300699int maps__find_ams(struct maps *maps, struct addr_map_symbol *ams)
Arnaldo Carvalho de Melo4e987712013-10-14 13:43:38 +0300700{
Arnaldo Carvalho de Melod46a4cd2019-11-04 15:57:38 -0300701 if (ams->addr < ams->ms.map->start || ams->addr >= ams->ms.map->end) {
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300702 if (maps == NULL)
Arnaldo Carvalho de Melo4e987712013-10-14 13:43:38 +0300703 return -1;
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300704 ams->ms.map = maps__find(maps, ams->addr);
Arnaldo Carvalho de Melod46a4cd2019-11-04 15:57:38 -0300705 if (ams->ms.map == NULL)
Arnaldo Carvalho de Melo4e987712013-10-14 13:43:38 +0300706 return -1;
707 }
708
Arnaldo Carvalho de Melod46a4cd2019-11-04 15:57:38 -0300709 ams->al_addr = ams->ms.map->map_ip(ams->ms.map, ams->addr);
710 ams->ms.sym = map__find_symbol(ams->ms.map, ams->al_addr);
Arnaldo Carvalho de Melo4e987712013-10-14 13:43:38 +0300711
Arnaldo Carvalho de Melod46a4cd2019-11-04 15:57:38 -0300712 return ams->ms.sym ? 0 : -1;
Arnaldo Carvalho de Melo4e987712013-10-14 13:43:38 +0300713}
714
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300715size_t maps__fprintf(struct maps *maps, FILE *fp)
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300716{
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300717 size_t printed = 0;
Arnaldo Carvalho de Melo8efc4f02019-10-28 11:31:38 -0300718 struct map *pos;
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300719
Arnaldo Carvalho de Melo0a7c74e2017-04-04 13:15:04 -0300720 down_read(&maps->lock);
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300721
Arnaldo Carvalho de Melo8efc4f02019-10-28 11:31:38 -0300722 maps__for_each_entry(maps, pos) {
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300723 printed += fprintf(fp, "Map:");
724 printed += map__fprintf(pos, fp);
725 if (verbose > 2) {
Arnaldo Carvalho de Melo3183f8c2018-04-26 16:52:34 -0300726 printed += dso__fprintf(pos->dso, fp);
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300727 printed += fprintf(fp, "--\n");
728 }
729 }
730
Arnaldo Carvalho de Melo0a7c74e2017-04-04 13:15:04 -0300731 up_read(&maps->lock);
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300732
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300733 return printed;
734}
735
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300736int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300737{
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300738 struct rb_root *root;
Konstantin Khlebnikov6a9405b2018-08-07 17:24:54 +0300739 struct rb_node *next, *first;
Arnaldo Carvalho de Melo0a1eae32010-08-02 19:45:23 -0300740 int err = 0;
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300741
Arnaldo Carvalho de Melo0a7c74e2017-04-04 13:15:04 -0300742 down_write(&maps->lock);
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300743
744 root = &maps->entries;
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300745
Konstantin Khlebnikov6a9405b2018-08-07 17:24:54 +0300746 /*
747 * Find first map where end > map->start.
748 * Same as find_vma() in kernel.
749 */
750 next = root->rb_node;
751 first = NULL;
752 while (next) {
753 struct map *pos = rb_entry(next, struct map, rb_node);
754
755 if (pos->end > map->start) {
756 first = next;
757 if (pos->start <= map->start)
758 break;
759 next = next->rb_left;
760 } else
761 next = next->rb_right;
762 }
763
764 next = first;
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300765 while (next) {
766 struct map *pos = rb_entry(next, struct map, rb_node);
767 next = rb_next(&pos->rb_node);
768
Konstantin Khlebnikov6a9405b2018-08-07 17:24:54 +0300769 /*
770 * Stop if current map starts after map->end.
771 * Maps are ordered by start: next will not overlap for sure.
772 */
773 if (pos->start >= map->end)
774 break;
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300775
776 if (verbose >= 2) {
Alexis Berlemont21e8c812016-10-12 23:48:23 +0200777
778 if (use_browser) {
Arnaldo Carvalho de Melod8e75a12018-09-04 10:43:07 -0300779 pr_debug("overlapping maps in %s (disable tui for more info)\n",
Alexis Berlemont21e8c812016-10-12 23:48:23 +0200780 map->dso->name);
781 } else {
782 fputs("overlapping maps:\n", fp);
783 map__fprintf(map, fp);
784 map__fprintf(pos, fp);
785 }
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300786 }
787
Arnaldo Carvalho de Melofacf3f02015-05-25 15:30:09 -0300788 rb_erase_init(&pos->rb_node, root);
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300789 /*
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300790 * Now check if we need to create new maps for areas not
791 * overlapped by the new map:
792 */
793 if (map->start > pos->start) {
794 struct map *before = map__clone(pos);
795
Arnaldo Carvalho de Melo0a1eae32010-08-02 19:45:23 -0300796 if (before == NULL) {
797 err = -ENOMEM;
Arnaldo Carvalho de Melo84c2caf2015-05-25 16:59:56 -0300798 goto put_map;
Arnaldo Carvalho de Melo0a1eae32010-08-02 19:45:23 -0300799 }
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300800
Stephane Eranian77faf4d2014-10-06 10:35:32 +0200801 before->end = map->start;
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300802 __maps__insert(maps, before);
Alexis Berlemont21e8c812016-10-12 23:48:23 +0200803 if (verbose >= 2 && !use_browser)
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300804 map__fprintf(before, fp);
Masami Hiramatsud91130e2015-12-09 11:11:31 +0900805 map__put(before);
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300806 }
807
808 if (map->end < pos->end) {
809 struct map *after = map__clone(pos);
810
Arnaldo Carvalho de Melo0a1eae32010-08-02 19:45:23 -0300811 if (after == NULL) {
812 err = -ENOMEM;
Arnaldo Carvalho de Melo84c2caf2015-05-25 16:59:56 -0300813 goto put_map;
Arnaldo Carvalho de Melo0a1eae32010-08-02 19:45:23 -0300814 }
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300815
Stephane Eranian77faf4d2014-10-06 10:35:32 +0200816 after->start = map->end;
Steve MacLeanee212d62019-09-28 01:39:00 +0000817 after->pgoff += map->end - pos->start;
818 assert(pos->map_ip(pos, map->end) == after->map_ip(after, map->end));
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300819 __maps__insert(maps, after);
Alexis Berlemont21e8c812016-10-12 23:48:23 +0200820 if (verbose >= 2 && !use_browser)
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300821 map__fprintf(after, fp);
Masami Hiramatsud91130e2015-12-09 11:11:31 +0900822 map__put(after);
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300823 }
Arnaldo Carvalho de Melo84c2caf2015-05-25 16:59:56 -0300824put_map:
Arnaldo Carvalho de Melo5c24b672015-06-15 23:29:51 -0300825 map__put(pos);
Arnaldo Carvalho de Melo0a1eae32010-08-02 19:45:23 -0300826
827 if (err)
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300828 goto out;
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300829 }
830
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300831 err = 0;
832out:
Arnaldo Carvalho de Melo0a7c74e2017-04-04 13:15:04 -0300833 up_write(&maps->lock);
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300834 return err;
835}
836
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300837/*
838 * XXX This should not really _copy_ te maps, but refcount them.
839 */
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300840int maps__clone(struct thread *thread, struct maps *parent)
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300841{
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300842 struct maps *maps = thread->maps;
Zhen Leic6f87142021-04-15 17:27:44 +0800843 int err;
Arnaldo Carvalho de Melo4bb7123d2015-05-22 11:52:22 -0300844 struct map *map;
Arnaldo Carvalho de Melo4bb7123d2015-05-22 11:52:22 -0300845
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300846 down_read(&parent->lock);
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300847
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300848 maps__for_each_entry(parent, map) {
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300849 struct map *new = map__clone(map);
Zhen Leic6f87142021-04-15 17:27:44 +0800850
851 if (new == NULL) {
852 err = -ENOMEM;
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300853 goto out_unlock;
Zhen Leic6f87142021-04-15 17:27:44 +0800854 }
Jiri Olsa6c502582016-07-04 14:16:23 +0200855
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300856 err = unwind__prepare_access(maps, new, NULL);
Jiri Olsa6c502582016-07-04 14:16:23 +0200857 if (err)
858 goto out_unlock;
859
Arnaldo Carvalho de Melo9a29cee2019-11-25 22:21:28 -0300860 maps__insert(maps, new);
Masami Hiramatsubae32b52015-12-09 11:11:20 +0900861 map__put(new);
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300862 }
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300863
864 err = 0;
865out_unlock:
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300866 up_read(&parent->lock);
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300867 return err;
Arnaldo Carvalho de Meloc6e718f2010-03-26 12:11:06 -0300868}
869
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300870static void __maps__insert(struct maps *maps, struct map *map)
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -0300871{
Arnaldo Carvalho de Melo1eee78a2015-05-22 12:58:53 -0300872 struct rb_node **p = &maps->entries.rb_node;
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -0300873 struct rb_node *parent = NULL;
874 const u64 ip = map->start;
875 struct map *m;
876
877 while (*p != NULL) {
878 parent = *p;
879 m = rb_entry(parent, struct map, rb_node);
880 if (ip < m->start)
881 p = &(*p)->rb_left;
882 else
883 p = &(*p)->rb_right;
884 }
885
886 rb_link_node(&map->rb_node, parent, p);
Arnaldo Carvalho de Melo1eee78a2015-05-22 12:58:53 -0300887 rb_insert_color(&map->rb_node, &maps->entries);
Arnaldo Carvalho de Melo84c2caf2015-05-25 16:59:56 -0300888 map__get(map);
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -0300889}
890
Arnaldo Carvalho de Melo1eee78a2015-05-22 12:58:53 -0300891struct map *maps__find(struct maps *maps, u64 ip)
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -0300892{
Eric Saint-Etienneb18e0882018-11-23 02:42:39 -0800893 struct rb_node *p;
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -0300894 struct map *m;
895
Arnaldo Carvalho de Melo0a7c74e2017-04-04 13:15:04 -0300896 down_read(&maps->lock);
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300897
Eric Saint-Etienneb18e0882018-11-23 02:42:39 -0800898 p = maps->entries.rb_node;
899 while (p != NULL) {
900 m = rb_entry(p, struct map, rb_node);
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -0300901 if (ip < m->start)
Eric Saint-Etienneb18e0882018-11-23 02:42:39 -0800902 p = p->rb_left;
Namhyung Kim4955ea22014-10-14 16:05:38 -0300903 else if (ip >= m->end)
Eric Saint-Etienneb18e0882018-11-23 02:42:39 -0800904 p = p->rb_right;
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -0300905 else
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300906 goto out;
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -0300907 }
908
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300909 m = NULL;
910out:
Arnaldo Carvalho de Melo0a7c74e2017-04-04 13:15:04 -0300911 up_read(&maps->lock);
Arnaldo Carvalho de Melo6a2ffcd2015-05-22 13:45:24 -0300912 return m;
Arnaldo Carvalho de Melo4b8cf842010-03-25 19:58:58 -0300913}
Adrian Hunter8e0cf962013-08-07 14:38:51 +0300914
Arnaldo Carvalho de Melo1eee78a2015-05-22 12:58:53 -0300915struct map *maps__first(struct maps *maps)
Adrian Hunter8e0cf962013-08-07 14:38:51 +0300916{
Arnaldo Carvalho de Melo1eee78a2015-05-22 12:58:53 -0300917 struct rb_node *first = rb_first(&maps->entries);
Adrian Hunter8e0cf962013-08-07 14:38:51 +0300918
919 if (first)
920 return rb_entry(first, struct map, rb_node);
921 return NULL;
922}
923
Arnaldo Carvalho de Melo20419d3a2019-10-28 11:50:12 -0300924static struct map *__map__next(struct map *map)
Adrian Hunter8e0cf962013-08-07 14:38:51 +0300925{
926 struct rb_node *next = rb_next(&map->rb_node);
927
928 if (next)
929 return rb_entry(next, struct map, rb_node);
930 return NULL;
931}
Wang Nanba927322015-04-07 08:22:45 +0000932
Arnaldo Carvalho de Melo20419d3a2019-10-28 11:50:12 -0300933struct map *map__next(struct map *map)
934{
935 return map ? __map__next(map) : NULL;
936}
937
Adrian Hunter5759a682018-05-22 13:54:35 +0300938struct kmap *__map__kmap(struct map *map)
939{
940 if (!map->dso || !map->dso->kernel)
941 return NULL;
942 return (struct kmap *)(map + 1);
943}
944
Wang Nanba927322015-04-07 08:22:45 +0000945struct kmap *map__kmap(struct map *map)
946{
Adrian Hunter5759a682018-05-22 13:54:35 +0300947 struct kmap *kmap = __map__kmap(map);
948
949 if (!kmap)
Wang Nanba927322015-04-07 08:22:45 +0000950 pr_err("Internal error: map__kmap with a non-kernel map\n");
Adrian Hunter5759a682018-05-22 13:54:35 +0300951 return kmap;
Wang Nanba927322015-04-07 08:22:45 +0000952}
953
Arnaldo Carvalho de Melo79b6bb72019-11-25 21:58:33 -0300954struct maps *map__kmaps(struct map *map)
Wang Nanba927322015-04-07 08:22:45 +0000955{
956 struct kmap *kmap = map__kmap(map);
957
958 if (!kmap || !kmap->kmaps) {
959 pr_err("Internal error: map__kmaps with a non-kernel map\n");
960 return NULL;
961 }
962 return kmap->kmaps;
963}