Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Ingo Molnar:
"Tooling fixes, mostly related to the KASLR fallout, but also other
fixes"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf buildid-cache: Check relocation when checking for existing kcore
perf tools: Adjust kallsyms for relocated kernel
perf tests: No need to set up ref_reloc_sym
perf symbols: Prevent the use of kcore if the kernel has moved
perf record: Get ref_reloc_sym from kernel map
perf machine: Set up ref_reloc_sym in machine__create_kernel_maps()
perf machine: Add machine__get_kallsyms_filename()
perf tools: Add kallsyms__get_function_start()
perf symbols: Fix symbol annotation for relocated kernel
perf tools: Fix include for non x86 architectures
perf tools: Fix AAAAARGH64 memory barriers
perf tools: Demangle kernel and kernel module symbols too
perf/doc: Remove mention of non-existent set_perf_event_pending() from design.txt

+162 -63
+29 -4
tools/perf/builtin-buildid-cache.c
··· 63 63 return 0; 64 64 } 65 65 66 + static bool same_kallsyms_reloc(const char *from_dir, char *to_dir) 67 + { 68 + char from[PATH_MAX]; 69 + char to[PATH_MAX]; 70 + const char *name; 71 + u64 addr1 = 0, addr2 = 0; 72 + int i; 73 + 74 + scnprintf(from, sizeof(from), "%s/kallsyms", from_dir); 75 + scnprintf(to, sizeof(to), "%s/kallsyms", to_dir); 76 + 77 + for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) { 78 + addr1 = kallsyms__get_function_start(from, name); 79 + if (addr1) 80 + break; 81 + } 82 + 83 + if (name) 84 + addr2 = kallsyms__get_function_start(to, name); 85 + 86 + return addr1 == addr2; 87 + } 88 + 66 89 static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir, 67 90 size_t to_dir_sz) 68 91 { 69 92 char from[PATH_MAX]; 70 93 char to[PATH_MAX]; 94 + char to_subdir[PATH_MAX]; 71 95 struct dirent *dent; 72 96 int ret = -1; 73 97 DIR *d; ··· 110 86 continue; 111 87 scnprintf(to, sizeof(to), "%s/%s/modules", to_dir, 112 88 dent->d_name); 113 - if (!compare_proc_modules(from, to)) { 114 - scnprintf(to, sizeof(to), "%s/%s", to_dir, 115 - dent->d_name); 116 - strlcpy(to_dir, to, to_dir_sz); 89 + scnprintf(to_subdir, sizeof(to_subdir), "%s/%s", 90 + to_dir, dent->d_name); 91 + if (!compare_proc_modules(from, to) && 92 + same_kallsyms_reloc(from_dir, to_subdir)) { 93 + strlcpy(to_dir, to_subdir, to_dir_sz); 117 94 ret = 0; 118 95 break; 119 96 }
+2 -8
tools/perf/builtin-record.c
··· 287 287 * have no _text sometimes. 288 288 */ 289 289 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 290 - machine, "_text"); 291 - if (err < 0) 292 - err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 293 - machine, "_stext"); 290 + machine); 294 291 if (err < 0) 295 292 pr_err("Couldn't record guest kernel [%d]'s reference" 296 293 " relocation symbol.\n", machine->pid); ··· 454 457 } 455 458 456 459 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 457 - machine, "_text"); 458 - if (err < 0) 459 - err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 460 - machine, "_stext"); 460 + machine); 461 461 if (err < 0) 462 462 pr_err("Couldn't record kernel reference relocation symbol\n" 463 463 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
-1
tools/perf/design.txt
··· 454 454 will need at least this: 455 455 - asm/perf_event.h - a basic stub will suffice at first 456 456 - support for atomic64 types (and associated helper functions) 457 - - set_perf_event_pending() implemented 458 457 459 458 If your architecture does have hardware capabilities, you can override the 460 459 weak stub hw_perf_event_init() to register hardware counters.
+2 -2
tools/perf/perf.h
··· 100 100 101 101 #ifdef __aarch64__ 102 102 #define mb() asm volatile("dmb ish" ::: "memory") 103 - #define wmb() asm volatile("dmb ishld" ::: "memory") 104 - #define rmb() asm volatile("dmb ishst" ::: "memory") 103 + #define wmb() asm volatile("dmb ishst" ::: "memory") 104 + #define rmb() asm volatile("dmb ishld" ::: "memory") 105 105 #define cpu_relax() asm volatile("yield" ::: "memory") 106 106 #endif 107 107
-10
tools/perf/tests/vmlinux-kallsyms.c
··· 26 26 struct map *kallsyms_map, *vmlinux_map; 27 27 struct machine kallsyms, vmlinux; 28 28 enum map_type type = MAP__FUNCTION; 29 - struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", }; 30 29 u64 mem_start, mem_end; 31 30 32 31 /* ··· 69 70 */ 70 71 kallsyms_map = machine__kernel_map(&kallsyms, type); 71 72 72 - sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL); 73 - if (sym == NULL) { 74 - pr_debug("dso__find_symbol_by_name "); 75 - goto out; 76 - } 77 - 78 - ref_reloc_sym.addr = UM(sym->start); 79 - 80 73 /* 81 74 * Step 5: 82 75 * ··· 80 89 } 81 90 82 91 vmlinux_map = machine__kernel_map(&vmlinux, type); 83 - map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym; 84 92 85 93 /* 86 94 * Step 6:
+17 -19
tools/perf/util/event.c
··· 470 470 return 1; 471 471 } 472 472 473 + u64 kallsyms__get_function_start(const char *kallsyms_filename, 474 + const char *symbol_name) 475 + { 476 + struct process_symbol_args args = { .name = symbol_name, }; 477 + 478 + if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0) 479 + return 0; 480 + 481 + return args.start; 482 + } 483 + 473 484 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, 474 485 perf_event__handler_t process, 475 - struct machine *machine, 476 - const char *symbol_name) 486 + struct machine *machine) 477 487 { 478 488 size_t size; 479 - const char *filename, *mmap_name; 480 - char path[PATH_MAX]; 489 + const char *mmap_name; 481 490 char name_buff[PATH_MAX]; 482 491 struct map *map; 492 + struct kmap *kmap; 483 493 int err; 484 494 /* 485 495 * We should get this from /sys/kernel/sections/.text, but till that is 486 496 * available use this, and after it is use this as a fallback for older 487 497 * kernels. 488 498 */ 489 - struct process_symbol_args args = { .name = symbol_name, }; 490 499 union perf_event *event = zalloc((sizeof(event->mmap) + 491 500 machine->id_hdr_size)); 492 501 if (event == NULL) { ··· 511 502 * see kernel/perf_event.c __perf_event_mmap 512 503 */ 513 504 event->header.misc = PERF_RECORD_MISC_KERNEL; 514 - filename = "/proc/kallsyms"; 515 505 } else { 516 506 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 517 - if (machine__is_default_guest(machine)) 518 - filename = (char *) symbol_conf.default_guest_kallsyms; 519 - else { 520 - sprintf(path, "%s/proc/kallsyms", machine->root_dir); 521 - filename = path; 522 - } 523 - } 524 - 525 - if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) { 526 - free(event); 527 - return -ENOENT; 528 507 } 529 508 530 509 map = machine->vmlinux_maps[MAP__FUNCTION]; 510 + kmap = map__kmap(map); 531 511 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), 532 - "%s%s", mmap_name, symbol_name) + 1; 512 + "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1; 533 513 size = PERF_ALIGN(size, sizeof(u64)); 534 514 event->mmap.header.type = PERF_RECORD_MMAP; 535 515 event->mmap.header.size = (sizeof(event->mmap) - 536 516 (sizeof(event->mmap.filename) - size) + machine->id_hdr_size); 537 - event->mmap.pgoff = args.start; 517 + event->mmap.pgoff = kmap->ref_reloc_sym->addr; 538 518 event->mmap.start = map->start; 539 519 event->mmap.len = map->end - event->mmap.start; 540 520 event->mmap.pid = machine->pid;
+4 -2
tools/perf/util/event.h
··· 214 214 struct machine *machine, bool mmap_data); 215 215 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, 216 216 perf_event__handler_t process, 217 - struct machine *machine, 218 - const char *symbol_name); 217 + struct machine *machine); 219 218 220 219 int perf_event__synthesize_modules(struct perf_tool *tool, 221 220 perf_event__handler_t process, ··· 277 278 size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp); 278 279 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp); 279 280 size_t perf_event__fprintf(union perf_event *event, FILE *fp); 281 + 282 + u64 kallsyms__get_function_start(const char *kallsyms_filename, 283 + const char *symbol_name); 280 284 281 285 #endif /* __PERF_RECORD_H */
+6
tools/perf/util/include/asm/hash.h
··· 1 + #ifndef __ASM_GENERIC_HASH_H 2 + #define __ASM_GENERIC_HASH_H 3 + 4 + /* Stub */ 5 + 6 + #endif /* __ASM_GENERIC_HASH_H */
+34 -8
tools/perf/util/machine.c
··· 496 496 return 1; 497 497 } 498 498 499 + static void machine__get_kallsyms_filename(struct machine *machine, char *buf, 500 + size_t bufsz) 501 + { 502 + if (machine__is_default_guest(machine)) 503 + scnprintf(buf, bufsz, "%s", symbol_conf.default_guest_kallsyms); 504 + else 505 + scnprintf(buf, bufsz, "%s/proc/kallsyms", machine->root_dir); 506 + } 507 + 499 508 /* Figure out the start address of kernel map from /proc/kallsyms */ 500 509 static u64 machine__get_kernel_start_addr(struct machine *machine) 501 510 { 502 - const char *filename; 503 - char path[PATH_MAX]; 511 + char filename[PATH_MAX]; 504 512 struct process_args args; 505 513 506 - if (machine__is_default_guest(machine)) 507 - filename = (char *)symbol_conf.default_guest_kallsyms; 508 - else { 509 - sprintf(path, "%s/proc/kallsyms", machine->root_dir); 510 - filename = path; 511 - } 514 + machine__get_kallsyms_filename(machine, filename, PATH_MAX); 512 515 513 516 if (symbol__restricted_filename(filename, "/proc/kallsyms")) 514 517 return 0; ··· 832 829 return 0; 833 830 } 834 831 832 + const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL}; 833 + 835 834 int machine__create_kernel_maps(struct machine *machine) 836 835 { 837 836 struct dso *kernel = machine__get_kernel(machine); 837 + char filename[PATH_MAX]; 838 + const char *name; 839 + u64 addr = 0; 840 + int i; 841 + 842 + machine__get_kallsyms_filename(machine, filename, PATH_MAX); 843 + 844 + for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) { 845 + addr = kallsyms__get_function_start(filename, name); 846 + if (addr) 847 + break; 848 + } 849 + if (!addr) 850 + return -1; 838 851 839 852 if (kernel == NULL || 840 853 __machine__create_kernel_maps(machine, kernel) < 0) ··· 869 850 * Now that we have all the maps created, just set the ->end of them: 870 851 */ 871 852 map_groups__fixup_end(&machine->kmaps); 853 + 854 + if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, 855 + addr)) { 856 + machine__destroy_kernel_maps(machine); 857 + return -1; 858 + } 859 + 872 860 return 0; 873 861 } 874 862
+2
tools/perf/util/machine.h
··· 18 18 #define HOST_KERNEL_ID (-1) 19 19 #define DEFAULT_GUEST_KERNEL_ID (0) 20 20 21 + extern const char *ref_reloc_sym_names[]; 22 + 21 23 struct machine { 22 24 struct rb_node rb_node; 23 25 pid_t pid;
+3 -2
tools/perf/util/map.c
··· 39 39 map->start = start; 40 40 map->end = end; 41 41 map->pgoff = pgoff; 42 + map->reloc = 0; 42 43 map->dso = dso; 43 44 map->map_ip = map__map_ip; 44 45 map->unmap_ip = map__unmap_ip; ··· 289 288 if (map->dso->rel) 290 289 return rip - map->pgoff; 291 290 292 - return map->unmap_ip(map, rip); 291 + return map->unmap_ip(map, rip) - map->reloc; 293 292 } 294 293 295 294 /** ··· 312 311 if (map->dso->rel) 313 312 return map->unmap_ip(map, ip + map->pgoff); 314 313 315 - return ip; 314 + return ip + map->reloc; 316 315 } 317 316 318 317 void map_groups__init(struct map_groups *mg)
+1
tools/perf/util/map.h
··· 36 36 bool erange_warned; 37 37 u32 priv; 38 38 u64 pgoff; 39 + u64 reloc; 39 40 u32 maj, min; /* only valid for MMAP2 record */ 40 41 u64 ino; /* only valid for MMAP2 record */ 41 42 u64 ino_generation;/* only valid for MMAP2 record */
+3 -1
tools/perf/util/symbol-elf.c
··· 751 751 if (strcmp(elf_name, kmap->ref_reloc_sym->name)) 752 752 continue; 753 753 kmap->ref_reloc_sym->unrelocated_addr = sym.st_value; 754 + map->reloc = kmap->ref_reloc_sym->addr - 755 + kmap->ref_reloc_sym->unrelocated_addr; 754 756 break; 755 757 } 756 758 } ··· 924 922 (u64)shdr.sh_offset); 925 923 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 926 924 } 925 + new_symbol: 927 926 /* 928 927 * We need to figure out if the object was created from C++ sources 929 928 * DWARF DW_compile_unit has this, but we don't always have access ··· 936 933 if (demangled != NULL) 937 934 elf_name = demangled; 938 935 } 939 - new_symbol: 940 936 f = symbol__new(sym.st_value, sym.st_size, 941 937 GELF_ST_BIND(sym.st_info), elf_name); 942 938 free(demangled);
+59 -6
tools/perf/util/symbol.c
··· 627 627 * kernel range is broken in several maps, named [kernel].N, as we don't have 628 628 * the original ELF section names vmlinux have. 629 629 */ 630 - static int dso__split_kallsyms(struct dso *dso, struct map *map, 630 + static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, 631 631 symbol_filter_t filter) 632 632 { 633 633 struct map_groups *kmaps = map__kmap(map)->kmaps; ··· 692 692 char dso_name[PATH_MAX]; 693 693 struct dso *ndso; 694 694 695 + if (delta) { 696 + /* Kernel was relocated at boot time */ 697 + pos->start -= delta; 698 + pos->end -= delta; 699 + } 700 + 695 701 if (count == 0) { 696 702 curr_map = map; 697 703 goto filter_symbol; ··· 727 721 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; 728 722 map_groups__insert(kmaps, curr_map); 729 723 ++kernel_range; 724 + } else if (delta) { 725 + /* Kernel was relocated at boot time */ 726 + pos->start -= delta; 727 + pos->end -= delta; 730 728 } 731 729 filter_symbol: 732 730 if (filter && filter(curr_map, pos)) { ··· 986 976 return 0; 987 977 } 988 978 979 + static int validate_kcore_addresses(const char *kallsyms_filename, 980 + struct map *map) 981 + { 982 + struct kmap *kmap = map__kmap(map); 983 + 984 + if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) { 985 + u64 start; 986 + 987 + start = kallsyms__get_function_start(kallsyms_filename, 988 + kmap->ref_reloc_sym->name); 989 + if (start != kmap->ref_reloc_sym->addr) 990 + return -EINVAL; 991 + } 992 + 993 + return validate_kcore_modules(kallsyms_filename, map); 994 + } 995 + 989 996 struct kcore_mapfn_data { 990 997 struct dso *dso; 991 998 enum map_type type; ··· 1046 1019 kallsyms_filename)) 1047 1020 return -EINVAL; 1048 1021 1049 - /* All modules must be present at their original addresses */ 1050 - if (validate_kcore_modules(kallsyms_filename, map)) 1022 + /* Modules and kernel must be present at their original addresses */ 1023 + if (validate_kcore_addresses(kallsyms_filename, map)) 1051 1024 return -EINVAL; 1052 1025 1053 1026 md.dso = dso; ··· 1140 1113 return -EINVAL; 1141 1114 } 1142 1115 1116 + /* 1117 + * If the kernel is relocated at boot time, kallsyms won't match. Compute the 1118 + * delta based on the relocation reference symbol. 1119 + */ 1120 + static int kallsyms__delta(struct map *map, const char *filename, u64 *delta) 1121 + { 1122 + struct kmap *kmap = map__kmap(map); 1123 + u64 addr; 1124 + 1125 + if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) 1126 + return 0; 1127 + 1128 + addr = kallsyms__get_function_start(filename, 1129 + kmap->ref_reloc_sym->name); 1130 + if (!addr) 1131 + return -1; 1132 + 1133 + *delta = addr - kmap->ref_reloc_sym->addr; 1134 + return 0; 1135 + } 1136 + 1143 1137 int dso__load_kallsyms(struct dso *dso, const char *filename, 1144 1138 struct map *map, symbol_filter_t filter) 1145 1139 { 1140 + u64 delta = 0; 1141 + 1146 1142 if (symbol__restricted_filename(filename, "/proc/kallsyms")) 1147 1143 return -1; 1148 1144 1149 1145 if (dso__load_all_kallsyms(dso, filename, map) < 0) 1146 + return -1; 1147 + 1148 + if (kallsyms__delta(map, filename, &delta)) 1150 1149 return -1; 1151 1150 1152 1151 symbols__fixup_duplicate(&dso->symbols[map->type]); ··· 1186 1133 if (!dso__load_kcore(dso, map, filename)) 1187 1134 return dso__split_kallsyms_for_kcore(dso, map, filter); 1188 1135 else 1189 - return dso__split_kallsyms(dso, map, filter); 1136 + return dso__split_kallsyms(dso, map, delta, filter); 1190 1137 } 1191 1138 1192 1139 static int dso__load_perf_map(struct dso *dso, struct map *map, ··· 1477 1424 continue; 1478 1425 scnprintf(kallsyms_filename, sizeof(kallsyms_filename), 1479 1426 "%s/%s/kallsyms", dir, dent->d_name); 1480 - if (!validate_kcore_modules(kallsyms_filename, map)) { 1427 + if (!validate_kcore_addresses(kallsyms_filename, map)) { 1481 1428 strlcpy(dir, kallsyms_filename, dir_sz); 1482 1429 ret = 0; 1483 1430 break; ··· 1532 1479 if (fd != -1) { 1533 1480 close(fd); 1534 1481 /* If module maps match go with /proc/kallsyms */ 1535 - if (!validate_kcore_modules("/proc/kallsyms", map)) 1482 + if (!validate_kcore_addresses("/proc/kallsyms", map)) 1536 1483 goto proc_kallsyms; 1537 1484 } 1538 1485