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 { inverted_profileinverted_profile215 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