18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file profile.h
38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Encapsulation for samples files over all profile classes
48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * belonging to the same binary image
58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2002 OProfile authors
78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING
88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Philippe Elie
108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author John Levon
118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#ifndef PROFILE_H
148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define PROFILE_H
158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <string>
178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <map>
188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <iterator>
198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "odb.h"
218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_types.h"
228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "utility.h"
238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "populate_for_spu.h"
248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddclass opd_header;
268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddclass op_bfd;
278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Class containing a single sample file contents.
308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * i.e. set of count values for VMA offsets for
318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * a particular binary.
328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddclass profile_t : noncopyable {
348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpublic:
358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/**
368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * profile_t - construct an empty  profile_t object
378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	profile_t();
398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/// return true if no sample file has been loaded
418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	bool empty() const { return !file_header.get(); }
428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/// return the header of the last opened samples file
448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	opd_header const & get_header() const {
458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return *file_header;
468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/**
498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * count samples count w/o recording them
508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * @param filename sample filename
518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * convenience interface for raw access to sample count w/o recording
538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * them. It's placed here so all access to samples files go through
548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * profile_t static or non static member.
558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	static count_type sample_count(std::string const & filename);
578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/**
598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * Indicate if given sample file is from a Cell Broadband Engine
608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * SPU profile
618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * @param filename sample filename
628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * Convenience interface put here so all access to samples files
648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * go through profile_t static or non static member.
658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	static enum profile_type is_spu_sample_file(std::string const & filename);
678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/**
698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * cumulate sample file to our container of samples
708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * @param filename  sample file name
718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * store samples for one sample file, sample file header is sanitized.
738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * all error are fatal
758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	void add_sample_file(std::string const & filename);
778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/// Set an appropriate start offset, see comments below.
798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	void set_offset(op_bfd const & abfd);
808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	class const_iterator;
828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	typedef std::pair<const_iterator, const_iterator> iterator_pair;
838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/**
858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * @param start  start offset
868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * @param end  end offset
878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * return an iterator pair to [start, end) range
898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	iterator_pair
918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	samples_range(odb_key_t start, odb_key_t end) const;
928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/// return a pair of iterator for all samples
948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	iterator_pair samples_range() const;
958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddprivate:
978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/// helper for sample_count() and add_sample_file(). All error launch
988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/// an exception.
998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	static void
1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	open_sample_file(std::string const & filename, odb_t &);
1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/// copy of the samples file header
1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	scoped_ptr<opd_header> file_header;
1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/// storage type for samples sorted by eip
1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	typedef std::map<odb_key_t, count_type> ordered_samples_t;
1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/**
1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * Samples are stored in hash table, iterating over hash table don't
1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * provide any ordering, the above count() interface rely on samples
1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * ordered by eip. This map is only a temporary storage where samples
1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * are ordered by eip.
1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ordered_samples_t ordered_samples;
1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/**
1178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * For certain profiles, such as kernel/modules, and anon
1188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * regions with a matching binary, this value is non-zero,
1198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * and represents the file offset of the relevant section.
1208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
1218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * For kernel profiles, this is done because we use the information
1228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * provided in /proc/ksyms, which only gives the mapped position of
1238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * .text, and the symbol _text from vmlinux. This value is used to fix
1248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * up the sample offsets for kernel code as a result of this difference
1258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
1268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * In user-space samples, the sample offset is from the start of the
1278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * mapped file, as seen in /proc/pid/maps. This is fine for
1288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * mappings of permanent files, but with anon mappings, we need
1298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * to adjust the key values to be a file offset against the
1308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * *binary* (if there is one). This can obviously be different.
1318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * So we pass our anon mapping start VMA to op_bfd, which looks
1328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * for a section with that VMA, then returns the section's
1338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * filepos. So all is good.
1348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
1358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * Finally, note that for cg we can't use this inside the
1368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * profile_t, as we're storing two offsets in the key value. So
1378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * we do it later in that case.
1388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
1398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * Phew.
1408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
1418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	u64 start_offset;
1428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd};
1438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd// It will be easier to derive profile_t::const_iterator from
1468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd// std::iterator<std::input_iterator_tag, unsigned int> but this doesn't
1478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd// work for gcc <= 2.95 so we provide the neccessary typedef in the hard way.
1488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd// See ISO C++ 17.4.3.1 � 1 and 14.7.3 � 9.
1498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddnamespace std {
1508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	template <>
1518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		struct iterator_traits<profile_t::const_iterator> {
1528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			typedef ptrdiff_t difference_type;
1538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			typedef count_type value_type;
1548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			typedef count_type * pointer;
1558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			typedef count_type & reference;
1568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			typedef input_iterator_tag iterator_category;
1578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		};
1588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddclass profile_t::const_iterator
1628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	typedef ordered_samples_t::const_iterator iterator_t;
1648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpublic:
1658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	const_iterator() : start_offset(0) {}
1668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	const_iterator(iterator_t it_, u64 start_offset_)
1678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		: it(it_), start_offset(start_offset_) {}
1688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	count_type operator*() const { return it->second; }
1708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	const_iterator & operator++() { ++it; return *this; }
1718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	odb_key_t vma() const { return it->first + start_offset; }
1738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	count_type count() const { return **this; }
1748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	bool operator!=(const_iterator const & rhs) const {
1768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return it != rhs.it;
1778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	bool operator==(const_iterator const & rhs) const {
1798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return it == rhs.it;
1808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddprivate:
1838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	iterator_t it;
1848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	u64 start_offset;
1858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd};
1868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif /* !PROFILE_H */
188