00001
00011 #include <iostream>
00012 #include <sstream>
00013
00014 #include "xml_utils.h"
00015 #include "format_output.h"
00016 #include "arrange_profiles.h"
00017 #include "op_bfd.h"
00018 #include "cverb.h"
00019
00020 using namespace std;
00021
00022 bool want_xml = false;
00023
00024 size_t nr_classes = 0;
00025 size_t nr_cpus = 0;
00026 size_t nr_events = 0;
00027 sym_iterator symbols_begin;
00028 sym_iterator symbols_end;
00029
00030 format_output::xml_formatter * xml_out;
00031 xml_utils * xml_support;
00032 size_t xml_utils::events_index = 0;
00033 bool xml_utils::has_nonzero_masks = false;
00034 ostringstream xml_options;
00035
00036
00037
00038 namespace {
00039
00040 bool has_separated_cpu_info()
00041 {
00042 return classes.v[0].ptemplate.cpu != "all";
00043 }
00044
00045
00046 string get_event_num(size_t pclass)
00047 {
00048 return classes.v[pclass].ptemplate.event;
00049 }
00050
00051
00052 size_t get_next_event_num_pclass(size_t start)
00053 {
00054 string cur_event = get_event_num(start);
00055 size_t i;
00056 for (i = start;
00057 i < nr_classes && get_event_num(i) == cur_event;
00058 ++i) ;
00059 return i;
00060 }
00061
00062
00063 void dump_symbol(string const & prefix, sym_iterator it, bool want_nl = true)
00064 {
00065 if (it == symbols_end)
00066 cverb << vxml << prefix << "END";
00067 else
00068 cverb << vxml << prefix << symbol_names.name((*it)->name);
00069 if (want_nl)
00070 cverb << vxml << endl;
00071 }
00072
00073
00074 void dump_symbols(string const & prefix, sym_iterator b, sym_iterator e)
00075 {
00076 if (b == (sym_iterator)0)
00077 return;
00078
00079 for (sym_iterator it = b; it != e; ++it)
00080 dump_symbol(prefix, it, true);
00081 }
00082
00083
00084
00085 void dump_classes()
00086 {
00087 cverb << vxml << "<!-- classes dump" << endl;
00088 cverb << vxml << classes.event;
00089 cverb << vxml << "classes.size= " << classes.v.size() << endl;
00090 for (size_t i = 0; i < classes.v.size(); ++i) {
00091 cverb << vxml << "--- class " << i << ":" << classes.v[i].name << " ---" << endl;
00092 cverb << vxml << classes.v[i].ptemplate;
00093 }
00094 cverb << vxml << "-->" << endl;
00095 }
00096
00097
00098 bool has_separated_thread_info()
00099 {
00100 return classes.v[0].ptemplate.tid != "all";
00101 }
00102
00103
00104 string get_cpu_num(size_t pclass)
00105 {
00106 return classes.v[pclass].ptemplate.cpu;
00107 }
00108
00109
00110 };
00111
00112 xml_utils::xml_utils(format_output::xml_formatter * xo,
00113 symbol_collection const & s, size_t nc,
00114 extra_images const & extra)
00115 :
00116 has_subclasses(false),
00117 bytes_index(0),
00118 extra_found_images(extra)
00119 {
00120 xml_out = xo;
00121 nr_classes = nc;
00122 symbols_begin = s.begin();
00123 symbols_end = s.end();
00124 multiple_events = get_next_event_num_pclass(0) != nr_classes;
00125
00126 if (has_separated_cpu_info()) {
00127 size_t cpus = 0;
00128
00129 for (size_t p = 0; p < nr_classes; ++p) {
00130 size_t cpu = atoi(classes.v[p].ptemplate.cpu.c_str());
00131 if (cpu > cpus) cpus = cpu;
00132 }
00133
00134 nr_cpus = cpus + 1;
00135 }
00136 }
00137
00138
00139 string xml_utils::get_timer_setup(size_t count)
00140 {
00141 return open_element(TIMER_SETUP, true) +
00142 init_attr(RTC_INTERRUPTS, count) + close_element();
00143 }
00144
00145
00146 string xml_utils::get_event_setup(string event, size_t count,
00147 string unit_mask)
00148 {
00149 ostringstream str;
00150
00151 str << open_element(EVENT_SETUP, true);
00152 str << init_attr(TABLE_ID, events_index++);
00153 str << init_attr(EVENT_NAME, event);
00154 if (unit_mask.size() != 0) str << init_attr(UNIT_MASK, unit_mask);
00155 str << init_attr(SETUP_COUNT, (size_t)count) + close_element();
00156 return str.str();
00157 }
00158
00159
00160 string xml_utils::get_profile_header(string cpu_name, double const speed)
00161 {
00162 ostringstream str;
00163 string cpu_type;
00164 string processor;
00165 string::size_type slash_pos = cpu_name.find("/");
00166
00167 if (slash_pos == string::npos) {
00168 cpu_type = cpu_name;
00169 processor = "";
00170 } else {
00171 cpu_type = cpu_name.substr(0, slash_pos);
00172 processor = cpu_name.substr(slash_pos+1);
00173 }
00174
00175 str << init_attr(CPU_NAME, cpu_type) << endl;
00176 if (processor.size() > 0)
00177 str << init_attr(PROCESSOR, string(processor)) << endl;
00178 if (nr_cpus > 1) str << init_attr(SEPARATED_CPUS, nr_cpus) << endl;
00179 str << init_attr(MHZ, speed) << endl;
00180
00181 return str.str();
00182 }
00183
00184
00185 void xml_utils::set_nr_cpus(size_t cpus)
00186 {
00187 nr_cpus = cpus;
00188 }
00189
00190 void xml_utils::set_nr_events(size_t events)
00191 {
00192 nr_events = events;
00193 }
00194
00195 void xml_utils::set_has_nonzero_masks()
00196 {
00197 has_nonzero_masks = true;
00198 }
00199
00200
00201 void xml_utils::add_option(tag_t tag, string const & value)
00202 {
00203 xml_options << init_attr(tag, value);
00204 }
00205
00206
00207 void xml_utils::add_option(tag_t tag, list<string> const & value)
00208 {
00209 list<string>::const_iterator begin = value.begin();
00210 list<string>::const_iterator end = value.end();
00211 list<string>::const_iterator cit = begin;
00212 ostringstream str;
00213
00214 for (; cit != end; ++cit) {
00215 if (cit != begin)
00216 str << ",";
00217 str << *cit;
00218 }
00219 xml_options << init_attr(tag, str.str());
00220 }
00221
00222
00223 void xml_utils::add_option(tag_t tag, vector<string> const & value)
00224 {
00225 vector<string>::const_iterator begin = value.begin();
00226 vector<string>::const_iterator end = value.end();
00227 vector<string>::const_iterator cit = begin;
00228 ostringstream str;
00229
00230 for (; cit != end; ++cit) {
00231 if (cit != begin)
00232 str << ",";
00233 str << *cit;
00234 }
00235 xml_options << init_attr(tag, str.str());
00236 }
00237
00238
00239 void xml_utils::add_option(tag_t tag, bool value)
00240 {
00241 xml_options << init_attr(tag, (value ? "true" : "false"));
00242 }
00243
00244
00245 void xml_utils::output_xml_header(string const & command_options,
00246 string const & cpu_info, string const & events)
00247 {
00248
00249
00250
00251
00252 string const schema_version = "3.0";
00253
00254
00255 string const xml_header = "<?xml version=\"1.0\" ?>";
00256
00257 cout << xml_header << endl;
00258 cout << open_element(PROFILE, true);
00259 cout << init_attr(SCHEMA_VERSION, schema_version);
00260
00261 cout << cpu_info;
00262 cout << init_attr(TITLE, "opreport " + command_options);
00263 cout << close_element(NONE, true);
00264
00265 cout << open_element(OPTIONS, true) << xml_options.str();
00266 cout << close_element();
00267
00268 cout << open_element(SETUP) << events;
00269 cout << close_element(SETUP) << endl;
00270 }
00271
00272 class subclass_info_t {
00273 public:
00274 string unitmask;
00275 string subclass_name;
00276 };
00277
00278 typedef growable_vector<subclass_info_t> subclass_array_t;
00279 typedef growable_vector<subclass_array_t> event_subclass_t;
00280 typedef growable_vector<event_subclass_t> cpu_subclass_t;
00281
00282 void xml_utils::build_subclasses(ostream & out)
00283 {
00284 size_t subclasses = 0;
00285 string subclass_name;
00286
00287 cpu_subclass_t cpu_subclasses;
00288
00289 event_subclass_t event_subclasses;
00290
00291 if (nr_cpus <= 1 && nr_events <= 1 && !has_nonzero_masks)
00292 return;
00293
00294 out << open_element(CLASSES);
00295 for (size_t i = 0; i < classes.v.size(); ++i) {
00296 profile_class & pclass = classes.v[i];
00297 size_t event = atoi(pclass.ptemplate.event.c_str());
00298
00299 subclass_array_t * sc_ptr;
00300
00301
00302 if (nr_cpus == 1) {
00303 sc_ptr = &event_subclasses[event];
00304 } else {
00305 size_t cpu = atoi(pclass.ptemplate.cpu.c_str());
00306 sc_ptr = &cpu_subclasses[cpu][event];
00307 }
00308
00309
00310 subclass_name = "";
00311 for (size_t j = 0; j < sc_ptr->size(); ++j) {
00312 if ((*sc_ptr)[j].unitmask == pclass.ptemplate.unitmask) {
00313 subclass_name = (*sc_ptr)[j].subclass_name;
00314 break;
00315 }
00316 }
00317
00318 if (subclass_name.size() == 0) {
00319 ostringstream str;
00320 size_t new_index = sc_ptr->size();
00321
00322
00323 str << "c" << subclasses++;
00324 subclass_name = str.str();
00325 (*sc_ptr)[new_index].unitmask = pclass.ptemplate.unitmask;
00326 (*sc_ptr)[new_index].subclass_name = subclass_name;
00327 out << open_element(CLASS, true);
00328 out << init_attr(NAME, subclass_name);
00329 if (nr_cpus > 1)
00330 out << init_attr(CPU_NUM, pclass.ptemplate.cpu);
00331 if (nr_events > 1)
00332 out << init_attr(EVENT_NUM, event);
00333 if (has_nonzero_masks)
00334 out << init_attr(EVENT_MASK, pclass.ptemplate.unitmask);
00335 out << close_element();
00336 }
00337
00338 pclass.name = subclass_name;
00339 }
00340 out << close_element(CLASSES);
00341 has_subclasses = true;
00342 }
00343
00344
00345 string
00346 get_counts_string(count_array_t const & counts, size_t begin, size_t end)
00347 {
00348 ostringstream str;
00349 bool got_count = false;
00350
00351
00352 if (nr_cpus == 1) {
00353 size_t count = counts[begin];
00354 if (count == 0)
00355 return "";
00356 str << count;
00357 return str.str();
00358 }
00359
00360 for (size_t p = begin; p != end; ++p) {
00361 size_t count = counts[p];
00362 if (p != begin) str << ",";
00363 if (count != 0) {
00364 got_count = true;
00365 str << count;
00366 }
00367 }
00368 return got_count ? str.str() : "";
00369 }
00370
00371
00372 void
00373 xml_utils::output_symbol_bytes(ostream & out, symbol_entry const * symb,
00374 size_t sym_id, op_bfd const & abfd)
00375 {
00376 size_t size = symb->size;
00377 scoped_array<unsigned char> contents(new unsigned char[size]);
00378 if (abfd.get_symbol_contents(symb->sym_index, contents.get())) {
00379 string const name = symbol_names.name(symb->name);
00380 out << open_element(BYTES, true) << init_attr(TABLE_ID, sym_id);
00381 out << close_element(NONE, true);
00382 for (size_t i = 0; i < size; ++i) {
00383 char hex_map[] = "0123456789ABCDEF";
00384 char hex[2];
00385 hex[0] = hex_map[(contents[i] >> 4) & 0xf];
00386 hex[1] = hex_map[contents[i] & 0xf];
00387 out << hex[0] << hex[1];
00388 }
00389 out << close_element(BYTES);
00390 }
00391 }
00392
00393
00394 bool
00395 xml_utils::output_summary_data(ostream & out, count_array_t const & summary, size_t pclass)
00396 {
00397 size_t const count = summary[pclass];
00398
00399 if (count == 0)
00400 return false;
00401
00402 out << open_element(COUNT, has_subclasses);
00403 if (has_subclasses) {
00404 out << init_attr(CLASS, classes.v[pclass].name);
00405 out << close_element(NONE, true);
00406 }
00407 out << count;
00408 out << close_element(COUNT);
00409 return true;
00410 }
00411
00412 class module_info {
00413 public:
00414 module_info()
00415 { lo = hi = 0; name = ""; begin = end = (sym_iterator)0;}
00416 void dump();
00417 void build_module(string const & n, sym_iterator it,
00418 size_t l, size_t h);
00419 string get_name() { return name; }
00420 void set_lo(size_t l) { lo = l; }
00421 void set_hi(size_t h) { hi = h; }
00422 count_array_t const & get_summary() { return summary; }
00423 void set_begin(sym_iterator b);
00424 void set_end(sym_iterator e);
00425 void add_to_summary(count_array_t const & counts);
00426 void output(ostream & out);
00427 bool is_closed(string const & n);
00428 protected:
00429 void output_summary(ostream & out);
00430 void output_symbols(ostream & out, bool is_module);
00431
00432 string name;
00433 sym_iterator begin;
00434 sym_iterator end;
00435
00436
00437 count_array_t summary;
00438
00439
00440 size_t lo;
00441 size_t hi;
00442 };
00443
00444 class thread_info : public module_info {
00445 public:
00446 thread_info() { nr_modules = 0; }
00447
00448 void build_thread(string const & tid, size_t l, size_t h);
00449 bool add_modules(string const & module, sym_iterator it);
00450 void add_module_symbol(string const & n, sym_iterator it);
00451 void summarize();
00452 void set_end(sym_iterator end);
00453 string const get_tid() { return thread_id; }
00454 void output(ostream & out);
00455 void dump();
00456 private:
00457
00458 size_t nr_modules;
00459 string thread_id;
00460 growable_vector<module_info> my_modules;
00461 };
00462
00463 class process_info : public module_info {
00464 public:
00465 process_info() { nr_threads = 0; }
00466 void build_process(string const & pid, size_t l, size_t h);
00467 void add_thread(string const & tid, size_t l, size_t h);
00468 void add_modules(string const & module,
00469 string const & app_name, sym_iterator it);
00470 void summarize();
00471 void set_end(sym_iterator end);
00472 void output(ostream & out);
00473 void dump();
00474 private:
00475 size_t nr_threads;
00476 string process_id;
00477 growable_vector<thread_info> my_threads;
00478
00479 };
00480 class process_root_info {
00481 public:
00482 process_root_info() { nr_processes = 0; }
00483 process_info * add_process(string const & pid, size_t lo, size_t hi);
00484 void add_modules(string const & module, string const & app_name,
00485 sym_iterator it);
00486 void summarize();
00487 void summarize_processes(extra_images const & extra_found_images);
00488 void set_process_end();
00489 void output_process_symbols(ostream & out);
00490 void dump_processes();
00491 private:
00492 size_t nr_processes;
00493
00494 growable_vector<process_info> processes;
00495 };
00496
00497 class binary_info : public module_info {
00498 public:
00499 binary_info() { nr_modules = 0; }
00500 void output(ostream & out);
00501 binary_info * build_binary(string const & n);
00502 void add_module_symbol(string const & module, string const & app,
00503 sym_iterator it);
00504 void close_binary(sym_iterator it);
00505 void dump();
00506 private:
00507 size_t nr_modules;
00508
00509 growable_vector<module_info> my_modules;
00510 };
00511
00512
00513 class binary_root_info {
00514 public:
00515 binary_root_info() { nr_binaries = 0; }
00516 binary_info * add_binary(string const & n, sym_iterator it);
00517 void summarize_binaries(extra_images const & extra_found_images);
00518 void output_binary_symbols(ostream & out);
00519 void dump_binaries();
00520 private:
00521 size_t nr_binaries;
00522
00523 growable_vector<binary_info> binaries;
00524 };
00525
00526 static process_root_info processes_root;
00527 static binary_root_info binaries_root;
00528
00529
00530 void module_info::
00531 build_module(string const & n, sym_iterator it, size_t l, size_t h)
00532 {
00533 name = n;
00534 begin = it;
00535 lo = l;
00536 hi = h;
00537 }
00538
00539
00540 void module_info::add_to_summary(count_array_t const & counts)
00541 {
00542 for (size_t pclass = lo ; pclass <= hi; ++pclass)
00543 summary[pclass] += counts[pclass];
00544 }
00545
00546
00547 void module_info::set_begin(sym_iterator b)
00548 {
00549 if (begin == (sym_iterator)0)
00550 begin = b;
00551 }
00552
00553
00554 void module_info::set_end(sym_iterator e)
00555 {
00556 if (end == (sym_iterator)0)
00557 end = e;
00558 }
00559
00560
00561 bool module_info::is_closed(string const & n)
00562 {
00563 return (name == n) && end != (sym_iterator)0;
00564 }
00565
00566
00567 void module_info::dump()
00568 {
00569 cverb << vxml << " module:class(" << lo << "," << hi << ")=";
00570 cverb << vxml << name << endl;
00571 dump_symbols(" ", begin, end);
00572 }
00573
00574
00575 void module_info::output(ostream & out)
00576 {
00577 out << open_element(MODULE, true);
00578 out << init_attr(NAME, name) << close_element(NONE, true);
00579 output_summary(out);
00580 output_symbols(out, true);
00581 out << close_element(MODULE);
00582 }
00583
00584
00585 void module_info::output_summary(ostream & out)
00586 {
00587 for (size_t p = lo; p <= hi; ++p)
00588 (void)xml_support->output_summary_data(out, summary, p);
00589 }
00590
00591
00592 void module_info::output_symbols(ostream & out, bool is_module)
00593 {
00594 if (begin == (sym_iterator)0)
00595 return;
00596
00597 for (sym_iterator it = begin; it != end; ++it)
00598 xml_out->output_symbol(out, *it, lo, hi, is_module);
00599 }
00600
00601
00602 void binary_info::close_binary(sym_iterator it)
00603 {
00604 set_end(it);
00605 if (nr_modules > 0) {
00606 module_info & m = my_modules[nr_modules-1];
00607 m.set_end(it);
00608 }
00609 }
00610
00611
00612 void binary_info::dump()
00613 {
00614 cverb << vxml << "app_name=" << name << endl;
00615 if (begin != (sym_iterator)0)
00616 dump_symbols(" ", begin, end);
00617
00618 for (size_t i = 0; i < nr_modules; ++i)
00619 my_modules[i].dump();
00620 }
00621
00622
00623 void binary_info::
00624 add_module_symbol(string const & module, string const & app,
00625 sym_iterator it)
00626 {
00627 size_t m = nr_modules;
00628
00629 if (module == app) {
00630
00631 set_begin(it);
00632
00633 if (m > 0) {
00634
00635 module_info & mod = my_modules[m-1];
00636 mod.set_end(it);
00637 }
00638
00639
00640 add_to_summary((*it)->sample.counts);
00641 return;
00642 }
00643
00644 string current_module_name = (m == 0 ? "" : my_modules[m-1].get_name());
00645 if (module != current_module_name) {
00646
00647
00648 if (m != 0) {
00649
00650 module_info & mod = my_modules[m-1];
00651 mod.set_end(it);
00652 }
00653
00654
00655
00656
00657 if (begin != (sym_iterator)0 && end == (sym_iterator)0)
00658 set_end(it);
00659
00660
00661 nr_modules++;
00662 my_modules[m].build_module(module, it, 0, nr_classes-1);
00663 }
00664
00665
00666 my_modules[nr_modules-1].add_to_summary((*it)->sample.counts);
00667 }
00668
00669
00670 void binary_root_info::
00671 summarize_binaries(extra_images const & extra_found_images)
00672 {
00673 binary_info * current_binary = 0;
00674 string current_binary_name = "";
00675
00676 for (sym_iterator it = symbols_begin ; it != symbols_end; ++it) {
00677 string binary = get_image_name((*it)->app_name,
00678 image_name_storage::int_filename, extra_found_images);
00679 string module = get_image_name((*it)->image_name,
00680 image_name_storage::int_filename, extra_found_images);
00681
00682 if (binary != current_binary_name) {
00683 current_binary = binaries_root.add_binary(binary, it);
00684 current_binary_name = binary;
00685 }
00686
00687 current_binary->add_module_symbol(module, binary, it);
00688 }
00689
00690
00691 current_binary->close_binary(symbols_end);
00692 }
00693
00694
00695 process_info *
00696 process_root_info::add_process(string const & pid, size_t lo, size_t hi)
00697 {
00698 processes[nr_processes].build_process(pid, lo, hi);
00699 return &processes[nr_processes++];
00700 }
00701
00702
00703 void process_root_info::
00704 add_modules(string const & module, string const & app_name,
00705 sym_iterator it)
00706 {
00707 for (size_t p = 0; p < nr_processes; ++p)
00708 processes[p].add_modules(module, app_name, it);
00709 }
00710
00711
00712
00713 void process_root_info::summarize()
00714 {
00715 for (size_t p = 0; p < nr_processes; ++p)
00716 processes[p].summarize();
00717 }
00718
00719
00720 void process_root_info::
00721 summarize_processes(extra_images const & extra_found_images)
00722 {
00723
00724 for (sym_iterator it = symbols_begin ; it != symbols_end; ++it) {
00725 string binary = get_image_name((*it)->app_name,
00726 image_name_storage::int_filename, extra_found_images);
00727 string module = get_image_name((*it)->image_name,
00728 image_name_storage::int_filename, extra_found_images);
00729
00730 processes_root.add_modules(module, binary, it);
00731 }
00732
00733
00734 processes_root.set_process_end();
00735
00736
00737 processes_root.summarize();
00738 }
00739
00740
00741 void process_root_info::set_process_end()
00742 {
00743 for (size_t p = 0; p < nr_processes; ++p)
00744 processes[p].set_end(symbols_end);
00745 }
00746
00747 void process_root_info::output_process_symbols(ostream & out)
00748 {
00749 for (size_t p = 0; p < nr_processes; ++p)
00750 processes[p].output(out);
00751 }
00752
00753
00754 void process_root_info::dump_processes()
00755 {
00756 cverb << vxml << "<!-- processes_dump:" << endl;
00757 for (size_t p = 0; p < nr_processes; ++p)
00758 processes[p].dump();
00759 cverb << vxml << "end processes_dump -->" << endl;
00760 }
00761
00762 binary_info *
00763 binary_info::build_binary(string const & n)
00764 {
00765 name = n;
00766 lo = 0;
00767 hi = nr_classes-1;
00768 return this;
00769 }
00770
00771
00772 void binary_info::output(ostream & out)
00773 {
00774 out << open_element(BINARY, true);
00775 out << init_attr(NAME, name) << close_element(NONE, true);
00776
00777 output_summary(out);
00778 output_symbols(out, false);
00779 for (size_t a = 0; a < nr_modules; ++a)
00780 my_modules[a].output(out);
00781
00782 out << close_element(BINARY);
00783 }
00784
00785
00786 binary_info *
00787 binary_root_info::add_binary(string const & n, sym_iterator it)
00788 {
00789 size_t a = nr_binaries++;
00790
00791
00792 if (a > 0) binaries[a-1].close_binary(it);
00793 return binaries[a].build_binary(n);
00794 }
00795
00796
00797 void binary_root_info::output_binary_symbols(ostream & out)
00798 {
00799 for (size_t a = 0; a < nr_binaries; ++a)
00800 binaries[a].output(out);
00801 }
00802
00803
00804 void binary_root_info::dump_binaries()
00805 {
00806 cverb << vxml << "<!-- binaries_dump:" << endl;
00807 for (size_t p = 0; p < nr_binaries; ++p)
00808 binaries[p].dump();
00809 cverb << vxml << "end processes_dump -->" << endl;
00810 }
00811
00812
00813 void process_info::build_process(string const & pid, size_t l, size_t h)
00814 {
00815 process_id = pid;
00816 lo = l;
00817 hi = h;
00818 }
00819
00820
00821 void process_info::add_thread(string const & tid, size_t l, size_t h)
00822 {
00823 my_threads[nr_threads++].build_thread(tid, l, h);
00824 }
00825
00826
00827 void process_info::add_modules(string const & module,
00828 string const & app_name, sym_iterator it)
00829 {
00830 bool added = false;
00831 for (size_t t = 0; t < nr_threads; ++t)
00832 added |= my_threads[t].add_modules(module, it);
00833 if (added && name.size() == 0) name = app_name;
00834 }
00835
00836
00837 void process_info::summarize()
00838 {
00839 for (size_t t = 0; t < nr_threads; ++t) {
00840 thread_info & thr = my_threads[t];
00841 thr.summarize();
00842 add_to_summary(thr.get_summary());
00843 }
00844 }
00845
00846
00847 void thread_info::build_thread(string const & tid, size_t l, size_t h)
00848 {
00849 thread_id = tid;
00850 lo = l;
00851 hi = h;
00852 }
00853
00854
00855 void thread_info::summarize()
00856 {
00857 for (size_t m = 0; m < nr_modules; ++m)
00858 add_to_summary(my_modules[m].get_summary());
00859 }
00860
00861
00862 void thread_info::set_end(sym_iterator end)
00863 {
00864 for (size_t m = 0; m < nr_modules; ++m)
00865 my_modules[m].set_end(end);
00866 }
00867
00868
00869 void thread_info::add_module_symbol(string const & n, sym_iterator it)
00870 {
00871 module_info & m = my_modules[nr_modules++];
00872 m.build_module(n, it, lo, hi);
00873 m.add_to_summary((*it)->sample.counts);
00874 }
00875
00876 void thread_info::output(ostream & out)
00877 {
00878 ostringstream thread_summary;
00879 ostringstream modules_output;
00880
00881 output_summary(thread_summary);
00882
00883 for (size_t m = 0; m < nr_modules; ++m)
00884 my_modules[m].output(modules_output);
00885
00886
00887 if (modules_output.str().size() == 0 && thread_summary.str().size() == 0)
00888 return;
00889
00890 out << open_element(THREAD, true);
00891 out << init_attr(THREAD_ID, thread_id) << close_element(NONE, true);
00892 out << thread_summary.str();
00893 out << modules_output.str();
00894 out << close_element(THREAD);
00895 }
00896
00897
00898 bool thread_info::add_modules(string const & module, sym_iterator it)
00899 {
00900 string old_name =
00901 (nr_modules == 0 ? "" : my_modules[nr_modules-1].get_name());
00902 if (nr_modules > 0 && old_name != module) {
00903 module_info & m = my_modules[nr_modules-1];
00904
00905 if (!m.is_closed(old_name))
00906 m.set_end(it);
00907 }
00908
00909
00910 if (nr_modules == 0 || module != old_name) {
00911 if (has_sample_counts((*it)->sample.counts, lo, hi)) {
00912 add_module_symbol(module, it);
00913 return true;
00914 }
00915 } else {
00916
00917 my_modules[nr_modules-1].add_to_summary((*it)->sample.counts);
00918 }
00919 return false;
00920 }
00921
00922
00923 void thread_info::dump()
00924 {
00925 cverb << vxml << "tid=" << thread_id << endl;
00926 for (size_t i = 0; i < nr_modules; ++i)
00927 my_modules[i].dump();
00928 }
00929
00930
00931 void process_info::set_end(sym_iterator end)
00932 {
00933 for (size_t t = 0; t < nr_threads; ++t)
00934 my_threads[t].set_end(end);
00935 }
00936
00937
00938 void process_info::output(ostream & out)
00939 {
00940 ostringstream process_summary;
00941 ostringstream thread_output;
00942
00943 output_summary(process_summary);
00944
00945 for (size_t t = 0; t < nr_threads; ++t)
00946 my_threads[t].output(thread_output);
00947
00948
00949 if (thread_output.str().size() == 0 && process_summary.str().size() == 0)
00950 return;
00951
00952 out << open_element(PROCESS, true);
00953 out << init_attr(PROC_ID, process_id);
00954 out << init_attr(NAME, name) << close_element(NONE, true);
00955 out << process_summary.str();
00956 out << thread_output.str();
00957 out << close_element(PROCESS);
00958 }
00959
00960
00961 void process_info::dump()
00962 {
00963 cverb << vxml << "pid=" << process_id << " app=" << name << endl;
00964 for (size_t i = 0; i < nr_threads; ++i)
00965 my_threads[i].dump();
00966 }
00967
00968 size_t get_next_tgid_pclass(size_t start)
00969 {
00970 string cur_tgid = classes.v[start].ptemplate.tgid;
00971 size_t i = start;
00972 for (i = start;
00973 i < nr_classes && classes.v[i].ptemplate.tgid == cur_tgid;
00974 ++i) ;
00975 return i;
00976 }
00977
00978
00979 size_t get_next_tid_pclass(size_t start)
00980 {
00981 string cur_tid = classes.v[start].ptemplate.tid;
00982 size_t i;
00983 for (i = start;
00984 i < nr_classes && classes.v[i].ptemplate.tid == cur_tid;
00985 ++i) ;
00986 return i;
00987 }
00988
00989
00990
00991
00992
00993
00994 void build_process_tree()
00995 {
00996 size_t tgid = 0;
00997 size_t tid = 0;
00998
00999
01000
01001
01002 do {
01003 size_t next_tgid = get_next_tgid_pclass(tgid);
01004 string const tgid_str = classes.v[tgid].ptemplate.tgid;
01005
01006 process_info * p = processes_root.add_process(tgid_str, tgid, next_tgid-1);
01007
01008 do {
01009 size_t next_tid = get_next_tid_pclass(tid);
01010
01011
01012 p->add_thread(classes.v[tid].ptemplate.tid, tid, next_tid-1);
01013 tid = next_tid;
01014 } while (tid != next_tgid);
01015 tgid = next_tgid;
01016 } while (tgid != nr_classes);
01017 }
01018
01019 void xml_utils::output_program_structure(ostream & out)
01020 {
01021
01022 if (cverb << vxml)
01023 dump_classes();
01024
01025 if (has_separated_thread_info()) {
01026 build_process_tree();
01027 processes_root.summarize_processes(extra_found_images);
01028 if (cverb << vxml)
01029 processes_root.dump_processes();
01030 processes_root.output_process_symbols(out);
01031 } else {
01032 binaries_root.summarize_binaries(extra_found_images);
01033 if (cverb << vxml)
01034 binaries_root.dump_binaries();
01035 binaries_root.output_binary_symbols(out);
01036 }
01037 }