The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/lib/dynamic_debug.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * lib/dynamic_debug.c
    3  *
    4  * make pr_debug()/dev_dbg() calls runtime configurable based upon their
    5  * source module.
    6  *
    7  * Copyright (C) 2008 Jason Baron <jbaron@redhat.com>
    8  * By Greg Banks <gnb@melbourne.sgi.com>
    9  * Copyright (c) 2008 Silicon Graphics Inc.  All Rights Reserved.
   10  * Copyright (C) 2011 Bart Van Assche.  All Rights Reserved.
   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 
   37 extern struct _ddebug __start___verbose[];
   38 extern struct _ddebug __stop___verbose[];
   39 
   40 struct ddebug_table {
   41         struct list_head link;
   42         char *mod_name;
   43         unsigned int num_ddebugs;
   44         struct _ddebug *ddebugs;
   45 };
   46 
   47 struct 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 
   55 struct ddebug_iter {
   56         struct ddebug_table *table;
   57         unsigned int idx;
   58 };
   59 
   60 static DEFINE_MUTEX(ddebug_lock);
   61 static LIST_HEAD(ddebug_tables);
   62 static int verbose = 0;
   63 module_param(verbose, int, 0644);
   64 
   65 /* Return the path relative to source root */
   66 static 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; /* prefix mismatch, don't skip */
   72 
   73         return path + skip;
   74 }
   75 
   76 static 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 /* format a string into buf[] which describes the _ddebug's flags */
   86 static 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, ...) \
  104         if (verbose) do { pr_info(fmt, ##__VA_ARGS__); } while (0)
  105 
  106 #define vpr_info_dq(q, msg)                                     \
  107 do {                                                            \
  108         /* trim last char off format print */                   \
  109         vpr_info("%s: func=\"%s\" file=\"%s\" "                 \
  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)
  120 
  121 /*
  122  * Search the tables for _ddebug's which match the given `query' and
  123  * apply the `flags' and `mask' to them.  Returns number of matching
  124  * callsites, normally the same as number of changes.  If verbose,
  125  * logs the changes.  Takes ddebug_lock.
  126  */
  127 static int ddebug_change(const struct ddebug_query *query,
  128                         unsigned int flags, unsigned int mask)
  129 {
  130         int i;
  131         struct ddebug_table *dt;
  132         unsigned int newflags;
  133         unsigned int nfound = 0;
  134         char flagbuf[10];
  135 
  136         /* search for matching ddebugs */
  137         mutex_lock(&ddebug_lock);
  138         list_for_each_entry(dt, &ddebug_tables, link) {
  139 
  140                 /* match against the module name */
  141                 if (query->module && strcmp(query->module, dt->mod_name))
  142                         continue;
  143 
  144                 for (i = 0 ; i < dt->num_ddebugs ; i++) {
  145                         struct _ddebug *dp = &dt->ddebugs[i];
  146 
  147                         /* match against the source filename */
  148                         if (query->filename &&
  149                             strcmp(query->filename, dp->filename) &&
  150                             strcmp(query->filename, kbasename(dp->filename)) &&
  151                             strcmp(query->filename, trim_prefix(dp->filename)))
  152                                 continue;
  153 
  154                         /* match against the function */
  155                         if (query->function &&
  156                             strcmp(query->function, dp->function))
  157                                 continue;
  158 
  159                         /* match against the format */
  160                         if (query->format &&
  161                             !strstr(dp->format, query->format))
  162                                 continue;
  163 
  164                         /* match against the line number range */
  165                         if (query->first_lineno &&
  166                             dp->lineno < query->first_lineno)
  167                                 continue;
  168                         if (query->last_lineno &&
  169                             dp->lineno > query->last_lineno)
  170                                 continue;
  171 
  172                         nfound++;
  173 
  174                         newflags = (dp->flags & mask) | flags;
  175                         if (newflags == dp->flags)
  176                                 continue;
  177                         dp->flags = newflags;
  178                         vpr_info("changed %s:%d [%s]%s =%s\n",
  179                                 trim_prefix(dp->filename), dp->lineno,
  180                                 dt->mod_name, dp->function,
  181                                 ddebug_describe_flags(dp, flagbuf,
  182                                                 sizeof(flagbuf)));
  183                 }
  184         }
  185         mutex_unlock(&ddebug_lock);
  186 
  187         if (!nfound && verbose)
  188                 pr_info("no matches for query\n");
  189 
  190         return nfound;
  191 }
  192 
  193 /*
  194  * Split the buffer `buf' into space-separated words.
  195  * Handles simple " and ' quoting, i.e. without nested,
  196  * embedded or escaped \".  Return the number of words
  197  * or <0 on error.
  198  */
  199 static int ddebug_tokenize(char *buf, char *words[], int maxwords)
  200 {
  201         int nwords = 0;
  202 
  203         while (*buf) {
  204                 char *end;
  205 
  206                 /* Skip leading whitespace */
  207                 buf = skip_spaces(buf);
  208                 if (!*buf)
  209                         break;  /* oh, it was trailing whitespace */
  210                 if (*buf == '#')
  211                         break;  /* token starts comment, skip rest of line */
  212 
  213                 /* find `end' of word, whitespace separated or quoted */
  214                 if (*buf == '"' || *buf == '\'') {
  215                         int quote = *buf++;
  216                         for (end = buf ; *end && *end != quote ; end++)
  217                                 ;
  218                         if (!*end)
  219                                 return -EINVAL; /* unclosed quote */
  220                 } else {
  221                         for (end = buf ; *end && !isspace(*end) ; end++)
  222                                 ;
  223                         BUG_ON(end == buf);
  224                 }
  225 
  226                 /* `buf' is start of word, `end' is one past its end */
  227                 if (nwords == maxwords)
  228                         return -EINVAL; /* ran out of words[] before bytes */
  229                 if (*end)
  230                         *end++ = '\0';  /* terminate the word */
  231                 words[nwords++] = buf;
  232                 buf = end;
  233         }
  234 
  235         if (verbose) {
  236                 int i;
  237                 pr_info("split into words:");
  238                 for (i = 0 ; i < nwords ; i++)
  239                         pr_cont(" \"%s\"", words[i]);
  240                 pr_cont("\n");
  241         }
  242 
  243         return nwords;
  244 }
  245 
  246 /*
  247  * Parse a single line number.  Note that the empty string ""
  248  * is treated as a special case and converted to zero, which
  249  * is later treated as a "don't care" value.
  250  */
  251 static inline int parse_lineno(const char *str, unsigned int *val)
  252 {
  253         char *end = NULL;
  254         BUG_ON(str == NULL);
  255         if (*str == '\0') {
  256                 *val = 0;
  257                 return 0;
  258         }
  259         *val = simple_strtoul(str, &end, 10);
  260         return end == NULL || end == str || *end != '\0' ? -EINVAL : 0;
  261 }
  262 
  263 /*
  264  * Undo octal escaping in a string, inplace.  This is useful to
  265  * allow the user to express a query which matches a format
  266  * containing embedded spaces.
  267  */
  268 #define isodigit(c)             ((c) >= '' && (c) <= '7')
  269 static char *unescape(char *str)
  270 {
  271         char *in = str;
  272         char *out = str;
  273 
  274         while (*in) {
  275                 if (*in == '\\') {
  276                         if (in[1] == '\\') {
  277                                 *out++ = '\\';
  278                                 in += 2;
  279                                 continue;
  280                         } else if (in[1] == 't') {
  281                                 *out++ = '\t';
  282                                 in += 2;
  283                                 continue;
  284                         } else if (in[1] == 'n') {
  285                                 *out++ = '\n';
  286                                 in += 2;
  287                                 continue;
  288                         } else if (isodigit(in[1]) &&
  289                                  isodigit(in[2]) &&
  290                                  isodigit(in[3])) {
  291                                 *out++ = ((in[1] - '')<<6) |
  292                                           ((in[2] - '')<<3) |
  293                                           (in[3] - '');
  294                                 in += 4;
  295                                 continue;
  296                         }
  297                 }
  298                 *out++ = *in++;
  299         }
  300         *out = '\0';
  301 
  302         return str;
  303 }
  304 
  305 static int check_set(const char **dest, char *src, char *name)
  306 {
  307         int rc = 0;
  308 
  309         if (*dest) {
  310                 rc = -EINVAL;
  311                 pr_err("match-spec:%s val:%s overridden by %s",
  312                         name, *dest, src);
  313         }
  314         *dest = src;
  315         return rc;
  316 }
  317 
  318 /*
  319  * Parse words[] as a ddebug query specification, which is a series
  320  * of (keyword, value) pairs chosen from these possibilities:
  321  *
  322  * func <function-name>
  323  * file <full-pathname>
  324  * file <base-filename>
  325  * module <module-name>
  326  * format <escaped-string-to-find-in-format>
  327  * line <lineno>
  328  * line <first-lineno>-<last-lineno> // where either may be empty
  329  *
  330  * Only 1 of each type is allowed.
  331  * Returns 0 on success, <0 on error.
  332  */
  333 static int ddebug_parse_query(char *words[], int nwords,
  334                         struct ddebug_query *query, const char *modname)
  335 {
  336         unsigned int i;
  337         int rc;
  338 
  339         /* check we have an even number of words */
  340         if (nwords % 2 != 0)
  341                 return -EINVAL;
  342         memset(query, 0, sizeof(*query));
  343 
  344         if (modname)
  345                 /* support $modname.dyndbg=<multiple queries> */
  346                 query->module = modname;
  347 
  348         for (i = 0 ; i < nwords ; i += 2) {
  349                 if (!strcmp(words[i], "func"))
  350                         rc = check_set(&query->function, words[i+1], "func");
  351                 else if (!strcmp(words[i], "file"))
  352                         rc = check_set(&query->filename, words[i+1], "file");
  353                 else if (!strcmp(words[i], "module"))
  354                         rc = check_set(&query->module, words[i+1], "module");
  355                 else if (!strcmp(words[i], "format"))
  356                         rc = check_set(&query->format, unescape(words[i+1]),
  357                                 "format");
  358                 else if (!strcmp(words[i], "line")) {
  359                         char *first = words[i+1];
  360                         char *last = strchr(first, '-');
  361                         if (query->first_lineno || query->last_lineno) {
  362                                 pr_err("match-spec:line given 2 times\n");
  363                                 return -EINVAL;
  364                         }
  365                         if (last)
  366                                 *last++ = '\0';
  367                         if (parse_lineno(first, &query->first_lineno) < 0)
  368                                 return -EINVAL;
  369                         if (last) {
  370                                 /* range <first>-<last> */
  371                                 if (parse_lineno(last, &query->last_lineno)
  372                                     < query->first_lineno) {
  373                                         pr_err("last-line < 1st-line\n");
  374                                         return -EINVAL;
  375                                 }
  376                         } else {
  377                                 query->last_lineno = query->first_lineno;
  378                         }
  379                 } else {
  380                         pr_err("unknown keyword \"%s\"\n", words[i]);
  381                         return -EINVAL;
  382                 }
  383                 if (rc)
  384                         return rc;
  385         }
  386         vpr_info_dq(query, "parsed");
  387         return 0;
  388 }
  389 
  390 /*
  391  * Parse `str' as a flags specification, format [-+=][p]+.
  392  * Sets up *maskp and *flagsp to be used when changing the
  393  * flags fields of matched _ddebug's.  Returns 0 on success
  394  * or <0 on error.
  395  */
  396 static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
  397                                unsigned int *maskp)
  398 {
  399         unsigned flags = 0;
  400         int op = '=', i;
  401 
  402         switch (*str) {
  403         case '+':
  404         case '-':
  405         case '=':
  406                 op = *str++;
  407                 break;
  408         default:
  409                 return -EINVAL;
  410         }
  411         vpr_info("op='%c'\n", op);
  412 
  413         for ( ; *str ; ++str) {
  414                 for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) {
  415                         if (*str == opt_array[i].opt_char) {
  416                                 flags |= opt_array[i].flag;
  417                                 break;
  418                         }
  419                 }
  420                 if (i < 0)
  421                         return -EINVAL;
  422         }
  423         vpr_info("flags=0x%x\n", flags);
  424 
  425         /* calculate final *flagsp, *maskp according to mask and op */
  426         switch (op) {
  427         case '=':
  428                 *maskp = 0;
  429                 *flagsp = flags;
  430                 break;
  431         case '+':
  432                 *maskp = ~0U;
  433                 *flagsp = flags;
  434                 break;
  435         case '-':
  436                 *maskp = ~flags;
  437                 *flagsp = 0;
  438                 break;
  439         }
  440         vpr_info("*flagsp=0x%x *maskp=0x%x\n", *flagsp, *maskp);
  441         return 0;
  442 }
  443 
  444 static int ddebug_exec_query(char *query_string, const char *modname)
  445 {
  446         unsigned int flags = 0, mask = 0;
  447         struct ddebug_query query;
  448 #define MAXWORDS 9
  449         int nwords, nfound;
  450         char *words[MAXWORDS];
  451 
  452         nwords = ddebug_tokenize(query_string, words, MAXWORDS);
  453         if (nwords <= 0)
  454                 return -EINVAL;
  455         if (ddebug_parse_query(words, nwords-1, &query, modname))
  456                 return -EINVAL;
  457         if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
  458                 return -EINVAL;
  459 
  460         /* actually go and implement the change */
  461         nfound = ddebug_change(&query, flags, mask);
  462         vpr_info_dq((&query), (nfound) ? "applied" : "no-match");
  463 
  464         return nfound;
  465 }
  466 
  467 /* handle multiple queries in query string, continue on error, return
  468    last error or number of matching callsites.  Module name is either
  469    in param (for boot arg) or perhaps in query string.
  470 */
  471 static int ddebug_exec_queries(char *query, const char *modname)
  472 {
  473         char *split;
  474         int i, errs = 0, exitcode = 0, rc, nfound = 0;
  475 
  476         for (i = 0; query; query = split) {
  477                 split = strpbrk(query, ";\n");
  478                 if (split)
  479                         *split++ = '\0';
  480 
  481                 query = skip_spaces(query);
  482                 if (!query || !*query || *query == '#')
  483                         continue;
  484 
  485                 vpr_info("query %d: \"%s\"\n", i, query);
  486 
  487                 rc = ddebug_exec_query(query, modname);
  488                 if (rc < 0) {
  489                         errs++;
  490                         exitcode = rc;
  491                 } else
  492                         nfound += rc;
  493                 i++;
  494         }
  495         vpr_info("processed %d queries, with %d matches, %d errs\n",
  496                  i, nfound, errs);
  497 
  498         if (exitcode)
  499                 return exitcode;
  500         return nfound;
  501 }
  502 
  503 #define PREFIX_SIZE 64
  504 
  505 static int remaining(int wrote)
  506 {
  507         if (PREFIX_SIZE - wrote > 0)
  508                 return PREFIX_SIZE - wrote;
  509         return 0;
  510 }
  511 
  512 static char *dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
  513 {
  514         int pos_after_tid;
  515         int pos = 0;
  516 
  517         *buf = '\0';
  518 
  519         if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
  520                 if (in_interrupt())
  521                         pos += snprintf(buf + pos, remaining(pos), "<intr> ");
  522                 else
  523                         pos += snprintf(buf + pos, remaining(pos), "[%d] ",
  524                                         task_pid_vnr(current));
  525         }
  526         pos_after_tid = pos;
  527         if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
  528                 pos += snprintf(buf + pos, remaining(pos), "%s:",
  529                                 desc->modname);
  530         if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
  531                 pos += snprintf(buf + pos, remaining(pos), "%s:",
  532                                 desc->function);
  533         if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO)
  534                 pos += snprintf(buf + pos, remaining(pos), "%d:",
  535                                 desc->lineno);
  536         if (pos - pos_after_tid)
  537                 pos += snprintf(buf + pos, remaining(pos), " ");
  538         if (pos >= PREFIX_SIZE)
  539                 buf[PREFIX_SIZE - 1] = '\0';
  540 
  541         return buf;
  542 }
  543 
  544 int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
  545 {
  546         va_list args;
  547         int res;
  548         struct va_format vaf;
  549         char buf[PREFIX_SIZE];
  550 
  551         BUG_ON(!descriptor);
  552         BUG_ON(!fmt);
  553 
  554         va_start(args, fmt);
  555 
  556         vaf.fmt = fmt;
  557         vaf.va = &args;
  558 
  559         res = printk(KERN_DEBUG "%s%pV",
  560                      dynamic_emit_prefix(descriptor, buf), &vaf);
  561 
  562         va_end(args);
  563 
  564         return res;
  565 }
  566 EXPORT_SYMBOL(__dynamic_pr_debug);
  567 
  568 int __dynamic_dev_dbg(struct _ddebug *descriptor,
  569                       const struct device *dev, const char *fmt, ...)
  570 {
  571         struct va_format vaf;
  572         va_list args;
  573         int res;
  574 
  575         BUG_ON(!descriptor);
  576         BUG_ON(!fmt);
  577 
  578         va_start(args, fmt);
  579 
  580         vaf.fmt = fmt;
  581         vaf.va = &args;
  582 
  583         if (!dev) {
  584                 res = printk(KERN_DEBUG "(NULL device *): %pV", &vaf);
  585         } else {
  586                 char buf[PREFIX_SIZE];
  587 
  588                 res = dev_printk_emit(7, dev, "%s%s %s: %pV",
  589                                       dynamic_emit_prefix(descriptor, buf),
  590                                       dev_driver_string(dev), dev_name(dev),
  591                                       &vaf);
  592         }
  593 
  594         va_end(args);
  595 
  596         return res;
  597 }
  598 EXPORT_SYMBOL(__dynamic_dev_dbg);
  599 
  600 #ifdef CONFIG_NET
  601 
  602 int __dynamic_netdev_dbg(struct _ddebug *descriptor,
  603                          const struct net_device *dev, const char *fmt, ...)
  604 {
  605         struct va_format vaf;
  606         va_list args;
  607         int res;
  608 
  609         BUG_ON(!descriptor);
  610         BUG_ON(!fmt);
  611 
  612         va_start(args, fmt);
  613 
  614         vaf.fmt = fmt;
  615         vaf.va = &args;
  616 
  617         if (dev && dev->dev.parent) {
  618                 char buf[PREFIX_SIZE];
  619 
  620                 res = dev_printk_emit(7, dev->dev.parent,
  621                                       "%s%s %s %s: %pV",
  622                                       dynamic_emit_prefix(descriptor, buf),
  623                                       dev_driver_string(dev->dev.parent),
  624                                       dev_name(dev->dev.parent),
  625                                       netdev_name(dev), &vaf);
  626         } else if (dev) {
  627                 res = printk(KERN_DEBUG "%s: %pV", netdev_name(dev), &vaf);
  628         } else {
  629                 res = printk(KERN_DEBUG "(NULL net_device): %pV", &vaf);
  630         }
  631 
  632         va_end(args);
  633 
  634         return res;
  635 }
  636 EXPORT_SYMBOL(__dynamic_netdev_dbg);
  637 
  638 #endif
  639 
  640 #define DDEBUG_STRING_SIZE 1024
  641 static __initdata char ddebug_setup_string[DDEBUG_STRING_SIZE];
  642 
  643 static __init int ddebug_setup_query(char *str)
  644 {
  645         if (strlen(str) >= DDEBUG_STRING_SIZE) {
  646                 pr_warn("ddebug boot param string too large\n");
  647                 return 0;
  648         }
  649         strlcpy(ddebug_setup_string, str, DDEBUG_STRING_SIZE);
  650         return 1;
  651 }
  652 
  653 __setup("ddebug_query=", ddebug_setup_query);
  654 
  655 /*
  656  * File_ops->write method for <debugfs>/dynamic_debug/conrol.  Gathers the
  657  * command text from userspace, parses and executes it.
  658  */
  659 #define USER_BUF_PAGE 4096
  660 static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
  661                                   size_t len, loff_t *offp)
  662 {
  663         char *tmpbuf;
  664         int ret;
  665 
  666         if (len == 0)
  667                 return 0;
  668         if (len > USER_BUF_PAGE - 1) {
  669                 pr_warn("expected <%d bytes into control\n", USER_BUF_PAGE);
  670                 return -E2BIG;
  671         }
  672         tmpbuf = kmalloc(len + 1, GFP_KERNEL);
  673         if (!tmpbuf)
  674                 return -ENOMEM;
  675         if (copy_from_user(tmpbuf, ubuf, len)) {
  676                 kfree(tmpbuf);
  677                 return -EFAULT;
  678         }
  679         tmpbuf[len] = '\0';
  680         vpr_info("read %d bytes from userspace\n", (int)len);
  681 
  682         ret = ddebug_exec_queries(tmpbuf, NULL);
  683         kfree(tmpbuf);
  684         if (ret < 0)
  685                 return ret;
  686 
  687         *offp += len;
  688         return len;
  689 }
  690 
  691 /*
  692  * Set the iterator to point to the first _ddebug object
  693  * and return a pointer to that first object.  Returns
  694  * NULL if there are no _ddebugs at all.
  695  */
  696 static struct _ddebug *ddebug_iter_first(struct ddebug_iter *iter)
  697 {
  698         if (list_empty(&ddebug_tables)) {
  699                 iter->table = NULL;
  700                 iter->idx = 0;
  701                 return NULL;
  702         }
  703         iter->table = list_entry(ddebug_tables.next,
  704                                  struct ddebug_table, link);
  705         iter->idx = 0;
  706         return &iter->table->ddebugs[iter->idx];
  707 }
  708 
  709 /*
  710  * Advance the iterator to point to the next _ddebug
  711  * object from the one the iterator currently points at,
  712  * and returns a pointer to the new _ddebug.  Returns
  713  * NULL if the iterator has seen all the _ddebugs.
  714  */
  715 static struct _ddebug *ddebug_iter_next(struct ddebug_iter *iter)
  716 {
  717         if (iter->table == NULL)
  718                 return NULL;
  719         if (++iter->idx == iter->table->num_ddebugs) {
  720                 /* iterate to next table */
  721                 iter->idx = 0;
  722                 if (list_is_last(&iter->table->link, &ddebug_tables)) {
  723                         iter->table = NULL;
  724                         return NULL;
  725                 }
  726                 iter->table = list_entry(iter->table->link.next,
  727                                          struct ddebug_table, link);
  728         }
  729         return &iter->table->ddebugs[iter->idx];
  730 }
  731 
  732 /*
  733  * Seq_ops start method.  Called at the start of every
  734  * read() call from userspace.  Takes the ddebug_lock and
  735  * seeks the seq_file's iterator to the given position.
  736  */
  737 static void *ddebug_proc_start(struct seq_file *m, loff_t *pos)
  738 {
  739         struct ddebug_iter *iter = m->private;
  740         struct _ddebug *dp;
  741         int n = *pos;
  742 
  743         vpr_info("called m=%p *pos=%lld\n", m, (unsigned long long)*pos);
  744 
  745         mutex_lock(&ddebug_lock);
  746 
  747         if (!n)
  748                 return SEQ_START_TOKEN;
  749         if (n < 0)
  750                 return NULL;
  751         dp = ddebug_iter_first(iter);
  752         while (dp != NULL && --n > 0)
  753                 dp = ddebug_iter_next(iter);
  754         return dp;
  755 }
  756 
  757 /*
  758  * Seq_ops next method.  Called several times within a read()
  759  * call from userspace, with ddebug_lock held.  Walks to the
  760  * next _ddebug object with a special case for the header line.
  761  */
  762 static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
  763 {
  764         struct ddebug_iter *iter = m->private;
  765         struct _ddebug *dp;
  766 
  767         vpr_info("called m=%p p=%p *pos=%lld\n",
  768                 m, p, (unsigned long long)*pos);
  769 
  770         if (p == SEQ_START_TOKEN)
  771                 dp = ddebug_iter_first(iter);
  772         else
  773                 dp = ddebug_iter_next(iter);
  774         ++*pos;
  775         return dp;
  776 }
  777 
  778 /*
  779  * Seq_ops show method.  Called several times within a read()
  780  * call from userspace, with ddebug_lock held.  Formats the
  781  * current _ddebug as a single human-readable line, with a
  782  * special case for the header line.
  783  */
  784 static int ddebug_proc_show(struct seq_file *m, void *p)
  785 {
  786         struct ddebug_iter *iter = m->private;
  787         struct _ddebug *dp = p;
  788         char flagsbuf[10];
  789 
  790         vpr_info("called m=%p p=%p\n", m, p);
  791 
  792         if (p == SEQ_START_TOKEN) {
  793                 seq_puts(m,
  794                         "# filename:lineno [module]function flags format\n");
  795                 return 0;
  796         }
  797 
  798         seq_printf(m, "%s:%u [%s]%s =%s \"",
  799                 trim_prefix(dp->filename), dp->lineno,
  800                 iter->table->mod_name, dp->function,
  801                 ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf)));
  802         seq_escape(m, dp->format, "\t\r\n\"");
  803         seq_puts(m, "\"\n");
  804 
  805         return 0;
  806 }
  807 
  808 /*
  809  * Seq_ops stop method.  Called at the end of each read()
  810  * call from userspace.  Drops ddebug_lock.
  811  */
  812 static void ddebug_proc_stop(struct seq_file *m, void *p)
  813 {
  814         vpr_info("called m=%p p=%p\n", m, p);
  815         mutex_unlock(&ddebug_lock);
  816 }
  817 
  818 static const struct seq_operations ddebug_proc_seqops = {
  819         .start = ddebug_proc_start,
  820         .next = ddebug_proc_next,
  821         .show = ddebug_proc_show,
  822         .stop = ddebug_proc_stop
  823 };
  824 
  825 /*
  826  * File_ops->open method for <debugfs>/dynamic_debug/control.  Does
  827  * the seq_file setup dance, and also creates an iterator to walk the
  828  * _ddebugs.  Note that we create a seq_file always, even for O_WRONLY
  829  * files where it's not needed, as doing so simplifies the ->release
  830  * method.
  831  */
  832 static int ddebug_proc_open(struct inode *inode, struct file *file)
  833 {
  834         struct ddebug_iter *iter;
  835         int err;
  836 
  837         vpr_info("called\n");
  838 
  839         iter = kzalloc(sizeof(*iter), GFP_KERNEL);
  840         if (iter == NULL)
  841                 return -ENOMEM;
  842 
  843         err = seq_open(file, &ddebug_proc_seqops);
  844         if (err) {
  845                 kfree(iter);
  846                 return err;
  847         }
  848         ((struct seq_file *) file->private_data)->private = iter;
  849         return 0;
  850 }
  851 
  852 static const struct file_operations ddebug_proc_fops = {
  853         .owner = THIS_MODULE,
  854         .open = ddebug_proc_open,
  855         .read = seq_read,
  856         .llseek = seq_lseek,
  857         .release = seq_release_private,
  858         .write = ddebug_proc_write
  859 };
  860 
  861 /*
  862  * Allocate a new ddebug_table for the given module
  863  * and add it to the global list.
  864  */
  865 int ddebug_add_module(struct _ddebug *tab, unsigned int n,
  866                              const char *name)
  867 {
  868         struct ddebug_table *dt;
  869         char *new_name;
  870 
  871         dt = kzalloc(sizeof(*dt), GFP_KERNEL);
  872         if (dt == NULL)
  873                 return -ENOMEM;
  874         new_name = kstrdup(name, GFP_KERNEL);
  875         if (new_name == NULL) {
  876                 kfree(dt);
  877                 return -ENOMEM;
  878         }
  879         dt->mod_name = new_name;
  880         dt->num_ddebugs = n;
  881         dt->ddebugs = tab;
  882 
  883         mutex_lock(&ddebug_lock);
  884         list_add_tail(&dt->link, &ddebug_tables);
  885         mutex_unlock(&ddebug_lock);
  886 
  887         vpr_info("%u debug prints in module %s\n", n, dt->mod_name);
  888         return 0;
  889 }
  890 EXPORT_SYMBOL_GPL(ddebug_add_module);
  891 
  892 /* helper for ddebug_dyndbg_(boot|module)_param_cb */
  893 static int ddebug_dyndbg_param_cb(char *param, char *val,
  894                                 const char *modname, int on_err)
  895 {
  896         char *sep;
  897 
  898         sep = strchr(param, '.');
  899         if (sep) {
  900                 /* needed only for ddebug_dyndbg_boot_param_cb */
  901                 *sep = '\0';
  902                 modname = param;
  903                 param = sep + 1;
  904         }
  905         if (strcmp(param, "dyndbg"))
  906                 return on_err; /* determined by caller */
  907 
  908         ddebug_exec_queries((val ? val : "+p"), modname);
  909 
  910         return 0; /* query failure shouldnt stop module load */
  911 }
  912 
  913 /* handle both dyndbg and $module.dyndbg params at boot */
  914 static int ddebug_dyndbg_boot_param_cb(char *param, char *val,
  915                                 const char *unused)
  916 {
  917         vpr_info("%s=\"%s\"\n", param, val);
  918         return ddebug_dyndbg_param_cb(param, val, NULL, 0);
  919 }
  920 
  921 /*
  922  * modprobe foo finds foo.params in boot-args, strips "foo.", and
  923  * passes them to load_module().  This callback gets unknown params,
  924  * processes dyndbg params, rejects others.
  925  */
  926 int ddebug_dyndbg_module_param_cb(char *param, char *val, const char *module)
  927 {
  928         vpr_info("module: %s %s=\"%s\"\n", module, param, val);
  929         return ddebug_dyndbg_param_cb(param, val, module, -ENOENT);
  930 }
  931 
  932 static void ddebug_table_free(struct ddebug_table *dt)
  933 {
  934         list_del_init(&dt->link);
  935         kfree(dt->mod_name);
  936         kfree(dt);
  937 }
  938 
  939 /*
  940  * Called in response to a module being unloaded.  Removes
  941  * any ddebug_table's which point at the module.
  942  */
  943 int ddebug_remove_module(const char *mod_name)
  944 {
  945         struct ddebug_table *dt, *nextdt;
  946         int ret = -ENOENT;
  947 
  948         vpr_info("removing module \"%s\"\n", mod_name);
  949 
  950         mutex_lock(&ddebug_lock);
  951         list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) {
  952                 if (!strcmp(dt->mod_name, mod_name)) {
  953                         ddebug_table_free(dt);
  954                         ret = 0;
  955                 }
  956         }
  957         mutex_unlock(&ddebug_lock);
  958         return ret;
  959 }
  960 EXPORT_SYMBOL_GPL(ddebug_remove_module);
  961 
  962 static void ddebug_remove_all_tables(void)
  963 {
  964         mutex_lock(&ddebug_lock);
  965         while (!list_empty(&ddebug_tables)) {
  966                 struct ddebug_table *dt = list_entry(ddebug_tables.next,
  967                                                       struct ddebug_table,
  968                                                       link);
  969                 ddebug_table_free(dt);
  970         }
  971         mutex_unlock(&ddebug_lock);
  972 }
  973 
  974 static __initdata int ddebug_init_success;
  975 
  976 static int __init dynamic_debug_init_debugfs(void)
  977 {
  978         struct dentry *dir, *file;
  979 
  980         if (!ddebug_init_success)
  981                 return -ENODEV;
  982 
  983         dir = debugfs_create_dir("dynamic_debug", NULL);
  984         if (!dir)
  985                 return -ENOMEM;
  986         file = debugfs_create_file("control", 0644, dir, NULL,
  987                                         &ddebug_proc_fops);
  988         if (!file) {
  989                 debugfs_remove(dir);
  990                 return -ENOMEM;
  991         }
  992         return 0;
  993 }
  994 
  995 static int __init dynamic_debug_init(void)
  996 {
  997         struct _ddebug *iter, *iter_start;
  998         const char *modname = NULL;
  999         char *cmdline;
 1000         int ret = 0;
 1001         int n = 0, entries = 0, modct = 0;
 1002         int verbose_bytes = 0;
 1003 
 1004         if (__start___verbose == __stop___verbose) {
 1005                 pr_warn("_ddebug table is empty in a "
 1006                         "CONFIG_DYNAMIC_DEBUG build");
 1007                 return 1;
 1008         }
 1009         iter = __start___verbose;
 1010         modname = iter->modname;
 1011         iter_start = iter;
 1012         for (; iter < __stop___verbose; iter++) {
 1013                 entries++;
 1014                 verbose_bytes += strlen(iter->modname) + strlen(iter->function)
 1015                         + strlen(iter->filename) + strlen(iter->format);
 1016 
 1017                 if (strcmp(modname, iter->modname)) {
 1018                         modct++;
 1019                         ret = ddebug_add_module(iter_start, n, modname);
 1020                         if (ret)
 1021                                 goto out_err;
 1022                         n = 0;
 1023                         modname = iter->modname;
 1024                         iter_start = iter;
 1025                 }
 1026                 n++;
 1027         }
 1028         ret = ddebug_add_module(iter_start, n, modname);
 1029         if (ret)
 1030                 goto out_err;
 1031 
 1032         ddebug_init_success = 1;
 1033         vpr_info("%d modules, %d entries and %d bytes in ddebug tables,"
 1034                 " %d bytes in (readonly) verbose section\n",
 1035                 modct, entries, (int)( modct * sizeof(struct ddebug_table)),
 1036                 verbose_bytes + (int)(__stop___verbose - __start___verbose));
 1037 
 1038         /* apply ddebug_query boot param, dont unload tables on err */
 1039         if (ddebug_setup_string[0] != '\0') {
 1040                 pr_warn("ddebug_query param name is deprecated,"
 1041                         " change it to dyndbg\n");
 1042                 ret = ddebug_exec_queries(ddebug_setup_string, NULL);
 1043                 if (ret < 0)
 1044                         pr_warn("Invalid ddebug boot param %s",
 1045                                 ddebug_setup_string);
 1046                 else
 1047                         pr_info("%d changes by ddebug_query\n", ret);
 1048         }
 1049         /* now that ddebug tables are loaded, process all boot args
 1050          * again to find and activate queries given in dyndbg params.
 1051          * While this has already been done for known boot params, it
 1052          * ignored the unknown ones (dyndbg in particular).  Reusing
 1053          * parse_args avoids ad-hoc parsing.  This will also attempt
 1054          * to activate queries for not-yet-loaded modules, which is
 1055          * slightly noisy if verbose, but harmless.
 1056          */
 1057         cmdline = kstrdup(saved_command_line, GFP_KERNEL);
 1058         parse_args("dyndbg params", cmdline, NULL,
 1059                    0, 0, 0, &ddebug_dyndbg_boot_param_cb);
 1060         kfree(cmdline);
 1061         return 0;
 1062 
 1063 out_err:
 1064         ddebug_remove_all_tables();
 1065         return 0;
 1066 }
 1067 /* Allow early initialization for boot messages via boot param */
 1068 early_initcall(dynamic_debug_init);
 1069 
 1070 /* Debugfs setup must be done later */
 1071 fs_initcall(dynamic_debug_init_debugfs);

Cache object: e3457b34da282f9193ca6e1c1ace09ad


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.