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