diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
| -rw-r--r-- | tools/perf/util/symbol.c | 72 | 
1 files changed, 56 insertions, 16 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index ceefa6568de..561db6361f5 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -41,6 +41,7 @@ struct symbol_conf symbol_conf = {  	.exclude_other	  = true,  	.use_modules	  = true,  	.try_vmlinux_path = true, +	.symfs            = "",  };  int dso__name_len(const struct dso *self) @@ -839,8 +840,11 @@ static int dso__synthesize_plt_symbols(struct  dso *self, struct map *map,  	char sympltname[1024];  	Elf *elf;  	int nr = 0, symidx, fd, err = 0; +	char name[PATH_MAX]; -	fd = open(self->long_name, O_RDONLY); +	snprintf(name, sizeof(name), "%s%s", +		 symbol_conf.symfs, self->long_name); +	fd = open(name, O_RDONLY);  	if (fd < 0)  		goto out; @@ -1452,16 +1456,19 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)  	     self->origin++) {  		switch (self->origin) {  		case DSO__ORIG_BUILD_ID_CACHE: -			if (dso__build_id_filename(self, name, size) == NULL) +			/* skip the locally configured cache if a symfs is given */ +			if (symbol_conf.symfs[0] || +			    (dso__build_id_filename(self, name, size) == NULL)) {  				continue; +			}  			break;  		case DSO__ORIG_FEDORA: -			snprintf(name, size, "/usr/lib/debug%s.debug", -				 self->long_name); +			snprintf(name, size, "%s/usr/lib/debug%s.debug", +				 symbol_conf.symfs, self->long_name);  			break;  		case DSO__ORIG_UBUNTU: -			snprintf(name, size, "/usr/lib/debug%s", -				 self->long_name); +			snprintf(name, size, "%s/usr/lib/debug%s", +				 symbol_conf.symfs, self->long_name);  			break;  		case DSO__ORIG_BUILDID: {  			char build_id_hex[BUILD_ID_SIZE * 2 + 1]; @@ -1473,19 +1480,26 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)  					  sizeof(self->build_id),  					  build_id_hex);  			snprintf(name, size, -				 "/usr/lib/debug/.build-id/%.2s/%s.debug", -				 build_id_hex, build_id_hex + 2); +				 "%s/usr/lib/debug/.build-id/%.2s/%s.debug", +				 symbol_conf.symfs, build_id_hex, build_id_hex + 2);  			}  			break;  		case DSO__ORIG_DSO: -			snprintf(name, size, "%s", self->long_name); +			snprintf(name, size, "%s%s", +			     symbol_conf.symfs, self->long_name);  			break;  		case DSO__ORIG_GUEST_KMODULE:  			if (map->groups && map->groups->machine)  				root_dir = map->groups->machine->root_dir;  			else  				root_dir = ""; -			snprintf(name, size, "%s%s", root_dir, self->long_name); +			snprintf(name, size, "%s%s%s", symbol_conf.symfs, +				 root_dir, self->long_name); +			break; + +		case DSO__ORIG_KMODULE: +			snprintf(name, size, "%s%s", symbol_conf.symfs, +				 self->long_name);  			break;  		default: @@ -1784,17 +1798,20 @@ static int dso__load_vmlinux(struct dso *self, struct map *map,  			     const char *vmlinux, symbol_filter_t filter)  {  	int err = -1, fd; +	char symfs_vmlinux[PATH_MAX]; -	fd = open(vmlinux, O_RDONLY); +	snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s/%s", +		 symbol_conf.symfs, vmlinux); +	fd = open(symfs_vmlinux, O_RDONLY);  	if (fd < 0)  		return -1;  	dso__set_loaded(self, map->type); -	err = dso__load_sym(self, map, vmlinux, fd, filter, 0, 0); +	err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0);  	close(fd);  	if (err > 0) -		pr_debug("Using %s for symbols\n", vmlinux); +		pr_debug("Using %s for symbols\n", symfs_vmlinux);  	return err;  } @@ -1872,6 +1889,10 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,  			goto out_fixup;  	} +	/* do not try local files if a symfs was given */ +	if (symbol_conf.symfs[0] != 0) +		return -1; +  	/*  	 * Say the kernel DSO was created when processing the build-id header table,  	 * we have a build-id, so check if it is the same as the running kernel, @@ -2262,9 +2283,6 @@ static int vmlinux_path__init(void)  	struct utsname uts;  	char bf[PATH_MAX]; -	if (uname(&uts) < 0) -		return -1; -  	vmlinux_path = malloc(sizeof(char *) * 5);  	if (vmlinux_path == NULL)  		return -1; @@ -2277,6 +2295,14 @@ static int vmlinux_path__init(void)  	if (vmlinux_path[vmlinux_path__nr_entries] == NULL)  		goto out_fail;  	++vmlinux_path__nr_entries; + +	/* only try running kernel version if no symfs was given */ +	if (symbol_conf.symfs[0] != 0) +		return 0; + +	if (uname(&uts) < 0) +		return -1; +  	snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);  	vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);  	if (vmlinux_path[vmlinux_path__nr_entries] == NULL) @@ -2336,6 +2362,8 @@ static int setup_list(struct strlist **list, const char *list_str,  int symbol__init(void)  { +	const char *symfs; +  	if (symbol_conf.initialized)  		return 0; @@ -2364,6 +2392,18 @@ int symbol__init(void)  		       symbol_conf.sym_list_str, "symbol") < 0)  		goto out_free_comm_list; +	/* +	 * A path to symbols of "/" is identical to "" +	 * reset here for simplicity. +	 */ +	symfs = realpath(symbol_conf.symfs, NULL); +	if (symfs == NULL) +		symfs = symbol_conf.symfs; +	if (strcmp(symfs, "/") == 0) +		symbol_conf.symfs = ""; +	if (symfs != symbol_conf.symfs) +		free((void *)symfs); +  	symbol_conf.initialized = true;  	return 0;  |