• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file common_option.cpp
3  * Contains common options and implementation of entry point of pp tools
4  * and some miscelleaneous functions
5  *
6  * @remark Copyright 2003 OProfile authors
7  * @remark Read the file COPYING
8  *
9  * @author Philippe Elie
10  */
11 
12 #include <cstdlib>
13 
14 #include <iostream>
15 #include <sstream>
16 #include <iterator>
17 #include <cstdlib>
18 
19 #include "op_config.h"
20 #include "locate_images.h"
21 #include "op_exception.h"
22 #include "popt_options.h"
23 #include "cverb.h"
24 #include "common_option.h"
25 #include "file_manip.h"
26 
27 using namespace std;
28 
29 namespace options {
30 	double threshold = 0.0;
31 	string threshold_opt;
32 	string session_dir = OP_SESSION_DIR_DEFAULT;
33 	string command_options;
34 	vector<string> image_path;
35 	string root_path;
36 }
37 
38 namespace {
39 
40 vector<string> verbose_strings;
41 
42 popt::option common_options_array[] = {
43 	popt::option(verbose_strings, "verbose", 'V',
44 		     // FIXME help string for verbose level
45 		     "verbose output", "all,debug,bfd,level1,sfile,stats,xml"),
46 	popt::option(options::session_dir, "session-dir", '\0',
47 		     "specify session path to hold samples database and session data (" OP_SESSION_DIR_DEFAULT ")", "path"),
48 	popt::option(options::image_path, "image-path", 'p',
49 		     "comma-separated path to search missing binaries", "path"),
50 	popt::option(options::root_path, "root", 'R',
51 		     "path to filesystem to search for missing binaries", "path"),
52 };
53 
54 
handle_threshold(string threshold)55 double handle_threshold(string threshold)
56 {
57 	double value = 0.0;
58 
59 	if (threshold.length()) {
60 		istringstream ss(threshold);
61 		if (!(ss >> value)) {
62 			cerr << "illegal threshold value: " << threshold
63 			     << " allowed range: [0-100]" << endl;
64 			exit(EXIT_FAILURE);
65 		}
66 
67 		if (value < 0.0 || value > 100.0) {
68 			cerr << "illegal threshold value: " << threshold
69 			     << " allowed range: [0-100]" << endl;
70 			exit(EXIT_FAILURE);
71 		}
72 	}
73 
74 	cverb << vdebug << "threshold: " << value << endl;;
75 
76 	return value;
77 }
78 
79 
pre_parse_spec(vector<string> const & non_options)80 vector<string> pre_parse_spec(vector<string> const & non_options)
81 {
82 	vector<string> result;
83 
84 	for (size_t i = 0; i < non_options.size(); ++i) {
85 		if (non_options[i] == "{}") {
86 			result.push_back("{");
87 			result.push_back("}");
88 		} else {
89 			result.push_back(non_options[i]);
90 		}
91 	}
92 
93 	return result;
94 }
95 
96 
parse_spec(vector<string> non_options)97 options::spec const parse_spec(vector<string> non_options)
98 {
99 	bool in_first = false;
100 	bool in_second = false;
101 	bool first = false;
102 	bool second = false;
103 	options::spec pspec;
104 
105 	non_options = pre_parse_spec(non_options);
106 
107 	vector<string>::const_iterator it = non_options.begin();
108 	vector<string>::const_iterator end = non_options.end();
109 
110 	for (; it != end; ++it) {
111 		if (*it == "{") {
112 			if (in_first || in_second || second)
113 				goto fail;
114 			if (first) {
115 				in_second = true;
116 				second = true;
117 			} else {
118 				in_first = true;
119 				first = true;
120 			}
121 			continue;
122 		}
123 
124 		if (*it == "}") {
125 			if (in_first) {
126 				in_first = false;
127 			} else if (in_second) {
128 				in_second = false;
129 			} else {
130 				goto fail;
131 			}
132 			continue;
133 		}
134 
135 		if (in_first) {
136 			pspec.first.push_back(*it);
137 		} else if (in_second) {
138 			pspec.second.push_back(*it);
139 		} else {
140 			pspec.common.push_back(*it);
141 		}
142 	}
143 
144 	if (in_first || in_second || (first && !second))
145 		goto fail;
146 
147 	if (pspec.first.empty() && pspec.second.size())
148 		goto fail;
149 
150 	if (first && second) {
151 		pspec.first.insert(pspec.first.begin(), pspec.common.begin(),
152 		                   pspec.common.end());
153 		pspec.second.insert(pspec.second.begin(), pspec.common.begin(),
154 		                   pspec.common.end());
155 	}
156 
157 	return pspec;
158 fail:
159 	cerr << "invalid profile specification ";
160 	copy(non_options.begin(), non_options.end(),
161 	     ostream_iterator<string>(cerr, " "));
162 	cerr << endl;
163 	exit(EXIT_FAILURE);
164 }
165 
166 
get_options(int argc,char const * argv[])167 options::spec get_options(int argc, char const * argv[])
168 {
169 	vector<string> non_options;
170 	popt::parse_options(argc, argv, non_options);
171 
172 	// initialize paths in op_config.h
173 	init_op_config_dirs(options::session_dir.c_str());
174 
175 	if (!options::threshold_opt.empty())
176 		options::threshold = handle_threshold(options::threshold_opt);
177 
178 	if (!verbose::setup(verbose_strings)) {
179 		cerr << "unknown --verbose= options\n";
180 		exit(EXIT_FAILURE);
181 	}
182 
183 	// XML generator needs command line options for its header
184 	ostringstream str;
185 	for (int i = 1; i < argc; ++i)
186 		str << argv[i] << " ";
187 	options::command_options = str.str();
188 
189 	return parse_spec(non_options);
190 }
191 
192 }  // anon namespace
193 
194 
run_pp_tool(int argc,char const * argv[],pp_fct_run_t fct)195 int run_pp_tool(int argc, char const * argv[], pp_fct_run_t fct)
196 {
197 	try {
198 		return fct(get_options(argc, argv));
199 	}
200 	catch (op_runtime_error const & e) {
201 		cerr << argv[0] << " error: " << e.what() << endl;
202 	}
203 	catch (op_fatal_error const & e) {
204 		cerr << argv[0] << " error: " << e.what() << endl;
205 	}
206 	catch (op_exception const & e) {
207 		cerr << argv[0] << " error: " << e.what() << endl;
208 	}
209 	catch (invalid_argument const & e) {
210 		cerr << argv[0] << " error: " << e.what() << endl;
211 	}
212 	catch (exception const & e) {
213 		cerr << argv[0] << " error: " << e.what() << endl;
214 	}
215 	catch (...) {
216 		cerr << argv[0] << " unknown exception" << endl;
217 	}
218 
219 	return EXIT_FAILURE;
220 }
221 
222 
handle_demangle_option(string const & option)223 demangle_type handle_demangle_option(string const & option)
224 {
225 	if (option == "none")
226 		return dmt_none;
227 	if (option == "smart")
228 		return dmt_smart;
229 	if (option == "normal")
230 		return dmt_normal;
231 
232 	throw op_runtime_error("invalid option --demangle=" + option);
233 }
234 
235 
handle_merge_option(vector<string> const & mergespec,bool allow_lib,bool exclude_dependent)236 merge_option handle_merge_option(vector<string> const & mergespec,
237     bool allow_lib, bool exclude_dependent)
238 {
239 	using namespace options;
240 	merge_option merge_by;
241 
242 	merge_by.cpu = false;
243 	merge_by.lib = false;
244 	merge_by.tid = false;
245 	merge_by.tgid = false;
246 	merge_by.unitmask = false;
247 
248 	if (!allow_lib)
249 		merge_by.lib = true;
250 
251 	bool is_all = false;
252 
253 	vector<string>::const_iterator cit = mergespec.begin();
254 	vector<string>::const_iterator end = mergespec.end();
255 
256 	for (; cit != end; ++cit) {
257 		if (*cit == "cpu") {
258 			merge_by.cpu = true;
259 		} else if (*cit == "tid") {
260 			merge_by.tid = true;
261 		} else if (*cit == "tgid") {
262 			// PP:5.21 tgid merge imply tid merging.
263 			merge_by.tgid = true;
264 			merge_by.tid = true;
265 		} else if ((*cit == "lib" || *cit == "library") && allow_lib) {
266 			merge_by.lib = true;
267 		} else if (*cit == "unitmask") {
268 			merge_by.unitmask = true;
269 		} else if (*cit == "all") {
270 			merge_by.cpu = true;
271 			merge_by.lib = true;
272 			merge_by.tid = true;
273 			merge_by.tgid = true;
274 			merge_by.unitmask = true;
275 			is_all = true;
276 		} else {
277 			cerr << "unknown merge option: " << *cit << endl;
278 			exit(EXIT_FAILURE);
279 		}
280 	}
281 
282 	// if --merge all, don't warn about lib merging,
283 	// it's not user friendly. Behaviour should still
284 	// be correct.
285 	if (exclude_dependent && merge_by.lib && allow_lib && !is_all) {
286 		cerr << "--merge=lib is meaningless "
287 		     << "with --exclude-dependent" << endl;
288 		exit(EXIT_FAILURE);
289 	}
290 
291 	return merge_by;
292 }
293