builtin-report.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728
  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 int thread__set_comm_adjust(struct thread *self, const char *comm)
  530. {
  531. int ret = thread__set_comm(self, comm);
  532. if (ret)
  533. return ret;
  534. if (!col_width_list_str && !field_sep &&
  535. (!comm_list || strlist__has_entry(comm_list, comm))) {
  536. unsigned int slen = strlen(comm);
  537. if (slen > comms__col_width) {
  538. comms__col_width = slen;
  539. threads__col_width = slen + 6;
  540. }
  541. }
  542. return 0;
  543. }
  544. static struct symbol *
  545. resolve_symbol(struct thread *thread, struct map **mapp,
  546. struct dso **dsop, u64 *ipp)
  547. {
  548. struct dso *dso = dsop ? *dsop : NULL;
  549. struct map *map = mapp ? *mapp : NULL;
  550. u64 ip = *ipp;
  551. if (!thread)
  552. return NULL;
  553. if (dso)
  554. goto got_dso;
  555. if (map)
  556. goto got_map;
  557. map = thread__find_map(thread, ip);
  558. if (map != NULL) {
  559. /*
  560. * We have to do this here as we may have a dso
  561. * with no symbol hit that has a name longer than
  562. * the ones with symbols sampled.
  563. */
  564. if (!sort_dso.elide && !map->dso->slen_calculated)
  565. dso__calc_col_width(map->dso);
  566. if (mapp)
  567. *mapp = map;
  568. got_map:
  569. ip = map->map_ip(map, ip);
  570. dso = map->dso;
  571. } else {
  572. /*
  573. * If this is outside of all known maps,
  574. * and is a negative address, try to look it
  575. * up in the kernel dso, as it might be a
  576. * vsyscall (which executes in user-mode):
  577. */
  578. if ((long long)ip < 0)
  579. dso = kernel_dso;
  580. }
  581. dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
  582. dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip);
  583. *ipp = ip;
  584. if (dsop)
  585. *dsop = dso;
  586. if (!dso)
  587. return NULL;
  588. got_dso:
  589. return dso->find_symbol(dso, ip);
  590. }
  591. static int call__match(struct symbol *sym)
  592. {
  593. if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
  594. return 1;
  595. return 0;
  596. }
  597. static struct symbol **
  598. resolve_callchain(struct thread *thread, struct map *map __used,
  599. struct ip_callchain *chain, struct hist_entry *entry)
  600. {
  601. u64 context = PERF_CONTEXT_MAX;
  602. struct symbol **syms = NULL;
  603. unsigned int i;
  604. if (callchain) {
  605. syms = calloc(chain->nr, sizeof(*syms));
  606. if (!syms) {
  607. fprintf(stderr, "Can't allocate memory for symbols\n");
  608. exit(-1);
  609. }
  610. }
  611. for (i = 0; i < chain->nr; i++) {
  612. u64 ip = chain->ips[i];
  613. struct dso *dso = NULL;
  614. struct symbol *sym;
  615. if (ip >= PERF_CONTEXT_MAX) {
  616. context = ip;
  617. continue;
  618. }
  619. switch (context) {
  620. case PERF_CONTEXT_HV:
  621. dso = hypervisor_dso;
  622. break;
  623. case PERF_CONTEXT_KERNEL:
  624. dso = kernel_dso;
  625. break;
  626. default:
  627. break;
  628. }
  629. sym = resolve_symbol(thread, NULL, &dso, &ip);
  630. if (sym) {
  631. if (sort__has_parent && call__match(sym) &&
  632. !entry->parent)
  633. entry->parent = sym;
  634. if (!callchain)
  635. break;
  636. syms[i] = sym;
  637. }
  638. }
  639. return syms;
  640. }
  641. /*
  642. * collect histogram counts
  643. */
  644. static int
  645. hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
  646. struct symbol *sym, u64 ip, struct ip_callchain *chain,
  647. char level, u64 count)
  648. {
  649. struct rb_node **p = &hist.rb_node;
  650. struct rb_node *parent = NULL;
  651. struct hist_entry *he;
  652. struct symbol **syms = NULL;
  653. struct hist_entry entry = {
  654. .thread = thread,
  655. .map = map,
  656. .dso = dso,
  657. .sym = sym,
  658. .ip = ip,
  659. .level = level,
  660. .count = count,
  661. .parent = NULL,
  662. .sorted_chain = RB_ROOT
  663. };
  664. int cmp;
  665. if ((sort__has_parent || callchain) && chain)
  666. syms = resolve_callchain(thread, map, chain, &entry);
  667. while (*p != NULL) {
  668. parent = *p;
  669. he = rb_entry(parent, struct hist_entry, rb_node);
  670. cmp = hist_entry__cmp(&entry, he);
  671. if (!cmp) {
  672. he->count += count;
  673. if (callchain) {
  674. append_chain(&he->callchain, chain, syms);
  675. free(syms);
  676. }
  677. return 0;
  678. }
  679. if (cmp < 0)
  680. p = &(*p)->rb_left;
  681. else
  682. p = &(*p)->rb_right;
  683. }
  684. he = malloc(sizeof(*he));
  685. if (!he)
  686. return -ENOMEM;
  687. *he = entry;
  688. if (callchain) {
  689. callchain_init(&he->callchain);
  690. append_chain(&he->callchain, chain, syms);
  691. free(syms);
  692. }
  693. rb_link_node(&he->rb_node, parent, p);
  694. rb_insert_color(&he->rb_node, &hist);
  695. return 0;
  696. }
  697. static void hist_entry__free(struct hist_entry *he)
  698. {
  699. free(he);
  700. }
  701. /*
  702. * collapse the histogram
  703. */
  704. static struct rb_root collapse_hists;
  705. static void collapse__insert_entry(struct hist_entry *he)
  706. {
  707. struct rb_node **p = &collapse_hists.rb_node;
  708. struct rb_node *parent = NULL;
  709. struct hist_entry *iter;
  710. int64_t cmp;
  711. while (*p != NULL) {
  712. parent = *p;
  713. iter = rb_entry(parent, struct hist_entry, rb_node);
  714. cmp = hist_entry__collapse(iter, he);
  715. if (!cmp) {
  716. iter->count += he->count;
  717. hist_entry__free(he);
  718. return;
  719. }
  720. if (cmp < 0)
  721. p = &(*p)->rb_left;
  722. else
  723. p = &(*p)->rb_right;
  724. }
  725. rb_link_node(&he->rb_node, parent, p);
  726. rb_insert_color(&he->rb_node, &collapse_hists);
  727. }
  728. static void collapse__resort(void)
  729. {
  730. struct rb_node *next;
  731. struct hist_entry *n;
  732. if (!sort__need_collapse)
  733. return;
  734. next = rb_first(&hist);
  735. while (next) {
  736. n = rb_entry(next, struct hist_entry, rb_node);
  737. next = rb_next(&n->rb_node);
  738. rb_erase(&n->rb_node, &hist);
  739. collapse__insert_entry(n);
  740. }
  741. }
  742. /*
  743. * reverse the map, sort on count.
  744. */
  745. static struct rb_root output_hists;
  746. static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
  747. {
  748. struct rb_node **p = &output_hists.rb_node;
  749. struct rb_node *parent = NULL;
  750. struct hist_entry *iter;
  751. if (callchain)
  752. callchain_param.sort(&he->sorted_chain, &he->callchain,
  753. min_callchain_hits, &callchain_param);
  754. while (*p != NULL) {
  755. parent = *p;
  756. iter = rb_entry(parent, struct hist_entry, rb_node);
  757. if (he->count > iter->count)
  758. p = &(*p)->rb_left;
  759. else
  760. p = &(*p)->rb_right;
  761. }
  762. rb_link_node(&he->rb_node, parent, p);
  763. rb_insert_color(&he->rb_node, &output_hists);
  764. }
  765. static void output__resort(u64 total_samples)
  766. {
  767. struct rb_node *next;
  768. struct hist_entry *n;
  769. struct rb_root *tree = &hist;
  770. u64 min_callchain_hits;
  771. min_callchain_hits = total_samples * (callchain_param.min_percent / 100);
  772. if (sort__need_collapse)
  773. tree = &collapse_hists;
  774. next = rb_first(tree);
  775. while (next) {
  776. n = rb_entry(next, struct hist_entry, rb_node);
  777. next = rb_next(&n->rb_node);
  778. rb_erase(&n->rb_node, tree);
  779. output__insert_entry(n, min_callchain_hits);
  780. }
  781. }
  782. static size_t output__fprintf(FILE *fp, u64 total_samples)
  783. {
  784. struct hist_entry *pos;
  785. struct sort_entry *se;
  786. struct rb_node *nd;
  787. size_t ret = 0;
  788. unsigned int width;
  789. char *col_width = col_width_list_str;
  790. int raw_printing_style;
  791. raw_printing_style = !strcmp(pretty_printing_style, "raw");
  792. init_rem_hits();
  793. fprintf(fp, "# Samples: %Ld\n", (u64)total_samples);
  794. fprintf(fp, "#\n");
  795. fprintf(fp, "# Overhead");
  796. if (show_nr_samples) {
  797. if (field_sep)
  798. fprintf(fp, "%cSamples", *field_sep);
  799. else
  800. fputs(" Samples ", fp);
  801. }
  802. list_for_each_entry(se, &hist_entry__sort_list, list) {
  803. if (se->elide)
  804. continue;
  805. if (field_sep) {
  806. fprintf(fp, "%c%s", *field_sep, se->header);
  807. continue;
  808. }
  809. width = strlen(se->header);
  810. if (se->width) {
  811. if (col_width_list_str) {
  812. if (col_width) {
  813. *se->width = atoi(col_width);
  814. col_width = strchr(col_width, ',');
  815. if (col_width)
  816. ++col_width;
  817. }
  818. }
  819. width = *se->width = max(*se->width, width);
  820. }
  821. fprintf(fp, " %*s", width, se->header);
  822. }
  823. fprintf(fp, "\n");
  824. if (field_sep)
  825. goto print_entries;
  826. fprintf(fp, "# ........");
  827. if (show_nr_samples)
  828. fprintf(fp, " ..........");
  829. list_for_each_entry(se, &hist_entry__sort_list, list) {
  830. unsigned int i;
  831. if (se->elide)
  832. continue;
  833. fprintf(fp, " ");
  834. if (se->width)
  835. width = *se->width;
  836. else
  837. width = strlen(se->header);
  838. for (i = 0; i < width; i++)
  839. fprintf(fp, ".");
  840. }
  841. fprintf(fp, "\n");
  842. fprintf(fp, "#\n");
  843. print_entries:
  844. for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
  845. pos = rb_entry(nd, struct hist_entry, rb_node);
  846. ret += hist_entry__fprintf(fp, pos, total_samples);
  847. }
  848. if (sort_order == default_sort_order &&
  849. parent_pattern == default_parent_pattern) {
  850. fprintf(fp, "#\n");
  851. fprintf(fp, "# (For a higher level overview, try: perf report --sort comm,dso)\n");
  852. fprintf(fp, "#\n");
  853. }
  854. fprintf(fp, "\n");
  855. free(rem_sq_bracket);
  856. if (show_threads)
  857. perf_read_values_display(fp, &show_threads_values,
  858. raw_printing_style);
  859. return ret;
  860. }
  861. static void register_idle_thread(void)
  862. {
  863. struct thread *thread = threads__findnew(0, &threads, &last_match);
  864. if (thread == NULL ||
  865. thread__set_comm_adjust(thread, "[idle]")) {
  866. fprintf(stderr, "problem inserting idle task.\n");
  867. exit(-1);
  868. }
  869. }
  870. static unsigned long total = 0,
  871. total_mmap = 0,
  872. total_comm = 0,
  873. total_fork = 0,
  874. total_unknown = 0,
  875. total_lost = 0;
  876. static int validate_chain(struct ip_callchain *chain, event_t *event)
  877. {
  878. unsigned int chain_size;
  879. chain_size = event->header.size;
  880. chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event;
  881. if (chain->nr*sizeof(u64) > chain_size)
  882. return -1;
  883. return 0;
  884. }
  885. static int
  886. process_sample_event(event_t *event, unsigned long offset, unsigned long head)
  887. {
  888. char level;
  889. int show = 0;
  890. struct dso *dso = NULL;
  891. struct thread *thread;
  892. u64 ip = event->ip.ip;
  893. u64 period = 1;
  894. struct map *map = NULL;
  895. void *more_data = event->ip.__more_data;
  896. struct ip_callchain *chain = NULL;
  897. int cpumode;
  898. thread = threads__findnew(event->ip.pid, &threads, &last_match);
  899. if (sample_type & PERF_SAMPLE_PERIOD) {
  900. period = *(u64 *)more_data;
  901. more_data += sizeof(u64);
  902. }
  903. dump_printf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n",
  904. (void *)(offset + head),
  905. (void *)(long)(event->header.size),
  906. event->header.misc,
  907. event->ip.pid, event->ip.tid,
  908. (void *)(long)ip,
  909. (long long)period);
  910. if (sample_type & PERF_SAMPLE_CALLCHAIN) {
  911. unsigned int i;
  912. chain = (void *)more_data;
  913. dump_printf("... chain: nr:%Lu\n", chain->nr);
  914. if (validate_chain(chain, event) < 0) {
  915. eprintf("call-chain problem with event, skipping it.\n");
  916. return 0;
  917. }
  918. if (dump_trace) {
  919. for (i = 0; i < chain->nr; i++)
  920. dump_printf("..... %2d: %016Lx\n", i, chain->ips[i]);
  921. }
  922. }
  923. dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
  924. if (thread == NULL) {
  925. eprintf("problem processing %d event, skipping it.\n",
  926. event->header.type);
  927. return -1;
  928. }
  929. if (comm_list && !strlist__has_entry(comm_list, thread->comm))
  930. return 0;
  931. cpumode = event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK;
  932. if (cpumode == PERF_EVENT_MISC_KERNEL) {
  933. show = SHOW_KERNEL;
  934. level = 'k';
  935. dso = kernel_dso;
  936. dump_printf(" ...... dso: %s\n", dso->name);
  937. } else if (cpumode == PERF_EVENT_MISC_USER) {
  938. show = SHOW_USER;
  939. level = '.';
  940. } else {
  941. show = SHOW_HV;
  942. level = 'H';
  943. dso = hypervisor_dso;
  944. dump_printf(" ...... dso: [hypervisor]\n");
  945. }
  946. if (show & show_mask) {
  947. struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip);
  948. if (dso_list && (!dso || !dso->name ||
  949. !strlist__has_entry(dso_list, dso->name)))
  950. return 0;
  951. if (sym_list && (!sym || !strlist__has_entry(sym_list, sym->name)))
  952. return 0;
  953. if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) {
  954. eprintf("problem incrementing symbol count, skipping event\n");
  955. return -1;
  956. }
  957. }
  958. total += period;
  959. return 0;
  960. }
  961. static int
  962. process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
  963. {
  964. struct thread *thread;
  965. struct map *map = map__new(&event->mmap, cwd, cwdlen);
  966. thread = threads__findnew(event->mmap.pid, &threads, &last_match);
  967. dump_printf("%p [%p]: PERF_EVENT_MMAP %d/%d: [%p(%p) @ %p]: %s\n",
  968. (void *)(offset + head),
  969. (void *)(long)(event->header.size),
  970. event->mmap.pid,
  971. event->mmap.tid,
  972. (void *)(long)event->mmap.start,
  973. (void *)(long)event->mmap.len,
  974. (void *)(long)event->mmap.pgoff,
  975. event->mmap.filename);
  976. if (thread == NULL || map == NULL) {
  977. dump_printf("problem processing PERF_EVENT_MMAP, skipping event.\n");
  978. return 0;
  979. }
  980. thread__insert_map(thread, map);
  981. total_mmap++;
  982. return 0;
  983. }
  984. static int
  985. process_comm_event(event_t *event, unsigned long offset, unsigned long head)
  986. {
  987. struct thread *thread;
  988. thread = threads__findnew(event->comm.pid, &threads, &last_match);
  989. dump_printf("%p [%p]: PERF_EVENT_COMM: %s:%d\n",
  990. (void *)(offset + head),
  991. (void *)(long)(event->header.size),
  992. event->comm.comm, event->comm.pid);
  993. if (thread == NULL ||
  994. thread__set_comm_adjust(thread, event->comm.comm)) {
  995. dump_printf("problem processing PERF_EVENT_COMM, skipping event.\n");
  996. return -1;
  997. }
  998. total_comm++;
  999. return 0;
  1000. }
  1001. static int
  1002. process_task_event(event_t *event, unsigned long offset, unsigned long head)
  1003. {
  1004. struct thread *thread;
  1005. struct thread *parent;
  1006. thread = threads__findnew(event->fork.pid, &threads, &last_match);
  1007. parent = threads__findnew(event->fork.ppid, &threads, &last_match);
  1008. dump_printf("%p [%p]: PERF_EVENT_%s: (%d:%d):(%d:%d)\n",
  1009. (void *)(offset + head),
  1010. (void *)(long)(event->header.size),
  1011. event->header.type == PERF_EVENT_FORK ? "FORK" : "EXIT",
  1012. event->fork.pid, event->fork.tid,
  1013. event->fork.ppid, event->fork.ptid);
  1014. /*
  1015. * A thread clone will have the same PID for both
  1016. * parent and child.
  1017. */
  1018. if (thread == parent)
  1019. return 0;
  1020. if (event->header.type == PERF_EVENT_EXIT)
  1021. return 0;
  1022. if (!thread || !parent || thread__fork(thread, parent)) {
  1023. dump_printf("problem processing PERF_EVENT_FORK, skipping event.\n");
  1024. return -1;
  1025. }
  1026. total_fork++;
  1027. return 0;
  1028. }
  1029. static int
  1030. process_lost_event(event_t *event, unsigned long offset, unsigned long head)
  1031. {
  1032. dump_printf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n",
  1033. (void *)(offset + head),
  1034. (void *)(long)(event->header.size),
  1035. event->lost.id,
  1036. event->lost.lost);
  1037. total_lost += event->lost.lost;
  1038. return 0;
  1039. }
  1040. static int
  1041. process_read_event(event_t *event, unsigned long offset, unsigned long head)
  1042. {
  1043. struct perf_counter_attr *attr;
  1044. attr = perf_header__find_attr(event->read.id, header);
  1045. if (show_threads) {
  1046. const char *name = attr ? __event_name(attr->type, attr->config)
  1047. : "unknown";
  1048. perf_read_values_add_value(&show_threads_values,
  1049. event->read.pid, event->read.tid,
  1050. event->read.id,
  1051. name,
  1052. event->read.value);
  1053. }
  1054. dump_printf("%p [%p]: PERF_EVENT_READ: %d %d %s %Lu\n",
  1055. (void *)(offset + head),
  1056. (void *)(long)(event->header.size),
  1057. event->read.pid,
  1058. event->read.tid,
  1059. attr ? __event_name(attr->type, attr->config)
  1060. : "FAIL",
  1061. event->read.value);
  1062. return 0;
  1063. }
  1064. static int
  1065. process_event(event_t *event, unsigned long offset, unsigned long head)
  1066. {
  1067. trace_event(event);
  1068. switch (event->header.type) {
  1069. case PERF_EVENT_SAMPLE:
  1070. return process_sample_event(event, offset, head);
  1071. case PERF_EVENT_MMAP:
  1072. return process_mmap_event(event, offset, head);
  1073. case PERF_EVENT_COMM:
  1074. return process_comm_event(event, offset, head);
  1075. case PERF_EVENT_FORK:
  1076. case PERF_EVENT_EXIT:
  1077. return process_task_event(event, offset, head);
  1078. case PERF_EVENT_LOST:
  1079. return process_lost_event(event, offset, head);
  1080. case PERF_EVENT_READ:
  1081. return process_read_event(event, offset, head);
  1082. /*
  1083. * We dont process them right now but they are fine:
  1084. */
  1085. case PERF_EVENT_THROTTLE:
  1086. case PERF_EVENT_UNTHROTTLE:
  1087. return 0;
  1088. default:
  1089. return -1;
  1090. }
  1091. return 0;
  1092. }
  1093. static int __cmd_report(void)
  1094. {
  1095. int ret, rc = EXIT_FAILURE;
  1096. unsigned long offset = 0;
  1097. unsigned long head, shift;
  1098. struct stat input_stat;
  1099. event_t *event;
  1100. uint32_t size;
  1101. char *buf;
  1102. register_idle_thread();
  1103. if (show_threads)
  1104. perf_read_values_init(&show_threads_values);
  1105. input = open(input_name, O_RDONLY);
  1106. if (input < 0) {
  1107. fprintf(stderr, " failed to open file: %s", input_name);
  1108. if (!strcmp(input_name, "perf.data"))
  1109. fprintf(stderr, " (try 'perf record' first)");
  1110. fprintf(stderr, "\n");
  1111. exit(-1);
  1112. }
  1113. ret = fstat(input, &input_stat);
  1114. if (ret < 0) {
  1115. perror("failed to stat file");
  1116. exit(-1);
  1117. }
  1118. if (!force && (input_stat.st_uid != geteuid())) {
  1119. fprintf(stderr, "file: %s not owned by current user\n", input_name);
  1120. exit(-1);
  1121. }
  1122. if (!input_stat.st_size) {
  1123. fprintf(stderr, "zero-sized file, nothing to do!\n");
  1124. exit(0);
  1125. }
  1126. header = perf_header__read(input);
  1127. head = header->data_offset;
  1128. sample_type = perf_header__sample_type(header);
  1129. if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
  1130. if (sort__has_parent) {
  1131. fprintf(stderr, "selected --sort parent, but no"
  1132. " callchain data. Did you call"
  1133. " perf record without -g?\n");
  1134. exit(-1);
  1135. }
  1136. if (callchain) {
  1137. fprintf(stderr, "selected -c but no callchain data."
  1138. " Did you call perf record without"
  1139. " -g?\n");
  1140. exit(-1);
  1141. }
  1142. } else if (callchain_param.mode != CHAIN_NONE && !callchain) {
  1143. callchain = 1;
  1144. if (register_callchain_param(&callchain_param) < 0) {
  1145. fprintf(stderr, "Can't register callchain"
  1146. " params\n");
  1147. exit(-1);
  1148. }
  1149. }
  1150. if (load_kernel() < 0) {
  1151. perror("failed to load kernel symbols");
  1152. return EXIT_FAILURE;
  1153. }
  1154. if (!full_paths) {
  1155. if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
  1156. perror("failed to get the current directory");
  1157. return EXIT_FAILURE;
  1158. }
  1159. cwdlen = strlen(cwd);
  1160. } else {
  1161. cwd = NULL;
  1162. cwdlen = 0;
  1163. }
  1164. shift = page_size * (head / page_size);
  1165. offset += shift;
  1166. head -= shift;
  1167. remap:
  1168. buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
  1169. MAP_SHARED, input, offset);
  1170. if (buf == MAP_FAILED) {
  1171. perror("failed to mmap file");
  1172. exit(-1);
  1173. }
  1174. more:
  1175. event = (event_t *)(buf + head);
  1176. size = event->header.size;
  1177. if (!size)
  1178. size = 8;
  1179. if (head + event->header.size >= page_size * mmap_window) {
  1180. int munmap_ret;
  1181. shift = page_size * (head / page_size);
  1182. munmap_ret = munmap(buf, page_size * mmap_window);
  1183. assert(munmap_ret == 0);
  1184. offset += shift;
  1185. head -= shift;
  1186. goto remap;
  1187. }
  1188. size = event->header.size;
  1189. dump_printf("\n%p [%p]: event: %d\n",
  1190. (void *)(offset + head),
  1191. (void *)(long)event->header.size,
  1192. event->header.type);
  1193. if (!size || process_event(event, offset, head) < 0) {
  1194. dump_printf("%p [%p]: skipping unknown header type: %d\n",
  1195. (void *)(offset + head),
  1196. (void *)(long)(event->header.size),
  1197. event->header.type);
  1198. total_unknown++;
  1199. /*
  1200. * assume we lost track of the stream, check alignment, and
  1201. * increment a single u64 in the hope to catch on again 'soon'.
  1202. */
  1203. if (unlikely(head & 7))
  1204. head &= ~7ULL;
  1205. size = 8;
  1206. }
  1207. head += size;
  1208. if (offset + head >= header->data_offset + header->data_size)
  1209. goto done;
  1210. if (offset + head < (unsigned long)input_stat.st_size)
  1211. goto more;
  1212. done:
  1213. rc = EXIT_SUCCESS;
  1214. close(input);
  1215. dump_printf(" IP events: %10ld\n", total);
  1216. dump_printf(" mmap events: %10ld\n", total_mmap);
  1217. dump_printf(" comm events: %10ld\n", total_comm);
  1218. dump_printf(" fork events: %10ld\n", total_fork);
  1219. dump_printf(" lost events: %10ld\n", total_lost);
  1220. dump_printf(" unknown events: %10ld\n", total_unknown);
  1221. if (dump_trace)
  1222. return 0;
  1223. if (verbose >= 3)
  1224. threads__fprintf(stdout, &threads);
  1225. if (verbose >= 2)
  1226. dsos__fprintf(stdout);
  1227. collapse__resort();
  1228. output__resort(total);
  1229. output__fprintf(stdout, total);
  1230. if (show_threads)
  1231. perf_read_values_destroy(&show_threads_values);
  1232. return rc;
  1233. }
  1234. static int
  1235. parse_callchain_opt(const struct option *opt __used, const char *arg,
  1236. int unset __used)
  1237. {
  1238. char *tok;
  1239. char *endptr;
  1240. callchain = 1;
  1241. if (!arg)
  1242. return 0;
  1243. tok = strtok((char *)arg, ",");
  1244. if (!tok)
  1245. return -1;
  1246. /* get the output mode */
  1247. if (!strncmp(tok, "graph", strlen(arg)))
  1248. callchain_param.mode = CHAIN_GRAPH_ABS;
  1249. else if (!strncmp(tok, "flat", strlen(arg)))
  1250. callchain_param.mode = CHAIN_FLAT;
  1251. else if (!strncmp(tok, "fractal", strlen(arg)))
  1252. callchain_param.mode = CHAIN_GRAPH_REL;
  1253. else if (!strncmp(tok, "none", strlen(arg))) {
  1254. callchain_param.mode = CHAIN_NONE;
  1255. callchain = 0;
  1256. return 0;
  1257. }
  1258. else
  1259. return -1;
  1260. /* get the min percentage */
  1261. tok = strtok(NULL, ",");
  1262. if (!tok)
  1263. goto setup;
  1264. callchain_param.min_percent = strtod(tok, &endptr);
  1265. if (tok == endptr)
  1266. return -1;
  1267. setup:
  1268. if (register_callchain_param(&callchain_param) < 0) {
  1269. fprintf(stderr, "Can't register callchain params\n");
  1270. return -1;
  1271. }
  1272. return 0;
  1273. }
  1274. static const char * const report_usage[] = {
  1275. "perf report [<options>] <command>",
  1276. NULL
  1277. };
  1278. static const struct option options[] = {
  1279. OPT_STRING('i', "input", &input_name, "file",
  1280. "input file name"),
  1281. OPT_BOOLEAN('v', "verbose", &verbose,
  1282. "be more verbose (show symbol address, etc)"),
  1283. OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
  1284. "dump raw trace in ASCII"),
  1285. OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"),
  1286. OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
  1287. OPT_BOOLEAN('m', "modules", &modules,
  1288. "load module symbols - WARNING: use only with -k and LIVE kernel"),
  1289. OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,
  1290. "Show a column with the number of samples"),
  1291. OPT_BOOLEAN('T', "threads", &show_threads,
  1292. "Show per-thread event counters"),
  1293. OPT_STRING(0, "pretty", &pretty_printing_style, "key",
  1294. "pretty printing style key: normal raw"),
  1295. OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
  1296. "sort by key(s): pid, comm, dso, symbol, parent"),
  1297. OPT_BOOLEAN('P', "full-paths", &full_paths,
  1298. "Don't shorten the pathnames taking into account the cwd"),
  1299. OPT_STRING('p', "parent", &parent_pattern, "regex",
  1300. "regex filter to identify parent, see: '--sort parent'"),
  1301. OPT_BOOLEAN('x', "exclude-other", &exclude_other,
  1302. "Only display entries with parent-match"),
  1303. OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent",
  1304. "Display callchains using output_type and min percent threshold. "
  1305. "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt),
  1306. OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
  1307. "only consider symbols in these dsos"),
  1308. OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]",
  1309. "only consider symbols in these comms"),
  1310. OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]",
  1311. "only consider these symbols"),
  1312. OPT_STRING('w', "column-widths", &col_width_list_str,
  1313. "width[,width...]",
  1314. "don't try to adjust column width, use these fixed values"),
  1315. OPT_STRING('t', "field-separator", &field_sep, "separator",
  1316. "separator for columns, no spaces will be added between "
  1317. "columns '.' is reserved."),
  1318. OPT_END()
  1319. };
  1320. static void setup_sorting(void)
  1321. {
  1322. char *tmp, *tok, *str = strdup(sort_order);
  1323. for (tok = strtok_r(str, ", ", &tmp);
  1324. tok; tok = strtok_r(NULL, ", ", &tmp)) {
  1325. if (sort_dimension__add(tok) < 0) {
  1326. error("Unknown --sort key: `%s'", tok);
  1327. usage_with_options(report_usage, options);
  1328. }
  1329. }
  1330. free(str);
  1331. }
  1332. static void setup_list(struct strlist **list, const char *list_str,
  1333. struct sort_entry *se, const char *list_name,
  1334. FILE *fp)
  1335. {
  1336. if (list_str) {
  1337. *list = strlist__new(true, list_str);
  1338. if (!*list) {
  1339. fprintf(stderr, "problems parsing %s list\n",
  1340. list_name);
  1341. exit(129);
  1342. }
  1343. if (strlist__nr_entries(*list) == 1) {
  1344. fprintf(fp, "# %s: %s\n", list_name,
  1345. strlist__entry(*list, 0)->s);
  1346. se->elide = true;
  1347. }
  1348. }
  1349. }
  1350. int cmd_report(int argc, const char **argv, const char *prefix __used)
  1351. {
  1352. symbol__init();
  1353. page_size = getpagesize();
  1354. argc = parse_options(argc, argv, options, report_usage, 0);
  1355. setup_sorting();
  1356. if (parent_pattern != default_parent_pattern) {
  1357. sort_dimension__add("parent");
  1358. sort_parent.elide = 1;
  1359. } else
  1360. exclude_other = 0;
  1361. /*
  1362. * Any (unrecognized) arguments left?
  1363. */
  1364. if (argc)
  1365. usage_with_options(report_usage, options);
  1366. setup_pager();
  1367. setup_list(&dso_list, dso_list_str, &sort_dso, "dso", stdout);
  1368. setup_list(&comm_list, comm_list_str, &sort_comm, "comm", stdout);
  1369. setup_list(&sym_list, sym_list_str, &sort_sym, "symbol", stdout);
  1370. if (field_sep && *field_sep == '.') {
  1371. fputs("'.' is the only non valid --field-separator argument\n",
  1372. stderr);
  1373. exit(129);
  1374. }
  1375. return __cmd_report();
  1376. }