• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
get_dep_name(struct sfile const * sf)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 
mangle_anon(struct anon_mapping const * anon)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 *
mangle_filename(struct sfile * last,struct sfile const * sf,int counter,int cg)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 
opd_open_sample_file(odb_t * file,struct sfile * last,struct sfile * sf,int counter,int cg)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