callchain.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  1. /*
  2. * Copyright (C) 2009-2011, Frederic Weisbecker <fweisbec@gmail.com>
  3. *
  4. * Handle the callchains from the stream in an ad-hoc radix tree and then
  5. * sort them in an rbtree.
  6. *
  7. * Using a radix for code path provides a fast retrieval and factorizes
  8. * memory use. Also that lets us use the paths in a hierarchical graph view.
  9. *
  10. */
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <stdbool.h>
  14. #include <errno.h>
  15. #include <math.h>
  16. #include "asm/bug.h"
  17. #include "hist.h"
  18. #include "util.h"
  19. #include "sort.h"
  20. #include "machine.h"
  21. #include "callchain.h"
  22. __thread struct callchain_cursor callchain_cursor;
  23. #ifdef HAVE_DWARF_UNWIND_SUPPORT
  24. static int get_stack_size(const char *str, unsigned long *_size)
  25. {
  26. char *endptr;
  27. unsigned long size;
  28. unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
  29. size = strtoul(str, &endptr, 0);
  30. do {
  31. if (*endptr)
  32. break;
  33. size = round_up(size, sizeof(u64));
  34. if (!size || size > max_size)
  35. break;
  36. *_size = size;
  37. return 0;
  38. } while (0);
  39. pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
  40. max_size, str);
  41. return -1;
  42. }
  43. #endif /* HAVE_DWARF_UNWIND_SUPPORT */
  44. int parse_callchain_record_opt(const char *arg)
  45. {
  46. char *tok, *name, *saveptr = NULL;
  47. char *buf;
  48. int ret = -1;
  49. /* We need buffer that we know we can write to. */
  50. buf = malloc(strlen(arg) + 1);
  51. if (!buf)
  52. return -ENOMEM;
  53. strcpy(buf, arg);
  54. tok = strtok_r((char *)buf, ",", &saveptr);
  55. name = tok ? : (char *)buf;
  56. do {
  57. /* Framepointer style */
  58. if (!strncmp(name, "fp", sizeof("fp"))) {
  59. if (!strtok_r(NULL, ",", &saveptr)) {
  60. callchain_param.record_mode = CALLCHAIN_FP;
  61. ret = 0;
  62. } else
  63. pr_err("callchain: No more arguments "
  64. "needed for --call-graph fp\n");
  65. break;
  66. #ifdef HAVE_DWARF_UNWIND_SUPPORT
  67. /* Dwarf style */
  68. } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
  69. const unsigned long default_stack_dump_size = 8192;
  70. ret = 0;
  71. callchain_param.record_mode = CALLCHAIN_DWARF;
  72. callchain_param.dump_size = default_stack_dump_size;
  73. tok = strtok_r(NULL, ",", &saveptr);
  74. if (tok) {
  75. unsigned long size = 0;
  76. ret = get_stack_size(tok, &size);
  77. callchain_param.dump_size = size;
  78. }
  79. #endif /* HAVE_DWARF_UNWIND_SUPPORT */
  80. } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
  81. if (!strtok_r(NULL, ",", &saveptr)) {
  82. callchain_param.record_mode = CALLCHAIN_LBR;
  83. ret = 0;
  84. } else
  85. pr_err("callchain: No more arguments "
  86. "needed for --call-graph lbr\n");
  87. break;
  88. } else {
  89. pr_err("callchain: Unknown --call-graph option "
  90. "value: %s\n", arg);
  91. break;
  92. }
  93. } while (0);
  94. free(buf);
  95. return ret;
  96. }
  97. static int parse_callchain_mode(const char *value)
  98. {
  99. if (!strncmp(value, "graph", strlen(value))) {
  100. callchain_param.mode = CHAIN_GRAPH_ABS;
  101. return 0;
  102. }
  103. if (!strncmp(value, "flat", strlen(value))) {
  104. callchain_param.mode = CHAIN_FLAT;
  105. return 0;
  106. }
  107. if (!strncmp(value, "fractal", strlen(value))) {
  108. callchain_param.mode = CHAIN_GRAPH_REL;
  109. return 0;
  110. }
  111. return -1;
  112. }
  113. static int parse_callchain_order(const char *value)
  114. {
  115. if (!strncmp(value, "caller", strlen(value))) {
  116. callchain_param.order = ORDER_CALLER;
  117. return 0;
  118. }
  119. if (!strncmp(value, "callee", strlen(value))) {
  120. callchain_param.order = ORDER_CALLEE;
  121. return 0;
  122. }
  123. return -1;
  124. }
  125. static int parse_callchain_sort_key(const char *value)
  126. {
  127. if (!strncmp(value, "function", strlen(value))) {
  128. callchain_param.key = CCKEY_FUNCTION;
  129. return 0;
  130. }
  131. if (!strncmp(value, "address", strlen(value))) {
  132. callchain_param.key = CCKEY_ADDRESS;
  133. return 0;
  134. }
  135. if (!strncmp(value, "branch", strlen(value))) {
  136. callchain_param.branch_callstack = 1;
  137. return 0;
  138. }
  139. return -1;
  140. }
  141. int
  142. parse_callchain_report_opt(const char *arg)
  143. {
  144. char *tok;
  145. char *endptr;
  146. bool minpcnt_set = false;
  147. symbol_conf.use_callchain = true;
  148. if (!arg)
  149. return 0;
  150. while ((tok = strtok((char *)arg, ",")) != NULL) {
  151. if (!strncmp(tok, "none", strlen(tok))) {
  152. callchain_param.mode = CHAIN_NONE;
  153. symbol_conf.use_callchain = false;
  154. return 0;
  155. }
  156. if (!parse_callchain_mode(tok) ||
  157. !parse_callchain_order(tok) ||
  158. !parse_callchain_sort_key(tok)) {
  159. /* parsing ok - move on to the next */
  160. } else if (!minpcnt_set) {
  161. /* try to get the min percent */
  162. callchain_param.min_percent = strtod(tok, &endptr);
  163. if (tok == endptr)
  164. return -1;
  165. minpcnt_set = true;
  166. } else {
  167. /* try print limit at last */
  168. callchain_param.print_limit = strtoul(tok, &endptr, 0);
  169. if (tok == endptr)
  170. return -1;
  171. }
  172. arg = NULL;
  173. }
  174. if (callchain_register_param(&callchain_param) < 0) {
  175. pr_err("Can't register callchain params\n");
  176. return -1;
  177. }
  178. return 0;
  179. }
  180. int perf_callchain_config(const char *var, const char *value)
  181. {
  182. char *endptr;
  183. if (prefixcmp(var, "call-graph."))
  184. return 0;
  185. var += sizeof("call-graph.") - 1;
  186. if (!strcmp(var, "record-mode"))
  187. return parse_callchain_record_opt(value);
  188. #ifdef HAVE_DWARF_UNWIND_SUPPORT
  189. if (!strcmp(var, "dump-size")) {
  190. unsigned long size = 0;
  191. int ret;
  192. ret = get_stack_size(value, &size);
  193. callchain_param.dump_size = size;
  194. return ret;
  195. }
  196. #endif
  197. if (!strcmp(var, "print-type"))
  198. return parse_callchain_mode(value);
  199. if (!strcmp(var, "order"))
  200. return parse_callchain_order(value);
  201. if (!strcmp(var, "sort-key"))
  202. return parse_callchain_sort_key(value);
  203. if (!strcmp(var, "threshold")) {
  204. callchain_param.min_percent = strtod(value, &endptr);
  205. if (value == endptr)
  206. return -1;
  207. }
  208. if (!strcmp(var, "print-limit")) {
  209. callchain_param.print_limit = strtod(value, &endptr);
  210. if (value == endptr)
  211. return -1;
  212. }
  213. return 0;
  214. }
  215. static void
  216. rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
  217. enum chain_mode mode)
  218. {
  219. struct rb_node **p = &root->rb_node;
  220. struct rb_node *parent = NULL;
  221. struct callchain_node *rnode;
  222. u64 chain_cumul = callchain_cumul_hits(chain);
  223. while (*p) {
  224. u64 rnode_cumul;
  225. parent = *p;
  226. rnode = rb_entry(parent, struct callchain_node, rb_node);
  227. rnode_cumul = callchain_cumul_hits(rnode);
  228. switch (mode) {
  229. case CHAIN_FLAT:
  230. if (rnode->hit < chain->hit)
  231. p = &(*p)->rb_left;
  232. else
  233. p = &(*p)->rb_right;
  234. break;
  235. case CHAIN_GRAPH_ABS: /* Falldown */
  236. case CHAIN_GRAPH_REL:
  237. if (rnode_cumul < chain_cumul)
  238. p = &(*p)->rb_left;
  239. else
  240. p = &(*p)->rb_right;
  241. break;
  242. case CHAIN_NONE:
  243. default:
  244. break;
  245. }
  246. }
  247. rb_link_node(&chain->rb_node, parent, p);
  248. rb_insert_color(&chain->rb_node, root);
  249. }
  250. static void
  251. __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
  252. u64 min_hit)
  253. {
  254. struct rb_node *n;
  255. struct callchain_node *child;
  256. n = rb_first(&node->rb_root_in);
  257. while (n) {
  258. child = rb_entry(n, struct callchain_node, rb_node_in);
  259. n = rb_next(n);
  260. __sort_chain_flat(rb_root, child, min_hit);
  261. }
  262. if (node->hit && node->hit >= min_hit)
  263. rb_insert_callchain(rb_root, node, CHAIN_FLAT);
  264. }
  265. /*
  266. * Once we get every callchains from the stream, we can now
  267. * sort them by hit
  268. */
  269. static void
  270. sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
  271. u64 min_hit, struct callchain_param *param __maybe_unused)
  272. {
  273. __sort_chain_flat(rb_root, &root->node, min_hit);
  274. }
  275. static void __sort_chain_graph_abs(struct callchain_node *node,
  276. u64 min_hit)
  277. {
  278. struct rb_node *n;
  279. struct callchain_node *child;
  280. node->rb_root = RB_ROOT;
  281. n = rb_first(&node->rb_root_in);
  282. while (n) {
  283. child = rb_entry(n, struct callchain_node, rb_node_in);
  284. n = rb_next(n);
  285. __sort_chain_graph_abs(child, min_hit);
  286. if (callchain_cumul_hits(child) >= min_hit)
  287. rb_insert_callchain(&node->rb_root, child,
  288. CHAIN_GRAPH_ABS);
  289. }
  290. }
  291. static void
  292. sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root,
  293. u64 min_hit, struct callchain_param *param __maybe_unused)
  294. {
  295. __sort_chain_graph_abs(&chain_root->node, min_hit);
  296. rb_root->rb_node = chain_root->node.rb_root.rb_node;
  297. }
  298. static void __sort_chain_graph_rel(struct callchain_node *node,
  299. double min_percent)
  300. {
  301. struct rb_node *n;
  302. struct callchain_node *child;
  303. u64 min_hit;
  304. node->rb_root = RB_ROOT;
  305. min_hit = ceil(node->children_hit * min_percent);
  306. n = rb_first(&node->rb_root_in);
  307. while (n) {
  308. child = rb_entry(n, struct callchain_node, rb_node_in);
  309. n = rb_next(n);
  310. __sort_chain_graph_rel(child, min_percent);
  311. if (callchain_cumul_hits(child) >= min_hit)
  312. rb_insert_callchain(&node->rb_root, child,
  313. CHAIN_GRAPH_REL);
  314. }
  315. }
  316. static void
  317. sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root,
  318. u64 min_hit __maybe_unused, struct callchain_param *param)
  319. {
  320. __sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0);
  321. rb_root->rb_node = chain_root->node.rb_root.rb_node;
  322. }
  323. int callchain_register_param(struct callchain_param *param)
  324. {
  325. switch (param->mode) {
  326. case CHAIN_GRAPH_ABS:
  327. param->sort = sort_chain_graph_abs;
  328. break;
  329. case CHAIN_GRAPH_REL:
  330. param->sort = sort_chain_graph_rel;
  331. break;
  332. case CHAIN_FLAT:
  333. param->sort = sort_chain_flat;
  334. break;
  335. case CHAIN_NONE:
  336. default:
  337. return -1;
  338. }
  339. return 0;
  340. }
  341. /*
  342. * Create a child for a parent. If inherit_children, then the new child
  343. * will become the new parent of it's parent children
  344. */
  345. static struct callchain_node *
  346. create_child(struct callchain_node *parent, bool inherit_children)
  347. {
  348. struct callchain_node *new;
  349. new = zalloc(sizeof(*new));
  350. if (!new) {
  351. perror("not enough memory to create child for code path tree");
  352. return NULL;
  353. }
  354. new->parent = parent;
  355. INIT_LIST_HEAD(&new->val);
  356. if (inherit_children) {
  357. struct rb_node *n;
  358. struct callchain_node *child;
  359. new->rb_root_in = parent->rb_root_in;
  360. parent->rb_root_in = RB_ROOT;
  361. n = rb_first(&new->rb_root_in);
  362. while (n) {
  363. child = rb_entry(n, struct callchain_node, rb_node_in);
  364. child->parent = new;
  365. n = rb_next(n);
  366. }
  367. /* make it the first child */
  368. rb_link_node(&new->rb_node_in, NULL, &parent->rb_root_in.rb_node);
  369. rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
  370. }
  371. return new;
  372. }
  373. /*
  374. * Fill the node with callchain values
  375. */
  376. static void
  377. fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
  378. {
  379. struct callchain_cursor_node *cursor_node;
  380. node->val_nr = cursor->nr - cursor->pos;
  381. if (!node->val_nr)
  382. pr_warning("Warning: empty node in callchain tree\n");
  383. cursor_node = callchain_cursor_current(cursor);
  384. while (cursor_node) {
  385. struct callchain_list *call;
  386. call = zalloc(sizeof(*call));
  387. if (!call) {
  388. perror("not enough memory for the code path tree");
  389. return;
  390. }
  391. call->ip = cursor_node->ip;
  392. call->ms.sym = cursor_node->sym;
  393. call->ms.map = cursor_node->map;
  394. list_add_tail(&call->list, &node->val);
  395. callchain_cursor_advance(cursor);
  396. cursor_node = callchain_cursor_current(cursor);
  397. }
  398. }
  399. static struct callchain_node *
  400. add_child(struct callchain_node *parent,
  401. struct callchain_cursor *cursor,
  402. u64 period)
  403. {
  404. struct callchain_node *new;
  405. new = create_child(parent, false);
  406. fill_node(new, cursor);
  407. new->children_hit = 0;
  408. new->hit = period;
  409. return new;
  410. }
  411. static s64 match_chain(struct callchain_cursor_node *node,
  412. struct callchain_list *cnode)
  413. {
  414. struct symbol *sym = node->sym;
  415. if (cnode->ms.sym && sym &&
  416. callchain_param.key == CCKEY_FUNCTION)
  417. return cnode->ms.sym->start - sym->start;
  418. else
  419. return cnode->ip - node->ip;
  420. }
  421. /*
  422. * Split the parent in two parts (a new child is created) and
  423. * give a part of its callchain to the created child.
  424. * Then create another child to host the given callchain of new branch
  425. */
  426. static void
  427. split_add_child(struct callchain_node *parent,
  428. struct callchain_cursor *cursor,
  429. struct callchain_list *to_split,
  430. u64 idx_parents, u64 idx_local, u64 period)
  431. {
  432. struct callchain_node *new;
  433. struct list_head *old_tail;
  434. unsigned int idx_total = idx_parents + idx_local;
  435. /* split */
  436. new = create_child(parent, true);
  437. /* split the callchain and move a part to the new child */
  438. old_tail = parent->val.prev;
  439. list_del_range(&to_split->list, old_tail);
  440. new->val.next = &to_split->list;
  441. new->val.prev = old_tail;
  442. to_split->list.prev = &new->val;
  443. old_tail->next = &new->val;
  444. /* split the hits */
  445. new->hit = parent->hit;
  446. new->children_hit = parent->children_hit;
  447. parent->children_hit = callchain_cumul_hits(new);
  448. new->val_nr = parent->val_nr - idx_local;
  449. parent->val_nr = idx_local;
  450. /* create a new child for the new branch if any */
  451. if (idx_total < cursor->nr) {
  452. struct callchain_node *first;
  453. struct callchain_list *cnode;
  454. struct callchain_cursor_node *node;
  455. struct rb_node *p, **pp;
  456. parent->hit = 0;
  457. parent->children_hit += period;
  458. node = callchain_cursor_current(cursor);
  459. new = add_child(parent, cursor, period);
  460. /*
  461. * This is second child since we moved parent's children
  462. * to new (first) child above.
  463. */
  464. p = parent->rb_root_in.rb_node;
  465. first = rb_entry(p, struct callchain_node, rb_node_in);
  466. cnode = list_first_entry(&first->val, struct callchain_list,
  467. list);
  468. if (match_chain(node, cnode) < 0)
  469. pp = &p->rb_left;
  470. else
  471. pp = &p->rb_right;
  472. rb_link_node(&new->rb_node_in, p, pp);
  473. rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
  474. } else {
  475. parent->hit = period;
  476. }
  477. }
  478. static int
  479. append_chain(struct callchain_node *root,
  480. struct callchain_cursor *cursor,
  481. u64 period);
  482. static void
  483. append_chain_children(struct callchain_node *root,
  484. struct callchain_cursor *cursor,
  485. u64 period)
  486. {
  487. struct callchain_node *rnode;
  488. struct callchain_cursor_node *node;
  489. struct rb_node **p = &root->rb_root_in.rb_node;
  490. struct rb_node *parent = NULL;
  491. node = callchain_cursor_current(cursor);
  492. if (!node)
  493. return;
  494. /* lookup in childrens */
  495. while (*p) {
  496. s64 ret;
  497. parent = *p;
  498. rnode = rb_entry(parent, struct callchain_node, rb_node_in);
  499. /* If at least first entry matches, rely to children */
  500. ret = append_chain(rnode, cursor, period);
  501. if (ret == 0)
  502. goto inc_children_hit;
  503. if (ret < 0)
  504. p = &parent->rb_left;
  505. else
  506. p = &parent->rb_right;
  507. }
  508. /* nothing in children, add to the current node */
  509. rnode = add_child(root, cursor, period);
  510. rb_link_node(&rnode->rb_node_in, parent, p);
  511. rb_insert_color(&rnode->rb_node_in, &root->rb_root_in);
  512. inc_children_hit:
  513. root->children_hit += period;
  514. }
  515. static int
  516. append_chain(struct callchain_node *root,
  517. struct callchain_cursor *cursor,
  518. u64 period)
  519. {
  520. struct callchain_list *cnode;
  521. u64 start = cursor->pos;
  522. bool found = false;
  523. u64 matches;
  524. int cmp = 0;
  525. /*
  526. * Lookup in the current node
  527. * If we have a symbol, then compare the start to match
  528. * anywhere inside a function, unless function
  529. * mode is disabled.
  530. */
  531. list_for_each_entry(cnode, &root->val, list) {
  532. struct callchain_cursor_node *node;
  533. node = callchain_cursor_current(cursor);
  534. if (!node)
  535. break;
  536. cmp = match_chain(node, cnode);
  537. if (cmp)
  538. break;
  539. found = true;
  540. callchain_cursor_advance(cursor);
  541. }
  542. /* matches not, relay no the parent */
  543. if (!found) {
  544. WARN_ONCE(!cmp, "Chain comparison error\n");
  545. return cmp;
  546. }
  547. matches = cursor->pos - start;
  548. /* we match only a part of the node. Split it and add the new chain */
  549. if (matches < root->val_nr) {
  550. split_add_child(root, cursor, cnode, start, matches, period);
  551. return 0;
  552. }
  553. /* we match 100% of the path, increment the hit */
  554. if (matches == root->val_nr && cursor->pos == cursor->nr) {
  555. root->hit += period;
  556. return 0;
  557. }
  558. /* We match the node and still have a part remaining */
  559. append_chain_children(root, cursor, period);
  560. return 0;
  561. }
  562. int callchain_append(struct callchain_root *root,
  563. struct callchain_cursor *cursor,
  564. u64 period)
  565. {
  566. if (!cursor->nr)
  567. return 0;
  568. callchain_cursor_commit(cursor);
  569. append_chain_children(&root->node, cursor, period);
  570. if (cursor->nr > root->max_depth)
  571. root->max_depth = cursor->nr;
  572. return 0;
  573. }
  574. static int
  575. merge_chain_branch(struct callchain_cursor *cursor,
  576. struct callchain_node *dst, struct callchain_node *src)
  577. {
  578. struct callchain_cursor_node **old_last = cursor->last;
  579. struct callchain_node *child;
  580. struct callchain_list *list, *next_list;
  581. struct rb_node *n;
  582. int old_pos = cursor->nr;
  583. int err = 0;
  584. list_for_each_entry_safe(list, next_list, &src->val, list) {
  585. callchain_cursor_append(cursor, list->ip,
  586. list->ms.map, list->ms.sym);
  587. list_del(&list->list);
  588. free(list);
  589. }
  590. if (src->hit) {
  591. callchain_cursor_commit(cursor);
  592. append_chain_children(dst, cursor, src->hit);
  593. }
  594. n = rb_first(&src->rb_root_in);
  595. while (n) {
  596. child = container_of(n, struct callchain_node, rb_node_in);
  597. n = rb_next(n);
  598. rb_erase(&child->rb_node_in, &src->rb_root_in);
  599. err = merge_chain_branch(cursor, dst, child);
  600. if (err)
  601. break;
  602. free(child);
  603. }
  604. cursor->nr = old_pos;
  605. cursor->last = old_last;
  606. return err;
  607. }
  608. int callchain_merge(struct callchain_cursor *cursor,
  609. struct callchain_root *dst, struct callchain_root *src)
  610. {
  611. return merge_chain_branch(cursor, &dst->node, &src->node);
  612. }
  613. int callchain_cursor_append(struct callchain_cursor *cursor,
  614. u64 ip, struct map *map, struct symbol *sym)
  615. {
  616. struct callchain_cursor_node *node = *cursor->last;
  617. if (!node) {
  618. node = calloc(1, sizeof(*node));
  619. if (!node)
  620. return -ENOMEM;
  621. *cursor->last = node;
  622. }
  623. node->ip = ip;
  624. node->map = map;
  625. node->sym = sym;
  626. cursor->nr++;
  627. cursor->last = &node->next;
  628. return 0;
  629. }
  630. int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent,
  631. struct perf_evsel *evsel, struct addr_location *al,
  632. int max_stack)
  633. {
  634. if (sample->callchain == NULL)
  635. return 0;
  636. if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
  637. sort__has_parent) {
  638. return thread__resolve_callchain(al->thread, evsel, sample,
  639. parent, al, max_stack);
  640. }
  641. return 0;
  642. }
  643. int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
  644. {
  645. if (!symbol_conf.use_callchain || sample->callchain == NULL)
  646. return 0;
  647. return callchain_append(he->callchain, &callchain_cursor, sample->period);
  648. }
  649. int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
  650. bool hide_unresolved)
  651. {
  652. al->map = node->map;
  653. al->sym = node->sym;
  654. if (node->map)
  655. al->addr = node->map->map_ip(node->map, node->ip);
  656. else
  657. al->addr = node->ip;
  658. if (al->sym == NULL) {
  659. if (hide_unresolved)
  660. return 0;
  661. if (al->map == NULL)
  662. goto out;
  663. }
  664. if (al->map->groups == &al->machine->kmaps) {
  665. if (machine__is_host(al->machine)) {
  666. al->cpumode = PERF_RECORD_MISC_KERNEL;
  667. al->level = 'k';
  668. } else {
  669. al->cpumode = PERF_RECORD_MISC_GUEST_KERNEL;
  670. al->level = 'g';
  671. }
  672. } else {
  673. if (machine__is_host(al->machine)) {
  674. al->cpumode = PERF_RECORD_MISC_USER;
  675. al->level = '.';
  676. } else if (perf_guest) {
  677. al->cpumode = PERF_RECORD_MISC_GUEST_USER;
  678. al->level = 'u';
  679. } else {
  680. al->cpumode = PERF_RECORD_MISC_HYPERVISOR;
  681. al->level = 'H';
  682. }
  683. }
  684. out:
  685. return 1;
  686. }
  687. char *callchain_list__sym_name(struct callchain_list *cl,
  688. char *bf, size_t bfsize, bool show_dso)
  689. {
  690. int printed;
  691. if (cl->ms.sym) {
  692. if (callchain_param.key == CCKEY_ADDRESS &&
  693. cl->ms.map && !cl->srcline)
  694. cl->srcline = get_srcline(cl->ms.map->dso,
  695. map__rip_2objdump(cl->ms.map,
  696. cl->ip),
  697. cl->ms.sym, false);
  698. if (cl->srcline)
  699. printed = scnprintf(bf, bfsize, "%s %s",
  700. cl->ms.sym->name, cl->srcline);
  701. else
  702. printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
  703. } else
  704. printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
  705. if (show_dso)
  706. scnprintf(bf + printed, bfsize - printed, " %s",
  707. cl->ms.map ?
  708. cl->ms.map->dso->short_name :
  709. "unknown");
  710. return bf;
  711. }
  712. static void free_callchain_node(struct callchain_node *node)
  713. {
  714. struct callchain_list *list, *tmp;
  715. struct callchain_node *child;
  716. struct rb_node *n;
  717. list_for_each_entry_safe(list, tmp, &node->val, list) {
  718. list_del(&list->list);
  719. free(list);
  720. }
  721. n = rb_first(&node->rb_root_in);
  722. while (n) {
  723. child = container_of(n, struct callchain_node, rb_node_in);
  724. n = rb_next(n);
  725. rb_erase(&child->rb_node_in, &node->rb_root_in);
  726. free_callchain_node(child);
  727. free(child);
  728. }
  729. }
  730. void free_callchain(struct callchain_root *root)
  731. {
  732. if (!symbol_conf.use_callchain)
  733. return;
  734. free_callchain_node(&root->node);
  735. }