1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdio.h>
2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/util.h"
4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/hist.h"
5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/sort.h"
6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/evsel.h"
7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int ret = fprintf(fp, "            ");
13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < left_margin; i++)
15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret += fprintf(fp, " ");
16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					  int left_margin)
22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t ret = callchain__fprintf_left_margin(fp, left_margin);
25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < depth; i++)
27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (depth_mask & (1 << i))
28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret += fprintf(fp, "|          ");
29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret += fprintf(fp, "           ");
31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret += fprintf(fp, "\n");
33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				     int depth, int depth_mask, int period,
39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				     u64 total_samples, u64 hits,
40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				     int left_margin)
41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t ret = 0;
44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret += callchain__fprintf_left_margin(fp, left_margin);
46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < depth; i++) {
47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (depth_mask & (1 << i))
48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret += fprintf(fp, "|");
49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret += fprintf(fp, " ");
51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!period && i == depth - 1) {
52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			double percent;
53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			percent = hits * 100.0 / total_samples;
55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		} else
57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret += fprintf(fp, "%s", "          ");
58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (chain->ms.sym)
60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret += fprintf(fp, "%s\n", chain->ms.sym->name);
61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else
62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip);
63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct symbol *rem_sq_bracket;
68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct callchain_list rem_hits;
69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void init_rem_hits(void)
71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!rem_sq_bracket) {
74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fprintf(stderr, "Not enough memory to display remaining hits\n");
75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return;
76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	strcpy(rem_sq_bracket->name, "[...]");
79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	rem_hits.ms.sym = rem_sq_bracket;
80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					 u64 total_samples, int depth,
84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					 int depth_mask, int left_margin)
85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *node, *next;
87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct callchain_node *child;
88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct callchain_list *chain;
89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int new_depth_mask = depth_mask;
90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u64 remaining;
91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t ret = 0;
92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	uint entries_printed = 0;
94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	remaining = total_samples;
96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	node = rb_first(root);
98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (node) {
99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		u64 new_total;
100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		u64 cumul;
101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		child = rb_entry(node, struct callchain_node, rb_node);
103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		cumul = callchain_cumul_hits(child);
104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		remaining -= cumul;
105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/*
107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * The depth mask manages the output of pipes that show
108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * the depth. We don't want to keep the pipes of the current
109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * level for the last child of this depth.
110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * Except if we have remaining filtered hits. They will
111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * supersede the last child
112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 */
113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		next = rb_next(node);
114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			new_depth_mask &= ~(1 << (depth - 1));
116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/*
118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * But we keep the older depth mask for the line separator
119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * to keep the level link until we reach the last child
120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 */
121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						   left_margin);
123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		i = 0;
124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		list_for_each_entry(chain, &child->val, list) {
125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret += ipchain__fprintf_graph(fp, chain, depth,
126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						      new_depth_mask, i++,
127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						      total_samples,
128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						      cumul,
129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						      left_margin);
130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (callchain_param.mode == CHAIN_GRAPH_REL)
133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			new_total = child->children_hit;
134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			new_total = total_samples;
136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret += __callchain__fprintf_graph(fp, &child->rb_root, new_total,
138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						  depth + 1,
139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						  new_depth_mask | (1 << depth),
140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						  left_margin);
141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		node = next;
142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (++entries_printed == callchain_param.print_limit)
143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (callchain_param.mode == CHAIN_GRAPH_REL &&
147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		remaining && remaining != total_samples) {
148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!rem_sq_bracket)
150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			return ret;
151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		new_depth_mask &= ~(1 << (depth - 1));
153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					      new_depth_mask, 0, total_samples,
155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					      remaining, left_margin);
156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				       u64 total_samples, int left_margin)
163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct callchain_node *cnode;
165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct callchain_list *chain;
166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u32 entries_printed = 0;
167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	bool printed = false;
168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *node;
169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i = 0;
170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int ret = 0;
171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/*
173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * If have one single callchain root, don't bother printing
174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * its percentage (100 % in fractal mode and the same percentage
175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * than the hist in graph mode). This also avoid one level of column.
176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 */
177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	node = rb_first(root);
178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (node && !rb_next(node)) {
179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		cnode = rb_entry(node, struct callchain_node, rb_node);
180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		list_for_each_entry(chain, &cnode->val, list) {
181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			/*
182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 * If we sort by symbol, the first entry is the same than
183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 * the symbol. No need to print it otherwise it appears as
184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 * displayed twice.
185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 */
186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (!i++ && sort__first_dimension == SORT_SYM)
187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				continue;
188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (!printed) {
189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				ret += callchain__fprintf_left_margin(fp, left_margin);
190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				ret += fprintf(fp, "|\n");
191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				ret += callchain__fprintf_left_margin(fp, left_margin);
192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				ret += fprintf(fp, "---");
193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				left_margin += 3;
194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				printed = true;
195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			} else
196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				ret += callchain__fprintf_left_margin(fp, left_margin);
197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (chain->ms.sym)
199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				ret += fprintf(fp, " %s\n", chain->ms.sym->name);
200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			else
201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (++entries_printed == callchain_param.print_limit)
204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				break;
205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		root = &cnode->rb_root;
207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret += __callchain__fprintf_graph(fp, root, total_samples,
210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					  1, 1, left_margin);
211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret += fprintf(fp, "\n");
212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t __callchain__fprintf_flat(FILE *fp,
217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					struct callchain_node *self,
218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					u64 total_samples)
219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct callchain_list *chain;
221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t ret = 0;
222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!self)
224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret += __callchain__fprintf_flat(fp, self->parent, total_samples);
227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	list_for_each_entry(chain, &self->val, list) {
230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (chain->ip >= PERF_CONTEXT_MAX)
231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (chain->ms.sym)
233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret += fprintf(fp, "                %s\n", chain->ms.sym->name);
234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret += fprintf(fp, "                %p\n",
236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					(void *)(long)chain->ip);
237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self,
243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				      u64 total_samples)
244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t ret = 0;
246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u32 entries_printed = 0;
247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *rb_node;
248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct callchain_node *chain;
249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	rb_node = rb_first(self);
251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (rb_node) {
252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		double percent;
253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		chain = rb_entry(rb_node, struct callchain_node, rb_node);
255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		percent = chain->hit * 100.0 / total_samples;
256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret = percent_color_fprintf(fp, "           %6.2f%%\n", percent);
258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret += __callchain__fprintf_flat(fp, chain, total_samples);
259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret += fprintf(fp, "\n");
260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (++entries_printed == callchain_param.print_limit)
261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		rb_node = rb_next(rb_node);
264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t hist_entry_callchain__fprintf(struct hist_entry *he,
270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					    u64 total_samples, int left_margin,
271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					    FILE *fp)
272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	switch (callchain_param.mode) {
274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case CHAIN_GRAPH_REL:
275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return callchain__fprintf_graph(fp, &he->sorted_chain, he->stat.period,
276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						left_margin);
277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case CHAIN_GRAPH_ABS:
279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples,
280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						left_margin);
281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case CHAIN_FLAT:
283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples);
284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case CHAIN_NONE:
286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	default:
288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_err("Bad callchain mode\n");
289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t hist_entry__callchain_fprintf(struct hist_entry *he,
295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					    struct hists *hists,
296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					    FILE *fp)
297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int left_margin = 0;
299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u64 total_period = hists->stats.total_period;
300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (sort__first_dimension == SORT_COMM) {
302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng							 typeof(*se), list);
304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		left_margin = hists__col_len(hists, se->se_width_idx);
305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		left_margin -= thread__comm_len(he->thread);
306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return hist_entry_callchain__fprintf(he, total_period, left_margin, fp);
309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic inline void advance_hpp(struct perf_hpp *hpp, int inc)
312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	hpp->buf  += inc;
314e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	hpp->size -= inc;
315e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
316e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
317e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int hist_entry__period_snprintf(struct perf_hpp *hpp,
318e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				       struct hist_entry *he)
319e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
320e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *sep = symbol_conf.field_sep;
321e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_hpp_fmt *fmt;
322e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char *start = hpp->buf;
323e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int ret;
324e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	bool first = true;
325e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
326e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (symbol_conf.exclude_other && !he->parent)
327e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
328e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
329e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	perf_hpp__for_each_format(fmt) {
330e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/*
331e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * If there's no field_sep, we still need
332e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * to display initial '  '.
333e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 */
334e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!sep || !first) {
335e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: "  ");
336e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			advance_hpp(hpp, ret);
337e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		} else
338e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			first = false;
339e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
340e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (perf_hpp__use_color() && fmt->color)
341e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret = fmt->color(fmt, hpp, he);
342e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
343e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret = fmt->entry(fmt, hpp, he);
344e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
345e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		advance_hpp(hpp, ret);
346e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
347e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
348e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return hpp->buf - start;
349e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
350e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
351e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int hist_entry__fprintf(struct hist_entry *he, size_t size,
352e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			       struct hists *hists,
353e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			       char *bf, size_t bfsz, FILE *fp)
354e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
355e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int ret;
356e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_hpp hpp = {
357e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.buf		= bf,
358e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.size		= size,
359e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	};
360e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
361e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (size == 0 || size > bfsz)
362e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		size = hpp.size = bfsz;
363e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
364e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret = hist_entry__period_snprintf(&hpp, he);
365e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	hist_entry__sort_snprintf(he, bf + ret, size - ret, hists);
366e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
367e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret = fprintf(fp, "%s\n", bf);
368e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
369e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (symbol_conf.use_callchain)
370e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret += hist_entry__callchain_fprintf(he, hists, fp);
371e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
372e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
373e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
374e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
375e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
376e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		      int max_cols, float min_pcnt, FILE *fp)
377e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
378e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_hpp_fmt *fmt;
379e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct sort_entry *se;
380e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *nd;
381e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t ret = 0;
382e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	unsigned int width;
383e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *sep = symbol_conf.field_sep;
384e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *col_width = symbol_conf.col_width_list_str;
385e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int nr_rows = 0;
386e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char bf[96];
387e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_hpp dummy_hpp = {
388e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.buf	= bf,
389e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.size	= sizeof(bf),
390e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.ptr	= hists_to_evsel(hists),
391e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	};
392e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	bool first = true;
393e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t linesz;
394e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char *line = NULL;
395e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
396e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	init_rem_hits();
397e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
398e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!show_header)
399e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto print_entries;
400e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
401e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fprintf(fp, "# ");
402e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
403e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	perf_hpp__for_each_format(fmt) {
404e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!first)
405e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			fprintf(fp, "%s", sep ?: "  ");
406e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
407e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			first = false;
408e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
409e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fmt->header(fmt, &dummy_hpp);
410e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fprintf(fp, "%s", bf);
411e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
412e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
413e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	list_for_each_entry(se, &hist_entry__sort_list, list) {
414e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (se->elide)
415e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
416e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (sep) {
417e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			fprintf(fp, "%c%s", *sep, se->se_header);
418e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
419e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
420e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		width = strlen(se->se_header);
421e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (symbol_conf.col_width_list_str) {
422e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (col_width) {
423e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				hists__set_col_len(hists, se->se_width_idx,
424e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						   atoi(col_width));
425e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				col_width = strchr(col_width, ',');
426e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				if (col_width)
427e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					++col_width;
428e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			}
429e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
430e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!hists__new_col_len(hists, se->se_width_idx, width))
431e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			width = hists__col_len(hists, se->se_width_idx);
432e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fprintf(fp, "  %*s", width, se->se_header);
433e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
434e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
435e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fprintf(fp, "\n");
436e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (max_rows && ++nr_rows >= max_rows)
437e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out;
438e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
439e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (sep)
440e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto print_entries;
441e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
442e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	first = true;
443e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
444e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fprintf(fp, "# ");
445e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
446e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	perf_hpp__for_each_format(fmt) {
447e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		unsigned int i;
448e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
449e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!first)
450e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			fprintf(fp, "%s", sep ?: "  ");
451e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
452e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			first = false;
453e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
454e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		width = fmt->width(fmt, &dummy_hpp);
455e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		for (i = 0; i < width; i++)
456e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			fprintf(fp, ".");
457e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
458e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
459e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	list_for_each_entry(se, &hist_entry__sort_list, list) {
460e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		unsigned int i;
461e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
462e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (se->elide)
463e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
464e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
465e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fprintf(fp, "  ");
466e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		width = hists__col_len(hists, se->se_width_idx);
467e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (width == 0)
468e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			width = strlen(se->se_header);
469e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		for (i = 0; i < width; i++)
470e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			fprintf(fp, ".");
471e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
472e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
473e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fprintf(fp, "\n");
474e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (max_rows && ++nr_rows >= max_rows)
475e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out;
476e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
477e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fprintf(fp, "#\n");
478e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (max_rows && ++nr_rows >= max_rows)
479e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out;
480e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
481e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengprint_entries:
482e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	linesz = hists__sort_list_width(hists) + 3 + 1;
483e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	linesz += perf_hpp__color_overhead();
484e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	line = malloc(linesz);
485e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (line == NULL) {
486e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret = -1;
487e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out;
488e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
489e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
490e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
491e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
492e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		float percent = h->stat.period * 100.0 /
493e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					hists->stats.total_period;
494e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
495e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (h->filtered)
496e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
497e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
498e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (percent < min_pcnt)
499e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
500e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
501e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret += hist_entry__fprintf(h, max_cols, hists, line, linesz, fp);
502e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
503e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (max_rows && ++nr_rows >= max_rows)
504e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
505e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
506e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (h->ms.map == NULL && verbose > 1) {
507e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			__map_groups__fprintf_maps(&h->thread->mg,
508e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						   MAP__FUNCTION, verbose, fp);
509e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			fprintf(fp, "%.10s end\n", graph_dotted_line);
510e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
511e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
512e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
513e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	free(line);
514e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout:
515e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	free(rem_sq_bracket);
516e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
517e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
518e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
519e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
520e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t events_stats__fprintf(struct events_stats *stats, FILE *fp)
521e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
522e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
523e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t ret = 0;
524e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
525e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
526e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		const char *name;
527e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
528e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (stats->nr_events[i] == 0)
529e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
530e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
531e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		name = perf_event__name(i);
532e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!strcmp(name, "UNKNOWN"))
533e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
534e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
535e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret += fprintf(fp, "%16s events: %10d\n", name,
536e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			       stats->nr_events[i]);
537e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
538e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
539e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
540e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
541