Home | History | Annotate | Download | only in daemon
      1 /**
      2  * @file daemon/opd_mangling.c
      3  * Mangling and opening of sample files
      4  *
      5  * @remark Copyright 2002 OProfile authors
      6  * @remark Read the file COPYING
      7  *
      8  * @author John Levon
      9  * @author Philippe Elie
     10  */
     11 
     12 #include <sys/types.h>
     13 
     14 #include "opd_mangling.h"
     15 #include "opd_kernel.h"
     16 #include "opd_cookie.h"
     17 #include "opd_sfile.h"
     18 #include "opd_anon.h"
     19 #include "opd_printf.h"
     20 #include "opd_events.h"
     21 #include "oprofiled.h"
     22 
     23 #include "op_file.h"
     24 #include "op_sample_file.h"
     25 #include "op_config.h"
     26 #include "op_mangle.h"
     27 #include "op_events.h"
     28 #include "op_libiberty.h"
     29 
     30 #include <limits.h>
     31 #include <stdio.h>
     32 #include <stdlib.h>
     33 #include <string.h>
     34 #include <errno.h>
     35 
     36 
     37 static char const * get_dep_name(struct sfile const * sf)
     38 {
     39 	if (sf->anon)
     40 		return find_cookie(sf->app_cookie);
     41 
     42 	/* avoid to call find_cookie(), caller can recover using image_name */
     43 	if (sf->cookie == sf->app_cookie)
     44 		return NULL;
     45 
     46 	if (!separate_kernel && !(separate_lib && !sf->kernel))
     47 		return NULL;
     48 
     49 	/* this will fail if e.g. kernel thread */
     50 	if (sf->app_cookie == 0)
     51 		return NULL;
     52 
     53 	return find_cookie(sf->app_cookie);
     54 }
     55 
     56 
     57 static char * mangle_anon(struct anon_mapping const * anon)
     58 {
     59 	char * name = xmalloc(PATH_MAX);
     60 
     61 	snprintf(name, 1024, "%u.0x%llx.0x%llx", (unsigned int)anon->tgid,
     62 	       anon->start, anon->end);
     63 
     64 	return name;
     65 }
     66 
     67 
     68 static char *
     69 mangle_filename(struct sfile * last, struct sfile const * sf, int counter, int cg)
     70 {
     71 	char * mangled;
     72 	struct mangle_values values;
     73 	struct opd_event * event = find_counter_event(counter);
     74 
     75 	values.flags = 0;
     76 
     77 	if (sf->kernel) {
     78 		values.image_name = sf->kernel->name;
     79 		values.flags |= MANGLE_KERNEL;
     80 	} else if (sf->anon) {
     81 		values.flags |= MANGLE_ANON;
     82 		values.image_name = mangle_anon(sf->anon);
     83 		values.anon_name = sf->anon->name;
     84 	} else {
     85 		values.image_name = find_cookie(sf->cookie);
     86 	}
     87 
     88 	values.dep_name = get_dep_name(sf);
     89 	if (!values.dep_name)
     90 		values.dep_name = values.image_name;
     91 
     92 	/* FIXME: log */
     93 	if (!values.image_name || !values.dep_name)
     94 		return NULL;
     95 
     96 	if (separate_thread) {
     97 		values.flags |= MANGLE_TGID | MANGLE_TID;
     98 		values.tid = sf->tid;
     99 		values.tgid = sf->tgid;
    100 	}
    101 
    102 	if (separate_cpu) {
    103 		values.flags |= MANGLE_CPU;
    104 		values.cpu = sf->cpu;
    105 	}
    106 
    107 	if (cg) {
    108 		values.flags |= MANGLE_CALLGRAPH;
    109 		if (last->kernel) {
    110 			values.cg_image_name = last->kernel->name;
    111 		} else if (last->anon) {
    112 			values.flags |= MANGLE_CG_ANON;
    113 			values.cg_image_name = mangle_anon(last->anon);
    114 			values.anon_name = last->anon->name;
    115 		} else {
    116 			values.cg_image_name = find_cookie(last->cookie);
    117 		}
    118 
    119 		/* FIXME: log */
    120 		if (!values.cg_image_name) {
    121 			if (values.flags & MANGLE_ANON)
    122 				free((char *)values.image_name);
    123 			return NULL;
    124 		}
    125 	}
    126 
    127 	values.event_name = event->name;
    128 	values.count = event->count;
    129 	values.unit_mask = event->um;
    130 
    131 	mangled = op_mangle_filename(&values);
    132 
    133 	if (values.flags & MANGLE_ANON)
    134 		free((char *)values.image_name);
    135 	if (values.flags & MANGLE_CG_ANON)
    136 		free((char *)values.cg_image_name);
    137 	return mangled;
    138 }
    139 
    140 
    141 int opd_open_sample_file(odb_t *file, struct sfile *last,
    142                          struct sfile * sf, int counter, int cg)
    143 {
    144 	char * mangled;
    145 	char const * binary;
    146 	int spu_profile = 0;
    147 	vma_t last_start = 0;
    148 	int err;
    149 
    150 	mangled = mangle_filename(last, sf, counter, cg);
    151 
    152 	if (!mangled)
    153 		return EINVAL;
    154 
    155 	verbprintf(vsfile, "Opening \"%s\"\n", mangled);
    156 
    157 	create_path(mangled);
    158 
    159 	/* locking sf will lock associated cg files too */
    160 	sfile_get(sf);
    161 	if (sf != last)
    162 		sfile_get(last);
    163 
    164 retry:
    165 	err = odb_open(file, mangled, ODB_RDWR, sizeof(struct opd_header));
    166 
    167 	/* This can naturally happen when racing against opcontrol --reset. */
    168 	if (err) {
    169 		if (err == EMFILE) {
    170 			if (sfile_lru_clear()) {
    171 				printf("LRU cleared but odb_open() fails for %s.\n", mangled);
    172 				abort();
    173 			}
    174 			goto retry;
    175 		}
    176 
    177 		fprintf(stderr, "oprofiled: open of %s failed: %s\n",
    178 		        mangled, strerror(err));
    179 		goto out;
    180 	}
    181 
    182 	if (!sf->kernel)
    183 		binary = find_cookie(sf->cookie);
    184 	else
    185 		binary = sf->kernel->name;
    186 
    187 	if (last && last->anon)
    188 		last_start = last->anon->start;
    189 
    190 	if (sf->embedded_offset != UNUSED_EMBEDDED_OFFSET)
    191 		spu_profile = 1;
    192 
    193 	fill_header(odb_get_data(file), counter,
    194 		    sf->anon ? sf->anon->start : 0, last_start,
    195 		    !!sf->kernel, last ? !!last->kernel : 0,
    196 		    spu_profile, sf->embedded_offset,
    197 		    binary ? op_get_mtime(binary) : 0);
    198 
    199 out:
    200 	sfile_put(sf);
    201 	if (sf != last)
    202 		sfile_put(last);
    203 	free(mangled);
    204 	return err;
    205 }
    206