diff options
author | Tuomas Tynkkynen <ttynkkynen@nvidia.com> | 2012-11-09 18:20:44 +0200 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-11-14 16:14:23 -0800 |
commit | 9e4812743ac7a29320d72bd0f51b322ef04ff04f (patch) | |
tree | 9dfa7ff2fc2417ee14002257e779b2d650ff90a7 /kernel | |
parent | 77c1717ac2eb4493afaf03307b4ce981dadc51c1 (diff) |
gcov-kernel: Make gcov work on vanilla gcc again.
Commit "gcov-kernel: patch for Android toolchain 4.4.x support" broke
support for gcov on vanilla gcc. Introduce #ifdefs to make it work on
both of them.
Since the gcov ABI for Android gcc is different, the build system
must set CONFIG_GCOV_TOOLCHAIN_IS_ANDROID when compiling with an
Android toolchain.
Also remove a few magic numbers from the original gcov code and fix a
unused function warning.
Bug 1155439
Change-Id: I7c18938e5503df4ee1c3f8de2b6f5a99ceef7f71
Signed-off-by: Tuomas Tynkkynen <ttynkkynen@nvidia.com>
Reviewed-on: http://git-master/r/162711
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Juha Tukkinen <jtukkinen@nvidia.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/gcov/Kconfig | 11 | ||||
-rw-r--r-- | kernel/gcov/gcc_3_4.c | 23 | ||||
-rw-r--r-- | kernel/gcov/gcov.h | 50 |
3 files changed, 61 insertions, 23 deletions
diff --git a/kernel/gcov/Kconfig b/kernel/gcov/Kconfig index 824b741925bb..19c4ba724787 100644 --- a/kernel/gcov/Kconfig +++ b/kernel/gcov/Kconfig @@ -46,6 +46,17 @@ config GCOV_PROFILE_ALL larger and run slower. Also be sure to exclude files from profiling which are not linked to the kernel image to prevent linker errors. +config GCOV_TOOLCHAIN_IS_ANDROID + bool "Use Android toolchain ABI for gcov instead of vanilla gcc ABI" + default n + ---help--- + This option must be set if a gcov-enabled kernel is being built with an + Android toolchain. The gcov ABI in Android gcc is not compatible with + vanilla gcc, and choosing this option incorrectly might lead to kernel + panics during boot or when dumping the gcov data. + + If unsure, say N. + config GCOV_CTORS string depends on CONSTRUCTORS diff --git a/kernel/gcov/gcc_3_4.c b/kernel/gcov/gcc_3_4.c index bc78336bc345..e075a1535fb0 100644 --- a/kernel/gcov/gcc_3_4.c +++ b/kernel/gcov/gcc_3_4.c @@ -349,7 +349,7 @@ int gcov_iter_next(struct gcov_iterator *iter) /* fall through */ case RECORD_COUNT_LEN: if (iter->count < get_func(iter)->n_ctrs[iter->type]) { - iter->record = 12; + iter->record = RECORD_COUNT; break; } /* Advance to next counter type */ @@ -359,7 +359,7 @@ int gcov_iter_next(struct gcov_iterator *iter) /* fall through */ case RECORD_FUNCTION_NAME: if (iter->type < iter->num_types) { - iter->record = 10; + iter->record = RECORD_COUNT_TAG; break; } /* Advance to next function */ @@ -368,7 +368,7 @@ int gcov_iter_next(struct gcov_iterator *iter) /* fall through */ case RECORD_TIME_STAMP: if (iter->function < iter->info->n_functions) - iter->record = 3; + iter->record = RECORD_FUNCTION_TAG; else iter->record = -1; break; @@ -423,6 +423,9 @@ static int seq_write_gcov_u64(struct seq_file *seq, u64 v) * first. */ static int seq_write_gcov_str(struct seq_file *seq, const char *str) + __attribute__ ((unused)); + +static int seq_write_gcov_str(struct seq_file *seq, const char *str) { if (str) { size_t len; @@ -450,7 +453,7 @@ static int seq_write_gcov_str(struct seq_file *seq, const char *str) */ int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq) { - int rc = -EINVAL; + int rc = 0; switch (iter->record) { case RECORD_FILE_MAGIC: @@ -477,24 +480,26 @@ int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq) rc = seq_write_gcov_u32(seq, get_func(iter)->ident); break; case RECORD_FUNCTION_CHECK_LINE: +#ifdef CONFIG_GCOV_TOOLCHAIN_IS_ANDROID rc = seq_write_gcov_u32(seq, get_func(iter)->lineno_checksum); +#else + rc = seq_write_gcov_u32(seq, get_func(iter)->checksum); +#endif break; case RECORD_FUNCTION_CHECK_CFG: +#ifdef CONFIG_GCOV_TOOLCHAIN_IS_ANDROID rc = seq_write_gcov_u32(seq, get_func(iter)->cfg_checksum); +#endif break; case RECORD_FUNCTION_NAME_LEN: #ifdef GCOV_FN_INFO_HAS_NAME_FIELD rc = seq_write_gcov_u32(seq, (sizeof_str(get_func(iter)->name) - 1)); -#else - rc = 0; #endif break; case RECORD_FUNCTION_NAME: #ifdef GCOV_FN_INFO_HAS_NAME_FIELD rc = seq_write_gcov_str(seq, get_func(iter)->name); -#else - rc = 0; #endif break; case RECORD_COUNT_TAG: @@ -510,6 +515,8 @@ int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq) iter->info->counts[iter->type]. values[iter->count + get_type(iter)->offset]); break; + default: + rc = -EINVAL; } return rc; } diff --git a/kernel/gcov/gcov.h b/kernel/gcov/gcov.h index 8c5130a5c1b5..3083b37f430d 100644 --- a/kernel/gcov/gcov.h +++ b/kernel/gcov/gcov.h @@ -17,21 +17,32 @@ #include <linux/types.h> /* - * GCC 4.6 drops the 'name' field from 'struct gcov_fn_info'. + * Profiling data types used for at least gcc 4.4 - these are defined by + * gcc and need to be kept as close to the original definition as possible to + * remain compatible. + * + * If compiling with an Android toolchain (from 4.4 to at least 4.6), + * CONFIG_GCOV_TOOLCHAIN_IS_ANDROID must be set, since it's not compatible + * with a vanilla gcc. */ -#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6) -#define GCOV_FN_INFO_HAS_NAME_FIELD -#endif + +#ifdef CONFIG_GCOV_TOOLCHAIN_IS_ANDROID /* - * Profiling data types used for at least gcc 4.4 and 4.6 - these are defined by - * gcc and need to be kept as close to the original definition as possible to - * remain compatible. + * Android GCC 4.6 drops the 'name' field from 'struct gcov_fn_info'. */ +# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6) +# define GCOV_FN_INFO_HAS_NAME_FIELD +# endif + +# define GCOV_TAG_FUNCTION_LENGTH 3 +#else /* !CONFIG_GCOV_TOOLCHAIN_IS_ANDROID */ +# define GCOV_TAG_FUNCTION_LENGTH 2 +#endif + #define GCOV_COUNTERS 10 #define GCOV_DATA_MAGIC ((unsigned int) 0x67636461) #define GCOV_TAG_FUNCTION ((unsigned int) 0x01000000) -#define GCOV_TAG_FUNCTION_LENGTH 3 #define GCOV_TAG_COUNTER_BASE ((unsigned int) 0x01a10000) #define GCOV_TAG_FOR_COUNTER(count) \ (GCOV_TAG_COUNTER_BASE + ((unsigned int) (count) << 17)) @@ -44,7 +55,7 @@ typedef long long gcov_type; /* * Source module info. The data structure is used in both runtime and - * profile-use phase. + * profile-use phase. Android toolchain only. */ struct gcov_module_info { unsigned int ident; @@ -70,10 +81,11 @@ struct gcov_module_info { /** * struct gcov_fn_info - profiling meta data per function * @ident: object file-unique function identifier - * @lineno_checksum: function lineno checksum - * @cfg_checksum: function cfg checksum + * @checksum: function checksum. Removed in Android GCC 4.4+ + * @lineno_checksum: function lineno checksum. In Android GCC 4.4+ + * @cfg_checksum: function cfg checksum. In Android GCC 4.4+ * @dc_offset: direct call offset - * @name: function name + * @name: function name. In Android GCC 4.4, removed from 4.6. * @n_ctrs: number of values per counter type belonging to this function * * This data is generated by gcc during compilation and doesn't change @@ -81,11 +93,15 @@ struct gcov_module_info { */ struct gcov_fn_info { unsigned int ident; +#ifndef CONFIG_GCOV_TOOLCHAIN_IS_ANDROID + unsigned int checksum; +#else unsigned int lineno_checksum; unsigned int cfg_checksum; unsigned int dc_offset; -#ifdef GCOV_FN_INFO_HAS_NAME_FIELD +# ifdef GCOV_FN_INFO_HAS_NAME_FIELD const char *name; +# endif #endif unsigned int n_ctrs[0]; }; @@ -106,13 +122,13 @@ struct gcov_ctr_info { }; /** - * struct gcov_info - profiling data per object file + * struct gcov_info - profiling data per object file. In Android GCC 4.4+ * @version: gcov version magic indicating the gcc version used for compilation * @modinfo: additional module information * @next: list head for a singly-linked list * @stamp: time stamp * @filename: name of the associated gcov data file - * @eof_pos: end position of profile data + * @eof_pos: end position of profile data. In Android GCC 4.4+ * @n_functions: number of instrumented functions * @functions: function data * @ctr_mask: mask specifying which counter types are active @@ -123,11 +139,15 @@ struct gcov_ctr_info { */ struct gcov_info { unsigned int version; +#ifdef CONFIG_GCOV_TOOLCHAIN_IS_ANDROID struct gcov_module_info *mod_info; +#endif struct gcov_info *next; unsigned int stamp; const char *filename; +#ifdef CONFIG_GCOV_TOOLCHAIN_IS_ANDROID unsigned int eof_pos; +#endif unsigned int n_functions; const struct gcov_fn_info *functions; unsigned int ctr_mask; |