diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
| -rw-r--r-- | tools/perf/util/symbol.c | 63 | 
1 files changed, 56 insertions, 7 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index b39f499e575..d628c8d1cf5 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -295,7 +295,9 @@ static void symbols__insert_by_name(struct rb_root *self, struct symbol *sym)  {  	struct rb_node **p = &self->rb_node;  	struct rb_node *parent = NULL; -	struct symbol_name_rb_node *symn = ((void *)sym) - sizeof(*parent), *s; +	struct symbol_name_rb_node *symn, *s; + +	symn = container_of(sym, struct symbol_name_rb_node, sym);  	while (*p != NULL) {  		parent = *p; @@ -530,7 +532,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,  	struct machine *machine = kmaps->machine;  	struct map *curr_map = map;  	struct symbol *pos; -	int count = 0; +	int count = 0, moved = 0;	  	struct rb_root *root = &self->symbols[map->type];  	struct rb_node *next = rb_first(root);  	int kernel_range = 0; @@ -588,6 +590,11 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,  			char dso_name[PATH_MAX];  			struct dso *dso; +			if (count == 0) { +				curr_map = map; +				goto filter_symbol; +			} +  			if (self->kernel == DSO_TYPE_GUEST_KERNEL)  				snprintf(dso_name, sizeof(dso_name),  					"[guest.kernel].%d", @@ -613,7 +620,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,  			map_groups__insert(kmaps, curr_map);  			++kernel_range;  		} - +filter_symbol:  		if (filter && filter(curr_map, pos)) {  discard_symbol:		rb_erase(&pos->rb_node, root);  			symbol__delete(pos); @@ -621,8 +628,9 @@ discard_symbol:		rb_erase(&pos->rb_node, root);  			if (curr_map != map) {  				rb_erase(&pos->rb_node, root);  				symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); -			} -			count++; +				++moved; +			} else +				++count;  		}  	} @@ -632,7 +640,7 @@ discard_symbol:		rb_erase(&pos->rb_node, root);  		dso__set_loaded(curr_map->dso, curr_map->type);  	} -	return count; +	return count + moved;  }  int dso__load_kallsyms(struct dso *self, const char *filename, @@ -2123,14 +2131,55 @@ static struct dso *machine__create_kernel(struct machine *self)  	return kernel;  } +struct process_args { +	u64 start; +}; + +static int symbol__in_kernel(void *arg, const char *name, +			     char type __used, u64 start) +{ +	struct process_args *args = arg; + +	if (strchr(name, '[')) +		return 0; + +	args->start = start; +	return 1; +} + +/* Figure out the start address of kernel map from /proc/kallsyms */ +static u64 machine__get_kernel_start_addr(struct machine *machine) +{ +	const char *filename; +	char path[PATH_MAX]; +	struct process_args args; + +	if (machine__is_host(machine)) { +		filename = "/proc/kallsyms"; +	} else { +		if (machine__is_default_guest(machine)) +			filename = (char *)symbol_conf.default_guest_kallsyms; +		else { +			sprintf(path, "%s/proc/kallsyms", machine->root_dir); +			filename = path; +		} +	} + +	if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0) +		return 0; + +	return args.start; +} +  int __machine__create_kernel_maps(struct machine *self, struct dso *kernel)  {  	enum map_type type; +	u64 start = machine__get_kernel_start_addr(self);  	for (type = 0; type < MAP__NR_TYPES; ++type) {  		struct kmap *kmap; -		self->vmlinux_maps[type] = map__new2(0, kernel, type); +		self->vmlinux_maps[type] = map__new2(start, kernel, type);  		if (self->vmlinux_maps[type] == NULL)  			return -1;  |