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