Branch data Line data Source code
1 : : /*
2 : : * trace binary printk
3 : : *
4 : : * Copyright (C) 2008 Lai Jiangshan <laijs@cn.fujitsu.com>
5 : : *
6 : : */
7 : : #include <linux/seq_file.h>
8 : : #include <linux/debugfs.h>
9 : : #include <linux/uaccess.h>
10 : : #include <linux/kernel.h>
11 : : #include <linux/ftrace.h>
12 : : #include <linux/string.h>
13 : : #include <linux/module.h>
14 : : #include <linux/mutex.h>
15 : : #include <linux/ctype.h>
16 : : #include <linux/list.h>
17 : : #include <linux/slab.h>
18 : : #include <linux/fs.h>
19 : :
20 : : #include "trace.h"
21 : :
22 : : #ifdef CONFIG_MODULES
23 : :
24 : : /*
25 : : * modules trace_printk()'s formats are autosaved in struct trace_bprintk_fmt
26 : : * which are queued on trace_bprintk_fmt_list.
27 : : */
28 : : static LIST_HEAD(trace_bprintk_fmt_list);
29 : :
30 : : /* serialize accesses to trace_bprintk_fmt_list */
31 : : static DEFINE_MUTEX(btrace_mutex);
32 : :
33 : : struct trace_bprintk_fmt {
34 : : struct list_head list;
35 : : const char *fmt;
36 : : };
37 : :
38 : : static inline struct trace_bprintk_fmt *lookup_format(const char *fmt)
39 : : {
40 : : struct trace_bprintk_fmt *pos;
41 [ # # ]: 0 : list_for_each_entry(pos, &trace_bprintk_fmt_list, list) {
42 [ # # ]: 0 : if (!strcmp(pos->fmt, fmt))
43 : : return pos;
44 : : }
45 : : return NULL;
46 : : }
47 : :
48 : : static
49 : 0 : void hold_module_trace_bprintk_format(const char **start, const char **end)
50 : : {
51 : : const char **iter;
52 : : char *fmt;
53 : :
54 : : /* allocate the trace_printk per cpu buffers */
55 [ # # ]: 0 : if (start != end)
56 : 0 : trace_printk_init_buffers();
57 : :
58 : 0 : mutex_lock(&btrace_mutex);
59 [ # # ]: 0 : for (iter = start; iter < end; iter++) {
60 : 0 : struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter);
61 [ # # ]: 0 : if (tb_fmt) {
62 : 0 : *iter = tb_fmt->fmt;
63 : 0 : continue;
64 : : }
65 : :
66 : : fmt = NULL;
67 : : tb_fmt = kmalloc(sizeof(*tb_fmt), GFP_KERNEL);
68 [ # # ]: 0 : if (tb_fmt) {
69 : 0 : fmt = kmalloc(strlen(*iter) + 1, GFP_KERNEL);
70 [ # # ]: 0 : if (fmt) {
71 : 0 : list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list);
72 : 0 : strcpy(fmt, *iter);
73 : 0 : tb_fmt->fmt = fmt;
74 : : } else
75 : 0 : kfree(tb_fmt);
76 : : }
77 : 0 : *iter = fmt;
78 : :
79 : : }
80 : 0 : mutex_unlock(&btrace_mutex);
81 : 0 : }
82 : :
83 : 0 : static int module_trace_bprintk_format_notify(struct notifier_block *self,
84 : : unsigned long val, void *data)
85 : : {
86 : : struct module *mod = data;
87 [ # # ]: 0 : if (mod->num_trace_bprintk_fmt) {
88 : 0 : const char **start = mod->trace_bprintk_fmt_start;
89 : 0 : const char **end = start + mod->num_trace_bprintk_fmt;
90 : :
91 [ # # ]: 0 : if (val == MODULE_STATE_COMING)
92 : 0 : hold_module_trace_bprintk_format(start, end);
93 : : }
94 : 0 : return 0;
95 : : }
96 : :
97 : : /*
98 : : * The debugfs/tracing/printk_formats file maps the addresses with
99 : : * the ASCII formats that are used in the bprintk events in the
100 : : * buffer. For userspace tools to be able to decode the events from
101 : : * the buffer, they need to be able to map the address with the format.
102 : : *
103 : : * The addresses of the bprintk formats are in their own section
104 : : * __trace_printk_fmt. But for modules we copy them into a link list.
105 : : * The code to print the formats and their addresses passes around the
106 : : * address of the fmt string. If the fmt address passed into the seq
107 : : * functions is within the kernel core __trace_printk_fmt section, then
108 : : * it simply uses the next pointer in the list.
109 : : *
110 : : * When the fmt pointer is outside the kernel core __trace_printk_fmt
111 : : * section, then we need to read the link list pointers. The trick is
112 : : * we pass the address of the string to the seq function just like
113 : : * we do for the kernel core formats. To get back the structure that
114 : : * holds the format, we simply use containerof() and then go to the
115 : : * next format in the list.
116 : : */
117 : : static const char **
118 : 0 : find_next_mod_format(int start_index, void *v, const char **fmt, loff_t *pos)
119 : : {
120 : : struct trace_bprintk_fmt *mod_fmt;
121 : :
122 [ # # ]: 0 : if (list_empty(&trace_bprintk_fmt_list))
123 : : return NULL;
124 : :
125 : : /*
126 : : * v will point to the address of the fmt record from t_next
127 : : * v will be NULL from t_start.
128 : : * If this is the first pointer or called from start
129 : : * then we need to walk the list.
130 : : */
131 [ # # ][ # # ]: 0 : if (!v || start_index == *pos) {
132 : : struct trace_bprintk_fmt *p;
133 : :
134 : : /* search the module list */
135 [ # # ]: 0 : list_for_each_entry(p, &trace_bprintk_fmt_list, list) {
136 [ # # ]: 0 : if (start_index == *pos)
137 : 0 : return &p->fmt;
138 : 0 : start_index++;
139 : : }
140 : : /* pos > index */
141 : : return NULL;
142 : : }
143 : :
144 : : /*
145 : : * v points to the address of the fmt field in the mod list
146 : : * structure that holds the module print format.
147 : : */
148 : : mod_fmt = container_of(v, typeof(*mod_fmt), fmt);
149 [ # # ]: 0 : if (mod_fmt->list.next == &trace_bprintk_fmt_list)
150 : : return NULL;
151 : :
152 : : mod_fmt = container_of(mod_fmt->list.next, typeof(*mod_fmt), list);
153 : :
154 : 0 : return &mod_fmt->fmt;
155 : : }
156 : :
157 : : static void format_mod_start(void)
158 : : {
159 : 0 : mutex_lock(&btrace_mutex);
160 : : }
161 : :
162 : : static void format_mod_stop(void)
163 : : {
164 : 0 : mutex_unlock(&btrace_mutex);
165 : : }
166 : :
167 : : #else /* !CONFIG_MODULES */
168 : : __init static int
169 : : module_trace_bprintk_format_notify(struct notifier_block *self,
170 : : unsigned long val, void *data)
171 : : {
172 : : return 0;
173 : : }
174 : : static inline const char **
175 : : find_next_mod_format(int start_index, void *v, const char **fmt, loff_t *pos)
176 : : {
177 : : return NULL;
178 : : }
179 : : static inline void format_mod_start(void) { }
180 : : static inline void format_mod_stop(void) { }
181 : : #endif /* CONFIG_MODULES */
182 : :
183 : :
184 : : __initdata_or_module static
185 : : struct notifier_block module_trace_bprintk_format_nb = {
186 : : .notifier_call = module_trace_bprintk_format_notify,
187 : : };
188 : :
189 : 0 : int __trace_bprintk(unsigned long ip, const char *fmt, ...)
190 : : {
191 : : int ret;
192 : : va_list ap;
193 : :
194 [ # # ]: 0 : if (unlikely(!fmt))
195 : : return 0;
196 : :
197 [ # # ]: 0 : if (!(trace_flags & TRACE_ITER_PRINTK))
198 : : return 0;
199 : :
200 : 0 : va_start(ap, fmt);
201 : 0 : ret = trace_vbprintk(ip, fmt, ap);
202 : 0 : va_end(ap);
203 : 0 : return ret;
204 : : }
205 : : EXPORT_SYMBOL_GPL(__trace_bprintk);
206 : :
207 : 0 : int __ftrace_vbprintk(unsigned long ip, const char *fmt, va_list ap)
208 : : {
209 [ # # ]: 0 : if (unlikely(!fmt))
210 : : return 0;
211 : :
212 [ # # ]: 0 : if (!(trace_flags & TRACE_ITER_PRINTK))
213 : : return 0;
214 : :
215 : 0 : return trace_vbprintk(ip, fmt, ap);
216 : : }
217 : : EXPORT_SYMBOL_GPL(__ftrace_vbprintk);
218 : :
219 : 0 : int __trace_printk(unsigned long ip, const char *fmt, ...)
220 : : {
221 : : int ret;
222 : : va_list ap;
223 : :
224 [ # # ]: 0 : if (!(trace_flags & TRACE_ITER_PRINTK))
225 : : return 0;
226 : :
227 : 0 : va_start(ap, fmt);
228 : 0 : ret = trace_vprintk(ip, fmt, ap);
229 : 0 : va_end(ap);
230 : 0 : return ret;
231 : : }
232 : : EXPORT_SYMBOL_GPL(__trace_printk);
233 : :
234 : 0 : int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap)
235 : : {
236 [ # # ]: 0 : if (!(trace_flags & TRACE_ITER_PRINTK))
237 : : return 0;
238 : :
239 : 0 : return trace_vprintk(ip, fmt, ap);
240 : : }
241 : : EXPORT_SYMBOL_GPL(__ftrace_vprintk);
242 : :
243 : 0 : static const char **find_next(void *v, loff_t *pos)
244 : : {
245 : : const char **fmt = v;
246 : : int start_index;
247 : : int last_index;
248 : :
249 : 0 : start_index = __stop___trace_bprintk_fmt - __start___trace_bprintk_fmt;
250 : :
251 [ # # ]: 0 : if (*pos < start_index)
252 : 0 : return __start___trace_bprintk_fmt + *pos;
253 : :
254 : : /*
255 : : * The __tracepoint_str section is treated the same as the
256 : : * __trace_printk_fmt section. The difference is that the
257 : : * __trace_printk_fmt section should only be used by trace_printk()
258 : : * in a debugging environment, as if anything exists in that section
259 : : * the trace_prink() helper buffers are allocated, which would just
260 : : * waste space in a production environment.
261 : : *
262 : : * The __tracepoint_str sections on the other hand are used by
263 : : * tracepoints which need to map pointers to their strings to
264 : : * the ASCII text for userspace.
265 : : */
266 : : last_index = start_index;
267 : 0 : start_index = __stop___tracepoint_str - __start___tracepoint_str;
268 : :
269 [ # # ]: 0 : if (*pos < last_index + start_index)
270 : 0 : return __start___tracepoint_str + (*pos - last_index);
271 : :
272 : 0 : return find_next_mod_format(start_index, v, fmt, pos);
273 : : }
274 : :
275 : : static void *
276 : 0 : t_start(struct seq_file *m, loff_t *pos)
277 : : {
278 : : format_mod_start();
279 : 0 : return find_next(NULL, pos);
280 : : }
281 : :
282 : 0 : static void *t_next(struct seq_file *m, void * v, loff_t *pos)
283 : : {
284 : 0 : (*pos)++;
285 : 0 : return find_next(v, pos);
286 : : }
287 : :
288 : 0 : static int t_show(struct seq_file *m, void *v)
289 : : {
290 : : const char **fmt = v;
291 : 0 : const char *str = *fmt;
292 : : int i;
293 : :
294 : 0 : seq_printf(m, "0x%lx : \"", *(unsigned long *)fmt);
295 : :
296 : : /*
297 : : * Tabs and new lines need to be converted.
298 : : */
299 [ # # ]: 0 : for (i = 0; str[i]; i++) {
300 [ # # # # : 0 : switch (str[i]) {
# ]
301 : : case '\n':
302 : 0 : seq_puts(m, "\\n");
303 : 0 : break;
304 : : case '\t':
305 : 0 : seq_puts(m, "\\t");
306 : 0 : break;
307 : : case '\\':
308 : 0 : seq_puts(m, "\\");
309 : 0 : break;
310 : : case '"':
311 : 0 : seq_puts(m, "\\\"");
312 : 0 : break;
313 : : default:
314 : 0 : seq_putc(m, str[i]);
315 : : }
316 : : }
317 : 0 : seq_puts(m, "\"\n");
318 : :
319 : 0 : return 0;
320 : : }
321 : :
322 : 0 : static void t_stop(struct seq_file *m, void *p)
323 : : {
324 : : format_mod_stop();
325 : 0 : }
326 : :
327 : : static const struct seq_operations show_format_seq_ops = {
328 : : .start = t_start,
329 : : .next = t_next,
330 : : .show = t_show,
331 : : .stop = t_stop,
332 : : };
333 : :
334 : : static int
335 : 0 : ftrace_formats_open(struct inode *inode, struct file *file)
336 : : {
337 : 0 : return seq_open(file, &show_format_seq_ops);
338 : : }
339 : :
340 : : static const struct file_operations ftrace_formats_fops = {
341 : : .open = ftrace_formats_open,
342 : : .read = seq_read,
343 : : .llseek = seq_lseek,
344 : : .release = seq_release,
345 : : };
346 : :
347 : 0 : static __init int init_trace_printk_function_export(void)
348 : : {
349 : : struct dentry *d_tracer;
350 : :
351 : 0 : d_tracer = tracing_init_dentry();
352 [ # # ]: 0 : if (!d_tracer)
353 : : return 0;
354 : :
355 : 0 : trace_create_file("printk_formats", 0444, d_tracer,
356 : : NULL, &ftrace_formats_fops);
357 : :
358 : 0 : return 0;
359 : : }
360 : :
361 : : fs_initcall(init_trace_printk_function_export);
362 : :
363 : 0 : static __init int init_trace_printk(void)
364 : : {
365 : 0 : return register_module_notifier(&module_trace_bprintk_format_nb);
366 : : }
367 : :
368 : : early_initcall(init_trace_printk);
|