vdso.c 1.7 KB

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