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
4949 mutex_unlock(&gcov_lock);
5050 }
5151
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+ */
63+size_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+ */
87+size_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+
52101 #ifdef CONFIG_MODULES
53102 /* Update list and generate events when modules are unloaded. */
54103 static int gcov_module_notifier(struct notifier_block *nb, unsigned long event,
kernel/gcov/clang.c+1−166
@@ -48,7 +48,6 @@ · 47 unmodified lines
4848 #include <linux/list.h>
4949 #include <linux/printk.h>
5050 #include <linux/ratelimit.h>
51−#include <linux/seq_file.h>
5251 #include <linux/slab.h>
5352 #include <linux/vmalloc.h>
5453 #include "gcov.h"
@@ -449,71 +448,6 @@ void gcov_info_free(struct gcov_info *info) · 394 unmodified lines
449448 }
450449 #endif
451450
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− */
461−struct 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− */
479−static 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− */
503−static 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−
517451 /**
518452 * convert_to_gcda - convert profiling data set to gcda file format
519453 * @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
521455 *
522456 * Returns the number of bytes that were/would have been stored into the buffer.
523457 */
524−static size_t convert_to_gcda(char *buffer, struct gcov_info *info)
458+size_t convert_to_gcda(char *buffer, struct gcov_info *info)
525459 {
526460 struct gcov_fn_info *fi_ptr;
527461 size_t pos = 0;
@@ -558,102 +492,3 @@ static size_t convert_to_gcda(char *buffer, struct gcov_info *info) · 30 unmodified lines
558492
559493 return pos;
560494 }
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− */
568−struct 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−
587−err_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− */
597−void 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− */
607−struct 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− */
616−void 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− */
627−int 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− */
645−int 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
2626 #include <linux/slab.h>
2727 #include <linux/mutex.h>
2828 #include <linux/seq_file.h>
29+#include <linux/vmalloc.h>
2930 #include "gcov.h"
3031
3132 /**
@@ -85,6 +86,121 @@ static int __init gcov_persist_setup(char *str) · 53 unmodified lines
8586 }
8687 __setup("gcov_persist=", gcov_persist_setup);
8788
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+ */
98+struct 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+ */
111+static 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+
130+err_free:
131+ kfree(iter);
132+ return NULL;
133+}
134+
135+
136+/**
137+ * gcov_iter_free - free iterator data
138+ * @iter: file iterator
139+ */
140+static 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+ */
150+static 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+ */
159+static 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+ */
170+static 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+ */
188+static 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+
88204 /*
89205 * seq_file.start() implementation for gcov data files. Note that the
90206 * 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
1515 #include <linux/errno.h>
1616 #include <linux/slab.h>
1717 #include <linux/string.h>
18−#include <linux/seq_file.h>
1918 #include <linux/vmalloc.h>
2019 #include "gcov.h"
2120
@@ -363,71 +362,6 @@ free_info: · 341 unmodified lines
363362 kfree(info);
364363 }
365364
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− */
375−struct 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− */
393−static 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− */
417−static 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−
431365 /**
432366 * convert_to_gcda - convert profiling data set to gcda file format
433367 * @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
435369 *
436370 * Returns the number of bytes that were/would have been stored into the buffer.
437371 */
438−static size_t convert_to_gcda(char *buffer, struct gcov_info *info)
372+size_t convert_to_gcda(char *buffer, struct gcov_info *info)
439373 {
440374 struct gcov_fn_info *fi_ptr;
441375 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
481415
482416 return pos;
483417 }
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− */
491−struct 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−
510−err_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− */
520−void 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− */
530−struct 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− */
539−void 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− */
550−int 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− */
568−int 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
4848 void gcov_info_link(struct gcov_info *info);
4949 void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info);
5050 bool gcov_info_within_module(struct gcov_info *info, struct module *mod);
51+size_t convert_to_gcda(char *buffer, struct gcov_info *info);
5152
5253 /* Base interface. */
5354 enum gcov_action {
@@ -58,16 +59,9 @@ enum gcov_action { · 4 unmodified lines
5859 void gcov_event(enum gcov_action action, struct gcov_info *info);
5960 void gcov_enable_events(void);
6061
61−/* Iterator control. */
62−struct seq_file;
63−struct gcov_iterator;
64−
65−struct gcov_iterator *gcov_iter_new(struct gcov_info *info);
66−void gcov_iter_free(struct gcov_iterator *iter);
67−void gcov_iter_start(struct gcov_iterator *iter);
68−int gcov_iter_next(struct gcov_iterator *iter);
69−int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq);
70−struct gcov_info *gcov_iter_get_info(struct gcov_iterator *iter);
62+/* writing helpers */
63+size_t store_gcov_u32(void *buffer, size_t off, u32 v);
64+size_t store_gcov_u64(void *buffer, size_t off, u64 v);
7165
7266 /* gcov_info control. */
7367 void 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