xml_utils.cpp

Go to the documentation of this file.
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 // handle on xml_formatter object
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 };  // anonymous namespace
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         // count number of cpus
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         // cpus names start with 0
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     // the integer portion indicates the schema version and should change
00249     // both here and in the schema file when major changes are made to
00250     // the schema.  changes to opreport, or minor changes to the schema
00251     // can be indicated by changes to the fraction part.
00252     string const schema_version = "3.0";
00253 
00254     // This is the XML version, not schema version.
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     // when --separate=cpu we will have an event_subclass array for each cpu
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         // select the right subclass array
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         // search for an existing unitmask
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             // no match found, create a new entry
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     // if no cpu separation then return a simple count, omit zero counts
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     // summary sample data
00437     count_array_t summary;
00438 
00439     // range of profile classes approprate for this module
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     // indices into the classes array applicable to this process
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         // set begin symbol for binary if not set
00631         set_begin(it);
00632 
00633         if (m > 0) {
00634             // close out current module
00635             module_info & mod = my_modules[m-1];
00636             mod.set_end(it);
00637         }
00638 
00639         // add symbol count to binary count
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         // we have a module distinct from it's binary: --separate=lib
00647         // and this is the first symbol for this module
00648         if (m != 0) {
00649             // close out current module
00650             module_info & mod = my_modules[m-1];
00651             mod.set_end(it);
00652         }
00653 
00654         // mark end of enclosing binary symbols if there have been any
00655         // NOTE: it is possible for the binary's symbols to follow its
00656         // module symbols
00657         if (begin != (sym_iterator)0 && end == (sym_iterator)0)
00658             set_end(it);
00659 
00660         // build the new module
00661         nr_modules++;
00662         my_modules[m].build_module(module, it, 0, nr_classes-1);
00663     }
00664 
00665     // propagate this symbols counts to the module
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     // close out last binary and module
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     // add modules to the appropriate threads in the process hierarchy
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     // set end symbol boundary for all modules in all threads
00734     processes_root.set_process_end();
00735 
00736     // propagate summaries to process/thread
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     // close out previous binary and module
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     // ignore threads with no sample data
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         // close out previous module if it hasn't already been closed out
00905         if (!m.is_closed(old_name))
00906             m.set_end(it);
00907     }
00908 
00909     // add a new module for this symbol if it has a non-zero count
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         // propagate symbols count to module
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     // ignore processes with no sample data
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 // build the process/thread/module hierarchy that will allow us later
00991 // to collect the summary sample data at each level and then
00992 // traverse the hierarchy to intersperse the summary data for the
00993 // symbols
00994 void build_process_tree()
00995 {
00996     size_t tgid = 0;
00997     size_t tid = 0;
00998 
00999     // build the structure representing the process/thread/module hierarchy
01000     // for holding the summary data associated with each level and to be
01001     // traversed when outputting the body of the XML
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             // build array of threads associated with this process
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 }

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1