1 /*
2 * This code provides functions to handle gcc's profiling data format
3 * introduced with gcc 3.4. Future versions of gcc may change the gcov
4 * format (as happened before), so all format-specific information needs
5 * to be kept modular and easily exchangeable.
6 *
7 * This file is based on gcc-internal definitions. Functions and data
8 * structures are defined to be compatible with gcc counterparts.
9 * For a better understanding, refer to gcc source: gcc/gcov-io.h.
10 *
11 * Copyright IBM Corp. 2009
12 * Author(s): Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
13 *
14 * Uses gcc-internal data definitions.
15 */
16
17 #include <linux/errno.h>
18 #include <linux/slab.h>
19 #include <linux/string.h>
20 #include <linux/seq_file.h>
21 #include <linux/vmalloc.h>
22 #include "gcov.h"
23
24 /* Symbolic links to be created for each profiling data file. */
25 const struct gcov_link gcov_link[] = {
26 { OBJ_TREE, "gcno" }, /* Link to .gcno file in $(objtree). */
27 { 0, NULL},
28 };
29
30 /*
31 * Determine whether a counter is active. Based on gcc magic. Doesn't change
32 * at run-time.
33 */
counter_active(struct gcov_info * info,unsigned int type)34 static int counter_active(struct gcov_info *info, unsigned int type)
35 {
36 return (1 << type) & info->ctr_mask;
37 }
38
39 /* Determine number of active counters. Based on gcc magic. */
num_counter_active(struct gcov_info * info)40 static unsigned int num_counter_active(struct gcov_info *info)
41 {
42 unsigned int i;
43 unsigned int result = 0;
44
45 for (i = 0; i < GCOV_COUNTERS; i++) {
46 if (counter_active(info, i))
47 result++;
48 }
49 return result;
50 }
51
52 /**
53 * gcov_info_reset - reset profiling data to zero
54 * @info: profiling data set
55 */
gcov_info_reset(struct gcov_info * info)56 void gcov_info_reset(struct gcov_info *info)
57 {
58 unsigned int active = num_counter_active(info);
59 unsigned int i;
60
61 for (i = 0; i < active; i++) {
62 memset(info->counts[i].values, 0,
63 info->counts[i].num * sizeof(gcov_type));
64 }
65 }
66
67 /**
68 * gcov_info_is_compatible - check if profiling data can be added
69 * @info1: first profiling data set
70 * @info2: second profiling data set
71 *
72 * Returns non-zero if profiling data can be added, zero otherwise.
73 */
gcov_info_is_compatible(struct gcov_info * info1,struct gcov_info * info2)74 int gcov_info_is_compatible(struct gcov_info *info1, struct gcov_info *info2)
75 {
76 return (info1->stamp == info2->stamp);
77 }
78
79 /**
80 * gcov_info_add - add up profiling data
81 * @dest: profiling data set to which data is added
82 * @source: profiling data set which is added
83 *
84 * Adds profiling counts of @source to @dest.
85 */
gcov_info_add(struct gcov_info * dest,struct gcov_info * source)86 void gcov_info_add(struct gcov_info *dest, struct gcov_info *source)
87 {
88 unsigned int i;
89 unsigned int j;
90
91 for (i = 0; i < num_counter_active(dest); i++) {
92 for (j = 0; j < dest->counts[i].num; j++) {
93 dest->counts[i].values[j] +=
94 source->counts[i].values[j];
95 }
96 }
97 }
98
99 /* Get size of function info entry. Based on gcc magic. */
get_fn_size(struct gcov_info * info)100 static size_t get_fn_size(struct gcov_info *info)
101 {
102 size_t size;
103
104 size = sizeof(struct gcov_fn_info) + num_counter_active(info) *
105 sizeof(unsigned int);
106 if (__alignof__(struct gcov_fn_info) > sizeof(unsigned int))
107 size = ALIGN(size, __alignof__(struct gcov_fn_info));
108 return size;
109 }
110
111 /* Get address of function info entry. Based on gcc magic. */
get_fn_info(struct gcov_info * info,unsigned int fn)112 static struct gcov_fn_info *get_fn_info(struct gcov_info *info, unsigned int fn)
113 {
114 return (struct gcov_fn_info *)
115 ((char *) info->functions + fn * get_fn_size(info));
116 }
117
118 /**
119 * gcov_info_dup - duplicate profiling data set
120 * @info: profiling data set to duplicate
121 *
122 * Return newly allocated duplicate on success, %NULL on error.
123 */
gcov_info_dup(struct gcov_info * info)124 struct gcov_info *gcov_info_dup(struct gcov_info *info)
125 {
126 struct gcov_info *dup;
127 unsigned int i;
128 unsigned int active;
129
130 /* Duplicate gcov_info. */
131 active = num_counter_active(info);
132 dup = kzalloc(sizeof(struct gcov_info) +
133 sizeof(struct gcov_ctr_info) * active, GFP_KERNEL);
134 if (!dup)
135 return NULL;
136 dup->version = info->version;
137 dup->stamp = info->stamp;
138 dup->n_functions = info->n_functions;
139 dup->ctr_mask = info->ctr_mask;
140 /* Duplicate filename. */
141 dup->filename = kstrdup(info->filename, GFP_KERNEL);
142 if (!dup->filename)
143 goto err_free;
144 /* Duplicate table of functions. */
145 dup->functions = kmemdup(info->functions, info->n_functions *
146 get_fn_size(info), GFP_KERNEL);
147 if (!dup->functions)
148 goto err_free;
149 /* Duplicate counter arrays. */
150 for (i = 0; i < active ; i++) {
151 struct gcov_ctr_info *ctr = &info->counts[i];
152 size_t size = ctr->num * sizeof(gcov_type);
153
154 dup->counts[i].num = ctr->num;
155 dup->counts[i].merge = ctr->merge;
156 dup->counts[i].values = vmalloc(size);
157 if (!dup->counts[i].values)
158 goto err_free;
159 memcpy(dup->counts[i].values, ctr->values, size);
160 }
161 return dup;
162
163 err_free:
164 gcov_info_free(dup);
165 return NULL;
166 }
167
168 /**
169 * gcov_info_free - release memory for profiling data set duplicate
170 * @info: profiling data set duplicate to free
171 */
gcov_info_free(struct gcov_info * info)172 void gcov_info_free(struct gcov_info *info)
173 {
174 unsigned int active = num_counter_active(info);
175 unsigned int i;
176
177 for (i = 0; i < active ; i++)
178 vfree(info->counts[i].values);
179 kfree(info->functions);
180 kfree(info->filename);
181 kfree(info);
182 }
183
184 /**
185 * struct type_info - iterator helper array
186 * @ctr_type: counter type
187 * @offset: index of the first value of the current function for this type
188 *
189 * This array is needed to convert the in-memory data format into the in-file
190 * data format:
191 *
192 * In-memory:
193 * for each counter type
194 * for each function
195 * values
196 *
197 * In-file:
198 * for each function
199 * for each counter type
200 * values
201 *
202 * See gcc source gcc/gcov-io.h for more information on data organization.
203 */
204 struct type_info {
205 int ctr_type;
206 unsigned int offset;
207 };
208
209 /**
210 * struct gcov_iterator - specifies current file position in logical records
211 * @info: associated profiling data
212 * @record: record type
213 * @function: function number
214 * @type: counter type
215 * @count: index into values array
216 * @num_types: number of counter types
217 * @type_info: helper array to get values-array offset for current function
218 */
219 struct gcov_iterator {
220 struct gcov_info *info;
221
222 int record;
223 unsigned int function;
224 unsigned int type;
225 unsigned int count;
226
227 int num_types;
228 struct type_info type_info[0];
229 };
230
get_func(struct gcov_iterator * iter)231 static struct gcov_fn_info *get_func(struct gcov_iterator *iter)
232 {
233 return get_fn_info(iter->info, iter->function);
234 }
235
get_type(struct gcov_iterator * iter)236 static struct type_info *get_type(struct gcov_iterator *iter)
237 {
238 return &iter->type_info[iter->type];
239 }
240
241 /**
242 * gcov_iter_new - allocate and initialize profiling data iterator
243 * @info: profiling data set to be iterated
244 *
245 * Return file iterator on success, %NULL otherwise.
246 */
gcov_iter_new(struct gcov_info * info)247 struct gcov_iterator *gcov_iter_new(struct gcov_info *info)
248 {
249 struct gcov_iterator *iter;
250
251 iter = kzalloc(sizeof(struct gcov_iterator) +
252 num_counter_active(info) * sizeof(struct type_info),
253 GFP_KERNEL);
254 if (iter)
255 iter->info = info;
256
257 return iter;
258 }
259
260 /**
261 * gcov_iter_free - release memory for iterator
262 * @iter: file iterator to free
263 */
gcov_iter_free(struct gcov_iterator * iter)264 void gcov_iter_free(struct gcov_iterator *iter)
265 {
266 kfree(iter);
267 }
268
269 /**
270 * gcov_iter_get_info - return profiling data set for given file iterator
271 * @iter: file iterator
272 */
gcov_iter_get_info(struct gcov_iterator * iter)273 struct gcov_info *gcov_iter_get_info(struct gcov_iterator *iter)
274 {
275 return iter->info;
276 }
277
278 /**
279 * gcov_iter_start - reset file iterator to starting position
280 * @iter: file iterator
281 */
gcov_iter_start(struct gcov_iterator * iter)282 void gcov_iter_start(struct gcov_iterator *iter)
283 {
284 int i;
285
286 iter->record = 0;
287 iter->function = 0;
288 iter->type = 0;
289 iter->count = 0;
290 iter->num_types = 0;
291 for (i = 0; i < GCOV_COUNTERS; i++) {
292 if (counter_active(iter->info, i)) {
293 iter->type_info[iter->num_types].ctr_type = i;
294 iter->type_info[iter->num_types++].offset = 0;
295 }
296 }
297 }
298
299 /* Mapping of logical record number to actual file content. */
300 #define RECORD_FILE_MAGIC 0
301 #define RECORD_GCOV_VERSION 1
302 #define RECORD_TIME_STAMP 2
303 #define RECORD_FUNCTION_TAG 3
304 #define RECORD_FUNCTON_TAG_LEN 4
305 #define RECORD_FUNCTION_IDENT 5
306 #define RECORD_FUNCTION_CHECK 6
307 #define RECORD_COUNT_TAG 7
308 #define RECORD_COUNT_LEN 8
309 #define RECORD_COUNT 9
310
311 /**
312 * gcov_iter_next - advance file iterator to next logical record
313 * @iter: file iterator
314 *
315 * Return zero if new position is valid, non-zero if iterator has reached end.
316 */
gcov_iter_next(struct gcov_iterator * iter)317 int gcov_iter_next(struct gcov_iterator *iter)
318 {
319 switch (iter->record) {
320 case RECORD_FILE_MAGIC:
321 case RECORD_GCOV_VERSION:
322 case RECORD_FUNCTION_TAG:
323 case RECORD_FUNCTON_TAG_LEN:
324 case RECORD_FUNCTION_IDENT:
325 case RECORD_COUNT_TAG:
326 /* Advance to next record */
327 iter->record++;
328 break;
329 case RECORD_COUNT:
330 /* Advance to next count */
331 iter->count++;
332 /* fall through */
333 case RECORD_COUNT_LEN:
334 if (iter->count < get_func(iter)->n_ctrs[iter->type]) {
335 iter->record = 9;
336 break;
337 }
338 /* Advance to next counter type */
339 get_type(iter)->offset += iter->count;
340 iter->count = 0;
341 iter->type++;
342 /* fall through */
343 case RECORD_FUNCTION_CHECK:
344 if (iter->type < iter->num_types) {
345 iter->record = 7;
346 break;
347 }
348 /* Advance to next function */
349 iter->type = 0;
350 iter->function++;
351 /* fall through */
352 case RECORD_TIME_STAMP:
353 if (iter->function < iter->info->n_functions)
354 iter->record = 3;
355 else
356 iter->record = -1;
357 break;
358 }
359 /* Check for EOF. */
360 if (iter->record == -1)
361 return -EINVAL;
362 else
363 return 0;
364 }
365
366 /**
367 * seq_write_gcov_u32 - write 32 bit number in gcov format to seq_file
368 * @seq: seq_file handle
369 * @v: value to be stored
370 *
371 * Number format defined by gcc: numbers are recorded in the 32 bit
372 * unsigned binary form of the endianness of the machine generating the
373 * file.
374 */
seq_write_gcov_u32(struct seq_file * seq,u32 v)375 static int seq_write_gcov_u32(struct seq_file *seq, u32 v)
376 {
377 return seq_write(seq, &v, sizeof(v));
378 }
379
380 /**
381 * seq_write_gcov_u64 - write 64 bit number in gcov format to seq_file
382 * @seq: seq_file handle
383 * @v: value to be stored
384 *
385 * Number format defined by gcc: numbers are recorded in the 32 bit
386 * unsigned binary form of the endianness of the machine generating the
387 * file. 64 bit numbers are stored as two 32 bit numbers, the low part
388 * first.
389 */
seq_write_gcov_u64(struct seq_file * seq,u64 v)390 static int seq_write_gcov_u64(struct seq_file *seq, u64 v)
391 {
392 u32 data[2];
393
394 data[0] = (v & 0xffffffffUL);
395 data[1] = (v >> 32);
396 return seq_write(seq, data, sizeof(data));
397 }
398
399 /**
400 * gcov_iter_write - write data for current pos to seq_file
401 * @iter: file iterator
402 * @seq: seq_file handle
403 *
404 * Return zero on success, non-zero otherwise.
405 */
gcov_iter_write(struct gcov_iterator * iter,struct seq_file * seq)406 int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq)
407 {
408 int rc = -EINVAL;
409
410 switch (iter->record) {
411 case RECORD_FILE_MAGIC:
412 rc = seq_write_gcov_u32(seq, GCOV_DATA_MAGIC);
413 break;
414 case RECORD_GCOV_VERSION:
415 rc = seq_write_gcov_u32(seq, iter->info->version);
416 break;
417 case RECORD_TIME_STAMP:
418 rc = seq_write_gcov_u32(seq, iter->info->stamp);
419 break;
420 case RECORD_FUNCTION_TAG:
421 rc = seq_write_gcov_u32(seq, GCOV_TAG_FUNCTION);
422 break;
423 case RECORD_FUNCTON_TAG_LEN:
424 rc = seq_write_gcov_u32(seq, 2);
425 break;
426 case RECORD_FUNCTION_IDENT:
427 rc = seq_write_gcov_u32(seq, get_func(iter)->ident);
428 break;
429 case RECORD_FUNCTION_CHECK:
430 rc = seq_write_gcov_u32(seq, get_func(iter)->checksum);
431 break;
432 case RECORD_COUNT_TAG:
433 rc = seq_write_gcov_u32(seq,
434 GCOV_TAG_FOR_COUNTER(get_type(iter)->ctr_type));
435 break;
436 case RECORD_COUNT_LEN:
437 rc = seq_write_gcov_u32(seq,
438 get_func(iter)->n_ctrs[iter->type] * 2);
439 break;
440 case RECORD_COUNT:
441 rc = seq_write_gcov_u64(seq,
442 iter->info->counts[iter->type].
443 values[iter->count + get_type(iter)->offset]);
444 break;
445 }
446 return rc;
447 }
448