profile.cpp revision cc2ee177dbb3befca43e36cfc56778b006c3d050
1/** 2 * @file profile.cpp 3 * Encapsulation for samples files over all profile classes 4 * belonging to the same binary image 5 * 6 * @remark Copyright 2002 OProfile authors 7 * @remark Read the file COPYING 8 * 9 * @author Philippe Elie 10 * @author John Levon 11 */ 12 13#include <unistd.h> 14 15#include <iostream> 16#include <string> 17#include <sstream> 18 19#include <cerrno> 20 21#include "op_exception.h" 22#include "op_header.h" 23#include "op_config.h" 24#include "op_sample_file.h" 25#include "profile.h" 26#include "op_bfd.h" 27#include "cverb.h" 28 29using namespace std; 30 31profile_t::profile_t() 32 : start_offset(0) 33{ 34} 35 36 37// static member 38unsigned int profile_t::sample_count(string const & filename) 39{ 40 odb_t samples_db; 41 42 open_sample_file(filename, samples_db); 43 44 unsigned int count = 0; 45 46 odb_node_nr_t node_nr, pos; 47 odb_node_t * node = odb_get_iterator(&samples_db, &node_nr); 48 for (pos = 0; pos < node_nr; ++pos) { 49 if (node[pos].key) 50 count += node[pos].value; 51 } 52 53 odb_close(&samples_db); 54 55 return count; 56} 57 58//static member 59void profile_t::open_sample_file(string const & filename, odb_t & db) 60{ 61 int rc = odb_open(&db, filename.c_str(), ODB_RDONLY, 62 sizeof(struct opd_header)); 63 64 if (rc) 65 throw op_fatal_error(filename + ": " + strerror(rc)); 66 67 opd_header const & head = 68 *static_cast<opd_header *>(odb_get_data(&db)); 69 70 if (head.version != OPD_VERSION) { 71 ostringstream os; 72 os << "oprofpp: samples files version mismatch, are you " 73 << "running a daemon and post-profile tools with version " 74 << "mismatch ?\n"; 75 throw op_fatal_error(os.str()); 76 } 77} 78 79void profile_t::add_sample_file(string const & filename) 80{ 81 odb_t samples_db; 82 83 open_sample_file(filename, samples_db); 84 85 opd_header const & head = 86 *static_cast<opd_header *>(odb_get_data(&samples_db)); 87 88 // if we already read a sample file header pointer is non null 89 if (file_header.get()) 90 op_check_header(head, *file_header, filename); 91 92 file_header.reset(new opd_header(head)); 93 94 odb_node_nr_t node_nr, pos; 95 odb_node_t * node = odb_get_iterator(&samples_db, &node_nr); 96 97 for (pos = 0; pos < node_nr; ++pos) { 98 if (node[pos].key) { 99 ordered_samples_t::iterator it = 100 ordered_samples.find(node[pos].key); 101 if (it != ordered_samples.end()) { 102 it->second += node[pos].value; 103 } else { 104 ordered_samples_t::value_type 105 val(node[pos].key, node[pos].value); 106 ordered_samples.insert(val); 107 } 108 } 109 } 110 111 odb_close(&samples_db); 112} 113 114 115void profile_t::set_offset(op_bfd const & abfd) 116{ 117 opd_header const & header = get_header(); 118 if (header.anon_start || header.is_kernel) 119 start_offset = abfd.get_start_offset(header.anon_start); 120 cverb << (vdebug) << "start_offset is now " << start_offset << endl; 121} 122 123 124profile_t::iterator_pair 125profile_t::samples_range(odb_key_t start, odb_key_t end) const 126{ 127 // Check the start position isn't before start_offset: 128 // this avoids wrapping/underflowing start/end. 129 // This can happen on e.g. ARM kernels, where .init is 130 // mapped before .text - we just have to skip any such 131 // .init symbols. 132 if (start < start_offset) { 133 return make_pair(const_iterator(ordered_samples.end(), 0), 134 const_iterator(ordered_samples.end(), 0)); 135 } 136 137 start -= start_offset; 138 end -= start_offset; 139 140 // sanity check if start > end caller will enter into an infinite loop 141 if (start > end) { 142 throw op_fatal_error("profile_t::samples_range(): start > end" 143 " something wrong with kernel or module layout ?\n" 144 "please report problem to " 145 "oprofile-list@lists.sourceforge.net"); 146 } 147 148 ordered_samples_t::const_iterator first = 149 ordered_samples.lower_bound(start); 150 ordered_samples_t::const_iterator last = 151 ordered_samples.lower_bound(end); 152 153 return make_pair(const_iterator(first, start_offset), 154 const_iterator(last, start_offset)); 155} 156 157 158profile_t::iterator_pair profile_t::samples_range() const 159{ 160 ordered_samples_t::const_iterator first = ordered_samples.begin(); 161 ordered_samples_t::const_iterator last = ordered_samples.end(); 162 163 return make_pair(const_iterator(first, start_offset), 164 const_iterator(last, start_offset)); 165} 166