summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorTuomas Tynkkynen <ttynkkynen@nvidia.com>2012-11-09 18:20:44 +0200
committerSimone Willett <swillett@nvidia.com>2012-11-14 16:14:23 -0800
commit9e4812743ac7a29320d72bd0f51b322ef04ff04f (patch)
tree9dfa7ff2fc2417ee14002257e779b2d650ff90a7 /kernel
parent77c1717ac2eb4493afaf03307b4ce981dadc51c1 (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/Kconfig11
-rw-r--r--kernel/gcov/gcc_3_4.c23
-rw-r--r--kernel/gcov/gcov.h50
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;