forked from Minki/linux
7dbf4dcfe2
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>
112 lines
1.7 KiB
C
112 lines
1.7 KiB
C
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <linux/kernel.h>
|
|
|
|
#include "vdso.h"
|
|
#include "util.h"
|
|
#include "symbol.h"
|
|
#include "linux/string.h"
|
|
|
|
static bool vdso_found;
|
|
static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX";
|
|
|
|
static int find_vdso_map(void **start, void **end)
|
|
{
|
|
FILE *maps;
|
|
char line[128];
|
|
int found = 0;
|
|
|
|
maps = fopen("/proc/self/maps", "r");
|
|
if (!maps) {
|
|
pr_err("vdso: cannot open maps\n");
|
|
return -1;
|
|
}
|
|
|
|
while (!found && fgets(line, sizeof(line), maps)) {
|
|
int m = -1;
|
|
|
|
/* We care only about private r-x mappings. */
|
|
if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
|
|
start, end, &m))
|
|
continue;
|
|
if (m < 0)
|
|
continue;
|
|
|
|
if (!strncmp(&line[m], VDSO__MAP_NAME,
|
|
sizeof(VDSO__MAP_NAME) - 1))
|
|
found = 1;
|
|
}
|
|
|
|
fclose(maps);
|
|
return !found;
|
|
}
|
|
|
|
static char *get_file(void)
|
|
{
|
|
char *vdso = NULL;
|
|
char *buf = NULL;
|
|
void *start, *end;
|
|
size_t size;
|
|
int fd;
|
|
|
|
if (vdso_found)
|
|
return vdso_file;
|
|
|
|
if (find_vdso_map(&start, &end))
|
|
return NULL;
|
|
|
|
size = end - start;
|
|
|
|
buf = memdup(start, size);
|
|
if (!buf)
|
|
return NULL;
|
|
|
|
fd = mkstemp(vdso_file);
|
|
if (fd < 0)
|
|
goto out;
|
|
|
|
if (size == (size_t) write(fd, buf, size))
|
|
vdso = vdso_file;
|
|
|
|
close(fd);
|
|
|
|
out:
|
|
free(buf);
|
|
|
|
vdso_found = (vdso != NULL);
|
|
return vdso;
|
|
}
|
|
|
|
void vdso__exit(void)
|
|
{
|
|
if (vdso_found)
|
|
unlink(vdso_file);
|
|
}
|
|
|
|
struct dso *vdso__dso_findnew(struct list_head *head)
|
|
{
|
|
struct dso *dso = dsos__find(head, VDSO__MAP_NAME);
|
|
|
|
if (!dso) {
|
|
char *file;
|
|
|
|
file = get_file();
|
|
if (!file)
|
|
return NULL;
|
|
|
|
dso = dso__new(VDSO__MAP_NAME);
|
|
if (dso != NULL) {
|
|
dsos__add(head, dso);
|
|
dso__set_long_name(dso, file);
|
|
}
|
|
}
|
|
|
|
return dso;
|
|
}
|