perf tools: Back [vdso] DSO with real data
Storing data for VDSO shared object, because we need it for the post
unwind processing.
The VDSO shared object is same for all process on a running system, so
it makes no difference when we store it inside the tracer - perf.
When [vdso] map memory is hit, we retrieve [vdso] DSO image and store it
into temporary file.
During the build-id processing phase, the [vdso] DSO image is stored in
build-id db, and build-id reference is made inside perf.data. The
build-id vdso file object is called '[vdso]'. We don't use temporary
file name which gets removed when record is finished.
During report phase the vdso build-id object is treated as any other
build-id DSO object.
Adding following API for vdso object:
bool is_vdso_map(const char *filename)
- returns true if the filename matches vdso map name
struct dso *vdso__dso_findnew(struct list_head *head)
- find/create proper vdso DSO object
vdso__exit(void)
- removes temporary VDSO image if there's any
This change makes backtrace dwarf post unwind possible from [vdso] maps.
Following output is current report of [vdso] sample dwarf backtrace:
# Overhead Command Shared Object Symbol
# ........ ....... ................. .............................
#
99.52% ex [vdso] [.] 0x00007fff3ace89af
|
--- 0x7fff3ace89af
Following output is new report of [vdso] sample dwarf backtrace:
# Overhead Command Shared Object Symbol
# ........ ....... ................. .............................
#
99.52% ex [vdso] [.] 0x00000000000009af
|
--- 0x7fff3ace89af
main
__libc_start_main
_start
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1347295819-23177-5-git-send-email-jolsa@redhat.com
[ committer note: s/ALIGN/PERF_ALIGN/g to cope with the android build changes ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 974e758..87996ca 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -21,6 +21,7 @@
#include "debug.h"
#include "cpumap.h"
#include "pmu.h"
+#include "vdso.h"
static bool no_buildid_cache = false;
@@ -207,6 +208,29 @@
continue; \
else
+static int write_buildid(char *name, size_t name_len, u8 *build_id,
+ pid_t pid, u16 misc, int fd)
+{
+ int err;
+ struct build_id_event b;
+ size_t len;
+
+ len = name_len + 1;
+ len = PERF_ALIGN(len, NAME_ALIGN);
+
+ memset(&b, 0, sizeof(b));
+ memcpy(&b.build_id, build_id, BUILD_ID_SIZE);
+ b.pid = pid;
+ b.header.misc = misc;
+ b.header.size = sizeof(b) + len;
+
+ err = do_write(fd, &b, sizeof(b));
+ if (err < 0)
+ return err;
+
+ return write_padded(fd, name, name_len + 1, len);
+}
+
static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
u16 misc, int fd)
{
@@ -214,24 +238,23 @@
dsos__for_each_with_build_id(pos, head) {
int err;
- struct build_id_event b;
- size_t len;
+ char *name;
+ size_t name_len;
if (!pos->hit)
continue;
- len = pos->long_name_len + 1;
- len = PERF_ALIGN(len, NAME_ALIGN);
- memset(&b, 0, sizeof(b));
- memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
- b.pid = pid;
- b.header.misc = misc;
- b.header.size = sizeof(b) + len;
- err = do_write(fd, &b, sizeof(b));
- if (err < 0)
- return err;
- err = write_padded(fd, pos->long_name,
- pos->long_name_len + 1, len);
- if (err < 0)
+
+ if (is_vdso_map(pos->short_name)) {
+ name = (char *) VDSO__MAP_NAME;
+ name_len = sizeof(VDSO__MAP_NAME) + 1;
+ } else {
+ name = pos->long_name;
+ name_len = pos->long_name_len + 1;
+ }
+
+ err = write_buildid(name, name_len, pos->build_id,
+ pid, misc, fd);
+ if (err)
return err;
}
@@ -277,19 +300,20 @@
}
int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
- const char *name, bool is_kallsyms)
+ const char *name, bool is_kallsyms, bool is_vdso)
{
const size_t size = PATH_MAX;
char *realname, *filename = zalloc(size),
*linkname = zalloc(size), *targetname;
int len, err = -1;
+ bool slash = is_kallsyms || is_vdso;
if (is_kallsyms) {
if (symbol_conf.kptr_restrict) {
pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
return 0;
}
- realname = (char *)name;
+ realname = (char *) name;
} else
realname = realpath(name, NULL);
@@ -297,7 +321,8 @@
goto out_free;
len = scnprintf(filename, size, "%s%s%s",
- debugdir, is_kallsyms ? "/" : "", realname);
+ debugdir, slash ? "/" : "",
+ is_vdso ? VDSO__MAP_NAME : realname);
if (mkdir_p(filename, 0755))
goto out_free;
@@ -333,13 +358,14 @@
static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
const char *name, const char *debugdir,
- bool is_kallsyms)
+ bool is_kallsyms, bool is_vdso)
{
char sbuild_id[BUILD_ID_SIZE * 2 + 1];
build_id__sprintf(build_id, build_id_size, sbuild_id);
- return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms);
+ return build_id_cache__add_s(sbuild_id, debugdir, name,
+ is_kallsyms, is_vdso);
}
int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
@@ -383,9 +409,11 @@
static int dso__cache_build_id(struct dso *dso, const char *debugdir)
{
bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
+ bool is_vdso = is_vdso_map(dso->short_name);
return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
- dso->long_name, debugdir, is_kallsyms);
+ dso->long_name, debugdir,
+ is_kallsyms, is_vdso);
}
static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)