191 lines
4.3 KiB
C++
191 lines
4.3 KiB
C++
/**
|
|
* @file symbol_sort.cpp
|
|
* Sorting symbols
|
|
*
|
|
* @remark Copyright 2002, 2003 OProfile authors
|
|
* @remark Read the file COPYING
|
|
*
|
|
* @author Philippe Elie
|
|
* @author John Levon
|
|
*/
|
|
|
|
#include "symbol_sort.h"
|
|
#include "symbol_functors.h"
|
|
|
|
#include "name_storage.h"
|
|
#include "op_exception.h"
|
|
|
|
#include <algorithm>
|
|
#include <sstream>
|
|
|
|
using namespace std;
|
|
|
|
namespace {
|
|
|
|
bool long_filenames;
|
|
|
|
int image_compare(image_name_id l, image_name_id r)
|
|
{
|
|
if (long_filenames)
|
|
return image_names.name(l).compare(image_names.name(r));
|
|
return image_names.basename(l).compare(image_names.basename(r));
|
|
}
|
|
|
|
|
|
int debug_compare(debug_name_id l, debug_name_id r)
|
|
{
|
|
if (long_filenames)
|
|
return debug_names.name(l).compare(debug_names.name(r));
|
|
return debug_names.basename(l).compare(debug_names.basename(r));
|
|
}
|
|
|
|
|
|
int compare_by(sort_options::sort_order order,
|
|
symbol_entry const & lhs, symbol_entry const & rhs)
|
|
{
|
|
switch (order) {
|
|
case sort_options::sample:
|
|
if (lhs.sample.counts[0] < rhs.sample.counts[0])
|
|
return 1;
|
|
if (lhs.sample.counts[0] > rhs.sample.counts[0])
|
|
return -1;
|
|
return 0;
|
|
|
|
case sort_options::symbol:
|
|
return symbol_names.demangle(lhs.name).compare(
|
|
symbol_names.demangle(rhs.name));
|
|
|
|
case sort_options::image:
|
|
return image_compare(lhs.image_name, rhs.image_name);
|
|
|
|
case sort_options::app_name:
|
|
return image_compare(lhs.app_name, rhs.app_name);
|
|
|
|
case sort_options::vma:
|
|
if (lhs.sample.vma < rhs.sample.vma)
|
|
return -1;
|
|
if (lhs.sample.vma > rhs.sample.vma)
|
|
return 1;
|
|
return 0;
|
|
|
|
case sort_options::debug: {
|
|
file_location const & f1 = lhs.sample.file_loc;
|
|
file_location const & f2 = rhs.sample.file_loc;
|
|
int ret = debug_compare(f1.filename, f2.filename);
|
|
if (ret == 0)
|
|
ret = f1.linenr - f2.linenr;
|
|
return ret;
|
|
}
|
|
|
|
default: {
|
|
// static_cast<> to shut up g++ 2.91.66 which warn
|
|
// about ambiguity between <<(int) and <<(long int)
|
|
ostringstream os;
|
|
os << "compare_by(): unknown sort option: "
|
|
<< static_cast<int>(order) << endl;
|
|
throw op_fatal_error(os.str());
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
struct symbol_compare {
|
|
symbol_compare(vector<sort_options::sort_order> const & order,
|
|
bool reverse)
|
|
: compare_order(order), reverse_sort(reverse) {}
|
|
|
|
bool operator()(symbol_entry const * lhs,
|
|
symbol_entry const * rhs) const {
|
|
return operator()(*lhs, *rhs);
|
|
}
|
|
|
|
bool operator()(symbol_entry const & lhs,
|
|
symbol_entry const & rhs) const;
|
|
|
|
protected:
|
|
vector<sort_options::sort_order> const & compare_order;
|
|
bool reverse_sort;
|
|
};
|
|
|
|
|
|
bool symbol_compare::operator()(symbol_entry const & lhs,
|
|
symbol_entry const & rhs) const
|
|
{
|
|
for (size_t i = 0; i < compare_order.size(); ++i) {
|
|
int ret = compare_by(compare_order[i], lhs, rhs);
|
|
|
|
if (reverse_sort)
|
|
ret = -ret;
|
|
if (ret != 0)
|
|
return ret < 0;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
void sort_options::
|
|
sort(symbol_collection & syms, bool reverse_sort, bool lf) const
|
|
{
|
|
long_filenames = lf;
|
|
|
|
vector<sort_order> sort_option(options);
|
|
for (sort_order cur = first; cur != last; cur = sort_order(cur + 1)) {
|
|
if (find(sort_option.begin(), sort_option.end(), cur) ==
|
|
sort_option.end())
|
|
sort_option.push_back(cur);
|
|
}
|
|
|
|
stable_sort(syms.begin(), syms.end(),
|
|
symbol_compare(sort_option, reverse_sort));
|
|
}
|
|
|
|
|
|
void sort_options::
|
|
sort(diff_collection & syms, bool reverse_sort, bool lf) const
|
|
{
|
|
long_filenames = lf;
|
|
|
|
vector<sort_order> sort_option(options);
|
|
for (sort_order cur = first; cur != last; cur = sort_order(cur + 1)) {
|
|
if (find(sort_option.begin(), sort_option.end(), cur) ==
|
|
sort_option.end())
|
|
sort_option.push_back(cur);
|
|
}
|
|
|
|
stable_sort(syms.begin(), syms.end(),
|
|
symbol_compare(sort_option, reverse_sort));
|
|
}
|
|
|
|
|
|
void sort_options::add_sort_option(string const & name)
|
|
{
|
|
if (name == "vma") {
|
|
options.push_back(vma);
|
|
} else if (name == "sample") {
|
|
options.push_back(sample);
|
|
} else if (name == "symbol") {
|
|
options.push_back(symbol);
|
|
} else if (name == "debug") {
|
|
options.push_back(debug);
|
|
} else if (name == "image") {
|
|
options.push_back(image);
|
|
} else if (name == "app-name") {
|
|
options.push_back(app_name);
|
|
} else {
|
|
ostringstream os;
|
|
os << "unknown sort option: " << name << endl;
|
|
throw op_fatal_error(os.str());
|
|
}
|
|
}
|
|
|
|
|
|
void sort_options::add_sort_option(sort_options::sort_order order)
|
|
{
|
|
options.push_back(order);
|
|
}
|