1/**
2 * @file opgprof_options.cpp
3 * Options for opgprof tool
4 *
5 * @remark Copyright 2003 OProfile authors
6 * @remark Read the file COPYING
7 *
8 * @author John Levon
9 * @author Philippe Elie
10 */
11
12#include <cstdlib>
13
14#include <vector>
15#include <list>
16#include <iterator>
17#include <iostream>
18#include <cstdlib>
19
20#include "opgprof_options.h"
21#include "popt_options.h"
22#include "cverb.h"
23#include "profile_spec.h"
24#include "arrange_profiles.h"
25
26using namespace std;
27
28profile_classes classes;
29inverted_profile image_profile;
30
31namespace options {
32	string gmon_filename = "gmon.out";
33
34	// Ugly, for build only
35	demangle_type demangle;
36}
37
38
39namespace {
40
41popt::option options_array[] = {
42	popt::option(options::gmon_filename, "output-filename", 'o',
43	             "output filename, defaults to gmon.out if not specified",
44	             "filename"),
45	popt::option(options::threshold_opt, "threshold", 't',
46		     "minimum percentage needed to produce output",
47		     "percent"),
48};
49
50
51bool try_merge_profiles(profile_spec const & spec, bool exclude_dependent)
52{
53	list<string> sample_files = spec.generate_file_list(exclude_dependent, false);
54
55	cverb << vsfile
56	      << "Matched sample files: " << sample_files.size() << endl;
57	copy(sample_files.begin(), sample_files.end(),
58	     ostream_iterator<string>(cverb << vsfile, "\n"));
59
60	// opgprof merge all by default
61	merge_option merge_by;
62	merge_by.cpu = true;
63	merge_by.lib = true;
64	merge_by.tid = true;
65	merge_by.tgid = true;
66	merge_by.unitmask = true;
67
68	classes	= arrange_profiles(sample_files, merge_by,
69				   spec.extra_found_images);
70
71	cverb << vsfile << "profile_classes:\n" << classes << endl;
72
73	size_t nr_classes = classes.v.size();
74
75	list<inverted_profile> iprofiles = invert_profiles(classes);
76
77	if (nr_classes == 1 && iprofiles.size() == 1) {
78		image_profile = *(iprofiles.begin());
79		return true;
80	}
81
82	// come round for another try
83	if (exclude_dependent)
84		return false;
85
86	if (iprofiles.empty()) {
87		cerr << "error: no sample files found: profile specification "
88		     "too strict ?" << endl;
89		exit(EXIT_FAILURE);
90	}
91
92	if (nr_classes > 1 || iprofiles.size() > 1) {
93		cerr << "error: specify exactly one binary to process "
94		     "and give an event: or count: specification if necessary"
95		     << endl;
96		exit(EXIT_FAILURE);
97	}
98
99	return false;
100}
101
102}  // anonymous namespace
103
104
105void handle_options(options::spec const & spec)
106{
107	if (spec.first.size()) {
108		cerr << "differential profiles not allowed" << endl;
109		exit(EXIT_FAILURE);
110	}
111
112	profile_spec const pspec =
113		profile_spec::create(spec.common, options::image_path,
114				     options::root_path);
115
116	cverb << vsfile << "output filename: " << options::gmon_filename
117	      << endl;
118
119	// we do a first try with exclude-dependent if it fails we include
120	// dependent. First try should catch "opgrof /usr/bin/make" whilst
121	// the second catch "opgprof /lib/libc-2.2.5.so"
122	if (!try_merge_profiles(pspec, true))
123		try_merge_profiles(pspec, false);
124}
125