Mike Dodd | 8cfa702 | 2010-11-17 11:12:26 -0800 | [diff] [blame] | 1 | /** |
| 2 | * @file libpp/populate_for_spu.cpp |
| 3 | * Fill up a profile_container from inverted profiles for |
| 4 | * a Cell BE SPU profile |
| 5 | * |
| 6 | * @remark Copyright 2007 OProfile authors |
| 7 | * @remark Read the file COPYING |
| 8 | * |
| 9 | * @author Maynard Johnson |
| 10 | * (C) Copyright IBM Corporation 2007 |
| 11 | */ |
| 12 | |
| 13 | #include "profile.h" |
| 14 | #include "profile_container.h" |
| 15 | #include "arrange_profiles.h" |
| 16 | #include "op_bfd.h" |
| 17 | #include "op_header.h" |
| 18 | #include "populate.h" |
| 19 | #include "populate_for_spu.h" |
| 20 | |
| 21 | #include "image_errors.h" |
| 22 | |
| 23 | #include <iostream> |
| 24 | |
| 25 | using namespace std; |
| 26 | |
| 27 | namespace { |
| 28 | |
| 29 | static int spu_profile = unknown_profile; |
| 30 | |
| 31 | /* |
| 32 | * On Cell Broadband Engine, an application executing on an SPE may |
| 33 | * have been loaded from a separate SPU executable binary file or may |
| 34 | * have been loaded from an embedded section of a PPE application or |
| 35 | * shared library. In the embedded case, the embedding file may actually |
| 36 | * contain multiple SPU images, resulting in different SPU images being loaded |
| 37 | * onto different SPUs. Thus, the SPUs may be executing different code, even |
| 38 | * though the application of the parent PPE process is the same. Therefore, |
| 39 | * we must be sure to create a separate op_bfd object for each SPU. When doing |
| 40 | * so below, we examine header.embedded_offset. If embedded_offset is > 0, it's |
| 41 | * interpreted as the offset of an SPU image embedded in the containing file, |
| 42 | * so the filename to do the check_mtime on is the containing file, ip.image; |
| 43 | * otherwise, the filename to do the check_mtime on is the separate backing |
| 44 | * file of the SPU image, abfd->filename. |
| 45 | */ |
| 46 | void |
| 47 | populate_spu_profile_from_files(list<profile_sample_files> const & files, |
| 48 | string const app_image, |
| 49 | profile_container & samples, |
| 50 | inverted_profile const & ip, |
| 51 | string_filter const & symbol_filter, |
| 52 | size_t ip_grp_num, bool * has_debug_info) |
| 53 | { |
| 54 | string archive_path = samples.extra_found_images.get_archive_path(); |
| 55 | bool ok = ip.error == image_ok; |
| 56 | op_bfd * abfd = NULL; |
| 57 | string fname_to_check; |
| 58 | list<profile_sample_files>::const_iterator it = files.begin(); |
| 59 | list<profile_sample_files>::const_iterator const end = files.end(); |
| 60 | for (; it != end; ++it) { |
| 61 | profile_t profile; |
| 62 | if (it->sample_filename.empty()) |
| 63 | continue; |
| 64 | |
| 65 | profile.add_sample_file(it->sample_filename); |
| 66 | opd_header header = profile.get_header(); |
| 67 | if (header.embedded_offset) { |
| 68 | abfd = new op_bfd(header.embedded_offset, |
| 69 | ip.image, |
| 70 | symbol_filter, |
| 71 | samples.extra_found_images, |
| 72 | ok); |
| 73 | fname_to_check = ip.image; |
| 74 | } else { |
| 75 | abfd = new op_bfd(ip.image, |
| 76 | symbol_filter, |
| 77 | samples.extra_found_images, |
| 78 | ok); |
| 79 | fname_to_check = abfd->get_filename(); |
| 80 | } |
| 81 | profile.set_offset(*abfd); |
| 82 | if (!ok && ip.error == image_ok) |
| 83 | ip.error = image_format_failure; |
| 84 | |
| 85 | if (ip.error == image_format_failure) |
| 86 | report_image_error(ip, false, |
| 87 | samples.extra_found_images); |
| 88 | |
| 89 | samples.add(profile, *abfd, app_image, ip_grp_num); |
| 90 | if (ip.error == image_ok) { |
| 91 | image_error error; |
| 92 | string filename = |
| 93 | samples.extra_found_images.find_image_path( |
| 94 | fname_to_check, error, true); |
| 95 | check_mtime(filename, profile.get_header()); |
| 96 | } |
| 97 | |
| 98 | if (has_debug_info && !*has_debug_info) |
| 99 | *has_debug_info = abfd->has_debug_info(); |
| 100 | delete abfd; |
| 101 | } |
| 102 | } |
| 103 | } // anon namespace |
| 104 | |
| 105 | void |
| 106 | populate_for_spu_image(profile_container & samples, |
| 107 | inverted_profile const & ip, |
| 108 | string_filter const & symbol_filter, |
| 109 | bool * has_debug_info) |
| 110 | { |
| 111 | |
| 112 | for (size_t i = 0; i < ip.groups.size(); ++i) { |
| 113 | list < image_set >::const_iterator it= |
| 114 | ip.groups[i].begin(); |
| 115 | list < image_set >::const_iterator const end |
| 116 | = ip.groups[i].end(); |
| 117 | |
| 118 | for (; it != end; ++it) |
| 119 | populate_spu_profile_from_files(it->files, |
| 120 | it->app_image, samples, ip, |
| 121 | symbol_filter, i, has_debug_info); |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | bool is_spu_profile(inverted_profile const & ip) |
| 126 | { |
| 127 | bool retval = false; |
| 128 | string sfname = ""; |
| 129 | if (spu_profile != unknown_profile) |
| 130 | return spu_profile; |
| 131 | |
| 132 | if (!ip.groups.size()) |
| 133 | return false; |
| 134 | |
| 135 | for (size_t i = 0; i < ip.groups.size(); ++i) { |
| 136 | list<image_set>::const_iterator grp_it |
| 137 | = ip.groups[i].begin(); |
| 138 | list<image_set>::const_iterator const grp_end |
| 139 | = ip.groups[i].end(); |
| 140 | |
| 141 | for (; grp_it != grp_end; ++grp_it) { |
| 142 | list<profile_sample_files>::const_iterator sfiles_it = |
| 143 | grp_it->files.begin(); |
| 144 | list<profile_sample_files>::const_iterator sfiles_end = |
| 145 | grp_it->files.end(); |
| 146 | for (; sfiles_it != sfiles_end; ++sfiles_it) { |
| 147 | if (!sfiles_it->sample_filename.empty()) { |
| 148 | sfname = sfiles_it->sample_filename; |
| 149 | goto do_check; |
| 150 | } |
| 151 | } |
| 152 | } |
| 153 | } |
| 154 | goto out; |
| 155 | |
| 156 | do_check: |
| 157 | spu_profile = profile_t::is_spu_sample_file(sfname); |
| 158 | |
| 159 | if (spu_profile == cell_spu_profile) |
| 160 | retval = true; |
| 161 | |
| 162 | out: |
| 163 | return retval; |
| 164 | } |
| 165 | |
| 166 | |