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