18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file profile_spec.cpp
38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Contains a PP profile specification
48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2003 OProfile authors
68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING
78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Philippe Elie
98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <algorithm>
128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <set>
138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <sstream>
148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <iterator>
158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <iostream>
168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <dirent.h>
178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "file_manip.h"
198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_config.h"
208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "profile_spec.h"
218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "string_manip.h"
228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "glob_filter.h"
238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "locate_images.h"
248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_exception.h"
258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_header.h"
268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_fileio.h"
278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddusing namespace std;
298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddnamespace {
318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd// PP:3.7, full path, or relative path. If we can't find it,
338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd// we should maintain the original to maintain the wordexp etc.
348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring const fixup_image_spec(string const & str, extra_images const & extra)
358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// On error find_image_path() return str, so if an occur we will
378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// use the provided image_name not the fixed one.
388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	image_error error;
398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return extra.find_image_path(str, error, true);
408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid fixup_image_spec(vector<string> & images, extra_images const & extra)
438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	vector<string>::iterator it = images.begin();
458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	vector<string>::iterator const end = images.end();
468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (; it != end; ++it)
488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		*it = fixup_image_spec(*it, extra);
498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}  // anon namespace
528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddprofile_spec::profile_spec()
558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	:
568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	extra_found_images()
578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	parse_table["archive"] = &profile_spec::parse_archive_path;
598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	parse_table["session"] = &profile_spec::parse_session;
608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	parse_table["session-exclude"] =
618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		&profile_spec::parse_session_exclude;
628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	parse_table["image"] = &profile_spec::parse_image;
638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	parse_table["image-exclude"] = &profile_spec::parse_image_exclude;
648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	parse_table["lib-image"] = &profile_spec::parse_lib_image;
658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	parse_table["event"] = &profile_spec::parse_event;
668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	parse_table["count"] = &profile_spec::parse_count;
678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	parse_table["unit-mask"] = &profile_spec::parse_unitmask;
688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	parse_table["tid"] = &profile_spec::parse_tid;
698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	parse_table["tgid"] = &profile_spec::parse_tgid;
708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	parse_table["cpu"] = &profile_spec::parse_cpu;
718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::parse(string const & tag_value)
758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	string value;
778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	action_t action = get_handler(tag_value, value);
788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!action) {
798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		throw invalid_argument("profile_spec::parse(): not "
808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				       "a valid tag \"" + tag_value + "\"");
818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	(this->*action)(value);
848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool profile_spec::is_valid_tag(string const & tag_value)
888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	string value;
908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return get_handler(tag_value, value);
918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::set_image_or_lib_name(string const & str)
958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* FIXME: what does spec say about this being allowed to be
978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * a comma list or not ? */
988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	image_or_lib_image.push_back(fixup_image_spec(str, extra_found_images));
998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::parse_archive_path(string const & str)
1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	archive_path = op_realpath(str);
1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring profile_spec::get_archive_path() const
1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return archive_path;
1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::parse_session(string const & str)
1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	session = separate_token(str, ',');
1178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::parse_session_exclude(string const & str)
1218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	session_exclude = separate_token(str, ',');
1238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::parse_image(string const & str)
1278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	image = separate_token(str, ',');
1298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	fixup_image_spec(image, extra_found_images);
1308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::parse_image_exclude(string const & str)
1348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	image_exclude = separate_token(str, ',');
1368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	fixup_image_spec(image_exclude, extra_found_images);
1378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::parse_lib_image(string const & str)
1418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	lib_image = separate_token(str, ',');
1438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	fixup_image_spec(lib_image, extra_found_images);
1448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::parse_event(string const & str)
1488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	event.set(str);
1508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::parse_count(string const & str)
1548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	count.set(str);
1568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::parse_unitmask(string const & str)
1608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unitmask.set(str);
1628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::parse_tid(string const & str)
1668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	tid.set(str);
1688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::parse_tgid(string const & str)
1728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	tgid.set(str);
1748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid profile_spec::parse_cpu(string const & str)
1788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	cpu.set(str);
1808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddprofile_spec::action_t
1848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddprofile_spec::get_handler(string const & tag_value, string & value)
1858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	string::size_type pos = tag_value.find_first_of(':');
1878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (pos == string::npos)
1888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return 0;
1898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	string tag(tag_value.substr(0, pos));
1918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	value = tag_value.substr(pos + 1);
1928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	parse_table_t::const_iterator it = parse_table.find(tag);
1948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (it == parse_table.end())
1958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return 0;
1968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return it->second;
1988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddnamespace {
2028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// return true if the value from the profile spec may match the comma
2048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// list
2058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddtemplate<typename T>
2068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool comma_match(comma_list<T> const & cl, generic_spec<T> const & value)
2078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
2088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// if the profile spec is "all" we match the sample file
2098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!cl.is_set())
2108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return true;
2118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// an "all" sample file should never match specified profile
2138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// spec values
2148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!value.is_set())
2158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return false;
2168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// now match each profile spec value against the sample file
2188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return cl.match(value.value());
2198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
2208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
2228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool profile_spec::match(filename_spec const & spec) const
2258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
2268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	bool matched_by_image_or_lib_image = false;
2278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// We need the true image name not the one based on the sample
2298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// filename for the benefit of module which have /oprofile in their
2308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// sample filename. This allow to specify profile spec based on the
2318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// real name of the image, e.g. 'binary:*oprofile.ko'
2328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	string simage = fixup_image_spec(spec.image, extra_found_images);
2338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	string slib_image = fixup_image_spec(spec.lib_image,
2348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					     extra_found_images);
2358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// PP:3.19
2378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!image_or_lib_image.empty()) {
2388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		glob_filter filter(image_or_lib_image, image_exclude);
2398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (filter.match(simage) || filter.match(slib_image))
2408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			matched_by_image_or_lib_image = true;
2418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
2428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!matched_by_image_or_lib_image) {
2448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		// PP:3.7 3.8
2458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!image.empty()) {
2468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			glob_filter filter(image, image_exclude);
2478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (!filter.match(simage))
2488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				return false;
2498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		} else if (!image_or_lib_image.empty()) {
2508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			// image.empty() means match all except if user
2518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			// specified image_or_lib_image
2528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return false;
2538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
2548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		// PP:3.9 3.10
2568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!lib_image.empty()) {
2578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			glob_filter filter(lib_image, image_exclude);
2588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (!filter.match(slib_image))
2598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				return false;
2608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		} else if (image.empty() && !image_or_lib_image.empty()) {
2618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			// lib_image empty means match all except if user
2628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			// specified image_or_lib_image *or* we already
2638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			// matched this spec through image
2648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return false;
2658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
2668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
2678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!matched_by_image_or_lib_image) {
2698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		// if we don't match by image_or_lib_image we must try to
2708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		// exclude from spec, exclusion from image_or_lib_image has
2718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		// been handled above
2728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		vector<string> empty;
2738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		glob_filter filter(empty, image_exclude);
2748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!filter.match(simage))
2758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return false;
2768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!spec.lib_image.empty() && !filter.match(slib_image))
2778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return false;
2788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
2798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!event.match(spec.event))
2818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return false;
2828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!count.match(spec.count))
2848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return false;
2858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!unitmask.match(spec.unitmask))
2878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return false;
2888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!comma_match(cpu, spec.cpu))
2908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return false;
2918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!comma_match(tid, spec.tid))
2938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return false;
2948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!comma_match(tgid, spec.tgid))
2968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return false;
2978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return true;
2998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
3008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddprofile_spec profile_spec::create(list<string> const & args,
3038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd                                  vector<string> const & image_path,
3048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				  string const & root_path)
3058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
3068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	profile_spec spec;
3078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	set<string> tag_seen;
3088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	vector<string> temp_image_or_lib;
3098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list<string>::const_iterator it = args.begin();
3118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list<string>::const_iterator end = args.end();
3128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (; it != end; ++it) {
3148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (spec.is_valid_tag(*it)) {
3158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (tag_seen.find(*it) != tag_seen.end()) {
3168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				throw op_runtime_error("tag specified "
3178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				       "more than once: " + *it);
3188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			}
3198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			tag_seen.insert(*it);
3208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			spec.parse(*it);
3218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		} else {
3228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			string const file = op_realpath(*it);
3238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			temp_image_or_lib.push_back(file);
3248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
3258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// PP:3.5 no session given means use the current session.
3288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (spec.session.empty())
3298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		spec.session.push_back("current");
3308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	bool ok = true;
3328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	vector<string>::const_iterator ip_it = image_path.begin();
3338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for ( ; ip_it != image_path.end(); ++ip_it) {
3348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!is_directory(spec.get_archive_path() + "/" + *ip_it)) {
3358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			cerr << spec.get_archive_path() + "/" + *ip_it << " isn't a valid directory\n";
3368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			ok = false;
3378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
3388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!ok)
3408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		throw op_runtime_error("invalid --image-path= options");
3418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	spec.extra_found_images.populate(image_path, spec.get_archive_path(),
3438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					 root_path);
3448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	vector<string>::const_iterator im = temp_image_or_lib.begin();
3458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	vector<string>::const_iterator last = temp_image_or_lib.end();
3468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (; im != last; ++im)
3478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		spec.set_image_or_lib_name(*im);
3488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return spec;
3508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
3518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddnamespace {
3538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvector<string> filter_session(vector<string> const & session,
3558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			      vector<string> const & session_exclude)
3568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
3578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	vector<string> result(session);
3588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (result.empty())
3608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		result.push_back("current");
3618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (size_t i = 0 ; i < session_exclude.size() ; ++i) {
3638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		// FIXME: would we use fnmatch on each item, are we allowed
3648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		// to --session=current* ?
3658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		vector<string>::iterator it =
3668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			find(result.begin(), result.end(), session_exclude[i]);
3678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (it != result.end())
3698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			result.erase(it);
3708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return result;
3738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
3748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic bool invalid_sample_file;
3768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool valid_candidate(string const & base_dir, string const & filename,
3778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd                     profile_spec const & spec, bool exclude_dependent,
3788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd                     bool exclude_cg)
3798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
3808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (exclude_cg && filename.find("{cg}") != string::npos)
3818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return false;
3828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// strip out non sample files
3848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	string const & sub = filename.substr(base_dir.size(), string::npos);
3858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!is_prefix(sub, "/{root}/") && !is_prefix(sub, "/{kern}/"))
3868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return false;
3878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* When overflows occur in the oprofile kernel driver's sample
3898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * buffers (caused by too high of a sampling rate), it's possible
3908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * for samples to be mis-attributed.  A common scenario is that,
3918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * while profiling process 'abc' running binary 'xzy', the task
3928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * switch for 'abc' gets dropped somehow.  Then, samples are taken
3938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * for the 'xyz' binary.  In the attempt to attribute the samples to
3948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * the associated binary, the oprofile kernel code examines the
3958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * the memory mappings for the last process for which it recorded
3968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * a task switch.  When profiling at a very high rate, the oprofile
3978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * daemon is often the process that is mistakenly examined.  Then the
3988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * sample from binary 'xyz' is matched to some file that's open in
3998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * oprofiled's memory space.  Because oprofiled has many sample files
4008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * open at any given time, there's a good chance the sample's VMA is
4018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * contained within one of those sample files.  So, once finding this
4028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * bogus match, the oprofile kernel records a cookie switch for the
4038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * sample file.  This scenario is made even more likely if a high
4048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * sampling rate (e.g., profiling on several events) is paired with
4058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * callgraph data collection.
4068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
4078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * When the daemon processes this sample data from the kernel, it
4088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * creates a sample file for the sample file, resulting in something
4098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * of the form:
4108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *    <session-dir>/[blah]<session-dir>/[blah]
4118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
4128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * When the sample data is post-processed, the sample file is parsed to
4138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * try to determine the name of the binary, but it gets horribly confused.
4148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * At best, the post-processing tool will spit out some warning messages,
4158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * such as:
4168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * warning:
4178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * /lib64/libdl-2.9.so/CYCLES.10000.0.all.all.all/{dep}/{root}/var/lib/oprofile/samples/current/{root}/lib64/libdl-2.9.so/{dep}/{root}/lib64/libdl-2.9.so/PM_RUN_CYC_GRP12.10000.0.all.all.all
4188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * could not be found.
4198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
4208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * At worst, the parsing may result in an "invalid argument" runtime error
4218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * because of the inability to parse a sample file whose name contains that
4228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * of another sample file.  This typically seems to happen when callgraph
4238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * data is being collected.
4248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
4258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * The next several lines of code checks if the passed filename
4268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * contains <session-dir>/samples; if so, we discard it as an
4278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * invalid sample file.
4288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
4298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int j = base_dir.rfind('/');
4318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	string session_samples_dir = base_dir.substr(0, j);
4328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (sub.find(session_samples_dir) != string::npos) {
4338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		invalid_sample_file = true;
4348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return false;
4358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// strip out generated JIT object files for samples of anonymous regions
4388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (is_jit_sample(sub))
4398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return false;
4408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	filename_spec file_spec(filename, spec.extra_found_images);
4428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (spec.match(file_spec)) {
4438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (exclude_dependent && file_spec.is_dependent())
4448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return false;
4458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return true;
4468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return false;
4498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
4508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
4538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Print a warning message if we detect any sample buffer overflows
4548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * occurred in the kernel driver.
4558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
4568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid warn_if_kern_buffs_overflow(string const & session_samples_dir)
4578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
4588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	DIR * dir;
4598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct dirent * dirent;
4608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	string stats_path;
4618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int ret = 0;
4628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	stats_path = session_samples_dir + "stats/";
4648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ret = op_read_int_from_file((stats_path + "event_lost_overflow").
4658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				    c_str(), 0);
4668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!(dir = opendir(stats_path.c_str()))) {
4688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		ret = -1;
4698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto done;
4708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	while ((dirent = readdir(dir)) && !ret) {
4738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		int cpu_nr;
4748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		string path;
4758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (sscanf(dirent->d_name, "cpu%d", &cpu_nr) != 1)
4768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			continue;
4778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		path = stats_path + dirent->d_name + "/";
4788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		ret = op_read_int_from_file((path + "sample_lost_overflow").
4798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					    c_str(), 0);
4808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	closedir(dir);
4828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd done:
4847a33c86eb98056ef0570c99e713214f8dc56b6efJeff Brown	if (ret > 0) {
4858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		cerr << "WARNING! The OProfile kernel driver reports sample "
4868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		     << "buffer overflows." << endl;
4878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		cerr << "Such overflows can result in incorrect sample attribution"
4888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		     << ", invalid sample" << endl
4898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		     <<	"files and other symptoms.  "
4908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		     << "See the oprofiled.log for details." << endl;
4918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		cerr << "You should adjust your sampling frequency to eliminate"
4928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		     << " (or at least minimize)" << endl
4938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		     <<	"these overflows." << endl;
4948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
4968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}  // anonymous namespace
4998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddlist<string> profile_spec::generate_file_list(bool exclude_dependent,
5028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd  bool exclude_cg) const
5038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
5048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	// FIXME: isn't remove_duplicates faster than doing this, then copy() ?
5058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	set<string> unique_files;
5068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	vector<string> sessions = filter_session(session, session_exclude);
5088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (sessions.empty()) {
5108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		ostringstream os;
5118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		os << "No session given\n"
5128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		   << "included session was:\n";
5138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		copy(session.begin(), session.end(),
5148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		     ostream_iterator<string>(os, "\n"));
5158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		os << "excluded session was:\n";
5168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		copy(session_exclude.begin(), session_exclude.end(),
5178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		     ostream_iterator<string>(os, "\n"));
5188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		throw invalid_argument(os.str());
5198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	bool found_file = false;
5228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	vector<string>::const_iterator cit = sessions.begin();
5248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	vector<string>::const_iterator end = sessions.end();
5258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (; cit != end; ++cit) {
5278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (cit->empty())
5288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			continue;
5298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		string base_dir;
5318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		invalid_sample_file = false;
5328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if ((*cit)[0] != '.' && (*cit)[0] != '/')
5338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			base_dir = archive_path + op_samples_dir;
5348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		base_dir += *cit;
5358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		base_dir = op_realpath(base_dir);
5378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		list<string> files;
5398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		create_file_list(files, base_dir, "*", true);
5408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!files.empty()) {
5428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			found_file = true;
5438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			warn_if_kern_buffs_overflow(base_dir + "/");
5448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
5458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		list<string>::const_iterator it = files.begin();
5478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		list<string>::const_iterator fend = files.end();
5488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		for (; it != fend; ++it) {
5498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (valid_candidate(base_dir, *it, *this,
5508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			    exclude_dependent, exclude_cg)) {
5518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				unique_files.insert(*it);
5528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			}
5538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
5548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (invalid_sample_file) {
5558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			cerr << "Warning: Invalid sample files found in "
5568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			     << base_dir << endl;
5578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			cerr << "This problem can be caused by too high of a sampling rate."
5588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			     << endl;
5598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
5608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!found_file) {
5638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		ostringstream os;
5648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		os  << "No sample file found: try running opcontrol --dump\n"
5658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		    << "or specify a session containing sample files\n";
5668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		throw op_fatal_error(os.str());
5678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list<string> result;
5708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	copy(unique_files.begin(), unique_files.end(), back_inserter(result));
5718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return result;
5738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
574