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