From: Arnaldo Carvalho de Melo <[email protected]>
Hi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit 0d4dd797564cddc1f71ab0b239e9ea50ddd40b2a:
perf/doc: Remove mention of non-existent set_perf_event_pending() from design.txt (2014-01-26 09:37:48 +0100)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux tags/perf-urgent-for-mingo
for you to fetch changes up to d3b70220292c40d3b499797fd2f33f608fc35edb:
perf buildid-cache: Check relocation when checking for existing kcore (2014-01-31 17:21:54 -0300)
----------------------------------------------------------------
perf/urgent fixes:
. 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]>
----------------------------------------------------------------
Adrian Hunter (9):
perf symbols: Fix symbol annotation for relocated kernel
perf tools: Add kallsyms__get_function_start()
perf machine: Add machine__get_kallsyms_filename()
perf machine: Set up ref_reloc_sym in machine__create_kernel_maps()
perf record: Get ref_reloc_sym from kernel map
perf symbols: Prevent the use of kcore if the kernel has moved
perf tests: No need to set up ref_reloc_sym
perf tools: Adjust kallsyms for relocated kernel
perf buildid-cache: Check relocation when checking for existing kcore
Avi Kivity (1):
perf tools: Demangle kernel and kernel module symbols too
Francesco Fusco (1):
perf tools: Fix include for non x86 architectures
Peter Zijlstra (1):
perf tools: Fix AAAAARGH64 memory barriers
tools/perf/builtin-buildid-cache.c | 33 ++++++++++++++++---
tools/perf/builtin-record.c | 10 ++----
tools/perf/perf.h | 4 +--
tools/perf/tests/vmlinux-kallsyms.c | 10 ------
tools/perf/util/event.c | 36 ++++++++++----------
tools/perf/util/event.h | 6 ++--
tools/perf/util/include/asm/hash.h | 6 ++++
tools/perf/util/machine.c | 42 +++++++++++++++++++-----
tools/perf/util/machine.h | 2 ++
tools/perf/util/map.c | 5 +--
tools/perf/util/map.h | 1 +
tools/perf/util/symbol-elf.c | 4 ++-
tools/perf/util/symbol.c | 65 +++++++++++++++++++++++++++++++++----
13 files changed, 162 insertions(+), 62 deletions(-)
create mode 100644 tools/perf/util/include/asm/hash.h
From: Francesco Fusco <[email protected]>
Commit 71ae8aac ("lib: introduce arch optimized hash library") added an
include to <linux/hash.h> for setting up an architecture specific fast
hash.
Since perf includes directly the non-uapi kernel header, it cannot find
<asm/hash.h> on non-x86 and thus prevents perf to be compiled on every
architecture other than x86.
The problem is the inclusion of <asm/hash.h> in hash.h that results in
the following error originating from util/evlist.c:
fatal error: asm/hash.h: No such file or directory
This commit simply adds an empty <asm/hash.h> stub/file to fix the
compile issue on non-x86 architectures.
As perf does not use any of these new functions, it fixes the
compilation and therefore seems to be the most appropriate solution to
go with.
Signed-off-by: Francesco Fusco <[email protected]>
Link: http://lkml.kernel.org/r/2cf8143aad65a6aa6fe30325ef8a65847141afa2.1390829373.git.ffusco@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/include/asm/hash.h | 6 ++++++
1 file changed, 6 insertions(+)
create mode 100644 tools/perf/util/include/asm/hash.h
diff --git a/tools/perf/util/include/asm/hash.h b/tools/perf/util/include/asm/hash.h
new file mode 100644
index 000000000000..d82b170bb216
--- /dev/null
+++ b/tools/perf/util/include/asm/hash.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_GENERIC_HASH_H
+#define __ASM_GENERIC_HASH_H
+
+/* Stub */
+
+#endif /* __ASM_GENERIC_HASH_H */
--
1.8.1.4
From: Peter Zijlstra <[email protected]>
Someone got the load and store barriers mixed up for AAAAARGH64. Turn
them the right side up.
Reported-by: Will Deacon <[email protected]>
Signed-off-by: Peter Zijlstra <[email protected]>
Fixes: a94d342b9cb0 ("tools/perf: Add required memory barriers")
Cc: Ingo Molnar <[email protected]>
Cc: Will Deacon <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/perf.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 7daa806d9050..e84fa26bc1be 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -100,8 +100,8 @@
#ifdef __aarch64__
#define mb() asm volatile("dmb ish" ::: "memory")
-#define wmb() asm volatile("dmb ishld" ::: "memory")
-#define rmb() asm volatile("dmb ishst" ::: "memory")
+#define wmb() asm volatile("dmb ishst" ::: "memory")
+#define rmb() asm volatile("dmb ishld" ::: "memory")
#define cpu_relax() asm volatile("yield" ::: "memory")
#endif
--
1.8.1.4
From: Avi Kivity <[email protected]>
Some kernels contain C++ code, and thus their symbols need to be
demangled. This allows 'perf kvm top' to generate readable output.
Signed-off-by: Avi Kivity <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/26f71bf5bf7ee1408e3f1a803556d5df18223ef1.1390420726.git.avi@cloudius-systems.com
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/symbol-elf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 759456728703..8f12f0f5101d 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -922,6 +922,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
(u64)shdr.sh_offset);
sym.st_value -= shdr.sh_addr - shdr.sh_offset;
}
+new_symbol:
/*
* We need to figure out if the object was created from C++ sources
* DWARF DW_compile_unit has this, but we don't always have access
@@ -933,7 +934,6 @@ int dso__load_sym(struct dso *dso, struct map *map,
if (demangled != NULL)
elf_name = demangled;
}
-new_symbol:
f = symbol__new(sym.st_value, sym.st_size,
GELF_ST_BIND(sym.st_info), elf_name);
free(demangled);
--
1.8.1.4
From: Adrian Hunter <[email protected]>
Separate out the logic used to find the start address of the reference
symbol used to track kernel relocation. kallsyms__get_function_start()
is used in subsequent patches.
Signed-off-by: Adrian Hunter <[email protected]>
Tested-by: Jiri Olsa <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/event.c | 18 +++++++++++++++---
tools/perf/util/event.h | 3 +++
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 1fc1c2f04772..17476df5c7b2 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -470,6 +470,17 @@ static int find_symbol_cb(void *arg, const char *name, char type,
return 1;
}
+u64 kallsyms__get_function_start(const char *kallsyms_filename,
+ const char *symbol_name)
+{
+ struct process_symbol_args args = { .name = symbol_name, };
+
+ if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0)
+ return 0;
+
+ return args.start;
+}
+
int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
perf_event__handler_t process,
struct machine *machine,
@@ -480,13 +491,13 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
char path[PATH_MAX];
char name_buff[PATH_MAX];
struct map *map;
+ u64 start;
int err;
/*
* We should get this from /sys/kernel/sections/.text, but till that is
* available use this, and after it is use this as a fallback for older
* kernels.
*/
- struct process_symbol_args args = { .name = symbol_name, };
union perf_event *event = zalloc((sizeof(event->mmap) +
machine->id_hdr_size));
if (event == NULL) {
@@ -513,7 +524,8 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
}
}
- if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) {
+ start = kallsyms__get_function_start(filename, symbol_name);
+ if (!start) {
free(event);
return -ENOENT;
}
@@ -525,7 +537,7 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
event->mmap.header.type = PERF_RECORD_MMAP;
event->mmap.header.size = (sizeof(event->mmap) -
(sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
- event->mmap.pgoff = args.start;
+ event->mmap.pgoff = start;
event->mmap.start = map->start;
event->mmap.len = map->end - event->mmap.start;
event->mmap.pid = machine->pid;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index faf6e219be21..66a0c0392863 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -279,4 +279,7 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
size_t perf_event__fprintf(union perf_event *event, FILE *fp);
+u64 kallsyms__get_function_start(const char *kallsyms_filename,
+ const char *symbol_name);
+
#endif /* __PERF_RECORD_H */
--
1.8.1.4
From: Adrian Hunter <[email protected]>
The ref_reloc_sym is always needed for the kernel map in order to check
for relocation. Consequently set it up when the kernel map is created.
Otherwise it was only being set up by 'perf record'.
Signed-off-by: Adrian Hunter <[email protected]>
Tested-by: Jiri Olsa <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/machine.c | 23 +++++++++++++++++++++++
tools/perf/util/machine.h | 2 ++
2 files changed, 25 insertions(+)
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 290c2e6d4001..c872991e0f65 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -832,9 +832,25 @@ static int machine__create_modules(struct machine *machine)
return 0;
}
+const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
+
int machine__create_kernel_maps(struct machine *machine)
{
struct dso *kernel = machine__get_kernel(machine);
+ char filename[PATH_MAX];
+ const char *name;
+ u64 addr = 0;
+ int i;
+
+ machine__get_kallsyms_filename(machine, filename, PATH_MAX);
+
+ for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
+ addr = kallsyms__get_function_start(filename, name);
+ if (addr)
+ break;
+ }
+ if (!addr)
+ return -1;
if (kernel == NULL ||
__machine__create_kernel_maps(machine, kernel) < 0)
@@ -853,6 +869,13 @@ int machine__create_kernel_maps(struct machine *machine)
* Now that we have all the maps created, just set the ->end of them:
*/
map_groups__fixup_end(&machine->kmaps);
+
+ if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name,
+ addr)) {
+ machine__destroy_kernel_maps(machine);
+ return -1;
+ }
+
return 0;
}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 477133015440..f77e91e483dc 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -18,6 +18,8 @@ union perf_event;
#define HOST_KERNEL_ID (-1)
#define DEFAULT_GUEST_KERNEL_ID (0)
+extern const char *ref_reloc_sym_names[];
+
struct machine {
struct rb_node rb_node;
pid_t pid;
--
1.8.1.4
From: Adrian Hunter <[email protected]>
Kernel maps map memory addresses to file offsets.
For symbol annotation, objdump needs the object VMA addresses. For an
unrelocated kernel, that is the same as the memory address.
The addresses passed to objdump for symbol annotation did not take into
account kernel relocation.
This patch fixes that.
Reported-by: Linus Torvalds <[email protected]>
Signed-off-by: Adrian Hunter <[email protected]>
Tested-by: Jiri Olsa <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/map.c | 5 +++--
tools/perf/util/map.h | 1 +
tools/perf/util/symbol-elf.c | 2 ++
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 3b97513f0e77..39cd2d0faff6 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -39,6 +39,7 @@ void map__init(struct map *map, enum map_type type,
map->start = start;
map->end = end;
map->pgoff = pgoff;
+ map->reloc = 0;
map->dso = dso;
map->map_ip = map__map_ip;
map->unmap_ip = map__unmap_ip;
@@ -288,7 +289,7 @@ u64 map__rip_2objdump(struct map *map, u64 rip)
if (map->dso->rel)
return rip - map->pgoff;
- return map->unmap_ip(map, rip);
+ return map->unmap_ip(map, rip) - map->reloc;
}
/**
@@ -311,7 +312,7 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
if (map->dso->rel)
return map->unmap_ip(map, ip + map->pgoff);
- return ip;
+ return ip + map->reloc;
}
void map_groups__init(struct map_groups *mg)
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 18068c6b71c1..257e513205ce 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -36,6 +36,7 @@ struct map {
bool erange_warned;
u32 priv;
u64 pgoff;
+ u64 reloc;
u32 maj, min; /* only valid for MMAP2 record */
u64 ino; /* only valid for MMAP2 record */
u64 ino_generation;/* only valid for MMAP2 record */
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 8f12f0f5101d..3e9f336740fa 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -751,6 +751,8 @@ int dso__load_sym(struct dso *dso, struct map *map,
if (strcmp(elf_name, kmap->ref_reloc_sym->name))
continue;
kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
+ map->reloc = kmap->ref_reloc_sym->addr -
+ kmap->ref_reloc_sym->unrelocated_addr;
break;
}
}
--
1.8.1.4
From: Adrian Hunter <[email protected]>
Now that ref_reloc_sym is set up by machine__create_kernel_maps(), the
"vmlinux symtab matches kallsyms" test does have to do it.
Signed-off-by: Adrian Hunter <[email protected]>
Tested-by: Jiri Olsa <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/tests/vmlinux-kallsyms.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index 2bd13edcbc17..3d9088003a5b 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -26,7 +26,6 @@ int test__vmlinux_matches_kallsyms(void)
struct map *kallsyms_map, *vmlinux_map;
struct machine kallsyms, vmlinux;
enum map_type type = MAP__FUNCTION;
- struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };
u64 mem_start, mem_end;
/*
@@ -70,14 +69,6 @@ int test__vmlinux_matches_kallsyms(void)
*/
kallsyms_map = machine__kernel_map(&kallsyms, type);
- sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL);
- if (sym == NULL) {
- pr_debug("dso__find_symbol_by_name ");
- goto out;
- }
-
- ref_reloc_sym.addr = UM(sym->start);
-
/*
* Step 5:
*
@@ -89,7 +80,6 @@ int test__vmlinux_matches_kallsyms(void)
}
vmlinux_map = machine__kernel_map(&vmlinux, type);
- map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym;
/*
* Step 6:
--
1.8.1.4
From: Adrian Hunter <[email protected]>
Now that ref_reloc_sym is set up when the kernel map is created,
'perf record' does not need to pass the symbol names to
perf_event__synthesize_kernel_mmap() which can read the values needed
from ref_reloc_sym directly.
Signed-off-by: Adrian Hunter <[email protected]>
Tested-by: Jiri Olsa <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-record.c | 10 ++--------
tools/perf/util/event.c | 26 ++++++--------------------
tools/perf/util/event.h | 3 +--
3 files changed, 9 insertions(+), 30 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 3c394bf16fa8..af47531b82ec 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -287,10 +287,7 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
* have no _text sometimes.
*/
err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
- machine, "_text");
- if (err < 0)
- err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
- machine, "_stext");
+ machine);
if (err < 0)
pr_err("Couldn't record guest kernel [%d]'s reference"
" relocation symbol.\n", machine->pid);
@@ -457,10 +454,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
}
err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
- machine, "_text");
- if (err < 0)
- err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
- machine, "_stext");
+ machine);
if (err < 0)
pr_err("Couldn't record kernel reference relocation symbol\n"
"Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 17476df5c7b2..b0f3ca850e9e 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -483,15 +483,13 @@ u64 kallsyms__get_function_start(const char *kallsyms_filename,
int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
perf_event__handler_t process,
- struct machine *machine,
- const char *symbol_name)
+ struct machine *machine)
{
size_t size;
- const char *filename, *mmap_name;
- char path[PATH_MAX];
+ const char *mmap_name;
char name_buff[PATH_MAX];
struct map *map;
- u64 start;
+ struct kmap *kmap;
int err;
/*
* We should get this from /sys/kernel/sections/.text, but till that is
@@ -513,31 +511,19 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
* see kernel/perf_event.c __perf_event_mmap
*/
event->header.misc = PERF_RECORD_MISC_KERNEL;
- filename = "/proc/kallsyms";
} else {
event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
- if (machine__is_default_guest(machine))
- filename = (char *) symbol_conf.default_guest_kallsyms;
- else {
- sprintf(path, "%s/proc/kallsyms", machine->root_dir);
- filename = path;
- }
- }
-
- start = kallsyms__get_function_start(filename, symbol_name);
- if (!start) {
- free(event);
- return -ENOENT;
}
map = machine->vmlinux_maps[MAP__FUNCTION];
+ kmap = map__kmap(map);
size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
- "%s%s", mmap_name, symbol_name) + 1;
+ "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1;
size = PERF_ALIGN(size, sizeof(u64));
event->mmap.header.type = PERF_RECORD_MMAP;
event->mmap.header.size = (sizeof(event->mmap) -
(sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
- event->mmap.pgoff = start;
+ event->mmap.pgoff = kmap->ref_reloc_sym->addr;
event->mmap.start = map->start;
event->mmap.len = map->end - event->mmap.start;
event->mmap.pid = machine->pid;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 66a0c0392863..851fa06f4a42 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -214,8 +214,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
struct machine *machine, bool mmap_data);
int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
perf_event__handler_t process,
- struct machine *machine,
- const char *symbol_name);
+ struct machine *machine);
int perf_event__synthesize_modules(struct perf_tool *tool,
perf_event__handler_t process,
--
1.8.1.4
From: Adrian Hunter <[email protected]>
perf buildid-cache does not make another copy of kcore if the buildid
and modules match an existing copy.
That does not take into account the possibility that the kernel has been
relocated.
Extend the check to check if the reference relocation symbol matches
too, otherwise do make a copy.
Signed-off-by: Adrian Hunter <[email protected]>
Tested-by: Jiri Olsa <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-buildid-cache.c | 33 +++++++++++++++++++++++++++++----
1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index cfede86161d8..b22dbb16f877 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -63,11 +63,35 @@ static int build_id_cache__kcore_dir(char *dir, size_t sz)
return 0;
}
+static bool same_kallsyms_reloc(const char *from_dir, char *to_dir)
+{
+ char from[PATH_MAX];
+ char to[PATH_MAX];
+ const char *name;
+ u64 addr1 = 0, addr2 = 0;
+ int i;
+
+ scnprintf(from, sizeof(from), "%s/kallsyms", from_dir);
+ scnprintf(to, sizeof(to), "%s/kallsyms", to_dir);
+
+ for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
+ addr1 = kallsyms__get_function_start(from, name);
+ if (addr1)
+ break;
+ }
+
+ if (name)
+ addr2 = kallsyms__get_function_start(to, name);
+
+ return addr1 == addr2;
+}
+
static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
size_t to_dir_sz)
{
char from[PATH_MAX];
char to[PATH_MAX];
+ char to_subdir[PATH_MAX];
struct dirent *dent;
int ret = -1;
DIR *d;
@@ -86,10 +110,11 @@ static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
continue;
scnprintf(to, sizeof(to), "%s/%s/modules", to_dir,
dent->d_name);
- if (!compare_proc_modules(from, to)) {
- scnprintf(to, sizeof(to), "%s/%s", to_dir,
- dent->d_name);
- strlcpy(to_dir, to, to_dir_sz);
+ scnprintf(to_subdir, sizeof(to_subdir), "%s/%s",
+ to_dir, dent->d_name);
+ if (!compare_proc_modules(from, to) &&
+ same_kallsyms_reloc(from_dir, to_subdir)) {
+ strlcpy(to_dir, to_subdir, to_dir_sz);
ret = 0;
break;
}
--
1.8.1.4
From: Adrian Hunter <[email protected]>
Use of kcore is predicated upon it matching the recorded data. If the
kernel has been relocated at boot time (i.e. since the data was
recorded) then do not use kcore.
Note that it is possible to make a copy of kcore at the time the data is
recorded using 'perf buildid-cache'. Then the perf tools will use the
copy because it does match the data.
Signed-off-by: Adrian Hunter <[email protected]>
Tested-by: Jiri Olsa <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/symbol.c | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 39ce9adbaaf0..4ac1f871ec27 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -976,6 +976,23 @@ static int validate_kcore_modules(const char *kallsyms_filename,
return 0;
}
+static int validate_kcore_addresses(const char *kallsyms_filename,
+ struct map *map)
+{
+ struct kmap *kmap = map__kmap(map);
+
+ if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) {
+ u64 start;
+
+ start = kallsyms__get_function_start(kallsyms_filename,
+ kmap->ref_reloc_sym->name);
+ if (start != kmap->ref_reloc_sym->addr)
+ return -EINVAL;
+ }
+
+ return validate_kcore_modules(kallsyms_filename, map);
+}
+
struct kcore_mapfn_data {
struct dso *dso;
enum map_type type;
@@ -1019,8 +1036,8 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
kallsyms_filename))
return -EINVAL;
- /* All modules must be present at their original addresses */
- if (validate_kcore_modules(kallsyms_filename, map))
+ /* Modules and kernel must be present at their original addresses */
+ if (validate_kcore_addresses(kallsyms_filename, map))
return -EINVAL;
md.dso = dso;
@@ -1424,7 +1441,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
continue;
scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
"%s/%s/kallsyms", dir, dent->d_name);
- if (!validate_kcore_modules(kallsyms_filename, map)) {
+ if (!validate_kcore_addresses(kallsyms_filename, map)) {
strlcpy(dir, kallsyms_filename, dir_sz);
ret = 0;
break;
@@ -1479,7 +1496,7 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
if (fd != -1) {
close(fd);
/* If module maps match go with /proc/kallsyms */
- if (!validate_kcore_modules("/proc/kallsyms", map))
+ if (!validate_kcore_addresses("/proc/kallsyms", map))
goto proc_kallsyms;
}
--
1.8.1.4
From: Adrian Hunter <[email protected]>
If the kernel is relocated at boot time, kallsyms will not match data
recorded previously.
That does not matter for modules because they are corrected anyway. It
also does not matter if vmlinux is being used for symbols. But if perf
tools has only kallsyms then the symbols will not match.
Fix by applying the delta gained by comparing the old and current
addresses of the relocation reference symbol.
Signed-off-by: Adrian Hunter <[email protected]>
Tested-by: Jiri Olsa <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/symbol.c | 40 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 4ac1f871ec27..a9d758a3b371 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -627,7 +627,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
* kernel range is broken in several maps, named [kernel].N, as we don't have
* the original ELF section names vmlinux have.
*/
-static int dso__split_kallsyms(struct dso *dso, struct map *map,
+static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
symbol_filter_t filter)
{
struct map_groups *kmaps = map__kmap(map)->kmaps;
@@ -692,6 +692,12 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map,
char dso_name[PATH_MAX];
struct dso *ndso;
+ if (delta) {
+ /* Kernel was relocated at boot time */
+ pos->start -= delta;
+ pos->end -= delta;
+ }
+
if (count == 0) {
curr_map = map;
goto filter_symbol;
@@ -721,6 +727,10 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map,
curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
map_groups__insert(kmaps, curr_map);
++kernel_range;
+ } else if (delta) {
+ /* Kernel was relocated at boot time */
+ pos->start -= delta;
+ pos->end -= delta;
}
filter_symbol:
if (filter && filter(curr_map, pos)) {
@@ -1130,15 +1140,41 @@ out_err:
return -EINVAL;
}
+/*
+ * If the kernel is relocated at boot time, kallsyms won't match. Compute the
+ * delta based on the relocation reference symbol.
+ */
+static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
+{
+ struct kmap *kmap = map__kmap(map);
+ u64 addr;
+
+ if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
+ return 0;
+
+ addr = kallsyms__get_function_start(filename,
+ kmap->ref_reloc_sym->name);
+ if (!addr)
+ return -1;
+
+ *delta = addr - kmap->ref_reloc_sym->addr;
+ return 0;
+}
+
int dso__load_kallsyms(struct dso *dso, const char *filename,
struct map *map, symbol_filter_t filter)
{
+ u64 delta = 0;
+
if (symbol__restricted_filename(filename, "/proc/kallsyms"))
return -1;
if (dso__load_all_kallsyms(dso, filename, map) < 0)
return -1;
+ if (kallsyms__delta(map, filename, &delta))
+ return -1;
+
symbols__fixup_duplicate(&dso->symbols[map->type]);
symbols__fixup_end(&dso->symbols[map->type]);
@@ -1150,7 +1186,7 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
if (!dso__load_kcore(dso, map, filename))
return dso__split_kallsyms_for_kcore(dso, map, filter);
else
- return dso__split_kallsyms(dso, map, filter);
+ return dso__split_kallsyms(dso, map, delta, filter);
}
static int dso__load_perf_map(struct dso *dso, struct map *map,
--
1.8.1.4
From: Adrian Hunter <[email protected]>
Separate out the logic used to make the kallsyms full path name for a
machine. It will be reused in a subsequent patch.
Signed-off-by: Adrian Hunter <[email protected]>
Tested-by: Jiri Olsa <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/machine.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index ded74590b92f..290c2e6d4001 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -496,19 +496,22 @@ static int symbol__in_kernel(void *arg, const char *name,
return 1;
}
+static void machine__get_kallsyms_filename(struct machine *machine, char *buf,
+ size_t bufsz)
+{
+ if (machine__is_default_guest(machine))
+ scnprintf(buf, bufsz, "%s", symbol_conf.default_guest_kallsyms);
+ else
+ scnprintf(buf, bufsz, "%s/proc/kallsyms", machine->root_dir);
+}
+
/* 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];
+ char filename[PATH_MAX];
struct process_args args;
- if (machine__is_default_guest(machine))
- filename = (char *)symbol_conf.default_guest_kallsyms;
- else {
- sprintf(path, "%s/proc/kallsyms", machine->root_dir);
- filename = path;
- }
+ machine__get_kallsyms_filename(machine, filename, PATH_MAX);
if (symbol__restricted_filename(filename, "/proc/kallsyms"))
return 0;
--
1.8.1.4
* Arnaldo Carvalho de Melo <[email protected]> wrote:
> From: Arnaldo Carvalho de Melo <[email protected]>
>
> Hi Ingo,
>
> Please consider pulling,
>
> - Arnaldo
>
> The following changes since commit 0d4dd797564cddc1f71ab0b239e9ea50ddd40b2a:
>
> perf/doc: Remove mention of non-existent set_perf_event_pending() from design.txt (2014-01-26 09:37:48 +0100)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux tags/perf-urgent-for-mingo
>
> for you to fetch changes up to d3b70220292c40d3b499797fd2f33f608fc35edb:
>
> perf buildid-cache: Check relocation when checking for existing kcore (2014-01-31 17:21:54 -0300)
>
> ----------------------------------------------------------------
> perf/urgent fixes:
>
> . 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]>
>
> ----------------------------------------------------------------
> Adrian Hunter (9):
> perf symbols: Fix symbol annotation for relocated kernel
> perf tools: Add kallsyms__get_function_start()
> perf machine: Add machine__get_kallsyms_filename()
> perf machine: Set up ref_reloc_sym in machine__create_kernel_maps()
> perf record: Get ref_reloc_sym from kernel map
> perf symbols: Prevent the use of kcore if the kernel has moved
> perf tests: No need to set up ref_reloc_sym
> perf tools: Adjust kallsyms for relocated kernel
> perf buildid-cache: Check relocation when checking for existing kcore
>
> Avi Kivity (1):
> perf tools: Demangle kernel and kernel module symbols too
>
> Francesco Fusco (1):
> perf tools: Fix include for non x86 architectures
>
> Peter Zijlstra (1):
> perf tools: Fix AAAAARGH64 memory barriers
>
> tools/perf/builtin-buildid-cache.c | 33 ++++++++++++++++---
> tools/perf/builtin-record.c | 10 ++----
> tools/perf/perf.h | 4 +--
> tools/perf/tests/vmlinux-kallsyms.c | 10 ------
> tools/perf/util/event.c | 36 ++++++++++----------
> tools/perf/util/event.h | 6 ++--
> tools/perf/util/include/asm/hash.h | 6 ++++
> tools/perf/util/machine.c | 42 +++++++++++++++++++-----
> tools/perf/util/machine.h | 2 ++
> tools/perf/util/map.c | 5 +--
> tools/perf/util/map.h | 1 +
> tools/perf/util/symbol-elf.c | 4 ++-
> tools/perf/util/symbol.c | 65 +++++++++++++++++++++++++++++++++----
> 13 files changed, 162 insertions(+), 62 deletions(-)
> create mode 100644 tools/perf/util/include/asm/hash.h
Pulled, thanks a lot Arnaldo!
Ingo