/**
* @file format_output.h
* outputting format for symbol lists
*
* @remark Copyright 2002 OProfile authors
* @remark Read the file COPYING
*
* @author Philippe Elie
* @author John Levon
*/
#ifndef FORMAT_OUTPUT_H
#define FORMAT_OUTPUT_H
#include "config.h"
#include <string>
#include <map>
#include <iosfwd>
#include "format_flags.h"
#include "symbol.h"
#include "string_filter.h"
#include "xml_output.h"
class symbol_entry;
class sample_entry;
class callgraph_container;
class profile_container;
class diff_container;
class extra_images;
class op_bfd;
struct profile_classes;
// FIXME: should be passed to the derived class formatter ctor
extern profile_classes classes;
namespace format_output {
/// base class for formatter, handle common options to formatter
class formatter {
public:
formatter(extra_images const & extra);
virtual ~formatter();
/// add a given column
void add_format(format_flags flag);
/// set the need_header boolean to false
void show_header(bool);
/// format for 64 bit wide VMAs
void vma_format_64bit(bool);
/// show long (full path) filenames
void show_long_filenames(bool);
/// use global count rather symbol count for details percent
void show_global_percent(bool);
/**
* Set the number of collected profile classes. Each class
* will output sample count and percentage in extra columns.
*
* This class assumes that the profile information has been
* populated with the right number of classes.
*/
void set_nr_classes(size_t nr_classes);
/// output table header, implemented by calling the virtual function
/// output_header_field()
void output_header(std::ostream & out);
protected:
struct counts_t {
/// total sample count
count_array_t total;
/// samples so far
count_array_t cumulated_samples;
/// percentage so far
count_array_t cumulated_percent;
/// detailed percentage so far
count_array_t cumulated_percent_details;
};
/// data passed for output
struct field_datum {
field_datum(symbol_entry const & sym,
sample_entry const & s,
size_t pc, counts_t & c,
extra_images const & extra, double d = 0.0)
: symbol(sym), sample(s), pclass(pc),
counts(c), extra(extra), diff(d) {}
symbol_entry const & symbol;
sample_entry const & sample;
size_t pclass;
mutable counts_t & counts;
extra_images const & extra;
double diff;
};
/// format callback type
typedef std::string (formatter::*fct_format)(field_datum const &);
/** @name format functions.
* The set of formatting functions, used internally by output().
*/
//@{
std::string format_vma(field_datum const &);
std::string format_symb_name(field_datum const &);
std::string format_image_name(field_datum const &);
std::string format_app_name(field_datum const &);
std::string format_linenr_info(field_datum const &);
std::string format_nr_samples(field_datum const &);
std::string format_nr_cumulated_samples(field_datum const &);
std::string format_percent(field_datum const &);
std::string format_cumulated_percent(field_datum const &);
std::string format_percent_details(field_datum const &);
std::string format_cumulated_percent_details(field_datum const &);
std::string format_diff(field_datum const &);
//@}
/// decribe one field of the colummned output.
struct field_description {
field_description() {}
field_description(std::size_t w, std::string h,
fct_format f)
: width(w), header_name(h), formatter(f) {}
std::size_t width;
std::string header_name;
fct_format formatter;
};
typedef std::map<format_flags, field_description> format_map_t;
/// actually do output
void do_output(std::ostream & out, symbol_entry const & symbol,
sample_entry const & sample, counts_t & c,
diff_array_t const & = diff_array_t(),
bool hide_immutable_field = false);
/// returns the nr of char needed to pad this field
size_t output_header_field(std::ostream & out, format_flags fl,
size_t padding);
/// returns the nr of char needed to pad this field
size_t output_field(std::ostream & out, field_datum const & datum,
format_flags fl, size_t padding,
bool hide_immutable);
/// stores functors for doing actual formatting
format_map_t format_map;
/// number of profile classes
size_t nr_classes;
/// total counts
counts_t counts;
/// formatting flags set
format_flags flags;
/// true if we need to format as 64 bits quantities
bool vma_64;
/// false if we use basename(filename) in output rather filename
bool long_filenames;
/// true if we need to show header before the first output
bool need_header;
/// bool if details percentage are relative to total count rather to
/// symbol count
bool global_percent;
/// To retrieve the real image location, usefull when acting on
/// an archive and for 2.6 kernel modules
extra_images const & extra_found_images;
};
/// class to output in a columned format symbols and associated samples
class opreport_formatter : public formatter {
public:
/// build a ready to use formatter
opreport_formatter(profile_container const & profile);
/** output a vector of symbols to out according to the output format
* specifier previously set by call(s) to add_format() */
void output(std::ostream & out, symbol_collection const & syms);
/// set the output_details boolean
void show_details(bool);
private:
/** output one symbol symb to out according to the output format
* specifier previously set by call(s) to add_format() */
void output(std::ostream & out, symbol_entry const * symb);
/// output details for the symbol
void output_details(std::ostream & out, symbol_entry const * symb);
/// container we work from
profile_container const & profile;
/// true if we need to show details for each symbols
bool need_details;
};
/// class to output in a columned format caller/callee and associated samples
class cg_formatter : public formatter {
public:
/// build a ready to use formatter
cg_formatter(callgraph_container const & profile);
/** output callgraph information according to the previously format
* specifier set by call(s) to add_format() */
void output(std::ostream & out, symbol_collection const & syms);
};
/// class to output a columned format symbols plus diff values
class diff_formatter : public formatter {
public:
/// build a ready to use formatter
diff_formatter(diff_container const & profile,
extra_images const & extra);
/**
* Output a vector of symbols to out according to the output
* format specifier previously set by call(s) to add_format()
*/
void output(std::ostream & out, diff_collection const & syms);
private:
/// output a single symbol
void output(std::ostream & out, diff_symbol const & sym);
};
/// class to output in XML format
class xml_formatter : public formatter {
public:
/// build a ready to use formatter
xml_formatter(profile_container const * profile,
symbol_collection & symbols, extra_images const & extra,
string_filter const & symbol_filter);
// output body of XML output
void output(std::ostream & out);
/** output one symbol symb to out according to the output format
* specifier previously set by call(s) to add_format() */
virtual void output_symbol(std::ostream & out,
symbol_entry const * symb, size_t lo, size_t hi,
bool is_module);
/// output details for the symbol
std::string output_symbol_details(symbol_entry const * symb,
size_t & detail_index, size_t const lo, size_t const hi);
/// set the output_details boolean
void show_details(bool);
// output SymbolData XML elements
void output_symbol_data(std::ostream & out);
private:
/// container we work from
profile_container const * profile;
// ordered collection of symbols associated with this profile
symbol_collection & symbols;
/// true if we need to show details for each symbols
bool need_details;
// count of DetailData items output so far
size_t detail_count;
/// with --details we need to reopen the bfd object for each symb to
/// get it's contents, hence we store the filter used by the bfd ctor.
string_filter const & symbol_filter;
void output_sample_data(std::ostream & out,
sample_entry const & sample, size_t count);
/// output attribute in XML
void output_attribute(std::ostream & out, field_datum const & datum,
format_flags fl, tag_t tag);
/// Retrieve a bfd object for this symbol, reopening a new bfd object
/// only if necessary
bool get_bfd_object(symbol_entry const * symb, op_bfd * & abfd) const;
void output_the_symbol_data(std::ostream & out,
symbol_entry const * symb, op_bfd * & abfd);
void output_cg_children(std::ostream & out,
cg_symbol::children const cg_symb, op_bfd * & abfd);
};
// callgraph XML output version
class xml_cg_formatter : public xml_formatter {
public:
/// build a ready to use formatter
xml_cg_formatter(callgraph_container const & callgraph,
symbol_collection & symbols, string_filter const & sf);
/** output one symbol symb to out according to the output format
* specifier previously set by call(s) to add_format() */
virtual void output_symbol(std::ostream & out,
symbol_entry const * symb, size_t lo, size_t hi, bool is_module);
private:
/// container we work from
callgraph_container const & callgraph;
void output_symbol_core(std::ostream & out,
cg_symbol::children const cg_symb,
std::string const selfname, std::string const qname,
size_t lo, size_t hi, bool is_module, tag_t tag);
};
} // namespace format_output
#endif /* !FORMAT_OUTPUT_H */