1
2
3
4
5
6
7
8
9
10
11
12
13#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/kallsyms.h>
19#include <linux/types.h>
20#include <linux/mutex.h>
21#include <linux/proc_fs.h>
22#include <linux/seq_file.h>
23#include <linux/list.h>
24#include <linux/sysctl.h>
25#include <linux/ctype.h>
26#include <linux/string.h>
27#include <linux/string_helpers.h>
28#include <linux/uaccess.h>
29#include <linux/dynamic_debug.h>
30#include <linux/debugfs.h>
31#include <linux/slab.h>
32#include <linux/jump_label.h>
33#include <linux/hardirq.h>
34#include <linux/sched.h>
35#include <linux/device.h>
36#include <linux/netdevice.h>
37
38extern struct _ddebug __start___verbose[];
39extern struct _ddebug __stop___verbose[];
40
41struct ddebug_table {
42 struct list_head link;
43 char *mod_name;
44 unsigned int num_ddebugs;
45 struct _ddebug *ddebugs;
46};
47
48struct ddebug_query {
49 const char *filename;
50 const char *module;
51 const char *function;
52 const char *format;
53 unsigned int first_lineno, last_lineno;
54};
55
56struct ddebug_iter {
57 struct ddebug_table *table;
58 unsigned int idx;
59};
60
61static DEFINE_MUTEX(ddebug_lock);
62static LIST_HEAD(ddebug_tables);
63static int verbose;
64module_param(verbose, int, 0644);
65
66
67static inline const char *trim_prefix(const char *path)
68{
69 int skip = strlen(__FILE__) - strlen("lib/dynamic_debug.c");
70
71 if (strncmp(path, __FILE__, skip))
72 skip = 0;
73
74 return path + skip;
75}
76
77static struct { unsigned flag:8; char opt_char; } opt_array[] = {
78 { _DPRINTK_FLAGS_PRINT, 'p' },
79 { _DPRINTK_FLAGS_INCL_MODNAME, 'm' },
80 { _DPRINTK_FLAGS_INCL_FUNCNAME, 'f' },
81 { _DPRINTK_FLAGS_INCL_LINENO, 'l' },
82 { _DPRINTK_FLAGS_INCL_TID, 't' },
83 { _DPRINTK_FLAGS_NONE, '_' },
84};
85
86
87static char *ddebug_describe_flags(struct _ddebug *dp, char *buf,
88 size_t maxlen)
89{
90 char *p = buf;
91 int i;
92
93 BUG_ON(maxlen < 6);
94 for (i = 0; i < ARRAY_SIZE(opt_array); ++i)
95 if (dp->flags & opt_array[i].flag)
96 *p++ = opt_array[i].opt_char;
97 if (p == buf)
98 *p++ = '_';
99 *p = '\0';
100
101 return buf;
102}
103
104#define vpr_info(fmt, ...) \
105do { \
106 if (verbose) \
107 pr_info(fmt, ##__VA_ARGS__); \
108} while (0)
109
110static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
111{
112
113 int fmtlen = 0;
114
115 if (query->format) {
116 fmtlen = strlen(query->format);
117 while (fmtlen && query->format[fmtlen - 1] == '\n')
118 fmtlen--;
119 }
120
121 vpr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u\n",
122 msg,
123 query->function ? query->function : "",
124 query->filename ? query->filename : "",
125 query->module ? query->module : "",
126 fmtlen, query->format ? query->format : "",
127 query->first_lineno, query->last_lineno);
128}
129
130
131
132
133
134
135
136static int ddebug_change(const struct ddebug_query *query,
137 unsigned int flags, unsigned int mask)
138{
139 int i;
140 struct ddebug_table *dt;
141 unsigned int newflags;
142 unsigned int nfound = 0;
143 char flagbuf[10];
144
145
146 mutex_lock(&ddebug_lock);
147 list_for_each_entry(dt, &ddebug_tables, link) {
148
149
150 if (query->module && strcmp(query->module, dt->mod_name))
151 continue;
152
153 for (i = 0; i < dt->num_ddebugs; i++) {
154 struct _ddebug *dp = &dt->ddebugs[i];
155
156
157 if (query->filename &&
158 strcmp(query->filename, dp->filename) &&
159 strcmp(query->filename, kbasename(dp->filename)) &&
160 strcmp(query->filename, trim_prefix(dp->filename)))
161 continue;
162
163
164 if (query->function &&
165 strcmp(query->function, dp->function))
166 continue;
167
168
169 if (query->format &&
170 !strstr(dp->format, query->format))
171 continue;
172
173
174 if (query->first_lineno &&
175 dp->lineno < query->first_lineno)
176 continue;
177 if (query->last_lineno &&
178 dp->lineno > query->last_lineno)
179 continue;
180
181 nfound++;
182
183 newflags = (dp->flags & mask) | flags;
184 if (newflags == dp->flags)
185 continue;
186 dp->flags = newflags;
187 vpr_info("changed %s:%d [%s]%s =%s\n",
188 trim_prefix(dp->filename), dp->lineno,
189 dt->mod_name, dp->function,
190 ddebug_describe_flags(dp, flagbuf,
191 sizeof(flagbuf)));
192 }
193 }
194 mutex_unlock(&ddebug_lock);
195
196 if (!nfound && verbose)
197 pr_info("no matches for query\n");
198
199 return nfound;
200}
201
202
203
204
205
206
207
208static int ddebug_tokenize(char *buf, char *words[], int maxwords)
209{
210 int nwords = 0;
211
212 while (*buf) {
213 char *end;
214
215
216 buf = skip_spaces(buf);
217 if (!*buf)
218 break;
219 if (*buf == '#')
220 break;
221
222
223 if (*buf == '"' || *buf == '\'') {
224 int quote = *buf++;
225 for (end = buf; *end && *end != quote; end++)
226 ;
227 if (!*end) {
228 pr_err("unclosed quote: %s\n", buf);
229 return -EINVAL;
230 }
231 } else {
232 for (end = buf; *end && !isspace(*end); end++)
233 ;
234 BUG_ON(end == buf);
235 }
236
237
238 if (nwords == maxwords) {
239 pr_err("too many words, legal max <=%d\n", maxwords);
240 return -EINVAL;
241 }
242 if (*end)
243 *end++ = '\0';
244 words[nwords++] = buf;
245 buf = end;
246 }
247
248 if (verbose) {
249 int i;
250 pr_info("split into words:");
251 for (i = 0; i < nwords; i++)
252 pr_cont(" \"%s\"", words[i]);
253 pr_cont("\n");
254 }
255
256 return nwords;
257}
258
259
260
261
262
263
264static inline int parse_lineno(const char *str, unsigned int *val)
265{
266 char *end = NULL;
267 BUG_ON(str == NULL);
268 if (*str == '\0') {
269 *val = 0;
270 return 0;
271 }
272 *val = simple_strtoul(str, &end, 10);
273 if (end == NULL || end == str || *end != '\0') {
274 pr_err("bad line-number: %s\n", str);
275 return -EINVAL;
276 }
277 return 0;
278}
279
280static int check_set(const char **dest, char *src, char *name)
281{
282 int rc = 0;
283
284 if (*dest) {
285 rc = -EINVAL;
286 pr_err("match-spec:%s val:%s overridden by %s\n",
287 name, *dest, src);
288 }
289 *dest = src;
290 return rc;
291}
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308static int ddebug_parse_query(char *words[], int nwords,
309 struct ddebug_query *query, const char *modname)
310{
311 unsigned int i;
312 int rc;
313
314
315 if (nwords % 2 != 0) {
316 pr_err("expecting pairs of match-spec <value>\n");
317 return -EINVAL;
318 }
319 memset(query, 0, sizeof(*query));
320
321 if (modname)
322
323 query->module = modname;
324
325 for (i = 0; i < nwords; i += 2) {
326 if (!strcmp(words[i], "func")) {
327 rc = check_set(&query->function, words[i+1], "func");
328 } else if (!strcmp(words[i], "file")) {
329 rc = check_set(&query->filename, words[i+1], "file");
330 } else if (!strcmp(words[i], "module")) {
331 rc = check_set(&query->module, words[i+1], "module");
332 } else if (!strcmp(words[i], "format")) {
333 string_unescape_inplace(words[i+1], UNESCAPE_SPACE |
334 UNESCAPE_OCTAL |
335 UNESCAPE_SPECIAL);
336 rc = check_set(&query->format, words[i+1], "format");
337 } else if (!strcmp(words[i], "line")) {
338 char *first = words[i+1];
339 char *last = strchr(first, '-');
340 if (query->first_lineno || query->last_lineno) {
341 pr_err("match-spec: line used 2x\n");
342 return -EINVAL;
343 }
344 if (last)
345 *last++ = '\0';
346 if (parse_lineno(first, &query->first_lineno) < 0) {
347 pr_err("line-number is <0\n");
348 return -EINVAL;
349 }
350 if (last) {
351
352 if (parse_lineno(last, &query->last_lineno)
353 < query->first_lineno) {
354 pr_err("last-line:%d < 1st-line:%d\n",
355 query->last_lineno,
356 query->first_lineno);
357 return -EINVAL;
358 }
359 } else {
360 query->last_lineno = query->first_lineno;
361 }
362 } else {
363 pr_err("unknown keyword \"%s\"\n", words[i]);
364 return -EINVAL;
365 }
366 if (rc)
367 return rc;
368 }
369 vpr_info_dq(query, "parsed");
370 return 0;
371}
372
373
374
375
376
377
378
379static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
380 unsigned int *maskp)
381{
382 unsigned flags = 0;
383 int op = '=', i;
384
385 switch (*str) {
386 case '+':
387 case '-':
388 case '=':
389 op = *str++;
390 break;
391 default:
392 pr_err("bad flag-op %c, at start of %s\n", *str, str);
393 return -EINVAL;
394 }
395 vpr_info("op='%c'\n", op);
396
397 for (; *str ; ++str) {
398 for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) {
399 if (*str == opt_array[i].opt_char) {
400 flags |= opt_array[i].flag;
401 break;
402 }
403 }
404 if (i < 0) {
405 pr_err("unknown flag '%c' in \"%s\"\n", *str, str);
406 return -EINVAL;
407 }
408 }
409 vpr_info("flags=0x%x\n", flags);
410
411
412 switch (op) {
413 case '=':
414 *maskp = 0;
415 *flagsp = flags;
416 break;
417 case '+':
418 *maskp = ~0U;
419 *flagsp = flags;
420 break;
421 case '-':
422 *maskp = ~flags;
423 *flagsp = 0;
424 break;
425 }
426 vpr_info("*flagsp=0x%x *maskp=0x%x\n", *flagsp, *maskp);
427 return 0;
428}
429
430static int ddebug_exec_query(char *query_string, const char *modname)
431{
432 unsigned int flags = 0, mask = 0;
433 struct ddebug_query query;
434#define MAXWORDS 9
435 int nwords, nfound;
436 char *words[MAXWORDS];
437
438 nwords = ddebug_tokenize(query_string, words, MAXWORDS);
439 if (nwords <= 0) {
440 pr_err("tokenize failed\n");
441 return -EINVAL;
442 }
443
444 if (ddebug_parse_flags(words[nwords-1], &flags, &mask)) {
445 pr_err("flags parse failed\n");
446 return -EINVAL;
447 }
448 if (ddebug_parse_query(words, nwords-1, &query, modname)) {
449 pr_err("query parse failed\n");
450 return -EINVAL;
451 }
452
453 nfound = ddebug_change(&query, flags, mask);
454 vpr_info_dq(&query, nfound ? "applied" : "no-match");
455
456 return nfound;
457}
458
459
460
461
462
463static int ddebug_exec_queries(char *query, const char *modname)
464{
465 char *split;
466 int i, errs = 0, exitcode = 0, rc, nfound = 0;
467
468 for (i = 0; query; query = split) {
469 split = strpbrk(query, ";\n");
470 if (split)
471 *split++ = '\0';
472
473 query = skip_spaces(query);
474 if (!query || !*query || *query == '#')
475 continue;
476
477 vpr_info("query %d: \"%s\"\n", i, query);
478
479 rc = ddebug_exec_query(query, modname);
480 if (rc < 0) {
481 errs++;
482 exitcode = rc;
483 } else {
484 nfound += rc;
485 }
486 i++;
487 }
488 vpr_info("processed %d queries, with %d matches, %d errs\n",
489 i, nfound, errs);
490
491 if (exitcode)
492 return exitcode;
493 return nfound;
494}
495
496#define PREFIX_SIZE 64
497
498static int remaining(int wrote)
499{
500 if (PREFIX_SIZE - wrote > 0)
501 return PREFIX_SIZE - wrote;
502 return 0;
503}
504
505static char *dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
506{
507 int pos_after_tid;
508 int pos = 0;
509
510 *buf = '\0';
511
512 if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
513 if (in_interrupt())
514 pos += snprintf(buf + pos, remaining(pos), "<intr> ");
515 else
516 pos += snprintf(buf + pos, remaining(pos), "[%d] ",
517 task_pid_vnr(current));
518 }
519 pos_after_tid = pos;
520 if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
521 pos += snprintf(buf + pos, remaining(pos), "%s:",
522 desc->modname);
523 if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
524 pos += snprintf(buf + pos, remaining(pos), "%s:",
525 desc->function);
526 if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO)
527 pos += snprintf(buf + pos, remaining(pos), "%d:",
528 desc->lineno);
529 if (pos - pos_after_tid)
530 pos += snprintf(buf + pos, remaining(pos), " ");
531 if (pos >= PREFIX_SIZE)
532 buf[PREFIX_SIZE - 1] = '\0';
533
534 return buf;
535}
536
537int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
538{
539 va_list args;
540 int res;
541 struct va_format vaf;
542 char buf[PREFIX_SIZE];
543
544 BUG_ON(!descriptor);
545 BUG_ON(!fmt);
546
547 va_start(args, fmt);
548
549 vaf.fmt = fmt;
550 vaf.va = &args;
551
552 res = printk(KERN_DEBUG "%s%pV",
553 dynamic_emit_prefix(descriptor, buf), &vaf);
554
555 va_end(args);
556
557 return res;
558}
559EXPORT_SYMBOL(__dynamic_pr_debug);
560
561int __dynamic_dev_dbg(struct _ddebug *descriptor,
562 const struct device *dev, const char *fmt, ...)
563{
564 struct va_format vaf;
565 va_list args;
566 int res;
567
568 BUG_ON(!descriptor);
569 BUG_ON(!fmt);
570
571 va_start(args, fmt);
572
573 vaf.fmt = fmt;
574 vaf.va = &args;
575
576 if (!dev) {
577 res = printk(KERN_DEBUG "(NULL device *): %pV", &vaf);
578 } else {
579 char buf[PREFIX_SIZE];
580
581 res = dev_printk_emit(7, dev, "%s%s %s: %pV",
582 dynamic_emit_prefix(descriptor, buf),
583 dev_driver_string(dev), dev_name(dev),
584 &vaf);
585 }
586
587 va_end(args);
588
589 return res;
590}
591EXPORT_SYMBOL(__dynamic_dev_dbg);
592
593#ifdef CONFIG_NET
594
595int __dynamic_netdev_dbg(struct _ddebug *descriptor,
596 const struct net_device *dev, const char *fmt, ...)
597{
598 struct va_format vaf;
599 va_list args;
600 int res;
601
602 BUG_ON(!descriptor);
603 BUG_ON(!fmt);
604
605 va_start(args, fmt);
606
607 vaf.fmt = fmt;
608 vaf.va = &args;
609
610 if (dev && dev->dev.parent) {
611 char buf[PREFIX_SIZE];
612
613 res = dev_printk_emit(7, dev->dev.parent,
614 "%s%s %s %s: %pV",
615 dynamic_emit_prefix(descriptor, buf),
616 dev_driver_string(dev->dev.parent),
617 dev_name(dev->dev.parent),
618 netdev_name(dev), &vaf);
619 } else if (dev) {
620 res = printk(KERN_DEBUG "%s: %pV", netdev_name(dev), &vaf);
621 } else {
622 res = printk(KERN_DEBUG "(NULL net_device): %pV", &vaf);
623 }
624
625 va_end(args);
626
627 return res;
628}
629EXPORT_SYMBOL(__dynamic_netdev_dbg);
630
631#endif
632
633#define DDEBUG_STRING_SIZE 1024
634static __initdata char ddebug_setup_string[DDEBUG_STRING_SIZE];
635
636static __init int ddebug_setup_query(char *str)
637{
638 if (strlen(str) >= DDEBUG_STRING_SIZE) {
639 pr_warn("ddebug boot param string too large\n");
640 return 0;
641 }
642 strlcpy(ddebug_setup_string, str, DDEBUG_STRING_SIZE);
643 return 1;
644}
645
646__setup("ddebug_query=", ddebug_setup_query);
647
648
649
650
651
652#define USER_BUF_PAGE 4096
653static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
654 size_t len, loff_t *offp)
655{
656 char *tmpbuf;
657 int ret;
658
659 if (len == 0)
660 return 0;
661 if (len > USER_BUF_PAGE - 1) {
662 pr_warn("expected <%d bytes into control\n", USER_BUF_PAGE);
663 return -E2BIG;
664 }
665 tmpbuf = kmalloc(len + 1, GFP_KERNEL);
666 if (!tmpbuf)
667 return -ENOMEM;
668 if (copy_from_user(tmpbuf, ubuf, len)) {
669 kfree(tmpbuf);
670 return -EFAULT;
671 }
672 tmpbuf[len] = '\0';
673 vpr_info("read %d bytes from userspace\n", (int)len);
674
675 ret = ddebug_exec_queries(tmpbuf, NULL);
676 kfree(tmpbuf);
677 if (ret < 0)
678 return ret;
679
680 *offp += len;
681 return len;
682}
683
684
685
686
687
688
689static struct _ddebug *ddebug_iter_first(struct ddebug_iter *iter)
690{
691 if (list_empty(&ddebug_tables)) {
692 iter->table = NULL;
693 iter->idx = 0;
694 return NULL;
695 }
696 iter->table = list_entry(ddebug_tables.next,
697 struct ddebug_table, link);
698 iter->idx = 0;
699 return &iter->table->ddebugs[iter->idx];
700}
701
702
703
704
705
706
707
708static struct _ddebug *ddebug_iter_next(struct ddebug_iter *iter)
709{
710 if (iter->table == NULL)
711 return NULL;
712 if (++iter->idx == iter->table->num_ddebugs) {
713
714 iter->idx = 0;
715 if (list_is_last(&iter->table->link, &ddebug_tables)) {
716 iter->table = NULL;
717 return NULL;
718 }
719 iter->table = list_entry(iter->table->link.next,
720 struct ddebug_table, link);
721 }
722 return &iter->table->ddebugs[iter->idx];
723}
724
725
726
727
728
729
730static void *ddebug_proc_start(struct seq_file *m, loff_t *pos)
731{
732 struct ddebug_iter *iter = m->private;
733 struct _ddebug *dp;
734 int n = *pos;
735
736 vpr_info("called m=%p *pos=%lld\n", m, (unsigned long long)*pos);
737
738 mutex_lock(&ddebug_lock);
739
740 if (!n)
741 return SEQ_START_TOKEN;
742 if (n < 0)
743 return NULL;
744 dp = ddebug_iter_first(iter);
745 while (dp != NULL && --n > 0)
746 dp = ddebug_iter_next(iter);
747 return dp;
748}
749
750
751
752
753
754
755static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
756{
757 struct ddebug_iter *iter = m->private;
758 struct _ddebug *dp;
759
760 vpr_info("called m=%p p=%p *pos=%lld\n",
761 m, p, (unsigned long long)*pos);
762
763 if (p == SEQ_START_TOKEN)
764 dp = ddebug_iter_first(iter);
765 else
766 dp = ddebug_iter_next(iter);
767 ++*pos;
768 return dp;
769}
770
771
772
773
774
775
776
777static int ddebug_proc_show(struct seq_file *m, void *p)
778{
779 struct ddebug_iter *iter = m->private;
780 struct _ddebug *dp = p;
781 char flagsbuf[10];
782
783 vpr_info("called m=%p p=%p\n", m, p);
784
785 if (p == SEQ_START_TOKEN) {
786 seq_puts(m,
787 "# filename:lineno [module]function flags format\n");
788 return 0;
789 }
790
791 seq_printf(m, "%s:%u [%s]%s =%s \"",
792 trim_prefix(dp->filename), dp->lineno,
793 iter->table->mod_name, dp->function,
794 ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf)));
795 seq_escape(m, dp->format, "\t\r\n\"");
796 seq_puts(m, "\"\n");
797
798 return 0;
799}
800
801
802
803
804
805static void ddebug_proc_stop(struct seq_file *m, void *p)
806{
807 vpr_info("called m=%p p=%p\n", m, p);
808 mutex_unlock(&ddebug_lock);
809}
810
811static const struct seq_operations ddebug_proc_seqops = {
812 .start = ddebug_proc_start,
813 .next = ddebug_proc_next,
814 .show = ddebug_proc_show,
815 .stop = ddebug_proc_stop
816};
817
818
819
820
821
822
823
824
825static int ddebug_proc_open(struct inode *inode, struct file *file)
826{
827 struct ddebug_iter *iter;
828 int err;
829
830 vpr_info("called\n");
831
832 iter = kzalloc(sizeof(*iter), GFP_KERNEL);
833 if (iter == NULL)
834 return -ENOMEM;
835
836 err = seq_open(file, &ddebug_proc_seqops);
837 if (err) {
838 kfree(iter);
839 return err;
840 }
841 ((struct seq_file *)file->private_data)->private = iter;
842 return 0;
843}
844
845static const struct file_operations ddebug_proc_fops = {
846 .owner = THIS_MODULE,
847 .open = ddebug_proc_open,
848 .read = seq_read,
849 .llseek = seq_lseek,
850 .release = seq_release_private,
851 .write = ddebug_proc_write
852};
853
854
855
856
857
858int ddebug_add_module(struct _ddebug *tab, unsigned int n,
859 const char *name)
860{
861 struct ddebug_table *dt;
862 char *new_name;
863
864 dt = kzalloc(sizeof(*dt), GFP_KERNEL);
865 if (dt == NULL)
866 return -ENOMEM;
867 new_name = kstrdup(name, GFP_KERNEL);
868 if (new_name == NULL) {
869 kfree(dt);
870 return -ENOMEM;
871 }
872 dt->mod_name = new_name;
873 dt->num_ddebugs = n;
874 dt->ddebugs = tab;
875
876 mutex_lock(&ddebug_lock);
877 list_add_tail(&dt->link, &ddebug_tables);
878 mutex_unlock(&ddebug_lock);
879
880 vpr_info("%u debug prints in module %s\n", n, dt->mod_name);
881 return 0;
882}
883EXPORT_SYMBOL_GPL(ddebug_add_module);
884
885
886static int ddebug_dyndbg_param_cb(char *param, char *val,
887 const char *modname, int on_err)
888{
889 char *sep;
890
891 sep = strchr(param, '.');
892 if (sep) {
893
894 *sep = '\0';
895 modname = param;
896 param = sep + 1;
897 }
898 if (strcmp(param, "dyndbg"))
899 return on_err;
900
901 ddebug_exec_queries((val ? val : "+p"), modname);
902
903 return 0;
904}
905
906
907static int ddebug_dyndbg_boot_param_cb(char *param, char *val,
908 const char *unused)
909{
910 vpr_info("%s=\"%s\"\n", param, val);
911 return ddebug_dyndbg_param_cb(param, val, NULL, 0);
912}
913
914
915
916
917
918
919int ddebug_dyndbg_module_param_cb(char *param, char *val, const char *module)
920{
921 vpr_info("module: %s %s=\"%s\"\n", module, param, val);
922 return ddebug_dyndbg_param_cb(param, val, module, -ENOENT);
923}
924
925static void ddebug_table_free(struct ddebug_table *dt)
926{
927 list_del_init(&dt->link);
928 kfree(dt->mod_name);
929 kfree(dt);
930}
931
932
933
934
935
936int ddebug_remove_module(const char *mod_name)
937{
938 struct ddebug_table *dt, *nextdt;
939 int ret = -ENOENT;
940
941 vpr_info("removing module \"%s\"\n", mod_name);
942
943 mutex_lock(&ddebug_lock);
944 list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) {
945 if (!strcmp(dt->mod_name, mod_name)) {
946 ddebug_table_free(dt);
947 ret = 0;
948 }
949 }
950 mutex_unlock(&ddebug_lock);
951 return ret;
952}
953EXPORT_SYMBOL_GPL(ddebug_remove_module);
954
955static void ddebug_remove_all_tables(void)
956{
957 mutex_lock(&ddebug_lock);
958 while (!list_empty(&ddebug_tables)) {
959 struct ddebug_table *dt = list_entry(ddebug_tables.next,
960 struct ddebug_table,
961 link);
962 ddebug_table_free(dt);
963 }
964 mutex_unlock(&ddebug_lock);
965}
966
967static __initdata int ddebug_init_success;
968
969static int __init dynamic_debug_init_debugfs(void)
970{
971 struct dentry *dir, *file;
972
973 if (!ddebug_init_success)
974 return -ENODEV;
975
976 dir = debugfs_create_dir("dynamic_debug", NULL);
977 if (!dir)
978 return -ENOMEM;
979 file = debugfs_create_file("control", 0644, dir, NULL,
980 &ddebug_proc_fops);
981 if (!file) {
982 debugfs_remove(dir);
983 return -ENOMEM;
984 }
985 return 0;
986}
987
988static int __init dynamic_debug_init(void)
989{
990 struct _ddebug *iter, *iter_start;
991 const char *modname = NULL;
992 char *cmdline;
993 int ret = 0;
994 int n = 0, entries = 0, modct = 0;
995 int verbose_bytes = 0;
996
997 if (__start___verbose == __stop___verbose) {
998 pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
999 return 1;
1000 }
1001 iter = __start___verbose;
1002 modname = iter->modname;
1003 iter_start = iter;
1004 for (; iter < __stop___verbose; iter++) {
1005 entries++;
1006 verbose_bytes += strlen(iter->modname) + strlen(iter->function)
1007 + strlen(iter->filename) + strlen(iter->format);
1008
1009 if (strcmp(modname, iter->modname)) {
1010 modct++;
1011 ret = ddebug_add_module(iter_start, n, modname);
1012 if (ret)
1013 goto out_err;
1014 n = 0;
1015 modname = iter->modname;
1016 iter_start = iter;
1017 }
1018 n++;
1019 }
1020 ret = ddebug_add_module(iter_start, n, modname);
1021 if (ret)
1022 goto out_err;
1023
1024 ddebug_init_success = 1;
1025 vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
1026 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
1027 verbose_bytes + (int)(__stop___verbose - __start___verbose));
1028
1029
1030 if (ddebug_setup_string[0] != '\0') {
1031 pr_warn("ddebug_query param name is deprecated, change it to dyndbg\n");
1032 ret = ddebug_exec_queries(ddebug_setup_string, NULL);
1033 if (ret < 0)
1034 pr_warn("Invalid ddebug boot param %s\n",
1035 ddebug_setup_string);
1036 else
1037 pr_info("%d changes by ddebug_query\n", ret);
1038 }
1039
1040
1041
1042
1043
1044
1045
1046
1047 cmdline = kstrdup(saved_command_line, GFP_KERNEL);
1048 parse_args("dyndbg params", cmdline, NULL,
1049 0, 0, 0, &ddebug_dyndbg_boot_param_cb);
1050 kfree(cmdline);
1051 return 0;
1052
1053out_err:
1054 ddebug_remove_all_tables();
1055 return 0;
1056}
1057
1058early_initcall(dynamic_debug_init);
1059
1060
1061fs_initcall(dynamic_debug_init_debugfs);
1062