History

gcov: combine common code

There's a lot of duplicated code between gcc and clang implementations, move it over to fs.c to simplify the code, there's no reason to believe that for small data like this one would not just implement the simple convert_to_gcda() function.

Johannes Berg committed 5 years ago

Commit 7a1d55b1 parent b2075db5 files · +171 −342Browse files

Showing the changes to kernel (5 of 5 files). Show all

Unified · Split

5 files
  1. kernel/gcov/base.c +49 −0
  2. kernel/gcov/clang.c +1 −166
  3. kernel/gcov/fs.c +116 −0
  4. kernel/gcov/gcc_4_7.c +1 −166
  5. kernel/gcov/gcov.h +4 −10
kernel/gcov/base.c+49−0
@@ -49,6 +49,55 @@ void gcov_enable_events(void) · 48 unmodified lines
49 mutex_unlock(&gcov_lock);49 mutex_unlock(&gcov_lock);
50}50}
51 51
52/**
53 * store_gcov_u32 - store 32 bit number in gcov format to buffer
54 * @buffer: target buffer or NULL
55 * @off: offset into the buffer
56 * @v: value to be stored
57 *
58 * Number format defined by gcc: numbers are recorded in the 32 bit
59 * unsigned binary form of the endianness of the machine generating the
60 * file. Returns the number of bytes stored. If @buffer is %NULL, doesn't
61 * store anything.
62 */
63size_t store_gcov_u32(void *buffer, size_t off, u32 v)
64{
65 u32 *data;
66
67 if (buffer) {
68 data = buffer + off;
69 *data = v;
70 }
71
72 return sizeof(*data);
73}
74
75/**
76 * store_gcov_u64 - store 64 bit number in gcov format to buffer
77 * @buffer: target buffer or NULL
78 * @off: offset into the buffer
79 * @v: value to be stored
80 *
81 * Number format defined by gcc: numbers are recorded in the 32 bit
82 * unsigned binary form of the endianness of the machine generating the
83 * file. 64 bit numbers are stored as two 32 bit numbers, the low part
84 * first. Returns the number of bytes stored. If @buffer is %NULL, doesn't store
85 * anything.
86 */
87size_t store_gcov_u64(void *buffer, size_t off, u64 v)
88{
89 u32 *data;
90
91 if (buffer) {
92 data = buffer + off;
93
94 data[0] = (v & 0xffffffffUL);
95 data[1] = (v >> 32);
96 }
97
98 return sizeof(*data) * 2;
99}
100
52#ifdef CONFIG_MODULES101#ifdef CONFIG_MODULES
53/* Update list and generate events when modules are unloaded. */102/* Update list and generate events when modules are unloaded. */
54static int gcov_module_notifier(struct notifier_block *nb, unsigned long event,103static int gcov_module_notifier(struct notifier_block *nb, unsigned long event,
kernel/gcov/clang.c+1−166
@@ -48,7 +48,6 @@ · 47 unmodified lines
48#include <linux/list.h>48#include <linux/list.h>
49#include <linux/printk.h>49#include <linux/printk.h>
50#include <linux/ratelimit.h>50#include <linux/ratelimit.h>
51#include <linux/seq_file.h>
52#include <linux/slab.h>51#include <linux/slab.h>
53#include <linux/vmalloc.h>52#include <linux/vmalloc.h>
54#include "gcov.h"53#include "gcov.h"
@@ -449,71 +448,6 @@ void gcov_info_free(struct gcov_info *info) · 394 unmodified lines
449}448}
450#endif449#endif
451 450
452#define ITER_STRIDE PAGE_SIZE
453
454/**
455 * struct gcov_iterator - specifies current file position in logical records
456 * @info: associated profiling data
457 * @buffer: buffer containing file data
458 * @size: size of buffer
459 * @pos: current position in file
460 */
461struct gcov_iterator {
462 struct gcov_info *info;
463 void *buffer;
464 size_t size;
465 loff_t pos;
466};
467
468/**
469 * store_gcov_u32 - store 32 bit number in gcov format to buffer
470 * @buffer: target buffer or NULL
471 * @off: offset into the buffer
472 * @v: value to be stored
473 *
474 * Number format defined by gcc: numbers are recorded in the 32 bit
475 * unsigned binary form of the endianness of the machine generating the
476 * file. Returns the number of bytes stored. If @buffer is %NULL, doesn't
477 * store anything.
478 */
479static size_t store_gcov_u32(void *buffer, size_t off, u32 v)
480{
481 u32 *data;
482
483 if (buffer) {
484 data = buffer + off;
485 *data = v;
486 }
487
488 return sizeof(*data);
489}
490
491/**
492 * store_gcov_u64 - store 64 bit number in gcov format to buffer
493 * @buffer: target buffer or NULL
494 * @off: offset into the buffer
495 * @v: value to be stored
496 *
497 * Number format defined by gcc: numbers are recorded in the 32 bit
498 * unsigned binary form of the endianness of the machine generating the
499 * file. 64 bit numbers are stored as two 32 bit numbers, the low part
500 * first. Returns the number of bytes stored. If @buffer is %NULL, doesn't store
501 * anything.
502 */
503static size_t store_gcov_u64(void *buffer, size_t off, u64 v)
504{
505 u32 *data;
506
507 if (buffer) {
508 data = buffer + off;
509
510 data[0] = (v & 0xffffffffUL);
511 data[1] = (v >> 32);
512 }
513
514 return sizeof(*data) * 2;
515}
516
517/**451/**
518 * convert_to_gcda - convert profiling data set to gcda file format452 * convert_to_gcda - convert profiling data set to gcda file format
519 * @buffer: the buffer to store file data or %NULL if no data should be stored453 * @buffer: the buffer to store file data or %NULL if no data should be stored
@@ -521,7 +455,7 @@ static size_t store_gcov_u64(void *buffer, size_t off, u64 v) · 1 unmodified line
521 *455 *
522 * Returns the number of bytes that were/would have been stored into the buffer.456 * Returns the number of bytes that were/would have been stored into the buffer.
523 */457 */
524static size_t convert_to_gcda(char *buffer, struct gcov_info *info)458size_t convert_to_gcda(char *buffer, struct gcov_info *info)
525{459{
526 struct gcov_fn_info *fi_ptr;460 struct gcov_fn_info *fi_ptr;
527 size_t pos = 0;461 size_t pos = 0;
@@ -558,102 +492,3 @@ static size_t convert_to_gcda(char *buffer, struct gcov_info *info) · 30 unmodified lines
558 492
559 return pos;493 return pos;
560}494}
561
562/**
563 * gcov_iter_new - allocate and initialize profiling data iterator
564 * @info: profiling data set to be iterated
565 *
566 * Return file iterator on success, %NULL otherwise.
567 */
568struct gcov_iterator *gcov_iter_new(struct gcov_info *info)
569{
570 struct gcov_iterator *iter;
571
572 iter = kzalloc(sizeof(struct gcov_iterator), GFP_KERNEL);
573 if (!iter)
574 goto err_free;
575
576 iter->info = info;
577 /* Dry-run to get the actual buffer size. */
578 iter->size = convert_to_gcda(NULL, info);
579 iter->buffer = vmalloc(iter->size);
580 if (!iter->buffer)
581 goto err_free;
582
583 convert_to_gcda(iter->buffer, info);
584
585 return iter;
586
587err_free:
588 kfree(iter);
589 return NULL;
590}
591
592
593/**
594 * gcov_iter_get_info - return profiling data set for given file iterator
595 * @iter: file iterator
596 */
597void gcov_iter_free(struct gcov_iterator *iter)
598{
599 vfree(iter->buffer);
600 kfree(iter);
601}
602
603/**
604 * gcov_iter_get_info - return profiling data set for given file iterator
605 * @iter: file iterator
606 */
607struct gcov_info *gcov_iter_get_info(struct gcov_iterator *iter)
608{
609 return iter->info;
610}
611
612/**
613 * gcov_iter_start - reset file iterator to starting position
614 * @iter: file iterator
615 */
616void gcov_iter_start(struct gcov_iterator *iter)
617{
618 iter->pos = 0;
619}
620
621/**
622 * gcov_iter_next - advance file iterator to next logical record
623 * @iter: file iterator
624 *
625 * Return zero if new position is valid, non-zero if iterator has reached end.
626 */
627int gcov_iter_next(struct gcov_iterator *iter)
628{
629 if (iter->pos < iter->size)
630 iter->pos += ITER_STRIDE;
631
632 if (iter->pos >= iter->size)
633 return -EINVAL;
634
635 return 0;
636}
637
638/**
639 * gcov_iter_write - write data for current pos to seq_file
640 * @iter: file iterator
641 * @seq: seq_file handle
642 *
643 * Return zero on success, non-zero otherwise.
644 */
645int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq)
646{
647 size_t len;
648
649 if (iter->pos >= iter->size)
650 return -EINVAL;
651
652 len = ITER_STRIDE;
653 if (iter->pos + len > iter->size)
654 len = iter->size - iter->pos;
655
656 seq_write(seq, iter->buffer + iter->pos, len);
657
658 return 0;
659}
kernel/gcov/fs.c+116−0
@@ -26,6 +26,7 @@ · 25 unmodified lines
26#include <linux/slab.h>26#include <linux/slab.h>
27#include <linux/mutex.h>27#include <linux/mutex.h>
28#include <linux/seq_file.h>28#include <linux/seq_file.h>
29#include <linux/vmalloc.h>
29#include "gcov.h"30#include "gcov.h"
30 31
31/**32/**
@@ -85,6 +86,121 @@ static int __init gcov_persist_setup(char *str) · 53 unmodified lines
85}86}
86__setup("gcov_persist=", gcov_persist_setup);87__setup("gcov_persist=", gcov_persist_setup);
87 88
89#define ITER_STRIDE PAGE_SIZE
90
91/**
92 * struct gcov_iterator - specifies current file position in logical records
93 * @info: associated profiling data
94 * @buffer: buffer containing file data
95 * @size: size of buffer
96 * @pos: current position in file
97 */
98struct gcov_iterator {
99 struct gcov_info *info;
100 void *buffer;
101 size_t size;
102 loff_t pos;
103};
104
105/**
106 * gcov_iter_new - allocate and initialize profiling data iterator
107 * @info: profiling data set to be iterated
108 *
109 * Return file iterator on success, %NULL otherwise.
110 */
111static struct gcov_iterator *gcov_iter_new(struct gcov_info *info)
112{
113 struct gcov_iterator *iter;
114
115 iter = kzalloc(sizeof(struct gcov_iterator), GFP_KERNEL);
116 if (!iter)
117 goto err_free;
118
119 iter->info = info;
120 /* Dry-run to get the actual buffer size. */
121 iter->size = convert_to_gcda(NULL, info);
122 iter->buffer = vmalloc(iter->size);
123 if (!iter->buffer)
124 goto err_free;
125
126 convert_to_gcda(iter->buffer, info);
127
128 return iter;
129
130err_free:
131 kfree(iter);
132 return NULL;
133}
134
135
136/**
137 * gcov_iter_free - free iterator data
138 * @iter: file iterator
139 */
140static void gcov_iter_free(struct gcov_iterator *iter)
141{
142 vfree(iter->buffer);
143 kfree(iter);
144}
145
146/**
147 * gcov_iter_get_info - return profiling data set for given file iterator
148 * @iter: file iterator
149 */
150static struct gcov_info *gcov_iter_get_info(struct gcov_iterator *iter)
151{
152 return iter->info;
153}
154
155/**
156 * gcov_iter_start - reset file iterator to starting position
157 * @iter: file iterator
158 */
159static void gcov_iter_start(struct gcov_iterator *iter)
160{
161 iter->pos = 0;
162}
163
164/**
165 * gcov_iter_next - advance file iterator to next logical record
166 * @iter: file iterator
167 *
168 * Return zero if new position is valid, non-zero if iterator has reached end.
169 */
170static int gcov_iter_next(struct gcov_iterator *iter)
171{
172 if (iter->pos < iter->size)
173 iter->pos += ITER_STRIDE;
174
175 if (iter->pos >= iter->size)
176 return -EINVAL;
177
178 return 0;
179}
180
181/**
182 * gcov_iter_write - write data for current pos to seq_file
183 * @iter: file iterator
184 * @seq: seq_file handle
185 *
186 * Return zero on success, non-zero otherwise.
187 */
188static int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq)
189{
190 size_t len;
191
192 if (iter->pos >= iter->size)
193 return -EINVAL;
194
195 len = ITER_STRIDE;
196 if (iter->pos + len > iter->size)
197 len = iter->size - iter->pos;
198
199 seq_write(seq, iter->buffer + iter->pos, len);
200
201 return 0;
202}
203
88/*204/*
89 * seq_file.start() implementation for gcov data files. Note that the205 * seq_file.start() implementation for gcov data files. Note that the
90 * gcov_iterator interface is designed to be more restrictive than seq_file206 * gcov_iterator interface is designed to be more restrictive than seq_file
kernel/gcov/gcc_4_7.c+1−166
@@ -15,7 +15,6 @@ · 14 unmodified lines
15#include <linux/errno.h>15#include <linux/errno.h>
16#include <linux/slab.h>16#include <linux/slab.h>
17#include <linux/string.h>17#include <linux/string.h>
18#include <linux/seq_file.h>
19#include <linux/vmalloc.h>18#include <linux/vmalloc.h>
20#include "gcov.h"19#include "gcov.h"
21 20
@@ -363,71 +362,6 @@ free_info: · 341 unmodified lines
363 kfree(info);362 kfree(info);
364}363}
365 364
366#define ITER_STRIDE PAGE_SIZE
367
368/**
369 * struct gcov_iterator - specifies current file position in logical records
370 * @info: associated profiling data
371 * @buffer: buffer containing file data
372 * @size: size of buffer
373 * @pos: current position in file
374 */
375struct gcov_iterator {
376 struct gcov_info *info;
377 void *buffer;
378 size_t size;
379 loff_t pos;
380};
381
382/**
383 * store_gcov_u32 - store 32 bit number in gcov format to buffer
384 * @buffer: target buffer or NULL
385 * @off: offset into the buffer
386 * @v: value to be stored
387 *
388 * Number format defined by gcc: numbers are recorded in the 32 bit
389 * unsigned binary form of the endianness of the machine generating the
390 * file. Returns the number of bytes stored. If @buffer is %NULL, doesn't
391 * store anything.
392 */
393static size_t store_gcov_u32(void *buffer, size_t off, u32 v)
394{
395 u32 *data;
396
397 if (buffer) {
398 data = buffer + off;
399 *data = v;
400 }
401
402 return sizeof(*data);
403}
404
405/**
406 * store_gcov_u64 - store 64 bit number in gcov format to buffer
407 * @buffer: target buffer or NULL
408 * @off: offset into the buffer
409 * @v: value to be stored
410 *
411 * Number format defined by gcc: numbers are recorded in the 32 bit
412 * unsigned binary form of the endianness of the machine generating the
413 * file. 64 bit numbers are stored as two 32 bit numbers, the low part
414 * first. Returns the number of bytes stored. If @buffer is %NULL, doesn't store
415 * anything.
416 */
417static size_t store_gcov_u64(void *buffer, size_t off, u64 v)
418{
419 u32 *data;
420
421 if (buffer) {
422 data = buffer + off;
423
424 data[0] = (v & 0xffffffffUL);
425 data[1] = (v >> 32);
426 }
427
428 return sizeof(*data) * 2;
429}
430
431/**365/**
432 * convert_to_gcda - convert profiling data set to gcda file format366 * convert_to_gcda - convert profiling data set to gcda file format
433 * @buffer: the buffer to store file data or %NULL if no data should be stored367 * @buffer: the buffer to store file data or %NULL if no data should be stored
@@ -435,7 +369,7 @@ static size_t store_gcov_u64(void *buffer, size_t off, u64 v) · 1 unmodified line
435 *369 *
436 * Returns the number of bytes that were/would have been stored into the buffer.370 * Returns the number of bytes that were/would have been stored into the buffer.
437 */371 */
438static size_t convert_to_gcda(char *buffer, struct gcov_info *info)372size_t convert_to_gcda(char *buffer, struct gcov_info *info)
439{373{
440 struct gcov_fn_info *fi_ptr;374 struct gcov_fn_info *fi_ptr;
441 struct gcov_ctr_info *ci_ptr;375 struct gcov_ctr_info *ci_ptr;
@@ -481,102 +415,3 @@ static size_t convert_to_gcda(char *buffer, struct gcov_info *info) · 39 unmodified lines
481 415
482 return pos;416 return pos;
483}417}
484
485/**
486 * gcov_iter_new - allocate and initialize profiling data iterator
487 * @info: profiling data set to be iterated
488 *
489 * Return file iterator on success, %NULL otherwise.
490 */
491struct gcov_iterator *gcov_iter_new(struct gcov_info *info)
492{
493 struct gcov_iterator *iter;
494
495 iter = kzalloc(sizeof(struct gcov_iterator), GFP_KERNEL);
496 if (!iter)
497 goto err_free;
498
499 iter->info = info;
500 /* Dry-run to get the actual buffer size. */
501 iter->size = convert_to_gcda(NULL, info);
502 iter->buffer = vmalloc(iter->size);
503 if (!iter->buffer)
504 goto err_free;
505
506 convert_to_gcda(iter->buffer, info);
507
508 return iter;
509
510err_free:
511 kfree(iter);
512 return NULL;
513}
514
515
516/**
517 * gcov_iter_get_info - return profiling data set for given file iterator
518 * @iter: file iterator
519 */
520void gcov_iter_free(struct gcov_iterator *iter)
521{
522 vfree(iter->buffer);
523 kfree(iter);
524}
525
526/**
527 * gcov_iter_get_info - return profiling data set for given file iterator
528 * @iter: file iterator
529 */
530struct gcov_info *gcov_iter_get_info(struct gcov_iterator *iter)
531{
532 return iter->info;
533}
534
535/**
536 * gcov_iter_start - reset file iterator to starting position
537 * @iter: file iterator
538 */
539void gcov_iter_start(struct gcov_iterator *iter)
540{
541 iter->pos = 0;
542}
543
544/**
545 * gcov_iter_next - advance file iterator to next logical record
546 * @iter: file iterator
547 *
548 * Return zero if new position is valid, non-zero if iterator has reached end.
549 */
550int gcov_iter_next(struct gcov_iterator *iter)
551{
552 if (iter->pos < iter->size)
553 iter->pos += ITER_STRIDE;
554
555 if (iter->pos >= iter->size)
556 return -EINVAL;
557
558 return 0;
559}
560
561/**
562 * gcov_iter_write - write data for current pos to seq_file
563 * @iter: file iterator
564 * @seq: seq_file handle
565 *
566 * Return zero on success, non-zero otherwise.
567 */
568int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq)
569{
570 size_t len;
571
572 if (iter->pos >= iter->size)
573 return -EINVAL;
574
575 len = ITER_STRIDE;
576 if (iter->pos + len > iter->size)
577 len = iter->size - iter->pos;
578
579 seq_write(seq, iter->buffer + iter->pos, len);
580
581 return 0;
582}
kernel/gcov/gcov.h+4−10
@@ -48,6 +48,7 @@ struct gcov_info *gcov_info_next(struct gcov_info *info); · 47 unmodified lines
48void gcov_info_link(struct gcov_info *info);48void gcov_info_link(struct gcov_info *info);
49void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info);49void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info);
50bool gcov_info_within_module(struct gcov_info *info, struct module *mod);50bool gcov_info_within_module(struct gcov_info *info, struct module *mod);
51size_t convert_to_gcda(char *buffer, struct gcov_info *info);
51 52
52/* Base interface. */53/* Base interface. */
53enum gcov_action {54enum gcov_action {
@@ -58,16 +59,9 @@ enum gcov_action { · 4 unmodified lines
58void gcov_event(enum gcov_action action, struct gcov_info *info);59void gcov_event(enum gcov_action action, struct gcov_info *info);
59void gcov_enable_events(void);60void gcov_enable_events(void);
60 61
61/* Iterator control. */62/* writing helpers */
62struct seq_file;63size_t store_gcov_u32(void *buffer, size_t off, u32 v);
63struct gcov_iterator;64size_t store_gcov_u64(void *buffer, size_t off, u64 v);
64
65struct gcov_iterator *gcov_iter_new(struct gcov_info *info);
66void gcov_iter_free(struct gcov_iterator *iter);
67void gcov_iter_start(struct gcov_iterator *iter);
68int gcov_iter_next(struct gcov_iterator *iter);
69int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq);
70struct gcov_info *gcov_iter_get_info(struct gcov_iterator *iter);
71 65
72/* gcov_info control. */66/* gcov_info control. */
73void gcov_info_reset(struct gcov_info *info);67void gcov_info_reset(struct gcov_info *info);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t