lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 11 Feb 2022 14:27:16 -0300
From:   Arnaldo Carvalho de Melo <acme@...nel.org>
To:     Ian Rogers <irogers@...gle.com>
Cc:     Peter Zijlstra <peterz@...radead.org>,
        Ingo Molnar <mingo@...hat.com>,
        Mark Rutland <mark.rutland@....com>,
        Alexander Shishkin <alexander.shishkin@...ux.intel.com>,
        Jiri Olsa <jolsa@...nel.org>,
        Namhyung Kim <namhyung@...nel.org>,
        Thomas Gleixner <tglx@...utronix.de>,
        Darren Hart <dvhart@...radead.org>,
        Davidlohr Bueso <dave@...olabs.net>,
        André Almeida <andrealmeid@...labora.com>,
        James Clark <james.clark@....com>,
        John Garry <john.garry@...wei.com>,
        Riccardo Mancini <rickyman7@...il.com>,
        Yury Norov <yury.norov@...il.com>,
        Andy Shevchenko <andriy.shevchenko@...ux.intel.com>,
        Andrew Morton <akpm@...ux-foundation.org>,
        Jin Yao <yao.jin@...ux.intel.com>,
        Adrian Hunter <adrian.hunter@...el.com>,
        Leo Yan <leo.yan@...aro.org>, Andi Kleen <ak@...ux.intel.com>,
        Thomas Richter <tmricht@...ux.ibm.com>,
        Kan Liang <kan.liang@...ux.intel.com>,
        Madhavan Srinivasan <maddy@...ux.ibm.com>,
        Shunsuke Nakamura <nakamura.shun@...itsu.com>,
        Song Liu <song@...nel.org>,
        Masami Hiramatsu <mhiramat@...nel.org>,
        Steven Rostedt <rostedt@...dmis.org>,
        Miaoqian Lin <linmq006@...il.com>,
        Stephen Brennan <stephen.s.brennan@...cle.com>,
        Kajol Jain <kjain@...ux.ibm.com>,
        Alexey Bayduraev <alexey.v.bayduraev@...ux.intel.com>,
        German Gomez <german.gomez@....com>,
        linux-perf-users@...r.kernel.org, linux-kernel@...r.kernel.org,
        Eric Dumazet <edumazet@...gle.com>,
        Dmitry Vyukov <dvyukov@...gle.com>,
        Hao Luo <haoluo@...gle.com>, eranian@...gle.com
Subject: Re: [PATCH v3 08/22] perf maps: Move maps code to own C file

Em Fri, Feb 11, 2022 at 02:34:01AM -0800, Ian Rogers escreveu:
> The maps code has its own header, move the corresponding C function
> definitions to their own C file. In the process tidy and minimize
> includes.

Depends on previously not processed patches.
 
> Signed-off-by: Ian Rogers <irogers@...gle.com>
> ---
>  tools/perf/util/Build  |   1 +
>  tools/perf/util/map.c  | 417 +----------------------------------------
>  tools/perf/util/map.h  |   2 +
>  tools/perf/util/maps.c | 403 +++++++++++++++++++++++++++++++++++++++
>  4 files changed, 414 insertions(+), 409 deletions(-)
>  create mode 100644 tools/perf/util/maps.c
> 
> diff --git a/tools/perf/util/Build b/tools/perf/util/Build
> index 2a403cefcaf2..9a7209a99e16 100644
> --- a/tools/perf/util/Build
> +++ b/tools/perf/util/Build
> @@ -56,6 +56,7 @@ perf-y += debug.o
>  perf-y += fncache.o
>  perf-y += machine.o
>  perf-y += map.o
> +perf-y += maps.o
>  perf-y += pstack.o
>  perf-y += session.o
>  perf-y += sample-raw.o
> diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
> index 4d1de363c19a..2cfe5744b86c 100644
> --- a/tools/perf/util/map.c
> +++ b/tools/perf/util/map.c
> @@ -1,31 +1,20 @@
>  // SPDX-License-Identifier: GPL-2.0
> -#include "symbol.h"
> -#include <assert.h>
> -#include <errno.h>
>  #include <inttypes.h>
>  #include <limits.h>
> +#include <stdio.h>
>  #include <stdlib.h>
>  #include <string.h>
> -#include <stdio.h>
> -#include <unistd.h>
> +#include <linux/string.h>
> +#include <linux/zalloc.h>
>  #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
> +#include "debug.h"
>  #include "dso.h"
>  #include "map.h"
> -#include "map_symbol.h"
> +#include "namespaces.h"
> +#include "srcline.h"
> +#include "symbol.h"
>  #include "thread.h"
>  #include "vdso.h"
> -#include "build-id.h"
> -#include "debug.h"
> -#include "machine.h"
> -#include <linux/string.h>
> -#include <linux/zalloc.h>
> -#include "srcline.h"
> -#include "namespaces.h"
> -#include "unwind.h"
> -#include "srccode.h"
> -#include "ui/ui.h"
> -
> -static void __maps__insert(struct maps *maps, struct map *map);
>  
>  static inline int is_android_lib(const char *filename)
>  {
> @@ -527,403 +516,13 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
>  	return ip + map->reloc;
>  }
>  
> -static void maps__init(struct maps *maps, struct machine *machine)
> -{
> -	maps->entries = RB_ROOT;
> -	init_rwsem(&maps->lock);
> -	maps->machine = machine;
> -	maps->last_search_by_name = NULL;
> -	maps->nr_maps = 0;
> -	maps->maps_by_name = NULL;
> -	refcount_set(&maps->refcnt, 1);
> -}
> -
> -static void __maps__free_maps_by_name(struct maps *maps)
> -{
> -	/*
> -	 * Free everything to try to do it from the rbtree in the next search
> -	 */
> -	zfree(&maps->maps_by_name);
> -	maps->nr_maps_allocated = 0;
> -}
> -
> -void maps__insert(struct maps *maps, struct map *map)
> -{
> -	down_write(&maps->lock);
> -	__maps__insert(maps, map);
> -	++maps->nr_maps;
> -
> -	if (map->dso && map->dso->kernel) {
> -		struct kmap *kmap = map__kmap(map);
> -
> -		if (kmap)
> -			kmap->kmaps = maps;
> -		else
> -			pr_err("Internal error: kernel dso with non kernel map\n");
> -	}
> -
> -
> -	/*
> -	 * If we already performed some search by name, then we need to add the just
> -	 * inserted map and resort.
> -	 */
> -	if (maps->maps_by_name) {
> -		if (maps->nr_maps > maps->nr_maps_allocated) {
> -			int nr_allocate = maps->nr_maps * 2;
> -			struct map **maps_by_name = realloc(maps->maps_by_name, nr_allocate * sizeof(map));
> -
> -			if (maps_by_name == NULL) {
> -				__maps__free_maps_by_name(maps);
> -				up_write(&maps->lock);
> -				return;
> -			}
> -
> -			maps->maps_by_name = maps_by_name;
> -			maps->nr_maps_allocated = nr_allocate;
> -		}
> -		maps->maps_by_name[maps->nr_maps - 1] = map;
> -		__maps__sort_by_name(maps);
> -	}
> -	up_write(&maps->lock);
> -}
> -
> -static void __maps__remove(struct maps *maps, struct map *map)
> -{
> -	rb_erase_init(&map->rb_node, &maps->entries);
> -	map__put(map);
> -}
> -
> -void maps__remove(struct maps *maps, struct map *map)
> -{
> -	down_write(&maps->lock);
> -	if (maps->last_search_by_name == map)
> -		maps->last_search_by_name = NULL;
> -
> -	__maps__remove(maps, map);
> -	--maps->nr_maps;
> -	if (maps->maps_by_name)
> -		__maps__free_maps_by_name(maps);
> -	up_write(&maps->lock);
> -}
> -
> -static void __maps__purge(struct maps *maps)
> -{
> -	struct map *pos, *next;
> -
> -	maps__for_each_entry_safe(maps, pos, next) {
> -		rb_erase_init(&pos->rb_node,  &maps->entries);
> -		map__put(pos);
> -	}
> -}
> -
> -static void maps__exit(struct maps *maps)
> -{
> -	down_write(&maps->lock);
> -	__maps__purge(maps);
> -	up_write(&maps->lock);
> -}
> -
> -bool maps__empty(struct maps *maps)
> -{
> -	return !maps__first(maps);
> -}
> -
> -struct maps *maps__new(struct machine *machine)
> -{
> -	struct maps *maps = zalloc(sizeof(*maps));
> -
> -	if (maps != NULL)
> -		maps__init(maps, machine);
> -
> -	return maps;
> -}
> -
> -void maps__delete(struct maps *maps)
> -{
> -	maps__exit(maps);
> -	unwind__finish_access(maps);
> -	free(maps);
> -}
> -
> -void maps__put(struct maps *maps)
> -{
> -	if (maps && refcount_dec_and_test(&maps->refcnt))
> -		maps__delete(maps);
> -}
> -
> -struct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp)
> -{
> -	struct map *map = maps__find(maps, addr);
> -
> -	/* Ensure map is loaded before using map->map_ip */
> -	if (map != NULL && map__load(map) >= 0) {
> -		if (mapp != NULL)
> -			*mapp = map;
> -		return map__find_symbol(map, map->map_ip(map, addr));
> -	}
> -
> -	return NULL;
> -}
> -
> -static bool map__contains_symbol(struct map *map, struct symbol *sym)
> +bool map__contains_symbol(struct map *map, struct symbol *sym)
>  {
>  	u64 ip = map->unmap_ip(map, sym->start);
>  
>  	return ip >= map->start && ip < map->end;
>  }
>  
> -struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp)
> -{
> -	struct symbol *sym;
> -	struct map *pos;
> -
> -	down_read(&maps->lock);
> -
> -	maps__for_each_entry(maps, pos) {
> -		sym = map__find_symbol_by_name(pos, name);
> -
> -		if (sym == NULL)
> -			continue;
> -		if (!map__contains_symbol(pos, sym)) {
> -			sym = NULL;
> -			continue;
> -		}
> -		if (mapp != NULL)
> -			*mapp = pos;
> -		goto out;
> -	}
> -
> -	sym = NULL;
> -out:
> -	up_read(&maps->lock);
> -	return sym;
> -}
> -
> -int maps__find_ams(struct maps *maps, struct addr_map_symbol *ams)
> -{
> -	if (ams->addr < ams->ms.map->start || ams->addr >= ams->ms.map->end) {
> -		if (maps == NULL)
> -			return -1;
> -		ams->ms.map = maps__find(maps, ams->addr);
> -		if (ams->ms.map == NULL)
> -			return -1;
> -	}
> -
> -	ams->al_addr = ams->ms.map->map_ip(ams->ms.map, ams->addr);
> -	ams->ms.sym = map__find_symbol(ams->ms.map, ams->al_addr);
> -
> -	return ams->ms.sym ? 0 : -1;
> -}
> -
> -size_t maps__fprintf(struct maps *maps, FILE *fp)
> -{
> -	size_t printed = 0;
> -	struct map *pos;
> -
> -	down_read(&maps->lock);
> -
> -	maps__for_each_entry(maps, pos) {
> -		printed += fprintf(fp, "Map:");
> -		printed += map__fprintf(pos, fp);
> -		if (verbose > 2) {
> -			printed += dso__fprintf(pos->dso, fp);
> -			printed += fprintf(fp, "--\n");
> -		}
> -	}
> -
> -	up_read(&maps->lock);
> -
> -	return printed;
> -}
> -
> -int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
> -{
> -	struct rb_root *root;
> -	struct rb_node *next, *first;
> -	int err = 0;
> -
> -	down_write(&maps->lock);
> -
> -	root = &maps->entries;
> -
> -	/*
> -	 * Find first map where end > map->start.
> -	 * Same as find_vma() in kernel.
> -	 */
> -	next = root->rb_node;
> -	first = NULL;
> -	while (next) {
> -		struct map *pos = rb_entry(next, struct map, rb_node);
> -
> -		if (pos->end > map->start) {
> -			first = next;
> -			if (pos->start <= map->start)
> -				break;
> -			next = next->rb_left;
> -		} else
> -			next = next->rb_right;
> -	}
> -
> -	next = first;
> -	while (next) {
> -		struct map *pos = rb_entry(next, struct map, rb_node);
> -		next = rb_next(&pos->rb_node);
> -
> -		/*
> -		 * Stop if current map starts after map->end.
> -		 * Maps are ordered by start: next will not overlap for sure.
> -		 */
> -		if (pos->start >= map->end)
> -			break;
> -
> -		if (verbose >= 2) {
> -
> -			if (use_browser) {
> -				pr_debug("overlapping maps in %s (disable tui for more info)\n",
> -					   map->dso->name);
> -			} else {
> -				fputs("overlapping maps:\n", fp);
> -				map__fprintf(map, fp);
> -				map__fprintf(pos, fp);
> -			}
> -		}
> -
> -		rb_erase_init(&pos->rb_node, root);
> -		/*
> -		 * Now check if we need to create new maps for areas not
> -		 * overlapped by the new map:
> -		 */
> -		if (map->start > pos->start) {
> -			struct map *before = map__clone(pos);
> -
> -			if (before == NULL) {
> -				err = -ENOMEM;
> -				goto put_map;
> -			}
> -
> -			before->end = map->start;
> -			__maps__insert(maps, before);
> -			if (verbose >= 2 && !use_browser)
> -				map__fprintf(before, fp);
> -			map__put(before);
> -		}
> -
> -		if (map->end < pos->end) {
> -			struct map *after = map__clone(pos);
> -
> -			if (after == NULL) {
> -				err = -ENOMEM;
> -				goto put_map;
> -			}
> -
> -			after->start = map->end;
> -			after->pgoff += map->end - pos->start;
> -			assert(pos->map_ip(pos, map->end) == after->map_ip(after, map->end));
> -			__maps__insert(maps, after);
> -			if (verbose >= 2 && !use_browser)
> -				map__fprintf(after, fp);
> -			map__put(after);
> -		}
> -put_map:
> -		map__put(pos);
> -
> -		if (err)
> -			goto out;
> -	}
> -
> -	err = 0;
> -out:
> -	up_write(&maps->lock);
> -	return err;
> -}
> -
> -/*
> - * XXX This should not really _copy_ te maps, but refcount them.
> - */
> -int maps__clone(struct thread *thread, struct maps *parent)
> -{
> -	struct maps *maps = thread->maps;
> -	int err;
> -	struct map *map;
> -
> -	down_read(&parent->lock);
> -
> -	maps__for_each_entry(parent, map) {
> -		struct map *new = map__clone(map);
> -
> -		if (new == NULL) {
> -			err = -ENOMEM;
> -			goto out_unlock;
> -		}
> -
> -		err = unwind__prepare_access(maps, new, NULL);
> -		if (err)
> -			goto out_unlock;
> -
> -		maps__insert(maps, new);
> -		map__put(new);
> -	}
> -
> -	err = 0;
> -out_unlock:
> -	up_read(&parent->lock);
> -	return err;
> -}
> -
> -static void __maps__insert(struct maps *maps, struct map *map)
> -{
> -	struct rb_node **p = &maps->entries.rb_node;
> -	struct rb_node *parent = NULL;
> -	const u64 ip = map->start;
> -	struct map *m;
> -
> -	while (*p != NULL) {
> -		parent = *p;
> -		m = rb_entry(parent, struct map, rb_node);
> -		if (ip < m->start)
> -			p = &(*p)->rb_left;
> -		else
> -			p = &(*p)->rb_right;
> -	}
> -
> -	rb_link_node(&map->rb_node, parent, p);
> -	rb_insert_color(&map->rb_node, &maps->entries);
> -	map__get(map);
> -}
> -
> -struct map *maps__find(struct maps *maps, u64 ip)
> -{
> -	struct rb_node *p;
> -	struct map *m;
> -
> -	down_read(&maps->lock);
> -
> -	p = maps->entries.rb_node;
> -	while (p != NULL) {
> -		m = rb_entry(p, struct map, rb_node);
> -		if (ip < m->start)
> -			p = p->rb_left;
> -		else if (ip >= m->end)
> -			p = p->rb_right;
> -		else
> -			goto out;
> -	}
> -
> -	m = NULL;
> -out:
> -	up_read(&maps->lock);
> -	return m;
> -}
> -
> -struct map *maps__first(struct maps *maps)
> -{
> -	struct rb_node *first = rb_first(&maps->entries);
> -
> -	if (first)
> -		return rb_entry(first, struct map, rb_node);
> -	return NULL;
> -}
> -
>  static struct map *__map__next(struct map *map)
>  {
>  	struct rb_node *next = rb_next(&map->rb_node);
> diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
> index d32f5b28c1fb..973dce27b253 100644
> --- a/tools/perf/util/map.h
> +++ b/tools/perf/util/map.h
> @@ -160,6 +160,8 @@ static inline bool __map__is_kmodule(const struct map *map)
>  
>  bool map__has_symbols(const struct map *map);
>  
> +bool map__contains_symbol(struct map *map, struct symbol *sym);
> +
>  #define ENTRY_TRAMPOLINE_NAME "__entry_SYSCALL_64_trampoline"
>  
>  static inline bool is_entry_trampoline(const char *name)
> diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c
> new file mode 100644
> index 000000000000..ededabf0a230
> --- /dev/null
> +++ b/tools/perf/util/maps.c
> @@ -0,0 +1,403 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <errno.h>
> +#include <stdlib.h>
> +#include <linux/zalloc.h>
> +#include "debug.h"
> +#include "dso.h"
> +#include "map.h"
> +#include "maps.h"
> +#include "thread.h"
> +#include "ui/ui.h"
> +#include "unwind.h"
> +
> +static void __maps__insert(struct maps *maps, struct map *map);
> +
> +void maps__init(struct maps *maps, struct machine *machine)
> +{
> +	maps->entries = RB_ROOT;
> +	init_rwsem(&maps->lock);
> +	maps->machine = machine;
> +	maps->last_search_by_name = NULL;
> +	maps->nr_maps = 0;
> +	maps->maps_by_name = NULL;
> +	refcount_set(&maps->refcnt, 1);
> +}
> +
> +static void __maps__free_maps_by_name(struct maps *maps)
> +{
> +	/*
> +	 * Free everything to try to do it from the rbtree in the next search
> +	 */
> +	zfree(&maps->maps_by_name);
> +	maps->nr_maps_allocated = 0;
> +}
> +
> +void maps__insert(struct maps *maps, struct map *map)
> +{
> +	down_write(&maps->lock);
> +	__maps__insert(maps, map);
> +	++maps->nr_maps;
> +
> +	if (map->dso && map->dso->kernel) {
> +		struct kmap *kmap = map__kmap(map);
> +
> +		if (kmap)
> +			kmap->kmaps = maps;
> +		else
> +			pr_err("Internal error: kernel dso with non kernel map\n");
> +	}
> +
> +
> +	/*
> +	 * If we already performed some search by name, then we need to add the just
> +	 * inserted map and resort.
> +	 */
> +	if (maps->maps_by_name) {
> +		if (maps->nr_maps > maps->nr_maps_allocated) {
> +			int nr_allocate = maps->nr_maps * 2;
> +			struct map **maps_by_name = realloc(maps->maps_by_name, nr_allocate * sizeof(map));
> +
> +			if (maps_by_name == NULL) {
> +				__maps__free_maps_by_name(maps);
> +				up_write(&maps->lock);
> +				return;
> +			}
> +
> +			maps->maps_by_name = maps_by_name;
> +			maps->nr_maps_allocated = nr_allocate;
> +		}
> +		maps->maps_by_name[maps->nr_maps - 1] = map;
> +		__maps__sort_by_name(maps);
> +	}
> +	up_write(&maps->lock);
> +}
> +
> +static void __maps__remove(struct maps *maps, struct map *map)
> +{
> +	rb_erase_init(&map->rb_node, &maps->entries);
> +	map__put(map);
> +}
> +
> +void maps__remove(struct maps *maps, struct map *map)
> +{
> +	down_write(&maps->lock);
> +	if (maps->last_search_by_name == map)
> +		maps->last_search_by_name = NULL;
> +
> +	__maps__remove(maps, map);
> +	--maps->nr_maps;
> +	if (maps->maps_by_name)
> +		__maps__free_maps_by_name(maps);
> +	up_write(&maps->lock);
> +}
> +
> +static void __maps__purge(struct maps *maps)
> +{
> +	struct map *pos, *next;
> +
> +	maps__for_each_entry_safe(maps, pos, next) {
> +		rb_erase_init(&pos->rb_node,  &maps->entries);
> +		map__put(pos);
> +	}
> +}
> +
> +void maps__exit(struct maps *maps)
> +{
> +	down_write(&maps->lock);
> +	__maps__purge(maps);
> +	up_write(&maps->lock);
> +}
> +
> +bool maps__empty(struct maps *maps)
> +{
> +	return !maps__first(maps);
> +}
> +
> +struct maps *maps__new(struct machine *machine)
> +{
> +	struct maps *maps = zalloc(sizeof(*maps));
> +
> +	if (maps != NULL)
> +		maps__init(maps, machine);
> +
> +	return maps;
> +}
> +
> +void maps__delete(struct maps *maps)
> +{
> +	maps__exit(maps);
> +	unwind__finish_access(maps);
> +	free(maps);
> +}
> +
> +void maps__put(struct maps *maps)
> +{
> +	if (maps && refcount_dec_and_test(&maps->refcnt))
> +		maps__delete(maps);
> +}
> +
> +struct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp)
> +{
> +	struct map *map = maps__find(maps, addr);
> +
> +	/* Ensure map is loaded before using map->map_ip */
> +	if (map != NULL && map__load(map) >= 0) {
> +		if (mapp != NULL)
> +			*mapp = map;
> +		return map__find_symbol(map, map->map_ip(map, addr));
> +	}
> +
> +	return NULL;
> +}
> +
> +struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp)
> +{
> +	struct symbol *sym;
> +	struct map *pos;
> +
> +	down_read(&maps->lock);
> +
> +	maps__for_each_entry(maps, pos) {
> +		sym = map__find_symbol_by_name(pos, name);
> +
> +		if (sym == NULL)
> +			continue;
> +		if (!map__contains_symbol(pos, sym)) {
> +			sym = NULL;
> +			continue;
> +		}
> +		if (mapp != NULL)
> +			*mapp = pos;
> +		goto out;
> +	}
> +
> +	sym = NULL;
> +out:
> +	up_read(&maps->lock);
> +	return sym;
> +}
> +
> +int maps__find_ams(struct maps *maps, struct addr_map_symbol *ams)
> +{
> +	if (ams->addr < ams->ms.map->start || ams->addr >= ams->ms.map->end) {
> +		if (maps == NULL)
> +			return -1;
> +		ams->ms.map = maps__find(maps, ams->addr);
> +		if (ams->ms.map == NULL)
> +			return -1;
> +	}
> +
> +	ams->al_addr = ams->ms.map->map_ip(ams->ms.map, ams->addr);
> +	ams->ms.sym = map__find_symbol(ams->ms.map, ams->al_addr);
> +
> +	return ams->ms.sym ? 0 : -1;
> +}
> +
> +size_t maps__fprintf(struct maps *maps, FILE *fp)
> +{
> +	size_t printed = 0;
> +	struct map *pos;
> +
> +	down_read(&maps->lock);
> +
> +	maps__for_each_entry(maps, pos) {
> +		printed += fprintf(fp, "Map:");
> +		printed += map__fprintf(pos, fp);
> +		if (verbose > 2) {
> +			printed += dso__fprintf(pos->dso, fp);
> +			printed += fprintf(fp, "--\n");
> +		}
> +	}
> +
> +	up_read(&maps->lock);
> +
> +	return printed;
> +}
> +
> +int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
> +{
> +	struct rb_root *root;
> +	struct rb_node *next, *first;
> +	int err = 0;
> +
> +	down_write(&maps->lock);
> +
> +	root = &maps->entries;
> +
> +	/*
> +	 * Find first map where end > map->start.
> +	 * Same as find_vma() in kernel.
> +	 */
> +	next = root->rb_node;
> +	first = NULL;
> +	while (next) {
> +		struct map *pos = rb_entry(next, struct map, rb_node);
> +
> +		if (pos->end > map->start) {
> +			first = next;
> +			if (pos->start <= map->start)
> +				break;
> +			next = next->rb_left;
> +		} else
> +			next = next->rb_right;
> +	}
> +
> +	next = first;
> +	while (next) {
> +		struct map *pos = rb_entry(next, struct map, rb_node);
> +		next = rb_next(&pos->rb_node);
> +
> +		/*
> +		 * Stop if current map starts after map->end.
> +		 * Maps are ordered by start: next will not overlap for sure.
> +		 */
> +		if (pos->start >= map->end)
> +			break;
> +
> +		if (verbose >= 2) {
> +
> +			if (use_browser) {
> +				pr_debug("overlapping maps in %s (disable tui for more info)\n",
> +					   map->dso->name);
> +			} else {
> +				fputs("overlapping maps:\n", fp);
> +				map__fprintf(map, fp);
> +				map__fprintf(pos, fp);
> +			}
> +		}
> +
> +		rb_erase_init(&pos->rb_node, root);
> +		/*
> +		 * Now check if we need to create new maps for areas not
> +		 * overlapped by the new map:
> +		 */
> +		if (map->start > pos->start) {
> +			struct map *before = map__clone(pos);
> +
> +			if (before == NULL) {
> +				err = -ENOMEM;
> +				goto put_map;
> +			}
> +
> +			before->end = map->start;
> +			__maps__insert(maps, before);
> +			if (verbose >= 2 && !use_browser)
> +				map__fprintf(before, fp);
> +			map__put(before);
> +		}
> +
> +		if (map->end < pos->end) {
> +			struct map *after = map__clone(pos);
> +
> +			if (after == NULL) {
> +				err = -ENOMEM;
> +				goto put_map;
> +			}
> +
> +			after->start = map->end;
> +			after->pgoff += map->end - pos->start;
> +			assert(pos->map_ip(pos, map->end) == after->map_ip(after, map->end));
> +			__maps__insert(maps, after);
> +			if (verbose >= 2 && !use_browser)
> +				map__fprintf(after, fp);
> +			map__put(after);
> +		}
> +put_map:
> +		map__put(pos);
> +
> +		if (err)
> +			goto out;
> +	}
> +
> +	err = 0;
> +out:
> +	up_write(&maps->lock);
> +	return err;
> +}
> +
> +/*
> + * XXX This should not really _copy_ te maps, but refcount them.
> + */
> +int maps__clone(struct thread *thread, struct maps *parent)
> +{
> +	struct maps *maps = thread->maps;
> +	int err;
> +	struct map *map;
> +
> +	down_read(&parent->lock);
> +
> +	maps__for_each_entry(parent, map) {
> +		struct map *new = map__clone(map);
> +
> +		if (new == NULL) {
> +			err = -ENOMEM;
> +			goto out_unlock;
> +		}
> +
> +		err = unwind__prepare_access(maps, new, NULL);
> +		if (err)
> +			goto out_unlock;
> +
> +		maps__insert(maps, new);
> +		map__put(new);
> +	}
> +
> +	err = 0;
> +out_unlock:
> +	up_read(&parent->lock);
> +	return err;
> +}
> +
> +static void __maps__insert(struct maps *maps, struct map *map)
> +{
> +	struct rb_node **p = &maps->entries.rb_node;
> +	struct rb_node *parent = NULL;
> +	const u64 ip = map->start;
> +	struct map *m;
> +
> +	while (*p != NULL) {
> +		parent = *p;
> +		m = rb_entry(parent, struct map, rb_node);
> +		if (ip < m->start)
> +			p = &(*p)->rb_left;
> +		else
> +			p = &(*p)->rb_right;
> +	}
> +
> +	rb_link_node(&map->rb_node, parent, p);
> +	rb_insert_color(&map->rb_node, &maps->entries);
> +	map__get(map);
> +}
> +
> +struct map *maps__find(struct maps *maps, u64 ip)
> +{
> +	struct rb_node *p;
> +	struct map *m;
> +
> +	down_read(&maps->lock);
> +
> +	p = maps->entries.rb_node;
> +	while (p != NULL) {
> +		m = rb_entry(p, struct map, rb_node);
> +		if (ip < m->start)
> +			p = p->rb_left;
> +		else if (ip >= m->end)
> +			p = p->rb_right;
> +		else
> +			goto out;
> +	}
> +
> +	m = NULL;
> +out:
> +	up_read(&maps->lock);
> +	return m;
> +}
> +
> +struct map *maps__first(struct maps *maps)
> +{
> +	struct rb_node *first = rb_first(&maps->entries);
> +
> +	if (first)
> +		return rb_entry(first, struct map, rb_node);
> +	return NULL;
> +}
> -- 
> 2.35.1.265.g69c8d7142f-goog

-- 

- Arnaldo

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ