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
37static 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
57static 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
68static char *
69mangle_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
141int 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
164retry:
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
199out:
200	sfile_put(sf);
201	if (sf != last)
202		sfile_put(last);
203	free(mangled);
204	return err;
205}
206