18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include "symbol.h"
38c2ecf20Sopenharmony_ci#include <assert.h>
48c2ecf20Sopenharmony_ci#include <errno.h>
58c2ecf20Sopenharmony_ci#include <inttypes.h>
68c2ecf20Sopenharmony_ci#include <limits.h>
78c2ecf20Sopenharmony_ci#include <stdlib.h>
88c2ecf20Sopenharmony_ci#include <string.h>
98c2ecf20Sopenharmony_ci#include <stdio.h>
108c2ecf20Sopenharmony_ci#include <unistd.h>
118c2ecf20Sopenharmony_ci#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
128c2ecf20Sopenharmony_ci#include "dso.h"
138c2ecf20Sopenharmony_ci#include "map.h"
148c2ecf20Sopenharmony_ci#include "map_symbol.h"
158c2ecf20Sopenharmony_ci#include "thread.h"
168c2ecf20Sopenharmony_ci#include "vdso.h"
178c2ecf20Sopenharmony_ci#include "build-id.h"
188c2ecf20Sopenharmony_ci#include "debug.h"
198c2ecf20Sopenharmony_ci#include "machine.h"
208c2ecf20Sopenharmony_ci#include <linux/string.h>
218c2ecf20Sopenharmony_ci#include <linux/zalloc.h>
228c2ecf20Sopenharmony_ci#include "srcline.h"
238c2ecf20Sopenharmony_ci#include "namespaces.h"
248c2ecf20Sopenharmony_ci#include "unwind.h"
258c2ecf20Sopenharmony_ci#include "srccode.h"
268c2ecf20Sopenharmony_ci#include "ui/ui.h"
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic void __maps__insert(struct maps *maps, struct map *map);
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic inline int is_android_lib(const char *filename)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	return strstarts(filename, "/data/app-lib/") ||
338c2ecf20Sopenharmony_ci	       strstarts(filename, "/system/lib/");
348c2ecf20Sopenharmony_ci}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cistatic inline bool replace_android_lib(const char *filename, char *newfilename)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	const char *libname;
398c2ecf20Sopenharmony_ci	char *app_abi;
408c2ecf20Sopenharmony_ci	size_t app_abi_length, new_length;
418c2ecf20Sopenharmony_ci	size_t lib_length = 0;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	libname  = strrchr(filename, '/');
448c2ecf20Sopenharmony_ci	if (libname)
458c2ecf20Sopenharmony_ci		lib_length = strlen(libname);
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	app_abi = getenv("APP_ABI");
488c2ecf20Sopenharmony_ci	if (!app_abi)
498c2ecf20Sopenharmony_ci		return false;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	app_abi_length = strlen(app_abi);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	if (strstarts(filename, "/data/app-lib/")) {
548c2ecf20Sopenharmony_ci		char *apk_path;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci		if (!app_abi_length)
578c2ecf20Sopenharmony_ci			return false;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci		new_length = 7 + app_abi_length + lib_length;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci		apk_path = getenv("APK_PATH");
628c2ecf20Sopenharmony_ci		if (apk_path) {
638c2ecf20Sopenharmony_ci			new_length += strlen(apk_path) + 1;
648c2ecf20Sopenharmony_ci			if (new_length > PATH_MAX)
658c2ecf20Sopenharmony_ci				return false;
668c2ecf20Sopenharmony_ci			snprintf(newfilename, new_length,
678c2ecf20Sopenharmony_ci				 "%s/libs/%s/%s", apk_path, app_abi, libname);
688c2ecf20Sopenharmony_ci		} else {
698c2ecf20Sopenharmony_ci			if (new_length > PATH_MAX)
708c2ecf20Sopenharmony_ci				return false;
718c2ecf20Sopenharmony_ci			snprintf(newfilename, new_length,
728c2ecf20Sopenharmony_ci				 "libs/%s/%s", app_abi, libname);
738c2ecf20Sopenharmony_ci		}
748c2ecf20Sopenharmony_ci		return true;
758c2ecf20Sopenharmony_ci	}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	if (strstarts(filename, "/system/lib/")) {
788c2ecf20Sopenharmony_ci		char *ndk, *app;
798c2ecf20Sopenharmony_ci		const char *arch;
808c2ecf20Sopenharmony_ci		int ndk_length, app_length;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci		ndk = getenv("NDK_ROOT");
838c2ecf20Sopenharmony_ci		app = getenv("APP_PLATFORM");
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci		if (!(ndk && app))
868c2ecf20Sopenharmony_ci			return false;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci		ndk_length = strlen(ndk);
898c2ecf20Sopenharmony_ci		app_length = strlen(app);
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci		if (!(ndk_length && app_length && app_abi_length))
928c2ecf20Sopenharmony_ci			return false;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci		arch = !strncmp(app_abi, "arm", 3) ? "arm" :
958c2ecf20Sopenharmony_ci		       !strncmp(app_abi, "mips", 4) ? "mips" :
968c2ecf20Sopenharmony_ci		       !strncmp(app_abi, "x86", 3) ? "x86" : NULL;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci		if (!arch)
998c2ecf20Sopenharmony_ci			return false;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci		new_length = 27 + ndk_length +
1028c2ecf20Sopenharmony_ci			     app_length + lib_length
1038c2ecf20Sopenharmony_ci			   + strlen(arch);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci		if (new_length > PATH_MAX)
1068c2ecf20Sopenharmony_ci			return false;
1078c2ecf20Sopenharmony_ci		snprintf(newfilename, new_length,
1088c2ecf20Sopenharmony_ci			"%.*s/platforms/%.*s/arch-%s/usr/lib/%s",
1098c2ecf20Sopenharmony_ci			ndk_length, ndk, app_length, app, arch, libname);
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci		return true;
1128c2ecf20Sopenharmony_ci	}
1138c2ecf20Sopenharmony_ci	return false;
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_civoid map__init(struct map *map, u64 start, u64 end, u64 pgoff, struct dso *dso)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	map->start    = start;
1198c2ecf20Sopenharmony_ci	map->end      = end;
1208c2ecf20Sopenharmony_ci	map->pgoff    = pgoff;
1218c2ecf20Sopenharmony_ci	map->reloc    = 0;
1228c2ecf20Sopenharmony_ci	map->dso      = dso__get(dso);
1238c2ecf20Sopenharmony_ci	map->map_ip   = map__map_ip;
1248c2ecf20Sopenharmony_ci	map->unmap_ip = map__unmap_ip;
1258c2ecf20Sopenharmony_ci	RB_CLEAR_NODE(&map->rb_node);
1268c2ecf20Sopenharmony_ci	map->erange_warned = false;
1278c2ecf20Sopenharmony_ci	refcount_set(&map->refcnt, 1);
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cistruct map *map__new(struct machine *machine, u64 start, u64 len,
1318c2ecf20Sopenharmony_ci		     u64 pgoff, struct dso_id *id,
1328c2ecf20Sopenharmony_ci		     u32 prot, u32 flags, char *filename,
1338c2ecf20Sopenharmony_ci		     struct thread *thread)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	struct map *map = malloc(sizeof(*map));
1368c2ecf20Sopenharmony_ci	struct nsinfo *nsi = NULL;
1378c2ecf20Sopenharmony_ci	struct nsinfo *nnsi;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	if (map != NULL) {
1408c2ecf20Sopenharmony_ci		char newfilename[PATH_MAX];
1418c2ecf20Sopenharmony_ci		struct dso *dso;
1428c2ecf20Sopenharmony_ci		int anon, no_dso, vdso, android;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci		android = is_android_lib(filename);
1458c2ecf20Sopenharmony_ci		anon = is_anon_memory(filename) || flags & MAP_HUGETLB;
1468c2ecf20Sopenharmony_ci		vdso = is_vdso_map(filename);
1478c2ecf20Sopenharmony_ci		no_dso = is_no_dso_memory(filename);
1488c2ecf20Sopenharmony_ci		map->prot = prot;
1498c2ecf20Sopenharmony_ci		map->flags = flags;
1508c2ecf20Sopenharmony_ci		nsi = nsinfo__get(thread->nsinfo);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci		if ((anon || no_dso) && nsi && (prot & PROT_EXEC)) {
1538c2ecf20Sopenharmony_ci			snprintf(newfilename, sizeof(newfilename),
1548c2ecf20Sopenharmony_ci				 "/tmp/perf-%d.map", nsi->pid);
1558c2ecf20Sopenharmony_ci			filename = newfilename;
1568c2ecf20Sopenharmony_ci		}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci		if (android) {
1598c2ecf20Sopenharmony_ci			if (replace_android_lib(filename, newfilename))
1608c2ecf20Sopenharmony_ci				filename = newfilename;
1618c2ecf20Sopenharmony_ci		}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci		if (vdso) {
1648c2ecf20Sopenharmony_ci			/* The vdso maps are always on the host and not the
1658c2ecf20Sopenharmony_ci			 * container.  Ensure that we don't use setns to look
1668c2ecf20Sopenharmony_ci			 * them up.
1678c2ecf20Sopenharmony_ci			 */
1688c2ecf20Sopenharmony_ci			nnsi = nsinfo__copy(nsi);
1698c2ecf20Sopenharmony_ci			if (nnsi) {
1708c2ecf20Sopenharmony_ci				nsinfo__put(nsi);
1718c2ecf20Sopenharmony_ci				nnsi->need_setns = false;
1728c2ecf20Sopenharmony_ci				nsi = nnsi;
1738c2ecf20Sopenharmony_ci			}
1748c2ecf20Sopenharmony_ci			pgoff = 0;
1758c2ecf20Sopenharmony_ci			dso = machine__findnew_vdso(machine, thread);
1768c2ecf20Sopenharmony_ci		} else
1778c2ecf20Sopenharmony_ci			dso = machine__findnew_dso_id(machine, filename, id);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci		if (dso == NULL)
1808c2ecf20Sopenharmony_ci			goto out_delete;
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci		map__init(map, start, start + len, pgoff, dso);
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci		if (anon || no_dso) {
1858c2ecf20Sopenharmony_ci			map->map_ip = map->unmap_ip = identity__map_ip;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci			/*
1888c2ecf20Sopenharmony_ci			 * Set memory without DSO as loaded. All map__find_*
1898c2ecf20Sopenharmony_ci			 * functions still return NULL, and we avoid the
1908c2ecf20Sopenharmony_ci			 * unnecessary map__load warning.
1918c2ecf20Sopenharmony_ci			 */
1928c2ecf20Sopenharmony_ci			if (!(prot & PROT_EXEC))
1938c2ecf20Sopenharmony_ci				dso__set_loaded(dso);
1948c2ecf20Sopenharmony_ci		}
1958c2ecf20Sopenharmony_ci		dso->nsinfo = nsi;
1968c2ecf20Sopenharmony_ci		dso__put(dso);
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci	return map;
1998c2ecf20Sopenharmony_ciout_delete:
2008c2ecf20Sopenharmony_ci	nsinfo__put(nsi);
2018c2ecf20Sopenharmony_ci	free(map);
2028c2ecf20Sopenharmony_ci	return NULL;
2038c2ecf20Sopenharmony_ci}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci/*
2068c2ecf20Sopenharmony_ci * Constructor variant for modules (where we know from /proc/modules where
2078c2ecf20Sopenharmony_ci * they are loaded) and for vmlinux, where only after we load all the
2088c2ecf20Sopenharmony_ci * symbols we'll know where it starts and ends.
2098c2ecf20Sopenharmony_ci */
2108c2ecf20Sopenharmony_cistruct map *map__new2(u64 start, struct dso *dso)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	struct map *map = calloc(1, (sizeof(*map) +
2138c2ecf20Sopenharmony_ci				     (dso->kernel ? sizeof(struct kmap) : 0)));
2148c2ecf20Sopenharmony_ci	if (map != NULL) {
2158c2ecf20Sopenharmony_ci		/*
2168c2ecf20Sopenharmony_ci		 * ->end will be filled after we load all the symbols
2178c2ecf20Sopenharmony_ci		 */
2188c2ecf20Sopenharmony_ci		map__init(map, start, 0, 0, dso);
2198c2ecf20Sopenharmony_ci	}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	return map;
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cibool __map__is_kernel(const struct map *map)
2258c2ecf20Sopenharmony_ci{
2268c2ecf20Sopenharmony_ci	if (!map->dso->kernel)
2278c2ecf20Sopenharmony_ci		return false;
2288c2ecf20Sopenharmony_ci	return machine__kernel_map(map__kmaps((struct map *)map)->machine) == map;
2298c2ecf20Sopenharmony_ci}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cibool __map__is_extra_kernel_map(const struct map *map)
2328c2ecf20Sopenharmony_ci{
2338c2ecf20Sopenharmony_ci	struct kmap *kmap = __map__kmap((struct map *)map);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	return kmap && kmap->name[0];
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_cibool __map__is_bpf_prog(const struct map *map)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	const char *name;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	if (map->dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO)
2438c2ecf20Sopenharmony_ci		return true;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	/*
2468c2ecf20Sopenharmony_ci	 * If PERF_RECORD_BPF_EVENT is not included, the dso will not have
2478c2ecf20Sopenharmony_ci	 * type of DSO_BINARY_TYPE__BPF_PROG_INFO. In such cases, we can
2488c2ecf20Sopenharmony_ci	 * guess the type based on name.
2498c2ecf20Sopenharmony_ci	 */
2508c2ecf20Sopenharmony_ci	name = map->dso->short_name;
2518c2ecf20Sopenharmony_ci	return name && (strstr(name, "bpf_prog_") == name);
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cibool __map__is_bpf_image(const struct map *map)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	const char *name;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	if (map->dso->binary_type == DSO_BINARY_TYPE__BPF_IMAGE)
2598c2ecf20Sopenharmony_ci		return true;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	/*
2628c2ecf20Sopenharmony_ci	 * If PERF_RECORD_KSYMBOL is not included, the dso will not have
2638c2ecf20Sopenharmony_ci	 * type of DSO_BINARY_TYPE__BPF_IMAGE. In such cases, we can
2648c2ecf20Sopenharmony_ci	 * guess the type based on name.
2658c2ecf20Sopenharmony_ci	 */
2668c2ecf20Sopenharmony_ci	name = map->dso->short_name;
2678c2ecf20Sopenharmony_ci	return name && is_bpf_image(name);
2688c2ecf20Sopenharmony_ci}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_cibool __map__is_ool(const struct map *map)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	return map->dso && map->dso->binary_type == DSO_BINARY_TYPE__OOL;
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cibool map__has_symbols(const struct map *map)
2768c2ecf20Sopenharmony_ci{
2778c2ecf20Sopenharmony_ci	return dso__has_symbols(map->dso);
2788c2ecf20Sopenharmony_ci}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cistatic void map__exit(struct map *map)
2818c2ecf20Sopenharmony_ci{
2828c2ecf20Sopenharmony_ci	BUG_ON(refcount_read(&map->refcnt) != 0);
2838c2ecf20Sopenharmony_ci	dso__zput(map->dso);
2848c2ecf20Sopenharmony_ci}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_civoid map__delete(struct map *map)
2878c2ecf20Sopenharmony_ci{
2888c2ecf20Sopenharmony_ci	map__exit(map);
2898c2ecf20Sopenharmony_ci	free(map);
2908c2ecf20Sopenharmony_ci}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_civoid map__put(struct map *map)
2938c2ecf20Sopenharmony_ci{
2948c2ecf20Sopenharmony_ci	if (map && refcount_dec_and_test(&map->refcnt))
2958c2ecf20Sopenharmony_ci		map__delete(map);
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_civoid map__fixup_start(struct map *map)
2998c2ecf20Sopenharmony_ci{
3008c2ecf20Sopenharmony_ci	struct rb_root_cached *symbols = &map->dso->symbols;
3018c2ecf20Sopenharmony_ci	struct rb_node *nd = rb_first_cached(symbols);
3028c2ecf20Sopenharmony_ci	if (nd != NULL) {
3038c2ecf20Sopenharmony_ci		struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
3048c2ecf20Sopenharmony_ci		map->start = sym->start;
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_civoid map__fixup_end(struct map *map)
3098c2ecf20Sopenharmony_ci{
3108c2ecf20Sopenharmony_ci	struct rb_root_cached *symbols = &map->dso->symbols;
3118c2ecf20Sopenharmony_ci	struct rb_node *nd = rb_last(&symbols->rb_root);
3128c2ecf20Sopenharmony_ci	if (nd != NULL) {
3138c2ecf20Sopenharmony_ci		struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
3148c2ecf20Sopenharmony_ci		map->end = sym->end;
3158c2ecf20Sopenharmony_ci	}
3168c2ecf20Sopenharmony_ci}
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci#define DSO__DELETED "(deleted)"
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ciint map__load(struct map *map)
3218c2ecf20Sopenharmony_ci{
3228c2ecf20Sopenharmony_ci	const char *name = map->dso->long_name;
3238c2ecf20Sopenharmony_ci	int nr;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	if (dso__loaded(map->dso))
3268c2ecf20Sopenharmony_ci		return 0;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	nr = dso__load(map->dso, map);
3298c2ecf20Sopenharmony_ci	if (nr < 0) {
3308c2ecf20Sopenharmony_ci		if (map->dso->has_build_id) {
3318c2ecf20Sopenharmony_ci			char sbuild_id[SBUILD_ID_SIZE];
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci			build_id__sprintf(&map->dso->bid, sbuild_id);
3348c2ecf20Sopenharmony_ci			pr_debug("%s with build id %s not found", name, sbuild_id);
3358c2ecf20Sopenharmony_ci		} else
3368c2ecf20Sopenharmony_ci			pr_debug("Failed to open %s", name);
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci		pr_debug(", continuing without symbols\n");
3398c2ecf20Sopenharmony_ci		return -1;
3408c2ecf20Sopenharmony_ci	} else if (nr == 0) {
3418c2ecf20Sopenharmony_ci#ifdef HAVE_LIBELF_SUPPORT
3428c2ecf20Sopenharmony_ci		const size_t len = strlen(name);
3438c2ecf20Sopenharmony_ci		const size_t real_len = len - sizeof(DSO__DELETED);
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci		if (len > sizeof(DSO__DELETED) &&
3468c2ecf20Sopenharmony_ci		    strcmp(name + real_len + 1, DSO__DELETED) == 0) {
3478c2ecf20Sopenharmony_ci			pr_debug("%.*s was updated (is prelink enabled?). "
3488c2ecf20Sopenharmony_ci				"Restart the long running apps that use it!\n",
3498c2ecf20Sopenharmony_ci				   (int)real_len, name);
3508c2ecf20Sopenharmony_ci		} else {
3518c2ecf20Sopenharmony_ci			pr_debug("no symbols found in %s, maybe install a debug package?\n", name);
3528c2ecf20Sopenharmony_ci		}
3538c2ecf20Sopenharmony_ci#endif
3548c2ecf20Sopenharmony_ci		return -1;
3558c2ecf20Sopenharmony_ci	}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	return 0;
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_cistruct symbol *map__find_symbol(struct map *map, u64 addr)
3618c2ecf20Sopenharmony_ci{
3628c2ecf20Sopenharmony_ci	if (map__load(map) < 0)
3638c2ecf20Sopenharmony_ci		return NULL;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	return dso__find_symbol(map->dso, addr);
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_cistruct symbol *map__find_symbol_by_name(struct map *map, const char *name)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	if (map__load(map) < 0)
3718c2ecf20Sopenharmony_ci		return NULL;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	if (!dso__sorted_by_name(map->dso))
3748c2ecf20Sopenharmony_ci		dso__sort_by_name(map->dso);
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	return dso__find_symbol_by_name(map->dso, name);
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cistruct map *map__clone(struct map *from)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	size_t size = sizeof(struct map);
3828c2ecf20Sopenharmony_ci	struct map *map;
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	if (from->dso && from->dso->kernel)
3858c2ecf20Sopenharmony_ci		size += sizeof(struct kmap);
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	map = memdup(from, size);
3888c2ecf20Sopenharmony_ci	if (map != NULL) {
3898c2ecf20Sopenharmony_ci		refcount_set(&map->refcnt, 1);
3908c2ecf20Sopenharmony_ci		RB_CLEAR_NODE(&map->rb_node);
3918c2ecf20Sopenharmony_ci		dso__get(map->dso);
3928c2ecf20Sopenharmony_ci	}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	return map;
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_cisize_t map__fprintf(struct map *map, FILE *fp)
3988c2ecf20Sopenharmony_ci{
3998c2ecf20Sopenharmony_ci	return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n",
4008c2ecf20Sopenharmony_ci		       map->start, map->end, map->pgoff, map->dso->name);
4018c2ecf20Sopenharmony_ci}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_cisize_t map__fprintf_dsoname(struct map *map, FILE *fp)
4048c2ecf20Sopenharmony_ci{
4058c2ecf20Sopenharmony_ci	char buf[symbol_conf.pad_output_len_dso + 1];
4068c2ecf20Sopenharmony_ci	const char *dsoname = "[unknown]";
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	if (map && map->dso) {
4098c2ecf20Sopenharmony_ci		if (symbol_conf.show_kernel_path && map->dso->long_name)
4108c2ecf20Sopenharmony_ci			dsoname = map->dso->long_name;
4118c2ecf20Sopenharmony_ci		else
4128c2ecf20Sopenharmony_ci			dsoname = map->dso->name;
4138c2ecf20Sopenharmony_ci	}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	if (symbol_conf.pad_output_len_dso) {
4168c2ecf20Sopenharmony_ci		scnprintf_pad(buf, symbol_conf.pad_output_len_dso, "%s", dsoname);
4178c2ecf20Sopenharmony_ci		dsoname = buf;
4188c2ecf20Sopenharmony_ci	}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	return fprintf(fp, "%s", dsoname);
4218c2ecf20Sopenharmony_ci}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_cichar *map__srcline(struct map *map, u64 addr, struct symbol *sym)
4248c2ecf20Sopenharmony_ci{
4258c2ecf20Sopenharmony_ci	if (map == NULL)
4268c2ecf20Sopenharmony_ci		return SRCLINE_UNKNOWN;
4278c2ecf20Sopenharmony_ci	return get_srcline(map->dso, map__rip_2objdump(map, addr), sym, true, true, addr);
4288c2ecf20Sopenharmony_ci}
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ciint map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
4318c2ecf20Sopenharmony_ci			 FILE *fp)
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	int ret = 0;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	if (map && map->dso) {
4368c2ecf20Sopenharmony_ci		char *srcline = map__srcline(map, addr, NULL);
4378c2ecf20Sopenharmony_ci		if (strncmp(srcline, SRCLINE_UNKNOWN, strlen(SRCLINE_UNKNOWN)) != 0)
4388c2ecf20Sopenharmony_ci			ret = fprintf(fp, "%s%s", prefix, srcline);
4398c2ecf20Sopenharmony_ci		free_srcline(srcline);
4408c2ecf20Sopenharmony_ci	}
4418c2ecf20Sopenharmony_ci	return ret;
4428c2ecf20Sopenharmony_ci}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_civoid srccode_state_free(struct srccode_state *state)
4458c2ecf20Sopenharmony_ci{
4468c2ecf20Sopenharmony_ci	zfree(&state->srcfile);
4478c2ecf20Sopenharmony_ci	state->line = 0;
4488c2ecf20Sopenharmony_ci}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci/**
4518c2ecf20Sopenharmony_ci * map__rip_2objdump - convert symbol start address to objdump address.
4528c2ecf20Sopenharmony_ci * @map: memory map
4538c2ecf20Sopenharmony_ci * @rip: symbol start address
4548c2ecf20Sopenharmony_ci *
4558c2ecf20Sopenharmony_ci * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
4568c2ecf20Sopenharmony_ci * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is
4578c2ecf20Sopenharmony_ci * relative to section start.
4588c2ecf20Sopenharmony_ci *
4598c2ecf20Sopenharmony_ci * Return: Address suitable for passing to "objdump --start-address="
4608c2ecf20Sopenharmony_ci */
4618c2ecf20Sopenharmony_ciu64 map__rip_2objdump(struct map *map, u64 rip)
4628c2ecf20Sopenharmony_ci{
4638c2ecf20Sopenharmony_ci	struct kmap *kmap = __map__kmap(map);
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	/*
4668c2ecf20Sopenharmony_ci	 * vmlinux does not have program headers for PTI entry trampolines and
4678c2ecf20Sopenharmony_ci	 * kcore may not either. However the trampoline object code is on the
4688c2ecf20Sopenharmony_ci	 * main kernel map, so just use that instead.
4698c2ecf20Sopenharmony_ci	 */
4708c2ecf20Sopenharmony_ci	if (kmap && is_entry_trampoline(kmap->name) && kmap->kmaps && kmap->kmaps->machine) {
4718c2ecf20Sopenharmony_ci		struct map *kernel_map = machine__kernel_map(kmap->kmaps->machine);
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci		if (kernel_map)
4748c2ecf20Sopenharmony_ci			map = kernel_map;
4758c2ecf20Sopenharmony_ci	}
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	if (!map->dso->adjust_symbols)
4788c2ecf20Sopenharmony_ci		return rip;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	if (map->dso->rel)
4818c2ecf20Sopenharmony_ci		return rip - map->pgoff;
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	/*
4848c2ecf20Sopenharmony_ci	 * kernel modules also have DSO_TYPE_USER in dso->kernel,
4858c2ecf20Sopenharmony_ci	 * but all kernel modules are ET_REL, so won't get here.
4868c2ecf20Sopenharmony_ci	 */
4878c2ecf20Sopenharmony_ci	if (map->dso->kernel == DSO_SPACE__USER)
4888c2ecf20Sopenharmony_ci		return rip + map->dso->text_offset;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	return map->unmap_ip(map, rip) - map->reloc;
4918c2ecf20Sopenharmony_ci}
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci/**
4948c2ecf20Sopenharmony_ci * map__objdump_2mem - convert objdump address to a memory address.
4958c2ecf20Sopenharmony_ci * @map: memory map
4968c2ecf20Sopenharmony_ci * @ip: objdump address
4978c2ecf20Sopenharmony_ci *
4988c2ecf20Sopenharmony_ci * Closely related to map__rip_2objdump(), this function takes an address from
4998c2ecf20Sopenharmony_ci * objdump and converts it to a memory address.  Note this assumes that @map
5008c2ecf20Sopenharmony_ci * contains the address.  To be sure the result is valid, check it forwards
5018c2ecf20Sopenharmony_ci * e.g. map__rip_2objdump(map->map_ip(map, map__objdump_2mem(map, ip))) == ip
5028c2ecf20Sopenharmony_ci *
5038c2ecf20Sopenharmony_ci * Return: Memory address.
5048c2ecf20Sopenharmony_ci */
5058c2ecf20Sopenharmony_ciu64 map__objdump_2mem(struct map *map, u64 ip)
5068c2ecf20Sopenharmony_ci{
5078c2ecf20Sopenharmony_ci	if (!map->dso->adjust_symbols)
5088c2ecf20Sopenharmony_ci		return map->unmap_ip(map, ip);
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	if (map->dso->rel)
5118c2ecf20Sopenharmony_ci		return map->unmap_ip(map, ip + map->pgoff);
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	/*
5148c2ecf20Sopenharmony_ci	 * kernel modules also have DSO_TYPE_USER in dso->kernel,
5158c2ecf20Sopenharmony_ci	 * but all kernel modules are ET_REL, so won't get here.
5168c2ecf20Sopenharmony_ci	 */
5178c2ecf20Sopenharmony_ci	if (map->dso->kernel == DSO_SPACE__USER)
5188c2ecf20Sopenharmony_ci		return map->unmap_ip(map, ip - map->dso->text_offset);
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	return ip + map->reloc;
5218c2ecf20Sopenharmony_ci}
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_civoid maps__init(struct maps *maps, struct machine *machine)
5248c2ecf20Sopenharmony_ci{
5258c2ecf20Sopenharmony_ci	maps->entries = RB_ROOT;
5268c2ecf20Sopenharmony_ci	init_rwsem(&maps->lock);
5278c2ecf20Sopenharmony_ci	maps->machine = machine;
5288c2ecf20Sopenharmony_ci	maps->last_search_by_name = NULL;
5298c2ecf20Sopenharmony_ci	maps->nr_maps = 0;
5308c2ecf20Sopenharmony_ci	maps->maps_by_name = NULL;
5318c2ecf20Sopenharmony_ci	refcount_set(&maps->refcnt, 1);
5328c2ecf20Sopenharmony_ci}
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_cistatic void __maps__free_maps_by_name(struct maps *maps)
5358c2ecf20Sopenharmony_ci{
5368c2ecf20Sopenharmony_ci	/*
5378c2ecf20Sopenharmony_ci	 * Free everything to try to do it from the rbtree in the next search
5388c2ecf20Sopenharmony_ci	 */
5398c2ecf20Sopenharmony_ci	zfree(&maps->maps_by_name);
5408c2ecf20Sopenharmony_ci	maps->nr_maps_allocated = 0;
5418c2ecf20Sopenharmony_ci}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_civoid maps__insert(struct maps *maps, struct map *map)
5448c2ecf20Sopenharmony_ci{
5458c2ecf20Sopenharmony_ci	down_write(&maps->lock);
5468c2ecf20Sopenharmony_ci	__maps__insert(maps, map);
5478c2ecf20Sopenharmony_ci	++maps->nr_maps;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	if (map->dso && map->dso->kernel) {
5508c2ecf20Sopenharmony_ci		struct kmap *kmap = map__kmap(map);
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci		if (kmap)
5538c2ecf20Sopenharmony_ci			kmap->kmaps = maps;
5548c2ecf20Sopenharmony_ci		else
5558c2ecf20Sopenharmony_ci			pr_err("Internal error: kernel dso with non kernel map\n");
5568c2ecf20Sopenharmony_ci	}
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci	/*
5608c2ecf20Sopenharmony_ci	 * If we already performed some search by name, then we need to add the just
5618c2ecf20Sopenharmony_ci	 * inserted map and resort.
5628c2ecf20Sopenharmony_ci	 */
5638c2ecf20Sopenharmony_ci	if (maps->maps_by_name) {
5648c2ecf20Sopenharmony_ci		if (maps->nr_maps > maps->nr_maps_allocated) {
5658c2ecf20Sopenharmony_ci			int nr_allocate = maps->nr_maps * 2;
5668c2ecf20Sopenharmony_ci			struct map **maps_by_name = realloc(maps->maps_by_name, nr_allocate * sizeof(map));
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci			if (maps_by_name == NULL) {
5698c2ecf20Sopenharmony_ci				__maps__free_maps_by_name(maps);
5708c2ecf20Sopenharmony_ci				up_write(&maps->lock);
5718c2ecf20Sopenharmony_ci				return;
5728c2ecf20Sopenharmony_ci			}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci			maps->maps_by_name = maps_by_name;
5758c2ecf20Sopenharmony_ci			maps->nr_maps_allocated = nr_allocate;
5768c2ecf20Sopenharmony_ci		}
5778c2ecf20Sopenharmony_ci		maps->maps_by_name[maps->nr_maps - 1] = map;
5788c2ecf20Sopenharmony_ci		__maps__sort_by_name(maps);
5798c2ecf20Sopenharmony_ci	}
5808c2ecf20Sopenharmony_ci	up_write(&maps->lock);
5818c2ecf20Sopenharmony_ci}
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_cistatic void __maps__remove(struct maps *maps, struct map *map)
5848c2ecf20Sopenharmony_ci{
5858c2ecf20Sopenharmony_ci	rb_erase_init(&map->rb_node, &maps->entries);
5868c2ecf20Sopenharmony_ci	map__put(map);
5878c2ecf20Sopenharmony_ci}
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_civoid maps__remove(struct maps *maps, struct map *map)
5908c2ecf20Sopenharmony_ci{
5918c2ecf20Sopenharmony_ci	down_write(&maps->lock);
5928c2ecf20Sopenharmony_ci	if (maps->last_search_by_name == map)
5938c2ecf20Sopenharmony_ci		maps->last_search_by_name = NULL;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	__maps__remove(maps, map);
5968c2ecf20Sopenharmony_ci	--maps->nr_maps;
5978c2ecf20Sopenharmony_ci	if (maps->maps_by_name)
5988c2ecf20Sopenharmony_ci		__maps__free_maps_by_name(maps);
5998c2ecf20Sopenharmony_ci	up_write(&maps->lock);
6008c2ecf20Sopenharmony_ci}
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_cistatic void __maps__purge(struct maps *maps)
6038c2ecf20Sopenharmony_ci{
6048c2ecf20Sopenharmony_ci	struct map *pos, *next;
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	maps__for_each_entry_safe(maps, pos, next) {
6078c2ecf20Sopenharmony_ci		rb_erase_init(&pos->rb_node,  &maps->entries);
6088c2ecf20Sopenharmony_ci		map__put(pos);
6098c2ecf20Sopenharmony_ci	}
6108c2ecf20Sopenharmony_ci}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_civoid maps__exit(struct maps *maps)
6138c2ecf20Sopenharmony_ci{
6148c2ecf20Sopenharmony_ci	down_write(&maps->lock);
6158c2ecf20Sopenharmony_ci	__maps__purge(maps);
6168c2ecf20Sopenharmony_ci	up_write(&maps->lock);
6178c2ecf20Sopenharmony_ci}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_cibool maps__empty(struct maps *maps)
6208c2ecf20Sopenharmony_ci{
6218c2ecf20Sopenharmony_ci	return !maps__first(maps);
6228c2ecf20Sopenharmony_ci}
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_cistruct maps *maps__new(struct machine *machine)
6258c2ecf20Sopenharmony_ci{
6268c2ecf20Sopenharmony_ci	struct maps *maps = zalloc(sizeof(*maps));
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	if (maps != NULL)
6298c2ecf20Sopenharmony_ci		maps__init(maps, machine);
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	return maps;
6328c2ecf20Sopenharmony_ci}
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_civoid maps__delete(struct maps *maps)
6358c2ecf20Sopenharmony_ci{
6368c2ecf20Sopenharmony_ci	maps__exit(maps);
6378c2ecf20Sopenharmony_ci	unwind__finish_access(maps);
6388c2ecf20Sopenharmony_ci	free(maps);
6398c2ecf20Sopenharmony_ci}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_civoid maps__put(struct maps *maps)
6428c2ecf20Sopenharmony_ci{
6438c2ecf20Sopenharmony_ci	if (maps && refcount_dec_and_test(&maps->refcnt))
6448c2ecf20Sopenharmony_ci		maps__delete(maps);
6458c2ecf20Sopenharmony_ci}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_cistruct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp)
6488c2ecf20Sopenharmony_ci{
6498c2ecf20Sopenharmony_ci	struct map *map = maps__find(maps, addr);
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	/* Ensure map is loaded before using map->map_ip */
6528c2ecf20Sopenharmony_ci	if (map != NULL && map__load(map) >= 0) {
6538c2ecf20Sopenharmony_ci		if (mapp != NULL)
6548c2ecf20Sopenharmony_ci			*mapp = map;
6558c2ecf20Sopenharmony_ci		return map__find_symbol(map, map->map_ip(map, addr));
6568c2ecf20Sopenharmony_ci	}
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	return NULL;
6598c2ecf20Sopenharmony_ci}
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_cistatic bool map__contains_symbol(struct map *map, struct symbol *sym)
6628c2ecf20Sopenharmony_ci{
6638c2ecf20Sopenharmony_ci	u64 ip = map->unmap_ip(map, sym->start);
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	return ip >= map->start && ip < map->end;
6668c2ecf20Sopenharmony_ci}
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_cistruct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp)
6698c2ecf20Sopenharmony_ci{
6708c2ecf20Sopenharmony_ci	struct symbol *sym;
6718c2ecf20Sopenharmony_ci	struct map *pos;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	down_read(&maps->lock);
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	maps__for_each_entry(maps, pos) {
6768c2ecf20Sopenharmony_ci		sym = map__find_symbol_by_name(pos, name);
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci		if (sym == NULL)
6798c2ecf20Sopenharmony_ci			continue;
6808c2ecf20Sopenharmony_ci		if (!map__contains_symbol(pos, sym)) {
6818c2ecf20Sopenharmony_ci			sym = NULL;
6828c2ecf20Sopenharmony_ci			continue;
6838c2ecf20Sopenharmony_ci		}
6848c2ecf20Sopenharmony_ci		if (mapp != NULL)
6858c2ecf20Sopenharmony_ci			*mapp = pos;
6868c2ecf20Sopenharmony_ci		goto out;
6878c2ecf20Sopenharmony_ci	}
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	sym = NULL;
6908c2ecf20Sopenharmony_ciout:
6918c2ecf20Sopenharmony_ci	up_read(&maps->lock);
6928c2ecf20Sopenharmony_ci	return sym;
6938c2ecf20Sopenharmony_ci}
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ciint maps__find_ams(struct maps *maps, struct addr_map_symbol *ams)
6968c2ecf20Sopenharmony_ci{
6978c2ecf20Sopenharmony_ci	if (ams->addr < ams->ms.map->start || ams->addr >= ams->ms.map->end) {
6988c2ecf20Sopenharmony_ci		if (maps == NULL)
6998c2ecf20Sopenharmony_ci			return -1;
7008c2ecf20Sopenharmony_ci		ams->ms.map = maps__find(maps, ams->addr);
7018c2ecf20Sopenharmony_ci		if (ams->ms.map == NULL)
7028c2ecf20Sopenharmony_ci			return -1;
7038c2ecf20Sopenharmony_ci	}
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	ams->al_addr = ams->ms.map->map_ip(ams->ms.map, ams->addr);
7068c2ecf20Sopenharmony_ci	ams->ms.sym = map__find_symbol(ams->ms.map, ams->al_addr);
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	return ams->ms.sym ? 0 : -1;
7098c2ecf20Sopenharmony_ci}
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_cisize_t maps__fprintf(struct maps *maps, FILE *fp)
7128c2ecf20Sopenharmony_ci{
7138c2ecf20Sopenharmony_ci	size_t printed = 0;
7148c2ecf20Sopenharmony_ci	struct map *pos;
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	down_read(&maps->lock);
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	maps__for_each_entry(maps, pos) {
7198c2ecf20Sopenharmony_ci		printed += fprintf(fp, "Map:");
7208c2ecf20Sopenharmony_ci		printed += map__fprintf(pos, fp);
7218c2ecf20Sopenharmony_ci		if (verbose > 2) {
7228c2ecf20Sopenharmony_ci			printed += dso__fprintf(pos->dso, fp);
7238c2ecf20Sopenharmony_ci			printed += fprintf(fp, "--\n");
7248c2ecf20Sopenharmony_ci		}
7258c2ecf20Sopenharmony_ci	}
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	up_read(&maps->lock);
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	return printed;
7308c2ecf20Sopenharmony_ci}
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ciint maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
7338c2ecf20Sopenharmony_ci{
7348c2ecf20Sopenharmony_ci	struct rb_root *root;
7358c2ecf20Sopenharmony_ci	struct rb_node *next, *first;
7368c2ecf20Sopenharmony_ci	int err = 0;
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	down_write(&maps->lock);
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	root = &maps->entries;
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	/*
7438c2ecf20Sopenharmony_ci	 * Find first map where end > map->start.
7448c2ecf20Sopenharmony_ci	 * Same as find_vma() in kernel.
7458c2ecf20Sopenharmony_ci	 */
7468c2ecf20Sopenharmony_ci	next = root->rb_node;
7478c2ecf20Sopenharmony_ci	first = NULL;
7488c2ecf20Sopenharmony_ci	while (next) {
7498c2ecf20Sopenharmony_ci		struct map *pos = rb_entry(next, struct map, rb_node);
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci		if (pos->end > map->start) {
7528c2ecf20Sopenharmony_ci			first = next;
7538c2ecf20Sopenharmony_ci			if (pos->start <= map->start)
7548c2ecf20Sopenharmony_ci				break;
7558c2ecf20Sopenharmony_ci			next = next->rb_left;
7568c2ecf20Sopenharmony_ci		} else
7578c2ecf20Sopenharmony_ci			next = next->rb_right;
7588c2ecf20Sopenharmony_ci	}
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci	next = first;
7618c2ecf20Sopenharmony_ci	while (next) {
7628c2ecf20Sopenharmony_ci		struct map *pos = rb_entry(next, struct map, rb_node);
7638c2ecf20Sopenharmony_ci		next = rb_next(&pos->rb_node);
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci		/*
7668c2ecf20Sopenharmony_ci		 * Stop if current map starts after map->end.
7678c2ecf20Sopenharmony_ci		 * Maps are ordered by start: next will not overlap for sure.
7688c2ecf20Sopenharmony_ci		 */
7698c2ecf20Sopenharmony_ci		if (pos->start >= map->end)
7708c2ecf20Sopenharmony_ci			break;
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci		if (verbose >= 2) {
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci			if (use_browser) {
7758c2ecf20Sopenharmony_ci				pr_debug("overlapping maps in %s (disable tui for more info)\n",
7768c2ecf20Sopenharmony_ci					   map->dso->name);
7778c2ecf20Sopenharmony_ci			} else {
7788c2ecf20Sopenharmony_ci				fputs("overlapping maps:\n", fp);
7798c2ecf20Sopenharmony_ci				map__fprintf(map, fp);
7808c2ecf20Sopenharmony_ci				map__fprintf(pos, fp);
7818c2ecf20Sopenharmony_ci			}
7828c2ecf20Sopenharmony_ci		}
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci		rb_erase_init(&pos->rb_node, root);
7858c2ecf20Sopenharmony_ci		/*
7868c2ecf20Sopenharmony_ci		 * Now check if we need to create new maps for areas not
7878c2ecf20Sopenharmony_ci		 * overlapped by the new map:
7888c2ecf20Sopenharmony_ci		 */
7898c2ecf20Sopenharmony_ci		if (map->start > pos->start) {
7908c2ecf20Sopenharmony_ci			struct map *before = map__clone(pos);
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci			if (before == NULL) {
7938c2ecf20Sopenharmony_ci				err = -ENOMEM;
7948c2ecf20Sopenharmony_ci				goto put_map;
7958c2ecf20Sopenharmony_ci			}
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci			before->end = map->start;
7988c2ecf20Sopenharmony_ci			__maps__insert(maps, before);
7998c2ecf20Sopenharmony_ci			if (verbose >= 2 && !use_browser)
8008c2ecf20Sopenharmony_ci				map__fprintf(before, fp);
8018c2ecf20Sopenharmony_ci			map__put(before);
8028c2ecf20Sopenharmony_ci		}
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci		if (map->end < pos->end) {
8058c2ecf20Sopenharmony_ci			struct map *after = map__clone(pos);
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci			if (after == NULL) {
8088c2ecf20Sopenharmony_ci				err = -ENOMEM;
8098c2ecf20Sopenharmony_ci				goto put_map;
8108c2ecf20Sopenharmony_ci			}
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci			after->start = map->end;
8138c2ecf20Sopenharmony_ci			after->pgoff += map->end - pos->start;
8148c2ecf20Sopenharmony_ci			assert(pos->map_ip(pos, map->end) == after->map_ip(after, map->end));
8158c2ecf20Sopenharmony_ci			__maps__insert(maps, after);
8168c2ecf20Sopenharmony_ci			if (verbose >= 2 && !use_browser)
8178c2ecf20Sopenharmony_ci				map__fprintf(after, fp);
8188c2ecf20Sopenharmony_ci			map__put(after);
8198c2ecf20Sopenharmony_ci		}
8208c2ecf20Sopenharmony_ciput_map:
8218c2ecf20Sopenharmony_ci		map__put(pos);
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci		if (err)
8248c2ecf20Sopenharmony_ci			goto out;
8258c2ecf20Sopenharmony_ci	}
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci	err = 0;
8288c2ecf20Sopenharmony_ciout:
8298c2ecf20Sopenharmony_ci	up_write(&maps->lock);
8308c2ecf20Sopenharmony_ci	return err;
8318c2ecf20Sopenharmony_ci}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci/*
8348c2ecf20Sopenharmony_ci * XXX This should not really _copy_ te maps, but refcount them.
8358c2ecf20Sopenharmony_ci */
8368c2ecf20Sopenharmony_ciint maps__clone(struct thread *thread, struct maps *parent)
8378c2ecf20Sopenharmony_ci{
8388c2ecf20Sopenharmony_ci	struct maps *maps = thread->maps;
8398c2ecf20Sopenharmony_ci	int err;
8408c2ecf20Sopenharmony_ci	struct map *map;
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	down_read(&parent->lock);
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	maps__for_each_entry(parent, map) {
8458c2ecf20Sopenharmony_ci		struct map *new = map__clone(map);
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci		if (new == NULL) {
8488c2ecf20Sopenharmony_ci			err = -ENOMEM;
8498c2ecf20Sopenharmony_ci			goto out_unlock;
8508c2ecf20Sopenharmony_ci		}
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci		err = unwind__prepare_access(maps, new, NULL);
8538c2ecf20Sopenharmony_ci		if (err)
8548c2ecf20Sopenharmony_ci			goto out_unlock;
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci		maps__insert(maps, new);
8578c2ecf20Sopenharmony_ci		map__put(new);
8588c2ecf20Sopenharmony_ci	}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	err = 0;
8618c2ecf20Sopenharmony_ciout_unlock:
8628c2ecf20Sopenharmony_ci	up_read(&parent->lock);
8638c2ecf20Sopenharmony_ci	return err;
8648c2ecf20Sopenharmony_ci}
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_cistatic void __maps__insert(struct maps *maps, struct map *map)
8678c2ecf20Sopenharmony_ci{
8688c2ecf20Sopenharmony_ci	struct rb_node **p = &maps->entries.rb_node;
8698c2ecf20Sopenharmony_ci	struct rb_node *parent = NULL;
8708c2ecf20Sopenharmony_ci	const u64 ip = map->start;
8718c2ecf20Sopenharmony_ci	struct map *m;
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	while (*p != NULL) {
8748c2ecf20Sopenharmony_ci		parent = *p;
8758c2ecf20Sopenharmony_ci		m = rb_entry(parent, struct map, rb_node);
8768c2ecf20Sopenharmony_ci		if (ip < m->start)
8778c2ecf20Sopenharmony_ci			p = &(*p)->rb_left;
8788c2ecf20Sopenharmony_ci		else
8798c2ecf20Sopenharmony_ci			p = &(*p)->rb_right;
8808c2ecf20Sopenharmony_ci	}
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	rb_link_node(&map->rb_node, parent, p);
8838c2ecf20Sopenharmony_ci	rb_insert_color(&map->rb_node, &maps->entries);
8848c2ecf20Sopenharmony_ci	map__get(map);
8858c2ecf20Sopenharmony_ci}
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_cistruct map *maps__find(struct maps *maps, u64 ip)
8888c2ecf20Sopenharmony_ci{
8898c2ecf20Sopenharmony_ci	struct rb_node *p;
8908c2ecf20Sopenharmony_ci	struct map *m;
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	down_read(&maps->lock);
8938c2ecf20Sopenharmony_ci
8948c2ecf20Sopenharmony_ci	p = maps->entries.rb_node;
8958c2ecf20Sopenharmony_ci	while (p != NULL) {
8968c2ecf20Sopenharmony_ci		m = rb_entry(p, struct map, rb_node);
8978c2ecf20Sopenharmony_ci		if (ip < m->start)
8988c2ecf20Sopenharmony_ci			p = p->rb_left;
8998c2ecf20Sopenharmony_ci		else if (ip >= m->end)
9008c2ecf20Sopenharmony_ci			p = p->rb_right;
9018c2ecf20Sopenharmony_ci		else
9028c2ecf20Sopenharmony_ci			goto out;
9038c2ecf20Sopenharmony_ci	}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	m = NULL;
9068c2ecf20Sopenharmony_ciout:
9078c2ecf20Sopenharmony_ci	up_read(&maps->lock);
9088c2ecf20Sopenharmony_ci	return m;
9098c2ecf20Sopenharmony_ci}
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_cistruct map *maps__first(struct maps *maps)
9128c2ecf20Sopenharmony_ci{
9138c2ecf20Sopenharmony_ci	struct rb_node *first = rb_first(&maps->entries);
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	if (first)
9168c2ecf20Sopenharmony_ci		return rb_entry(first, struct map, rb_node);
9178c2ecf20Sopenharmony_ci	return NULL;
9188c2ecf20Sopenharmony_ci}
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_cistatic struct map *__map__next(struct map *map)
9218c2ecf20Sopenharmony_ci{
9228c2ecf20Sopenharmony_ci	struct rb_node *next = rb_next(&map->rb_node);
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	if (next)
9258c2ecf20Sopenharmony_ci		return rb_entry(next, struct map, rb_node);
9268c2ecf20Sopenharmony_ci	return NULL;
9278c2ecf20Sopenharmony_ci}
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_cistruct map *map__next(struct map *map)
9308c2ecf20Sopenharmony_ci{
9318c2ecf20Sopenharmony_ci	return map ? __map__next(map) : NULL;
9328c2ecf20Sopenharmony_ci}
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_cistruct kmap *__map__kmap(struct map *map)
9358c2ecf20Sopenharmony_ci{
9368c2ecf20Sopenharmony_ci	if (!map->dso || !map->dso->kernel)
9378c2ecf20Sopenharmony_ci		return NULL;
9388c2ecf20Sopenharmony_ci	return (struct kmap *)(map + 1);
9398c2ecf20Sopenharmony_ci}
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_cistruct kmap *map__kmap(struct map *map)
9428c2ecf20Sopenharmony_ci{
9438c2ecf20Sopenharmony_ci	struct kmap *kmap = __map__kmap(map);
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	if (!kmap)
9468c2ecf20Sopenharmony_ci		pr_err("Internal error: map__kmap with a non-kernel map\n");
9478c2ecf20Sopenharmony_ci	return kmap;
9488c2ecf20Sopenharmony_ci}
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_cistruct maps *map__kmaps(struct map *map)
9518c2ecf20Sopenharmony_ci{
9528c2ecf20Sopenharmony_ci	struct kmap *kmap = map__kmap(map);
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ci	if (!kmap || !kmap->kmaps) {
9558c2ecf20Sopenharmony_ci		pr_err("Internal error: map__kmaps with a non-kernel map\n");
9568c2ecf20Sopenharmony_ci		return NULL;
9578c2ecf20Sopenharmony_ci	}
9588c2ecf20Sopenharmony_ci	return kmap->kmaps;
9598c2ecf20Sopenharmony_ci}
960