builtin-annotate.c 23 KB

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