diff options
author | Juha Tukkinen <jtukkinen@nvidia.com> | 2011-11-08 15:28:08 +0200 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:49:57 -0800 |
commit | 2526094b11a205ddcd10e9b6078fe39d038de0e9 (patch) | |
tree | 2cc910ed69734c9245c408ad1fec6808c744113a | |
parent | e4cb3c4d365364d6fdb0925132ad9b0ce8acda8f (diff) |
gcov-kernel: patch for Android toolchain 4.4.x support
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
-rw-r--r-- | kernel/gcov/gcc_3_4.c | 88 | ||||
-rw-r--r-- | kernel/gcov/gcov.h | 42 |
2 files changed, 111 insertions, 19 deletions
diff --git a/kernel/gcov/gcc_3_4.c b/kernel/gcov/gcc_3_4.c index ae5bb4260033..d753d1152b7b 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) } /* 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, diff --git a/kernel/gcov/gcov.h b/kernel/gcov/gcov.h index 060073ebf7a6..040c6980df0d 100644 --- a/kernel/gcov/gcov.h +++ b/kernel/gcov/gcov.h @@ -21,9 +21,10 @@ * 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; |