session.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #include <linux/kernel.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. #include "session.h"
  5. #include "sort.h"
  6. #include "util.h"
  7. static int perf_session__open(struct perf_session *self, bool force)
  8. {
  9. struct stat input_stat;
  10. self->fd = open(self->filename, O_RDONLY);
  11. if (self->fd < 0) {
  12. pr_err("failed to open file: %s", self->filename);
  13. if (!strcmp(self->filename, "perf.data"))
  14. pr_err(" (try 'perf record' first)");
  15. pr_err("\n");
  16. return -errno;
  17. }
  18. if (fstat(self->fd, &input_stat) < 0)
  19. goto out_close;
  20. if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
  21. pr_err("file %s not owned by current user or root\n",
  22. self->filename);
  23. goto out_close;
  24. }
  25. if (!input_stat.st_size) {
  26. pr_info("zero-sized file (%s), nothing to do!\n",
  27. self->filename);
  28. goto out_close;
  29. }
  30. if (perf_header__read(&self->header, self->fd) < 0) {
  31. pr_err("incompatible file format");
  32. goto out_close;
  33. }
  34. self->size = input_stat.st_size;
  35. return 0;
  36. out_close:
  37. close(self->fd);
  38. self->fd = -1;
  39. return -1;
  40. }
  41. struct perf_session *perf_session__new(const char *filename, int mode,
  42. bool force, struct symbol_conf *conf)
  43. {
  44. size_t len = filename ? strlen(filename) + 1 : 0;
  45. struct perf_session *self = zalloc(sizeof(*self) + len);
  46. if (self == NULL)
  47. goto out;
  48. if (perf_header__init(&self->header) < 0)
  49. goto out_free;
  50. memcpy(self->filename, filename, len);
  51. self->threads = RB_ROOT;
  52. self->last_match = NULL;
  53. self->mmap_window = 32;
  54. self->cwd = NULL;
  55. self->cwdlen = 0;
  56. map_groups__init(&self->kmaps);
  57. if (perf_session__create_kernel_maps(self, conf) < 0)
  58. goto out_delete;
  59. if (mode == O_RDONLY && perf_session__open(self, force) < 0)
  60. goto out_delete;
  61. out:
  62. return self;
  63. out_free:
  64. free(self);
  65. return NULL;
  66. out_delete:
  67. perf_session__delete(self);
  68. return NULL;
  69. }
  70. void perf_session__delete(struct perf_session *self)
  71. {
  72. perf_header__exit(&self->header);
  73. close(self->fd);
  74. free(self->cwd);
  75. free(self);
  76. }
  77. static bool symbol__match_parent_regex(struct symbol *sym)
  78. {
  79. if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
  80. return 1;
  81. return 0;
  82. }
  83. struct symbol **perf_session__resolve_callchain(struct perf_session *self,
  84. struct thread *thread,
  85. struct ip_callchain *chain,
  86. struct symbol **parent)
  87. {
  88. u8 cpumode = PERF_RECORD_MISC_USER;
  89. struct symbol **syms = NULL;
  90. unsigned int i;
  91. if (self->use_callchain) {
  92. syms = calloc(chain->nr, sizeof(*syms));
  93. if (!syms) {
  94. fprintf(stderr, "Can't allocate memory for symbols\n");
  95. exit(-1);
  96. }
  97. }
  98. for (i = 0; i < chain->nr; i++) {
  99. u64 ip = chain->ips[i];
  100. struct addr_location al;
  101. if (ip >= PERF_CONTEXT_MAX) {
  102. switch (ip) {
  103. case PERF_CONTEXT_HV:
  104. cpumode = PERF_RECORD_MISC_HYPERVISOR; break;
  105. case PERF_CONTEXT_KERNEL:
  106. cpumode = PERF_RECORD_MISC_KERNEL; break;
  107. case PERF_CONTEXT_USER:
  108. cpumode = PERF_RECORD_MISC_USER; break;
  109. default:
  110. break;
  111. }
  112. continue;
  113. }
  114. thread__find_addr_location(thread, self, cpumode,
  115. MAP__FUNCTION, ip, &al, NULL);
  116. if (al.sym != NULL) {
  117. if (sort__has_parent && !*parent &&
  118. symbol__match_parent_regex(al.sym))
  119. *parent = al.sym;
  120. if (!self->use_callchain)
  121. break;
  122. syms[i] = al.sym;
  123. }
  124. }
  125. return syms;
  126. }