perf symbols: Split kernel symbol processing from dso__load_sym()
More should be done to split this function, removing stuff map relocation steps from the actual symbol table loading. Arch specific stuff also should go elsewhere, to tools/arch/ and we should have it keyed by data from the perf_env either in the perf.data header or from the running environment. Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Wang Nan <wangnan0@huawei.com> Link: https://lkml.kernel.org/n/tip-236gyo6cx6iet90u3uc01cws@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
		
							parent
							
								
									857140e816
								
							
						
					
					
						commit
						4e0d1e8bcb
					
				| @ -797,6 +797,110 @@ static u64 ref_reloc(struct kmap *kmap) | ||||
| void __weak arch__sym_update(struct symbol *s __maybe_unused, | ||||
| 		GElf_Sym *sym __maybe_unused) { } | ||||
| 
 | ||||
| static int dso__process_kernel_symbol(struct dso *dso, struct map *map, | ||||
| 				      GElf_Sym *sym, GElf_Shdr *shdr, | ||||
| 				      struct map_groups *kmaps, struct kmap *kmap, | ||||
| 				      struct dso **curr_dsop, struct map **curr_mapp, | ||||
| 				      const char *section_name, | ||||
| 				      bool adjust_kernel_syms, bool kmodule, bool *remap_kernel) | ||||
| { | ||||
| 	struct dso *curr_dso = *curr_dsop; | ||||
| 	struct map *curr_map; | ||||
| 	char dso_name[PATH_MAX]; | ||||
| 
 | ||||
| 	/* Adjust symbol to map to file offset */ | ||||
| 	if (adjust_kernel_syms) | ||||
| 		sym->st_value -= shdr->sh_addr - shdr->sh_offset; | ||||
| 
 | ||||
| 	if (strcmp(section_name, (curr_dso->short_name + dso->short_name_len)) == 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if (strcmp(section_name, ".text") == 0) { | ||||
| 		/*
 | ||||
| 		 * The initial kernel mapping is based on | ||||
| 		 * kallsyms and identity maps.  Overwrite it to | ||||
| 		 * map to the kernel dso. | ||||
| 		 */ | ||||
| 		if (*remap_kernel && dso->kernel) { | ||||
| 			*remap_kernel = false; | ||||
| 			map->start = shdr->sh_addr + ref_reloc(kmap); | ||||
| 			map->end = map->start + shdr->sh_size; | ||||
| 			map->pgoff = shdr->sh_offset; | ||||
| 			map->map_ip = map__map_ip; | ||||
| 			map->unmap_ip = map__unmap_ip; | ||||
| 			/* Ensure maps are correctly ordered */ | ||||
| 			if (kmaps) { | ||||
| 				map__get(map); | ||||
| 				map_groups__remove(kmaps, map); | ||||
| 				map_groups__insert(kmaps, map); | ||||
| 				map__put(map); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * The initial module mapping is based on | ||||
| 		 * /proc/modules mapped to offset zero. | ||||
| 		 * Overwrite it to map to the module dso. | ||||
| 		 */ | ||||
| 		if (*remap_kernel && kmodule) { | ||||
| 			*remap_kernel = false; | ||||
| 			map->pgoff = shdr->sh_offset; | ||||
| 		} | ||||
| 
 | ||||
| 		*curr_mapp = map; | ||||
| 		*curr_dsop = dso; | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!kmap) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	snprintf(dso_name, sizeof(dso_name), "%s%s", dso->short_name, section_name); | ||||
| 
 | ||||
| 	curr_map = map_groups__find_by_name(kmaps, dso_name); | ||||
| 	if (curr_map == NULL) { | ||||
| 		u64 start = sym->st_value; | ||||
| 
 | ||||
| 		if (kmodule) | ||||
| 			start += map->start + shdr->sh_offset; | ||||
| 
 | ||||
| 		curr_dso = dso__new(dso_name); | ||||
| 		if (curr_dso == NULL) | ||||
| 			return -1; | ||||
| 		curr_dso->kernel = dso->kernel; | ||||
| 		curr_dso->long_name = dso->long_name; | ||||
| 		curr_dso->long_name_len = dso->long_name_len; | ||||
| 		curr_map = map__new2(start, curr_dso); | ||||
| 		dso__put(curr_dso); | ||||
| 		if (curr_map == NULL) | ||||
| 			return -1; | ||||
| 
 | ||||
| 		if (adjust_kernel_syms) { | ||||
| 			curr_map->start  = shdr->sh_addr + ref_reloc(kmap); | ||||
| 			curr_map->end	 = curr_map->start + shdr->sh_size; | ||||
| 			curr_map->pgoff	 = shdr->sh_offset; | ||||
| 		} else { | ||||
| 			curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; | ||||
| 		} | ||||
| 		curr_dso->symtab_type = dso->symtab_type; | ||||
| 		map_groups__insert(kmaps, curr_map); | ||||
| 		/*
 | ||||
| 		 * Add it before we drop the referece to curr_map, i.e. while | ||||
| 		 * we still are sure to have a reference to this DSO via | ||||
| 		 * *curr_map->dso. | ||||
| 		 */ | ||||
| 		dsos__add(&map->groups->machine->dsos, curr_dso); | ||||
| 		/* kmaps already got it */ | ||||
| 		map__put(curr_map); | ||||
| 		dso__set_loaded(curr_dso); | ||||
| 		*curr_mapp = curr_map; | ||||
| 		*curr_dsop = curr_dso; | ||||
| 	} else | ||||
| 		*curr_dsop = curr_map->dso; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, | ||||
| 		  struct symsrc *runtime_ss, int kmodule) | ||||
| { | ||||
| @ -973,102 +1077,9 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, | ||||
| 			--sym.st_value; | ||||
| 
 | ||||
| 		if (dso->kernel || kmodule) { | ||||
| 			char dso_name[PATH_MAX]; | ||||
| 
 | ||||
| 			/* Adjust symbol to map to file offset */ | ||||
| 			if (adjust_kernel_syms) | ||||
| 				sym.st_value -= shdr.sh_addr - shdr.sh_offset; | ||||
| 
 | ||||
| 			if (strcmp(section_name, | ||||
| 				   (curr_dso->short_name + | ||||
| 				    dso->short_name_len)) == 0) | ||||
| 				goto new_symbol; | ||||
| 
 | ||||
| 			if (strcmp(section_name, ".text") == 0) { | ||||
| 				/*
 | ||||
| 				 * The initial kernel mapping is based on | ||||
| 				 * kallsyms and identity maps.  Overwrite it to | ||||
| 				 * map to the kernel dso. | ||||
| 				 */ | ||||
| 				if (remap_kernel && dso->kernel) { | ||||
| 					remap_kernel = false; | ||||
| 					map->start = shdr.sh_addr + | ||||
| 						     ref_reloc(kmap); | ||||
| 					map->end = map->start + shdr.sh_size; | ||||
| 					map->pgoff = shdr.sh_offset; | ||||
| 					map->map_ip = map__map_ip; | ||||
| 					map->unmap_ip = map__unmap_ip; | ||||
| 					/* Ensure maps are correctly ordered */ | ||||
| 					if (kmaps) { | ||||
| 						map__get(map); | ||||
| 						map_groups__remove(kmaps, map); | ||||
| 						map_groups__insert(kmaps, map); | ||||
| 						map__put(map); | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				/*
 | ||||
| 				 * The initial module mapping is based on | ||||
| 				 * /proc/modules mapped to offset zero. | ||||
| 				 * Overwrite it to map to the module dso. | ||||
| 				 */ | ||||
| 				if (remap_kernel && kmodule) { | ||||
| 					remap_kernel = false; | ||||
| 					map->pgoff = shdr.sh_offset; | ||||
| 				} | ||||
| 
 | ||||
| 				curr_map = map; | ||||
| 				curr_dso = dso; | ||||
| 				goto new_symbol; | ||||
| 			} | ||||
| 
 | ||||
| 			if (!kmap) | ||||
| 				goto new_symbol; | ||||
| 
 | ||||
| 			snprintf(dso_name, sizeof(dso_name), | ||||
| 				 "%s%s", dso->short_name, section_name); | ||||
| 
 | ||||
| 			curr_map = map_groups__find_by_name(kmaps, dso_name); | ||||
| 			if (curr_map == NULL) { | ||||
| 				u64 start = sym.st_value; | ||||
| 
 | ||||
| 				if (kmodule) | ||||
| 					start += map->start + shdr.sh_offset; | ||||
| 
 | ||||
| 				curr_dso = dso__new(dso_name); | ||||
| 				if (curr_dso == NULL) | ||||
| 					goto out_elf_end; | ||||
| 				curr_dso->kernel = dso->kernel; | ||||
| 				curr_dso->long_name = dso->long_name; | ||||
| 				curr_dso->long_name_len = dso->long_name_len; | ||||
| 				curr_map = map__new2(start, curr_dso); | ||||
| 				dso__put(curr_dso); | ||||
| 				if (curr_map == NULL) { | ||||
| 					goto out_elf_end; | ||||
| 				} | ||||
| 				if (adjust_kernel_syms) { | ||||
| 					curr_map->start = shdr.sh_addr + | ||||
| 							  ref_reloc(kmap); | ||||
| 					curr_map->end = curr_map->start + | ||||
| 							shdr.sh_size; | ||||
| 					curr_map->pgoff = shdr.sh_offset; | ||||
| 				} else { | ||||
| 					curr_map->map_ip = identity__map_ip; | ||||
| 					curr_map->unmap_ip = identity__map_ip; | ||||
| 				} | ||||
| 				curr_dso->symtab_type = dso->symtab_type; | ||||
| 				map_groups__insert(kmaps, curr_map); | ||||
| 				/*
 | ||||
| 				 * Add it before we drop the referece to curr_map, | ||||
| 				 * i.e. while we still are sure to have a reference | ||||
| 				 * to this DSO via curr_map->dso. | ||||
| 				 */ | ||||
| 				dsos__add(&map->groups->machine->dsos, curr_dso); | ||||
| 				/* kmaps already got it */ | ||||
| 				map__put(curr_map); | ||||
| 				dso__set_loaded(curr_dso); | ||||
| 			} else | ||||
| 				curr_dso = curr_map->dso; | ||||
| 			if (dso__process_kernel_symbol(dso, map, &sym, &shdr, kmaps, kmap, &curr_dso, &curr_map, | ||||
| 						       section_name, adjust_kernel_syms, kmodule, &remap_kernel)) | ||||
| 				goto out_elf_end; | ||||
| 		} else if ((used_opd && runtime_ss->adjust_symbols) || | ||||
| 			   (!used_opd && syms_ss->adjust_symbols)) { | ||||
| 			pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " | ||||
| @ -1077,7 +1088,7 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, | ||||
| 				  (u64)shdr.sh_offset); | ||||
| 			sym.st_value -= shdr.sh_addr - shdr.sh_offset; | ||||
| 		} | ||||
| new_symbol: | ||||
| 
 | ||||
| 		demangled = demangle_sym(dso, kmodule, elf_name); | ||||
| 		if (demangled != NULL) | ||||
| 			elf_name = demangled; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user