18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/** 28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file callgraph_container.cpp 38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Container associating symbols and caller/caller symbols 48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2004 OProfile authors 68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING 78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Philippe Elie 98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author John Levon 108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <cstdlib> 138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <map> 158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <set> 168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <algorithm> 178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <iterator> 188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <string> 198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <iostream> 208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <numeric> 218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "callgraph_container.h" 238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "cverb.h" 248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "parse_filename.h" 258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "profile_container.h" 268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "arrange_profiles.h" 278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "populate.h" 288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "string_filter.h" 298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_bfd.h" 308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_sample_file.h" 318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "locate_images.h" 328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddusing namespace std; 348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddnamespace { 368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool operator==(cg_symbol const & lhs, cg_symbol const & rhs) 388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd less_symbol cmp_symb; 408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return !cmp_symb(lhs, rhs) && !cmp_symb(rhs, lhs); 418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd// we store {caller,callee} inside a single u64 458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddodb_key_t caller_to_key(u32 value) 468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return odb_key_t(value) << 32; 488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddu32 key_to_callee(odb_key_t key) 528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return key & 0xffffffff; 548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool compare_by_callee_vma(pair<odb_key_t, count_type> const & lhs, 588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd pair<odb_key_t, count_type> const & rhs) 598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return (key_to_callee(lhs.first)) < (key_to_callee(rhs.first)); 618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* 658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * We need 2 comparators for callgraph to get the desired output: 668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * caller_with_few_samples 688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * caller_with_many_samples 698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * function_with_many_samples 708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * callee_with_many_samples 718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * callee_with_few_samples 728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool 758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddcompare_arc_count(symbol_entry const & lhs, symbol_entry const & rhs) 768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return lhs.sample.counts[0] < rhs.sample.counts[0]; 788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool 828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddcompare_arc_count_reverse(symbol_entry const & lhs, symbol_entry const & rhs) 838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return rhs.sample.counts[0] < lhs.sample.counts[0]; 858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd// find the nearest bfd symbol for the given file offset and check it's 898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd// in range 908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddop_bfd_symbol const * 918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddget_symbol_by_filepos(op_bfd const & bfd, u32 bfd_offset, 928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd vma_t offset, symbol_index_t & i) 938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd offset += bfd_offset; 958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd op_bfd_symbol tmpsym(offset, 0, string()); 968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // sorted by filepos so this will find the nearest 988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd vector<op_bfd_symbol>::const_iterator it = 998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd upper_bound(bfd.syms.begin(), bfd.syms.end(), tmpsym); 1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (it != bfd.syms.begin()) 1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd --it; 1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (it == bfd.syms.end()) { 1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "get_symbol_by_filepos: no symbols at all?" << endl; 1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd abort(); 1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // if the offset is past the end of the symbol, we didn't find one 1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd u32 const end_offset = it->size() + it->filepos(); 1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (offset >= end_offset) { 1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // let's be verbose for now 1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "warning: dropping hyperspace sample at offset " 1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << hex << offset << " >= " << end_offset 1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << " for binary " << bfd.get_filename() << dec << endl; 1178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return NULL; 1188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd i = distance(bfd.syms.begin(), it); 1218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return &(*it); 1228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 1238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// temporary caller and callee data held during processing 1268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddclass call_data { 1278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpublic: 1288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd call_data(profile_container const & p, profile_t const & pr, 1298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd op_bfd const & bfd, u32 boff, image_name_id iid, 1308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd image_name_id aid, bool debug_info) 1318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd : pc(p), profile(pr), b(bfd), boffset(boff), image(iid), 1328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd app(aid), debug(debug_info) {} 1338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /// point to a caller symbol 1358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd void caller_sym(symbol_index_t i) { 1368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym = symbol_entry(); 1378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unsigned long long start; 1398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unsigned long long end; 1408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd b.get_symbol_range(i, start, end); 1418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd samples.clear(); 1438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // see profile_t::samples_range() for why we need this check 1458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (start > boffset) { 1468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd profile_t::iterator_pair p_it = profile.samples_range( 1478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd caller_to_key(start - boffset), 1488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd caller_to_key(end - boffset)); 1498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Our odb_key_t contain (from_eip << 32 | to_eip), 1518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // the range of keys we selected above contains one 1528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // caller but different callees, and due to the 1538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // ordering callee offsets are not consecutive: so 1548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // we must sort them first. 1558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (; p_it.first != p_it.second; ++p_it.first) { 1578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd samples.push_back(make_pair(p_it.first.vma(), 1588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd p_it.first.count())); 1598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sort(samples.begin(), samples.end(), 1628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd compare_by_callee_vma); 1638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.size = end - start; 1668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.name = symbol_names.create(b.syms[i].name()); 1678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.sample.vma = b.syms[i].vma(); 1688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd finish_sym(i, start); 1708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (cverb << vdebug) { 1728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cverb << vdebug << hex << "Caller sym: " 1738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << b.syms[i].name() << " filepos " << start 1748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << "-" << end << dec << endl; 1758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /// point to a callee symbol 1798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bool callee_sym(u32 off) { 1808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym = symbol_entry(); 1818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_index_t i = 0; 1838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd op_bfd_symbol const * bfdsym = 1848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd get_symbol_by_filepos(b, boffset, off, i); 1858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!bfdsym) 1878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return false; 1888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd callee_end = bfdsym->size() + bfdsym->filepos() - boffset; 1908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.size = bfdsym->size(); 1928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.name = symbol_names.create(bfdsym->name()); 1938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.sample.vma = bfdsym->vma(); 1948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd finish_sym(i, bfdsym->filepos()); 1968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (cverb << vdebug) { 1988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cverb << vdebug << hex << "Callee sym: " 1998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << bfdsym->name() << " filepos " 2008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << bfdsym->filepos() << "-" 2018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << (bfdsym->filepos() + bfdsym->size()) 2028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << dec << endl; 2038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return true; 2058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd void verbose_bfd(string const & prefix) const { 2088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cverb << vdebug << prefix << " " << b.get_filename() 2098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << " offset " << boffset << " app " 2108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << image_names.name(app) << endl; 2118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd typedef vector<pair<odb_key_t, count_type> > samples_t; 2148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd typedef samples_t::const_iterator const_iterator; 2168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd samples_t samples; 2188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_entry sym; 2198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd u32 callee_end; 2208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddprivate: 2228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /// fill in the rest of the sym 2238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd void finish_sym(symbol_index_t i, unsigned long start) { 2248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.image_name = image; 2258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.app_name = app; 2268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_entry const * self = pc.find(sym); 2278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (self) 2288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.sample.counts = self->sample.counts; 2298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (debug) { 2318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string filename; 2328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd file_location & loc = sym.sample.file_loc; 2338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (b.get_linenr(i, start, filename, loc.linenr)) 2348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd loc.filename = debug_names.create(filename); 2358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd profile_container const & pc; 2398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd profile_t const & profile; 2408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd op_bfd const & b; 2418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd u32 boffset; 2428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd image_name_id image; 2438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd image_name_id app; 2448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bool debug; 2458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}; 2468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// accumulate all samples for a given caller/callee pair 2498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddcount_type 2508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddaccumulate_callee(call_data::const_iterator & it, call_data::const_iterator end, 2518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd u32 callee_end) 2528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd count_type count = 0; 2548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd call_data::const_iterator const start = it; 2558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd while (it != end) { 2578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd u32 offset = key_to_callee(it->first); 2588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (cverb << (vdebug & vlevel1)) { 2608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cverb << (vdebug & vlevel1) << hex << "offset: " 2618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << offset << dec << endl; 2628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // stop if we pass the end of the callee 2658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (offset >= callee_end) 2668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd break; 2678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd count += it->second; 2698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ++it; 2708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // If we haven't advanced at all, then we'll get 2738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // an infinite loop, so we must abort. 2748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (it == start) { 2758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "failure to advance iterator\n"; 2768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd abort(); 2778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return count; 2808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} // anonymous namespace 2848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid arc_recorder:: 2878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddadd(symbol_entry const & caller, symbol_entry const * callee, 2888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd count_array_t const & arc_count) 2898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cg_data & data = sym_map[caller]; 2918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // If we have a callee, add it to the caller's list, then 2938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // add the caller to the callee's list. 2948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (callee) { 2958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd data.callees[*callee] += arc_count; 2968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cg_data & callee_data = sym_map[*callee]; 2988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd callee_data.callers[caller] += arc_count; 3008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 3018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid arc_recorder::process_children(cg_symbol & sym, double threshold) 3058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // generate the synthetic self entry for the symbol 3078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_entry self = sym; 3088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd self.name = symbol_names.create(symbol_names.demangle(self.name) 3108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd + " [self]"); 3118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.total_callee_count += self.sample.counts; 3138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.callees.push_back(self); 3148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sort(sym.callers.begin(), sym.callers.end(), compare_arc_count); 3168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sort(sym.callees.begin(), sym.callees.end(), compare_arc_count_reverse); 3178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // FIXME: this relies on sort always being sample count 3198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cg_symbol::children::iterator cit = sym.callers.begin(); 3218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cg_symbol::children::iterator cend = sym.callers.end(); 3228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd while (cit != cend && op_ratio(cit->sample.counts[0], 3248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.total_caller_count[0]) < threshold) 3258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ++cit; 3268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (cit != cend) 3288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.callers.erase(sym.callers.begin(), cit); 3298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cit = sym.callees.begin(); 3318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cend = sym.callees.end(); 3328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd while (cit != cend && op_ratio(cit->sample.counts[0], 3348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.total_callee_count[0]) >= threshold) 3358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ++cit; 3368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (cit != cend) 3388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.callees.erase(cit, sym.callees.end()); 3398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid arc_recorder:: 3438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddprocess(count_array_t total, double threshold, 3448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string_filter const & sym_filter) 3458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd map_t::const_iterator it; 3478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd map_t::const_iterator end = sym_map.end(); 3488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (it = sym_map.begin(); it != end; ++it) { 3508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cg_symbol sym((*it).first); 3518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cg_data const & data = (*it).second; 3528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // threshold out the main symbol if needed 3548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (op_ratio(sym.sample.counts[0], total[0]) < threshold) 3558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd continue; 3568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // FIXME: slow? 3588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!sym_filter.match(symbol_names.demangle(sym.name))) 3598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd continue; 3608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cg_data::children::const_iterator cit; 3628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cg_data::children::const_iterator cend = data.callers.end(); 3638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (cit = data.callers.begin(); cit != cend; ++cit) { 3658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_entry csym = cit->first; 3668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd csym.sample.counts = cit->second; 3678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.callers.push_back(csym); 3688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.total_caller_count += cit->second; 3698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 3708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cend = data.callees.end(); 3728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (cit = data.callees.begin(); cit != cend; ++cit) { 3748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_entry csym = cit->first; 3758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd csym.sample.counts = cit->second; 3768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.callees.push_back(csym); 3778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sym.total_callee_count += cit->second; 3788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 3798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd process_children(sym, threshold); 3818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // insert sym into cg_syms_objs 3838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // then store pointer to sym in cg_syms 3848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cg_syms.push_back(&(*cg_syms_objs.insert(cg_syms_objs.end(), sym))); 3858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 3868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddsymbol_collection const & arc_recorder::get_symbols() const 3908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return cg_syms; 3928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid callgraph_container::populate(list<inverted_profile> const & iprofiles, 3968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd extra_images const & extra, bool debug_info, double threshold, 3978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bool merge_lib, string_filter const & sym_filter) 3988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd this->extra_found_images = extra; 4008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // non callgraph samples container, we record sample at symbol level 4018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // not at vma level. 4028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd profile_container pc(debug_info, false, extra_found_images); 4038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<inverted_profile>::const_iterator it; 4058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<inverted_profile>::const_iterator const end = iprofiles.end(); 4068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (it = iprofiles.begin(); it != end; ++it) { 4078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // populate_caller_image take care about empty sample filename 4088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd populate_for_image(pc, *it, sym_filter, 0); 4098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 4108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd add_symbols(pc); 4128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd total_count = pc.samples_count(); 4148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (it = iprofiles.begin(); it != end; ++it) { 4168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t i = 0; i < it->groups.size(); ++i) { 4178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd populate(it->groups[i], it->image, 4188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd i, pc, debug_info, merge_lib); 4198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 4208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 4218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd recorder.process(total_count, threshold / 100.0, sym_filter); 4238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 4248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid callgraph_container::populate(list<image_set> const & lset, 4278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const & app_image, size_t pclass, 4288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd profile_container const & pc, bool debug_info, bool merge_lib) 4298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 4308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<image_set>::const_iterator lit; 4318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<image_set>::const_iterator const lend = lset.end(); 4328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (lit = lset.begin(); lit != lend; ++lit) { 4338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<profile_sample_files>::const_iterator pit; 4348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<profile_sample_files>::const_iterator pend 4358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd = lit->files.end(); 4368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (pit = lit->files.begin(); pit != pend; ++pit) { 4378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd populate(pit->cg_files, app_image, 4388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd pclass, pc, debug_info, merge_lib); 4398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 4408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 4418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 4428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid callgraph_container::populate(list<string> const & cg_files, 4458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const & app_image, size_t pclass, 4468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd profile_container const & pc, bool debug_info, bool merge_lib) 4478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 4488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string>::const_iterator it; 4498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string>::const_iterator const end = cg_files.end(); 4508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (it = cg_files.begin(); it != end; ++it) { 4518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cverb << vdebug << "samples file : " << *it << endl; 4528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd parsed_filename caller_file = 4548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd parse_filename(*it, extra_found_images); 4558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const app_name = caller_file.image; 4568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd image_error error; 4588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd extra_found_images.find_image_path(caller_file.lib_image, 4598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd error, false); 4608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (error != image_ok) 4628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd report_image_error(caller_file.lib_image, 4638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd error, false, extra_found_images); 4648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bool caller_bfd_ok = true; 4668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd op_bfd caller_bfd(caller_file.lib_image, 4678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string_filter(), extra_found_images, caller_bfd_ok); 4688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!caller_bfd_ok) 4698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd report_image_error(caller_file.lib_image, 4708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd image_format_failure, false, 4718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd extra_found_images); 4728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd parsed_filename callee_file = 4748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd parse_filename(*it, extra_found_images); 4758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd extra_found_images.find_image_path(callee_file.cg_image, 4778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd error, false); 4788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (error != image_ok) 4798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd report_image_error(callee_file.cg_image, 4808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd error, false, extra_found_images); 4818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bool callee_bfd_ok = true; 4838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd op_bfd callee_bfd(callee_file.cg_image, 4848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string_filter(), extra_found_images, callee_bfd_ok); 4858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!callee_bfd_ok) 4868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd report_image_error(callee_file.cg_image, 4878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd image_format_failure, false, 4888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd extra_found_images); 4898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd profile_t profile; 4918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // We can't use start_offset support in profile_t, give 4928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // it a zero offset and we will fix that in add() 4938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd profile.add_sample_file(*it); 4948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd add(profile, caller_bfd, caller_bfd_ok, callee_bfd, 4958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd merge_lib ? app_image : app_name, pc, 4968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd debug_info, pclass); 4978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 4988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 4998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid callgraph_container:: 5028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddadd(profile_t const & profile, op_bfd const & caller_bfd, bool caller_bfd_ok, 5038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd op_bfd const & callee_bfd, string const & app_name, 5048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd profile_container const & pc, bool debug_info, size_t pclass) 5058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 5068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const image_name = caller_bfd.get_filename(); 5078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_header const & header = profile.get_header(); 5098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // We can't use kernel sample file w/o the binary else we will 5118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // use it with a zero offset, the code below will abort because 5128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // we will get incorrect callee sub-range and out of range 5138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // callee vma. FIXME 5148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (header.is_kernel && !caller_bfd_ok) 5158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return; 5168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // We must handle start_offset, this offset can be different for the 5188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // caller and the callee: kernel sample traversing the syscall barrier. 5198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd u32 caller_offset; 5208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (header.is_kernel) 5218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd caller_offset = caller_bfd.get_start_offset(0); 5228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd else 5238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd caller_offset = header.anon_start; 5248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd u32 callee_offset; 5268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (header.cg_to_is_kernel) 5278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd callee_offset = callee_bfd.get_start_offset(0); 5288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd else 5298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd callee_offset = header.cg_to_anon_start; 5308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd image_name_id image_id = image_names.create(image_name); 5328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd image_name_id callee_image_id = image_names.create(callee_bfd.get_filename()); 5338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd image_name_id app_id = image_names.create(app_name); 5348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd call_data caller(pc, profile, caller_bfd, caller_offset, image_id, 5368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd app_id, debug_info); 5378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd call_data callee(pc, profile, callee_bfd, callee_offset, 5388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd callee_image_id, app_id, debug_info); 5398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (cverb << vdebug) { 5418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd caller.verbose_bfd("Caller:"); 5428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd callee.verbose_bfd("Callee:"); 5438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 5448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // For each symbol in the caller bfd, process all arcs to 5468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // callee bfd symbols 5478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (symbol_index_t i = 0; i < caller_bfd.syms.size(); ++i) { 5498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd caller.caller_sym(i); 5518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd call_data::const_iterator dit = caller.samples.begin(); 5538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd call_data::const_iterator dend = caller.samples.end(); 5548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd while (dit != dend) { 5558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // if we can't find the callee, skip an arc 5568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!callee.callee_sym(key_to_callee(dit->first))) { 5578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ++dit; 5588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd continue; 5598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 5608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd count_array_t arc_count; 5628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd arc_count[pclass] = 5638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd accumulate_callee(dit, dend, callee.callee_end); 5648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd recorder.add(caller.sym, &callee.sym, arc_count); 5668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 5678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 5688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 5698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid callgraph_container::add_symbols(profile_container const & pc) 5728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 5738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_container::symbols_t::iterator it; 5748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_container::symbols_t::iterator const end = pc.end_symbol(); 5758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (it = pc.begin_symbol(); it != end; ++it) 5778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd recorder.add(*it, 0, count_array_t()); 5788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 5798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddcolumn_flags callgraph_container::output_hint() const 5828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 5838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd column_flags output_hints = cf_none; 5848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // FIXME: costly: must we access directly recorder map ? 5868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_collection syms = recorder.get_symbols(); 5878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_collection::iterator it; 5898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_collection::iterator const end = syms.end(); 5908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (it = syms.begin(); it != end; ++it) 5918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd output_hints = (*it)->output_hint(output_hints); 5928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return output_hints; 5948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 5958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddcount_array_t callgraph_container::samples_count() const 5988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 5998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return total_count; 6008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 6018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddsymbol_collection const & callgraph_container::get_symbols() const 6048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 6058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return recorder.get_symbols(); 6068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 607