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