linux/include/linux/dynamic_debug.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef _DYNAMIC_DEBUG_H
   3#define _DYNAMIC_DEBUG_H
   4
   5#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
   6#include <linux/jump_label.h>
   7#endif
   8
   9/*
  10 * An instance of this structure is created in a special
  11 * ELF section at every dynamic debug callsite.  At runtime,
  12 * the special section is treated as an array of these.
  13 */
  14struct _ddebug {
  15        /*
  16         * These fields are used to drive the user interface
  17         * for selecting and displaying debug callsites.
  18         */
  19        const char *modname;
  20        const char *function;
  21        const char *filename;
  22        const char *format;
  23        unsigned int lineno:18;
  24        /*
  25         * The flags field controls the behaviour at the callsite.
  26         * The bits here are changed dynamically when the user
  27         * writes commands to <debugfs>/dynamic_debug/control
  28         */
  29#define _DPRINTK_FLAGS_NONE     0
  30#define _DPRINTK_FLAGS_PRINT    (1<<0) /* printk() a message using the format */
  31#define _DPRINTK_FLAGS_INCL_MODNAME     (1<<1)
  32#define _DPRINTK_FLAGS_INCL_FUNCNAME    (1<<2)
  33#define _DPRINTK_FLAGS_INCL_LINENO      (1<<3)
  34#define _DPRINTK_FLAGS_INCL_TID         (1<<4)
  35#if defined DEBUG
  36#define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT
  37#else
  38#define _DPRINTK_FLAGS_DEFAULT 0
  39#endif
  40        unsigned int flags:8;
  41#ifdef HAVE_JUMP_LABEL
  42        union {
  43                struct static_key_true dd_key_true;
  44                struct static_key_false dd_key_false;
  45        } key;
  46#endif
  47} __attribute__((aligned(8)));
  48
  49
  50int ddebug_add_module(struct _ddebug *tab, unsigned int n,
  51                                const char *modname);
  52
  53#if defined(CONFIG_DYNAMIC_DEBUG)
  54extern int ddebug_remove_module(const char *mod_name);
  55extern __printf(2, 3)
  56void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
  57
  58extern int ddebug_dyndbg_module_param_cb(char *param, char *val,
  59                                        const char *modname);
  60
  61struct device;
  62
  63extern __printf(3, 4)
  64void __dynamic_dev_dbg(struct _ddebug *descriptor, const struct device *dev,
  65                       const char *fmt, ...);
  66
  67struct net_device;
  68
  69extern __printf(3, 4)
  70void __dynamic_netdev_dbg(struct _ddebug *descriptor,
  71                          const struct net_device *dev,
  72                          const char *fmt, ...);
  73
  74#define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init) \
  75        static struct _ddebug  __aligned(8)                     \
  76        __attribute__((section("__verbose"))) name = {          \
  77                .modname = KBUILD_MODNAME,                      \
  78                .function = __func__,                           \
  79                .filename = __FILE__,                           \
  80                .format = (fmt),                                \
  81                .lineno = __LINE__,                             \
  82                .flags = _DPRINTK_FLAGS_DEFAULT,                \
  83                dd_key_init(key, init)                          \
  84        }
  85
  86#ifdef HAVE_JUMP_LABEL
  87
  88#define dd_key_init(key, init) key = (init)
  89
  90#ifdef DEBUG
  91#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
  92        DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, .key.dd_key_true, \
  93                                          (STATIC_KEY_TRUE_INIT))
  94
  95#define DYNAMIC_DEBUG_BRANCH(descriptor) \
  96        static_branch_likely(&descriptor.key.dd_key_true)
  97#else
  98#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
  99        DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, .key.dd_key_false, \
 100                                          (STATIC_KEY_FALSE_INIT))
 101
 102#define DYNAMIC_DEBUG_BRANCH(descriptor) \
 103        static_branch_unlikely(&descriptor.key.dd_key_false)
 104#endif
 105
 106#else
 107
 108#define dd_key_init(key, init)
 109
 110#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
 111        DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, 0, 0)
 112
 113#ifdef DEBUG
 114#define DYNAMIC_DEBUG_BRANCH(descriptor) \
 115        likely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
 116#else
 117#define DYNAMIC_DEBUG_BRANCH(descriptor) \
 118        unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
 119#endif
 120
 121#endif
 122
 123#define dynamic_pr_debug(fmt, ...)                              \
 124do {                                                            \
 125        DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);         \
 126        if (DYNAMIC_DEBUG_BRANCH(descriptor))                   \
 127                __dynamic_pr_debug(&descriptor, pr_fmt(fmt),    \
 128                                   ##__VA_ARGS__);              \
 129} while (0)
 130
 131#define dynamic_dev_dbg(dev, fmt, ...)                          \
 132do {                                                            \
 133        DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);         \
 134        if (DYNAMIC_DEBUG_BRANCH(descriptor))                   \
 135                __dynamic_dev_dbg(&descriptor, dev, fmt,        \
 136                                  ##__VA_ARGS__);               \
 137} while (0)
 138
 139#define dynamic_netdev_dbg(dev, fmt, ...)                       \
 140do {                                                            \
 141        DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);         \
 142        if (DYNAMIC_DEBUG_BRANCH(descriptor))                   \
 143                __dynamic_netdev_dbg(&descriptor, dev, fmt,     \
 144                                     ##__VA_ARGS__);            \
 145} while (0)
 146
 147#define dynamic_hex_dump(prefix_str, prefix_type, rowsize,      \
 148                         groupsize, buf, len, ascii)            \
 149do {                                                            \
 150        DEFINE_DYNAMIC_DEBUG_METADATA(descriptor,               \
 151                __builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\
 152        if (DYNAMIC_DEBUG_BRANCH(descriptor))                   \
 153                print_hex_dump(KERN_DEBUG, prefix_str,          \
 154                               prefix_type, rowsize, groupsize, \
 155                               buf, len, ascii);                \
 156} while (0)
 157
 158#else
 159
 160#include <linux/string.h>
 161#include <linux/errno.h>
 162
 163static inline int ddebug_remove_module(const char *mod)
 164{
 165        return 0;
 166}
 167
 168static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,
 169                                                const char *modname)
 170{
 171        if (strstr(param, "dyndbg")) {
 172                /* avoid pr_warn(), which wants pr_fmt() fully defined */
 173                printk(KERN_WARNING "dyndbg param is supported only in "
 174                        "CONFIG_DYNAMIC_DEBUG builds\n");
 175                return 0; /* allow and ignore */
 176        }
 177        return -EINVAL;
 178}
 179
 180#define dynamic_pr_debug(fmt, ...)                                      \
 181        do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0)
 182#define dynamic_dev_dbg(dev, fmt, ...)                                  \
 183        do { if (0) dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); } while (0)
 184#endif
 185
 186#endif
 187