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 16 static bool vdso_found; 17 static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX"; 18 19 static 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 50 static 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 86 void vdso__exit(void) 87 { 88 if (vdso_found) 89 unlink(vdso_file); 90 } 91 92 struct dso *vdso__dso_findnew(struct list_head *head) 93 { 94 struct dso *dso = dsos__find(head, VDSO__MAP_NAME); 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); 107 } 108 } 109 110 return dso; 111 } 112