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