]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blob - kernel/gcov/clang.c
gcov: use kvmalloc()
[mirror_ubuntu-kernels.git] / kernel / gcov / clang.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2019 Google, Inc.
4 * modified from kernel/gcov/gcc_4_7.c
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 *
16 * LLVM uses profiling data that's deliberately similar to GCC, but has a
17 * very different way of exporting that data. LLVM calls llvm_gcov_init() once
18 * per module, and provides a couple of callbacks that we can use to ask for
19 * more data.
20 *
21 * We care about the "writeout" callback, which in turn calls back into
22 * compiler-rt/this module to dump all the gathered coverage data to disk:
23 *
24 * llvm_gcda_start_file()
25 * llvm_gcda_emit_function()
26 * llvm_gcda_emit_arcs()
27 * llvm_gcda_emit_function()
28 * llvm_gcda_emit_arcs()
29 * [... repeats for each function ...]
30 * llvm_gcda_summary_info()
31 * llvm_gcda_end_file()
32 *
33 * This design is much more stateless and unstructured than gcc's, and is
34 * intended to run at process exit. This forces us to keep some local state
35 * about which module we're dealing with at the moment. On the other hand, it
36 * also means we don't depend as much on how LLVM represents profiling data
37 * internally.
38 *
39 * See LLVM's lib/Transforms/Instrumentation/GCOVProfiling.cpp for more
40 * details on how this works, particularly GCOVProfiler::emitProfileArcs(),
41 * GCOVProfiler::insertCounterWriteout(), and
42 * GCOVProfiler::insertFlush().
43 */
44
45 #define pr_fmt(fmt) "gcov: " fmt
46
47 #include <linux/kernel.h>
48 #include <linux/list.h>
49 #include <linux/printk.h>
50 #include <linux/ratelimit.h>
51 #include <linux/slab.h>
52 #include <linux/mm.h>
53 #include "gcov.h"
54
55 typedef void (*llvm_gcov_callback)(void);
56
57 struct gcov_info {
58 struct list_head head;
59
60 const char *filename;
61 unsigned int version;
62 u32 checksum;
63
64 struct list_head functions;
65 };
66
67 struct gcov_fn_info {
68 struct list_head head;
69
70 u32 ident;
71 u32 checksum;
72 #if CONFIG_CLANG_VERSION < 110000
73 u8 use_extra_checksum;
74 #endif
75 u32 cfg_checksum;
76
77 u32 num_counters;
78 u64 *counters;
79 #if CONFIG_CLANG_VERSION < 110000
80 const char *function_name;
81 #endif
82 };
83
84 static struct gcov_info *current_info;
85
86 static LIST_HEAD(clang_gcov_list);
87
88 void llvm_gcov_init(llvm_gcov_callback writeout, llvm_gcov_callback flush)
89 {
90 struct gcov_info *info = kzalloc(sizeof(*info), GFP_KERNEL);
91
92 if (!info)
93 return;
94
95 INIT_LIST_HEAD(&info->head);
96 INIT_LIST_HEAD(&info->functions);
97
98 mutex_lock(&gcov_lock);
99
100 list_add_tail(&info->head, &clang_gcov_list);
101 current_info = info;
102 writeout();
103 current_info = NULL;
104 if (gcov_events_enabled)
105 gcov_event(GCOV_ADD, info);
106
107 mutex_unlock(&gcov_lock);
108 }
109 EXPORT_SYMBOL(llvm_gcov_init);
110
111 #if CONFIG_CLANG_VERSION < 110000
112 void llvm_gcda_start_file(const char *orig_filename, const char version[4],
113 u32 checksum)
114 {
115 current_info->filename = orig_filename;
116 memcpy(&current_info->version, version, sizeof(current_info->version));
117 current_info->checksum = checksum;
118 }
119 EXPORT_SYMBOL(llvm_gcda_start_file);
120 #else
121 void llvm_gcda_start_file(const char *orig_filename, u32 version, u32 checksum)
122 {
123 current_info->filename = orig_filename;
124 current_info->version = version;
125 current_info->checksum = checksum;
126 }
127 EXPORT_SYMBOL(llvm_gcda_start_file);
128 #endif
129
130 #if CONFIG_CLANG_VERSION < 110000
131 void llvm_gcda_emit_function(u32 ident, const char *function_name,
132 u32 func_checksum, u8 use_extra_checksum, u32 cfg_checksum)
133 {
134 struct gcov_fn_info *info = kzalloc(sizeof(*info), GFP_KERNEL);
135
136 if (!info)
137 return;
138
139 INIT_LIST_HEAD(&info->head);
140 info->ident = ident;
141 info->checksum = func_checksum;
142 info->use_extra_checksum = use_extra_checksum;
143 info->cfg_checksum = cfg_checksum;
144 if (function_name)
145 info->function_name = kstrdup(function_name, GFP_KERNEL);
146
147 list_add_tail(&info->head, &current_info->functions);
148 }
149 #else
150 void llvm_gcda_emit_function(u32 ident, u32 func_checksum, u32 cfg_checksum)
151 {
152 struct gcov_fn_info *info = kzalloc(sizeof(*info), GFP_KERNEL);
153
154 if (!info)
155 return;
156
157 INIT_LIST_HEAD(&info->head);
158 info->ident = ident;
159 info->checksum = func_checksum;
160 info->cfg_checksum = cfg_checksum;
161 list_add_tail(&info->head, &current_info->functions);
162 }
163 #endif
164 EXPORT_SYMBOL(llvm_gcda_emit_function);
165
166 void llvm_gcda_emit_arcs(u32 num_counters, u64 *counters)
167 {
168 struct gcov_fn_info *info = list_last_entry(&current_info->functions,
169 struct gcov_fn_info, head);
170
171 info->num_counters = num_counters;
172 info->counters = counters;
173 }
174 EXPORT_SYMBOL(llvm_gcda_emit_arcs);
175
176 void llvm_gcda_summary_info(void)
177 {
178 }
179 EXPORT_SYMBOL(llvm_gcda_summary_info);
180
181 void llvm_gcda_end_file(void)
182 {
183 }
184 EXPORT_SYMBOL(llvm_gcda_end_file);
185
186 /**
187 * gcov_info_filename - return info filename
188 * @info: profiling data set
189 */
190 const char *gcov_info_filename(struct gcov_info *info)
191 {
192 return info->filename;
193 }
194
195 /**
196 * gcov_info_version - return info version
197 * @info: profiling data set
198 */
199 unsigned int gcov_info_version(struct gcov_info *info)
200 {
201 return info->version;
202 }
203
204 /**
205 * gcov_info_next - return next profiling data set
206 * @info: profiling data set
207 *
208 * Returns next gcov_info following @info or first gcov_info in the chain if
209 * @info is %NULL.
210 */
211 struct gcov_info *gcov_info_next(struct gcov_info *info)
212 {
213 if (!info)
214 return list_first_entry_or_null(&clang_gcov_list,
215 struct gcov_info, head);
216 if (list_is_last(&info->head, &clang_gcov_list))
217 return NULL;
218 return list_next_entry(info, head);
219 }
220
221 /**
222 * gcov_info_link - link/add profiling data set to the list
223 * @info: profiling data set
224 */
225 void gcov_info_link(struct gcov_info *info)
226 {
227 list_add_tail(&info->head, &clang_gcov_list);
228 }
229
230 /**
231 * gcov_info_unlink - unlink/remove profiling data set from the list
232 * @prev: previous profiling data set
233 * @info: profiling data set
234 */
235 void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info)
236 {
237 /* Generic code unlinks while iterating. */
238 __list_del_entry(&info->head);
239 }
240
241 /**
242 * gcov_info_within_module - check if a profiling data set belongs to a module
243 * @info: profiling data set
244 * @mod: module
245 *
246 * Returns true if profiling data belongs module, false otherwise.
247 */
248 bool gcov_info_within_module(struct gcov_info *info, struct module *mod)
249 {
250 return within_module((unsigned long)info->filename, mod);
251 }
252
253 /* Symbolic links to be created for each profiling data file. */
254 const struct gcov_link gcov_link[] = {
255 { OBJ_TREE, "gcno" }, /* Link to .gcno file in $(objtree). */
256 { 0, NULL},
257 };
258
259 /**
260 * gcov_info_reset - reset profiling data to zero
261 * @info: profiling data set
262 */
263 void gcov_info_reset(struct gcov_info *info)
264 {
265 struct gcov_fn_info *fn;
266
267 list_for_each_entry(fn, &info->functions, head)
268 memset(fn->counters, 0,
269 sizeof(fn->counters[0]) * fn->num_counters);
270 }
271
272 /**
273 * gcov_info_is_compatible - check if profiling data can be added
274 * @info1: first profiling data set
275 * @info2: second profiling data set
276 *
277 * Returns non-zero if profiling data can be added, zero otherwise.
278 */
279 int gcov_info_is_compatible(struct gcov_info *info1, struct gcov_info *info2)
280 {
281 struct gcov_fn_info *fn_ptr1 = list_first_entry_or_null(
282 &info1->functions, struct gcov_fn_info, head);
283 struct gcov_fn_info *fn_ptr2 = list_first_entry_or_null(
284 &info2->functions, struct gcov_fn_info, head);
285
286 if (info1->checksum != info2->checksum)
287 return false;
288 if (!fn_ptr1)
289 return fn_ptr1 == fn_ptr2;
290 while (!list_is_last(&fn_ptr1->head, &info1->functions) &&
291 !list_is_last(&fn_ptr2->head, &info2->functions)) {
292 if (fn_ptr1->checksum != fn_ptr2->checksum)
293 return false;
294 #if CONFIG_CLANG_VERSION < 110000
295 if (fn_ptr1->use_extra_checksum != fn_ptr2->use_extra_checksum)
296 return false;
297 if (fn_ptr1->use_extra_checksum &&
298 fn_ptr1->cfg_checksum != fn_ptr2->cfg_checksum)
299 return false;
300 #else
301 if (fn_ptr1->cfg_checksum != fn_ptr2->cfg_checksum)
302 return false;
303 #endif
304 fn_ptr1 = list_next_entry(fn_ptr1, head);
305 fn_ptr2 = list_next_entry(fn_ptr2, head);
306 }
307 return list_is_last(&fn_ptr1->head, &info1->functions) &&
308 list_is_last(&fn_ptr2->head, &info2->functions);
309 }
310
311 /**
312 * gcov_info_add - add up profiling data
313 * @dest: profiling data set to which data is added
314 * @source: profiling data set which is added
315 *
316 * Adds profiling counts of @source to @dest.
317 */
318 void gcov_info_add(struct gcov_info *dst, struct gcov_info *src)
319 {
320 struct gcov_fn_info *dfn_ptr;
321 struct gcov_fn_info *sfn_ptr = list_first_entry_or_null(&src->functions,
322 struct gcov_fn_info, head);
323
324 list_for_each_entry(dfn_ptr, &dst->functions, head) {
325 u32 i;
326
327 for (i = 0; i < sfn_ptr->num_counters; i++)
328 dfn_ptr->counters[i] += sfn_ptr->counters[i];
329 }
330 }
331
332 #if CONFIG_CLANG_VERSION < 110000
333 static struct gcov_fn_info *gcov_fn_info_dup(struct gcov_fn_info *fn)
334 {
335 size_t cv_size; /* counter values size */
336 struct gcov_fn_info *fn_dup = kmemdup(fn, sizeof(*fn), GFP_KERNEL);
337
338 if (!fn_dup)
339 return NULL;
340 INIT_LIST_HEAD(&fn_dup->head);
341
342 fn_dup->function_name = kstrdup(fn->function_name, GFP_KERNEL);
343 if (!fn_dup->function_name)
344 goto err_name;
345
346 cv_size = fn->num_counters * sizeof(fn->counters[0]);
347 fn_dup->counters = kvmalloc(cv_size, GFP_KERNEL);
348 if (!fn_dup->counters)
349 goto err_counters;
350 memcpy(fn_dup->counters, fn->counters, cv_size);
351
352 return fn_dup;
353
354 err_counters:
355 kfree(fn_dup->function_name);
356 err_name:
357 kfree(fn_dup);
358 return NULL;
359 }
360 #else
361 static struct gcov_fn_info *gcov_fn_info_dup(struct gcov_fn_info *fn)
362 {
363 size_t cv_size; /* counter values size */
364 struct gcov_fn_info *fn_dup = kmemdup(fn, sizeof(*fn),
365 GFP_KERNEL);
366 if (!fn_dup)
367 return NULL;
368 INIT_LIST_HEAD(&fn_dup->head);
369
370 cv_size = fn->num_counters * sizeof(fn->counters[0]);
371 fn_dup->counters = kvmalloc(cv_size, GFP_KERNEL);
372 if (!fn_dup->counters) {
373 kfree(fn_dup);
374 return NULL;
375 }
376
377 memcpy(fn_dup->counters, fn->counters, cv_size);
378
379 return fn_dup;
380 }
381 #endif
382
383 /**
384 * gcov_info_dup - duplicate profiling data set
385 * @info: profiling data set to duplicate
386 *
387 * Return newly allocated duplicate on success, %NULL on error.
388 */
389 struct gcov_info *gcov_info_dup(struct gcov_info *info)
390 {
391 struct gcov_info *dup;
392 struct gcov_fn_info *fn;
393
394 dup = kmemdup(info, sizeof(*dup), GFP_KERNEL);
395 if (!dup)
396 return NULL;
397 INIT_LIST_HEAD(&dup->head);
398 INIT_LIST_HEAD(&dup->functions);
399 dup->filename = kstrdup(info->filename, GFP_KERNEL);
400 if (!dup->filename)
401 goto err;
402
403 list_for_each_entry(fn, &info->functions, head) {
404 struct gcov_fn_info *fn_dup = gcov_fn_info_dup(fn);
405
406 if (!fn_dup)
407 goto err;
408 list_add_tail(&fn_dup->head, &dup->functions);
409 }
410
411 return dup;
412
413 err:
414 gcov_info_free(dup);
415 return NULL;
416 }
417
418 /**
419 * gcov_info_free - release memory for profiling data set duplicate
420 * @info: profiling data set duplicate to free
421 */
422 #if CONFIG_CLANG_VERSION < 110000
423 void gcov_info_free(struct gcov_info *info)
424 {
425 struct gcov_fn_info *fn, *tmp;
426
427 list_for_each_entry_safe(fn, tmp, &info->functions, head) {
428 kfree(fn->function_name);
429 vfree(fn->counters);
430 list_del(&fn->head);
431 kfree(fn);
432 }
433 kfree(info->filename);
434 kfree(info);
435 }
436 #else
437 void gcov_info_free(struct gcov_info *info)
438 {
439 struct gcov_fn_info *fn, *tmp;
440
441 list_for_each_entry_safe(fn, tmp, &info->functions, head) {
442 kvfree(fn->counters);
443 list_del(&fn->head);
444 kfree(fn);
445 }
446 kfree(info->filename);
447 kfree(info);
448 }
449 #endif
450
451 /**
452 * convert_to_gcda - convert profiling data set to gcda file format
453 * @buffer: the buffer to store file data or %NULL if no data should be stored
454 * @info: profiling data set to be converted
455 *
456 * Returns the number of bytes that were/would have been stored into the buffer.
457 */
458 size_t convert_to_gcda(char *buffer, struct gcov_info *info)
459 {
460 struct gcov_fn_info *fi_ptr;
461 size_t pos = 0;
462
463 /* File header. */
464 pos += store_gcov_u32(buffer, pos, GCOV_DATA_MAGIC);
465 pos += store_gcov_u32(buffer, pos, info->version);
466 pos += store_gcov_u32(buffer, pos, info->checksum);
467
468 list_for_each_entry(fi_ptr, &info->functions, head) {
469 u32 i;
470
471 pos += store_gcov_u32(buffer, pos, GCOV_TAG_FUNCTION);
472 #if CONFIG_CLANG_VERSION < 110000
473 pos += store_gcov_u32(buffer, pos,
474 fi_ptr->use_extra_checksum ? 3 : 2);
475 #else
476 pos += store_gcov_u32(buffer, pos, 3);
477 #endif
478 pos += store_gcov_u32(buffer, pos, fi_ptr->ident);
479 pos += store_gcov_u32(buffer, pos, fi_ptr->checksum);
480 #if CONFIG_CLANG_VERSION < 110000
481 if (fi_ptr->use_extra_checksum)
482 pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum);
483 #else
484 pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum);
485 #endif
486
487 pos += store_gcov_u32(buffer, pos, GCOV_TAG_COUNTER_BASE);
488 pos += store_gcov_u32(buffer, pos, fi_ptr->num_counters * 2);
489 for (i = 0; i < fi_ptr->num_counters; i++)
490 pos += store_gcov_u64(buffer, pos, fi_ptr->counters[i]);
491 }
492
493 return pos;
494 }