root/kernel/trace/trace_printk.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lookup_format
  2. hold_module_trace_bprintk_format
  3. module_trace_bprintk_format_notify
  4. find_next_mod_format
  5. format_mod_start
  6. format_mod_stop
  7. module_trace_bprintk_format_notify
  8. find_next_mod_format
  9. format_mod_start
  10. format_mod_stop
  11. trace_printk_control
  12. __trace_bprintk
  13. __ftrace_vbprintk
  14. __trace_printk
  15. __ftrace_vprintk
  16. find_next
  17. t_start
  18. t_next
  19. t_show
  20. t_stop
  21. ftrace_formats_open
  22. init_trace_printk_function_export
  23. init_trace_printk

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

/* [<][>][^][v][top][bottom][index][help] */