builtin-report.c 21 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079
  1. /*
  2. * builtin-report.c
  3. *
  4. * Builtin report command: Analyze the perf.data input file,
  5. * look up and read DSOs and symbol information and display
  6. * a histogram of results, along various sorting keys.
  7. */
  8. #include "builtin.h"
  9. #include "util/util.h"
  10. #include "util/list.h"
  11. #include "util/cache.h"
  12. #include "util/rbtree.h"
  13. #include "util/symbol.h"
  14. #include "util/string.h"
  15. #include "perf.h"
  16. #include "util/parse-options.h"
  17. #include "util/parse-events.h"
  18. #define SHOW_KERNEL 1
  19. #define SHOW_USER 2
  20. #define SHOW_HV 4
  21. static char const *input_name = "perf.data";
  22. static char *vmlinux = NULL;
  23. static char *sort_order = "comm,dso";
  24. static int input;
  25. static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
  26. static int dump_trace = 0;
  27. #define dprintf(x...) do { if (dump_trace) printf(x); } while (0)
  28. static int verbose;
  29. static int full_paths;
  30. static unsigned long page_size;
  31. static unsigned long mmap_window = 32;
  32. const char *perf_event_names[] = {
  33. [PERF_EVENT_MMAP] = " PERF_EVENT_MMAP",
  34. [PERF_EVENT_MUNMAP] = " PERF_EVENT_MUNMAP",
  35. [PERF_EVENT_COMM] = " PERF_EVENT_COMM",
  36. };
  37. struct ip_event {
  38. struct perf_event_header header;
  39. __u64 ip;
  40. __u32 pid, tid;
  41. };
  42. struct mmap_event {
  43. struct perf_event_header header;
  44. __u32 pid, tid;
  45. __u64 start;
  46. __u64 len;
  47. __u64 pgoff;
  48. char filename[PATH_MAX];
  49. };
  50. struct comm_event {
  51. struct perf_event_header header;
  52. __u32 pid, tid;
  53. char comm[16];
  54. };
  55. typedef union event_union {
  56. struct perf_event_header header;
  57. struct ip_event ip;
  58. struct mmap_event mmap;
  59. struct comm_event comm;
  60. } event_t;
  61. static LIST_HEAD(dsos);
  62. static struct dso *kernel_dso;
  63. static void dsos__add(struct dso *dso)
  64. {
  65. list_add_tail(&dso->node, &dsos);
  66. }
  67. static struct dso *dsos__find(const char *name)
  68. {
  69. struct dso *pos;
  70. list_for_each_entry(pos, &dsos, node)
  71. if (strcmp(pos->name, name) == 0)
  72. return pos;
  73. return NULL;
  74. }
  75. static struct dso *dsos__findnew(const char *name)
  76. {
  77. struct dso *dso = dsos__find(name);
  78. int nr;
  79. if (dso)
  80. return dso;
  81. dso = dso__new(name, 0);
  82. if (!dso)
  83. goto out_delete_dso;
  84. nr = dso__load(dso, NULL);
  85. if (nr < 0) {
  86. fprintf(stderr, "Failed to open: %s\n", name);
  87. goto out_delete_dso;
  88. }
  89. if (!nr && verbose) {
  90. fprintf(stderr,
  91. "No symbols found in: %s, maybe install a debug package?\n",
  92. name);
  93. }
  94. dsos__add(dso);
  95. return dso;
  96. out_delete_dso:
  97. dso__delete(dso);
  98. return NULL;
  99. }
  100. static void dsos__fprintf(FILE *fp)
  101. {
  102. struct dso *pos;
  103. list_for_each_entry(pos, &dsos, node)
  104. dso__fprintf(pos, fp);
  105. }
  106. static int load_kernel(void)
  107. {
  108. int err;
  109. kernel_dso = dso__new("[kernel]", 0);
  110. if (!kernel_dso)
  111. return -1;
  112. err = dso__load_kernel(kernel_dso, vmlinux, NULL);
  113. if (err) {
  114. dso__delete(kernel_dso);
  115. kernel_dso = NULL;
  116. } else
  117. dsos__add(kernel_dso);
  118. return err;
  119. }
  120. static char __cwd[PATH_MAX];
  121. static char *cwd = __cwd;
  122. static int cwdlen;
  123. static int strcommon(const char *pathname)
  124. {
  125. int n = 0;
  126. while (pathname[n] == cwd[n] && n < cwdlen)
  127. ++n;
  128. return n;
  129. }
  130. struct map {
  131. struct list_head node;
  132. uint64_t start;
  133. uint64_t end;
  134. uint64_t pgoff;
  135. struct dso *dso;
  136. };
  137. static struct map *map__new(struct mmap_event *event)
  138. {
  139. struct map *self = malloc(sizeof(*self));
  140. if (self != NULL) {
  141. const char *filename = event->filename;
  142. char newfilename[PATH_MAX];
  143. if (cwd) {
  144. int n = strcommon(filename);
  145. if (n == cwdlen) {
  146. snprintf(newfilename, sizeof(newfilename),
  147. ".%s", filename + n);
  148. filename = newfilename;
  149. }
  150. }
  151. self->start = event->start;
  152. self->end = event->start + event->len;
  153. self->pgoff = event->pgoff;
  154. self->dso = dsos__findnew(filename);
  155. if (self->dso == NULL)
  156. goto out_delete;
  157. }
  158. return self;
  159. out_delete:
  160. free(self);
  161. return NULL;
  162. }
  163. struct thread;
  164. struct thread {
  165. struct rb_node rb_node;
  166. struct list_head maps;
  167. pid_t pid;
  168. char *comm;
  169. };
  170. static struct thread *thread__new(pid_t pid)
  171. {
  172. struct thread *self = malloc(sizeof(*self));
  173. if (self != NULL) {
  174. self->pid = pid;
  175. self->comm = malloc(32);
  176. if (self->comm)
  177. snprintf(self->comm, 32, ":%d", self->pid);
  178. INIT_LIST_HEAD(&self->maps);
  179. }
  180. return self;
  181. }
  182. static int thread__set_comm(struct thread *self, const char *comm)
  183. {
  184. if (self->comm)
  185. free(self->comm);
  186. self->comm = strdup(comm);
  187. return self->comm ? 0 : -ENOMEM;
  188. }
  189. static struct rb_root threads;
  190. static struct thread *last_match;
  191. static struct thread *threads__findnew(pid_t pid)
  192. {
  193. struct rb_node **p = &threads.rb_node;
  194. struct rb_node *parent = NULL;
  195. struct thread *th;
  196. /*
  197. * Font-end cache - PID lookups come in blocks,
  198. * so most of the time we dont have to look up
  199. * the full rbtree:
  200. */
  201. if (last_match && last_match->pid == pid)
  202. return last_match;
  203. while (*p != NULL) {
  204. parent = *p;
  205. th = rb_entry(parent, struct thread, rb_node);
  206. if (th->pid == pid) {
  207. last_match = th;
  208. return th;
  209. }
  210. if (pid < th->pid)
  211. p = &(*p)->rb_left;
  212. else
  213. p = &(*p)->rb_right;
  214. }
  215. th = thread__new(pid);
  216. if (th != NULL) {
  217. rb_link_node(&th->rb_node, parent, p);
  218. rb_insert_color(&th->rb_node, &threads);
  219. last_match = th;
  220. }
  221. return th;
  222. }
  223. static void thread__insert_map(struct thread *self, struct map *map)
  224. {
  225. list_add_tail(&map->node, &self->maps);
  226. }
  227. static struct map *thread__find_map(struct thread *self, uint64_t ip)
  228. {
  229. struct map *pos;
  230. if (self == NULL)
  231. return NULL;
  232. list_for_each_entry(pos, &self->maps, node)
  233. if (ip >= pos->start && ip <= pos->end)
  234. return pos;
  235. return NULL;
  236. }
  237. /*
  238. * histogram, sorted on item, collects counts
  239. */
  240. static struct rb_root hist;
  241. struct hist_entry {
  242. struct rb_node rb_node;
  243. struct thread *thread;
  244. struct map *map;
  245. struct dso *dso;
  246. struct symbol *sym;
  247. uint64_t ip;
  248. char level;
  249. uint32_t count;
  250. };
  251. /*
  252. * configurable sorting bits
  253. */
  254. struct sort_entry {
  255. struct list_head list;
  256. char *header;
  257. int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
  258. int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
  259. size_t (*print)(FILE *fp, struct hist_entry *);
  260. };
  261. /* --sort pid */
  262. static int64_t
  263. sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
  264. {
  265. return right->thread->pid - left->thread->pid;
  266. }
  267. static size_t
  268. sort__thread_print(FILE *fp, struct hist_entry *self)
  269. {
  270. return fprintf(fp, " %16s:%5d", self->thread->comm ?: "", self->thread->pid);
  271. }
  272. static struct sort_entry sort_thread = {
  273. .header = " Command: Pid ",
  274. .cmp = sort__thread_cmp,
  275. .print = sort__thread_print,
  276. };
  277. /* --sort comm */
  278. static int64_t
  279. sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
  280. {
  281. return right->thread->pid - left->thread->pid;
  282. }
  283. static int64_t
  284. sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
  285. {
  286. char *comm_l = left->thread->comm;
  287. char *comm_r = right->thread->comm;
  288. if (!comm_l || !comm_r) {
  289. if (!comm_l && !comm_r)
  290. return 0;
  291. else if (!comm_l)
  292. return -1;
  293. else
  294. return 1;
  295. }
  296. return strcmp(comm_l, comm_r);
  297. }
  298. static size_t
  299. sort__comm_print(FILE *fp, struct hist_entry *self)
  300. {
  301. return fprintf(fp, " %16s", self->thread->comm);
  302. }
  303. static struct sort_entry sort_comm = {
  304. .header = " Command",
  305. .cmp = sort__comm_cmp,
  306. .collapse = sort__comm_collapse,
  307. .print = sort__comm_print,
  308. };
  309. /* --sort dso */
  310. static int64_t
  311. sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
  312. {
  313. struct dso *dso_l = left->dso;
  314. struct dso *dso_r = right->dso;
  315. if (!dso_l || !dso_r) {
  316. if (!dso_l && !dso_r)
  317. return 0;
  318. else if (!dso_l)
  319. return -1;
  320. else
  321. return 1;
  322. }
  323. return strcmp(dso_l->name, dso_r->name);
  324. }
  325. static size_t
  326. sort__dso_print(FILE *fp, struct hist_entry *self)
  327. {
  328. if (self->dso)
  329. return fprintf(fp, " %-25s", self->dso->name);
  330. return fprintf(fp, " %016llx", (__u64)self->ip);
  331. }
  332. static struct sort_entry sort_dso = {
  333. .header = " Shared Object ",
  334. .cmp = sort__dso_cmp,
  335. .print = sort__dso_print,
  336. };
  337. /* --sort symbol */
  338. static int64_t
  339. sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
  340. {
  341. uint64_t ip_l, ip_r;
  342. if (left->sym == right->sym)
  343. return 0;
  344. ip_l = left->sym ? left->sym->start : left->ip;
  345. ip_r = right->sym ? right->sym->start : right->ip;
  346. return (int64_t)(ip_r - ip_l);
  347. }
  348. static size_t
  349. sort__sym_print(FILE *fp, struct hist_entry *self)
  350. {
  351. size_t ret = 0;
  352. if (verbose)
  353. ret += fprintf(fp, " %#018llx", (__u64)self->ip);
  354. if (self->dso)
  355. ret += fprintf(fp, " %s: ", self->dso->name);
  356. else
  357. ret += fprintf(fp, " %#016llx: ", (__u64)self->ip);
  358. if (self->sym)
  359. ret += fprintf(fp, "%s", self->sym->name);
  360. else
  361. ret += fprintf(fp, "%#016llx", (__u64)self->ip);
  362. return ret;
  363. }
  364. static struct sort_entry sort_sym = {
  365. .header = " Shared Object: Symbol",
  366. .cmp = sort__sym_cmp,
  367. .print = sort__sym_print,
  368. };
  369. static int sort__need_collapse = 0;
  370. struct sort_dimension {
  371. char *name;
  372. struct sort_entry *entry;
  373. int taken;
  374. };
  375. static struct sort_dimension sort_dimensions[] = {
  376. { .name = "pid", .entry = &sort_thread, },
  377. { .name = "comm", .entry = &sort_comm, },
  378. { .name = "dso", .entry = &sort_dso, },
  379. { .name = "symbol", .entry = &sort_sym, },
  380. };
  381. static LIST_HEAD(hist_entry__sort_list);
  382. static int sort_dimension__add(char *tok)
  383. {
  384. int i;
  385. for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
  386. struct sort_dimension *sd = &sort_dimensions[i];
  387. if (sd->taken)
  388. continue;
  389. if (strncasecmp(tok, sd->name, strlen(tok)))
  390. continue;
  391. if (sd->entry->collapse)
  392. sort__need_collapse = 1;
  393. list_add_tail(&sd->entry->list, &hist_entry__sort_list);
  394. sd->taken = 1;
  395. return 0;
  396. }
  397. return -ESRCH;
  398. }
  399. static int64_t
  400. hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
  401. {
  402. struct sort_entry *se;
  403. int64_t cmp = 0;
  404. list_for_each_entry(se, &hist_entry__sort_list, list) {
  405. cmp = se->cmp(left, right);
  406. if (cmp)
  407. break;
  408. }
  409. return cmp;
  410. }
  411. static int64_t
  412. hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
  413. {
  414. struct sort_entry *se;
  415. int64_t cmp = 0;
  416. list_for_each_entry(se, &hist_entry__sort_list, list) {
  417. int64_t (*f)(struct hist_entry *, struct hist_entry *);
  418. f = se->collapse ?: se->cmp;
  419. cmp = f(left, right);
  420. if (cmp)
  421. break;
  422. }
  423. return cmp;
  424. }
  425. static size_t
  426. hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
  427. {
  428. struct sort_entry *se;
  429. size_t ret;
  430. if (total_samples) {
  431. ret = fprintf(fp, " %6.2f%%",
  432. (self->count * 100.0) / total_samples);
  433. } else
  434. ret = fprintf(fp, "%12d ", self->count);
  435. list_for_each_entry(se, &hist_entry__sort_list, list)
  436. ret += se->print(fp, self);
  437. ret += fprintf(fp, "\n");
  438. return ret;
  439. }
  440. /*
  441. * collect histogram counts
  442. */
  443. static int
  444. hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
  445. struct symbol *sym, uint64_t ip, char level)
  446. {
  447. struct rb_node **p = &hist.rb_node;
  448. struct rb_node *parent = NULL;
  449. struct hist_entry *he;
  450. struct hist_entry entry = {
  451. .thread = thread,
  452. .map = map,
  453. .dso = dso,
  454. .sym = sym,
  455. .ip = ip,
  456. .level = level,
  457. .count = 1,
  458. };
  459. int cmp;
  460. while (*p != NULL) {
  461. parent = *p;
  462. he = rb_entry(parent, struct hist_entry, rb_node);
  463. cmp = hist_entry__cmp(&entry, he);
  464. if (!cmp) {
  465. he->count++;
  466. return 0;
  467. }
  468. if (cmp < 0)
  469. p = &(*p)->rb_left;
  470. else
  471. p = &(*p)->rb_right;
  472. }
  473. he = malloc(sizeof(*he));
  474. if (!he)
  475. return -ENOMEM;
  476. *he = entry;
  477. rb_link_node(&he->rb_node, parent, p);
  478. rb_insert_color(&he->rb_node, &hist);
  479. return 0;
  480. }
  481. static void hist_entry__free(struct hist_entry *he)
  482. {
  483. free(he);
  484. }
  485. /*
  486. * collapse the histogram
  487. */
  488. static struct rb_root collapse_hists;
  489. static void collapse__insert_entry(struct hist_entry *he)
  490. {
  491. struct rb_node **p = &collapse_hists.rb_node;
  492. struct rb_node *parent = NULL;
  493. struct hist_entry *iter;
  494. int64_t cmp;
  495. while (*p != NULL) {
  496. parent = *p;
  497. iter = rb_entry(parent, struct hist_entry, rb_node);
  498. cmp = hist_entry__collapse(iter, he);
  499. if (!cmp) {
  500. iter->count += he->count;
  501. hist_entry__free(he);
  502. return;
  503. }
  504. if (cmp < 0)
  505. p = &(*p)->rb_left;
  506. else
  507. p = &(*p)->rb_right;
  508. }
  509. rb_link_node(&he->rb_node, parent, p);
  510. rb_insert_color(&he->rb_node, &collapse_hists);
  511. }
  512. static void collapse__resort(void)
  513. {
  514. struct rb_node *next;
  515. struct hist_entry *n;
  516. if (!sort__need_collapse)
  517. return;
  518. next = rb_first(&hist);
  519. while (next) {
  520. n = rb_entry(next, struct hist_entry, rb_node);
  521. next = rb_next(&n->rb_node);
  522. rb_erase(&n->rb_node, &hist);
  523. collapse__insert_entry(n);
  524. }
  525. }
  526. /*
  527. * reverse the map, sort on count.
  528. */
  529. static struct rb_root output_hists;
  530. static void output__insert_entry(struct hist_entry *he)
  531. {
  532. struct rb_node **p = &output_hists.rb_node;
  533. struct rb_node *parent = NULL;
  534. struct hist_entry *iter;
  535. while (*p != NULL) {
  536. parent = *p;
  537. iter = rb_entry(parent, struct hist_entry, rb_node);
  538. if (he->count > iter->count)
  539. p = &(*p)->rb_left;
  540. else
  541. p = &(*p)->rb_right;
  542. }
  543. rb_link_node(&he->rb_node, parent, p);
  544. rb_insert_color(&he->rb_node, &output_hists);
  545. }
  546. static void output__resort(void)
  547. {
  548. struct rb_node *next;
  549. struct hist_entry *n;
  550. if (sort__need_collapse)
  551. next = rb_first(&collapse_hists);
  552. else
  553. next = rb_first(&hist);
  554. while (next) {
  555. n = rb_entry(next, struct hist_entry, rb_node);
  556. next = rb_next(&n->rb_node);
  557. rb_erase(&n->rb_node, &hist);
  558. output__insert_entry(n);
  559. }
  560. }
  561. static size_t output__fprintf(FILE *fp, uint64_t total_samples)
  562. {
  563. struct hist_entry *pos;
  564. struct sort_entry *se;
  565. struct rb_node *nd;
  566. size_t ret = 0;
  567. fprintf(fp, "#\n");
  568. fprintf(fp, "# Overhead");
  569. list_for_each_entry(se, &hist_entry__sort_list, list)
  570. fprintf(fp, " %s", se->header);
  571. fprintf(fp, "\n");
  572. fprintf(fp, "# ........");
  573. list_for_each_entry(se, &hist_entry__sort_list, list) {
  574. int i;
  575. fprintf(fp, " ");
  576. for (i = 0; i < strlen(se->header)-1; i++)
  577. fprintf(fp, ".");
  578. }
  579. fprintf(fp, "\n");
  580. fprintf(fp, "#\n");
  581. for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
  582. pos = rb_entry(nd, struct hist_entry, rb_node);
  583. ret += hist_entry__fprintf(fp, pos, total_samples);
  584. }
  585. return ret;
  586. }
  587. static void register_idle_thread(void)
  588. {
  589. struct thread *thread = threads__findnew(0);
  590. if (thread == NULL ||
  591. thread__set_comm(thread, "[idle]")) {
  592. fprintf(stderr, "problem inserting idle task.\n");
  593. exit(-1);
  594. }
  595. }
  596. static unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0;
  597. static int
  598. process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
  599. {
  600. char level;
  601. int show = 0;
  602. struct dso *dso = NULL;
  603. struct thread *thread = threads__findnew(event->ip.pid);
  604. uint64_t ip = event->ip.ip;
  605. struct map *map = NULL;
  606. dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
  607. (void *)(offset + head),
  608. (void *)(long)(event->header.size),
  609. event->header.misc,
  610. event->ip.pid,
  611. (void *)(long)ip);
  612. dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid);
  613. if (thread == NULL) {
  614. fprintf(stderr, "problem processing %d event, skipping it.\n",
  615. event->header.type);
  616. return -1;
  617. }
  618. if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
  619. show = SHOW_KERNEL;
  620. level = 'k';
  621. dso = kernel_dso;
  622. dprintf(" ...... dso: %s\n", dso->name);
  623. } else if (event->header.misc & PERF_EVENT_MISC_USER) {
  624. show = SHOW_USER;
  625. level = '.';
  626. map = thread__find_map(thread, ip);
  627. if (map != NULL) {
  628. dso = map->dso;
  629. ip -= map->start + map->pgoff;
  630. } else {
  631. /*
  632. * If this is outside of all known maps,
  633. * and is a negative address, try to look it
  634. * up in the kernel dso, as it might be a
  635. * vsyscall (which executes in user-mode):
  636. */
  637. if ((long long)ip < 0)
  638. dso = kernel_dso;
  639. }
  640. dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
  641. } else {
  642. show = SHOW_HV;
  643. level = 'H';
  644. dprintf(" ...... dso: [hypervisor]\n");
  645. }
  646. if (show & show_mask) {
  647. struct symbol *sym = dso__find_symbol(dso, ip);
  648. if (hist_entry__add(thread, map, dso, sym, ip, level)) {
  649. fprintf(stderr,
  650. "problem incrementing symbol count, skipping event\n");
  651. return -1;
  652. }
  653. }
  654. total++;
  655. return 0;
  656. }
  657. static int
  658. process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
  659. {
  660. struct thread *thread = threads__findnew(event->mmap.pid);
  661. struct map *map = map__new(&event->mmap);
  662. dprintf("%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n",
  663. (void *)(offset + head),
  664. (void *)(long)(event->header.size),
  665. (void *)(long)event->mmap.start,
  666. (void *)(long)event->mmap.len,
  667. (void *)(long)event->mmap.pgoff,
  668. event->mmap.filename);
  669. if (thread == NULL || map == NULL) {
  670. dprintf("problem processing PERF_EVENT_MMAP, skipping event.\n");
  671. return -1;
  672. }
  673. thread__insert_map(thread, map);
  674. total_mmap++;
  675. return 0;
  676. }
  677. static int
  678. process_comm_event(event_t *event, unsigned long offset, unsigned long head)
  679. {
  680. struct thread *thread = threads__findnew(event->comm.pid);
  681. dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n",
  682. (void *)(offset + head),
  683. (void *)(long)(event->header.size),
  684. event->comm.comm, event->comm.pid);
  685. if (thread == NULL ||
  686. thread__set_comm(thread, event->comm.comm)) {
  687. dprintf("problem processing PERF_EVENT_COMM, skipping event.\n");
  688. return -1;
  689. }
  690. total_comm++;
  691. return 0;
  692. }
  693. static int
  694. process_event(event_t *event, unsigned long offset, unsigned long head)
  695. {
  696. if (event->header.misc & PERF_EVENT_MISC_OVERFLOW)
  697. return process_overflow_event(event, offset, head);
  698. switch (event->header.type) {
  699. case PERF_EVENT_MMAP:
  700. return process_mmap_event(event, offset, head);
  701. case PERF_EVENT_COMM:
  702. return process_comm_event(event, offset, head);
  703. /*
  704. * We dont process them right now but they are fine:
  705. */
  706. case PERF_EVENT_MUNMAP:
  707. case PERF_EVENT_PERIOD:
  708. case PERF_EVENT_THROTTLE:
  709. case PERF_EVENT_UNTHROTTLE:
  710. return 0;
  711. default:
  712. return -1;
  713. }
  714. return 0;
  715. }
  716. static int __cmd_report(void)
  717. {
  718. int ret, rc = EXIT_FAILURE;
  719. unsigned long offset = 0;
  720. unsigned long head = 0;
  721. struct stat stat;
  722. event_t *event;
  723. uint32_t size;
  724. char *buf;
  725. register_idle_thread();
  726. input = open(input_name, O_RDONLY);
  727. if (input < 0) {
  728. perror("failed to open file");
  729. exit(-1);
  730. }
  731. ret = fstat(input, &stat);
  732. if (ret < 0) {
  733. perror("failed to stat file");
  734. exit(-1);
  735. }
  736. if (!stat.st_size) {
  737. fprintf(stderr, "zero-sized file, nothing to do!\n");
  738. exit(0);
  739. }
  740. if (load_kernel() < 0) {
  741. perror("failed to load kernel symbols");
  742. return EXIT_FAILURE;
  743. }
  744. if (!full_paths) {
  745. if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
  746. perror("failed to get the current directory");
  747. return EXIT_FAILURE;
  748. }
  749. cwdlen = strlen(cwd);
  750. } else {
  751. cwd = NULL;
  752. cwdlen = 0;
  753. }
  754. remap:
  755. buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
  756. MAP_SHARED, input, offset);
  757. if (buf == MAP_FAILED) {
  758. perror("failed to mmap file");
  759. exit(-1);
  760. }
  761. more:
  762. event = (event_t *)(buf + head);
  763. size = event->header.size;
  764. if (!size)
  765. size = 8;
  766. if (head + event->header.size >= page_size * mmap_window) {
  767. unsigned long shift = page_size * (head / page_size);
  768. int ret;
  769. ret = munmap(buf, page_size * mmap_window);
  770. assert(ret == 0);
  771. offset += shift;
  772. head -= shift;
  773. goto remap;
  774. }
  775. size = event->header.size;
  776. if (!size || process_event(event, offset, head) < 0) {
  777. dprintf("%p [%p]: skipping unknown header type: %d\n",
  778. (void *)(offset + head),
  779. (void *)(long)(event->header.size),
  780. event->header.type);
  781. total_unknown++;
  782. /*
  783. * assume we lost track of the stream, check alignment, and
  784. * increment a single u64 in the hope to catch on again 'soon'.
  785. */
  786. if (unlikely(head & 7))
  787. head &= ~7ULL;
  788. size = 8;
  789. }
  790. head += size;
  791. if (offset + head < stat.st_size)
  792. goto more;
  793. rc = EXIT_SUCCESS;
  794. close(input);
  795. dprintf(" IP events: %10ld\n", total);
  796. dprintf(" mmap events: %10ld\n", total_mmap);
  797. dprintf(" comm events: %10ld\n", total_comm);
  798. dprintf(" unknown events: %10ld\n", total_unknown);
  799. if (dump_trace)
  800. return 0;
  801. if (verbose >= 2)
  802. dsos__fprintf(stdout);
  803. collapse__resort();
  804. output__resort();
  805. output__fprintf(stdout, total);
  806. return rc;
  807. }
  808. static const char * const report_usage[] = {
  809. "perf report [<options>] <command>",
  810. NULL
  811. };
  812. static const struct option options[] = {
  813. OPT_STRING('i', "input", &input_name, "file",
  814. "input file name"),
  815. OPT_BOOLEAN('v', "verbose", &verbose,
  816. "be more verbose (show symbol address, etc)"),
  817. OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
  818. "dump raw trace in ASCII"),
  819. OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
  820. OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
  821. "sort by key(s): pid, comm, dso, symbol. Default: pid,symbol"),
  822. OPT_BOOLEAN('P', "full-paths", &full_paths,
  823. "Don't shorten the pathnames taking into account the cwd"),
  824. OPT_END()
  825. };
  826. static void setup_sorting(void)
  827. {
  828. char *tmp, *tok, *str = strdup(sort_order);
  829. for (tok = strtok_r(str, ", ", &tmp);
  830. tok; tok = strtok_r(NULL, ", ", &tmp)) {
  831. if (sort_dimension__add(tok) < 0) {
  832. error("Unknown --sort key: `%s'", tok);
  833. usage_with_options(report_usage, options);
  834. }
  835. }
  836. free(str);
  837. }
  838. int cmd_report(int argc, const char **argv, const char *prefix)
  839. {
  840. symbol__init();
  841. page_size = getpagesize();
  842. parse_options(argc, argv, options, report_usage, 0);
  843. setup_sorting();
  844. setup_pager();
  845. return __cmd_report();
  846. }