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

	// To silence Coverity
	values.anon_name = NULL;
	values.cg_image_name = NULL;
	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);

	err = create_path(mangled);
	if (err) {
		fprintf(stderr, "oprofiled: create path for %s failed: %s\n",
		        mangled, strerror(err));
		goto out;
	}

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