builtin-annotate.c 23 KB

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