Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 323808
b: refs/heads/master
c: 7dbf4dc
h: refs/heads/master
v: v3
  • Loading branch information
Jiri Olsa authored and Arnaldo Carvalho de Melo committed Sep 11, 2012
1 parent 358bb72 commit b7c1534
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1c4be9ff5933e5c0f033ea98169cd89e22c90900
refs/heads/master: 7dbf4dcfe2987c35c2c4675cd7ae1b6006979176
2 changes: 2 additions & 0 deletions trunk/tools/perf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ LIB_H += util/intlist.h
LIB_H += util/perf_regs.h
LIB_H += util/unwind.h
LIB_H += ui/helpline.h
LIB_H += util/vdso.h

LIB_OBJS += $(OUTPUT)util/abspath.o
LIB_OBJS += $(OUTPUT)util/alias.o
Expand Down Expand Up @@ -404,6 +405,7 @@ LIB_OBJS += $(OUTPUT)util/cgroup.o
LIB_OBJS += $(OUTPUT)util/target.o
LIB_OBJS += $(OUTPUT)util/rblist.o
LIB_OBJS += $(OUTPUT)util/intlist.o
LIB_OBJS += $(OUTPUT)util/vdso.o

LIB_OBJS += $(OUTPUT)ui/helpline.o
LIB_OBJS += $(OUTPUT)ui/hist.o
Expand Down
3 changes: 2 additions & 1 deletion trunk/tools/perf/builtin-buildid-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir)
}

build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
err = build_id_cache__add_s(sbuild_id, debugdir, filename, false);
err = build_id_cache__add_s(sbuild_id, debugdir, filename,
false, false);
if (verbose)
pr_info("Adding %s %s: %s\n", sbuild_id, filename,
err ? "FAIL" : "Ok");
Expand Down
70 changes: 49 additions & 21 deletions trunk/tools/perf/util/header.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "debug.h"
#include "cpumap.h"
#include "pmu.h"
#include "vdso.h"

static bool no_buildid_cache = false;

Expand Down Expand Up @@ -207,31 +208,53 @@ perf_header__set_cmdline(int argc, const char **argv)
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)
{
struct dso *pos;

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;
}

Expand Down Expand Up @@ -277,27 +300,29 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd)
}

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

if (realname == NULL || filename == NULL || linkname == NULL)
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;

Expand Down Expand Up @@ -333,13 +358,14 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,

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)
Expand Down Expand Up @@ -383,9 +409,11 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
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)
Expand Down
2 changes: 1 addition & 1 deletion trunk/tools/perf/util/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ int perf_header__process_sections(struct perf_header *header, int fd,
int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);

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);
int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);

int perf_event__synthesize_attr(struct perf_tool *tool,
Expand Down
12 changes: 9 additions & 3 deletions trunk/tools/perf/util/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "map.h"
#include "thread.h"
#include "strlist.h"
#include "vdso.h"

const char *map_type__name[MAP__NR_TYPES] = {
[MAP__FUNCTION] = "Functions",
Expand All @@ -23,7 +24,6 @@ static inline int is_anon_memory(const char *filename)
static inline int is_no_dso_memory(const char *filename)
{
return !strcmp(filename, "[stack]") ||
!strcmp(filename, "[vdso]") ||
!strcmp(filename, "[heap]");
}

Expand Down Expand Up @@ -52,17 +52,23 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
if (self != NULL) {
char newfilename[PATH_MAX];
struct dso *dso;
int anon, no_dso;
int anon, no_dso, vdso;

anon = is_anon_memory(filename);
vdso = is_vdso_map(filename);
no_dso = is_no_dso_memory(filename);

if (anon) {
snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
filename = newfilename;
}

dso = __dsos__findnew(dsos__list, filename);
if (vdso) {
pgoff = 0;
dso = vdso__dso_findnew(dsos__list);
} else
dso = __dsos__findnew(dsos__list, filename);

if (dso == NULL)
goto out_delete;

Expand Down
2 changes: 2 additions & 0 deletions trunk/tools/perf/util/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "event-parse.h"
#include "perf_regs.h"
#include "unwind.h"
#include "vdso.h"

static int perf_session__open(struct perf_session *self, bool force)
{
Expand Down Expand Up @@ -211,6 +212,7 @@ void perf_session__delete(struct perf_session *self)
machine__exit(&self->host_machine);
close(self->fd);
free(self);
vdso__exit();
}

void machine__remove_thread(struct machine *self, struct thread *th)
Expand Down
111 changes: 111 additions & 0 deletions trunk/tools/perf/util/vdso.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@

#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;
}
18 changes: 18 additions & 0 deletions trunk/tools/perf/util/vdso.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef __PERF_VDSO__
#define __PERF_VDSO__

#include <linux/types.h>
#include <string.h>
#include <stdbool.h>

#define VDSO__MAP_NAME "[vdso]"

static inline bool is_vdso_map(const char *filename)
{
return !strcmp(filename, VDSO__MAP_NAME);
}

struct dso *vdso__dso_findnew(struct list_head *head);
void vdso__exit(void);

#endif /* __PERF_VDSO__ */

0 comments on commit b7c1534

Please sign in to comment.