| /** |
| * @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; |
| } |
| |
| |