builtin-report.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726
  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/color.h"
  11. #include <linux/list.h>
  12. #include "util/cache.h"
  13. #include <linux/rbtree.h>
  14. #include "util/symbol.h"
  15. #include "util/string.h"
  16. #include "util/callchain.h"
  17. #include "util/strlist.h"
  18. #include "util/values.h"
  19. #include "perf.h"
  20. #include "util/debug.h"
  21. #include "util/header.h"
  22. #include "util/parse-options.h"
  23. #include "util/parse-events.h"
  24. #include "util/thread.h"
  25. static char const *input_name = "perf.data";
  26. static char default_sort_order[] = "comm,dso,symbol";
  27. static char *sort_order = default_sort_order;
  28. static char *dso_list_str, *comm_list_str, *sym_list_str,
  29. *col_width_list_str;
  30. static struct strlist *dso_list, *comm_list, *sym_list;
  31. static char *field_sep;
  32. static int force;
  33. static int input;
  34. static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
  35. static int full_paths;
  36. static int show_nr_samples;
  37. static int show_threads;
  38. static struct perf_read_values show_threads_values;
  39. static char default_pretty_printing_style[] = "normal";
  40. static char *pretty_printing_style = default_pretty_printing_style;
  41. static unsigned long page_size;
  42. static unsigned long mmap_window = 32;
  43. static char default_parent_pattern[] = "^sys_|^do_page_fault";
  44. static char *parent_pattern = default_parent_pattern;
  45. static regex_t parent_regex;
  46. static int exclude_other = 1;
  47. static char callchain_default_opt[] = "fractal,0.5";
  48. static int callchain;
  49. static char __cwd[PATH_MAX];
  50. static char *cwd = __cwd;
  51. static int cwdlen;
  52. static struct rb_root threads;
  53. static struct thread *last_match;
  54. static struct perf_header *header;
  55. static
  56. struct callchain_param callchain_param = {
  57. .mode = CHAIN_GRAPH_REL,
  58. .min_percent = 0.5
  59. };
  60. static u64 sample_type;
  61. static int repsep_fprintf(FILE *fp, const char *fmt, ...)
  62. {
  63. int n;
  64. va_list ap;
  65. va_start(ap, fmt);
  66. if (!field_sep)
  67. n = vfprintf(fp, fmt, ap);
  68. else {
  69. char *bf = NULL;
  70. n = vasprintf(&bf, fmt, ap);
  71. if (n > 0) {
  72. char *sep = bf;
  73. while (1) {
  74. sep = strchr(sep, *field_sep);
  75. if (sep == NULL)
  76. break;
  77. *sep = '.';
  78. }
  79. }
  80. fputs(bf, fp);
  81. free(bf);
  82. }
  83. va_end(ap);
  84. return n;
  85. }
  86. static unsigned int dsos__col_width,
  87. comms__col_width,
  88. threads__col_width;
  89. /*
  90. * histogram, sorted on item, collects counts
  91. */
  92. static struct rb_root hist;
  93. struct hist_entry {
  94. struct rb_node rb_node;
  95. struct thread *thread;
  96. struct map *map;
  97. struct dso *dso;
  98. struct symbol *sym;
  99. struct symbol *parent;
  100. u64 ip;
  101. char level;
  102. struct callchain_node callchain;
  103. struct rb_root sorted_chain;
  104. u64 count;
  105. };
  106. /*
  107. * configurable sorting bits
  108. */
  109. struct sort_entry {
  110. struct list_head list;
  111. const char *header;
  112. int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
  113. int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
  114. size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width);
  115. unsigned int *width;
  116. bool elide;
  117. };
  118. static int64_t cmp_null(void *l, void *r)
  119. {
  120. if (!l && !r)
  121. return 0;
  122. else if (!l)
  123. return -1;
  124. else
  125. return 1;
  126. }
  127. /* --sort pid */
  128. static int64_t
  129. sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
  130. {
  131. return right->thread->pid - left->thread->pid;
  132. }
  133. static size_t
  134. sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
  135. {
  136. return repsep_fprintf(fp, "%*s:%5d", width - 6,
  137. self->thread->comm ?: "", self->thread->pid);
  138. }
  139. static struct sort_entry sort_thread = {
  140. .header = "Command: Pid",
  141. .cmp = sort__thread_cmp,
  142. .print = sort__thread_print,
  143. .width = &threads__col_width,
  144. };
  145. /* --sort comm */
  146. static int64_t
  147. sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
  148. {
  149. return right->thread->pid - left->thread->pid;
  150. }
  151. static int64_t
  152. sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
  153. {
  154. char *comm_l = left->thread->comm;
  155. char *comm_r = right->thread->comm;
  156. if (!comm_l || !comm_r)
  157. return cmp_null(comm_l, comm_r);
  158. return strcmp(comm_l, comm_r);
  159. }
  160. static size_t
  161. sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
  162. {
  163. return repsep_fprintf(fp, "%*s", width, self->thread->comm);
  164. }
  165. static struct sort_entry sort_comm = {
  166. .header = "Command",
  167. .cmp = sort__comm_cmp,
  168. .collapse = sort__comm_collapse,
  169. .print = sort__comm_print,
  170. .width = &comms__col_width,
  171. };
  172. /* --sort dso */
  173. static int64_t
  174. sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
  175. {
  176. struct dso *dso_l = left->dso;
  177. struct dso *dso_r = right->dso;
  178. if (!dso_l || !dso_r)
  179. return cmp_null(dso_l, dso_r);
  180. return strcmp(dso_l->name, dso_r->name);
  181. }
  182. static size_t
  183. sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
  184. {
  185. if (self->dso)
  186. return repsep_fprintf(fp, "%-*s", width, self->dso->name);
  187. return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
  188. }
  189. static struct sort_entry sort_dso = {
  190. .header = "Shared Object",
  191. .cmp = sort__dso_cmp,
  192. .print = sort__dso_print,
  193. .width = &dsos__col_width,
  194. };
  195. /* --sort symbol */
  196. static int64_t
  197. sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
  198. {
  199. u64 ip_l, ip_r;
  200. if (left->sym == right->sym)
  201. return 0;
  202. ip_l = left->sym ? left->sym->start : left->ip;
  203. ip_r = right->sym ? right->sym->start : right->ip;
  204. return (int64_t)(ip_r - ip_l);
  205. }
  206. static size_t
  207. sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
  208. {
  209. size_t ret = 0;
  210. if (verbose)
  211. ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip,
  212. dso__symtab_origin(self->dso));
  213. ret += repsep_fprintf(fp, "[%c] ", self->level);
  214. if (self->sym) {
  215. ret += repsep_fprintf(fp, "%s", self->sym->name);
  216. if (self->sym->module)
  217. ret += repsep_fprintf(fp, "\t[%s]",
  218. self->sym->module->name);
  219. } else {
  220. ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
  221. }
  222. return ret;
  223. }
  224. static struct sort_entry sort_sym = {
  225. .header = "Symbol",
  226. .cmp = sort__sym_cmp,
  227. .print = sort__sym_print,
  228. };
  229. /* --sort parent */
  230. static int64_t
  231. sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
  232. {
  233. struct symbol *sym_l = left->parent;
  234. struct symbol *sym_r = right->parent;
  235. if (!sym_l || !sym_r)
  236. return cmp_null(sym_l, sym_r);
  237. return strcmp(sym_l->name, sym_r->name);
  238. }
  239. static size_t
  240. sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
  241. {
  242. return repsep_fprintf(fp, "%-*s", width,
  243. self->parent ? self->parent->name : "[other]");
  244. }
  245. static unsigned int parent_symbol__col_width;
  246. static struct sort_entry sort_parent = {
  247. .header = "Parent symbol",
  248. .cmp = sort__parent_cmp,
  249. .print = sort__parent_print,
  250. .width = &parent_symbol__col_width,
  251. };
  252. static int sort__need_collapse = 0;
  253. static int sort__has_parent = 0;
  254. struct sort_dimension {
  255. const char *name;
  256. struct sort_entry *entry;
  257. int taken;
  258. };
  259. static struct sort_dimension sort_dimensions[] = {
  260. { .name = "pid", .entry = &sort_thread, },
  261. { .name = "comm", .entry = &sort_comm, },
  262. { .name = "dso", .entry = &sort_dso, },
  263. { .name = "symbol", .entry = &sort_sym, },
  264. { .name = "parent", .entry = &sort_parent, },
  265. };
  266. static LIST_HEAD(hist_entry__sort_list);
  267. static int sort_dimension__add(const char *tok)
  268. {
  269. unsigned int i;
  270. for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
  271. struct sort_dimension *sd = &sort_dimensions[i];
  272. if (sd->taken)
  273. continue;
  274. if (strncasecmp(tok, sd->name, strlen(tok)))
  275. continue;
  276. if (sd->entry->collapse)
  277. sort__need_collapse = 1;
  278. if (sd->entry == &sort_parent) {
  279. int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
  280. if (ret) {
  281. char err[BUFSIZ];
  282. regerror(ret, &parent_regex, err, sizeof(err));
  283. fprintf(stderr, "Invalid regex: %s\n%s",
  284. parent_pattern, err);
  285. exit(-1);
  286. }
  287. sort__has_parent = 1;
  288. }
  289. list_add_tail(&sd->entry->list, &hist_entry__sort_list);
  290. sd->taken = 1;
  291. return 0;
  292. }
  293. return -ESRCH;
  294. }
  295. static int64_t
  296. hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
  297. {
  298. struct sort_entry *se;
  299. int64_t cmp = 0;
  300. list_for_each_entry(se, &hist_entry__sort_list, list) {
  301. cmp = se->cmp(left, right);
  302. if (cmp)
  303. break;
  304. }
  305. return cmp;
  306. }
  307. static int64_t
  308. hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
  309. {
  310. struct sort_entry *se;
  311. int64_t cmp = 0;
  312. list_for_each_entry(se, &hist_entry__sort_list, list) {
  313. int64_t (*f)(struct hist_entry *, struct hist_entry *);
  314. f = se->collapse ?: se->cmp;
  315. cmp = f(left, right);
  316. if (cmp)
  317. break;
  318. }
  319. return cmp;
  320. }
  321. static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask)
  322. {
  323. int i;
  324. size_t ret = 0;
  325. ret += fprintf(fp, "%s", " ");
  326. for (i = 0; i < depth; i++)
  327. if (depth_mask & (1 << i))
  328. ret += fprintf(fp, "| ");
  329. else
  330. ret += fprintf(fp, " ");
  331. ret += fprintf(fp, "\n");
  332. return ret;
  333. }
  334. static size_t
  335. ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
  336. int depth_mask, int count, u64 total_samples,
  337. int hits)
  338. {
  339. int i;
  340. size_t ret = 0;
  341. ret += fprintf(fp, "%s", " ");
  342. for (i = 0; i < depth; i++) {
  343. if (depth_mask & (1 << i))
  344. ret += fprintf(fp, "|");
  345. else
  346. ret += fprintf(fp, " ");
  347. if (!count && i == depth - 1) {
  348. double percent;
  349. percent = hits * 100.0 / total_samples;
  350. ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
  351. } else
  352. ret += fprintf(fp, "%s", " ");
  353. }
  354. if (chain->sym)
  355. ret += fprintf(fp, "%s\n", chain->sym->name);
  356. else
  357. ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
  358. return ret;
  359. }
  360. static struct symbol *rem_sq_bracket;
  361. static struct callchain_list rem_hits;
  362. static void init_rem_hits(void)
  363. {
  364. rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
  365. if (!rem_sq_bracket) {
  366. fprintf(stderr, "Not enough memory to display remaining hits\n");
  367. return;
  368. }
  369. strcpy(rem_sq_bracket->name, "[...]");
  370. rem_hits.sym = rem_sq_bracket;
  371. }
  372. static size_t
  373. callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
  374. u64 total_samples, int depth, int depth_mask)
  375. {
  376. struct rb_node *node, *next;
  377. struct callchain_node *child;
  378. struct callchain_list *chain;
  379. int new_depth_mask = depth_mask;
  380. u64 new_total;
  381. u64 remaining;
  382. size_t ret = 0;
  383. int i;
  384. if (callchain_param.mode == CHAIN_GRAPH_REL)
  385. new_total = self->children_hit;
  386. else
  387. new_total = total_samples;
  388. remaining = new_total;
  389. node = rb_first(&self->rb_root);
  390. while (node) {
  391. u64 cumul;
  392. child = rb_entry(node, struct callchain_node, rb_node);
  393. cumul = cumul_hits(child);
  394. remaining -= cumul;
  395. /*
  396. * The depth mask manages the output of pipes that show
  397. * the depth. We don't want to keep the pipes of the current
  398. * level for the last child of this depth.
  399. * Except if we have remaining filtered hits. They will
  400. * supersede the last child
  401. */
  402. next = rb_next(node);
  403. if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
  404. new_depth_mask &= ~(1 << (depth - 1));
  405. /*
  406. * But we keep the older depth mask for the line seperator
  407. * to keep the level link until we reach the last child
  408. */
  409. ret += ipchain__fprintf_graph_line(fp, depth, depth_mask);
  410. i = 0;
  411. list_for_each_entry(chain, &child->val, list) {
  412. if (chain->ip >= PERF_CONTEXT_MAX)
  413. continue;
  414. ret += ipchain__fprintf_graph(fp, chain, depth,
  415. new_depth_mask, i++,
  416. new_total,
  417. cumul);
  418. }
  419. ret += callchain__fprintf_graph(fp, child, new_total,
  420. depth + 1,
  421. new_depth_mask | (1 << depth));
  422. node = next;
  423. }
  424. if (callchain_param.mode == CHAIN_GRAPH_REL &&
  425. remaining && remaining != new_total) {
  426. if (!rem_sq_bracket)
  427. return ret;
  428. new_depth_mask &= ~(1 << (depth - 1));
  429. ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
  430. new_depth_mask, 0, new_total,
  431. remaining);
  432. }
  433. return ret;
  434. }
  435. static size_t
  436. callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
  437. u64 total_samples)
  438. {
  439. struct callchain_list *chain;
  440. size_t ret = 0;
  441. if (!self)
  442. return 0;
  443. ret += callchain__fprintf_flat(fp, self->parent, total_samples);
  444. list_for_each_entry(chain, &self->val, list) {
  445. if (chain->ip >= PERF_CONTEXT_MAX)
  446. continue;
  447. if (chain->sym)
  448. ret += fprintf(fp, " %s\n", chain->sym->name);
  449. else
  450. ret += fprintf(fp, " %p\n",
  451. (void *)(long)chain->ip);
  452. }
  453. return ret;
  454. }
  455. static size_t
  456. hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
  457. u64 total_samples)
  458. {
  459. struct rb_node *rb_node;
  460. struct callchain_node *chain;
  461. size_t ret = 0;
  462. rb_node = rb_first(&self->sorted_chain);
  463. while (rb_node) {
  464. double percent;
  465. chain = rb_entry(rb_node, struct callchain_node, rb_node);
  466. percent = chain->hit * 100.0 / total_samples;
  467. switch (callchain_param.mode) {
  468. case CHAIN_FLAT:
  469. ret += percent_color_fprintf(fp, " %6.2f%%\n",
  470. percent);
  471. ret += callchain__fprintf_flat(fp, chain, total_samples);
  472. break;
  473. case CHAIN_GRAPH_ABS: /* Falldown */
  474. case CHAIN_GRAPH_REL:
  475. ret += callchain__fprintf_graph(fp, chain,
  476. total_samples, 1, 1);
  477. case CHAIN_NONE:
  478. default:
  479. break;
  480. }
  481. ret += fprintf(fp, "\n");
  482. rb_node = rb_next(rb_node);
  483. }
  484. return ret;
  485. }
  486. static size_t
  487. hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
  488. {
  489. struct sort_entry *se;
  490. size_t ret;
  491. if (exclude_other && !self->parent)
  492. return 0;
  493. if (total_samples)
  494. ret = percent_color_fprintf(fp,
  495. field_sep ? "%.2f" : " %6.2f%%",
  496. (self->count * 100.0) / total_samples);
  497. else
  498. ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count);
  499. if (show_nr_samples) {
  500. if (field_sep)
  501. fprintf(fp, "%c%lld", *field_sep, self->count);
  502. else
  503. fprintf(fp, "%11lld", self->count);
  504. }
  505. list_for_each_entry(se, &hist_entry__sort_list, list) {
  506. if (se->elide)
  507. continue;
  508. fprintf(fp, "%s", field_sep ?: " ");
  509. ret += se->print(fp, self, se->width ? *se->width : 0);
  510. }
  511. ret += fprintf(fp, "\n");
  512. if (callchain)
  513. hist_entry_callchain__fprintf(fp, self, total_samples);
  514. return ret;
  515. }
  516. /*
  517. *
  518. */
  519. static void dso__calc_col_width(struct dso *self)
  520. {
  521. if (!col_width_list_str && !field_sep &&
  522. (!dso_list || strlist__has_entry(dso_list, self->name))) {
  523. unsigned int slen = strlen(self->name);
  524. if (slen > dsos__col_width)
  525. dsos__col_width = slen;
  526. }
  527. self->slen_calculated = 1;
  528. }
  529. static void thread__comm_adjust(struct thread *self)
  530. {
  531. char *comm = self->comm;
  532. if (!col_width_list_str && !field_sep &&
  533. (!comm_list || strlist__has_entry(comm_list, comm))) {
  534. unsigned int slen = strlen(comm);
  535. if (slen > comms__col_width) {
  536. comms__col_width = slen;
  537. threads__col_width = slen + 6;
  538. }
  539. }
  540. }
  541. static int thread__set_comm_adjust(struct thread *self, const char *comm)
  542. {
  543. int ret = thread__set_comm(self, comm);
  544. if (ret)
  545. return ret;
  546. thread__comm_adjust(self);
  547. return 0;
  548. }
  549. static struct symbol *
  550. resolve_symbol(struct thread *thread, struct map **mapp,
  551. struct dso **dsop, u64 *ipp)
  552. {
  553. struct dso *dso = dsop ? *dsop : NULL;
  554. struct map *map = mapp ? *mapp : NULL;
  555. u64 ip = *ipp;
  556. if (!thread)
  557. return NULL;
  558. if (dso)
  559. goto got_dso;
  560. if (map)
  561. goto got_map;
  562. map = thread__find_map(thread, ip);
  563. if (map != NULL) {
  564. /*
  565. * We have to do this here as we may have a dso
  566. * with no symbol hit that has a name longer than
  567. * the ones with symbols sampled.
  568. */
  569. if (!sort_dso.elide && !map->dso->slen_calculated)
  570. dso__calc_col_width(map->dso);
  571. if (mapp)
  572. *mapp = map;
  573. got_map:
  574. ip = map->map_ip(map, ip);
  575. dso = map->dso;
  576. } else {
  577. /*
  578. * If this is outside of all known maps,
  579. * and is a negative address, try to look it
  580. * up in the kernel dso, as it might be a
  581. * vsyscall (which executes in user-mode):
  582. */
  583. if ((long long)ip < 0)
  584. dso = kernel_dso;
  585. }
  586. dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
  587. dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip);
  588. *ipp = ip;
  589. if (dsop)
  590. *dsop = dso;
  591. if (!dso)
  592. return NULL;
  593. got_dso:
  594. return dso->find_symbol(dso, ip);
  595. }
  596. static int call__match(struct symbol *sym)
  597. {
  598. if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
  599. return 1;
  600. return 0;
  601. }
  602. static struct symbol **
  603. resolve_callchain(struct thread *thread, struct map *map __used,
  604. struct ip_callchain *chain, struct hist_entry *entry)
  605. {
  606. u64 context = PERF_CONTEXT_MAX;
  607. struct symbol **syms = NULL;
  608. unsigned int i;
  609. if (callchain) {
  610. syms = calloc(chain->nr, sizeof(*syms));
  611. if (!syms) {
  612. fprintf(stderr, "Can't allocate memory for symbols\n");
  613. exit(-1);
  614. }
  615. }
  616. for (i = 0; i < chain->nr; i++) {
  617. u64 ip = chain->ips[i];
  618. struct dso *dso = NULL;
  619. struct symbol *sym;
  620. if (ip >= PERF_CONTEXT_MAX) {
  621. context = ip;
  622. continue;
  623. }
  624. switch (context) {
  625. case PERF_CONTEXT_HV:
  626. dso = hypervisor_dso;
  627. break;
  628. case PERF_CONTEXT_KERNEL:
  629. dso = kernel_dso;
  630. break;
  631. default:
  632. break;
  633. }
  634. sym = resolve_symbol(thread, NULL, &dso, &ip);
  635. if (sym) {
  636. if (sort__has_parent && call__match(sym) &&
  637. !entry->parent)
  638. entry->parent = sym;
  639. if (!callchain)
  640. break;
  641. syms[i] = sym;
  642. }
  643. }
  644. return syms;
  645. }
  646. /*
  647. * collect histogram counts
  648. */
  649. static int
  650. hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
  651. struct symbol *sym, u64 ip, struct ip_callchain *chain,
  652. char level, u64 count)
  653. {
  654. struct rb_node **p = &hist.rb_node;
  655. struct rb_node *parent = NULL;
  656. struct hist_entry *he;
  657. struct symbol **syms = NULL;
  658. struct hist_entry entry = {
  659. .thread = thread,
  660. .map = map,
  661. .dso = dso,
  662. .sym = sym,
  663. .ip = ip,
  664. .level = level,
  665. .count = count,
  666. .parent = NULL,
  667. .sorted_chain = RB_ROOT
  668. };
  669. int cmp;
  670. if ((sort__has_parent || callchain) && chain)
  671. syms = resolve_callchain(thread, map, chain, &entry);
  672. while (*p != NULL) {
  673. parent = *p;
  674. he = rb_entry(parent, struct hist_entry, rb_node);
  675. cmp = hist_entry__cmp(&entry, he);
  676. if (!cmp) {
  677. he->count += count;
  678. if (callchain) {
  679. append_chain(&he->callchain, chain, syms);
  680. free(syms);
  681. }
  682. return 0;
  683. }
  684. if (cmp < 0)
  685. p = &(*p)->rb_left;
  686. else
  687. p = &(*p)->rb_right;
  688. }
  689. he = malloc(sizeof(*he));
  690. if (!he)
  691. return -ENOMEM;
  692. *he = entry;
  693. if (callchain) {
  694. callchain_init(&he->callchain);
  695. append_chain(&he->callchain, chain, syms);
  696. free(syms);
  697. }
  698. rb_link_node(&he->rb_node, parent, p);
  699. rb_insert_color(&he->rb_node, &hist);
  700. return 0;
  701. }
  702. static void hist_entry__free(struct hist_entry *he)
  703. {
  704. free(he);
  705. }
  706. /*
  707. * collapse the histogram
  708. */
  709. static struct rb_root collapse_hists;
  710. static void collapse__insert_entry(struct hist_entry *he)
  711. {
  712. struct rb_node **p = &collapse_hists.rb_node;
  713. struct rb_node *parent = NULL;
  714. struct hist_entry *iter;
  715. int64_t cmp;
  716. while (*p != NULL) {
  717. parent = *p;
  718. iter = rb_entry(parent, struct hist_entry, rb_node);
  719. cmp = hist_entry__collapse(iter, he);
  720. if (!cmp) {
  721. iter->count += he->count;
  722. hist_entry__free(he);
  723. return;
  724. }
  725. if (cmp < 0)
  726. p = &(*p)->rb_left;
  727. else
  728. p = &(*p)->rb_right;
  729. }
  730. rb_link_node(&he->rb_node, parent, p);
  731. rb_insert_color(&he->rb_node, &collapse_hists);
  732. }
  733. static void collapse__resort(void)
  734. {
  735. struct rb_node *next;
  736. struct hist_entry *n;
  737. if (!sort__need_collapse)
  738. return;
  739. next = rb_first(&hist);
  740. while (next) {
  741. n = rb_entry(next, struct hist_entry, rb_node);
  742. next = rb_next(&n->rb_node);
  743. rb_erase(&n->rb_node, &hist);
  744. collapse__insert_entry(n);
  745. }
  746. }
  747. /*
  748. * reverse the map, sort on count.
  749. */
  750. static struct rb_root output_hists;
  751. static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
  752. {
  753. struct rb_node **p = &output_hists.rb_node;
  754. struct rb_node *parent = NULL;
  755. struct hist_entry *iter;
  756. if (callchain)
  757. callchain_param.sort(&he->sorted_chain, &he->callchain,
  758. min_callchain_hits, &callchain_param);
  759. while (*p != NULL) {
  760. parent = *p;
  761. iter = rb_entry(parent, struct hist_entry, rb_node);
  762. if (he->count > iter->count)
  763. p = &(*p)->rb_left;
  764. else
  765. p = &(*p)->rb_right;
  766. }
  767. rb_link_node(&he->rb_node, parent, p);
  768. rb_insert_color(&he->rb_node, &output_hists);
  769. }
  770. static void output__resort(u64 total_samples)
  771. {
  772. struct rb_node *next;
  773. struct hist_entry *n;
  774. struct rb_root *tree = &hist;
  775. u64 min_callchain_hits;
  776. min_callchain_hits = total_samples * (callchain_param.min_percent / 100);
  777. if (sort__need_collapse)
  778. tree = &collapse_hists;
  779. next = rb_first(tree);
  780. while (next) {
  781. n = rb_entry(next, struct hist_entry, rb_node);
  782. next = rb_next(&n->rb_node);
  783. rb_erase(&n->rb_node, tree);
  784. output__insert_entry(n, min_callchain_hits);
  785. }
  786. }
  787. static size_t output__fprintf(FILE *fp, u64 total_samples)
  788. {
  789. struct hist_entry *pos;
  790. struct sort_entry *se;
  791. struct rb_node *nd;
  792. size_t ret = 0;
  793. unsigned int width;
  794. char *col_width = col_width_list_str;
  795. int raw_printing_style;
  796. raw_printing_style = !strcmp(pretty_printing_style, "raw");
  797. init_rem_hits();
  798. fprintf(fp, "# Samples: %Ld\n", (u64)total_samples);
  799. fprintf(fp, "#\n");
  800. fprintf(fp, "# Overhead");
  801. if (show_nr_samples) {
  802. if (field_sep)
  803. fprintf(fp, "%cSamples", *field_sep);
  804. else
  805. fputs(" Samples ", fp);
  806. }
  807. list_for_each_entry(se, &hist_entry__sort_list, list) {
  808. if (se->elide)
  809. continue;
  810. if (field_sep) {
  811. fprintf(fp, "%c%s", *field_sep, se->header);
  812. continue;
  813. }
  814. width = strlen(se->header);
  815. if (se->width) {
  816. if (col_width_list_str) {
  817. if (col_width) {
  818. *se->width = atoi(col_width);
  819. col_width = strchr(col_width, ',');
  820. if (col_width)
  821. ++col_width;
  822. }
  823. }
  824. width = *se->width = max(*se->width, width);
  825. }
  826. fprintf(fp, " %*s", width, se->header);
  827. }
  828. fprintf(fp, "\n");
  829. if (field_sep)
  830. goto print_entries;
  831. fprintf(fp, "# ........");
  832. if (show_nr_samples)
  833. fprintf(fp, " ..........");
  834. list_for_each_entry(se, &hist_entry__sort_list, list) {
  835. unsigned int i;
  836. if (se->elide)
  837. continue;
  838. fprintf(fp, " ");
  839. if (se->width)
  840. width = *se->width;
  841. else
  842. width = strlen(se->header);
  843. for (i = 0; i < width; i++)
  844. fprintf(fp, ".");
  845. }
  846. fprintf(fp, "\n");
  847. fprintf(fp, "#\n");
  848. print_entries:
  849. for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
  850. pos = rb_entry(nd, struct hist_entry, rb_node);
  851. ret += hist_entry__fprintf(fp, pos, total_samples);
  852. }
  853. if (sort_order == default_sort_order &&
  854. parent_pattern == default_parent_pattern) {
  855. fprintf(fp, "#\n");
  856. fprintf(fp, "# (For a higher level overview, try: perf report --sort comm,dso)\n");
  857. fprintf(fp, "#\n");
  858. }
  859. fprintf(fp, "\n");
  860. free(rem_sq_bracket);
  861. if (show_threads)
  862. perf_read_values_display(fp, &show_threads_values,
  863. raw_printing_style);
  864. return ret;
  865. }
  866. static unsigned long total = 0,
  867. total_mmap = 0,
  868. total_comm = 0,
  869. total_fork = 0,
  870. total_unknown = 0,
  871. total_lost = 0;
  872. static int validate_chain(struct ip_callchain *chain, event_t *event)
  873. {
  874. unsigned int chain_size;
  875. chain_size = event->header.size;
  876. chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event;
  877. if (chain->nr*sizeof(u64) > chain_size)
  878. return -1;
  879. return 0;
  880. }
  881. static int
  882. process_sample_event(event_t *event, unsigned long offset, unsigned long head)
  883. {
  884. char level;
  885. int show = 0;
  886. struct dso *dso = NULL;
  887. struct thread *thread;
  888. u64 ip = event->ip.ip;
  889. u64 period = 1;
  890. struct map *map = NULL;
  891. void *more_data = event->ip.__more_data;
  892. struct ip_callchain *chain = NULL;
  893. int cpumode;
  894. thread = threads__findnew(event->ip.pid, &threads, &last_match);
  895. if (sample_type & PERF_SAMPLE_PERIOD) {
  896. period = *(u64 *)more_data;
  897. more_data += sizeof(u64);
  898. }
  899. dump_printf("%p [%p]: PERF_RECORD_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n",
  900. (void *)(offset + head),
  901. (void *)(long)(event->header.size),
  902. event->header.misc,
  903. event->ip.pid, event->ip.tid,
  904. (void *)(long)ip,
  905. (long long)period);
  906. if (sample_type & PERF_SAMPLE_CALLCHAIN) {
  907. unsigned int i;
  908. chain = (void *)more_data;
  909. dump_printf("... chain: nr:%Lu\n", chain->nr);
  910. if (validate_chain(chain, event) < 0) {
  911. eprintf("call-chain problem with event, skipping it.\n");
  912. return 0;
  913. }
  914. if (dump_trace) {
  915. for (i = 0; i < chain->nr; i++)
  916. dump_printf("..... %2d: %016Lx\n", i, chain->ips[i]);
  917. }
  918. }
  919. dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
  920. if (thread == NULL) {
  921. eprintf("problem processing %d event, skipping it.\n",
  922. event->header.type);
  923. return -1;
  924. }
  925. if (comm_list && !strlist__has_entry(comm_list, thread->comm))
  926. return 0;
  927. cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
  928. if (cpumode == PERF_RECORD_MISC_KERNEL) {
  929. show = SHOW_KERNEL;
  930. level = 'k';
  931. dso = kernel_dso;
  932. dump_printf(" ...... dso: %s\n", dso->name);
  933. } else if (cpumode == PERF_RECORD_MISC_USER) {
  934. show = SHOW_USER;
  935. level = '.';
  936. } else {
  937. show = SHOW_HV;
  938. level = 'H';
  939. dso = hypervisor_dso;
  940. dump_printf(" ...... dso: [hypervisor]\n");
  941. }
  942. if (show & show_mask) {
  943. struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip);
  944. if (dso_list && (!dso || !dso->name ||
  945. !strlist__has_entry(dso_list, dso->name)))
  946. return 0;
  947. if (sym_list && (!sym || !strlist__has_entry(sym_list, sym->name)))
  948. return 0;
  949. if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) {
  950. eprintf("problem incrementing symbol count, skipping event\n");
  951. return -1;
  952. }
  953. }
  954. total += period;
  955. return 0;
  956. }
  957. static int
  958. process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
  959. {
  960. struct thread *thread;
  961. struct map *map = map__new(&event->mmap, cwd, cwdlen);
  962. thread = threads__findnew(event->mmap.pid, &threads, &last_match);
  963. dump_printf("%p [%p]: PERF_RECORD_MMAP %d/%d: [%p(%p) @ %p]: %s\n",
  964. (void *)(offset + head),
  965. (void *)(long)(event->header.size),
  966. event->mmap.pid,
  967. event->mmap.tid,
  968. (void *)(long)event->mmap.start,
  969. (void *)(long)event->mmap.len,
  970. (void *)(long)event->mmap.pgoff,
  971. event->mmap.filename);
  972. if (thread == NULL || map == NULL) {
  973. dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
  974. return 0;
  975. }
  976. thread__insert_map(thread, map);
  977. total_mmap++;
  978. return 0;
  979. }
  980. static int
  981. process_comm_event(event_t *event, unsigned long offset, unsigned long head)
  982. {
  983. struct thread *thread;
  984. thread = threads__findnew(event->comm.pid, &threads, &last_match);
  985. dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
  986. (void *)(offset + head),
  987. (void *)(long)(event->header.size),
  988. event->comm.comm, event->comm.pid);
  989. if (thread == NULL ||
  990. thread__set_comm_adjust(thread, event->comm.comm)) {
  991. dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
  992. return -1;
  993. }
  994. total_comm++;
  995. return 0;
  996. }
  997. static int
  998. process_task_event(event_t *event, unsigned long offset, unsigned long head)
  999. {
  1000. struct thread *thread;
  1001. struct thread *parent;
  1002. thread = threads__findnew(event->fork.pid, &threads, &last_match);
  1003. parent = threads__findnew(event->fork.ppid, &threads, &last_match);
  1004. dump_printf("%p [%p]: PERF_RECORD_%s: (%d:%d):(%d:%d)\n",
  1005. (void *)(offset + head),
  1006. (void *)(long)(event->header.size),
  1007. event->header.type == PERF_RECORD_FORK ? "FORK" : "EXIT",
  1008. event->fork.pid, event->fork.tid,
  1009. event->fork.ppid, event->fork.ptid);
  1010. /*
  1011. * A thread clone will have the same PID for both
  1012. * parent and child.
  1013. */
  1014. if (thread == parent)
  1015. return 0;
  1016. if (event->header.type == PERF_RECORD_EXIT)
  1017. return 0;
  1018. if (!thread || !parent || thread__fork(thread, parent)) {
  1019. dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
  1020. return -1;
  1021. }
  1022. total_fork++;
  1023. return 0;
  1024. }
  1025. static int
  1026. process_lost_event(event_t *event, unsigned long offset, unsigned long head)
  1027. {
  1028. dump_printf("%p [%p]: PERF_RECORD_LOST: id:%Ld: lost:%Ld\n",
  1029. (void *)(offset + head),
  1030. (void *)(long)(event->header.size),
  1031. event->lost.id,
  1032. event->lost.lost);
  1033. total_lost += event->lost.lost;
  1034. return 0;
  1035. }
  1036. static int
  1037. process_read_event(event_t *event, unsigned long offset, unsigned long head)
  1038. {
  1039. struct perf_event_attr *attr;
  1040. attr = perf_header__find_attr(event->read.id, header);
  1041. if (show_threads) {
  1042. const char *name = attr ? __event_name(attr->type, attr->config)
  1043. : "unknown";
  1044. perf_read_values_add_value(&show_threads_values,
  1045. event->read.pid, event->read.tid,
  1046. event->read.id,
  1047. name,
  1048. event->read.value);
  1049. }
  1050. dump_printf("%p [%p]: PERF_RECORD_READ: %d %d %s %Lu\n",
  1051. (void *)(offset + head),
  1052. (void *)(long)(event->header.size),
  1053. event->read.pid,
  1054. event->read.tid,
  1055. attr ? __event_name(attr->type, attr->config)
  1056. : "FAIL",
  1057. event->read.value);
  1058. return 0;
  1059. }
  1060. static int
  1061. process_event(event_t *event, unsigned long offset, unsigned long head)
  1062. {
  1063. trace_event(event);
  1064. switch (event->header.type) {
  1065. case PERF_RECORD_SAMPLE:
  1066. return process_sample_event(event, offset, head);
  1067. case PERF_RECORD_MMAP:
  1068. return process_mmap_event(event, offset, head);
  1069. case PERF_RECORD_COMM:
  1070. return process_comm_event(event, offset, head);
  1071. case PERF_RECORD_FORK:
  1072. case PERF_RECORD_EXIT:
  1073. return process_task_event(event, offset, head);
  1074. case PERF_RECORD_LOST:
  1075. return process_lost_event(event, offset, head);
  1076. case PERF_RECORD_READ:
  1077. return process_read_event(event, offset, head);
  1078. /*
  1079. * We dont process them right now but they are fine:
  1080. */
  1081. case PERF_RECORD_THROTTLE:
  1082. case PERF_RECORD_UNTHROTTLE:
  1083. return 0;
  1084. default:
  1085. return -1;
  1086. }
  1087. return 0;
  1088. }
  1089. static int __cmd_report(void)
  1090. {
  1091. int ret, rc = EXIT_FAILURE;
  1092. unsigned long offset = 0;
  1093. unsigned long head, shift;
  1094. struct stat input_stat;
  1095. struct thread *idle;
  1096. event_t *event;
  1097. uint32_t size;
  1098. char *buf;
  1099. idle = register_idle_thread(&threads, &last_match);
  1100. thread__comm_adjust(idle);
  1101. if (show_threads)
  1102. perf_read_values_init(&show_threads_values);
  1103. input = open(input_name, O_RDONLY);
  1104. if (input < 0) {
  1105. fprintf(stderr, " failed to open file: %s", input_name);
  1106. if (!strcmp(input_name, "perf.data"))
  1107. fprintf(stderr, " (try 'perf record' first)");
  1108. fprintf(stderr, "\n");
  1109. exit(-1);
  1110. }
  1111. ret = fstat(input, &input_stat);
  1112. if (ret < 0) {
  1113. perror("failed to stat file");
  1114. exit(-1);
  1115. }
  1116. if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
  1117. fprintf(stderr, "file: %s not owned by current user or root\n", input_name);
  1118. exit(-1);
  1119. }
  1120. if (!input_stat.st_size) {
  1121. fprintf(stderr, "zero-sized file, nothing to do!\n");
  1122. exit(0);
  1123. }
  1124. header = perf_header__read(input);
  1125. head = header->data_offset;
  1126. sample_type = perf_header__sample_type(header);
  1127. if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
  1128. if (sort__has_parent) {
  1129. fprintf(stderr, "selected --sort parent, but no"
  1130. " callchain data. Did you call"
  1131. " perf record without -g?\n");
  1132. exit(-1);
  1133. }
  1134. if (callchain) {
  1135. fprintf(stderr, "selected -g but no callchain data."
  1136. " Did you call perf record without"
  1137. " -g?\n");
  1138. exit(-1);
  1139. }
  1140. } else if (callchain_param.mode != CHAIN_NONE && !callchain) {
  1141. callchain = 1;
  1142. if (register_callchain_param(&callchain_param) < 0) {
  1143. fprintf(stderr, "Can't register callchain"
  1144. " params\n");
  1145. exit(-1);
  1146. }
  1147. }
  1148. if (load_kernel() < 0) {
  1149. perror("failed to load kernel symbols");
  1150. return EXIT_FAILURE;
  1151. }
  1152. if (!full_paths) {
  1153. if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
  1154. perror("failed to get the current directory");
  1155. return EXIT_FAILURE;
  1156. }
  1157. cwdlen = strlen(cwd);
  1158. } else {
  1159. cwd = NULL;
  1160. cwdlen = 0;
  1161. }
  1162. shift = page_size * (head / page_size);
  1163. offset += shift;
  1164. head -= shift;
  1165. remap:
  1166. buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
  1167. MAP_SHARED, input, offset);
  1168. if (buf == MAP_FAILED) {
  1169. perror("failed to mmap file");
  1170. exit(-1);
  1171. }
  1172. more:
  1173. event = (event_t *)(buf + head);
  1174. size = event->header.size;
  1175. if (!size)
  1176. size = 8;
  1177. if (head + event->header.size >= page_size * mmap_window) {
  1178. int munmap_ret;
  1179. shift = page_size * (head / page_size);
  1180. munmap_ret = munmap(buf, page_size * mmap_window);
  1181. assert(munmap_ret == 0);
  1182. offset += shift;
  1183. head -= shift;
  1184. goto remap;
  1185. }
  1186. size = event->header.size;
  1187. dump_printf("\n%p [%p]: event: %d\n",
  1188. (void *)(offset + head),
  1189. (void *)(long)event->header.size,
  1190. event->header.type);
  1191. if (!size || process_event(event, offset, head) < 0) {
  1192. dump_printf("%p [%p]: skipping unknown header type: %d\n",
  1193. (void *)(offset + head),
  1194. (void *)(long)(event->header.size),
  1195. event->header.type);
  1196. total_unknown++;
  1197. /*
  1198. * assume we lost track of the stream, check alignment, and
  1199. * increment a single u64 in the hope to catch on again 'soon'.
  1200. */
  1201. if (unlikely(head & 7))
  1202. head &= ~7ULL;
  1203. size = 8;
  1204. }
  1205. head += size;
  1206. if (offset + head >= header->data_offset + header->data_size)
  1207. goto done;
  1208. if (offset + head < (unsigned long)input_stat.st_size)
  1209. goto more;
  1210. done:
  1211. rc = EXIT_SUCCESS;
  1212. close(input);
  1213. dump_printf(" IP events: %10ld\n", total);
  1214. dump_printf(" mmap events: %10ld\n", total_mmap);
  1215. dump_printf(" comm events: %10ld\n", total_comm);
  1216. dump_printf(" fork events: %10ld\n", total_fork);
  1217. dump_printf(" lost events: %10ld\n", total_lost);
  1218. dump_printf(" unknown events: %10ld\n", total_unknown);
  1219. if (dump_trace)
  1220. return 0;
  1221. if (verbose >= 3)
  1222. threads__fprintf(stdout, &threads);
  1223. if (verbose >= 2)
  1224. dsos__fprintf(stdout);
  1225. collapse__resort();
  1226. output__resort(total);
  1227. output__fprintf(stdout, total);
  1228. if (show_threads)
  1229. perf_read_values_destroy(&show_threads_values);
  1230. return rc;
  1231. }
  1232. static int
  1233. parse_callchain_opt(const struct option *opt __used, const char *arg,
  1234. int unset __used)
  1235. {
  1236. char *tok;
  1237. char *endptr;
  1238. callchain = 1;
  1239. if (!arg)
  1240. return 0;
  1241. tok = strtok((char *)arg, ",");
  1242. if (!tok)
  1243. return -1;
  1244. /* get the output mode */
  1245. if (!strncmp(tok, "graph", strlen(arg)))
  1246. callchain_param.mode = CHAIN_GRAPH_ABS;
  1247. else if (!strncmp(tok, "flat", strlen(arg)))
  1248. callchain_param.mode = CHAIN_FLAT;
  1249. else if (!strncmp(tok, "fractal", strlen(arg)))
  1250. callchain_param.mode = CHAIN_GRAPH_REL;
  1251. else if (!strncmp(tok, "none", strlen(arg))) {
  1252. callchain_param.mode = CHAIN_NONE;
  1253. callchain = 0;
  1254. return 0;
  1255. }
  1256. else
  1257. return -1;
  1258. /* get the min percentage */
  1259. tok = strtok(NULL, ",");
  1260. if (!tok)
  1261. goto setup;
  1262. callchain_param.min_percent = strtod(tok, &endptr);
  1263. if (tok == endptr)
  1264. return -1;
  1265. setup:
  1266. if (register_callchain_param(&callchain_param) < 0) {
  1267. fprintf(stderr, "Can't register callchain params\n");
  1268. return -1;
  1269. }
  1270. return 0;
  1271. }
  1272. static const char * const report_usage[] = {
  1273. "perf report [<options>] <command>",
  1274. NULL
  1275. };
  1276. static const struct option options[] = {
  1277. OPT_STRING('i', "input", &input_name, "file",
  1278. "input file name"),
  1279. OPT_BOOLEAN('v', "verbose", &verbose,
  1280. "be more verbose (show symbol address, etc)"),
  1281. OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
  1282. "dump raw trace in ASCII"),
  1283. OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"),
  1284. OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
  1285. OPT_BOOLEAN('m', "modules", &modules,
  1286. "load module symbols - WARNING: use only with -k and LIVE kernel"),
  1287. OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,
  1288. "Show a column with the number of samples"),
  1289. OPT_BOOLEAN('T', "threads", &show_threads,
  1290. "Show per-thread event counters"),
  1291. OPT_STRING(0, "pretty", &pretty_printing_style, "key",
  1292. "pretty printing style key: normal raw"),
  1293. OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
  1294. "sort by key(s): pid, comm, dso, symbol, parent"),
  1295. OPT_BOOLEAN('P', "full-paths", &full_paths,
  1296. "Don't shorten the pathnames taking into account the cwd"),
  1297. OPT_STRING('p', "parent", &parent_pattern, "regex",
  1298. "regex filter to identify parent, see: '--sort parent'"),
  1299. OPT_BOOLEAN('x', "exclude-other", &exclude_other,
  1300. "Only display entries with parent-match"),
  1301. OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent",
  1302. "Display callchains using output_type and min percent threshold. "
  1303. "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt),
  1304. OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
  1305. "only consider symbols in these dsos"),
  1306. OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]",
  1307. "only consider symbols in these comms"),
  1308. OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]",
  1309. "only consider these symbols"),
  1310. OPT_STRING('w', "column-widths", &col_width_list_str,
  1311. "width[,width...]",
  1312. "don't try to adjust column width, use these fixed values"),
  1313. OPT_STRING('t', "field-separator", &field_sep, "separator",
  1314. "separator for columns, no spaces will be added between "
  1315. "columns '.' is reserved."),
  1316. OPT_END()
  1317. };
  1318. static void setup_sorting(void)
  1319. {
  1320. char *tmp, *tok, *str = strdup(sort_order);
  1321. for (tok = strtok_r(str, ", ", &tmp);
  1322. tok; tok = strtok_r(NULL, ", ", &tmp)) {
  1323. if (sort_dimension__add(tok) < 0) {
  1324. error("Unknown --sort key: `%s'", tok);
  1325. usage_with_options(report_usage, options);
  1326. }
  1327. }
  1328. free(str);
  1329. }
  1330. static void setup_list(struct strlist **list, const char *list_str,
  1331. struct sort_entry *se, const char *list_name,
  1332. FILE *fp)
  1333. {
  1334. if (list_str) {
  1335. *list = strlist__new(true, list_str);
  1336. if (!*list) {
  1337. fprintf(stderr, "problems parsing %s list\n",
  1338. list_name);
  1339. exit(129);
  1340. }
  1341. if (strlist__nr_entries(*list) == 1) {
  1342. fprintf(fp, "# %s: %s\n", list_name,
  1343. strlist__entry(*list, 0)->s);
  1344. se->elide = true;
  1345. }
  1346. }
  1347. }
  1348. int cmd_report(int argc, const char **argv, const char *prefix __used)
  1349. {
  1350. symbol__init();
  1351. page_size = getpagesize();
  1352. argc = parse_options(argc, argv, options, report_usage, 0);
  1353. setup_sorting();
  1354. if (parent_pattern != default_parent_pattern) {
  1355. sort_dimension__add("parent");
  1356. sort_parent.elide = 1;
  1357. } else
  1358. exclude_other = 0;
  1359. /*
  1360. * Any (unrecognized) arguments left?
  1361. */
  1362. if (argc)
  1363. usage_with_options(report_usage, options);
  1364. setup_pager();
  1365. setup_list(&dso_list, dso_list_str, &sort_dso, "dso", stdout);
  1366. setup_list(&comm_list, comm_list_str, &sort_comm, "comm", stdout);
  1367. setup_list(&sym_list, sym_list_str, &sort_sym, "symbol", stdout);
  1368. if (field_sep && *field_sep == '.') {
  1369. fputs("'.' is the only non valid --field-separator argument\n",
  1370. stderr);
  1371. exit(129);
  1372. }
  1373. return __cmd_report();
  1374. }