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