1/**
2 * @file format_output.h
3 * outputting format for symbol lists
4 *
5 * @remark Copyright 2002 OProfile authors
6 * @remark Read the file COPYING
7 *
8 * @author Philippe Elie
9 * @author John Levon
10 */
11
12#ifndef FORMAT_OUTPUT_H
13#define FORMAT_OUTPUT_H
14
15#include "config.h"
16
17#include <string>
18#include <map>
19#include <iosfwd>
20
21#include "format_flags.h"
22#include "symbol.h"
23#include "string_filter.h"
24#include "xml_output.h"
25
26class symbol_entry;
27class sample_entry;
28class callgraph_container;
29class profile_container;
30class diff_container;
31class extra_images;
32class op_bfd;
33
34struct profile_classes;
35// FIXME: should be passed to the derived class formatter ctor
36extern profile_classes classes;
37
38namespace format_output {
39
40/// base class for formatter, handle common options to formatter
41class formatter {
42public:
43	formatter(extra_images const & extra);
44	virtual ~formatter();
45
46	/// add a given column
47	void add_format(format_flags flag);
48
49	/// set the need_header boolean to false
50	void show_header(bool);
51	/// format for 64 bit wide VMAs
52	void vma_format_64bit(bool);
53	/// show long (full path) filenames
54	void show_long_filenames(bool);
55	/// use global count rather symbol count for details percent
56	void show_global_percent(bool);
57
58	/**
59	 * Set the number of collected profile classes. Each class
60	 * will output sample count and percentage in extra columns.
61	 *
62	 * This class assumes that the profile information has been
63	 * populated with the right number of classes.
64	 */
65	void set_nr_classes(size_t nr_classes);
66
67	/// output table header, implemented by calling the virtual function
68	/// output_header_field()
69	void output_header(std::ostream & out);
70
71protected:
72	struct counts_t {
73		/// total sample count
74		count_array_t total;
75		/// samples so far
76		count_array_t cumulated_samples;
77		/// percentage so far
78		count_array_t cumulated_percent;
79		/// detailed percentage so far
80		count_array_t cumulated_percent_details;
81	};
82
83	/// data passed for output
84	struct field_datum {
85		field_datum(symbol_entry const & sym,
86		            sample_entry const & s,
87			    size_t pc, counts_t & c,
88			    extra_images const & extra, double d = 0.0)
89			: symbol(sym), sample(s), pclass(pc),
90			  counts(c), extra(extra), diff(d) {}
91		symbol_entry const & symbol;
92		sample_entry const & sample;
93		size_t pclass;
94		counts_t & counts;
95		extra_images const & extra;
96		double diff;
97	};
98
99	/// format callback type
100	typedef std::string (formatter::*fct_format)(field_datum const &);
101
102	/** @name format functions.
103	 * The set of formatting functions, used internally by output().
104	 */
105	//@{
106	std::string format_vma(field_datum const &);
107	std::string format_symb_name(field_datum const &);
108	std::string format_image_name(field_datum const &);
109	std::string format_app_name(field_datum const &);
110	std::string format_linenr_info(field_datum const &);
111	std::string format_nr_samples(field_datum const &);
112	std::string format_nr_cumulated_samples(field_datum const &);
113	std::string format_percent(field_datum const &);
114	std::string format_cumulated_percent(field_datum const &);
115	std::string format_percent_details(field_datum const &);
116	std::string format_cumulated_percent_details(field_datum const &);
117	std::string format_diff(field_datum const &);
118	//@}
119
120	/// decribe one field of the colummned output.
121	struct field_description {
122		field_description() {}
123		field_description(std::size_t w, std::string h,
124				  fct_format f)
125			: width(w), header_name(h), formatter(f) {}
126
127		std::size_t width;
128		std::string header_name;
129		fct_format formatter;
130	};
131
132	typedef std::map<format_flags, field_description> format_map_t;
133
134	/// actually do output
135	void do_output(std::ostream & out, symbol_entry const & symbol,
136		      sample_entry const & sample, counts_t & c,
137	              diff_array_t const & = diff_array_t(),
138	              bool hide_immutable_field = false);
139
140	/// returns the nr of char needed to pad this field
141	size_t output_header_field(std::ostream & out, format_flags fl,
142	                           size_t padding);
143
144	/// returns the nr of char needed to pad this field
145	size_t output_field(std::ostream & out, field_datum const & datum,
146			   format_flags fl, size_t padding,
147			   bool hide_immutable);
148
149	/// stores functors for doing actual formatting
150	format_map_t format_map;
151
152	/// number of profile classes
153	size_t nr_classes;
154
155	/// total counts
156	counts_t counts;
157
158	/// formatting flags set
159	format_flags flags;
160	/// true if we need to format as 64 bits quantities
161	bool vma_64;
162	/// false if we use basename(filename) in output rather filename
163	bool long_filenames;
164	/// true if we need to show header before the first output
165	bool need_header;
166	/// bool if details percentage are relative to total count rather to
167	/// symbol count
168	bool global_percent;
169
170	/// To retrieve the real image location, usefull when acting on
171	/// an archive and for 2.6 kernel modules
172	extra_images const & extra_found_images;
173};
174
175
176/// class to output in a columned format symbols and associated samples
177class opreport_formatter : public formatter {
178public:
179	/// build a ready to use formatter
180	opreport_formatter(profile_container const & profile);
181
182	/** output a vector of symbols to out according to the output format
183	 * specifier previously set by call(s) to add_format() */
184	void output(std::ostream & out, symbol_collection const & syms);
185
186	/// set the output_details boolean
187	void show_details(bool);
188
189private:
190
191	/** output one symbol symb to out according to the output format
192	 * specifier previously set by call(s) to add_format() */
193	void output(std::ostream & out, symbol_entry const * symb);
194
195	/// output details for the symbol
196	void output_details(std::ostream & out, symbol_entry const * symb);
197
198	/// container we work from
199	profile_container const & profile;
200
201	/// true if we need to show details for each symbols
202	bool need_details;
203};
204
205
206/// class to output in a columned format caller/callee and associated samples
207class cg_formatter : public formatter {
208public:
209	/// build a ready to use formatter
210	cg_formatter(callgraph_container const & profile);
211
212	/** output callgraph information according to the previously format
213	 * specifier set by call(s) to add_format() */
214	void output(std::ostream & out, symbol_collection const & syms);
215};
216
217/// class to output a columned format symbols plus diff values
218class diff_formatter : public formatter {
219public:
220	/// build a ready to use formatter
221	diff_formatter(diff_container const & profile,
222		       extra_images const & extra);
223
224	/**
225	 * Output a vector of symbols to out according to the output
226	 * format specifier previously set by call(s) to add_format()
227	 */
228	void output(std::ostream & out, diff_collection const & syms);
229
230private:
231	/// output a single symbol
232	void output(std::ostream & out, diff_symbol const & sym);
233
234};
235
236
237/// class to output in XML format
238class xml_formatter : public formatter {
239public:
240	/// build a ready to use formatter
241	xml_formatter(profile_container const * profile,
242		      symbol_collection & symbols, extra_images const & extra,
243		      string_filter const & symbol_filter);
244
245	// output body of XML output
246	void output(std::ostream & out);
247
248	/** output one symbol symb to out according to the output format
249	 * specifier previously set by call(s) to add_format() */
250	virtual void output_symbol(std::ostream & out,
251		symbol_entry const * symb, size_t lo, size_t hi,
252		bool is_module);
253
254	/// output details for the symbol
255	std::string output_symbol_details(symbol_entry const * symb,
256		size_t & detail_index, size_t const lo, size_t const hi);
257
258	/// set the output_details boolean
259	void show_details(bool);
260
261	// output SymbolData XML elements
262	void output_symbol_data(std::ostream & out);
263
264private:
265	/// container we work from
266	profile_container const * profile;
267
268	// ordered collection of symbols associated with this profile
269	symbol_collection & symbols;
270
271	/// true if we need to show details for each symbols
272	bool need_details;
273
274	// count of DetailData items output so far
275	size_t detail_count;
276
277	/// with --details we need to reopen the bfd object for each symb to
278	/// get it's contents, hence we store the filter used by the bfd ctor.
279	string_filter const & symbol_filter;
280
281	void output_sample_data(std::ostream & out,
282		sample_entry const & sample, size_t count);
283
284	/// output attribute in XML
285	void output_attribute(std::ostream & out, field_datum const & datum,
286			      format_flags fl, tag_t tag);
287
288	/// Retrieve a bfd object for this symbol, reopening a new bfd object
289	/// only if necessary
290	bool get_bfd_object(symbol_entry const * symb, op_bfd * & abfd) const;
291
292	void output_the_symbol_data(std::ostream & out,
293		symbol_entry const * symb, op_bfd * & abfd);
294
295	void output_cg_children(std::ostream & out,
296		cg_symbol::children const cg_symb, op_bfd * & abfd);
297};
298
299// callgraph XML output version
300class xml_cg_formatter : public xml_formatter {
301public:
302	/// build a ready to use formatter
303	xml_cg_formatter(callgraph_container const & callgraph,
304		symbol_collection & symbols, string_filter const & sf);
305
306	/** output one symbol symb to out according to the output format
307	 * specifier previously set by call(s) to add_format() */
308	virtual void output_symbol(std::ostream & out,
309		symbol_entry const * symb, size_t lo, size_t hi, bool is_module);
310
311private:
312	/// container we work from
313	callgraph_container const & callgraph;
314
315	void output_symbol_core(std::ostream & out,
316		cg_symbol::children const cg_symb,
317		std::string const selfname, std::string const qname,
318		size_t lo, size_t hi, bool is_module, tag_t tag);
319};
320
321} // namespace format_output
322
323
324#endif /* !FORMAT_OUTPUT_H */
325