Update of /cvsroot/oprofile/oprofile/libpp In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17795/libpp Modified Files: callgraph_container.cpp image_errors.cpp op_header.cpp parse_filename.cpp populate.cpp profile.cpp profile.h profile_spec.cpp Log Message: merge anon mapping support Index: callgraph_container.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/libpp/callgraph_container.cpp,v retrieving revision 1.32 retrieving revision 1.33 diff -u -p -d -r1.32 -r1.33 --- callgraph_container.cpp 7 Apr 2005 00:05:23 -0000 1.32 +++ callgraph_container.cpp 2 May 2005 15:07:02 -0000 1.33 @@ -41,12 +41,26 @@ bool operator==(cg_symbol const & lhs, c } +// we store {caller,callee} inside a single u64 +odb_key_t caller_to_key(u32 value) +{ + return odb_key_t(value) << 32; +} + + +u32 key_to_callee(odb_key_t key) +{ + return key & 0xffffffff; +} + + bool compare_by_callee_vma(pair<odb_key_t, odb_value_t> const & lhs, pair<odb_key_t, odb_value_t> const & rhs) { - return (lhs.first & 0xffffffff) < (rhs.first & 0xffffffff); + return (key_to_callee(lhs.first)) < (key_to_callee(rhs.first)); } + /* * We need 2 comparators for callgraph to get the desired output: * @@ -71,6 +85,196 @@ compare_arc_count_reverse(symbol_entry c } +// find the nearest bfd symbol for the given file offset and check it's +// in range +op_bfd_symbol const * +get_symbol_by_filepos(op_bfd const & bfd, u32 bfd_offset, + vma_t offset, symbol_index_t & i) +{ + offset += bfd_offset; + op_bfd_symbol tmpsym(offset, 0, string()); + + // sorted by filepos so this will find the nearest + vector<op_bfd_symbol>::const_iterator it = + upper_bound(bfd.syms.begin(), bfd.syms.end(), tmpsym); + + if (it != bfd.syms.begin()) + --it; + + if (it == bfd.syms.end()) { + cerr << "get_symbol_by_filepos: no symbols at all?" << endl; + abort(); + } + + // if the offset is past the end of the symbol, we didn't find one + u32 const end_offset = it->size() + it->filepos(); + + if (offset >= end_offset) { + // let's be verbose for now + cerr << "warning: dropping hyperspace sample at offset " + << hex << offset << " >= " << end_offset + << " for binary " << bfd.get_filename() << dec << endl; + return NULL; + } + + i = distance(bfd.syms.begin(), it); + return &(*it); +} + + +/// temporary caller and callee data held during processing +class call_data { +public: + call_data(profile_container const & p, profile_t const & pr, + op_bfd const & bfd, u32 boff, image_name_id iid, + image_name_id aid, bool debug_info) + : pc(p), profile(pr), b(bfd), boffset(boff), image(iid), + app(aid), debug(debug_info) {} + + /// point to a caller symbol + void caller_sym(symbol_index_t i) { + sym = symbol_entry(); + + unsigned long start; + unsigned long end; + b.get_symbol_range(i, start, end); + + profile_t::iterator_pair p_it = profile.samples_range( + caller_to_key(start - boffset), + caller_to_key(end - boffset)); + + // Our odb_key_t contain (from_eip << 32 | to_eip), the range + // of key we selected above contain one caller but different + // callee and due to the ordering callee offsets are not + // consecutive so we must sort them first. + + samples.clear(); + + for (; p_it.first != p_it.second; ++p_it.first) { + samples.push_back(make_pair(p_it.first.vma(), + p_it.first.count())); + } + + sort(samples.begin(), samples.end(), compare_by_callee_vma); + + sym.size = end - start; + sym.name = symbol_names.create(b.syms[i].name()); + sym.sample.vma = b.sym_offset(i, start) + b.syms[i].vma(); + + finish_sym(i, start); + + if (cverb << vdebug) { + cverb << vdebug << hex << "Caller sym: " + << b.syms[i].name() << " filepos " << start + << "-" << end << dec << endl; + } + } + + /// point to a callee symbol + bool callee_sym(u32 off) { + sym = symbol_entry(); + + symbol_index_t i; + op_bfd_symbol const * bfdsym = + get_symbol_by_filepos(b, boffset, off, i); + + if (!bfdsym) + return false; + + callee_end = bfdsym->size() + bfdsym->filepos() - boffset; + + sym.size = bfdsym->size(); + sym.name = symbol_names.create(bfdsym->name()); + sym.sample.vma = bfdsym->vma(); + + finish_sym(i, bfdsym->filepos()); + + if (cverb << vdebug) { + cverb << vdebug << hex << "Callee sym: " + << bfdsym->name() << " filepos " + << bfdsym->filepos() << "-" + << (bfdsym->filepos() + bfdsym->size()) + << dec << endl; + } + return true; + } + + void verbose_bfd(string const & prefix) const { + cverb << vdebug << prefix << " " << b.get_filename() + << " offset " << boffset << " app " + << image_names.name(app) << endl; + } + + typedef vector<pair<odb_key_t, odb_value_t> > samples_t; + + typedef samples_t::const_iterator const_iterator; + + samples_t samples; + symbol_entry sym; + u32 callee_end; + +private: + /// fill in the rest of the sym + void finish_sym(symbol_index_t i, unsigned long start) { + sym.image_name = image; + sym.app_name = app; + symbol_entry const * self = pc.find(sym); + if (self) + sym.sample.counts = self->sample.counts; + + if (debug) { + string filename; + file_location & loc = sym.sample.file_loc; + if (b.get_linenr(i, start, filename, loc.linenr)) + loc.filename = debug_names.create(filename); + } + } + + profile_container const & pc; + profile_t const & profile; + op_bfd const & b; + u32 boffset; + image_name_id image; + image_name_id app; + bool debug; +}; + + +/// accumulate all samples for a given caller/callee pair +u32 +accumulate_callee(call_data::const_iterator & it, call_data::const_iterator end, + u32 callee_end) +{ + u32 count = 0; + call_data::const_iterator const start = it; + + while (it != end) { + u32 offset = key_to_callee(it->first); + + if (cverb << (vdebug & vlevel1)) { + cverb << (vdebug & vlevel1) << hex << "offset: " + << offset << dec << endl; + } + + // stop if we pass the end of the callee + if (offset >= callee_end) + break; + + count += it->second; + ++it; + } + + // If we haven't advanced at all, then we'll get + // an infinite loop, so we must abort. + if (it == start) { + cerr << "failure to advance iterator\n"; + abort(); + } + + return count; +} + + } // anonymous namespace @@ -253,9 +457,6 @@ void callgraph_container::populate(strin report_image_error(archive_path + caller_file.lib_image, error, false); - cverb << vdebug << "caller binary name: " - << caller_binary << "\n"; - bool caller_bfd_ok = true; op_bfd caller_bfd(archive_path, caller_binary, string_filter(), caller_bfd_ok); @@ -271,9 +472,6 @@ void callgraph_container::populate(strin if (error != image_ok) report_image_error(callee_file.cg_image, error, false); - cverb << vdebug << "cg binary callee name: " - << callee_binary << endl; - bool callee_bfd_ok = true; op_bfd callee_bfd(archive_path, callee_binary, string_filter(), callee_bfd_ok); @@ -284,7 +482,7 @@ void callgraph_container::populate(strin profile_t profile; // We can't use start_offset support in profile_t, give // it a zero offset and we will fix that in add() - profile.add_sample_file(*it, 0); + profile.add_sample_file(*it); add(profile, caller_bfd, caller_bfd_ok, callee_bfd, merge_lib ? app_image : app_name, pc, debug_info, pclass); @@ -299,176 +497,65 @@ add(profile_t const & profile, op_bfd co { string const image_name = caller_bfd.get_filename(); + opd_header const & header = profile.get_header(); + + // We can't use kernel sample file w/o the binary else we will + // use it with a zero offset, the code below will abort because + // we will get incorrect callee sub-range and out of range + // callee vma. FIXME + if (header.is_kernel && !caller_bfd_ok) + return; + // We must handle start_offset, this offset can be different for the // caller and the callee: kernel sample traversing the syscall barrier. - u32 caller_start_offset = 0; - if (profile.get_header().is_kernel) { - // We can't use kernel sample file w/o the binary else we will - // use it with a zero offset, the code below will abort because - // we will get incorrect callee sub-range and out of range - // callee vma. FIXME - if (!caller_bfd_ok) { - // We already warned. - return; - } - caller_start_offset = caller_bfd.get_start_offset(); + u32 caller_offset = 0; + + if (header.is_kernel || header.anon_start) { + caller_offset = caller_bfd.get_start_offset(header.anon_start); } u32 callee_offset = 0; - if (profile.get_header().cg_to_is_kernel) - callee_offset = callee_bfd.get_start_offset(); - cverb << vdebug << hex - << "caller_bfd_start_offset: " << caller_start_offset << endl - << "callee_bfd_start_offset: " << callee_offset << dec << endl; + if (header.cg_to_is_kernel || header.cg_to_anon_start) { + callee_offset = + callee_bfd.get_start_offset(header.cg_to_anon_start); + } image_name_id image_id = image_names.create(image_name); image_name_id callee_image_id = image_names.create(callee_bfd.get_filename()); image_name_id app_id = image_names.create(app_name); - for (symbol_index_t i = 0; i < caller_bfd.syms.size(); ++i) { - unsigned long start, end; - caller_bfd.get_symbol_range(i, start, end); - - profile_t::iterator_pair p_it = profile.samples_range( - odb_key_t(start - caller_start_offset) << 32, - odb_key_t(end - caller_start_offset) << 32); - - symbol_entry caller; - - caller.size = end - start; - caller.name = symbol_names.create(caller_bfd.syms[i].name()); - caller.image_name = image_id; - caller.app_name = app_id; - caller.sample.vma = caller_bfd.sym_offset(i, start) + - caller_bfd.syms[i].vma(); - - symbol_entry const * self = pc.find(caller); - if (self) - caller.sample.counts = self->sample.counts; - - if (debug_info) { - string filename; - if (caller_bfd.get_linenr(i, start, filename, - caller.sample.file_loc.linenr)) { - caller.sample.file_loc.filename = - debug_names.create(filename); - } - } - - // Our odb_key_t contain (from_eip << 32 | to_eip), the range - // of key we selected above contain one caller but different - // callee and due to the ordering callee offsets are not - // consecutive so we must sort them first. - - typedef vector<pair<odb_key_t, odb_value_t> > data_t; - data_t data; - - for (; p_it.first != p_it.second; ++p_it.first) { - data.push_back(make_pair(p_it.first.vma(), - p_it.first.count())); - } + call_data caller(pc, profile, caller_bfd, caller_offset, image_id, + app_id, debug_info); + call_data callee(pc, profile, callee_bfd, callee_offset, + callee_image_id, app_id, debug_info); - sort(data.begin(), data.end(), compare_by_callee_vma); - - data_t::const_iterator dit; - data_t::const_iterator dend = data.end(); - for (dit = data.begin(); dit != dend; ) { - // find the callee. - data_t::const_iterator it = dit; - bfd_vma callee_vma = (it->first & 0xffffffff) + - callee_offset; + if (cverb << vdebug) { + caller.verbose_bfd("Caller:"); + callee.verbose_bfd("Callee:"); + } - cverb << vdebug - << "offset caller: " << hex - << (it->first >> 32) << " callee: " - << callee_vma << dec << endl; + // For each symbol in the caller bfd, process all arcs to + // callee bfd symbols - op_bfd_symbol symb(callee_vma, 0, string()); + for (symbol_index_t i = 0; i < caller_bfd.syms.size(); ++i) { - vector<op_bfd_symbol>::const_iterator bfd_symb_callee = - upper_bound(callee_bfd.syms.begin(), - callee_bfd.syms.end(), symb); + caller.caller_sym(i); - if (bfd_symb_callee == callee_bfd.syms.end()) - cverb << vdebug << "reaching end of symbol\n"; - // ugly but upper_bound() work in this way. - if (bfd_symb_callee != callee_bfd.syms.begin()) - --bfd_symb_callee; - if (bfd_symb_callee == callee_bfd.syms.end()) { - // FIXME: not clear if we need to abort, - // recover or an exception, for now I need a - // a core dump - cerr << "Unable to retrieve callee symbol\n"; - abort(); + call_data::const_iterator dit = caller.samples.begin(); + call_data::const_iterator dend = caller.samples.end(); + while (dit != dend) { + // if we can't find the callee, skip an arc + if (!callee.callee_sym(key_to_callee(dit->first))) { + ++dit; + continue; } - symbol_entry callee; - - callee.size = bfd_symb_callee->size(); - callee.name = - symbol_names.create(bfd_symb_callee->name()); - callee.image_name = callee_image_id; - callee.app_name = app_id; - callee.sample.vma = bfd_symb_callee->vma(); - - self = pc.find(callee); - if (self) - callee.sample.counts = self->sample.counts; - - u32 upper_bound = bfd_symb_callee->size() + - bfd_symb_callee->filepos() - callee_offset; - cverb << vdebug - << "upper bound: " << hex << upper_bound - << dec << endl; - - data_t::const_iterator dcur = it; - - // Process all arc from this caller to this callee - count_array_t arc_count; + arc_count[pclass] = + accumulate_callee(dit, dend, callee.callee_end); - for (; it != dend && - (it->first & 0xffffffff) < upper_bound; - ++it) { - cverb << (vdebug & vlevel1) << hex - << "offset: " << (it->first & 0xffffffff) - << dec << endl; - arc_count[pclass] += it->second; - } - // FIXME: very fragile, any inaccuracy in caller offset - // can lead to an abort! - if (it == dcur) { - // This is impossible, we need a core dump else - // we enter in an infinite loop - cerr << "failure to advance iterator\n"; - abort(); - } - - cverb << vdebug - << caller_bfd.syms[i].name() << " " - << bfd_symb_callee->name() << " " - << arc_count[pclass] << endl; - - if (debug_info) { - symbol_index_t index = - distance(callee_bfd.syms.begin(), - bfd_symb_callee); - unsigned long start, end; - callee_bfd.get_symbol_range(index, start, end); - - string filename; - if (callee_bfd.get_linenr(index, start, filename, - callee.sample.file_loc.linenr)) { - callee.sample.file_loc.filename = - debug_names.create(filename); - } - } - - recorder.add(caller, &callee, arc_count); - - // next callee symbol - dit = it; + recorder.add(caller.sym, &callee.sym, arc_count); } } } Index: image_errors.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/libpp/image_errors.cpp,v retrieving revision 1.4 retrieving revision 1.5 diff -u -p -d -r1.4 -r1.5 --- image_errors.cpp 28 Jan 2004 15:28:34 -0000 1.4 +++ image_errors.cpp 2 May 2005 15:07:02 -0000 1.5 @@ -11,6 +11,7 @@ #include "image_errors.h" #include "arrange_profiles.h" +#include "string_manip.h" #include <iostream> #include <set> @@ -31,6 +32,10 @@ void report_image_error(string const & i if (reported_images_error.find(image) == reported_images_error.end()) { reported_images_error.insert(image); + // FIXME: hacky + if (error == image_not_found && is_prefix(image, "anon ")) + return; + cerr << (fatal ? "error: " : "warning: "); cerr << image << ' '; Index: op_header.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/libpp/op_header.cpp,v retrieving revision 1.20 retrieving revision 1.21 diff -u -p -d -r1.20 -r1.21 --- op_header.cpp 29 May 2004 16:29:42 -0000 1.20 +++ op_header.cpp 2 May 2005 15:07:02 -0000 1.21 @@ -43,6 +43,13 @@ void op_check_header(opd_header const & throw op_fatal_error(os.str()); } + if (h1.anon_start != h2.anon_start) { + ostringstream os; + os << "header anon_start flags are different for " + << filename << "\n"; + throw op_fatal_error(os.str()); + } + // Note that we don't check CPU speed since that can vary // freely on the same machine } Index: parse_filename.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/libpp/parse_filename.cpp,v retrieving revision 1.7 retrieving revision 1.8 diff -u -p -d -r1.7 -r1.8 --- parse_filename.cpp 25 Jan 2004 01:53:55 -0000 1.7 +++ parse_filename.cpp 2 May 2005 15:07:02 -0000 1.8 @@ -14,6 +14,7 @@ #include <iostream> #include "parse_filename.h" +#include "file_manip.h" #include "string_manip.h" using namespace std; @@ -57,29 +58,45 @@ parsed_filename parse_event_spec(string /** * @param component path component * - * remove from path_component all directory left to {root} or {kern} + * remove from path_component all directory left to {root}, {kern} or {anon} */ void remove_base_dir(vector<string> & path) { vector<string>::iterator it; for (it = path.begin(); it != path.end(); ++it) { - if (*it == "{root}" || *it == "{kern}") + if (*it == "{root}" || *it == "{kern}" || *it == "{anon}") break; } path.erase(path.begin(), it); } + +/// Handle an anon region. Pretty print the details. +string const parse_anon(string const & str) +{ + vector<string> parts = separate_token(str, '.'); + if (parts.size() != 3) + throw invalid_argument("parse_anon() invalid name: " + str); + + string ret = "anon (tgid:"; + ret += parts[0] + " range:" + parts[1] + "-" + parts[2] + ")"; + return ret; +} + + } // anonymous namespace /* - * valid filename are: + * valid filename are variations on: * * {kern}/name/event_spec - * {root}/path/to/bin/event_spec * {root}/path/to/bin/{dep}/{root}/path/to/bin/event_spec + * {root}/path/to/bin/{dep}/{anon}/pid.start.end/event_spec * {root}/path/to/bin/{dep}/{kern}/name/event_spec + * {root}/path/to/bin/{dep}/{root}/path/to/bin/{cg}/{root}/path/to/bin/event_spec + * * where /name/ denote a unique path component */ @@ -125,35 +142,48 @@ parsed_filename parse_filename(string co // skip "{dep}" ++i; - // PP:3.19 {dep}/ must be followed by {kern}/ or {root}/ - if (path[i] != "{kern}" && path[i] != "{root}") { + // PP:3.19 {dep}/ must be followed by {kern}/, {root}/ or {anon}/ + if (path[i] != "{kern}" && path[i] != "{root}" && path[i] != "{anon}") { throw invalid_argument("parse_filename() invalid filename: " + filename); } - // skip "{root}" or "{kern}" + bool anon = path[i] == "{anon}"; + + // skip "{root}", "{kern}" or "{anon}" ++i; for (; i < path.size(); ++i) { if (path[i] == "{cg}") break; + + if (anon) { + result.lib_image = parse_anon(path[i++]); + break; + } result.lib_image += "/" + path[i]; } - if (i != path.size()) { - // skip "{cg}" - ++i; - if (i == path.size() || - (path[i] != "{kern}" && path[i] != "{root}")) { - throw invalid_argument( - "parse_filename() invalid filename: " + - filename); - } - // skip "{root}" or "{kern}" - ++i; + if (i == path.size()) + return result; + + // skip "{cg}" + ++i; + if (i == path.size() || + (path[i] != "{kern}" && path[i] != "{root}" && path[i] != "{anon}")) { + throw invalid_argument("parse_filename() invalid filename: " + + filename); } - for (; i < path.size(); ++i) { - result.cg_image += "/" + path[i]; + + // skip "{root}", "{kern}" or "{anon}" + anon = path[i] == "{anon}"; + ++i; + + if (anon) { + result.cg_image = parse_anon(path[i++]); + } else { + for (; i < path.size(); ++i) + result.cg_image += "/" + path[i]; } return result; Index: populate.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/libpp/populate.cpp,v retrieving revision 1.6 retrieving revision 1.7 diff -u -p -d -r1.6 -r1.7 --- populate.cpp 24 Apr 2005 02:36:53 -0000 1.6 +++ populate.cpp 2 May 2005 15:07:03 -0000 1.7 @@ -18,14 +18,16 @@ #include "image_errors.h" +#include <iostream> + using namespace std; namespace { /// load merged files for one set of sample files bool -populate_from_files(profile_t & profile, - list<profile_sample_files> const & files, u32 offset) +populate_from_files(profile_t & profile, op_bfd const & abfd, + list<profile_sample_files> const & files) { list<profile_sample_files>::const_iterator it = files.begin(); list<profile_sample_files>::const_iterator const end = files.end(); @@ -37,7 +39,8 @@ populate_from_files(profile_t & profile, // since we can create a profile_sample_files for cg file only // (i.e no sample to the binary) if (!it->sample_filename.empty()) { - profile.add_sample_file(it->sample_filename, offset); + profile.add_sample_file(it->sample_filename); + profile.set_offset(abfd); found = true; } } @@ -62,8 +65,6 @@ populate_for_image(string const & archiv if (ip.error == image_format_failure) report_image_error(ip, false); - u32 offset = abfd.get_start_offset(); - opd_header header; bool found = false; @@ -79,7 +80,7 @@ populate_for_image(string const & archiv // to the wrong app_image otherwise for (; it != end; ++it) { profile_t profile; - if (populate_from_files(profile, it->files, offset)) { + if (populate_from_files(profile, abfd, it->files)) { header = profile.get_header(); samples.add(profile, abfd, it->app_image, i); found = true; Index: profile.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/libpp/profile.cpp,v retrieving revision 1.21 retrieving revision 1.22 diff -u -p -d -r1.21 -r1.22 --- profile.cpp 29 May 2004 16:29:42 -0000 1.21 +++ profile.cpp 2 May 2005 15:07:03 -0000 1.22 @@ -22,8 +22,9 @@ #include "op_header.h" #include "op_config.h" #include "op_sample_file.h" - #include "profile.h" +#include "op_bfd.h" +#include "cverb.h" using namespace std; @@ -75,7 +76,7 @@ void profile_t::open_sample_file(string } } -void profile_t::add_sample_file(string const & filename, u32 offset) +void profile_t::add_sample_file(string const & filename) { odb_t samples_db; @@ -85,9 +86,8 @@ void profile_t::add_sample_file(string c *static_cast<opd_header *>(odb_get_data(&samples_db)); // if we already read a sample file header pointer is non null - if (file_header.get()) { + if (file_header.get()) op_check_header(head, *file_header, filename); - } file_header.reset(new opd_header(head)); @@ -109,11 +109,15 @@ void profile_t::add_sample_file(string c } odb_close(&samples_db); +} - if (!get_header().is_kernel) - return; - start_offset = offset; +void profile_t::set_offset(op_bfd const & abfd) +{ + opd_header const & header = get_header(); + if (header.anon_start || header.is_kernel) + start_offset = abfd.get_start_offset(header.anon_start); + cverb << (vdebug) << "start_offset is now " << start_offset << endl; } Index: profile.h =================================================================== RCS file: /cvsroot/oprofile/oprofile/libpp/profile.h,v retrieving revision 1.16 retrieving revision 1.17 diff -u -p -d -r1.16 -r1.17 --- profile.h 29 May 2004 16:29:42 -0000 1.16 +++ profile.h 2 May 2005 15:07:03 -0000 1.17 @@ -22,6 +22,7 @@ #include "utility.h" class opd_header; +class op_bfd; /** * Class containing a single sample file contents. @@ -56,13 +57,15 @@ public: /** * cumulate sample file to our container of samples * @param filename sample file name - * @param offset the offset for kernel files, \sa start_offset * * store samples for one sample file, sample file header is sanitized. * * all error are fatal */ - void add_sample_file(std::string const & filename, u32 offset); + void add_sample_file(std::string const & filename); + + /// Set an appropriate start offset, see comments below. + void set_offset(op_bfd const & abfd); class const_iterator; typedef std::pair<const_iterator, const_iterator> iterator_pair; @@ -100,14 +103,29 @@ private: ordered_samples_t ordered_samples; /** - * For the kernel and kernel modules, this value is non-zero and - * equal to the offset of the .text section. This is done because - * we use the information provided in /proc/ksyms, which only gives - * the mapped position of .text, and the symbol _text from - * vmlinux. This value is used to fix up the sample offsets - * for kernel code as a result of this difference (in user-space - * samples, the sample offset is from the start of the mapped - * file, as seen in /proc/pid/maps). + * For certain profiles, such as kernel/modules, and anon + * regions with a matching binary, this value is non-zero, + * and represents the file offset of the relevant section. + * + * For kernel profiles, this is done because we use the information + * provided in /proc/ksyms, which only gives the mapped position of + * .text, and the symbol _text from vmlinux. This value is used to fix + * up the sample offsets for kernel code as a result of this difference + * + * In user-space samples, the sample offset is from the start of the + * mapped file, as seen in /proc/pid/maps. This is fine for + * mappings of permanent files, but with anon mappings, we need + * to adjust the key values to be a file offset against the + * *binary* (if there is one). This can obviously be different. + * So we pass our anon mapping start VMA to op_bfd, which looks + * for a section with that VMA, then returns the section's + * filepos. So all is good. + * + * Finally, note that for cg we can't use this inside the + * profile_t, as we're storing two offsets in the key value. So + * we do it later in that case. + * + * Phew. */ u32 start_offset; }; @@ -122,8 +140,8 @@ namespace std { struct iterator_traits<profile_t::const_iterator> { typedef ptrdiff_t difference_type; typedef unsigned int value_type; - typedef unsigned int* pointer; - typedef unsigned int& reference; + typedef unsigned int * pointer; + typedef unsigned int & reference; typedef input_iterator_tag iterator_category; }; } Index: profile_spec.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/libpp/profile_spec.cpp,v retrieving revision 1.27 retrieving revision 1.28 diff -u -p -d -r1.27 -r1.28 --- profile_spec.cpp 12 Apr 2005 03:14:09 -0000 1.27 +++ profile_spec.cpp 2 May 2005 15:07:03 -0000 1.28 @@ -356,11 +356,18 @@ vector<string> filter_session(vector<str } -bool valid_candidate(string const & filename, profile_spec const & spec, - bool exclude_dependent, bool exclude_cg) +bool valid_candidate(string const & base_dir, string const & filename, + profile_spec const & spec, bool exclude_dependent, + bool exclude_cg) { if (exclude_cg && filename.find("{cg}") != string::npos) return false; + + // strip out non sample files + string const & sub = filename.substr(base_dir.size(), string::npos); + if (!is_prefix(sub, "/{root}/") && !is_prefix(sub, "/{kern}/")) + return false; + filename_spec file_spec(filename); if (spec.match(file_spec)) { if (exclude_dependent && file_spec.is_dependent()) @@ -419,8 +426,8 @@ list<string> profile_spec::generate_file list<string>::const_iterator it = files.begin(); list<string>::const_iterator fend = files.end(); for (; it != fend; ++it) { - if (valid_candidate(*it, *this, exclude_dependent, - exclude_cg)) { + if (valid_candidate(base_dir, *it, *this, + exclude_dependent, exclude_cg)) { unique_files.insert(*it); } } |