Home | History | Annotate | Download | only in libpp
      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 
    167