Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1
  2#include <unistd.h>
  3#include <stdio.h>
  4#include <string.h>
  5#include <sys/types.h>
  6#include <sys/stat.h>
  7#include <fcntl.h>
  8#include <stdlib.h>
  9#include <linux/kernel.h>
 10
 11#include "vdso.h"
 12#include "util.h"
 13#include "symbol.h"
 14#include "linux/string.h"
 15
 16static bool vdso_found;
 17static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX";
 18
 19static int find_vdso_map(void **start, void **end)
 20{
 21	FILE *maps;
 22	char line[128];
 23	int found = 0;
 24
 25	maps = fopen("/proc/self/maps", "r");
 26	if (!maps) {
 27		pr_err("vdso: cannot open maps\n");
 28		return -1;
 29	}
 30
 31	while (!found && fgets(line, sizeof(line), maps)) {
 32		int m = -1;
 33
 34		/* We care only about private r-x mappings. */
 35		if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
 36				start, end, &m))
 37			continue;
 38		if (m < 0)
 39			continue;
 40
 41		if (!strncmp(&line[m], VDSO__MAP_NAME,
 42			     sizeof(VDSO__MAP_NAME) - 1))
 43			found = 1;
 44	}
 45
 46	fclose(maps);
 47	return !found;
 48}
 49
 50static char *get_file(void)
 51{
 52	char *vdso = NULL;
 53	char *buf = NULL;
 54	void *start, *end;
 55	size_t size;
 56	int fd;
 57
 58	if (vdso_found)
 59		return vdso_file;
 60
 61	if (find_vdso_map(&start, &end))
 62		return NULL;
 63
 64	size = end - start;
 65
 66	buf = memdup(start, size);
 67	if (!buf)
 68		return NULL;
 69
 70	fd = mkstemp(vdso_file);
 71	if (fd < 0)
 72		goto out;
 73
 74	if (size == (size_t) write(fd, buf, size))
 75		vdso = vdso_file;
 76
 77	close(fd);
 78
 79 out:
 80	free(buf);
 81
 82	vdso_found = (vdso != NULL);
 83	return vdso;
 84}
 85
 86void vdso__exit(void)
 87{
 88	if (vdso_found)
 89		unlink(vdso_file);
 90}
 91
 92struct dso *vdso__dso_findnew(struct list_head *head)
 93{
 94	struct dso *dso = dsos__find(head, VDSO__MAP_NAME, true);
 95
 96	if (!dso) {
 97		char *file;
 98
 99		file = get_file();
100		if (!file)
101			return NULL;
102
103		dso = dso__new(VDSO__MAP_NAME);
104		if (dso != NULL) {
105			dsos__add(head, dso);
106			dso__set_long_name(dso, file, false);
107		}
108	}
109
110	return dso;
111}