oprofile 0.9.6
Copy in the rest of the oprofile 0.9.6 tree so we have a source
copy to match the prebuilt binaries that are checked into
external/.
Change-Id: Iaac327571d5d583594a4194973bf256569061048
diff --git a/pp/opreport_options.cpp b/pp/opreport_options.cpp
new file mode 100644
index 0000000..95d219c
--- /dev/null
+++ b/pp/opreport_options.cpp
@@ -0,0 +1,335 @@
+/**
+ * @file opreport_options.cpp
+ * Options for opreport tool
+ *
+ * @remark Copyright 2003 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ * @author Philippe Elie
+ */
+
+#include <vector>
+#include <list>
+#include <iostream>
+#include <algorithm>
+#include <iterator>
+#include <fstream>
+
+#include "profile_spec.h"
+#include "arrange_profiles.h"
+#include "opreport_options.h"
+#include "popt_options.h"
+#include "string_filter.h"
+#include "file_manip.h"
+#include "xml_output.h"
+#include "xml_utils.h"
+#include "cverb.h"
+
+using namespace std;
+
+profile_classes classes;
+profile_classes classes2;
+
+namespace options {
+ demangle_type demangle = dmt_normal;
+ bool symbols;
+ bool callgraph;
+ bool debug_info;
+ bool details;
+ bool exclude_dependent;
+ string_filter symbol_filter;
+ sort_options sort_by;
+ merge_option merge_by;
+ bool show_header = true;
+ bool long_filenames;
+ bool show_address;
+ bool accumulated;
+ bool reverse_sort;
+ bool global_percent;
+ bool xml;
+ string xml_options;
+}
+
+
+namespace {
+
+string outfile;
+vector<string> mergespec;
+vector<string> sort;
+vector<string> exclude_symbols;
+vector<string> include_symbols;
+string demangle_option = "normal";
+
+popt::option options_array[] = {
+ popt::option(options::callgraph, "callgraph", 'c',
+ "show call graph"),
+ popt::option(options::details, "details", 'd',
+ "output detailed samples for each symbol"),
+ popt::option(options::symbols, "symbols", 'l',
+ "list all symbols"),
+
+ popt::option(outfile, "output-file", 'o',
+ "output to the given filename", "file"),
+
+ popt::option(sort, "sort", 's',
+ "sort by", "sample,image,app-name,symbol,debug,vma"),
+ popt::option(options::reverse_sort, "reverse-sort", 'r',
+ "use reverse sort"),
+ popt::option(mergespec, "merge", 'm',
+ "comma separated list", "cpu,lib,tid,tgid,unitmask,all"),
+ popt::option(options::exclude_dependent, "exclude-dependent", 'x',
+ "exclude libs, kernel, and module samples for applications"),
+ popt::option(exclude_symbols, "exclude-symbols", 'e',
+ "exclude these comma separated symbols", "symbols"),
+ popt::option(include_symbols, "include-symbols", 'i',
+ "include these comma separated symbols", "symbols"),
+ popt::option(options::threshold_opt, "threshold", 't',
+ "minimum percentage needed to produce output",
+ "percent"),
+
+ popt::option(demangle_option, "demangle", 'D',
+ "demangle GNU C++ symbol names (default normal)",
+ "none|normal|smart"),
+ // PP:5
+ popt::option(options::debug_info, "debug-info", 'g',
+ "add source file and line number to output"),
+ popt::option(options::show_header, "no-header", 'n',
+ "remove all headers from output"),
+ popt::option(options::show_address, "show-address", 'w',
+ "show VMA address of each symbol"),
+ popt::option(options::long_filenames, "long-filenames", 'f',
+ "show the full path of filenames"),
+ popt::option(options::accumulated, "accumulated", 'a',
+ "percentage field show accumulated count"),
+ popt::option(options::global_percent, "global-percent", '%',
+ "percentage are not relative to symbol count or image "
+ "count but total sample count"),
+
+ popt::option(options::xml, "xml", 'X',
+ "XML output"),
+
+};
+
+
+void handle_sort_option()
+{
+ if (options::xml && !sort.empty()) {
+ cerr << "warning: sort options ignored because they "
+ << "are incompatible with --xml" << endl;
+ // don't allow any other sorting, except the default below,
+ // to mess up symbol traversal for XML
+ sort.clear();
+ }
+
+ if (sort.empty() || options::xml) {
+ // PP:5.14 sort default to sample
+ if (options::xml) {
+ // implicitly sort by app-name,image so that in the
+ // symbol traversal all library module symbols are
+ // grouped together with their application
+ sort.push_back("app-name");
+ sort.push_back("image");
+ } else
+ sort.push_back("sample");
+ }
+
+ vector<string>::const_iterator cit = sort.begin();
+ vector<string>::const_iterator end = sort.end();
+
+ for (; cit != end; ++cit)
+ options::sort_by.add_sort_option(*cit);
+}
+
+
+void handle_output_file()
+{
+ if (outfile.empty())
+ return;
+
+ static ofstream os(outfile.c_str());
+ if (!os) {
+ cerr << "Couldn't open \"" << outfile
+ << "\" for writing." << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ cout.rdbuf(os.rdbuf());
+}
+
+
+/// Check incompatible or meaningless options.
+void check_options(bool diff)
+{
+ using namespace options;
+
+ bool do_exit = false;
+
+ if (callgraph) {
+ symbols = true;
+ if (details) {
+ cerr << "--callgraph is incompatible with --details" << endl;
+ do_exit = true;
+ }
+
+ if (diff) {
+ cerr << "differential profiles are incompatible with --callgraph" << endl;
+ do_exit = true;
+ }
+ }
+
+ if (xml) {
+ if (accumulated) {
+ cerr << "--accumulated is incompatible with --xml" << endl;
+ do_exit = true;
+ }
+
+ if (global_percent) {
+ cerr << "--global_percent is incompatible with --xml" << endl;
+ do_exit = true;
+ }
+ }
+
+
+ if (details && diff) {
+ cerr << "differential profiles are incompatible with --details" << endl;
+ do_exit = true;
+ }
+
+ if (!symbols) {
+ if (diff) {
+ cerr << "different profiles are meaningless "
+ "without --symbols" << endl;
+ do_exit = true;
+ }
+
+ if (show_address) {
+ cerr << "--show-address is meaningless "
+ "without --symbols" << endl;
+ do_exit = true;
+ }
+
+ if (debug_info || accumulated) {
+ cerr << "--debug-info and --accumulated are "
+ << "meaningless without --symbols" << endl;
+ do_exit = true;
+ }
+
+ if (!exclude_symbols.empty() || !include_symbols.empty()) {
+ cerr << "--exclude-symbols and --include-symbols are "
+ << "meaningless without --symbols" << endl;
+ do_exit = true;
+ }
+
+ if (find(sort_by.options.begin(), sort_by.options.end(),
+ sort_options::vma) != sort_by.options.end()) {
+ cerr << "--sort=vma is "
+ << "meaningless without --symbols" << endl;
+ do_exit = true;
+ }
+ }
+
+ if (global_percent && symbols && !(details || callgraph)) {
+ cerr << "--global-percent is meaningless with --symbols "
+ "and without --details or --callgraph" << endl;
+ do_exit = true;
+ }
+
+ if (do_exit)
+ exit(EXIT_FAILURE);
+}
+
+
+/// process a spec into classes
+void process_spec(profile_classes & classes, list<string> const & spec)
+{
+ using namespace options;
+
+ copy(spec.begin(), spec.end(),
+ ostream_iterator<string>(cverb << vsfile, " "));
+ cverb << vsfile << "\n\n";
+
+ profile_spec const pspec =
+ profile_spec::create(spec, options::image_path,
+ options::root_path);
+
+ list<string> sample_files = pspec.generate_file_list(exclude_dependent,
+ !options::callgraph);
+
+ cverb << vsfile << "Archive: " << pspec.get_archive_path() << endl;
+
+ cverb << vsfile << "Matched sample files: " << sample_files.size()
+ << endl;
+ copy(sample_files.begin(), sample_files.end(),
+ ostream_iterator<string>(cverb << vsfile, "\n"));
+
+ classes = arrange_profiles(sample_files, merge_by,
+ pspec.extra_found_images);
+
+ cverb << vsfile << "profile_classes:\n" << classes << endl;
+
+ if (classes.v.empty()) {
+ cerr << "error: no sample files found: profile specification "
+ "too strict ?" << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+
+} // namespace anon
+
+
+void handle_options(options::spec const & spec)
+{
+ using namespace options;
+
+ if (details) {
+ symbols = true;
+ show_address = true;
+ }
+
+ if (options::xml) {
+ if (spec.common.size() != 0)
+ xml_utils::add_option(SESSION, spec.common);
+ if (debug_info)
+ xml_utils::add_option(DEBUG_INFO, true);
+ if (details)
+ xml_utils::add_option(DETAILS, true);
+ if (!image_path.empty())
+ xml_utils::add_option(IMAGE_PATH, image_path);
+ if (!mergespec.empty())
+ xml_utils::add_option(MERGE, mergespec);
+ if (exclude_dependent)
+ xml_utils::add_option(EXCLUDE_DEPENDENT, true);
+ if (!exclude_symbols.empty())
+ xml_utils::add_option(EXCLUDE_SYMBOLS, exclude_symbols);
+ if (!include_symbols.empty())
+ xml_utils::add_option(INCLUDE_SYMBOLS, include_symbols);
+ }
+
+ handle_sort_option();
+ merge_by = handle_merge_option(mergespec, true, exclude_dependent);
+ handle_output_file();
+ demangle = handle_demangle_option(demangle_option);
+ check_options(spec.first.size());
+
+ symbol_filter = string_filter(include_symbols, exclude_symbols);
+
+ if (!spec.first.size()) {
+ process_spec(classes, spec.common);
+ } else {
+ if (options::xml) {
+ cerr << "differential profiles are incompatible with --xml" << endl;
+ exit(EXIT_FAILURE);
+ }
+ cverb << vsfile << "profile spec 1:" << endl;
+ process_spec(classes, spec.first);
+ cverb << vsfile << "profile spec 2:" << endl;
+ process_spec(classes2, spec.second);
+
+ if (!classes.matches(classes2)) {
+ cerr << "profile classes are incompatible" << endl;
+ exit(EXIT_FAILURE);
+ }
+ }
+}