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/marker.h> 15 #include <linux/mutex.h> 16 #include <linux/ctype.h> 17 #include <linux/list.h> 18 #include <linux/slab.h> 19 #include <linux/fs.h> 20 21 #include "trace.h" 22 23 #ifdef CONFIG_MODULES 24 25 /* 26 * modules trace_printk()'s formats are autosaved in struct trace_bprintk_fmt 27 * which are queued on trace_bprintk_fmt_list. 28 */ 29 static LIST_HEAD(trace_bprintk_fmt_list); 30 31 /* serialize accesses to trace_bprintk_fmt_list */ 32 static DEFINE_MUTEX(btrace_mutex); 33 34 struct trace_bprintk_fmt { 35 struct list_head list; 36 char fmt[0]; 37 }; 38 39 static inline struct trace_bprintk_fmt *lookup_format(const char *fmt) 40 { 41 struct trace_bprintk_fmt *pos; 42 list_for_each_entry(pos, &trace_bprintk_fmt_list, list) { 43 if (!strcmp(pos->fmt, fmt)) 44 return pos; 45 } 46 return NULL; 47 } 48 49 static 50 void hold_module_trace_bprintk_format(const char **start, const char **end) 51 { 52 const char **iter; 53 54 mutex_lock(&btrace_mutex); 55 for (iter = start; iter < end; iter++) { 56 struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter); 57 if (tb_fmt) { 58 *iter = tb_fmt->fmt; 59 continue; 60 } 61 62 tb_fmt = kmalloc(offsetof(struct trace_bprintk_fmt, fmt) 63 + strlen(*iter) + 1, GFP_KERNEL); 64 if (tb_fmt) { 65 list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list); 66 strcpy(tb_fmt->fmt, *iter); 67 *iter = tb_fmt->fmt; 68 } else 69 *iter = NULL; 70 } 71 mutex_unlock(&btrace_mutex); 72 } 73 74 static int module_trace_bprintk_format_notify(struct notifier_block *self, 75 unsigned long val, void *data) 76 { 77 struct module *mod = data; 78 if (mod->num_trace_bprintk_fmt) { 79 const char **start = mod->trace_bprintk_fmt_start; 80 const char **end = start + mod->num_trace_bprintk_fmt; 81 82 if (val == MODULE_STATE_COMING) 83 hold_module_trace_bprintk_format(start, end); 84 } 85 return 0; 86 } 87 88 #else /* !CONFIG_MODULES */ 89 __init static int 90 module_trace_bprintk_format_notify(struct notifier_block *self, 91 unsigned long val, void *data) 92 { 93 return 0; 94 } 95 #endif /* CONFIG_MODULES */ 96 97 98 __initdata_or_module static 99 struct notifier_block module_trace_bprintk_format_nb = { 100 .notifier_call = module_trace_bprintk_format_notify, 101 }; 102 103 int __trace_bprintk(unsigned long ip, const char *fmt, ...) 104 { 105 int ret; 106 va_list ap; 107 108 if (unlikely(!fmt)) 109 return 0; 110 111 if (!(trace_flags & TRACE_ITER_PRINTK)) 112 return 0; 113 114 va_start(ap, fmt); 115 ret = trace_vbprintk(ip, fmt, ap); 116 va_end(ap); 117 return ret; 118 } 119 EXPORT_SYMBOL_GPL(__trace_bprintk); 120 121 int __ftrace_vbprintk(unsigned long ip, const char *fmt, va_list ap) 122 { 123 if (unlikely(!fmt)) 124 return 0; 125 126 if (!(trace_flags & TRACE_ITER_PRINTK)) 127 return 0; 128 129 return trace_vbprintk(ip, fmt, ap); 130 } 131 EXPORT_SYMBOL_GPL(__ftrace_vbprintk); 132 133 int __trace_printk(unsigned long ip, const char *fmt, ...) 134 { 135 int ret; 136 va_list ap; 137 138 if (!(trace_flags & TRACE_ITER_PRINTK)) 139 return 0; 140 141 va_start(ap, fmt); 142 ret = trace_vprintk(ip, fmt, ap); 143 va_end(ap); 144 return ret; 145 } 146 EXPORT_SYMBOL_GPL(__trace_printk); 147 148 int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap) 149 { 150 if (!(trace_flags & TRACE_ITER_PRINTK)) 151 return 0; 152 153 return trace_vprintk(ip, fmt, ap); 154 } 155 EXPORT_SYMBOL_GPL(__ftrace_vprintk); 156 157 static void * 158 t_next(struct seq_file *m, void *v, loff_t *pos) 159 { 160 const char **fmt = m->private; 161 const char **next = fmt; 162 163 (*pos)++; 164 165 if ((unsigned long)fmt >= (unsigned long)__stop___trace_bprintk_fmt) 166 return NULL; 167 168 next = fmt; 169 m->private = ++next; 170 171 return fmt; 172 } 173 174 static void *t_start(struct seq_file *m, loff_t *pos) 175 { 176 return t_next(m, NULL, pos); 177 } 178 179 static int t_show(struct seq_file *m, void *v) 180 { 181 const char **fmt = v; 182 const char *str = *fmt; 183 int i; 184 185 seq_printf(m, "0x%lx : \"", (unsigned long)fmt); 186 187 /* 188 * Tabs and new lines need to be converted. 189 */ 190 for (i = 0; str[i]; i++) { 191 switch (str[i]) { 192 case '\n': 193 seq_puts(m, "\\n"); 194 break; 195 case '\t': 196 seq_puts(m, "\\t"); 197 break; 198 case '\\': 199 seq_puts(m, "\\"); 200 break; 201 case '"': 202 seq_puts(m, "\\\""); 203 break; 204 default: 205 seq_putc(m, str[i]); 206 } 207 } 208 seq_puts(m, "\"\n"); 209 210 return 0; 211 } 212 213 static void t_stop(struct seq_file *m, void *p) 214 { 215 } 216 217 static const struct seq_operations show_format_seq_ops = { 218 .start = t_start, 219 .next = t_next, 220 .show = t_show, 221 .stop = t_stop, 222 }; 223 224 static int 225 ftrace_formats_open(struct inode *inode, struct file *file) 226 { 227 int ret; 228 229 ret = seq_open(file, &show_format_seq_ops); 230 if (!ret) { 231 struct seq_file *m = file->private_data; 232 233 m->private = __start___trace_bprintk_fmt; 234 } 235 return ret; 236 } 237 238 static const struct file_operations ftrace_formats_fops = { 239 .open = ftrace_formats_open, 240 .read = seq_read, 241 .llseek = seq_lseek, 242 .release = seq_release, 243 }; 244 245 static __init int init_trace_printk_function_export(void) 246 { 247 struct dentry *d_tracer; 248 249 d_tracer = tracing_init_dentry(); 250 if (!d_tracer) 251 return 0; 252 253 trace_create_file("printk_formats", 0444, d_tracer, 254 NULL, &ftrace_formats_fops); 255 256 return 0; 257 } 258 259 fs_initcall(init_trace_printk_function_export); 260 261 static __init int init_trace_printk(void) 262 { 263 return register_module_notifier(&module_trace_bprintk_format_nb); 264 } 265 266 early_initcall(init_trace_printk); 267