Imported Upstream version 1.0.0
[platform/upstream/oprofile.git] / pp / opannotate_options.cpp
1 /**
2  * @file opannotate_options.cpp
3  * Options for opannotate 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 "op_config.h"
21 #include "profile_spec.h"
22 #include "arrange_profiles.h"
23 #include "op_exception.h"
24 #include "opannotate_options.h"
25 #include "popt_options.h"
26 #include "cverb.h"
27
28 using namespace std;
29
30 profile_classes classes;
31
32 namespace options {
33         demangle_type demangle = dmt_normal;
34         string output_dir;
35         vector<string> search_dirs;
36         vector<string> base_dirs;
37         merge_option merge_by;
38         path_filter file_filter;
39         string_filter symbol_filter;
40         bool source;
41         bool assembly;
42         vector<string> objdump_params;
43         bool exclude_dependent;
44 }
45
46
47 namespace {
48
49 string include_symbols;
50 string exclude_symbols;
51 string include_file;
52 string exclude_file;
53 string demangle_option = "normal";
54 vector<string> mergespec;
55
56 popt::option options_array[] = {
57         popt::option(demangle_option, "demangle", 'D',
58                      "demangle GNU C++ symbol names (default normal)",
59                      "none|normal|smart"),
60         popt::option(options::output_dir, "output-dir", 'o',
61                      "output directory", "directory name"),
62         popt::option(options::search_dirs, "search-dirs", 'd',
63                      "directories to look for source files", "comma-separated paths"),
64         popt::option(options::base_dirs, "base-dirs", 'b',
65                      "source file prefixes to strip", "comma-separated paths"),
66         popt::option(include_file, "include-file", '\0',
67                      "include these comma separated filename", "filenames"),
68         popt::option(exclude_file, "exclude-file", '\0',
69                      "exclude these comma separated filename", "filenames"),
70         popt::option(include_symbols, "include-symbols", 'i',
71                      "include these comma separated symbols", "symbols"),
72         popt::option(exclude_symbols, "exclude-symbols", 'e',
73                      "exclude these comma separated symbols", "symbols"),
74         popt::option(options::objdump_params, "objdump-params", '\0',
75                      "additional params to pass to objdump", "parameters"),
76         popt::option(options::exclude_dependent, "exclude-dependent", 'x',
77                      "exclude libs, kernel, and module samples for applications"),
78         popt::option(mergespec, "merge", 'm',
79                      "comma separated list", "cpu,tid,tgid,unitmask,all"),
80         popt::option(options::source, "source", 's', "output source"),
81         popt::option(options::assembly, "assembly", 'a', "output assembly"),
82         popt::option(options::threshold_opt, "threshold", 't',
83                      "minimum percentage needed to produce output",
84                      "percent"),
85 };
86
87 }  // anonymous namespace
88
89
90 void handle_options(options::spec const & spec)
91 {
92         using namespace options;
93         vector<string> tmp_objdump_parms;
94
95         /* When passing a quoted string of options from opannotate for the
96          * objdump command, objdump_parms consists of a single string.  Need
97          * to break the string into a series of individual options otherwise
98          * the call to exec_comand fails when it sees the space between the
99          * options.
100          */
101         for (unsigned int i = 0; i < objdump_params.size(); i++) {
102                 string s;
103                 s = objdump_params[i];
104                 stringstream ss(s);
105                 istream_iterator<string> begin(ss);
106                 istream_iterator<string> end;
107                 vector<string> vstrings(begin, end);
108
109                 for (unsigned int j = 0; j < vstrings.size(); j++)
110                         tmp_objdump_parms.push_back(vstrings[j]);
111         }
112
113         // update objdump_parms.
114         objdump_params.assign(tmp_objdump_parms.begin(), tmp_objdump_parms.end());
115
116         if (spec.first.size()) {
117                 cerr << "differential profiles not allowed" << endl;
118                 exit(EXIT_FAILURE);
119         }
120
121         if (!assembly && !source) {
122                 cerr << "you must specify at least --source or --assembly\n";
123                 exit(EXIT_FAILURE);
124         }
125
126         if (!objdump_params.empty() && !assembly) {
127                 cerr << "--objdump-params is meaningless without --assembly\n";
128                 exit(EXIT_FAILURE);
129         }
130
131         if (search_dirs.empty() && !base_dirs.empty()) {
132                 cerr << "--base-dirs is useless unless you specify an "
133                         "alternative source location with --search-dirs"
134                      << endl;
135                 exit(EXIT_FAILURE);
136         }
137
138         if (assembly && !output_dir.empty()) {
139                 cerr << "--output-dir is meaningless with --assembly" << endl;
140                 exit(EXIT_FAILURE);
141         }
142
143         if (assembly && (!include_file.empty() || !exclude_file.empty())) {
144                 cerr << "--exclude[include]-file options not supported with --assembly" << endl;
145                 cerr << "Please see the opannotate man page." << endl;
146                 exit(EXIT_FAILURE);
147         }
148
149         options::symbol_filter = string_filter(include_symbols, exclude_symbols);
150
151         options::file_filter = path_filter(include_file, exclude_file);
152
153         profile_spec const pspec =
154                 profile_spec::create(spec.common, options::image_path,
155                                      options::root_path);
156
157         if (!was_session_dir_supplied())
158                 cerr << "Using " << op_samples_dir << " for session-dir" << endl;
159
160         list<string> sample_files = pspec.generate_file_list(exclude_dependent, true);
161
162         cverb << vsfile << "Archive: " << pspec.get_archive_path() << endl;
163
164         cverb << vsfile << "Matched sample files: " << sample_files.size()
165               << endl;
166         copy(sample_files.begin(), sample_files.end(),
167              ostream_iterator<string>(cverb << vsfile, "\n"));
168
169         demangle = handle_demangle_option(demangle_option);
170
171         // we always merge but this have no effect on output since at source
172         // or assembly point of view the result will be merged anyway
173         merge_by = handle_merge_option(mergespec, false, exclude_dependent);
174
175         classes = arrange_profiles(sample_files, merge_by,
176                                    pspec.extra_found_images);
177
178         cverb << vsfile << "profile_classes:\n" << classes << endl;
179
180         if (classes.v.empty()) {
181                 cerr << "error: no sample files found: profile specification "
182                      "too strict ?" << endl;
183                 exit(EXIT_FAILURE);
184         }
185 }