aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/gcov
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gcov')
-rw-r--r--kernel/gcov/Kconfig10
-rw-r--r--kernel/gcov/gcc_3_4.c88
-rw-r--r--kernel/gcov/gcov.h42
3 files changed, 119 insertions, 21 deletions
diff --git a/kernel/gcov/Kconfig b/kernel/gcov/Kconfig
index 5bf924d80b5..824b741925b 100644
--- a/kernel/gcov/Kconfig
+++ b/kernel/gcov/Kconfig
@@ -3,7 +3,7 @@ menu "GCOV-based kernel profiling"
3config GCOV_KERNEL 3config GCOV_KERNEL
4 bool "Enable gcov-based kernel profiling" 4 bool "Enable gcov-based kernel profiling"
5 depends on DEBUG_FS 5 depends on DEBUG_FS
6 select CONSTRUCTORS 6 select CONSTRUCTORS if !UML
7 default n 7 default n
8 ---help--- 8 ---help---
9 This option enables gcov-based code profiling (e.g. for code coverage 9 This option enables gcov-based code profiling (e.g. for code coverage
@@ -35,7 +35,7 @@ config GCOV_KERNEL
35config GCOV_PROFILE_ALL 35config GCOV_PROFILE_ALL
36 bool "Profile entire Kernel" 36 bool "Profile entire Kernel"
37 depends on GCOV_KERNEL 37 depends on GCOV_KERNEL
38 depends on SUPERH || S390 || X86 || (PPC && EXPERIMENTAL) || MICROBLAZE 38 depends on SUPERH || S390 || X86 || (PPC && EXPERIMENTAL) || MICROBLAZE || ARM
39 default n 39 default n
40 ---help--- 40 ---help---
41 This options activates profiling for the entire kernel. 41 This options activates profiling for the entire kernel.
@@ -46,4 +46,10 @@ config GCOV_PROFILE_ALL
46 larger and run slower. Also be sure to exclude files from profiling 46 larger and run slower. Also be sure to exclude files from profiling
47 which are not linked to the kernel image to prevent linker errors. 47 which are not linked to the kernel image to prevent linker errors.
48 48
49config GCOV_CTORS
50 string
51 depends on CONSTRUCTORS
52 default ".init_array" if ARM && AEABI
53 default ".ctors"
54
49endmenu 55endmenu
diff --git a/kernel/gcov/gcc_3_4.c b/kernel/gcov/gcc_3_4.c
index ae5bb426003..d753d1152b7 100644
--- a/kernel/gcov/gcc_3_4.c
+++ b/kernel/gcov/gcc_3_4.c
@@ -297,16 +297,30 @@ void gcov_iter_start(struct gcov_iterator *iter)
297} 297}
298 298
299/* Mapping of logical record number to actual file content. */ 299/* Mapping of logical record number to actual file content. */
300#define RECORD_FILE_MAGIC 0 300#define RECORD_FILE_MAGIC 0
301#define RECORD_GCOV_VERSION 1 301#define RECORD_GCOV_VERSION 1
302#define RECORD_TIME_STAMP 2 302#define RECORD_TIME_STAMP 2
303#define RECORD_FUNCTION_TAG 3 303#define RECORD_FUNCTION_TAG 3
304#define RECORD_FUNCTON_TAG_LEN 4 304#define RECORD_FUNCTON_TAG_LEN 4
305#define RECORD_FUNCTION_IDENT 5 305#define RECORD_FUNCTION_IDENT 5
306#define RECORD_FUNCTION_CHECK 6 306#define RECORD_FUNCTION_CHECK_LINE 6
307#define RECORD_COUNT_TAG 7 307#define RECORD_FUNCTION_CHECK_CFG 7
308#define RECORD_COUNT_LEN 8 308#define RECORD_FUNCTION_NAME_LEN 8
309#define RECORD_COUNT 9 309#define RECORD_FUNCTION_NAME 9
310#define RECORD_COUNT_TAG 10
311#define RECORD_COUNT_LEN 11
312#define RECORD_COUNT 12
313
314/* Return length of string encoded in GCOV format. */
315static size_t
316sizeof_str(const char *str)
317{
318 size_t len;
319 len = (str) ? strlen(str) : 0;
320 if (len == 0)
321 return 1;
322 return 1 + ((len + 4) >> 2);
323}
310 324
311/** 325/**
312 * gcov_iter_next - advance file iterator to next logical record 326 * gcov_iter_next - advance file iterator to next logical record
@@ -323,6 +337,9 @@ int gcov_iter_next(struct gcov_iterator *iter)
323 case RECORD_FUNCTON_TAG_LEN: 337 case RECORD_FUNCTON_TAG_LEN:
324 case RECORD_FUNCTION_IDENT: 338 case RECORD_FUNCTION_IDENT:
325 case RECORD_COUNT_TAG: 339 case RECORD_COUNT_TAG:
340 case RECORD_FUNCTION_CHECK_LINE:
341 case RECORD_FUNCTION_CHECK_CFG:
342 case RECORD_FUNCTION_NAME_LEN:
326 /* Advance to next record */ 343 /* Advance to next record */
327 iter->record++; 344 iter->record++;
328 break; 345 break;
@@ -332,7 +349,7 @@ int gcov_iter_next(struct gcov_iterator *iter)
332 /* fall through */ 349 /* fall through */
333 case RECORD_COUNT_LEN: 350 case RECORD_COUNT_LEN:
334 if (iter->count < get_func(iter)->n_ctrs[iter->type]) { 351 if (iter->count < get_func(iter)->n_ctrs[iter->type]) {
335 iter->record = 9; 352 iter->record = 12;
336 break; 353 break;
337 } 354 }
338 /* Advance to next counter type */ 355 /* Advance to next counter type */
@@ -340,9 +357,9 @@ int gcov_iter_next(struct gcov_iterator *iter)
340 iter->count = 0; 357 iter->count = 0;
341 iter->type++; 358 iter->type++;
342 /* fall through */ 359 /* fall through */
343 case RECORD_FUNCTION_CHECK: 360 case RECORD_FUNCTION_NAME:
344 if (iter->type < iter->num_types) { 361 if (iter->type < iter->num_types) {
345 iter->record = 7; 362 iter->record = 10;
346 break; 363 break;
347 } 364 }
348 /* Advance to next function */ 365 /* Advance to next function */
@@ -395,6 +412,34 @@ static int seq_write_gcov_u64(struct seq_file *seq, u64 v)
395 data[1] = (v >> 32); 412 data[1] = (v >> 32);
396 return seq_write(seq, data, sizeof(data)); 413 return seq_write(seq, data, sizeof(data));
397} 414}
415/**
416 * seq_write_gcov_str - write string in gcov format to seq_file
417 * @seq: seq_file handle
418 * @str: string to be stored
419 *
420 * Number format defined by gcc: numbers are recorded in the 32 bit
421 * unsigned binary form of the endianness of the machine generating the
422 * file. 64 bit numbers are stored as two 32 bit numbers, the low part
423 * first.
424 */
425static int seq_write_gcov_str(struct seq_file *seq, const char *str)
426{
427 if (str) {
428 size_t len;
429 int str_off;
430 u32 data;
431 len = strlen(str);
432 for (str_off = 0; str_off < (sizeof_str(str) - 2) ; str_off++) {
433 memcpy(&data, (str + str_off * 4), 4);
434 seq_write(seq, &data, sizeof(data));
435 }
436 data = 0;
437 memcpy(&data, (str + str_off * 4), (len - str_off * 4));
438 return seq_write(seq, &data, sizeof(data));
439 } else {
440 return 0;
441 }
442}
398 443
399/** 444/**
400 * gcov_iter_write - write data for current pos to seq_file 445 * gcov_iter_write - write data for current pos to seq_file
@@ -421,13 +466,24 @@ int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq)
421 rc = seq_write_gcov_u32(seq, GCOV_TAG_FUNCTION); 466 rc = seq_write_gcov_u32(seq, GCOV_TAG_FUNCTION);
422 break; 467 break;
423 case RECORD_FUNCTON_TAG_LEN: 468 case RECORD_FUNCTON_TAG_LEN:
424 rc = seq_write_gcov_u32(seq, 2); 469 rc = seq_write_gcov_u32(seq, GCOV_TAG_FUNCTION_LENGTH +
470 (sizeof_str(get_func(iter)->name)));
425 break; 471 break;
426 case RECORD_FUNCTION_IDENT: 472 case RECORD_FUNCTION_IDENT:
427 rc = seq_write_gcov_u32(seq, get_func(iter)->ident); 473 rc = seq_write_gcov_u32(seq, get_func(iter)->ident);
428 break; 474 break;
429 case RECORD_FUNCTION_CHECK: 475 case RECORD_FUNCTION_CHECK_LINE:
430 rc = seq_write_gcov_u32(seq, get_func(iter)->checksum); 476 rc = seq_write_gcov_u32(seq, get_func(iter)->lineno_checksum);
477 break;
478 case RECORD_FUNCTION_CHECK_CFG:
479 rc = seq_write_gcov_u32(seq, get_func(iter)->cfg_checksum);
480 break;
481 case RECORD_FUNCTION_NAME_LEN:
482 rc = seq_write_gcov_u32(seq,
483 (sizeof_str(get_func(iter)->name) - 1));
484 break;
485 case RECORD_FUNCTION_NAME:
486 rc = seq_write_gcov_str(seq, get_func(iter)->name);
431 break; 487 break;
432 case RECORD_COUNT_TAG: 488 case RECORD_COUNT_TAG:
433 rc = seq_write_gcov_u32(seq, 489 rc = seq_write_gcov_u32(seq,
diff --git a/kernel/gcov/gcov.h b/kernel/gcov/gcov.h
index 060073ebf7a..040c6980df0 100644
--- a/kernel/gcov/gcov.h
+++ b/kernel/gcov/gcov.h
@@ -21,9 +21,10 @@
21 * gcc and need to be kept as close to the original definition as possible to 21 * gcc and need to be kept as close to the original definition as possible to
22 * remain compatible. 22 * remain compatible.
23 */ 23 */
24#define GCOV_COUNTERS 5 24#define GCOV_COUNTERS 10
25#define GCOV_DATA_MAGIC ((unsigned int) 0x67636461) 25#define GCOV_DATA_MAGIC ((unsigned int) 0x67636461)
26#define GCOV_TAG_FUNCTION ((unsigned int) 0x01000000) 26#define GCOV_TAG_FUNCTION ((unsigned int) 0x01000000)
27#define GCOV_TAG_FUNCTION_LENGTH 3
27#define GCOV_TAG_COUNTER_BASE ((unsigned int) 0x01a10000) 28#define GCOV_TAG_COUNTER_BASE ((unsigned int) 0x01a10000)
28#define GCOV_TAG_FOR_COUNTER(count) \ 29#define GCOV_TAG_FOR_COUNTER(count) \
29 (GCOV_TAG_COUNTER_BASE + ((unsigned int) (count) << 17)) 30 (GCOV_TAG_COUNTER_BASE + ((unsigned int) (count) << 17))
@@ -34,10 +35,38 @@ typedef long gcov_type;
34typedef long long gcov_type; 35typedef long long gcov_type;
35#endif 36#endif
36 37
38/*
39 * Source module info. The data structure is used in both runtime and
40 * profile-use phase.
41 */
42struct gcov_module_info {
43 unsigned int ident;
44/*
45 * This is overloaded to mean two things:
46 * (1) means FDO/LIPO in instrumented binary.
47 * (2) means IS_PRIMARY in persistent file or memory copy used in profile-use.
48 */
49 unsigned int is_primary;
50 unsigned int is_exported;
51 unsigned int lang;
52 char *da_filename;
53 char *source_filename;
54 unsigned int num_quote_paths;
55 unsigned int num_bracket_paths;
56 unsigned int num_cpp_defines;
57 unsigned int num_cpp_includes;
58 unsigned int num_cl_args;
59 char *string_array[1];
60};
61
62
37/** 63/**
38 * struct gcov_fn_info - profiling meta data per function 64 * struct gcov_fn_info - profiling meta data per function
39 * @ident: object file-unique function identifier 65 * @ident: object file-unique function identifier
40 * @checksum: function checksum 66 * @lineno_checksum: function lineno checksum
67 * @cfg_checksum: function cfg checksum
68 * @dc_offset: direct call offset
69 * @name: function name
41 * @n_ctrs: number of values per counter type belonging to this function 70 * @n_ctrs: number of values per counter type belonging to this function
42 * 71 *
43 * This data is generated by gcc during compilation and doesn't change 72 * This data is generated by gcc during compilation and doesn't change
@@ -45,7 +74,10 @@ typedef long long gcov_type;
45 */ 74 */
46struct gcov_fn_info { 75struct gcov_fn_info {
47 unsigned int ident; 76 unsigned int ident;
48 unsigned int checksum; 77 unsigned int lineno_checksum;
78 unsigned int cfg_checksum;
79 unsigned int dc_offset;
80 const char *name;
49 unsigned int n_ctrs[0]; 81 unsigned int n_ctrs[0];
50}; 82};
51 83
@@ -67,9 +99,11 @@ struct gcov_ctr_info {
67/** 99/**
68 * struct gcov_info - profiling data per object file 100 * struct gcov_info - profiling data per object file
69 * @version: gcov version magic indicating the gcc version used for compilation 101 * @version: gcov version magic indicating the gcc version used for compilation
102 * @modinfo: additional module information
70 * @next: list head for a singly-linked list 103 * @next: list head for a singly-linked list
71 * @stamp: time stamp 104 * @stamp: time stamp
72 * @filename: name of the associated gcov data file 105 * @filename: name of the associated gcov data file
106 * @eof_pos: end position of profile data
73 * @n_functions: number of instrumented functions 107 * @n_functions: number of instrumented functions
74 * @functions: function data 108 * @functions: function data
75 * @ctr_mask: mask specifying which counter types are active 109 * @ctr_mask: mask specifying which counter types are active
@@ -80,9 +114,11 @@ struct gcov_ctr_info {
80 */ 114 */
81struct gcov_info { 115struct gcov_info {
82 unsigned int version; 116 unsigned int version;
117 struct gcov_module_info *mod_info;
83 struct gcov_info *next; 118 struct gcov_info *next;
84 unsigned int stamp; 119 unsigned int stamp;
85 const char *filename; 120 const char *filename;
121 unsigned int eof_pos;
86 unsigned int n_functions; 122 unsigned int n_functions;
87 const struct gcov_fn_info *functions; 123 const struct gcov_fn_info *functions;
88 unsigned int ctr_mask; 124 unsigned int ctr_mask;