]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - tools/perf/util/map.c
perf map: Use zalloc for map_groups
[mirror_ubuntu-eoan-kernel.git] / tools / perf / util / map.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
66e274f3 2#include "symbol.h"
724750b3 3#include <assert.h>
c6e718ff 4#include <errno.h>
9486aa38 5#include <inttypes.h>
4b8cf846 6#include <limits.h>
66e274f3
FW
7#include <stdlib.h>
8#include <string.h>
9#include <stdio.h>
a1645ce1 10#include <unistd.h>
fbef103f 11#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
4b8cf846 12#include "map.h"
5cd95c2d 13#include "thread.h"
7dbf4dcf 14#include "vdso.h"
ebb296c2 15#include "build-id.h"
acebd408 16#include "debug.h"
2a03068c 17#include "machine.h"
8e16017d 18#include <linux/string.h>
7f7c536f 19#include <linux/zalloc.h>
632a5cab 20#include "srcline.h"
843ff37b 21#include "namespaces.h"
6c502584 22#include "unwind.h"
dd2e18e9 23#include "srccode.h"
66e274f3 24
6a2ffcdd 25static void __maps__insert(struct maps *maps, struct map *map);
1e628569 26static void __maps__insert_name(struct maps *maps, struct map *map);
6a2ffcdd 27
0ac3348e 28static inline int is_anon_memory(const char *filename, u32 flags)
66e274f3 29{
fbef103f 30 return flags & MAP_HUGETLB ||
0ac3348e 31 !strcmp(filename, "//anon") ||
b2be5451
YB
32 !strncmp(filename, "/dev/zero", sizeof("/dev/zero") - 1) ||
33 !strncmp(filename, "/anon_hugepage", sizeof("/anon_hugepage") - 1);
66e274f3
FW
34}
35
87ffef79
JO
36static inline int is_no_dso_memory(const char *filename)
37{
1e82574d 38 return !strncmp(filename, "[stack", 6) ||
700be564 39 !strncmp(filename, "/SYSV",5) ||
87ffef79
JO
40 !strcmp(filename, "[heap]");
41}
42
eca81836
ML
43static inline int is_android_lib(const char *filename)
44{
45 return !strncmp(filename, "/data/app-lib", 13) ||
46 !strncmp(filename, "/system/lib", 11);
47}
48
49static inline bool replace_android_lib(const char *filename, char *newfilename)
50{
51 const char *libname;
52 char *app_abi;
53 size_t app_abi_length, new_length;
54 size_t lib_length = 0;
55
56 libname = strrchr(filename, '/');
57 if (libname)
58 lib_length = strlen(libname);
59
60 app_abi = getenv("APP_ABI");
61 if (!app_abi)
62 return false;
63
64 app_abi_length = strlen(app_abi);
65
66 if (!strncmp(filename, "/data/app-lib", 13)) {
67 char *apk_path;
68
69 if (!app_abi_length)
70 return false;
71
72 new_length = 7 + app_abi_length + lib_length;
73
74 apk_path = getenv("APK_PATH");
75 if (apk_path) {
76 new_length += strlen(apk_path) + 1;
77 if (new_length > PATH_MAX)
78 return false;
79 snprintf(newfilename, new_length,
80 "%s/libs/%s/%s", apk_path, app_abi, libname);
81 } else {
82 if (new_length > PATH_MAX)
83 return false;
84 snprintf(newfilename, new_length,
85 "libs/%s/%s", app_abi, libname);
86 }
87 return true;
88 }
89
90 if (!strncmp(filename, "/system/lib/", 11)) {
91 char *ndk, *app;
92 const char *arch;
93 size_t ndk_length;
94 size_t app_length;
95
96 ndk = getenv("NDK_ROOT");
97 app = getenv("APP_PLATFORM");
98
99 if (!(ndk && app))
100 return false;
101
102 ndk_length = strlen(ndk);
103 app_length = strlen(app);
104
105 if (!(ndk_length && app_length && app_abi_length))
106 return false;
107
108 arch = !strncmp(app_abi, "arm", 3) ? "arm" :
109 !strncmp(app_abi, "mips", 4) ? "mips" :
110 !strncmp(app_abi, "x86", 3) ? "x86" : NULL;
111
112 if (!arch)
113 return false;
114
115 new_length = 27 + ndk_length +
116 app_length + lib_length
117 + strlen(arch);
118
119 if (new_length > PATH_MAX)
120 return false;
121 snprintf(newfilename, new_length,
122 "%s/platforms/%s/arch-%s/usr/lib/%s",
123 ndk, app, arch, libname);
124
125 return true;
126 }
127 return false;
128}
129
3183f8ca 130void map__init(struct map *map, u64 start, u64 end, u64 pgoff, struct dso *dso)
afb7b4f0 131{
237a7e04
ACM
132 map->start = start;
133 map->end = end;
134 map->pgoff = pgoff;
9176753d 135 map->reloc = 0;
d3a7c489 136 map->dso = dso__get(dso);
237a7e04
ACM
137 map->map_ip = map__map_ip;
138 map->unmap_ip = map__unmap_ip;
139 RB_CLEAR_NODE(&map->rb_node);
140 map->groups = NULL;
237a7e04 141 map->erange_warned = false;
e3a42cdd 142 refcount_set(&map->refcnt, 1);
afb7b4f0
ACM
143}
144
2a03068c 145struct map *map__new(struct machine *machine, u64 start, u64 len,
bf2e710b 146 u64 pgoff, u32 d_maj, u32 d_min, u64 ino,
7ef80703 147 u64 ino_gen, u32 prot, u32 flags, char *filename,
3183f8ca 148 struct thread *thread)
66e274f3 149{
237a7e04 150 struct map *map = malloc(sizeof(*map));
bf2e710b
KJ
151 struct nsinfo *nsi = NULL;
152 struct nsinfo *nnsi;
66e274f3 153
237a7e04 154 if (map != NULL) {
66e274f3 155 char newfilename[PATH_MAX];
afb7b4f0 156 struct dso *dso;
eca81836 157 int anon, no_dso, vdso, android;
66e274f3 158
eca81836 159 android = is_android_lib(filename);
0ac3348e 160 anon = is_anon_memory(filename, flags);
7dbf4dcf 161 vdso = is_vdso_map(filename);
87ffef79 162 no_dso = is_no_dso_memory(filename);
66e274f3 163
5c5e854b
SE
164 map->maj = d_maj;
165 map->min = d_min;
166 map->ino = ino;
167 map->ino_generation = ino_gen;
7ef80703
DZ
168 map->prot = prot;
169 map->flags = flags;
bf2e710b 170 nsi = nsinfo__get(thread->nsinfo);
5c5e854b 171
d183b261 172 if ((anon || no_dso) && nsi && (prot & PROT_EXEC)) {
bf2e710b
KJ
173 snprintf(newfilename, sizeof(newfilename),
174 "/tmp/perf-%d.map", nsi->pid);
66e274f3
FW
175 filename = newfilename;
176 }
177
eca81836
ML
178 if (android) {
179 if (replace_android_lib(filename, newfilename))
180 filename = newfilename;
181 }
182
7dbf4dcf 183 if (vdso) {
bf2e710b
KJ
184 /* The vdso maps are always on the host and not the
185 * container. Ensure that we don't use setns to look
186 * them up.
187 */
188 nnsi = nsinfo__copy(nsi);
189 if (nnsi) {
190 nsinfo__put(nsi);
191 nnsi->need_setns = false;
192 nsi = nnsi;
193 }
7dbf4dcf 194 pgoff = 0;
9a4388c7 195 dso = machine__findnew_vdso(machine, thread);
7dbf4dcf 196 } else
aa7cc2ae 197 dso = machine__findnew_dso(machine, filename);
7dbf4dcf 198
afb7b4f0 199 if (dso == NULL)
66e274f3
FW
200 goto out_delete;
201
3183f8ca 202 map__init(map, start, start + len, pgoff, dso);
afb7b4f0 203
87ffef79 204 if (anon || no_dso) {
237a7e04 205 map->map_ip = map->unmap_ip = identity__map_ip;
87ffef79
JO
206
207 /*
208 * Set memory without DSO as loaded. All map__find_*
209 * functions still return NULL, and we avoid the
210 * unnecessary map__load warning.
211 */
d183b261 212 if (!(prot & PROT_EXEC))
3183f8ca 213 dso__set_loaded(dso);
8d92c02a 214 }
bf2e710b 215 dso->nsinfo = nsi;
d3a7c489 216 dso__put(dso);
66e274f3 217 }
237a7e04 218 return map;
66e274f3 219out_delete:
bf2e710b 220 nsinfo__put(nsi);
237a7e04 221 free(map);
66e274f3
FW
222 return NULL;
223}
224
e5a1845f
NK
225/*
226 * Constructor variant for modules (where we know from /proc/modules where
227 * they are loaded) and for vmlinux, where only after we load all the
228 * symbols we'll know where it starts and ends.
229 */
3183f8ca 230struct map *map__new2(u64 start, struct dso *dso)
e5a1845f
NK
231{
232 struct map *map = calloc(1, (sizeof(*map) +
233 (dso->kernel ? sizeof(struct kmap) : 0)));
234 if (map != NULL) {
235 /*
236 * ->end will be filled after we load all the symbols
237 */
3183f8ca 238 map__init(map, start, 0, 0, dso);
e5a1845f
NK
239 }
240
241 return map;
242}
243
e6ce7126
ACM
244/*
245 * Use this and __map__is_kmodule() for map instances that are in
246 * machine->kmaps, and thus have map->groups->machine all properly set, to
247 * disambiguate between the kernel and modules.
248 *
249 * When the need arises, introduce map__is_{kernel,kmodule)() that
250 * checks (map->groups != NULL && map->groups->machine != NULL &&
251 * map->dso->kernel) before calling __map__is_{kernel,kmodule}())
252 */
253bool __map__is_kernel(const struct map *map)
254{
3183f8ca 255 return machine__kernel_map(map->groups->machine) == map;
e6ce7126
ACM
256}
257
5759a682
AH
258bool __map__is_extra_kernel_map(const struct map *map)
259{
260 struct kmap *kmap = __map__kmap((struct map *)map);
261
262 return kmap && kmap->name[0];
263}
264
a93e0b23
SL
265bool __map__is_bpf_prog(const struct map *map)
266{
267 const char *name;
268
269 if (map->dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO)
270 return true;
271
272 /*
273 * If PERF_RECORD_BPF_EVENT is not included, the dso will not have
274 * type of DSO_BINARY_TYPE__BPF_PROG_INFO. In such cases, we can
275 * guess the type based on name.
276 */
277 name = map->dso->short_name;
278 return name && (strstr(name, "bpf_prog_") == name);
279}
280
e94b861a
ACM
281bool map__has_symbols(const struct map *map)
282{
3183f8ca 283 return dso__has_symbols(map->dso);
e94b861a
ACM
284}
285
d3a7c489 286static void map__exit(struct map *map)
c338aee8 287{
facf3f06 288 BUG_ON(!RB_EMPTY_NODE(&map->rb_node));
d3a7c489
ACM
289 dso__zput(map->dso);
290}
291
292void map__delete(struct map *map)
293{
294 map__exit(map);
237a7e04 295 free(map);
c338aee8
ACM
296}
297
84c2cafa
ACM
298void map__put(struct map *map)
299{
e3a42cdd 300 if (map && refcount_dec_and_test(&map->refcnt))
84c2cafa
ACM
301 map__delete(map);
302}
303
237a7e04 304void map__fixup_start(struct map *map)
c338aee8 305{
7137ff50
DB
306 struct rb_root_cached *symbols = &map->dso->symbols;
307 struct rb_node *nd = rb_first_cached(symbols);
c338aee8
ACM
308 if (nd != NULL) {
309 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
237a7e04 310 map->start = sym->start;
c338aee8
ACM
311 }
312}
313
237a7e04 314void map__fixup_end(struct map *map)
c338aee8 315{
7137ff50
DB
316 struct rb_root_cached *symbols = &map->dso->symbols;
317 struct rb_node *nd = rb_last(&symbols->rb_root);
c338aee8
ACM
318 if (nd != NULL) {
319 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
237a7e04 320 map->end = sym->end;
c338aee8
ACM
321 }
322}
323
d70a5402
ACM
324#define DSO__DELETED "(deleted)"
325
be39db9f 326int map__load(struct map *map)
66bd8424 327{
237a7e04 328 const char *name = map->dso->long_name;
a128168d 329 int nr;
79406cd7 330
3183f8ca 331 if (dso__loaded(map->dso))
a128168d
MH
332 return 0;
333
be39db9f 334 nr = dso__load(map->dso, map);
79406cd7 335 if (nr < 0) {
237a7e04 336 if (map->dso->has_build_id) {
b5d8bbe8 337 char sbuild_id[SBUILD_ID_SIZE];
79406cd7 338
237a7e04
ACM
339 build_id__sprintf(map->dso->build_id,
340 sizeof(map->dso->build_id),
79406cd7 341 sbuild_id);
d8e75a11 342 pr_debug("%s with build id %s not found", name, sbuild_id);
79406cd7 343 } else
d8e75a11 344 pr_debug("Failed to open %s", name);
79406cd7 345
d8e75a11 346 pr_debug(", continuing without symbols\n");
79406cd7
ACM
347 return -1;
348 } else if (nr == 0) {
89fe808a 349#ifdef HAVE_LIBELF_SUPPORT
79406cd7
ACM
350 const size_t len = strlen(name);
351 const size_t real_len = len - sizeof(DSO__DELETED);
352
353 if (len > sizeof(DSO__DELETED) &&
354 strcmp(name + real_len + 1, DSO__DELETED) == 0) {
d8e75a11 355 pr_debug("%.*s was updated (is prelink enabled?). "
e77b15bd 356 "Restart the long running apps that use it!\n",
79406cd7
ACM
357 (int)real_len, name);
358 } else {
d8e75a11 359 pr_debug("no symbols found in %s, maybe install a debug package?\n", name);
66bd8424 360 }
393be2e3 361#endif
79406cd7 362 return -1;
66bd8424
ACM
363 }
364
79406cd7
ACM
365 return 0;
366}
367
be39db9f 368struct symbol *map__find_symbol(struct map *map, u64 addr)
79406cd7 369{
be39db9f 370 if (map__load(map) < 0)
79406cd7
ACM
371 return NULL;
372
3183f8ca 373 return dso__find_symbol(map->dso, addr);
66bd8424
ACM
374}
375
be39db9f 376struct symbol *map__find_symbol_by_name(struct map *map, const char *name)
79406cd7 377{
be39db9f 378 if (map__load(map) < 0)
79406cd7
ACM
379 return NULL;
380
3183f8ca
ACM
381 if (!dso__sorted_by_name(map->dso))
382 dso__sort_by_name(map->dso);
79406cd7 383
3183f8ca 384 return dso__find_symbol_by_name(map->dso, name);
79406cd7
ACM
385}
386
66671d00 387struct map *map__clone(struct map *from)
66e274f3 388{
66671d00
ACM
389 struct map *map = memdup(from, sizeof(*map));
390
391 if (map != NULL) {
e3a42cdd 392 refcount_set(&map->refcnt, 1);
66671d00
ACM
393 RB_CLEAR_NODE(&map->rb_node);
394 dso__get(map->dso);
395 map->groups = NULL;
396 }
397
398 return map;
66e274f3
FW
399}
400
237a7e04 401size_t map__fprintf(struct map *map, FILE *fp)
66e274f3 402{
9486aa38 403 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n",
237a7e04 404 map->start, map->end, map->pgoff, map->dso->name);
66e274f3 405}
7a2b6209 406
547a92e0
AN
407size_t map__fprintf_dsoname(struct map *map, FILE *fp)
408{
1c492422 409 char buf[symbol_conf.pad_output_len_dso + 1];
8f28f19a 410 const char *dsoname = "[unknown]";
547a92e0 411
5eae7d84 412 if (map && map->dso) {
0bc8d205
AN
413 if (symbol_conf.show_kernel_path && map->dso->long_name)
414 dsoname = map->dso->long_name;
5eae7d84 415 else
0bc8d205 416 dsoname = map->dso->name;
8f28f19a 417 }
547a92e0 418
1c492422
JO
419 if (symbol_conf.pad_output_len_dso) {
420 scnprintf_pad(buf, symbol_conf.pad_output_len_dso, "%s", dsoname);
421 dsoname = buf;
422 }
423
547a92e0
AN
424 return fprintf(fp, "%s", dsoname);
425}
426
e2d88aaa
ACM
427char *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
cc8fae1d
AH
434int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
435 FILE *fp)
436{
cc8fae1d
AH
437 int ret = 0;
438
439 if (map && map->dso) {
e2d88aaa 440 char *srcline = map__srcline(map, addr, NULL);
cc8fae1d
AH
441 if (srcline != SRCLINE_UNKNOWN)
442 ret = fprintf(fp, "%s%s", prefix, srcline);
443 free_srcline(srcline);
444 }
445 return ret;
446}
447
dd2e18e9
AK
448int map__fprintf_srccode(struct map *map, u64 addr,
449 FILE *fp,
450 struct srccode_state *state)
451{
452 char *srcfile;
453 int ret = 0;
454 unsigned line;
455 int len;
456 char *srccode;
457
458 if (!map || !map->dso)
459 return 0;
460 srcfile = get_srcline_split(map->dso,
461 map__rip_2objdump(map, addr),
462 &line);
463 if (!srcfile)
464 return 0;
465
466 /* Avoid redundant printing */
467 if (state &&
468 state->srcfile &&
469 !strcmp(state->srcfile, srcfile) &&
470 state->line == line) {
471 free(srcfile);
472 return 0;
473 }
474
475 srccode = find_sourceline(srcfile, line, &len);
476 if (!srccode)
477 goto out_free_line;
478
479 ret = fprintf(fp, "|%-8d %.*s", line, len, srccode);
363bbaef
LY
480
481 if (state) {
482 state->srcfile = srcfile;
483 state->line = line;
484 }
dd2e18e9
AK
485 return ret;
486
487out_free_line:
488 free(srcfile);
489 return ret;
490}
491
492
493void srccode_state_free(struct srccode_state *state)
494{
495 zfree(&state->srcfile);
496 state->line = 0;
497}
498
1d5077bd
AH
499/**
500 * map__rip_2objdump - convert symbol start address to objdump address.
501 * @map: memory map
502 * @rip: symbol start address
503 *
7a2b6209 504 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
0131c4ec
AH
505 * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is
506 * relative to section start.
1d5077bd
AH
507 *
508 * Return: Address suitable for passing to "objdump --start-address="
7a2b6209
KS
509 */
510u64 map__rip_2objdump(struct map *map, u64 rip)
511{
97802f3b
AH
512 struct kmap *kmap = __map__kmap(map);
513
514 /*
515 * vmlinux does not have program headers for PTI entry trampolines and
516 * kcore may not either. However the trampoline object code is on the
517 * main kernel map, so just use that instead.
518 */
519 if (kmap && is_entry_trampoline(kmap->name) && kmap->kmaps && kmap->kmaps->machine) {
520 struct map *kernel_map = machine__kernel_map(kmap->kmaps->machine);
521
522 if (kernel_map)
523 map = kernel_map;
524 }
525
0131c4ec
AH
526 if (!map->dso->adjust_symbols)
527 return rip;
528
529 if (map->dso->rel)
530 return rip - map->pgoff;
531
a58f7033
WN
532 /*
533 * kernel modules also have DSO_TYPE_USER in dso->kernel,
534 * but all kernel modules are ET_REL, so won't get here.
535 */
536 if (map->dso->kernel == DSO_TYPE_USER)
537 return rip + map->dso->text_offset;
538
9176753d 539 return map->unmap_ip(map, rip) - map->reloc;
7a2b6209 540}
ee11b90b 541
1d5077bd
AH
542/**
543 * map__objdump_2mem - convert objdump address to a memory address.
544 * @map: memory map
545 * @ip: objdump address
546 *
547 * Closely related to map__rip_2objdump(), this function takes an address from
548 * objdump and converts it to a memory address. Note this assumes that @map
549 * contains the address. To be sure the result is valid, check it forwards
550 * e.g. map__rip_2objdump(map->map_ip(map, map__objdump_2mem(map, ip))) == ip
551 *
552 * Return: Memory address.
553 */
554u64 map__objdump_2mem(struct map *map, u64 ip)
555{
556 if (!map->dso->adjust_symbols)
557 return map->unmap_ip(map, ip);
558
559 if (map->dso->rel)
560 return map->unmap_ip(map, ip + map->pgoff);
561
a58f7033
WN
562 /*
563 * kernel modules also have DSO_TYPE_USER in dso->kernel,
564 * but all kernel modules are ET_REL, so won't get here.
565 */
566 if (map->dso->kernel == DSO_TYPE_USER)
567 return map->unmap_ip(map, ip - map->dso->text_offset);
568
9176753d 569 return ip + map->reloc;
1d5077bd
AH
570}
571
1eee78ae
ACM
572static void maps__init(struct maps *maps)
573{
574 maps->entries = RB_ROOT;
1e628569 575 maps->names = RB_ROOT;
0a7c74ea 576 init_rwsem(&maps->lock);
1eee78ae
ACM
577}
578
11246c70 579void map_groups__init(struct map_groups *mg, struct machine *machine)
c6e718ff 580{
3183f8ca 581 maps__init(&mg->maps);
11246c70 582 mg->machine = machine;
ead05e8f 583 refcount_set(&mg->refcnt, 1);
c6e718ff
ACM
584}
585
41f30914
ACM
586void map_groups__insert(struct map_groups *mg, struct map *map)
587{
588 maps__insert(&mg->maps, map);
589 map->groups = mg;
590}
591
6a2ffcdd 592static void __maps__purge(struct maps *maps)
591765fd 593{
1eee78ae
ACM
594 struct rb_root *root = &maps->entries;
595 struct rb_node *next = rb_first(root);
591765fd
ACM
596
597 while (next) {
598 struct map *pos = rb_entry(next, struct map, rb_node);
599
600 next = rb_next(&pos->rb_node);
facf3f06 601 rb_erase_init(&pos->rb_node, root);
84c2cafa 602 map__put(pos);
591765fd
ACM
603 }
604}
605
da3a53a7
CD
606static void __maps__purge_names(struct maps *maps)
607{
608 struct rb_root *root = &maps->names;
609 struct rb_node *next = rb_first(root);
610
611 while (next) {
612 struct map *pos = rb_entry(next, struct map, rb_node_name);
613
614 next = rb_next(&pos->rb_node_name);
615 rb_erase_init(&pos->rb_node_name, root);
616 map__put(pos);
617 }
618}
619
1eee78ae
ACM
620static void maps__exit(struct maps *maps)
621{
0a7c74ea 622 down_write(&maps->lock);
6a2ffcdd 623 __maps__purge(maps);
da3a53a7 624 __maps__purge_names(maps);
0a7c74ea 625 up_write(&maps->lock);
1eee78ae
ACM
626}
627
98dfd55d 628void map_groups__exit(struct map_groups *mg)
591765fd 629{
3183f8ca 630 maps__exit(&mg->maps);
591765fd
ACM
631}
632
29ce3612
AH
633bool map_groups__empty(struct map_groups *mg)
634{
3183f8ca 635 return !maps__first(&mg->maps);
29ce3612
AH
636}
637
11246c70 638struct map_groups *map_groups__new(struct machine *machine)
93d5731d 639{
d412c281 640 struct map_groups *mg = zalloc(sizeof(*mg));
93d5731d
ACM
641
642 if (mg != NULL)
11246c70 643 map_groups__init(mg, machine);
93d5731d
ACM
644
645 return mg;
646}
647
648void map_groups__delete(struct map_groups *mg)
649{
650 map_groups__exit(mg);
b312b6c2 651 unwind__finish_access(mg);
93d5731d
ACM
652 free(mg);
653}
654
a26ca671
ACM
655void map_groups__put(struct map_groups *mg)
656{
ead05e8f 657 if (mg && refcount_dec_and_test(&mg->refcnt))
a26ca671
ACM
658 map_groups__delete(mg);
659}
660
98dfd55d 661struct symbol *map_groups__find_symbol(struct map_groups *mg,
3183f8ca 662 u64 addr, struct map **mapp)
4b8cf846 663{
3183f8ca 664 struct map *map = map_groups__find(mg, addr);
4b8cf846 665
4afc81cd 666 /* Ensure map is loaded before using map->map_ip */
be39db9f 667 if (map != NULL && map__load(map) >= 0) {
7e5e1b14
ACM
668 if (mapp != NULL)
669 *mapp = map;
be39db9f 670 return map__find_symbol(map, map->map_ip(map, addr));
7e5e1b14
ACM
671 }
672
673 return NULL;
674}
675
03db8b58
AH
676static bool map__contains_symbol(struct map *map, struct symbol *sym)
677{
678 u64 ip = map->unmap_ip(map, sym->start);
679
680 return ip >= map->start && ip < map->end;
681}
682
b7f9ff56 683struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
be39db9f 684 struct map **mapp)
7e5e1b14 685{
6a2ffcdd 686 struct symbol *sym;
7e5e1b14
ACM
687 struct rb_node *nd;
688
0a7c74ea 689 down_read(&maps->lock);
6a2ffcdd
ACM
690
691 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) {
7e5e1b14 692 struct map *pos = rb_entry(nd, struct map, rb_node);
6a2ffcdd 693
be39db9f 694 sym = map__find_symbol_by_name(pos, name);
7e5e1b14
ACM
695
696 if (sym == NULL)
697 continue;
03db8b58
AH
698 if (!map__contains_symbol(pos, sym)) {
699 sym = NULL;
700 continue;
701 }
7e5e1b14
ACM
702 if (mapp != NULL)
703 *mapp = pos;
6a2ffcdd 704 goto out;
7e5e1b14 705 }
4b8cf846 706
6a2ffcdd
ACM
707 sym = NULL;
708out:
0a7c74ea 709 up_read(&maps->lock);
6a2ffcdd 710 return sym;
4b8cf846
ACM
711}
712
b7f9ff56 713struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
b7f9ff56 714 const char *name,
be39db9f 715 struct map **mapp)
b7f9ff56 716{
3183f8ca 717 return maps__find_symbol_by_name(&mg->maps, name, mapp);
b7f9ff56
ACM
718}
719
be39db9f 720int map_groups__find_ams(struct addr_map_symbol *ams)
4e987712 721{
77faf4d0 722 if (ams->addr < ams->map->start || ams->addr >= ams->map->end) {
4e987712
ACM
723 if (ams->map->groups == NULL)
724 return -1;
3183f8ca 725 ams->map = map_groups__find(ams->map->groups, ams->addr);
4e987712
ACM
726 if (ams->map == NULL)
727 return -1;
728 }
729
730 ams->al_addr = ams->map->map_ip(ams->map, ams->addr);
be39db9f 731 ams->sym = map__find_symbol(ams->map, ams->al_addr);
4e987712
ACM
732
733 return ams->sym ? 0 : -1;
734}
735
6a2ffcdd 736static size_t maps__fprintf(struct maps *maps, FILE *fp)
c6e718ff 737{
6a2ffcdd 738 size_t printed = 0;
c6e718ff
ACM
739 struct rb_node *nd;
740
0a7c74ea 741 down_read(&maps->lock);
6a2ffcdd
ACM
742
743 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) {
c6e718ff
ACM
744 struct map *pos = rb_entry(nd, struct map, rb_node);
745 printed += fprintf(fp, "Map:");
746 printed += map__fprintf(pos, fp);
747 if (verbose > 2) {
3183f8ca 748 printed += dso__fprintf(pos->dso, fp);
c6e718ff
ACM
749 printed += fprintf(fp, "--\n");
750 }
751 }
752
0a7c74ea 753 up_read(&maps->lock);
6a2ffcdd 754
c6e718ff
ACM
755 return printed;
756}
757
5c24b67a 758size_t map_groups__fprintf(struct map_groups *mg, FILE *fp)
c6e718ff 759{
3183f8ca 760 return maps__fprintf(&mg->maps, fp);
c6e718ff
ACM
761}
762
cb8382e0
JO
763static void __map_groups__insert(struct map_groups *mg, struct map *map)
764{
3183f8ca 765 __maps__insert(&mg->maps, map);
1e628569 766 __maps__insert_name(&mg->maps, map);
cb8382e0
JO
767 map->groups = mg;
768}
769
6a2ffcdd 770static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
c6e718ff 771{
6a2ffcdd 772 struct rb_root *root;
6a9405b5 773 struct rb_node *next, *first;
0a1eae39 774 int err = 0;
c6e718ff 775
0a7c74ea 776 down_write(&maps->lock);
6a2ffcdd
ACM
777
778 root = &maps->entries;
6a2ffcdd 779
6a9405b5
KK
780 /*
781 * Find first map where end > map->start.
782 * Same as find_vma() in kernel.
783 */
784 next = root->rb_node;
785 first = NULL;
786 while (next) {
787 struct map *pos = rb_entry(next, struct map, rb_node);
788
789 if (pos->end > map->start) {
790 first = next;
791 if (pos->start <= map->start)
792 break;
793 next = next->rb_left;
794 } else
795 next = next->rb_right;
796 }
797
798 next = first;
c6e718ff
ACM
799 while (next) {
800 struct map *pos = rb_entry(next, struct map, rb_node);
801 next = rb_next(&pos->rb_node);
802
6a9405b5
KK
803 /*
804 * Stop if current map starts after map->end.
805 * Maps are ordered by start: next will not overlap for sure.
806 */
807 if (pos->start >= map->end)
808 break;
c6e718ff
ACM
809
810 if (verbose >= 2) {
21e8c810
AB
811
812 if (use_browser) {
d8e75a11 813 pr_debug("overlapping maps in %s (disable tui for more info)\n",
21e8c810
AB
814 map->dso->name);
815 } else {
816 fputs("overlapping maps:\n", fp);
817 map__fprintf(map, fp);
818 map__fprintf(pos, fp);
819 }
c6e718ff
ACM
820 }
821
facf3f06 822 rb_erase_init(&pos->rb_node, root);
c6e718ff
ACM
823 /*
824 * Now check if we need to create new maps for areas not
825 * overlapped by the new map:
826 */
827 if (map->start > pos->start) {
828 struct map *before = map__clone(pos);
829
0a1eae39
ACM
830 if (before == NULL) {
831 err = -ENOMEM;
84c2cafa 832 goto put_map;
0a1eae39 833 }
c6e718ff 834
77faf4d0 835 before->end = map->start;
cb8382e0 836 __map_groups__insert(pos->groups, before);
21e8c810 837 if (verbose >= 2 && !use_browser)
c6e718ff 838 map__fprintf(before, fp);
d91130e9 839 map__put(before);
c6e718ff
ACM
840 }
841
842 if (map->end < pos->end) {
843 struct map *after = map__clone(pos);
844
0a1eae39
ACM
845 if (after == NULL) {
846 err = -ENOMEM;
84c2cafa 847 goto put_map;
0a1eae39 848 }
c6e718ff 849
77faf4d0 850 after->start = map->end;
724750b3
SM
851 after->pgoff += map->end - pos->start;
852 assert(pos->map_ip(pos, map->end) == after->map_ip(after, map->end));
cb8382e0 853 __map_groups__insert(pos->groups, after);
21e8c810 854 if (verbose >= 2 && !use_browser)
c6e718ff 855 map__fprintf(after, fp);
d91130e9 856 map__put(after);
c6e718ff 857 }
84c2cafa 858put_map:
5c24b67a 859 map__put(pos);
0a1eae39
ACM
860
861 if (err)
6a2ffcdd 862 goto out;
c6e718ff
ACM
863 }
864
6a2ffcdd
ACM
865 err = 0;
866out:
0a7c74ea 867 up_write(&maps->lock);
6a2ffcdd
ACM
868 return err;
869}
870
871int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
872 FILE *fp)
873{
3183f8ca 874 return maps__fixup_overlappings(&mg->maps, map, fp);
c6e718ff
ACM
875}
876
877/*
878 * XXX This should not really _copy_ te maps, but refcount them.
879 */
3183f8ca 880int map_groups__clone(struct thread *thread, struct map_groups *parent)
c6e718ff 881{
6c502584 882 struct map_groups *mg = thread->mg;
6a2ffcdd 883 int err = -ENOMEM;
4bb7123d 884 struct map *map;
3183f8ca 885 struct maps *maps = &parent->maps;
4bb7123d 886
0a7c74ea 887 down_read(&maps->lock);
6a2ffcdd 888
4bb7123d 889 for (map = maps__first(maps); map; map = map__next(map)) {
c6e718ff
ACM
890 struct map *new = map__clone(map);
891 if (new == NULL)
6a2ffcdd 892 goto out_unlock;
6c502584 893
b312b6c2 894 err = unwind__prepare_access(mg, new, NULL);
6c502584
JO
895 if (err)
896 goto out_unlock;
897
98dfd55d 898 map_groups__insert(mg, new);
bae32b50 899 map__put(new);
c6e718ff 900 }
6a2ffcdd
ACM
901
902 err = 0;
903out_unlock:
0a7c74ea 904 up_read(&maps->lock);
6a2ffcdd 905 return err;
c6e718ff
ACM
906}
907
6a2ffcdd 908static void __maps__insert(struct maps *maps, struct map *map)
4b8cf846 909{
1eee78ae 910 struct rb_node **p = &maps->entries.rb_node;
4b8cf846
ACM
911 struct rb_node *parent = NULL;
912 const u64 ip = map->start;
913 struct map *m;
914
915 while (*p != NULL) {
916 parent = *p;
917 m = rb_entry(parent, struct map, rb_node);
918 if (ip < m->start)
919 p = &(*p)->rb_left;
920 else
921 p = &(*p)->rb_right;
922 }
923
924 rb_link_node(&map->rb_node, parent, p);
1eee78ae 925 rb_insert_color(&map->rb_node, &maps->entries);
84c2cafa 926 map__get(map);
4b8cf846
ACM
927}
928
1e628569
ESE
929static void __maps__insert_name(struct maps *maps, struct map *map)
930{
931 struct rb_node **p = &maps->names.rb_node;
932 struct rb_node *parent = NULL;
933 struct map *m;
934 int rc;
935
936 while (*p != NULL) {
937 parent = *p;
938 m = rb_entry(parent, struct map, rb_node_name);
939 rc = strcmp(m->dso->short_name, map->dso->short_name);
940 if (rc < 0)
941 p = &(*p)->rb_left;
1e628569 942 else
b9abbdfa 943 p = &(*p)->rb_right;
1e628569
ESE
944 }
945 rb_link_node(&map->rb_node_name, parent, p);
946 rb_insert_color(&map->rb_node_name, &maps->names);
947 map__get(map);
948}
949
6a2ffcdd
ACM
950void maps__insert(struct maps *maps, struct map *map)
951{
0a7c74ea 952 down_write(&maps->lock);
6a2ffcdd 953 __maps__insert(maps, map);
1e628569 954 __maps__insert_name(maps, map);
0a7c74ea 955 up_write(&maps->lock);
6a2ffcdd
ACM
956}
957
958static void __maps__remove(struct maps *maps, struct map *map)
076c6e45 959{
facf3f06 960 rb_erase_init(&map->rb_node, &maps->entries);
84c2cafa 961 map__put(map);
b49265e0
CD
962
963 rb_erase_init(&map->rb_node_name, &maps->names);
964 map__put(map);
076c6e45
ACM
965}
966
6a2ffcdd
ACM
967void maps__remove(struct maps *maps, struct map *map)
968{
0a7c74ea 969 down_write(&maps->lock);
6a2ffcdd 970 __maps__remove(maps, map);
0a7c74ea 971 up_write(&maps->lock);
6a2ffcdd
ACM
972}
973
1eee78ae 974struct map *maps__find(struct maps *maps, u64 ip)
4b8cf846 975{
b18e0888 976 struct rb_node *p;
4b8cf846
ACM
977 struct map *m;
978
0a7c74ea 979 down_read(&maps->lock);
6a2ffcdd 980
b18e0888
ESE
981 p = maps->entries.rb_node;
982 while (p != NULL) {
983 m = rb_entry(p, struct map, rb_node);
4b8cf846 984 if (ip < m->start)
b18e0888 985 p = p->rb_left;
4955ea22 986 else if (ip >= m->end)
b18e0888 987 p = p->rb_right;
4b8cf846 988 else
6a2ffcdd 989 goto out;
4b8cf846
ACM
990 }
991
6a2ffcdd
ACM
992 m = NULL;
993out:
0a7c74ea 994 up_read(&maps->lock);
6a2ffcdd 995 return m;
4b8cf846 996}
8e0cf965 997
1eee78ae 998struct map *maps__first(struct maps *maps)
8e0cf965 999{
1eee78ae 1000 struct rb_node *first = rb_first(&maps->entries);
8e0cf965
AH
1001
1002 if (first)
1003 return rb_entry(first, struct map, rb_node);
1004 return NULL;
1005}
1006
4d4dee9a 1007struct map *map__next(struct map *map)
8e0cf965
AH
1008{
1009 struct rb_node *next = rb_next(&map->rb_node);
1010
1011 if (next)
1012 return rb_entry(next, struct map, rb_node);
1013 return NULL;
1014}
ba92732e 1015
5759a682 1016struct kmap *__map__kmap(struct map *map)
ba92732e 1017{
5759a682 1018 if (!map->dso || !map->dso->kernel)
ba92732e 1019 return NULL;
ba92732e
WN
1020 return (struct kmap *)(map + 1);
1021}
1022
5759a682
AH
1023struct kmap *map__kmap(struct map *map)
1024{
1025 struct kmap *kmap = __map__kmap(map);
1026
1027 if (!kmap)
1028 pr_err("Internal error: map__kmap with a non-kernel map\n");
1029 return kmap;
1030}
1031
ba92732e
WN
1032struct map_groups *map__kmaps(struct map *map)
1033{
1034 struct kmap *kmap = map__kmap(map);
1035
1036 if (!kmap || !kmap->kmaps) {
1037 pr_err("Internal error: map__kmaps with a non-kernel map\n");
1038 return NULL;
1039 }
1040 return kmap->kmaps;
1041}