Mike Dodd | 8cfa702 | 2010-11-17 11:12:26 -0800 | [diff] [blame] | 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 | |
| 26 | class symbol_entry; |
| 27 | class sample_entry; |
| 28 | class callgraph_container; |
| 29 | class profile_container; |
| 30 | class diff_container; |
| 31 | class extra_images; |
| 32 | class op_bfd; |
| 33 | |
| 34 | struct profile_classes; |
| 35 | // FIXME: should be passed to the derived class formatter ctor |
| 36 | extern profile_classes classes; |
| 37 | |
| 38 | namespace format_output { |
| 39 | |
| 40 | /// base class for formatter, handle common options to formatter |
| 41 | class formatter { |
| 42 | public: |
| 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 | |
| 71 | protected: |
| 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; |
Conley Owens | d390240 | 2011-11-09 14:05:49 -0800 | [diff] [blame^] | 94 | counts_t & counts; |
Mike Dodd | 8cfa702 | 2010-11-17 11:12:26 -0800 | [diff] [blame] | 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 |
| 177 | class opreport_formatter : public formatter { |
| 178 | public: |
| 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 | |
| 189 | private: |
| 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 |
| 207 | class cg_formatter : public formatter { |
| 208 | public: |
| 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 |
| 218 | class diff_formatter : public formatter { |
| 219 | public: |
| 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 | |
| 230 | private: |
| 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 |
| 238 | class xml_formatter : public formatter { |
| 239 | public: |
| 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 | |
| 264 | private: |
| 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 |
| 300 | class xml_cg_formatter : public xml_formatter { |
| 301 | public: |
| 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 | |
| 311 | private: |
| 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 */ |