aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dynamic_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dynamic_debug.c')
-rw-r--r--lib/dynamic_debug.c118
1 files changed, 62 insertions, 56 deletions
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 1db1fc660538..ac7d27737e42 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -59,7 +59,7 @@ struct ddebug_iter {
59 59
60static DEFINE_MUTEX(ddebug_lock); 60static DEFINE_MUTEX(ddebug_lock);
61static LIST_HEAD(ddebug_tables); 61static LIST_HEAD(ddebug_tables);
62static int verbose = 0; 62static int verbose;
63module_param(verbose, int, 0644); 63module_param(verbose, int, 0644);
64 64
65/* Return the path relative to source root */ 65/* Return the path relative to source root */
@@ -100,24 +100,32 @@ static char *ddebug_describe_flags(struct _ddebug *dp, char *buf,
100 return buf; 100 return buf;
101} 101}
102 102
103#define vpr_info(fmt, ...) \ 103#define vpr_info(fmt, ...) \
104 if (verbose) do { pr_info(fmt, ##__VA_ARGS__); } while (0)
105
106#define vpr_info_dq(q, msg) \
107do { \ 104do { \
108 /* trim last char off format print */ \ 105 if (verbose) \
109 vpr_info("%s: func=\"%s\" file=\"%s\" " \ 106 pr_info(fmt, ##__VA_ARGS__); \
110 "module=\"%s\" format=\"%.*s\" " \
111 "lineno=%u-%u", \
112 msg, \
113 q->function ? q->function : "", \
114 q->filename ? q->filename : "", \
115 q->module ? q->module : "", \
116 (int)(q->format ? strlen(q->format) - 1 : 0), \
117 q->format ? q->format : "", \
118 q->first_lineno, q->last_lineno); \
119} while (0) 107} while (0)
120 108
109static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
110{
111 /* trim any trailing newlines */
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
121/* 129/*
122 * Search the tables for _ddebug's which match the given `query' and 130 * Search the tables for _ddebug's which match the given `query' and
123 * apply the `flags' and `mask' to them. Returns number of matching 131 * apply the `flags' and `mask' to them. Returns number of matching
@@ -141,7 +149,7 @@ static int ddebug_change(const struct ddebug_query *query,
141 if (query->module && strcmp(query->module, dt->mod_name)) 149 if (query->module && strcmp(query->module, dt->mod_name))
142 continue; 150 continue;
143 151
144 for (i = 0 ; i < dt->num_ddebugs ; i++) { 152 for (i = 0; i < dt->num_ddebugs; i++) {
145 struct _ddebug *dp = &dt->ddebugs[i]; 153 struct _ddebug *dp = &dt->ddebugs[i];
146 154
147 /* match against the source filename */ 155 /* match against the source filename */
@@ -176,10 +184,10 @@ static int ddebug_change(const struct ddebug_query *query,
176 continue; 184 continue;
177 dp->flags = newflags; 185 dp->flags = newflags;
178 vpr_info("changed %s:%d [%s]%s =%s\n", 186 vpr_info("changed %s:%d [%s]%s =%s\n",
179 trim_prefix(dp->filename), dp->lineno, 187 trim_prefix(dp->filename), dp->lineno,
180 dt->mod_name, dp->function, 188 dt->mod_name, dp->function,
181 ddebug_describe_flags(dp, flagbuf, 189 ddebug_describe_flags(dp, flagbuf,
182 sizeof(flagbuf))); 190 sizeof(flagbuf)));
183 } 191 }
184 } 192 }
185 mutex_unlock(&ddebug_lock); 193 mutex_unlock(&ddebug_lock);
@@ -213,12 +221,12 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords)
213 /* find `end' of word, whitespace separated or quoted */ 221 /* find `end' of word, whitespace separated or quoted */
214 if (*buf == '"' || *buf == '\'') { 222 if (*buf == '"' || *buf == '\'') {
215 int quote = *buf++; 223 int quote = *buf++;
216 for (end = buf ; *end && *end != quote ; end++) 224 for (end = buf; *end && *end != quote; end++)
217 ; 225 ;
218 if (!*end) 226 if (!*end)
219 return -EINVAL; /* unclosed quote */ 227 return -EINVAL; /* unclosed quote */
220 } else { 228 } else {
221 for (end = buf ; *end && !isspace(*end) ; end++) 229 for (end = buf; *end && !isspace(*end); end++)
222 ; 230 ;
223 BUG_ON(end == buf); 231 BUG_ON(end == buf);
224 } 232 }
@@ -235,7 +243,7 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords)
235 if (verbose) { 243 if (verbose) {
236 int i; 244 int i;
237 pr_info("split into words:"); 245 pr_info("split into words:");
238 for (i = 0 ; i < nwords ; i++) 246 for (i = 0; i < nwords; i++)
239 pr_cont(" \"%s\"", words[i]); 247 pr_cont(" \"%s\"", words[i]);
240 pr_cont("\n"); 248 pr_cont("\n");
241 } 249 }
@@ -286,11 +294,11 @@ static char *unescape(char *str)
286 in += 2; 294 in += 2;
287 continue; 295 continue;
288 } else if (isodigit(in[1]) && 296 } else if (isodigit(in[1]) &&
289 isodigit(in[2]) && 297 isodigit(in[2]) &&
290 isodigit(in[3])) { 298 isodigit(in[3])) {
291 *out++ = ((in[1] - '0')<<6) | 299 *out++ = (((in[1] - '0') << 6) |
292 ((in[2] - '0')<<3) | 300 ((in[2] - '0') << 3) |
293 (in[3] - '0'); 301 (in[3] - '0'));
294 in += 4; 302 in += 4;
295 continue; 303 continue;
296 } 304 }
@@ -308,8 +316,8 @@ static int check_set(const char **dest, char *src, char *name)
308 316
309 if (*dest) { 317 if (*dest) {
310 rc = -EINVAL; 318 rc = -EINVAL;
311 pr_err("match-spec:%s val:%s overridden by %s", 319 pr_err("match-spec:%s val:%s overridden by %s\n",
312 name, *dest, src); 320 name, *dest, src);
313 } 321 }
314 *dest = src; 322 *dest = src;
315 return rc; 323 return rc;
@@ -345,17 +353,17 @@ static int ddebug_parse_query(char *words[], int nwords,
345 /* support $modname.dyndbg=<multiple queries> */ 353 /* support $modname.dyndbg=<multiple queries> */
346 query->module = modname; 354 query->module = modname;
347 355
348 for (i = 0 ; i < nwords ; i += 2) { 356 for (i = 0; i < nwords; i += 2) {
349 if (!strcmp(words[i], "func")) 357 if (!strcmp(words[i], "func")) {
350 rc = check_set(&query->function, words[i+1], "func"); 358 rc = check_set(&query->function, words[i+1], "func");
351 else if (!strcmp(words[i], "file")) 359 } else if (!strcmp(words[i], "file")) {
352 rc = check_set(&query->filename, words[i+1], "file"); 360 rc = check_set(&query->filename, words[i+1], "file");
353 else if (!strcmp(words[i], "module")) 361 } else if (!strcmp(words[i], "module")) {
354 rc = check_set(&query->module, words[i+1], "module"); 362 rc = check_set(&query->module, words[i+1], "module");
355 else if (!strcmp(words[i], "format")) 363 } else if (!strcmp(words[i], "format")) {
356 rc = check_set(&query->format, unescape(words[i+1]), 364 rc = check_set(&query->format, unescape(words[i+1]),
357 "format"); 365 "format");
358 else if (!strcmp(words[i], "line")) { 366 } else if (!strcmp(words[i], "line")) {
359 char *first = words[i+1]; 367 char *first = words[i+1];
360 char *last = strchr(first, '-'); 368 char *last = strchr(first, '-');
361 if (query->first_lineno || query->last_lineno) { 369 if (query->first_lineno || query->last_lineno) {
@@ -410,7 +418,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
410 } 418 }
411 vpr_info("op='%c'\n", op); 419 vpr_info("op='%c'\n", op);
412 420
413 for ( ; *str ; ++str) { 421 for (; *str ; ++str) {
414 for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) { 422 for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) {
415 if (*str == opt_array[i].opt_char) { 423 if (*str == opt_array[i].opt_char) {
416 flags |= opt_array[i].flag; 424 flags |= opt_array[i].flag;
@@ -459,7 +467,7 @@ static int ddebug_exec_query(char *query_string, const char *modname)
459 467
460 /* actually go and implement the change */ 468 /* actually go and implement the change */
461 nfound = ddebug_change(&query, flags, mask); 469 nfound = ddebug_change(&query, flags, mask);
462 vpr_info_dq((&query), (nfound) ? "applied" : "no-match"); 470 vpr_info_dq(&query, nfound ? "applied" : "no-match");
463 471
464 return nfound; 472 return nfound;
465} 473}
@@ -488,8 +496,9 @@ static int ddebug_exec_queries(char *query, const char *modname)
488 if (rc < 0) { 496 if (rc < 0) {
489 errs++; 497 errs++;
490 exitcode = rc; 498 exitcode = rc;
491 } else 499 } else {
492 nfound += rc; 500 nfound += rc;
501 }
493 i++; 502 i++;
494 } 503 }
495 vpr_info("processed %d queries, with %d matches, %d errs\n", 504 vpr_info("processed %d queries, with %d matches, %d errs\n",
@@ -765,7 +774,7 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
765 struct _ddebug *dp; 774 struct _ddebug *dp;
766 775
767 vpr_info("called m=%p p=%p *pos=%lld\n", 776 vpr_info("called m=%p p=%p *pos=%lld\n",
768 m, p, (unsigned long long)*pos); 777 m, p, (unsigned long long)*pos);
769 778
770 if (p == SEQ_START_TOKEN) 779 if (p == SEQ_START_TOKEN)
771 dp = ddebug_iter_first(iter); 780 dp = ddebug_iter_first(iter);
@@ -791,14 +800,14 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
791 800
792 if (p == SEQ_START_TOKEN) { 801 if (p == SEQ_START_TOKEN) {
793 seq_puts(m, 802 seq_puts(m,
794 "# filename:lineno [module]function flags format\n"); 803 "# filename:lineno [module]function flags format\n");
795 return 0; 804 return 0;
796 } 805 }
797 806
798 seq_printf(m, "%s:%u [%s]%s =%s \"", 807 seq_printf(m, "%s:%u [%s]%s =%s \"",
799 trim_prefix(dp->filename), dp->lineno, 808 trim_prefix(dp->filename), dp->lineno,
800 iter->table->mod_name, dp->function, 809 iter->table->mod_name, dp->function,
801 ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf))); 810 ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf)));
802 seq_escape(m, dp->format, "\t\r\n\""); 811 seq_escape(m, dp->format, "\t\r\n\"");
803 seq_puts(m, "\"\n"); 812 seq_puts(m, "\"\n");
804 813
@@ -845,7 +854,7 @@ static int ddebug_proc_open(struct inode *inode, struct file *file)
845 kfree(iter); 854 kfree(iter);
846 return err; 855 return err;
847 } 856 }
848 ((struct seq_file *) file->private_data)->private = iter; 857 ((struct seq_file *)file->private_data)->private = iter;
849 return 0; 858 return 0;
850} 859}
851 860
@@ -1002,8 +1011,7 @@ static int __init dynamic_debug_init(void)
1002 int verbose_bytes = 0; 1011 int verbose_bytes = 0;
1003 1012
1004 if (__start___verbose == __stop___verbose) { 1013 if (__start___verbose == __stop___verbose) {
1005 pr_warn("_ddebug table is empty in a " 1014 pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
1006 "CONFIG_DYNAMIC_DEBUG build");
1007 return 1; 1015 return 1;
1008 } 1016 }
1009 iter = __start___verbose; 1017 iter = __start___verbose;
@@ -1030,18 +1038,16 @@ static int __init dynamic_debug_init(void)
1030 goto out_err; 1038 goto out_err;
1031 1039
1032 ddebug_init_success = 1; 1040 ddebug_init_success = 1;
1033 vpr_info("%d modules, %d entries and %d bytes in ddebug tables," 1041 vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
1034 " %d bytes in (readonly) verbose section\n", 1042 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
1035 modct, entries, (int)( modct * sizeof(struct ddebug_table)), 1043 verbose_bytes + (int)(__stop___verbose - __start___verbose));
1036 verbose_bytes + (int)(__stop___verbose - __start___verbose));
1037 1044
1038 /* apply ddebug_query boot param, dont unload tables on err */ 1045 /* apply ddebug_query boot param, dont unload tables on err */
1039 if (ddebug_setup_string[0] != '\0') { 1046 if (ddebug_setup_string[0] != '\0') {
1040 pr_warn("ddebug_query param name is deprecated," 1047 pr_warn("ddebug_query param name is deprecated, change it to dyndbg\n");
1041 " change it to dyndbg\n");
1042 ret = ddebug_exec_queries(ddebug_setup_string, NULL); 1048 ret = ddebug_exec_queries(ddebug_setup_string, NULL);
1043 if (ret < 0) 1049 if (ret < 0)
1044 pr_warn("Invalid ddebug boot param %s", 1050 pr_warn("Invalid ddebug boot param %s\n",
1045 ddebug_setup_string); 1051 ddebug_setup_string);
1046 else 1052 else
1047 pr_info("%d changes by ddebug_query\n", ret); 1053 pr_info("%d changes by ddebug_query\n", ret);