callchain.c 19 KB

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