/**
* @file daemon/opd_mangling.c
* Mangling and opening of sample files
*
* @remark Copyright 2002 OProfile authors
* @remark Read the file COPYING
*
* @author John Levon
* @author Philippe Elie
*/
#include <sys/types.h>
#include "opd_mangling.h"
#include "opd_kernel.h"
#include "opd_cookie.h"
#include "opd_sfile.h"
#include "opd_anon.h"
#include "opd_printf.h"
#include "opd_events.h"
#include "oprofiled.h"
#include "op_file.h"
#include "op_sample_file.h"
#include "op_config.h"
#include "op_mangle.h"
#include "op_events.h"
#include "op_libiberty.h"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
static char const * get_dep_name(struct sfile const * sf)
{
if (sf->anon)
return find_cookie(sf->app_cookie);
/* avoid to call find_cookie(), caller can recover using image_name */
if (sf->cookie == sf->app_cookie)
return NULL;
if (!separate_kernel && !(separate_lib && !sf->kernel))
return NULL;
/* this will fail if e.g. kernel thread */
if (sf->app_cookie == 0)
return NULL;
return find_cookie(sf->app_cookie);
}
static char * mangle_anon(struct anon_mapping const * anon)
{
char * name = xmalloc(PATH_MAX);
snprintf(name, 1024, "%u.0x%llx.0x%llx", (unsigned int)anon->tgid,
anon->start, anon->end);
return name;
}
static char *
mangle_filename(struct sfile * last, struct sfile const * sf, int counter, int cg)
{
char * mangled;
struct mangle_values values;
struct opd_event * event = find_counter_event(counter);
values.flags = 0;
if (sf->kernel) {
values.image_name = sf->kernel->name;
values.flags |= MANGLE_KERNEL;
} else if (sf->anon) {
values.flags |= MANGLE_ANON;
values.image_name = mangle_anon(sf->anon);
values.anon_name = sf->anon->name;
} else {
values.image_name = find_cookie(sf->cookie);
}
values.dep_name = get_dep_name(sf);
if (!values.dep_name)
values.dep_name = values.image_name;
/* FIXME: log */
if (!values.image_name || !values.dep_name)
return NULL;
if (separate_thread) {
values.flags |= MANGLE_TGID | MANGLE_TID;
values.tid = sf->tid;
values.tgid = sf->tgid;
}
if (separate_cpu) {
values.flags |= MANGLE_CPU;
values.cpu = sf->cpu;
}
if (cg) {
values.flags |= MANGLE_CALLGRAPH;
if (last->kernel) {
values.cg_image_name = last->kernel->name;
} else if (last->anon) {
values.flags |= MANGLE_CG_ANON;
values.cg_image_name = mangle_anon(last->anon);
values.anon_name = last->anon->name;
} else {
values.cg_image_name = find_cookie(last->cookie);
}
/* FIXME: log */
if (!values.cg_image_name) {
if (values.flags & MANGLE_ANON)
free((char *)values.image_name);
return NULL;
}
}
values.event_name = event->name;
values.count = event->count;
values.unit_mask = event->um;
mangled = op_mangle_filename(&values);
if (values.flags & MANGLE_ANON)
free((char *)values.image_name);
if (values.flags & MANGLE_CG_ANON)
free((char *)values.cg_image_name);
return mangled;
}
int opd_open_sample_file(odb_t *file, struct sfile *last,
struct sfile * sf, int counter, int cg)
{
char * mangled;
char const * binary;
int spu_profile = 0;
vma_t last_start = 0;
int err;
mangled = mangle_filename(last, sf, counter, cg);
if (!mangled)
return EINVAL;
verbprintf(vsfile, "Opening \"%s\"\n", mangled);
create_path(mangled);
/* locking sf will lock associated cg files too */
sfile_get(sf);
if (sf != last)
sfile_get(last);
retry:
err = odb_open(file, mangled, ODB_RDWR, sizeof(struct opd_header));
/* This can naturally happen when racing against opcontrol --reset. */
if (err) {
if (err == EMFILE) {
if (sfile_lru_clear()) {
printf("LRU cleared but odb_open() fails for %s.\n", mangled);
abort();
}
goto retry;
}
fprintf(stderr, "oprofiled: open of %s failed: %s\n",
mangled, strerror(err));
goto out;
}
if (!sf->kernel)
binary = find_cookie(sf->cookie);
else
binary = sf->kernel->name;
if (last && last->anon)
last_start = last->anon->start;
if (sf->embedded_offset != UNUSED_EMBEDDED_OFFSET)
spu_profile = 1;
fill_header(odb_get_data(file), counter,
sf->anon ? sf->anon->start : 0, last_start,
!!sf->kernel, last ? !!last->kernel : 0,
spu_profile, sf->embedded_offset,
binary ? op_get_mtime(binary) : 0);
out:
sfile_put(sf);
if (sf != last)
sfile_put(last);
free(mangled);
return err;
}