Home | History | Annotate | Download | only in libpp
      1 /**
      2  * @file arrange_profiles.h
      3  * Classify and process a list of candidate sample files
      4  * into merged sets and classes.
      5  *
      6  * @remark Copyright 2003 OProfile authors
      7  * @remark Read the file COPYING
      8  *
      9  * @author John Levon
     10  */
     11 
     12 #ifndef ARRANGE_PROFILES_H
     13 #define ARRANGE_PROFILES_H
     14 
     15 #include <string>
     16 #include <list>
     17 #include <vector>
     18 #include <iosfwd>
     19 
     20 #include "image_errors.h"
     21 #include "locate_images.h"
     22 
     23 /**
     24  * store merging options options used to classify profiles
     25  */
     26 struct merge_option {
     27 	bool cpu;
     28 	bool lib;
     29 	bool tid;
     30 	bool tgid;
     31 	bool unitmask;
     32 };
     33 
     34 
     35 /**
     36  * This describes which parameters are set for each
     37  * equivalence class.
     38  */
     39 struct profile_template {
     40 	std::string event;
     41 	std::string count;
     42 	std::string unitmask;
     43 	std::string tgid;
     44 	std::string tid;
     45 	std::string cpu;
     46 };
     47 
     48 
     49 /**
     50  * A samples filename + its associated callgraph sample filename.
     51  */
     52 struct profile_sample_files {
     53 	/**
     54 	 * This member can be empty since it is possible to get callgraph
     55 	 * w/o any samples to the binary. e.g an application which defer all
     56 	 * works to shared library but if arrange_profiles receive a sample
     57 	 * file list filtered from cg file sample_filename can't be empty
     58 	 */
     59 	std::string sample_filename;
     60 	/**
     61 	 * List of callgraph sample filename. If the {dep} part of
     62 	 * cg_filename != {cg} part it's a cross binary samples file.
     63 	 */
     64 	std::list<std::string> cg_files;
     65 };
     66 
     67 
     68 /**
     69  * A number of profiles files that are all dependent on
     70  * the same main (application) profile, for the same
     71  * dependent image.
     72  */
     73 struct profile_dep_set {
     74 	/// which dependent image is this set for
     75 	std::string lib_image;
     76 
     77 	/// the actual sample files optionnaly including callgraph sample files
     78 	std::list<profile_sample_files> files;
     79 };
     80 
     81 /**
     82  * A number of profile files all for the same binary with the same
     83  * profile specification (after merging). Includes the set of dependent
     84  * profile files, if any.
     85  *
     86  * For example, we could have image == "/bin/bash", where files
     87  * contains all profiles against /bin/bash, and deps contains
     88  * the sample file list for /lib/libc.so, /lib/ld.so etc.
     89  */
     90 struct profile_set {
     91 	std::string image;
     92 
     93 	/// the actual sample files for the main image and the asociated
     94 	/// callgraph files
     95 	std::list<profile_sample_files> files;
     96 
     97 	/// all profile files dependent on the main image
     98 	std::list<profile_dep_set> deps;
     99 };
    100 
    101 
    102 /**
    103  * A class collection of profiles. This is an equivalence class and
    104  * will correspond to columnar output of opreport.
    105  */
    106 struct profile_class {
    107 	std::list<profile_set> profiles;
    108 
    109 	/// human-readable column name
    110 	std::string name;
    111 
    112 	/// human-readable long name
    113 	std::string longname;
    114 
    115 	/// merging matches against this
    116 	profile_template ptemplate;
    117 };
    118 
    119 
    120 /**
    121  * The "axis" says what we've used to split the sample
    122  * files into the classes. Only one is allowed.
    123  */
    124 enum axis_types {
    125 	AXIS_EVENT,
    126 	AXIS_TGID,
    127 	AXIS_TID,
    128 	AXIS_CPU,
    129 	AXIS_MAX
    130 };
    131 
    132 
    133 struct profile_classes {
    134 	/**
    135 	 * This is only set if we're not classifying on event/count
    136 	 * anyway - if we're classifying on event/count, then we'll
    137 	 * already output the details of each class's event/count.
    138 	 *
    139 	 * It's only used when classifying by CPU, tgid etc. so the
    140 	 * user can still see what perfctr event was used.
    141 	 */
    142 	std::string event;
    143 
    144 	/// CPU info
    145 	std::string cpuinfo;
    146 
    147 	/// the actual classes
    148 	std::vector<profile_class> v;
    149 
    150 	/// the axis of the classes
    151 	axis_types axis;
    152 
    153 	/// the extra images to consider for this profile_classes
    154 	extra_images extra_found_images;
    155 
    156 	/// is this class set comparable with another?
    157 	bool matches(profile_classes const & classes);
    158 };
    159 
    160 
    161 std::ostream & operator<<(std::ostream &, profile_sample_files const &);
    162 std::ostream & operator<<(std::ostream &, profile_dep_set const &);
    163 std::ostream & operator<<(std::ostream &, profile_set const &);
    164 std::ostream & operator<<(std::ostream &, profile_template const &);
    165 std::ostream & operator<<(std::ostream &, profile_class const &);
    166 std::ostream & operator<<(std::ostream &, profile_classes const &);
    167 
    168 
    169 /**
    170  * Take a list of sample filenames, and process them into a set of
    171  * classes containing profile_sets. Merging is done at this stage
    172  * as well as attaching dependent profiles to the main image.
    173  *
    174  * The classes correspond to the columns you'll get in opreport:
    175  * this can be a number of events, or different CPUs, etc.
    176  */
    177 profile_classes const
    178 arrange_profiles(std::list<std::string> const & files,
    179 		 merge_option const & merge_by, extra_images const & extra);
    180 
    181 
    182 /**
    183  * A set of sample files where the image binary to open
    184  * are all the same.
    185  */
    186 struct image_set {
    187 	/// this is main app image, *not* necessarily
    188 	/// the one we need to open
    189 	std::string app_image;
    190 
    191 	/// the sample files
    192 	std::list<profile_sample_files> files;
    193 };
    194 
    195 typedef std::list<image_set> image_group_set;
    196 
    197 /**
    198  * All sample files where the binary image to open is
    199  * the same.
    200  *
    201  * This is the "inverse" to some degree of profile_set.
    202  * For example, here we might have image = "/lib/libc.so",
    203  * with groups being the profile classifications
    204  * tgid:404, tgid:301, etc.
    205  *
    206  * Within each group there's a number of image_sets.
    207  * All the sample files listed within the image_sets
    208  * are still for /lib/libc.so, but they may have
    209  * different app_image values, e.g. /bin/bash.
    210  * We need to keep track of the app_image values to
    211  * make opreport give the right info in the "app"
    212  * column.
    213  */
    214 struct inverted_profile {
    215 	inverted_profile() : error(image_ok) {}
    216 	/// the image to open
    217 	std::string image;
    218 
    219 	/// an error found in reading the image
    220 	mutable image_error error;
    221 
    222 	/// all sample files with data for the above image
    223 	std::vector<image_group_set> groups;
    224 };
    225 
    226 
    227 /**
    228  * Invert the profile set. For opreport -l, opannotate etc.,
    229  * processing the profile_classes directly is slow, because
    230  * we end up opening BFDs multiple times (for each class,
    231  * dependent images etc.). This function returns an inverted
    232  * set of sample files, where the primary sort is on the binary
    233  * image to open.
    234  *
    235  * Thus each element in the returned list is for exactly one
    236  * binary file that we're going to bfd_openr(). Attached to that
    237  * is the actual sample files we need to process for that binary
    238  * file. In order to get the output right, these have to be
    239  * marked with the profile class they're from (hence the groups
    240  * vector), and the app image that owned the sample file, if
    241  * applicable (hence image_set).
    242  */
    243 std::list<inverted_profile> const
    244 invert_profiles(profile_classes const & classes);
    245 
    246 #endif /* !ARRANGE_PROFILES_H */
    247