opreport_options.cpp

Go to the documentation of this file.
00001 
00012 #include <vector>
00013 #include <list>
00014 #include <iostream>
00015 #include <algorithm>
00016 #include <iterator>
00017 #include <fstream>
00018 
00019 #include "op_config.h"
00020 #include "profile_spec.h"
00021 #include "arrange_profiles.h"
00022 #include "opreport_options.h"
00023 #include "popt_options.h"
00024 #include "string_filter.h"
00025 #include "file_manip.h"
00026 #include "xml_output.h"
00027 #include "xml_utils.h"
00028 #include "cverb.h"
00029 
00030 using namespace std;
00031 
00032 profile_classes classes;
00033 profile_classes classes2;
00034 
00035 namespace options {
00036     demangle_type demangle = dmt_normal;
00037     bool symbols;
00038     bool callgraph;
00039     bool debug_info;
00040     bool details;
00041     bool exclude_dependent;
00042     string_filter symbol_filter;
00043     sort_options sort_by;
00044     merge_option merge_by;
00045     bool show_header = true;
00046     bool long_filenames;
00047     bool show_address;
00048     bool accumulated;
00049     bool reverse_sort;
00050     bool global_percent;
00051     bool xml;
00052     string xml_options;
00053 }
00054 
00055 
00056 namespace {
00057 
00058 string outfile;
00059 vector<string> mergespec;
00060 vector<string> sort;
00061 vector<string> exclude_symbols;
00062 vector<string> include_symbols;
00063 string demangle_option = "normal";
00064 
00065 popt::option options_array[] = {
00066     popt::option(options::callgraph, "callgraph", 'c',
00067                  "show call graph"),
00068     popt::option(options::details, "details", 'd',
00069              "output detailed samples for each symbol"),
00070     popt::option(options::symbols, "symbols", 'l',
00071              "list all symbols"),
00072 
00073     popt::option(outfile, "output-file", 'o',
00074                  "output to the given filename", "file"),
00075 
00076     popt::option(sort, "sort", 's',
00077              "sort by", "sample,image,app-name,symbol,debug,vma"),
00078     popt::option(options::reverse_sort, "reverse-sort", 'r',
00079              "use reverse sort"),
00080     popt::option(mergespec, "merge", 'm',
00081              "comma separated list", "cpu,lib,tid,tgid,unitmask,all"),
00082     popt::option(options::exclude_dependent, "exclude-dependent", 'x',
00083              "exclude libs, kernel, and module samples for applications"),
00084     popt::option(exclude_symbols, "exclude-symbols", 'e',
00085              "exclude these comma separated symbols", "symbols"),
00086     popt::option(include_symbols, "include-symbols", 'i',
00087              "include these comma separated symbols", "symbols"),
00088     popt::option(options::threshold_opt, "threshold", 't',
00089              "minimum percentage needed to produce output",
00090              "percent"),
00091 
00092     popt::option(demangle_option, "demangle", 'D',
00093              "demangle GNU C++ symbol names (default normal)",
00094                  "none|normal|smart"),
00095     // PP:5
00096     popt::option(options::debug_info, "debug-info", 'g',
00097              "add source file and line number to output"),
00098     popt::option(options::show_header, "no-header", 'n',
00099              "remove all headers from output"),
00100     popt::option(options::show_address, "show-address", 'w',
00101                  "show VMA address of each symbol"),
00102     popt::option(options::long_filenames, "long-filenames", 'f',
00103              "show the full path of filenames"),
00104     popt::option(options::accumulated, "accumulated", 'a',
00105              "percentage field show accumulated count"),
00106     popt::option(options::global_percent, "global-percent", '%',
00107              "percentage are not relative to symbol count or image "
00108              "count but total sample count"),
00109 
00110     popt::option(options::xml, "xml", 'X',
00111              "XML output"),
00112 
00113 };
00114 
00115 
00116 void handle_sort_option()
00117 {
00118     if (options::xml && !sort.empty()) {
00119         cerr << "warning: sort options ignored because they "
00120              << "are incompatible with --xml" << endl;
00121         // don't allow any other sorting, except the default below,
00122         // to mess up symbol traversal for XML
00123         sort.clear();
00124     }
00125 
00126     if (sort.empty() || options::xml) {
00127         // PP:5.14 sort default to sample
00128         if (options::xml) {
00129             // implicitly sort by app-name,image so that in the
00130             // symbol traversal all library module symbols are
00131             // grouped together with their application
00132             sort.push_back("app-name");
00133             sort.push_back("image");
00134         } else
00135             sort.push_back("sample");
00136     }
00137 
00138     vector<string>::const_iterator cit = sort.begin();
00139     vector<string>::const_iterator end = sort.end();
00140 
00141     for (; cit != end; ++cit)
00142         options::sort_by.add_sort_option(*cit);
00143 }
00144 
00145 
00146 void handle_output_file()
00147 {
00148     if (outfile.empty())
00149         return;
00150 
00151     static ofstream os(outfile.c_str());
00152     if (!os) {
00153         cerr << "Couldn't open \"" << outfile
00154              << "\" for writing." << endl;
00155         exit(EXIT_FAILURE);
00156     }
00157 
00158     cout.rdbuf(os.rdbuf());
00159 }
00160 
00161 
00163 void check_options(bool diff)
00164 {
00165     using namespace options;
00166 
00167     bool do_exit = false;
00168 
00169     if (callgraph) {
00170         symbols = true;
00171         if (details) {
00172             cerr << "--callgraph is incompatible with --details" << endl;
00173             do_exit = true;
00174         }
00175 
00176         if (diff) {
00177             cerr << "differential profiles are incompatible with --callgraph" << endl;
00178             do_exit = true;
00179         }
00180     }
00181 
00182     if (xml) {
00183         if (accumulated) {
00184             cerr << "--accumulated is incompatible with --xml" << endl;
00185             do_exit = true;
00186         }
00187 
00188         if (global_percent) {
00189             cerr << "--global_percent is incompatible with --xml" << endl;
00190             do_exit = true;
00191         }
00192     }
00193 
00194 
00195     if (details && diff) {
00196         cerr << "differential profiles are incompatible with --details" << endl;
00197         do_exit = true;
00198     }
00199 
00200     if (!symbols) {
00201         if (diff) {
00202             cerr << "different profiles are meaningless "
00203                 "without --symbols" << endl;
00204             do_exit = true;
00205         }
00206 
00207         if (show_address) {
00208             cerr << "--show-address is meaningless "
00209                 "without --symbols" << endl;
00210             do_exit = true;
00211         }
00212 
00213         if (debug_info || accumulated) {
00214             cerr << "--debug-info and --accumulated are "
00215                  << "meaningless without --symbols" << endl;
00216             do_exit = true;
00217         }
00218 
00219         if (!exclude_symbols.empty() || !include_symbols.empty()) {
00220             cerr << "--exclude-symbols and --include-symbols are "
00221                  << "meaningless without --symbols" << endl;
00222             do_exit = true;
00223         }
00224 
00225         if (find(sort_by.options.begin(), sort_by.options.end(), 
00226              sort_options::vma) != sort_by.options.end()) {
00227             cerr << "--sort=vma is "
00228                  << "meaningless without --symbols" << endl;
00229             do_exit = true;
00230         }
00231     }
00232 
00233     if (global_percent && symbols && !(details || callgraph)) {
00234         cerr << "--global-percent is meaningless with --symbols "
00235                 "and without --details or --callgraph" << endl;
00236         do_exit = true;
00237     }
00238 
00239     if (do_exit)
00240         exit(EXIT_FAILURE);
00241 }
00242 
00243 
00245 void process_spec(profile_classes & classes, list<string> const & spec)
00246 {
00247     using namespace options;
00248 
00249     copy(spec.begin(), spec.end(),
00250          ostream_iterator<string>(cverb << vsfile, " "));
00251     cverb << vsfile << "\n\n";
00252 
00253     profile_spec const pspec =
00254         profile_spec::create(spec, options::image_path,
00255                      options::root_path);
00256 
00257     if (!was_session_dir_supplied())
00258         cerr << "Using " << op_samples_dir << " for samples directory." << endl;
00259 
00260     list<string> sample_files = pspec.generate_file_list(exclude_dependent,
00261                                                 !options::callgraph);
00262 
00263     cverb << vsfile << "Archive: " << pspec.get_archive_path() << endl;
00264 
00265     cverb << vsfile << "Matched sample files: " << sample_files.size()
00266           << endl;
00267     copy(sample_files.begin(), sample_files.end(),
00268          ostream_iterator<string>(cverb << vsfile, "\n"));
00269 
00270     classes = arrange_profiles(sample_files, merge_by,
00271                    pspec.extra_found_images);
00272 
00273     cverb << vsfile << "profile_classes:\n" << classes << endl;
00274 
00275     if (classes.v.empty()) {
00276         cerr << "error: no sample files found: profile specification "
00277              "too strict ?" << endl;
00278         exit(EXIT_FAILURE);
00279     }
00280 }
00281 
00282 
00283 } // namespace anon
00284 
00285 
00286 void handle_options(options::spec const & spec)
00287 {
00288     using namespace options;
00289 
00290     if (details) {
00291         symbols = true;
00292         show_address = true;
00293     }
00294 
00295     if (options::xml) {
00296         if (spec.common.size() != 0)
00297             xml_utils::add_option(SESSION, spec.common);
00298         if (debug_info)
00299             xml_utils::add_option(DEBUG_INFO, true);
00300         if (details)
00301             xml_utils::add_option(DETAILS, true);
00302         if (!image_path.empty())
00303             xml_utils::add_option(IMAGE_PATH, image_path);
00304         if (!mergespec.empty())
00305             xml_utils::add_option(MERGE, mergespec);
00306         if (exclude_dependent)
00307             xml_utils::add_option(EXCLUDE_DEPENDENT, true);
00308         if (!exclude_symbols.empty())
00309             xml_utils::add_option(EXCLUDE_SYMBOLS, exclude_symbols);
00310         if (!include_symbols.empty())
00311             xml_utils::add_option(INCLUDE_SYMBOLS, include_symbols);
00312     }
00313 
00314     handle_sort_option();
00315     merge_by = handle_merge_option(mergespec, true, exclude_dependent);
00316     handle_output_file();
00317     demangle = handle_demangle_option(demangle_option);
00318     check_options(spec.first.size());
00319 
00320     symbol_filter = string_filter(include_symbols, exclude_symbols);
00321 
00322     if (!spec.first.size()) {
00323         process_spec(classes, spec.common);
00324     } else {
00325         if (options::xml) {
00326             cerr << "differential profiles are incompatible with --xml" << endl;
00327             exit(EXIT_FAILURE);
00328         }
00329         cverb << vsfile << "profile spec 1:" << endl;
00330         process_spec(classes, spec.first);
00331         cverb << vsfile << "profile spec 2:" << endl;
00332         process_spec(classes2, spec.second);
00333 
00334         if (!classes.matches(classes2)) {
00335             cerr << "profile classes are incompatible" << endl;
00336             exit(EXIT_FAILURE);
00337         }
00338     }
00339 }

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1