gcov-kernel: patch for Android toolchain 4.4.x support
Juha Tukkinen [Tue, 8 Nov 2011 13:28:08 +0000 (15:28 +0200)]
Based on work done for LTP in
http://ltp.cvs.sourceforge.net/viewvc/ltp/utils/analysis/gcov-kernel

Patch originates from Motorola kernel team (mkw348@motorola.com).

Change-Id: Ibb2a7c8afd79051e8d6c7fde83f04745be14f5fd
Signed-off-by: Juha Tukkinen <jtukkinen@nvidia.com>
Reviewed-on: http://git-master/r/62997
Reviewed-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Reviewed-by: Scott Williams <scwilliams@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>

Rebase-Id: R67557d023bc94fbe900bfc9deef2f5de9955ea43

kernel/gcov/gcc_3_4.c
kernel/gcov/gcov.h

index ae5bb42..d753d11 100644 (file)
@@ -297,16 +297,30 @@ void gcov_iter_start(struct gcov_iterator *iter)
 }
 
 /* Mapping of logical record number to actual file content. */
-#define RECORD_FILE_MAGIC      0
-#define RECORD_GCOV_VERSION    1
-#define RECORD_TIME_STAMP      2
-#define RECORD_FUNCTION_TAG    3
-#define RECORD_FUNCTON_TAG_LEN 4
-#define RECORD_FUNCTION_IDENT  5
-#define RECORD_FUNCTION_CHECK  6
-#define RECORD_COUNT_TAG       7
-#define RECORD_COUNT_LEN       8
-#define RECORD_COUNT           9
+#define RECORD_FILE_MAGIC              0
+#define RECORD_GCOV_VERSION            1
+#define RECORD_TIME_STAMP              2
+#define RECORD_FUNCTION_TAG            3
+#define RECORD_FUNCTON_TAG_LEN         4
+#define RECORD_FUNCTION_IDENT          5
+#define RECORD_FUNCTION_CHECK_LINE     6
+#define RECORD_FUNCTION_CHECK_CFG      7
+#define RECORD_FUNCTION_NAME_LEN       8
+#define RECORD_FUNCTION_NAME           9
+#define RECORD_COUNT_TAG               10
+#define RECORD_COUNT_LEN               11
+#define RECORD_COUNT                   12
+
+/* Return length of string encoded in GCOV format. */
+static size_t
+sizeof_str(const char *str)
+{
+       size_t len;
+       len = (str) ? strlen(str) : 0;
+       if (len == 0)
+               return 1;
+       return 1 + ((len + 4) >> 2);
+}
 
 /**
  * gcov_iter_next - advance file iterator to next logical record
@@ -323,6 +337,9 @@ int gcov_iter_next(struct gcov_iterator *iter)
        case RECORD_FUNCTON_TAG_LEN:
        case RECORD_FUNCTION_IDENT:
        case RECORD_COUNT_TAG:
+       case RECORD_FUNCTION_CHECK_LINE:
+       case RECORD_FUNCTION_CHECK_CFG:
+       case RECORD_FUNCTION_NAME_LEN:
                /* Advance to next record */
                iter->record++;
                break;
@@ -332,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 = 9;
+                       iter->record = 12;
                        break;
                }
                /* Advance to next counter type */
@@ -340,9 +357,9 @@ int gcov_iter_next(struct gcov_iterator *iter)
                iter->count = 0;
                iter->type++;
                /* fall through */
-       case RECORD_FUNCTION_CHECK:
+       case RECORD_FUNCTION_NAME:
                if (iter->type < iter->num_types) {
-                       iter->record = 7;
+                       iter->record = 10;
                        break;
                }
                /* Advance to next function */
@@ -395,6 +412,34 @@ static int seq_write_gcov_u64(struct seq_file *seq, u64 v)
        data[1] = (v >> 32);
        return seq_write(seq, data, sizeof(data));
 }
+/**
+ * seq_write_gcov_str - write string in gcov format to seq_file
+ * @seq: seq_file handle
+ * @str: string to be stored
+ *
+ * Number format defined by gcc: numbers are recorded in the 32 bit
+ * unsigned binary form of the endianness of the machine generating the
+ * file. 64 bit numbers are stored as two 32 bit numbers, the low part
+ * first.
+ */
+static int seq_write_gcov_str(struct seq_file *seq, const char *str)
+{
+       if (str) {
+               size_t len;
+               int str_off;
+               u32 data;
+               len = strlen(str);
+               for (str_off = 0; str_off < (sizeof_str(str) - 2) ; str_off++) {
+                       memcpy(&data, (str + str_off * 4), 4);
+                       seq_write(seq, &data, sizeof(data));
+               }
+               data = 0;
+               memcpy(&data, (str + str_off * 4), (len - str_off * 4));
+               return seq_write(seq, &data, sizeof(data));
+       } else {
+               return 0;
+       }
+}
 
 /**
  * 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)
                rc = seq_write_gcov_u32(seq, GCOV_TAG_FUNCTION);
                break;
        case RECORD_FUNCTON_TAG_LEN:
-               rc = seq_write_gcov_u32(seq, 2);
+               rc = seq_write_gcov_u32(seq, GCOV_TAG_FUNCTION_LENGTH +
+                       (sizeof_str(get_func(iter)->name)));
                break;
        case RECORD_FUNCTION_IDENT:
                rc = seq_write_gcov_u32(seq, get_func(iter)->ident);
                break;
-       case RECORD_FUNCTION_CHECK:
-               rc = seq_write_gcov_u32(seq, get_func(iter)->checksum);
+       case RECORD_FUNCTION_CHECK_LINE:
+               rc = seq_write_gcov_u32(seq, get_func(iter)->lineno_checksum);
+               break;
+       case RECORD_FUNCTION_CHECK_CFG:
+               rc = seq_write_gcov_u32(seq, get_func(iter)->cfg_checksum);
+               break;
+       case RECORD_FUNCTION_NAME_LEN:
+               rc = seq_write_gcov_u32(seq,
+                       (sizeof_str(get_func(iter)->name) - 1));
+               break;
+       case RECORD_FUNCTION_NAME:
+               rc = seq_write_gcov_str(seq, get_func(iter)->name);
                break;
        case RECORD_COUNT_TAG:
                rc = seq_write_gcov_u32(seq,
index 060073e..040c698 100644 (file)
  * gcc and need to be kept as close to the original definition as possible to
  * remain compatible.
  */
-#define GCOV_COUNTERS          5
+#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))
@@ -34,10 +35,38 @@ typedef long gcov_type;
 typedef long long gcov_type;
 #endif
 
+/*
+ * Source module info. The data structure is used in both runtime and
+ * profile-use phase.
+ */
+struct gcov_module_info {
+       unsigned int ident;
+/*
+ * This is overloaded to mean two things:
+ * (1) means FDO/LIPO in instrumented binary.
+ * (2) means IS_PRIMARY in persistent file or memory copy used in profile-use.
+ */
+       unsigned int is_primary;
+       unsigned int is_exported;
+       unsigned int lang;
+       char *da_filename;
+       char *source_filename;
+       unsigned int num_quote_paths;
+       unsigned int num_bracket_paths;
+       unsigned int num_cpp_defines;
+       unsigned int num_cpp_includes;
+       unsigned int num_cl_args;
+       char *string_array[1];
+};
+
+
 /**
  * struct gcov_fn_info - profiling meta data per function
  * @ident: object file-unique function identifier
- * @checksum: function checksum
+ * @lineno_checksum: function lineno checksum
+ * @cfg_checksum: function cfg checksum
+ * @dc_offset: direct call offset
+ * @name: function name
  * @n_ctrs: number of values per counter type belonging to this function
  *
  * This data is generated by gcc during compilation and doesn't change
@@ -45,7 +74,10 @@ typedef long long gcov_type;
  */
 struct gcov_fn_info {
        unsigned int ident;
-       unsigned int checksum;
+       unsigned int lineno_checksum;
+       unsigned int cfg_checksum;
+       unsigned int dc_offset;
+       const char   *name;
        unsigned int n_ctrs[0];
 };
 
@@ -67,9 +99,11 @@ struct gcov_ctr_info {
 /**
  * struct gcov_info - profiling data per object file
  * @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
  * @n_functions: number of instrumented functions
  * @functions: function data
  * @ctr_mask: mask specifying which counter types are active
@@ -80,9 +114,11 @@ struct gcov_ctr_info {
  */
 struct gcov_info {
        unsigned int                    version;
+       struct gcov_module_info         *mod_info;
        struct gcov_info                *next;
        unsigned int                    stamp;
        const char                      *filename;
+       unsigned int                    eof_pos;
        unsigned int                    n_functions;
        const struct gcov_fn_info       *functions;
        unsigned int                    ctr_mask;