session.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. #define _FILE_OFFSET_BITS 64
  2. #include <linux/kernel.h>
  3. #include <byteswap.h>
  4. #include <unistd.h>
  5. #include <sys/types.h>
  6. #include "session.h"
  7. #include "sort.h"
  8. #include "util.h"
  9. static int perf_session__open(struct perf_session *self, bool force)
  10. {
  11. struct stat input_stat;
  12. self->fd = open(self->filename, O_RDONLY);
  13. if (self->fd < 0) {
  14. pr_err("failed to open file: %s", self->filename);
  15. if (!strcmp(self->filename, "perf.data"))
  16. pr_err(" (try 'perf record' first)");
  17. pr_err("\n");
  18. return -errno;
  19. }
  20. if (fstat(self->fd, &input_stat) < 0)
  21. goto out_close;
  22. if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
  23. pr_err("file %s not owned by current user or root\n",
  24. self->filename);
  25. goto out_close;
  26. }
  27. if (!input_stat.st_size) {
  28. pr_info("zero-sized file (%s), nothing to do!\n",
  29. self->filename);
  30. goto out_close;
  31. }
  32. if (perf_header__read(&self->header, self->fd) < 0) {
  33. pr_err("incompatible file format");
  34. goto out_close;
  35. }
  36. self->size = input_stat.st_size;
  37. return 0;
  38. out_close:
  39. close(self->fd);
  40. self->fd = -1;
  41. return -1;
  42. }
  43. static inline int perf_session__create_kernel_maps(struct perf_session *self)
  44. {
  45. return map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps);
  46. }
  47. struct perf_session *perf_session__new(const char *filename, int mode, bool force)
  48. {
  49. size_t len = filename ? strlen(filename) + 1 : 0;
  50. struct perf_session *self = zalloc(sizeof(*self) + len);
  51. if (self == NULL)
  52. goto out;
  53. if (perf_header__init(&self->header) < 0)
  54. goto out_free;
  55. memcpy(self->filename, filename, len);
  56. self->threads = RB_ROOT;
  57. self->last_match = NULL;
  58. self->mmap_window = 32;
  59. self->cwd = NULL;
  60. self->cwdlen = 0;
  61. self->unknown_events = 0;
  62. map_groups__init(&self->kmaps);
  63. if (mode == O_RDONLY) {
  64. if (perf_session__open(self, force) < 0)
  65. goto out_delete;
  66. } else if (mode == O_WRONLY) {
  67. /*
  68. * In O_RDONLY mode this will be performed when reading the
  69. * kernel MMAP event, in event__process_mmap().
  70. */
  71. if (perf_session__create_kernel_maps(self) < 0)
  72. goto out_delete;
  73. }
  74. self->sample_type = perf_header__sample_type(&self->header);
  75. out:
  76. return self;
  77. out_free:
  78. free(self);
  79. return NULL;
  80. out_delete:
  81. perf_session__delete(self);
  82. return NULL;
  83. }
  84. void perf_session__delete(struct perf_session *self)
  85. {
  86. perf_header__exit(&self->header);
  87. close(self->fd);
  88. free(self->cwd);
  89. free(self);
  90. }
  91. static bool symbol__match_parent_regex(struct symbol *sym)
  92. {
  93. if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
  94. return 1;
  95. return 0;
  96. }
  97. struct symbol **perf_session__resolve_callchain(struct perf_session *self,
  98. struct thread *thread,
  99. struct ip_callchain *chain,
  100. struct symbol **parent)
  101. {
  102. u8 cpumode = PERF_RECORD_MISC_USER;
  103. struct symbol **syms = NULL;
  104. unsigned int i;
  105. if (symbol_conf.use_callchain) {
  106. syms = calloc(chain->nr, sizeof(*syms));
  107. if (!syms) {
  108. fprintf(stderr, "Can't allocate memory for symbols\n");
  109. exit(-1);
  110. }
  111. }
  112. for (i = 0; i < chain->nr; i++) {
  113. u64 ip = chain->ips[i];
  114. struct addr_location al;
  115. if (ip >= PERF_CONTEXT_MAX) {
  116. switch (ip) {
  117. case PERF_CONTEXT_HV:
  118. cpumode = PERF_RECORD_MISC_HYPERVISOR; break;
  119. case PERF_CONTEXT_KERNEL:
  120. cpumode = PERF_RECORD_MISC_KERNEL; break;
  121. case PERF_CONTEXT_USER:
  122. cpumode = PERF_RECORD_MISC_USER; break;
  123. default:
  124. break;
  125. }
  126. continue;
  127. }
  128. thread__find_addr_location(thread, self, cpumode,
  129. MAP__FUNCTION, ip, &al, NULL);
  130. if (al.sym != NULL) {
  131. if (sort__has_parent && !*parent &&
  132. symbol__match_parent_regex(al.sym))
  133. *parent = al.sym;
  134. if (!symbol_conf.use_callchain)
  135. break;
  136. syms[i] = al.sym;
  137. }
  138. }
  139. return syms;
  140. }
  141. static int process_event_stub(event_t *event __used,
  142. struct perf_session *session __used)
  143. {
  144. dump_printf(": unhandled!\n");
  145. return 0;
  146. }
  147. static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
  148. {
  149. if (handler->sample == NULL)
  150. handler->sample = process_event_stub;
  151. if (handler->mmap == NULL)
  152. handler->mmap = process_event_stub;
  153. if (handler->comm == NULL)
  154. handler->comm = process_event_stub;
  155. if (handler->fork == NULL)
  156. handler->fork = process_event_stub;
  157. if (handler->exit == NULL)
  158. handler->exit = process_event_stub;
  159. if (handler->lost == NULL)
  160. handler->lost = process_event_stub;
  161. if (handler->read == NULL)
  162. handler->read = process_event_stub;
  163. if (handler->throttle == NULL)
  164. handler->throttle = process_event_stub;
  165. if (handler->unthrottle == NULL)
  166. handler->unthrottle = process_event_stub;
  167. }
  168. static const char *event__name[] = {
  169. [0] = "TOTAL",
  170. [PERF_RECORD_MMAP] = "MMAP",
  171. [PERF_RECORD_LOST] = "LOST",
  172. [PERF_RECORD_COMM] = "COMM",
  173. [PERF_RECORD_EXIT] = "EXIT",
  174. [PERF_RECORD_THROTTLE] = "THROTTLE",
  175. [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE",
  176. [PERF_RECORD_FORK] = "FORK",
  177. [PERF_RECORD_READ] = "READ",
  178. [PERF_RECORD_SAMPLE] = "SAMPLE",
  179. };
  180. unsigned long event__total[PERF_RECORD_MAX];
  181. void event__print_totals(void)
  182. {
  183. int i;
  184. for (i = 0; i < PERF_RECORD_MAX; ++i)
  185. pr_info("%10s events: %10ld\n",
  186. event__name[i], event__total[i]);
  187. }
  188. void mem_bswap_64(void *src, int byte_size)
  189. {
  190. u64 *m = src;
  191. while (byte_size > 0) {
  192. *m = bswap_64(*m);
  193. byte_size -= sizeof(u64);
  194. ++m;
  195. }
  196. }
  197. static void event__all64_swap(event_t *self)
  198. {
  199. struct perf_event_header *hdr = &self->header;
  200. mem_bswap_64(hdr + 1, self->header.size - sizeof(*hdr));
  201. }
  202. static void event__comm_swap(event_t *self)
  203. {
  204. self->comm.pid = bswap_32(self->comm.pid);
  205. self->comm.tid = bswap_32(self->comm.tid);
  206. }
  207. static void event__mmap_swap(event_t *self)
  208. {
  209. self->mmap.pid = bswap_32(self->mmap.pid);
  210. self->mmap.tid = bswap_32(self->mmap.tid);
  211. self->mmap.start = bswap_64(self->mmap.start);
  212. self->mmap.len = bswap_64(self->mmap.len);
  213. self->mmap.pgoff = bswap_64(self->mmap.pgoff);
  214. }
  215. static void event__task_swap(event_t *self)
  216. {
  217. self->fork.pid = bswap_32(self->fork.pid);
  218. self->fork.tid = bswap_32(self->fork.tid);
  219. self->fork.ppid = bswap_32(self->fork.ppid);
  220. self->fork.ptid = bswap_32(self->fork.ptid);
  221. self->fork.time = bswap_64(self->fork.time);
  222. }
  223. static void event__read_swap(event_t *self)
  224. {
  225. self->read.pid = bswap_32(self->read.pid);
  226. self->read.tid = bswap_32(self->read.tid);
  227. self->read.value = bswap_64(self->read.value);
  228. self->read.time_enabled = bswap_64(self->read.time_enabled);
  229. self->read.time_running = bswap_64(self->read.time_running);
  230. self->read.id = bswap_64(self->read.id);
  231. }
  232. typedef void (*event__swap_op)(event_t *self);
  233. static event__swap_op event__swap_ops[] = {
  234. [PERF_RECORD_MMAP] = event__mmap_swap,
  235. [PERF_RECORD_COMM] = event__comm_swap,
  236. [PERF_RECORD_FORK] = event__task_swap,
  237. [PERF_RECORD_EXIT] = event__task_swap,
  238. [PERF_RECORD_LOST] = event__all64_swap,
  239. [PERF_RECORD_READ] = event__read_swap,
  240. [PERF_RECORD_SAMPLE] = event__all64_swap,
  241. [PERF_RECORD_MAX] = NULL,
  242. };
  243. static int perf_session__process_event(struct perf_session *self,
  244. event_t *event,
  245. struct perf_event_ops *ops,
  246. u64 offset, u64 head)
  247. {
  248. trace_event(event);
  249. if (event->header.type < PERF_RECORD_MAX) {
  250. dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
  251. offset + head, event->header.size,
  252. event__name[event->header.type]);
  253. ++event__total[0];
  254. ++event__total[event->header.type];
  255. }
  256. if (self->header.needs_swap && event__swap_ops[event->header.type])
  257. event__swap_ops[event->header.type](event);
  258. switch (event->header.type) {
  259. case PERF_RECORD_SAMPLE:
  260. return ops->sample(event, self);
  261. case PERF_RECORD_MMAP:
  262. return ops->mmap(event, self);
  263. case PERF_RECORD_COMM:
  264. return ops->comm(event, self);
  265. case PERF_RECORD_FORK:
  266. return ops->fork(event, self);
  267. case PERF_RECORD_EXIT:
  268. return ops->exit(event, self);
  269. case PERF_RECORD_LOST:
  270. return ops->lost(event, self);
  271. case PERF_RECORD_READ:
  272. return ops->read(event, self);
  273. case PERF_RECORD_THROTTLE:
  274. return ops->throttle(event, self);
  275. case PERF_RECORD_UNTHROTTLE:
  276. return ops->unthrottle(event, self);
  277. default:
  278. self->unknown_events++;
  279. return -1;
  280. }
  281. }
  282. void perf_event_header__bswap(struct perf_event_header *self)
  283. {
  284. self->type = bswap_32(self->type);
  285. self->misc = bswap_16(self->misc);
  286. self->size = bswap_16(self->size);
  287. }
  288. int perf_header__read_build_ids(struct perf_header *self,
  289. int input, u64 offset, u64 size)
  290. {
  291. struct build_id_event bev;
  292. char filename[PATH_MAX];
  293. u64 limit = offset + size;
  294. int err = -1;
  295. while (offset < limit) {
  296. struct dso *dso;
  297. ssize_t len;
  298. struct list_head *head = &dsos__user;
  299. if (read(input, &bev, sizeof(bev)) != sizeof(bev))
  300. goto out;
  301. if (self->needs_swap)
  302. perf_event_header__bswap(&bev.header);
  303. len = bev.header.size - sizeof(bev);
  304. if (read(input, filename, len) != len)
  305. goto out;
  306. if (bev.header.misc & PERF_RECORD_MISC_KERNEL)
  307. head = &dsos__kernel;
  308. dso = __dsos__findnew(head, filename);
  309. if (dso != NULL) {
  310. dso__set_build_id(dso, &bev.build_id);
  311. if (head == &dsos__kernel && filename[0] == '[')
  312. dso->kernel = 1;
  313. }
  314. offset += bev.header.size;
  315. }
  316. err = 0;
  317. out:
  318. return err;
  319. }
  320. static struct thread *perf_session__register_idle_thread(struct perf_session *self)
  321. {
  322. struct thread *thread = perf_session__findnew(self, 0);
  323. if (thread == NULL || thread__set_comm(thread, "swapper")) {
  324. pr_err("problem inserting idle task.\n");
  325. thread = NULL;
  326. }
  327. return thread;
  328. }
  329. int __perf_session__process_events(struct perf_session *self,
  330. u64 data_offset, u64 data_size,
  331. u64 file_size, struct perf_event_ops *ops)
  332. {
  333. int err, mmap_prot, mmap_flags;
  334. u64 head, shift;
  335. u64 offset = 0;
  336. size_t page_size;
  337. event_t *event;
  338. uint32_t size;
  339. char *buf;
  340. perf_event_ops__fill_defaults(ops);
  341. page_size = sysconf(_SC_PAGESIZE);
  342. head = data_offset;
  343. shift = page_size * (head / page_size);
  344. offset += shift;
  345. head -= shift;
  346. mmap_prot = PROT_READ;
  347. mmap_flags = MAP_SHARED;
  348. if (self->header.needs_swap) {
  349. mmap_prot |= PROT_WRITE;
  350. mmap_flags = MAP_PRIVATE;
  351. }
  352. remap:
  353. buf = mmap(NULL, page_size * self->mmap_window, mmap_prot,
  354. mmap_flags, self->fd, offset);
  355. if (buf == MAP_FAILED) {
  356. pr_err("failed to mmap file\n");
  357. err = -errno;
  358. goto out_err;
  359. }
  360. more:
  361. event = (event_t *)(buf + head);
  362. if (self->header.needs_swap)
  363. perf_event_header__bswap(&event->header);
  364. size = event->header.size;
  365. if (size == 0)
  366. size = 8;
  367. if (head + event->header.size >= page_size * self->mmap_window) {
  368. int munmap_ret;
  369. shift = page_size * (head / page_size);
  370. munmap_ret = munmap(buf, page_size * self->mmap_window);
  371. assert(munmap_ret == 0);
  372. offset += shift;
  373. head -= shift;
  374. goto remap;
  375. }
  376. size = event->header.size;
  377. dump_printf("\n%#Lx [%#x]: event: %d\n",
  378. offset + head, event->header.size, event->header.type);
  379. if (size == 0 ||
  380. perf_session__process_event(self, event, ops, offset, head) < 0) {
  381. dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n",
  382. offset + head, event->header.size,
  383. event->header.type);
  384. /*
  385. * assume we lost track of the stream, check alignment, and
  386. * increment a single u64 in the hope to catch on again 'soon'.
  387. */
  388. if (unlikely(head & 7))
  389. head &= ~7ULL;
  390. size = 8;
  391. }
  392. head += size;
  393. if (offset + head >= data_offset + data_size)
  394. goto done;
  395. if (offset + head < file_size)
  396. goto more;
  397. done:
  398. err = 0;
  399. out_err:
  400. return err;
  401. }
  402. int perf_session__process_events(struct perf_session *self,
  403. struct perf_event_ops *ops)
  404. {
  405. int err;
  406. if (perf_session__register_idle_thread(self) == NULL)
  407. return -ENOMEM;
  408. if (!symbol_conf.full_paths) {
  409. char bf[PATH_MAX];
  410. if (getcwd(bf, sizeof(bf)) == NULL) {
  411. err = -errno;
  412. out_getcwd_err:
  413. pr_err("failed to get the current directory\n");
  414. goto out_err;
  415. }
  416. self->cwd = strdup(bf);
  417. if (self->cwd == NULL) {
  418. err = -ENOMEM;
  419. goto out_getcwd_err;
  420. }
  421. self->cwdlen = strlen(self->cwd);
  422. }
  423. err = __perf_session__process_events(self, self->header.data_offset,
  424. self->header.data_size,
  425. self->size, ops);
  426. out_err:
  427. return err;
  428. }
  429. bool perf_session__has_traces(struct perf_session *self, const char *msg)
  430. {
  431. if (!(self->sample_type & PERF_SAMPLE_RAW)) {
  432. pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg);
  433. return false;
  434. }
  435. return true;
  436. }
  437. int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self,
  438. const char *symbol_name,
  439. u64 addr)
  440. {
  441. char *bracket;
  442. enum map_type i;
  443. self->ref_reloc_sym.name = strdup(symbol_name);
  444. if (self->ref_reloc_sym.name == NULL)
  445. return -ENOMEM;
  446. bracket = strchr(self->ref_reloc_sym.name, ']');
  447. if (bracket)
  448. *bracket = '\0';
  449. self->ref_reloc_sym.addr = addr;
  450. for (i = 0; i < MAP__NR_TYPES; ++i) {
  451. struct kmap *kmap = map__kmap(self->vmlinux_maps[i]);
  452. kmap->ref_reloc_sym = &self->ref_reloc_sym;
  453. }
  454. return 0;
  455. }
  456. static u64 map__reloc_map_ip(struct map *map, u64 ip)
  457. {
  458. return ip + (s64)map->pgoff;
  459. }
  460. static u64 map__reloc_unmap_ip(struct map *map, u64 ip)
  461. {
  462. return ip - (s64)map->pgoff;
  463. }
  464. void map__reloc_vmlinux(struct map *self)
  465. {
  466. struct kmap *kmap = map__kmap(self);
  467. s64 reloc;
  468. if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->unrelocated_addr)
  469. return;
  470. reloc = (kmap->ref_reloc_sym->unrelocated_addr -
  471. kmap->ref_reloc_sym->addr);
  472. if (!reloc)
  473. return;
  474. self->map_ip = map__reloc_map_ip;
  475. self->unmap_ip = map__reloc_unmap_ip;
  476. self->pgoff = reloc;
  477. }