00001
00012
00013 #ifndef _GNU_SOURCE
00014 #define _GNU_SOURCE
00015 #endif
00016
00017 #include <cassert>
00018 #include <sstream>
00019 #include <iomanip>
00020 #include <iostream>
00021 #include <cmath>
00022
00023 #include "string_manip.h"
00024 #include "string_filter.h"
00025
00026 #include "format_output.h"
00027 #include "profile_container.h"
00028 #include "callgraph_container.h"
00029 #include "diff_container.h"
00030 #include "arrange_profiles.h"
00031 #include "xml_output.h"
00032 #include "xml_utils.h"
00033 #include "cverb.h"
00034
00035 using namespace std;
00036
00037 namespace {
00038
00039
00040 string const get_linenr_info(file_location const floc, bool lf)
00041 {
00042 ostringstream out;
00043
00044 string const & filename = lf
00045 ? debug_names.name(floc.filename)
00046 : debug_names.basename(floc.filename);
00047
00048 if (!filename.empty())
00049 out << filename << ":" << floc.linenr;
00050 else
00051 out << "(no location information)";
00052
00053 return out.str();
00054 }
00055
00056 string get_vma(bfd_vma vma, bool vma_64)
00057 {
00058 ostringstream out;
00059 int width = vma_64 ? 16 : 8;
00060
00061 out << hex << setw(width) << setfill('0') << vma;
00062
00063 return out.str();
00064 }
00065
00066 string get_percent(count_type dividend, count_type divisor)
00067 {
00068 double ratio = op_ratio(dividend, divisor);
00069
00070 return ::format_percent(ratio * 100, percent_int_width,
00071 percent_fract_width);
00072 }
00073
00074 bool extract_linenr_info(string const & info, string & file, size_t & line)
00075 {
00076 line = 0;
00077 file = "";
00078 string::size_type colon_pos = info.find(":");
00079
00080 if (colon_pos == string::npos)
00081 return false;
00082
00083 file = info.substr(0, colon_pos);
00084 istringstream is_info(info.substr(colon_pos+1));
00085 is_info >> line;
00086 return true;
00087 }
00088
00089
00090 }
00091
00092 namespace format_output {
00093
00094 formatter::formatter(extra_images const & extra)
00095 :
00096 nr_classes(1),
00097 flags(ff_none),
00098 vma_64(false),
00099 long_filenames(false),
00100 need_header(true),
00101 extra_found_images(extra)
00102 {
00103 format_map[ff_vma] = field_description(9, "vma", &formatter::format_vma);
00104 format_map[ff_nr_samples] = field_description(9, "samples", &formatter::format_nr_samples);
00105 format_map[ff_nr_samples_cumulated] = field_description(14, "cum. samples", &formatter::format_nr_cumulated_samples);
00106 format_map[ff_percent] = field_description(9, "%", &formatter::format_percent);
00107 format_map[ff_percent_cumulated] = field_description(11, "cum. %", &formatter::format_cumulated_percent);
00108 format_map[ff_linenr_info] = field_description(28, "linenr info", &formatter::format_linenr_info);
00109 format_map[ff_image_name] = field_description(25, "image name", &formatter::format_image_name);
00110 format_map[ff_app_name] = field_description(25, "app name", &formatter::format_app_name);
00111 format_map[ff_symb_name] = field_description(30, "symbol name", &formatter::format_symb_name);
00112 format_map[ff_percent_details] = field_description(9, "%", &formatter::format_percent_details);
00113 format_map[ff_percent_cumulated_details] = field_description(10, "cum. %", &formatter::format_cumulated_percent_details);
00114 format_map[ff_diff] = field_description(10, "diff %", &formatter::format_diff);
00115 }
00116
00117
00118 formatter::~formatter()
00119 {
00120 }
00121
00122
00123 void formatter::set_nr_classes(size_t nr)
00124 {
00125 nr_classes = nr;
00126 }
00127
00128
00129 void formatter::add_format(format_flags flag)
00130 {
00131 flags = static_cast<format_flags>(flags | flag);
00132 }
00133
00134
00135 void formatter::show_header(bool on_off)
00136 {
00137 need_header = on_off;
00138 }
00139
00140
00141 void formatter::vma_format_64bit(bool on_off)
00142 {
00143 vma_64 = on_off;
00144 }
00145
00146
00147 void formatter::show_long_filenames(bool on_off)
00148 {
00149 long_filenames = on_off;
00150 }
00151
00152
00153 void formatter::show_global_percent(bool on_off)
00154 {
00155 global_percent = on_off;
00156 }
00157
00158
00159 void formatter::output_header(ostream & out)
00160 {
00161 if (!need_header)
00162 return;
00163
00164 size_t padding = 0;
00165
00166
00167 if (flags & ff_vma)
00168 padding = output_header_field(out, ff_vma, padding);
00169
00170
00171 for (size_t pclass = 0 ; pclass < nr_classes; ++pclass) {
00172 if (flags & ff_nr_samples)
00173 padding = output_header_field(out,
00174 ff_nr_samples, padding);
00175
00176 if (flags & ff_nr_samples_cumulated)
00177 padding = output_header_field(out,
00178 ff_nr_samples_cumulated, padding);
00179
00180 if (flags & ff_percent)
00181 padding = output_header_field(out,
00182 ff_percent, padding);
00183
00184 if (flags & ff_percent_cumulated)
00185 padding = output_header_field(out,
00186 ff_percent_cumulated, padding);
00187
00188 if (flags & ff_diff)
00189 padding = output_header_field(out,
00190 ff_diff, padding);
00191
00192 if (flags & ff_percent_details)
00193 padding = output_header_field(out,
00194 ff_percent_details, padding);
00195
00196 if (flags & ff_percent_cumulated_details)
00197 padding = output_header_field(out,
00198 ff_percent_cumulated_details, padding);
00199 }
00200
00201
00202 if (flags & ff_linenr_info)
00203 padding = output_header_field(out, ff_linenr_info, padding);
00204
00205 if (flags & ff_image_name)
00206 padding = output_header_field(out, ff_image_name, padding);
00207
00208 if (flags & ff_app_name)
00209 padding = output_header_field(out, ff_app_name, padding);
00210
00211 if (flags & ff_symb_name)
00212 padding = output_header_field(out, ff_symb_name, padding);
00213
00214 out << "\n";
00215 }
00216
00217
00219
00220
00221
00222
00223 size_t formatter::
00224 output_field(ostream & out, field_datum const & datum,
00225 format_flags fl, size_t padding, bool hide_immutable)
00226 {
00227 if (!hide_immutable) {
00228 out << string(padding, ' ');
00229
00230 field_description const & field(format_map[fl]);
00231 string str = (this->*field.formatter)(datum);
00232 out << str;
00233
00234
00235 padding = 1;
00236 if (str.length() < field.width)
00237 padding = field.width - str.length();
00238 } else {
00239 field_description const & field(format_map[fl]);
00240 padding += field.width;
00241 }
00242
00243 return padding;
00244 }
00245
00246
00247 size_t formatter::
00248 output_header_field(ostream & out, format_flags fl, size_t padding)
00249 {
00250 out << string(padding, ' ');
00251
00252 field_description const & field(format_map[fl]);
00253 out << field.header_name;
00254
00255
00256 padding = 1;
00257 if (field.header_name.length() < field.width)
00258 padding = field.width - field.header_name.length();
00259
00260 return padding;
00261 }
00262
00263
00264 string formatter::format_vma(field_datum const & f)
00265 {
00266 return get_vma(f.sample.vma, vma_64);
00267 }
00268
00269
00270 string formatter::format_symb_name(field_datum const & f)
00271 {
00272 return symbol_names.demangle(f.symbol.name);
00273 }
00274
00275
00276 string formatter::format_image_name(field_datum const & f)
00277 {
00278 return get_image_name(f.symbol.image_name,
00279 long_filenames
00280 ? image_name_storage::int_real_filename
00281 : image_name_storage::int_real_basename,
00282 extra_found_images);
00283 }
00284
00285
00286 string formatter::format_app_name(field_datum const & f)
00287 {
00288 return get_image_name(f.symbol.app_name,
00289 long_filenames
00290 ? image_name_storage::int_real_filename
00291 : image_name_storage::int_real_basename,
00292 extra_found_images);
00293 }
00294
00295
00296 string formatter::format_linenr_info(field_datum const & f)
00297 {
00298 return get_linenr_info(f.sample.file_loc, long_filenames);
00299 }
00300
00301
00302 string formatter::format_nr_samples(field_datum const & f)
00303 {
00304 ostringstream out;
00305 out << f.sample.counts[f.pclass];
00306 return out.str();
00307 }
00308
00309
00310 string formatter::format_nr_cumulated_samples(field_datum const & f)
00311 {
00312 if (f.diff == -INFINITY)
00313 return "---";
00314 ostringstream out;
00315 f.counts.cumulated_samples[f.pclass] += f.sample.counts[f.pclass];
00316 out << f.counts.cumulated_samples[f.pclass];
00317 return out.str();
00318 }
00319
00320
00321 string formatter::format_percent(field_datum const & f)
00322 {
00323 if (f.diff == -INFINITY)
00324 return "---";
00325 return get_percent(f.sample.counts[f.pclass], f.counts.total[f.pclass]);
00326 }
00327
00328
00329 string formatter::format_cumulated_percent(field_datum const & f)
00330 {
00331 if (f.diff == -INFINITY)
00332 return "---";
00333 f.counts.cumulated_percent[f.pclass] += f.sample.counts[f.pclass];
00334
00335 return get_percent(f.counts.cumulated_percent[f.pclass],
00336 f.counts.total[f.pclass]);
00337 }
00338
00339
00340 string formatter::format_percent_details(field_datum const & f)
00341 {
00342 return get_percent(f.sample.counts[f.pclass],
00343 f.counts.total[f.pclass]);
00344 }
00345
00346
00347 string formatter::format_cumulated_percent_details(field_datum const & f)
00348 {
00349 f.counts.cumulated_percent_details[f.pclass] += f.sample.counts[f.pclass];
00350
00351 return get_percent(f.counts.cumulated_percent_details[f.pclass],
00352 f.counts.total[f.pclass]);
00353 }
00354
00355
00356 string formatter::format_diff(field_datum const & f)
00357 {
00358 if (f.diff == INFINITY)
00359 return "+++";
00360 else if (f.diff == -INFINITY)
00361 return "---";
00362
00363 return ::format_percent(f.diff, percent_int_width,
00364 percent_fract_width, true);
00365 }
00366
00367
00368 void formatter::
00369 do_output(ostream & out, symbol_entry const & symb, sample_entry const & sample,
00370 counts_t & c, diff_array_t const & diffs, bool hide_immutable)
00371 {
00372 size_t padding = 0;
00373
00374
00375 field_datum datum(symb, sample, 0, c, extra_found_images);
00376 if (flags & ff_vma)
00377 padding = output_field(out, datum, ff_vma, padding, false);
00378
00379
00380 for (size_t pclass = 0 ; pclass < nr_classes; ++pclass) {
00381 field_datum datum(symb, sample, pclass, c,
00382 extra_found_images, diffs[pclass]);
00383
00384 if (flags & ff_nr_samples)
00385 padding = output_field(out, datum,
00386 ff_nr_samples, padding, false);
00387
00388 if (flags & ff_nr_samples_cumulated)
00389 padding = output_field(out, datum,
00390 ff_nr_samples_cumulated, padding, false);
00391
00392 if (flags & ff_percent)
00393 padding = output_field(out, datum,
00394 ff_percent, padding, false);
00395
00396 if (flags & ff_percent_cumulated)
00397 padding = output_field(out, datum,
00398 ff_percent_cumulated, padding, false);
00399
00400 if (flags & ff_diff)
00401 padding = output_field(out, datum,
00402 ff_diff, padding, false);
00403
00404 if (flags & ff_percent_details)
00405 padding = output_field(out, datum,
00406 ff_percent_details, padding, false);
00407
00408 if (flags & ff_percent_cumulated_details)
00409 padding = output_field(out, datum,
00410 ff_percent_cumulated_details, padding, false);
00411 }
00412
00413
00414 if (flags & ff_linenr_info)
00415 padding = output_field(out, datum, ff_linenr_info,
00416 padding, false);
00417
00418 if (flags & ff_image_name)
00419 padding = output_field(out, datum, ff_image_name,
00420 padding, hide_immutable);
00421
00422 if (flags & ff_app_name)
00423 padding = output_field(out, datum, ff_app_name,
00424 padding, hide_immutable);
00425
00426 if (flags & ff_symb_name)
00427 padding = output_field(out, datum, ff_symb_name,
00428 padding, hide_immutable);
00429
00430 out << "\n";
00431 }
00432
00433
00434 opreport_formatter::opreport_formatter(profile_container const & p)
00435 :
00436 formatter(p.extra_found_images),
00437 profile(p),
00438 need_details(false)
00439 {
00440 counts.total = profile.samples_count();
00441 }
00442
00443
00444 void opreport_formatter::show_details(bool on_off)
00445 {
00446 need_details = on_off;
00447 }
00448
00449
00450 void opreport_formatter::output(ostream & out, symbol_entry const * symb)
00451 {
00452 do_output(out, *symb, symb->sample, counts);
00453
00454 if (need_details)
00455 output_details(out, symb);
00456 }
00457
00458
00459 void opreport_formatter::
00460 output(ostream & out, symbol_collection const & syms)
00461 {
00462 output_header(out);
00463
00464 symbol_collection::const_iterator it = syms.begin();
00465 symbol_collection::const_iterator end = syms.end();
00466 for (; it != end; ++it)
00467 output(out, *it);
00468 }
00469
00470
00471 void opreport_formatter::
00472 output_details(ostream & out, symbol_entry const * symb)
00473 {
00474 counts_t c = counts;
00475
00476 if (!global_percent)
00477 c.total = symb->sample.counts;
00478
00479
00480 c.cumulated_samples = count_array_t();
00481 c.cumulated_percent = count_array_t();
00482
00483 sample_container::samples_iterator it = profile.begin(symb);
00484 sample_container::samples_iterator end = profile.end(symb);
00485 for (; it != end; ++it) {
00486 out << " ";
00487 do_output(out, *symb, it->second, c, diff_array_t(), true);
00488 }
00489 }
00490
00491
00492 cg_formatter::cg_formatter(callgraph_container const & profile)
00493 :
00494 formatter(profile.extra_found_images)
00495 {
00496 counts.total = profile.samples_count();
00497 }
00498
00499
00500 void cg_formatter::output(ostream & out, symbol_collection const & syms)
00501 {
00502
00503 string const child_parent_prefix(" ");
00504
00505 output_header(out);
00506
00507 out << string(79, '-') << endl;
00508
00509 symbol_collection::const_iterator it;
00510 symbol_collection::const_iterator end = syms.end();
00511
00512 for (it = syms.begin(); it < end; ++it) {
00513 cg_symbol const * sym = dynamic_cast<cg_symbol const *>(*it);
00514
00515 cg_symbol::children::const_iterator cit;
00516 cg_symbol::children::const_iterator cend = sym->callers.end();
00517
00518 counts_t c;
00519 if (global_percent)
00520 c.total = counts.total;
00521 else
00522 c.total = sym->total_caller_count;
00523
00524 for (cit = sym->callers.begin(); cit != cend; ++cit) {
00525 out << child_parent_prefix;
00526 do_output(out, *cit, cit->sample, c);
00527 }
00528
00529 do_output(out, *sym, sym->sample, counts);
00530
00531 c = counts_t();
00532 if (global_percent)
00533 c.total = counts.total;
00534 else
00535 c.total = sym->total_callee_count;
00536
00537 cend = sym->callees.end();
00538
00539 for (cit = sym->callees.begin(); cit != cend; ++cit) {
00540 out << child_parent_prefix;
00541 do_output(out, *cit, cit->sample, c);
00542 }
00543
00544 out << string(79, '-') << endl;
00545 }
00546 }
00547
00548
00549 diff_formatter::diff_formatter(diff_container const & profile,
00550 extra_images const & extra)
00551 :
00552 formatter(extra)
00553 {
00554 counts.total = profile.samples_count();
00555 }
00556
00557
00558 void diff_formatter::output(ostream & out, diff_collection const & syms)
00559 {
00560 output_header(out);
00561
00562 diff_collection::const_iterator it = syms.begin();
00563 diff_collection::const_iterator end = syms.end();
00564 for (; it != end; ++it)
00565 do_output(out, *it, it->sample, counts, it->diffs);
00566 }
00567
00568
00569
00570 ostringstream bytes_out;
00571
00572
00573 map<string, size_t> symbol_data_table;
00574 size_t symbol_data_index = 0;
00575
00576
00577 size_t xml_get_symbol_index(string const & name)
00578 {
00579 size_t index = symbol_data_index;
00580 map<string, size_t>::iterator it = symbol_data_table.find(name);
00581
00582 if (it == symbol_data_table.end()) {
00583 symbol_data_table[name] = symbol_data_index++;
00584 return index;
00585 }
00586
00587 return it->second;
00588 }
00589
00590
00591 class symbol_details_t {
00592 public:
00593 symbol_details_t() { size = index = 0; id = -1; }
00594 int id;
00595 size_t size;
00596 size_t index;
00597 string details;
00598 };
00599
00600 typedef growable_vector<symbol_details_t> symbol_details_array_t;
00601 symbol_details_array_t symbol_details;
00602 size_t detail_table_index = 0;
00603
00604 xml_formatter::
00605 xml_formatter(profile_container const * p,
00606 symbol_collection & s, extra_images const & extra,
00607 string_filter const & sf)
00608 :
00609 formatter(extra),
00610 profile(p),
00611 symbols(s),
00612 need_details(false),
00613 symbol_filter(sf)
00614 {
00615 if (profile)
00616 counts.total = profile->samples_count();
00617 }
00618
00619
00620 void xml_formatter::
00621 show_details(bool on_off)
00622 {
00623 need_details = on_off;
00624 }
00625
00626
00627 void xml_formatter::output(ostream & out)
00628 {
00629 xml_support->build_subclasses(out);
00630
00631 xml_support->output_program_structure(out);
00632 output_symbol_data(out);
00633 if (need_details) {
00634 out << open_element(DETAIL_TABLE);
00635 for (size_t i = 0; i < symbol_details.size(); ++i) {
00636 int id = symbol_details[i].id;
00637
00638 if (id >= 0) {
00639 out << open_element(SYMBOL_DETAILS, true);
00640 out << init_attr(TABLE_ID, (size_t)id);
00641 out << close_element(NONE, true);
00642 out << symbol_details[i].details;
00643 out << close_element(SYMBOL_DETAILS);
00644 }
00645 }
00646 out << close_element(DETAIL_TABLE);
00647
00648
00649 out << open_element(BYTES_TABLE);
00650 out << bytes_out.str();
00651 out << close_element(BYTES_TABLE);
00652 }
00653
00654 out << close_element(PROFILE);
00655 }
00656
00657 bool
00658 xml_formatter::get_bfd_object(symbol_entry const * symb, op_bfd * & abfd) const
00659 {
00660 bool ok = true;
00661
00662 string const & image_name = get_image_name(symb->image_name,
00663 image_name_storage::int_filename, extra_found_images);
00664 if (symb->spu_offset) {
00665
00666
00667
00668 string tmp = get_image_name(symb->embedding_filename,
00669 image_name_storage::int_filename, extra_found_images);
00670 if (abfd && abfd->get_filename() == tmp)
00671 return true;
00672 delete abfd;
00673 abfd = new op_bfd(symb->spu_offset, tmp,
00674 symbol_filter, extra_found_images, ok);
00675 } else {
00676 if (abfd && abfd->get_filename() == image_name)
00677 return true;
00678 delete abfd;
00679 abfd = new op_bfd(image_name, symbol_filter,
00680 extra_found_images, ok);
00681
00682 }
00683
00684 if (!ok) {
00685 report_image_error(image_name, image_format_failure,
00686 false, extra_found_images);
00687 delete abfd;
00688 abfd = 0;
00689 return false;
00690 }
00691
00692 return true;
00693 }
00694
00695 void xml_formatter::
00696 output_the_symbol_data(ostream & out, symbol_entry const * symb, op_bfd * & abfd)
00697 {
00698 string const name = symbol_names.name(symb->name);
00699 assert(name.size() > 0);
00700
00701 string const image = get_image_name(symb->image_name,
00702 image_name_storage::int_filename, extra_found_images);
00703 string const qname = image + ":" + name;
00704 map<string, size_t>::iterator sd_it = symbol_data_table.find(qname);
00705
00706 if (sd_it != symbol_data_table.end()) {
00707
00708 out << open_element(SYMBOL_DATA, true);
00709 out << init_attr(TABLE_ID, sd_it->second);
00710
00711 field_datum datum(*symb, symb->sample, 0, counts,
00712 extra_found_images);
00713
00714 output_attribute(out, datum, ff_symb_name, NAME);
00715
00716 if (flags & ff_linenr_info) {
00717 output_attribute(out, datum, ff_linenr_info, SOURCE_FILE);
00718 output_attribute(out, datum, ff_linenr_info, SOURCE_LINE);
00719 }
00720
00721 if (name.size() > 0 && name[0] != '?') {
00722 output_attribute(out, datum, ff_vma, STARTING_ADDR);
00723
00724 if (need_details) {
00725 get_bfd_object(symb, abfd);
00726 if (abfd && abfd->symbol_has_contents(symb->sym_index))
00727 xml_support->output_symbol_bytes(bytes_out, symb, sd_it->second, *abfd);
00728 }
00729 }
00730 out << close_element();
00731
00732
00733 symbol_data_table.erase(qname);
00734 }
00735 }
00736
00737 void xml_formatter::output_cg_children(ostream & out,
00738 cg_symbol::children const cg_symb, op_bfd * & abfd)
00739 {
00740 cg_symbol::children::const_iterator cit;
00741 cg_symbol::children::const_iterator cend = cg_symb.end();
00742
00743 for (cit = cg_symb.begin(); cit != cend; ++cit) {
00744 string const name = symbol_names.name(cit->name);
00745 string const image = get_image_name(cit->image_name,
00746 image_name_storage::int_filename, extra_found_images);
00747 string const qname = image + ":" + name;
00748 map<string, size_t>::iterator sd_it = symbol_data_table.find(qname);
00749
00750 if (sd_it != symbol_data_table.end()) {
00751 symbol_entry const * child = &(*cit);
00752 output_the_symbol_data(out, child, abfd);
00753 }
00754 }
00755 }
00756
00757 void xml_formatter::output_symbol_data(ostream & out)
00758 {
00759 op_bfd * abfd = NULL;
00760 sym_iterator it = symbols.begin();
00761 sym_iterator end = symbols.end();
00762
00763 out << open_element(SYMBOL_TABLE);
00764 for ( ; it != end; ++it) {
00765 symbol_entry const * symb = *it;
00766 cg_symbol const * cg_symb = dynamic_cast<cg_symbol const *>(symb);
00767 output_the_symbol_data(out, symb, abfd);
00768 if (cg_symb) {
00769
00770 output_cg_children(out, cg_symb->callers, abfd);
00771 output_cg_children(out, cg_symb->callees, abfd);
00772 }
00773 }
00774 out << close_element(SYMBOL_TABLE);
00775
00776 delete abfd;
00777 }
00778
00779 string xml_formatter::
00780 output_symbol_details(symbol_entry const * symb,
00781 size_t & detail_index, size_t const lo, size_t const hi)
00782 {
00783 if (!has_sample_counts(symb->sample.counts, lo, hi))
00784 return "";
00785
00786 sample_container::samples_iterator it = profile->begin(symb);
00787 sample_container::samples_iterator end = profile->end(symb);
00788
00789 ostringstream str;
00790 for (; it != end; ++it) {
00791 counts_t c;
00792
00793 for (size_t p = lo; p <= hi; ++p) {
00794 size_t count = it->second.counts[p];
00795
00796 if (count == 0) continue;
00797
00798 str << open_element(DETAIL_DATA, true);
00799 str << init_attr(TABLE_ID, detail_index++);
00800
00801
00802 field_datum datum(*symb, it->second, 0, c,
00803 extra_found_images, 0.0);
00804 output_attribute(str, datum, ff_vma, VMA);
00805 if (ff_linenr_info) {
00806 string sym_file;
00807 size_t sym_line;
00808 string samp_file;
00809 size_t samp_line;
00810 string sym_info = get_linenr_info(symb->sample.file_loc, true);
00811 string samp_info = get_linenr_info(it->second.file_loc, true);
00812
00813 if (extract_linenr_info(samp_info, samp_file, samp_line)) {
00814 if (extract_linenr_info(sym_info, sym_file, sym_line)) {
00815
00816
00817
00818 if (sym_file != samp_file)
00819 str << init_attr(SOURCE_FILE, samp_file);
00820 }
00821 str << init_attr(SOURCE_LINE, samp_line);
00822 }
00823 }
00824 str << close_element(NONE, true);
00825
00826
00827 output_sample_data(str, it->second, p);
00828
00829 str << close_element(DETAIL_DATA);
00830 }
00831 }
00832 return str.str();
00833 }
00834
00835 void xml_formatter::
00836 output_symbol(ostream & out,
00837 symbol_entry const * symb, size_t lo, size_t hi, bool is_module)
00838 {
00839 ostringstream str;
00840
00841 size_t indx = is_module ? 0 : 1;
00842
00843
00844 bool got_samples = false;
00845
00846 for (size_t p = lo; p <= hi; ++p) {
00847 got_samples |= xml_support->output_summary_data(str,
00848 symb->sample.counts, p);
00849 }
00850
00851 if (!got_samples)
00852 return;
00853
00854 if (cverb << vxml)
00855 out << "<!-- symbol_ref=" << symbol_names.name(symb->name) <<
00856 " -->" << endl;
00857
00858 out << open_element(SYMBOL, true);
00859
00860 string const name = symbol_names.name(symb->name);
00861 assert(name.size() > 0);
00862
00863 string const image = get_image_name(symb->image_name,
00864 image_name_storage::int_filename, extra_found_images);
00865 string const qname = image + ":" + name;
00866
00867 indx = xml_get_symbol_index(qname);
00868
00869 out << init_attr(ID_REF, indx);
00870
00871 if (need_details) {
00872 ostringstream details;
00873 symbol_details_t & sd = symbol_details[indx];
00874 size_t const detail_lo = sd.index;
00875
00876 string detail_str = output_symbol_details(symb, sd.index, lo, hi);
00877
00878 if (detail_str.size() > 0) {
00879 if (sd.id < 0)
00880 sd.id = indx;
00881 details << detail_str;
00882 }
00883
00884 if (sd.index > detail_lo) {
00885 sd.details = sd.details + details.str();
00886 out << init_attr(DETAIL_LO, detail_lo);
00887 out << init_attr(DETAIL_HI, sd.index-1);
00888 }
00889 }
00890 out << close_element(NONE, true);
00891
00892 out << str.str();
00893 out << close_element(SYMBOL);
00894 }
00895
00896
00897 void xml_formatter::
00898 output_sample_data(ostream & out, sample_entry const & sample, size_t pclass)
00899 {
00900 out << open_element(COUNT, true);
00901 out << init_attr(CLASS, classes.v[pclass].name);
00902 out << close_element(NONE, true);
00903 out << sample.counts[pclass];
00904 out << close_element(COUNT);
00905 }
00906
00907
00908 void xml_formatter::
00909 output_attribute(ostream & out, field_datum const & datum,
00910 format_flags fl, tag_t tag)
00911 {
00912 field_description const & field(format_map[fl]);
00913
00914 string str = (this->*field.formatter)(datum);
00915
00916 if (!str.empty()) {
00917 if (fl == ff_linenr_info && (tag == SOURCE_LINE || tag == SOURCE_FILE)) {
00918 string file;
00919 size_t line;
00920
00921 if (extract_linenr_info(str, file, line)) {
00922 if (tag == SOURCE_LINE)
00923 out << init_attr(tag, line);
00924 else
00925 out << init_attr(tag, file);
00926 }
00927 } else
00928 out << " " << init_attr(tag, str);
00929 }
00930 }
00931
00932 xml_cg_formatter::
00933 xml_cg_formatter(callgraph_container const & cg, symbol_collection & s,
00934 string_filter const & sf)
00935 :
00936 xml_formatter(0, s, cg.extra_found_images, sf),
00937 callgraph(cg)
00938 {
00939 counts.total = callgraph.samples_count();
00940 }
00941
00942 void xml_cg_formatter::
00943 output_symbol_core(ostream & out, cg_symbol::children const cg_symb,
00944 string const selfname, string const qname,
00945 size_t lo, size_t hi, bool is_module, tag_t tag)
00946 {
00947 cg_symbol::children::const_iterator cit;
00948 cg_symbol::children::const_iterator cend = cg_symb.end();
00949
00950 for (cit = cg_symb.begin(); cit != cend; ++cit) {
00951 string const & module = get_image_name((cit)->image_name,
00952 image_name_storage::int_filename, extra_found_images);
00953 bool self = false;
00954 ostringstream str;
00955 size_t indx;
00956
00957
00958 for (size_t p = lo; p <= hi; ++p)
00959 xml_support->output_summary_data(str, cit->sample.counts, p);
00960
00961 if (cverb << vxml)
00962 out << "<!-- symbol_ref=" << symbol_names.name(cit->name) <<
00963 " -->" << endl;
00964
00965 if (is_module) {
00966 out << open_element(MODULE, true);
00967 out << init_attr(NAME, module) << close_element(NONE, true);
00968 }
00969
00970 out << open_element(SYMBOL, true);
00971
00972 string const symname = symbol_names.name(cit->name);
00973 assert(symname.size() > 0);
00974
00975 string const symqname = module + ":" + symname;
00976
00977
00978 if ((symname == selfname) && (tag == CALLEES)) {
00979 self = true;
00980 indx = xml_get_symbol_index(qname);
00981 } else {
00982 indx = xml_get_symbol_index(symqname);
00983 }
00984
00985 out << init_attr(ID_REF, indx);
00986
00987 if (self)
00988 out << init_attr(SELFREF, "true");
00989
00990 out << close_element(NONE, true);
00991 out << str.str();
00992 out << close_element(SYMBOL);
00993
00994 if (is_module)
00995 out << close_element(MODULE);
00996 }
00997 }
00998
00999
01000 void xml_cg_formatter::
01001 output_symbol(ostream & out,
01002 symbol_entry const * symb, size_t lo, size_t hi, bool is_module)
01003 {
01004 cg_symbol const * cg_symb = dynamic_cast<cg_symbol const *>(symb);
01005 ostringstream str;
01006 size_t indx;
01007
01008
01009 for (size_t p = lo; p <= hi; ++p)
01010 xml_support->output_summary_data(str, symb->sample.counts, p);
01011
01012 if (cverb << vxml)
01013 out << "<!-- symbol_ref=" << symbol_names.name(symb->name) <<
01014 " -->" << endl;
01015
01016 out << open_element(SYMBOL, true);
01017
01018 string const name = symbol_names.name(symb->name);
01019 assert(name.size() > 0);
01020
01021 string const image = get_image_name(symb->image_name,
01022 image_name_storage::int_filename, extra_found_images);
01023 string const qname = image + ":" + name;
01024
01025 string const selfname = symbol_names.demangle(symb->name) + " [self]";
01026
01027 indx = xml_get_symbol_index(qname);
01028
01029 out << init_attr(ID_REF, indx);
01030
01031 out << close_element(NONE, true);
01032
01033 out << open_element(CALLERS);
01034 if (cg_symb)
01035 output_symbol_core(out, cg_symb->callers, selfname, qname, lo, hi, is_module, CALLERS);
01036 out << close_element(CALLERS);
01037
01038 out << open_element(CALLEES);
01039 if (cg_symb)
01040 output_symbol_core(out, cg_symb->callees, selfname, qname, lo, hi, is_module, CALLEES);
01041
01042 out << close_element(CALLEES);
01043
01044
01045 out << str.str();
01046 out << close_element(SYMBOL);
01047 }
01048
01049 }