Skip to content

Commit 2737fce

Browse files
author
Ingo Molnar
committed
Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/urgent fixes from Arnaldo Carvalho de Melo: * Fix annotation for relocated kernel (Adrian Hunter) * Fix demangling of symbols in kernel and kernel modules (Avi Kivity) * Fix include for non x86 architectures (Francesco Fusco) * Fix ARM64 memory barriers (Peter Zijlstra) Signed-off-by: Arnaldo Carvalho de Melo <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
2 parents 0d4dd79 + d3b7022 commit 2737fce

File tree

13 files changed

+162
-62
lines changed

13 files changed

+162
-62
lines changed

tools/perf/builtin-buildid-cache.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,35 @@ static int build_id_cache__kcore_dir(char *dir, size_t sz)
6363
return 0;
6464
}
6565

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+
6689
static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
6790
size_t to_dir_sz)
6891
{
6992
char from[PATH_MAX];
7093
char to[PATH_MAX];
94+
char to_subdir[PATH_MAX];
7195
struct dirent *dent;
7296
int ret = -1;
7397
DIR *d;
@@ -86,10 +110,11 @@ static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
86110
continue;
87111
scnprintf(to, sizeof(to), "%s/%s/modules", to_dir,
88112
dent->d_name);
89-
if (!compare_proc_modules(from, to)) {
90-
scnprintf(to, sizeof(to), "%s/%s", to_dir,
91-
dent->d_name);
92-
strlcpy(to_dir, to, to_dir_sz);
113+
scnprintf(to_subdir, sizeof(to_subdir), "%s/%s",
114+
to_dir, dent->d_name);
115+
if (!compare_proc_modules(from, to) &&
116+
same_kallsyms_reloc(from_dir, to_subdir)) {
117+
strlcpy(to_dir, to_subdir, to_dir_sz);
93118
ret = 0;
94119
break;
95120
}

tools/perf/builtin-record.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,7 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
287287
* have no _text sometimes.
288288
*/
289289
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);
294291
if (err < 0)
295292
pr_err("Couldn't record guest kernel [%d]'s reference"
296293
" relocation symbol.\n", machine->pid);
@@ -457,10 +454,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
457454
}
458455

459456
err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
460-
machine, "_text");
461-
if (err < 0)
462-
err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
463-
machine, "_stext");
457+
machine);
464458
if (err < 0)
465459
pr_err("Couldn't record kernel reference relocation symbol\n"
466460
"Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"

tools/perf/perf.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@
100100

101101
#ifdef __aarch64__
102102
#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")
105105
#define cpu_relax() asm volatile("yield" ::: "memory")
106106
#endif
107107

tools/perf/tests/vmlinux-kallsyms.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ int test__vmlinux_matches_kallsyms(void)
2626
struct map *kallsyms_map, *vmlinux_map;
2727
struct machine kallsyms, vmlinux;
2828
enum map_type type = MAP__FUNCTION;
29-
struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };
3029
u64 mem_start, mem_end;
3130

3231
/*
@@ -70,14 +69,6 @@ int test__vmlinux_matches_kallsyms(void)
7069
*/
7170
kallsyms_map = machine__kernel_map(&kallsyms, type);
7271

73-
sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL);
74-
if (sym == NULL) {
75-
pr_debug("dso__find_symbol_by_name ");
76-
goto out;
77-
}
78-
79-
ref_reloc_sym.addr = UM(sym->start);
80-
8172
/*
8273
* Step 5:
8374
*
@@ -89,7 +80,6 @@ int test__vmlinux_matches_kallsyms(void)
8980
}
9081

9182
vmlinux_map = machine__kernel_map(&vmlinux, type);
92-
map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym;
9383

9484
/*
9585
* Step 6:

tools/perf/util/event.c

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -470,23 +470,32 @@ static int find_symbol_cb(void *arg, const char *name, char type,
470470
return 1;
471471
}
472472

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+
473484
int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
474485
perf_event__handler_t process,
475-
struct machine *machine,
476-
const char *symbol_name)
486+
struct machine *machine)
477487
{
478488
size_t size;
479-
const char *filename, *mmap_name;
480-
char path[PATH_MAX];
489+
const char *mmap_name;
481490
char name_buff[PATH_MAX];
482491
struct map *map;
492+
struct kmap *kmap;
483493
int err;
484494
/*
485495
* We should get this from /sys/kernel/sections/.text, but till that is
486496
* available use this, and after it is use this as a fallback for older
487497
* kernels.
488498
*/
489-
struct process_symbol_args args = { .name = symbol_name, };
490499
union perf_event *event = zalloc((sizeof(event->mmap) +
491500
machine->id_hdr_size));
492501
if (event == NULL) {
@@ -502,30 +511,19 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
502511
* see kernel/perf_event.c __perf_event_mmap
503512
*/
504513
event->header.misc = PERF_RECORD_MISC_KERNEL;
505-
filename = "/proc/kallsyms";
506514
} else {
507515
event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
508-
if (machine__is_default_guest(machine))
509-
filename = (char *) symbol_conf.default_guest_kallsyms;
510-
else {
511-
sprintf(path, "%s/proc/kallsyms", machine->root_dir);
512-
filename = path;
513-
}
514-
}
515-
516-
if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) {
517-
free(event);
518-
return -ENOENT;
519516
}
520517

521518
map = machine->vmlinux_maps[MAP__FUNCTION];
519+
kmap = map__kmap(map);
522520
size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
523-
"%s%s", mmap_name, symbol_name) + 1;
521+
"%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1;
524522
size = PERF_ALIGN(size, sizeof(u64));
525523
event->mmap.header.type = PERF_RECORD_MMAP;
526524
event->mmap.header.size = (sizeof(event->mmap) -
527525
(sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
528-
event->mmap.pgoff = args.start;
526+
event->mmap.pgoff = kmap->ref_reloc_sym->addr;
529527
event->mmap.start = map->start;
530528
event->mmap.len = map->end - event->mmap.start;
531529
event->mmap.pid = machine->pid;

tools/perf/util/event.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
214214
struct machine *machine, bool mmap_data);
215215
int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
216216
perf_event__handler_t process,
217-
struct machine *machine,
218-
const char *symbol_name);
217+
struct machine *machine);
219218

220219
int perf_event__synthesize_modules(struct perf_tool *tool,
221220
perf_event__handler_t process,
@@ -279,4 +278,7 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
279278
size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
280279
size_t perf_event__fprintf(union perf_event *event, FILE *fp);
281280

281+
u64 kallsyms__get_function_start(const char *kallsyms_filename,
282+
const char *symbol_name);
283+
282284
#endif /* __PERF_RECORD_H */

tools/perf/util/include/asm/hash.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#ifndef __ASM_GENERIC_HASH_H
2+
#define __ASM_GENERIC_HASH_H
3+
4+
/* Stub */
5+
6+
#endif /* __ASM_GENERIC_HASH_H */

tools/perf/util/machine.c

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -496,19 +496,22 @@ static int symbol__in_kernel(void *arg, const char *name,
496496
return 1;
497497
}
498498

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+
499508
/* Figure out the start address of kernel map from /proc/kallsyms */
500509
static u64 machine__get_kernel_start_addr(struct machine *machine)
501510
{
502-
const char *filename;
503-
char path[PATH_MAX];
511+
char filename[PATH_MAX];
504512
struct process_args args;
505513

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);
512515

513516
if (symbol__restricted_filename(filename, "/proc/kallsyms"))
514517
return 0;
@@ -829,9 +832,25 @@ static int machine__create_modules(struct machine *machine)
829832
return 0;
830833
}
831834

835+
const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
836+
832837
int machine__create_kernel_maps(struct machine *machine)
833838
{
834839
struct dso *kernel = machine__get_kernel(machine);
840+
char filename[PATH_MAX];
841+
const char *name;
842+
u64 addr = 0;
843+
int i;
844+
845+
machine__get_kallsyms_filename(machine, filename, PATH_MAX);
846+
847+
for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
848+
addr = kallsyms__get_function_start(filename, name);
849+
if (addr)
850+
break;
851+
}
852+
if (!addr)
853+
return -1;
835854

836855
if (kernel == NULL ||
837856
__machine__create_kernel_maps(machine, kernel) < 0)
@@ -850,6 +869,13 @@ int machine__create_kernel_maps(struct machine *machine)
850869
* Now that we have all the maps created, just set the ->end of them:
851870
*/
852871
map_groups__fixup_end(&machine->kmaps);
872+
873+
if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name,
874+
addr)) {
875+
machine__destroy_kernel_maps(machine);
876+
return -1;
877+
}
878+
853879
return 0;
854880
}
855881

tools/perf/util/machine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ union perf_event;
1818
#define HOST_KERNEL_ID (-1)
1919
#define DEFAULT_GUEST_KERNEL_ID (0)
2020

21+
extern const char *ref_reloc_sym_names[];
22+
2123
struct machine {
2224
struct rb_node rb_node;
2325
pid_t pid;

tools/perf/util/map.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ void map__init(struct map *map, enum map_type type,
3939
map->start = start;
4040
map->end = end;
4141
map->pgoff = pgoff;
42+
map->reloc = 0;
4243
map->dso = dso;
4344
map->map_ip = map__map_ip;
4445
map->unmap_ip = map__unmap_ip;
@@ -288,7 +289,7 @@ u64 map__rip_2objdump(struct map *map, u64 rip)
288289
if (map->dso->rel)
289290
return rip - map->pgoff;
290291

291-
return map->unmap_ip(map, rip);
292+
return map->unmap_ip(map, rip) - map->reloc;
292293
}
293294

294295
/**
@@ -311,7 +312,7 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
311312
if (map->dso->rel)
312313
return map->unmap_ip(map, ip + map->pgoff);
313314

314-
return ip;
315+
return ip + map->reloc;
315316
}
316317

317318
void map_groups__init(struct map_groups *mg)

tools/perf/util/map.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct map {
3636
bool erange_warned;
3737
u32 priv;
3838
u64 pgoff;
39+
u64 reloc;
3940
u32 maj, min; /* only valid for MMAP2 record */
4041
u64 ino; /* only valid for MMAP2 record */
4142
u64 ino_generation;/* only valid for MMAP2 record */

tools/perf/util/symbol-elf.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,8 @@ int dso__load_sym(struct dso *dso, struct map *map,
751751
if (strcmp(elf_name, kmap->ref_reloc_sym->name))
752752
continue;
753753
kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
754+
map->reloc = kmap->ref_reloc_sym->addr -
755+
kmap->ref_reloc_sym->unrelocated_addr;
754756
break;
755757
}
756758
}
@@ -922,6 +924,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
922924
(u64)shdr.sh_offset);
923925
sym.st_value -= shdr.sh_addr - shdr.sh_offset;
924926
}
927+
new_symbol:
925928
/*
926929
* We need to figure out if the object was created from C++ sources
927930
* DWARF DW_compile_unit has this, but we don't always have access
@@ -933,7 +936,6 @@ int dso__load_sym(struct dso *dso, struct map *map,
933936
if (demangled != NULL)
934937
elf_name = demangled;
935938
}
936-
new_symbol:
937939
f = symbol__new(sym.st_value, sym.st_size,
938940
GELF_ST_BIND(sym.st_info), elf_name);
939941
free(demangled);

0 commit comments

Comments
 (0)