diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
| -rw-r--r-- | tools/perf/util/symbol.c | 63 | 
1 files changed, 55 insertions, 8 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 0500895a45a..439ab947daf 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -532,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; @@ -590,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", @@ -615,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); @@ -623,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;  		}  	} @@ -634,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, @@ -1774,8 +1780,8 @@ out_failure:  	return -1;  } -static int dso__load_vmlinux(struct dso *self, struct map *map, -			     const char *vmlinux, symbol_filter_t filter) +int dso__load_vmlinux(struct dso *self, struct map *map, +		      const char *vmlinux, symbol_filter_t filter)  {  	int err = -1, fd; @@ -2125,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;  |