/** * @file libpp/populate_for_spu.cpp * Fill up a profile_container from inverted profiles for * a Cell BE SPU profile * * @remark Copyright 2007 OProfile authors * @remark Read the file COPYING * * @author Maynard Johnson * (C) Copyright IBM Corporation 2007 */ #include "profile.h" #include "profile_container.h" #include "arrange_profiles.h" #include "op_bfd.h" #include "op_header.h" #include "populate.h" #include "populate_for_spu.h" #include "image_errors.h" #include <iostream> using namespace std; namespace { static int spu_profile = unknown_profile; /* * On Cell Broadband Engine, an application executing on an SPE may * have been loaded from a separate SPU executable binary file or may * have been loaded from an embedded section of a PPE application or * shared library. In the embedded case, the embedding file may actually * contain multiple SPU images, resulting in different SPU images being loaded * onto different SPUs. Thus, the SPUs may be executing different code, even * though the application of the parent PPE process is the same. Therefore, * we must be sure to create a separate op_bfd object for each SPU. When doing * so below, we examine header.embedded_offset. If embedded_offset is > 0, it's * interpreted as the offset of an SPU image embedded in the containing file, * so the filename to do the check_mtime on is the containing file, ip.image; * otherwise, the filename to do the check_mtime on is the separate backing * file of the SPU image, abfd->filename. */ void populate_spu_profile_from_files(list<profile_sample_files> const & files, string const app_image, profile_container & samples, inverted_profile const & ip, string_filter const & symbol_filter, size_t ip_grp_num, bool * has_debug_info) { string archive_path = samples.extra_found_images.get_archive_path(); bool ok = ip.error == image_ok; op_bfd * abfd = NULL; string fname_to_check; list<profile_sample_files>::const_iterator it = files.begin(); list<profile_sample_files>::const_iterator const end = files.end(); for (; it != end; ++it) { profile_t profile; if (it->sample_filename.empty()) continue; profile.add_sample_file(it->sample_filename); opd_header header = profile.get_header(); if (header.embedded_offset) { abfd = new op_bfd(header.embedded_offset, ip.image, symbol_filter, samples.extra_found_images, ok); fname_to_check = ip.image; } else { abfd = new op_bfd(ip.image, symbol_filter, samples.extra_found_images, ok); fname_to_check = abfd->get_filename(); } profile.set_offset(*abfd); if (!ok && ip.error == image_ok) ip.error = image_format_failure; if (ip.error == image_format_failure) report_image_error(ip, false, samples.extra_found_images); samples.add(profile, *abfd, app_image, ip_grp_num); if (ip.error == image_ok) { image_error error; string filename = samples.extra_found_images.find_image_path( fname_to_check, error, true); check_mtime(filename, profile.get_header()); } if (has_debug_info && !*has_debug_info) *has_debug_info = abfd->has_debug_info(); delete abfd; } } } // anon namespace void populate_for_spu_image(profile_container & samples, inverted_profile const & ip, string_filter const & symbol_filter, bool * has_debug_info) { for (size_t i = 0; i < ip.groups.size(); ++i) { list < image_set >::const_iterator it= ip.groups[i].begin(); list < image_set >::const_iterator const end = ip.groups[i].end(); for (; it != end; ++it) populate_spu_profile_from_files(it->files, it->app_image, samples, ip, symbol_filter, i, has_debug_info); } } bool is_spu_profile(inverted_profile const & ip) { bool retval = false; string sfname = ""; if (spu_profile != unknown_profile) return spu_profile; if (!ip.groups.size()) return false; for (size_t i = 0; i < ip.groups.size(); ++i) { list<image_set>::const_iterator grp_it = ip.groups[i].begin(); list<image_set>::const_iterator const grp_end = ip.groups[i].end(); for (; grp_it != grp_end; ++grp_it) { list<profile_sample_files>::const_iterator sfiles_it = grp_it->files.begin(); list<profile_sample_files>::const_iterator sfiles_end = grp_it->files.end(); for (; sfiles_it != sfiles_end; ++sfiles_it) { if (!sfiles_it->sample_filename.empty()) { sfname = sfiles_it->sample_filename; goto do_check; } } } } goto out; do_check: spu_profile = profile_t::is_spu_sample_file(sfname); if (spu_profile == cell_spu_profile) retval = true; out: return retval; }