1 /** 2 * @file symbol_sort.cpp 3 * Sorting symbols 4 * 5 * @remark Copyright 2002, 2003 OProfile authors 6 * @remark Read the file COPYING 7 * 8 * @author Philippe Elie 9 * @author John Levon 10 */ 11 12 #include "symbol_sort.h" 13 #include "symbol_functors.h" 14 15 #include "name_storage.h" 16 #include "op_exception.h" 17 18 #include <algorithm> 19 #include <sstream> 20 21 using namespace std; 22 23 namespace { 24 25 bool long_filenames; 26 27 int image_compare(image_name_id l, image_name_id r) 28 { 29 if (long_filenames) 30 return image_names.name(l).compare(image_names.name(r)); 31 return image_names.basename(l).compare(image_names.basename(r)); 32 } 33 34 35 int debug_compare(debug_name_id l, debug_name_id r) 36 { 37 if (long_filenames) 38 return debug_names.name(l).compare(debug_names.name(r)); 39 return debug_names.basename(l).compare(debug_names.basename(r)); 40 } 41 42 43 int compare_by(sort_options::sort_order order, 44 symbol_entry const & lhs, symbol_entry const & rhs) 45 { 46 switch (order) { 47 case sort_options::sample: 48 if (lhs.sample.counts[0] < rhs.sample.counts[0]) 49 return 1; 50 if (lhs.sample.counts[0] > rhs.sample.counts[0]) 51 return -1; 52 return 0; 53 54 case sort_options::symbol: 55 return symbol_names.demangle(lhs.name).compare( 56 symbol_names.demangle(rhs.name)); 57 58 case sort_options::image: 59 return image_compare(lhs.image_name, rhs.image_name); 60 61 case sort_options::app_name: 62 return image_compare(lhs.app_name, rhs.app_name); 63 64 case sort_options::vma: 65 if (lhs.sample.vma < rhs.sample.vma) 66 return -1; 67 if (lhs.sample.vma > rhs.sample.vma) 68 return 1; 69 return 0; 70 71 case sort_options::debug: { 72 file_location const & f1 = lhs.sample.file_loc; 73 file_location const & f2 = rhs.sample.file_loc; 74 int ret = debug_compare(f1.filename, f2.filename); 75 if (ret == 0) 76 ret = f1.linenr - f2.linenr; 77 return ret; 78 } 79 80 default: { 81 // static_cast<> to shut up g++ 2.91.66 which warn 82 // about ambiguity between <<(int) and <<(long int) 83 ostringstream os; 84 os << "compare_by(): unknown sort option: " 85 << static_cast<int>(order) << endl; 86 throw op_fatal_error(os.str()); 87 } 88 } 89 90 return 0; 91 } 92 93 94 struct symbol_compare { 95 symbol_compare(vector<sort_options::sort_order> const & order, 96 bool reverse) 97 : compare_order(order), reverse_sort(reverse) {} 98 99 bool operator()(symbol_entry const * lhs, 100 symbol_entry const * rhs) const { 101 return operator()(*lhs, *rhs); 102 } 103 104 bool operator()(symbol_entry const & lhs, 105 symbol_entry const & rhs) const; 106 107 protected: 108 vector<sort_options::sort_order> const & compare_order; 109 bool reverse_sort; 110 }; 111 112 113 bool symbol_compare::operator()(symbol_entry const & lhs, 114 symbol_entry const & rhs) const 115 { 116 for (size_t i = 0; i < compare_order.size(); ++i) { 117 int ret = compare_by(compare_order[i], lhs, rhs); 118 119 if (reverse_sort) 120 ret = -ret; 121 if (ret != 0) 122 return ret < 0; 123 } 124 return false; 125 } 126 127 128 } // anonymous namespace 129 130 131 void sort_options:: 132 sort(symbol_collection & syms, bool reverse_sort, bool lf) const 133 { 134 long_filenames = lf; 135 136 vector<sort_order> sort_option(options); 137 for (sort_order cur = first; cur != last; cur = sort_order(cur + 1)) { 138 if (find(sort_option.begin(), sort_option.end(), cur) == 139 sort_option.end()) 140 sort_option.push_back(cur); 141 } 142 143 stable_sort(syms.begin(), syms.end(), 144 symbol_compare(sort_option, reverse_sort)); 145 } 146 147 148 void sort_options:: 149 sort(diff_collection & syms, bool reverse_sort, bool lf) const 150 { 151 long_filenames = lf; 152 153 vector<sort_order> sort_option(options); 154 for (sort_order cur = first; cur != last; cur = sort_order(cur + 1)) { 155 if (find(sort_option.begin(), sort_option.end(), cur) == 156 sort_option.end()) 157 sort_option.push_back(cur); 158 } 159 160 stable_sort(syms.begin(), syms.end(), 161 symbol_compare(sort_option, reverse_sort)); 162 } 163 164 165 void sort_options::add_sort_option(string const & name) 166 { 167 if (name == "vma") { 168 options.push_back(vma); 169 } else if (name == "sample") { 170 options.push_back(sample); 171 } else if (name == "symbol") { 172 options.push_back(symbol); 173 } else if (name == "debug") { 174 options.push_back(debug); 175 } else if (name == "image") { 176 options.push_back(image); 177 } else if (name == "app-name") { 178 options.push_back(app_name); 179 } else { 180 ostringstream os; 181 os << "unknown sort option: " << name << endl; 182 throw op_fatal_error(os.str()); 183 } 184 } 185 186 187 void sort_options::add_sort_option(sort_options::sort_order order) 188 { 189 options.push_back(order); 190 } 191