profile.cpp

Go to the documentation of this file.
00001 
00013 #include <unistd.h>
00014 #include <cstring>
00015 
00016 #include <iostream>
00017 #include <string>
00018 #include <sstream>
00019 #include <cstring>
00020 
00021 #include <cerrno>
00022 
00023 #include "op_exception.h"
00024 #include "op_header.h"
00025 #include "op_config.h"
00026 #include "op_sample_file.h"
00027 #include "profile.h"
00028 #include "op_bfd.h"
00029 #include "cverb.h"
00030 #include "populate_for_spu.h"
00031 
00032 using namespace std;
00033 
00034 profile_t::profile_t()
00035     : start_offset(0)
00036 {
00037 }
00038 
00039 
00040 // static member
00041 count_type profile_t::sample_count(string const & filename)
00042 {
00043     odb_t samples_db;
00044 
00045     open_sample_file(filename, samples_db);
00046 
00047     count_type count = 0;
00048 
00049     odb_node_nr_t node_nr, pos;
00050     odb_node_t * node = odb_get_iterator(&samples_db, &node_nr);
00051     for (pos = 0; pos < node_nr; ++pos)
00052         count += node[pos].value;
00053 
00054     odb_close(&samples_db);
00055 
00056     return count;
00057 }
00058 
00059 //static member
00060 enum profile_type profile_t::is_spu_sample_file(string const & filename)
00061 {
00062     profile_type retval;
00063     odb_t samples_db;
00064     open_sample_file(filename, samples_db);
00065     opd_header const & hdr =
00066         *static_cast<opd_header *>(odb_get_data(&samples_db));
00067     retval = hdr.spu_profile ? cell_spu_profile: normal_profile;
00068     odb_close(&samples_db);
00069     return retval;
00070 }
00071 
00072 //static member
00073 void profile_t::open_sample_file(string const & filename, odb_t & db)
00074 {
00075     // Check first if the sample file version is ok else odb_open() can
00076     // fail and the error message will be obscure.
00077     opd_header head = read_header(filename);
00078 
00079     if (head.version != OPD_VERSION) {
00080         ostringstream os;
00081         os << "oprofpp: samples files version mismatch, are you "
00082            << "running a daemon and post-profile tools with version "
00083            <<  "mismatch ?\n";
00084         throw op_fatal_error(os.str());
00085     }
00086 
00087     int rc = odb_open(&db, filename.c_str(), ODB_RDONLY,
00088         sizeof(struct opd_header));
00089 
00090     if (rc)
00091         throw op_fatal_error(filename + ": " + strerror(rc));
00092 }
00093 
00094 void profile_t::add_sample_file(string const & filename)
00095 {
00096     odb_t samples_db;
00097 
00098     open_sample_file(filename, samples_db);
00099 
00100     opd_header const & head =
00101         *static_cast<opd_header *>(odb_get_data(&samples_db));
00102 
00103     // if we already read a sample file header pointer is non null
00104     if (file_header.get())
00105         op_check_header(head, *file_header, filename);
00106     else
00107         file_header.reset(new opd_header(head));
00108 
00109     odb_node_nr_t node_nr, pos;
00110     odb_node_t * node = odb_get_iterator(&samples_db, &node_nr);
00111 
00112     for (pos = 0; pos < node_nr; ++pos) {
00113         ordered_samples_t::iterator it = 
00114             ordered_samples.find(node[pos].key);
00115         if (it != ordered_samples.end()) {
00116             it->second += node[pos].value;
00117         } else {
00118             ordered_samples_t::value_type
00119                 val(node[pos].key, node[pos].value);
00120             ordered_samples.insert(val);
00121         }
00122     }
00123 
00124     odb_close(&samples_db);
00125 }
00126 
00127 
00128 void profile_t::set_offset(op_bfd const & abfd)
00129 {
00130     // if no bfd file has been located for this samples file, we can't
00131     // shift sample because abfd.get_symbol_range() return the whole
00132     // address space and setting a non zero start_offset will overflow
00133     // in get_symbol_range() caller.
00134     if (abfd.valid()) {
00135         opd_header const & header = get_header();
00136         if (header.anon_start) {
00137             start_offset = header.anon_start;
00138         } else if (header.is_kernel) {
00139             start_offset = abfd.get_start_offset(0);
00140         }
00141     }
00142     cverb << (vdebug) << "start_offset is now " << start_offset << endl;
00143 }
00144 
00145 
00146 profile_t::iterator_pair
00147 profile_t::samples_range(odb_key_t start, odb_key_t end) const
00148 {
00149     // Check the start position isn't before start_offset:
00150     // this avoids wrapping/underflowing start/end.
00151     // This can happen on e.g. ARM kernels, where .init is
00152     // mapped before .text - we just have to skip any such
00153     // .init symbols.
00154     if (start < start_offset) {
00155         return make_pair(const_iterator(ordered_samples.end(), 0), 
00156             const_iterator(ordered_samples.end(), 0));
00157     }
00158     
00159     start -= start_offset;
00160     end -= start_offset;
00161 
00162     // sanity check if start > end caller will enter into an infinite loop
00163     if (start > end) {
00164         throw op_fatal_error("profile_t::samples_range(): start > end"
00165             " something wrong with kernel or module layout ?\n"
00166             "please report problem to "
00167             "oprofile-list@lists.sourceforge.net");
00168     }
00169 
00170     ordered_samples_t::const_iterator first = 
00171         ordered_samples.lower_bound(start);
00172     ordered_samples_t::const_iterator last =
00173         ordered_samples.lower_bound(end);
00174 
00175     return make_pair(const_iterator(first, start_offset),
00176         const_iterator(last, start_offset));
00177 }
00178 
00179 
00180 profile_t::iterator_pair profile_t::samples_range() const
00181 {
00182     ordered_samples_t::const_iterator first = ordered_samples.begin();
00183     ordered_samples_t::const_iterator last = ordered_samples.end();
00184 
00185     return make_pair(const_iterator(first, start_offset),
00186         const_iterator(last, start_offset));
00187 }

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1