18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/** 28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file profile.cpp 38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Encapsulation for samples files over all profile classes 48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * belonging to the same binary image 58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2002 OProfile authors 78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING 88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Philippe Elie 108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author John Levon 118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <unistd.h> 148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <cstring> 158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <iostream> 178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <string> 188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <sstream> 198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <cstring> 208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <cerrno> 228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_exception.h" 248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_header.h" 258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_config.h" 268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_sample_file.h" 278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "profile.h" 288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_bfd.h" 298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "cverb.h" 308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "populate_for_spu.h" 318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddusing namespace std; 338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddprofile_t::profile_t() 358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd : start_offset(0) 368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd// static member 418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddcount_type profile_t::sample_count(string const & filename) 428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd odb_t samples_db; 448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd open_sample_file(filename, samples_db); 468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd count_type count = 0; 488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd odb_node_nr_t node_nr, pos; 508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd odb_node_t * node = odb_get_iterator(&samples_db, &node_nr); 518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (pos = 0; pos < node_nr; ++pos) 528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd count += node[pos].value; 538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd odb_close(&samples_db); 558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return count; 578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd//static member 608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddenum profile_type profile_t::is_spu_sample_file(string const & filename) 618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd profile_type retval; 638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd odb_t samples_db; 648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd open_sample_file(filename, samples_db); 658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_header const & hdr = 668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *static_cast<opd_header *>(odb_get_data(&samples_db)); 678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd retval = hdr.spu_profile ? cell_spu_profile: normal_profile; 688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd odb_close(&samples_db); 698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return retval; 708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd//static member 738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_t::open_sample_file(string const & filename, odb_t & db) 748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Check first if the sample file version is ok else odb_open() can 768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // fail and the error message will be obscure. 778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_header head = read_header(filename); 788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (head.version != OPD_VERSION) { 808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ostringstream os; 818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd os << "oprofpp: samples files version mismatch, are you " 828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << "running a daemon and post-profile tools with version " 838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << "mismatch ?\n"; 848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd throw op_fatal_error(os.str()); 858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd int rc = odb_open(&db, filename.c_str(), ODB_RDONLY, 888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sizeof(struct opd_header)); 898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (rc) 918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd throw op_fatal_error(filename + ": " + strerror(rc)); 928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_t::add_sample_file(string const & filename) 958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd odb_t samples_db; 978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd open_sample_file(filename, samples_db); 998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_header const & head = 1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *static_cast<opd_header *>(odb_get_data(&samples_db)); 1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // if we already read a sample file header pointer is non null 1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (file_header.get()) 1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd op_check_header(head, *file_header, filename); 1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd else 1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd file_header.reset(new opd_header(head)); 1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd odb_node_nr_t node_nr, pos; 1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd odb_node_t * node = odb_get_iterator(&samples_db, &node_nr); 1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (pos = 0; pos < node_nr; ++pos) { 1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ordered_samples_t::iterator it = 1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ordered_samples.find(node[pos].key); 1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (it != ordered_samples.end()) { 1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd it->second += node[pos].value; 1178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else { 1188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ordered_samples_t::value_type 1198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd val(node[pos].key, node[pos].value); 1208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ordered_samples.insert(val); 1218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd odb_close(&samples_db); 1258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 1268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_t::set_offset(op_bfd const & abfd) 1298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 1308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // if no bfd file has been located for this samples file, we can't 1318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // shift sample because abfd.get_symbol_range() return the whole 1328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // address space and setting a non zero start_offset will overflow 1338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // in get_symbol_range() caller. 1348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (abfd.valid()) { 1358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_header const & header = get_header(); 1368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (header.anon_start) { 1378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd start_offset = header.anon_start; 1388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else if (header.is_kernel) { 1398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd start_offset = abfd.get_start_offset(0); 1408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cverb << (vdebug) << "start_offset is now " << start_offset << endl; 1438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 1448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddprofile_t::iterator_pair 1478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddprofile_t::samples_range(odb_key_t start, odb_key_t end) const 1488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 1498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Check the start position isn't before start_offset: 1508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // this avoids wrapping/underflowing start/end. 1518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // This can happen on e.g. ARM kernels, where .init is 1528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // mapped before .text - we just have to skip any such 1538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // .init symbols. 1548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (start < start_offset) { 1558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return make_pair(const_iterator(ordered_samples.end(), 0), 1568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd const_iterator(ordered_samples.end(), 0)); 1578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd start -= start_offset; 1608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd end -= start_offset; 1618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // sanity check if start > end caller will enter into an infinite loop 1638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (start > end) { 1648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd throw op_fatal_error("profile_t::samples_range(): start > end" 1658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd " something wrong with kernel or module layout ?\n" 1668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd "please report problem to " 1678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd "oprofile-list@lists.sourceforge.net"); 1688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ordered_samples_t::const_iterator first = 1718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ordered_samples.lower_bound(start); 1728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ordered_samples_t::const_iterator last = 1738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ordered_samples.lower_bound(end); 1748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return make_pair(const_iterator(first, start_offset), 1768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd const_iterator(last, start_offset)); 1778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 1788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddprofile_t::iterator_pair profile_t::samples_range() const 1818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 1828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ordered_samples_t::const_iterator first = ordered_samples.begin(); 1838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ordered_samples_t::const_iterator last = ordered_samples.end(); 1848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return make_pair(const_iterator(first, start_offset), 1868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd const_iterator(last, start_offset)); 1878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 188