/** * @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; 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 */