diff options
Diffstat (limited to 'kernel/gcov/clang.c')
| -rw-r--r-- | kernel/gcov/clang.c | 88 | 
1 files changed, 83 insertions, 5 deletions
| diff --git a/kernel/gcov/clang.c b/kernel/gcov/clang.c index c94b820a1b62..c466c7fbdece 100644 --- a/kernel/gcov/clang.c +++ b/kernel/gcov/clang.c @@ -70,12 +70,16 @@ struct gcov_fn_info {  	u32 ident;  	u32 checksum; +#if CONFIG_CLANG_VERSION < 110000  	u8 use_extra_checksum; +#endif  	u32 cfg_checksum;  	u32 num_counters;  	u64 *counters; +#if CONFIG_CLANG_VERSION < 110000  	const char *function_name; +#endif  };  static struct gcov_info *current_info; @@ -105,6 +109,7 @@ void llvm_gcov_init(llvm_gcov_callback writeout, llvm_gcov_callback flush)  }  EXPORT_SYMBOL(llvm_gcov_init); +#if CONFIG_CLANG_VERSION < 110000  void llvm_gcda_start_file(const char *orig_filename, const char version[4],  		u32 checksum)  { @@ -113,7 +118,17 @@ void llvm_gcda_start_file(const char *orig_filename, const char version[4],  	current_info->checksum = checksum;  }  EXPORT_SYMBOL(llvm_gcda_start_file); +#else +void llvm_gcda_start_file(const char *orig_filename, u32 version, u32 checksum) +{ +	current_info->filename = orig_filename; +	current_info->version = version; +	current_info->checksum = checksum; +} +EXPORT_SYMBOL(llvm_gcda_start_file); +#endif +#if CONFIG_CLANG_VERSION < 110000  void llvm_gcda_emit_function(u32 ident, const char *function_name,  		u32 func_checksum, u8 use_extra_checksum, u32 cfg_checksum)  { @@ -132,6 +147,21 @@ void llvm_gcda_emit_function(u32 ident, const char *function_name,  	list_add_tail(&info->head, ¤t_info->functions);  } +#else +void llvm_gcda_emit_function(u32 ident, u32 func_checksum, u32 cfg_checksum) +{ +	struct gcov_fn_info *info = kzalloc(sizeof(*info), GFP_KERNEL); + +	if (!info) +		return; + +	INIT_LIST_HEAD(&info->head); +	info->ident = ident; +	info->checksum = func_checksum; +	info->cfg_checksum = cfg_checksum; +	list_add_tail(&info->head, ¤t_info->functions); +} +#endif  EXPORT_SYMBOL(llvm_gcda_emit_function);  void llvm_gcda_emit_arcs(u32 num_counters, u64 *counters) @@ -262,11 +292,16 @@ int gcov_info_is_compatible(struct gcov_info *info1, struct gcov_info *info2)  		!list_is_last(&fn_ptr2->head, &info2->functions)) {  		if (fn_ptr1->checksum != fn_ptr2->checksum)  			return false; +#if CONFIG_CLANG_VERSION < 110000  		if (fn_ptr1->use_extra_checksum != fn_ptr2->use_extra_checksum)  			return false;  		if (fn_ptr1->use_extra_checksum &&  			fn_ptr1->cfg_checksum != fn_ptr2->cfg_checksum)  			return false; +#else +		if (fn_ptr1->cfg_checksum != fn_ptr2->cfg_checksum) +			return false; +#endif  		fn_ptr1 = list_next_entry(fn_ptr1, head);  		fn_ptr2 = list_next_entry(fn_ptr2, head);  	} @@ -295,6 +330,7 @@ void gcov_info_add(struct gcov_info *dst, struct gcov_info *src)  	}  } +#if CONFIG_CLANG_VERSION < 110000  static struct gcov_fn_info *gcov_fn_info_dup(struct gcov_fn_info *fn)  {  	size_t cv_size; /* counter values size */ @@ -322,6 +358,28 @@ err_name:  	kfree(fn_dup);  	return NULL;  } +#else +static struct gcov_fn_info *gcov_fn_info_dup(struct gcov_fn_info *fn) +{ +	size_t cv_size; /* counter values size */ +	struct gcov_fn_info *fn_dup = kmemdup(fn, sizeof(*fn), +			GFP_KERNEL); +	if (!fn_dup) +		return NULL; +	INIT_LIST_HEAD(&fn_dup->head); + +	cv_size = fn->num_counters * sizeof(fn->counters[0]); +	fn_dup->counters = vmalloc(cv_size); +	if (!fn_dup->counters) { +		kfree(fn_dup); +		return NULL; +	} + +	memcpy(fn_dup->counters, fn->counters, cv_size); + +	return fn_dup; +} +#endif  /**   * gcov_info_dup - duplicate profiling data set @@ -362,6 +420,7 @@ err:   * gcov_info_free - release memory for profiling data set duplicate   * @info: profiling data set duplicate to free   */ +#if CONFIG_CLANG_VERSION < 110000  void gcov_info_free(struct gcov_info *info)  {  	struct gcov_fn_info *fn, *tmp; @@ -375,6 +434,20 @@ void gcov_info_free(struct gcov_info *info)  	kfree(info->filename);  	kfree(info);  } +#else +void gcov_info_free(struct gcov_info *info) +{ +	struct gcov_fn_info *fn, *tmp; + +	list_for_each_entry_safe(fn, tmp, &info->functions, head) { +		vfree(fn->counters); +		list_del(&fn->head); +		kfree(fn); +	} +	kfree(info->filename); +	kfree(info); +} +#endif  #define ITER_STRIDE	PAGE_SIZE @@ -460,17 +533,22 @@ static size_t convert_to_gcda(char *buffer, struct gcov_info *info)  	list_for_each_entry(fi_ptr, &info->functions, head) {  		u32 i; -		u32 len = 2; - -		if (fi_ptr->use_extra_checksum) -			len++;  		pos += store_gcov_u32(buffer, pos, GCOV_TAG_FUNCTION); -		pos += store_gcov_u32(buffer, pos, len); +#if CONFIG_CLANG_VERSION < 110000 +		pos += store_gcov_u32(buffer, pos, +			fi_ptr->use_extra_checksum ? 3 : 2); +#else +		pos += store_gcov_u32(buffer, pos, 3); +#endif  		pos += store_gcov_u32(buffer, pos, fi_ptr->ident);  		pos += store_gcov_u32(buffer, pos, fi_ptr->checksum); +#if CONFIG_CLANG_VERSION < 110000  		if (fi_ptr->use_extra_checksum)  			pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum); +#else +		pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum); +#endif  		pos += store_gcov_u32(buffer, pos, GCOV_TAG_COUNTER_BASE);  		pos += store_gcov_u32(buffer, pos, fi_ptr->num_counters * 2); |