Commit 6c6804fb authored by Andrew Lutomirski's avatar Andrew Lutomirski Committed by Arnaldo Carvalho de Melo

perf symbols: Fix vsyscall symbol lookup

Perf can't currently trace into the vsyscall page.  It looks like it was
meant to work.

Tested on 2.6.38 and today's -git.

The bug is easy to reproduce.  Compile this:

int main()
{
	int i;
	struct timespec t;
	for(i = 0; i < 10000000; i++)
		clock_gettime(CLOCK_MONOTONIC, &t);
	return 0;
}

and run it through perf record; perf report.  The top entry shows
"[unknown]" and you can't zoom in.

It looks like there are two issues.  The first is a that a test for user
mode executing in kernel space is backwards.  (That's the first hunk
below).  The second (I think) is that something's wrong with the code
that generates lots of little struct dso objects for different sections
-- when it runs on vmlinux it results in bogus long_name values which
cause objdump to fail.

Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
LPU-Reference: <AANLkTikxSw5+wJZUWNz++nL7mgivCh_Zf=2Kq6=f9Ce_@mail.gmail.com>
Signed-off-by: default avatarAndy Lutomirski <luto@mit.edu>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 18bcd0c8
...@@ -710,7 +710,7 @@ void thread__find_addr_map(struct thread *self, ...@@ -710,7 +710,7 @@ void thread__find_addr_map(struct thread *self,
* in the whole kernel symbol list. * in the whole kernel symbol list.
*/ */
if ((long long)al->addr < 0 && if ((long long)al->addr < 0 &&
cpumode == PERF_RECORD_MISC_KERNEL && cpumode == PERF_RECORD_MISC_USER &&
machine && mg != &machine->kmaps) { machine && mg != &machine->kmaps) {
mg = &machine->kmaps; mg = &machine->kmaps;
goto try_again; goto try_again;
......
...@@ -1196,6 +1196,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, ...@@ -1196,6 +1196,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
if (curr_dso == NULL) if (curr_dso == NULL)
goto out_elf_end; goto out_elf_end;
curr_dso->kernel = self->kernel; curr_dso->kernel = self->kernel;
curr_dso->long_name = self->long_name;
curr_dso->long_name_len = self->long_name_len;
curr_map = map__new2(start, curr_dso, curr_map = map__new2(start, curr_dso,
map->type); map->type);
if (curr_map == NULL) { if (curr_map == NULL) {
...@@ -1842,6 +1844,7 @@ int dso__load_vmlinux(struct dso *self, struct map *map, ...@@ -1842,6 +1844,7 @@ int dso__load_vmlinux(struct dso *self, struct map *map,
if (fd < 0) if (fd < 0)
return -1; return -1;
dso__set_long_name(self, (char *)vmlinux);
dso__set_loaded(self, map->type); dso__set_loaded(self, map->type);
err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0); err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0);
close(fd); close(fd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment