aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/asm-generic/vmlinux.lds.h9
-rw-r--r--include/linux/ftrace.h1
-rw-r--r--include/linux/kernel.h80
-rw-r--r--include/linux/module.h5
-rw-r--r--include/linux/ring_buffer.h15
-rw-r--r--include/linux/string.h7
-rw-r--r--include/trace/power.h2
-rw-r--r--kernel/trace/Kconfig2
-rw-r--r--kernel/trace/Makefile2
-rw-r--r--kernel/trace/ftrace.c17
-rw-r--r--kernel/trace/ring_buffer.c2
-rw-r--r--kernel/trace/trace.c165
-rw-r--r--kernel/trace/trace.h15
-rw-r--r--kernel/trace/trace_event_types.h165
-rw-r--r--kernel/trace/trace_events.c12
-rw-r--r--kernel/trace/trace_events_stage_2.h53
-rw-r--r--kernel/trace/trace_export.c81
-rw-r--r--kernel/trace/trace_format.h55
-rw-r--r--kernel/trace/trace_functions_graph.c6
-rw-r--r--kernel/trace/trace_mmiotrace.c9
-rw-r--r--kernel/trace/trace_output.c41
-rw-r--r--kernel/trace/trace_output.h2
-rw-r--r--kernel/trace/trace_printk.c138
-rw-r--r--kernel/trace/trace_sysprof.c2
-rw-r--r--lib/Kconfig3
-rw-r--r--lib/vsprintf.c1006
26 files changed, 1468 insertions, 427 deletions
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 9d974914e914..89997dfdf3d0 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -69,6 +69,14 @@
69#define FTRACE_EVENTS() 69#define FTRACE_EVENTS()
70#endif 70#endif
71 71
72#ifdef CONFIG_TRACING
73#define TRACE_PRINTKS() VMLINUX_SYMBOL(__start___trace_bprintk_fmt) = .; \
74 *(__trace_printk_fmt) /* Trace_printk fmt' pointer */ \
75 VMLINUX_SYMBOL(__stop___trace_bprintk_fmt) = .;
76#else
77#define TRACE_PRINTKS()
78#endif
79
72/* .data section */ 80/* .data section */
73#define DATA_DATA \ 81#define DATA_DATA \
74 *(.data) \ 82 *(.data) \
@@ -100,6 +108,7 @@
100 *(__vermagic) /* Kernel version magic */ \ 108 *(__vermagic) /* Kernel version magic */ \
101 *(__markers_strings) /* Markers: strings */ \ 109 *(__markers_strings) /* Markers: strings */ \
102 *(__tracepoints_strings)/* Tracepoints: strings */ \ 110 *(__tracepoints_strings)/* Tracepoints: strings */ \
111 TRACE_PRINTKS() \
103 } \ 112 } \
104 \ 113 \
105 .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \ 114 .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 498769425eb2..e1583f2639b0 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -223,7 +223,6 @@ extern int ftrace_make_nop(struct module *mod,
223 */ 223 */
224extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr); 224extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr);
225 225
226
227/* May be defined in arch */ 226/* May be defined in arch */
228extern int ftrace_arch_read_dyn_info(char *buf, int size); 227extern int ftrace_arch_read_dyn_info(char *buf, int size);
229 228
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 08bf5da86676..4e726b9a71ec 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -242,6 +242,19 @@ extern struct ratelimit_state printk_ratelimit_state;
242extern int printk_ratelimit(void); 242extern int printk_ratelimit(void);
243extern bool printk_timed_ratelimit(unsigned long *caller_jiffies, 243extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
244 unsigned int interval_msec); 244 unsigned int interval_msec);
245
246/*
247 * Print a one-time message (analogous to WARN_ONCE() et al):
248 */
249#define printk_once(x...) ({ \
250 static int __print_once = 1; \
251 \
252 if (__print_once) { \
253 __print_once = 0; \
254 printk(x); \
255 } \
256})
257
245#else 258#else
246static inline int vprintk(const char *s, va_list args) 259static inline int vprintk(const char *s, va_list args)
247 __attribute__ ((format (printf, 1, 0))); 260 __attribute__ ((format (printf, 1, 0)));
@@ -253,6 +266,10 @@ static inline int printk_ratelimit(void) { return 0; }
253static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \ 266static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \
254 unsigned int interval_msec) \ 267 unsigned int interval_msec) \
255 { return false; } 268 { return false; }
269
270/* No effect, but we still get type checking even in the !PRINTK case: */
271#define printk_once(x...) printk(x)
272
256#endif 273#endif
257 274
258extern int printk_needs_cpu(int cpu); 275extern int printk_needs_cpu(int cpu);
@@ -369,8 +386,35 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
369 386
370/* 387/*
371 * General tracing related utility functions - trace_printk(), 388 * General tracing related utility functions - trace_printk(),
372 * tracing_start()/tracing_stop: 389 * tracing_on/tracing_off and tracing_start()/tracing_stop
390 *
391 * Use tracing_on/tracing_off when you want to quickly turn on or off
392 * tracing. It simply enables or disables the recording of the trace events.
393 * This also corresponds to the user space debugfs/tracing/tracing_on
394 * file, which gives a means for the kernel and userspace to interact.
395 * Place a tracing_off() in the kernel where you want tracing to end.
396 * From user space, examine the trace, and then echo 1 > tracing_on
397 * to continue tracing.
398 *
399 * tracing_stop/tracing_start has slightly more overhead. It is used
400 * by things like suspend to ram where disabling the recording of the
401 * trace is not enough, but tracing must actually stop because things
402 * like calling smp_processor_id() may crash the system.
403 *
404 * Most likely, you want to use tracing_on/tracing_off.
373 */ 405 */
406#ifdef CONFIG_RING_BUFFER
407void tracing_on(void);
408void tracing_off(void);
409/* trace_off_permanent stops recording with no way to bring it back */
410void tracing_off_permanent(void);
411int tracing_is_on(void);
412#else
413static inline void tracing_on(void) { }
414static inline void tracing_off(void) { }
415static inline void tracing_off_permanent(void) { }
416static inline int tracing_is_on(void) { return 0; }
417#endif
374#ifdef CONFIG_TRACING 418#ifdef CONFIG_TRACING
375extern void tracing_start(void); 419extern void tracing_start(void);
376extern void tracing_stop(void); 420extern void tracing_stop(void);
@@ -379,6 +423,16 @@ extern void ftrace_off_permanent(void);
379extern void 423extern void
380ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3); 424ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3);
381 425
426static inline void __attribute__ ((format (printf, 1, 2)))
427____trace_printk_check_format(const char *fmt, ...)
428{
429}
430#define __trace_printk_check_format(fmt, args...) \
431do { \
432 if (0) \
433 ____trace_printk_check_format(fmt, ##args); \
434} while (0)
435
382/** 436/**
383 * trace_printk - printf formatting in the ftrace buffer 437 * trace_printk - printf formatting in the ftrace buffer
384 * @fmt: the printf format for printing 438 * @fmt: the printf format for printing
@@ -395,13 +449,31 @@ ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3);
395 * Please refrain from leaving trace_printks scattered around in 449 * Please refrain from leaving trace_printks scattered around in
396 * your code. 450 * your code.
397 */ 451 */
398# define trace_printk(fmt...) __trace_printk(_THIS_IP_, fmt) 452
453#define trace_printk(fmt, args...) \
454do { \
455 static const char *trace_printk_fmt \
456 __attribute__((section("__trace_printk_fmt"))); \
457 trace_printk_fmt = fmt; \
458 __trace_printk_check_format(fmt, ##args); \
459 __trace_printk(_THIS_IP_, trace_printk_fmt, ##args); \
460} while (0)
461
399extern int 462extern int
400__trace_printk(unsigned long ip, const char *fmt, ...) 463__trace_printk(unsigned long ip, const char *fmt, ...)
401 __attribute__ ((format (printf, 2, 3))); 464 __attribute__ ((format (printf, 2, 3)));
402# define ftrace_vprintk(fmt, ap) __trace_printk(_THIS_IP_, fmt, ap) 465
466#define ftrace_vprintk(fmt, vargs) \
467do { \
468 static const char *trace_printk_fmt \
469 __attribute__((section("__trace_printk_fmt"))); \
470 trace_printk_fmt = fmt; \
471 __ftrace_vprintk(_THIS_IP_, trace_printk_fmt, vargs); \
472} while (0)
473
403extern int 474extern int
404__ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap); 475__ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap);
476
405extern void ftrace_dump(void); 477extern void ftrace_dump(void);
406#else 478#else
407static inline void 479static inline void
@@ -423,7 +495,7 @@ ftrace_vprintk(const char *fmt, va_list ap)
423 return 0; 495 return 0;
424} 496}
425static inline void ftrace_dump(void) { } 497static inline void ftrace_dump(void) { }
426#endif 498#endif /* CONFIG_TRACING */
427 499
428/* 500/*
429 * Display an IP address in readable format. 501 * Display an IP address in readable format.
diff --git a/include/linux/module.h b/include/linux/module.h
index 145a75528cc1..22d9878e868c 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -329,6 +329,11 @@ struct module
329 unsigned int num_tracepoints; 329 unsigned int num_tracepoints;
330#endif 330#endif
331 331
332#ifdef CONFIG_TRACING
333 const char **trace_bprintk_fmt_start;
334 unsigned int num_trace_bprintk_fmt;
335#endif
336
332#ifdef CONFIG_MODULE_UNLOAD 337#ifdef CONFIG_MODULE_UNLOAD
333 /* What modules depend on me? */ 338 /* What modules depend on me? */
334 struct list_head modules_which_use_me; 339 struct list_head modules_which_use_me;
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index 79fcbc4b09d6..b1a0068a5557 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -124,21 +124,6 @@ void ring_buffer_normalize_time_stamp(int cpu, u64 *ts);
124size_t ring_buffer_page_len(void *page); 124size_t ring_buffer_page_len(void *page);
125 125
126 126
127/*
128 * The below functions are fine to use outside the tracing facility.
129 */
130#ifdef CONFIG_RING_BUFFER
131void tracing_on(void);
132void tracing_off(void);
133void tracing_off_permanent(void);
134int tracing_is_on(void);
135#else
136static inline void tracing_on(void) { }
137static inline void tracing_off(void) { }
138static inline void tracing_off_permanent(void) { }
139static inline int tracing_is_on(void) { return 0; }
140#endif
141
142void *ring_buffer_alloc_read_page(struct ring_buffer *buffer); 127void *ring_buffer_alloc_read_page(struct ring_buffer *buffer);
143void ring_buffer_free_read_page(struct ring_buffer *buffer, void *data); 128void ring_buffer_free_read_page(struct ring_buffer *buffer, void *data);
144int ring_buffer_read_page(struct ring_buffer *buffer, void **data_page, 129int ring_buffer_read_page(struct ring_buffer *buffer, void **data_page,
diff --git a/include/linux/string.h b/include/linux/string.h
index d18fc198aa2f..27ac31784ad2 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -10,6 +10,7 @@
10#include <linux/compiler.h> /* for inline */ 10#include <linux/compiler.h> /* for inline */
11#include <linux/types.h> /* for size_t */ 11#include <linux/types.h> /* for size_t */
12#include <linux/stddef.h> /* for NULL */ 12#include <linux/stddef.h> /* for NULL */
13#include <stdarg.h>
13 14
14extern char *strndup_user(const char __user *, long); 15extern char *strndup_user(const char __user *, long);
15 16
@@ -111,6 +112,12 @@ extern void argv_free(char **argv);
111 112
112extern bool sysfs_streq(const char *s1, const char *s2); 113extern bool sysfs_streq(const char *s1, const char *s2);
113 114
115#ifdef CONFIG_BINARY_PRINTF
116int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args);
117int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf);
118int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...) __printf(3, 4);
119#endif
120
114extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos, 121extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
115 const void *from, size_t available); 122 const void *from, size_t available);
116 123
diff --git a/include/trace/power.h b/include/trace/power.h
index 2c733e58e89c..38aca537e497 100644
--- a/include/trace/power.h
+++ b/include/trace/power.h
@@ -11,12 +11,10 @@ enum {
11}; 11};
12 12
13struct power_trace { 13struct power_trace {
14#ifdef CONFIG_POWER_TRACER
15 ktime_t stamp; 14 ktime_t stamp;
16 ktime_t end; 15 ktime_t end;
17 int type; 16 int type;
18 int state; 17 int state;
19#endif
20}; 18};
21 19
22DECLARE_TRACE(power_start, 20DECLARE_TRACE(power_start,
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 5d733da5345a..8e4a2a61cd75 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -52,6 +52,7 @@ config TRACING
52 select STACKTRACE if STACKTRACE_SUPPORT 52 select STACKTRACE if STACKTRACE_SUPPORT
53 select TRACEPOINTS 53 select TRACEPOINTS
54 select NOP_TRACER 54 select NOP_TRACER
55 select BINARY_PRINTF
55 56
56# 57#
57# Minimum requirements an architecture has to meet for us to 58# Minimum requirements an architecture has to meet for us to
@@ -61,6 +62,7 @@ config TRACING_SUPPORT
61 bool 62 bool
62 depends on TRACE_IRQFLAGS_SUPPORT 63 depends on TRACE_IRQFLAGS_SUPPORT
63 depends on STACKTRACE_SUPPORT 64 depends on STACKTRACE_SUPPORT
65 default y
64 66
65if TRACING_SUPPORT 67if TRACING_SUPPORT
66 68
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index c931fe0560cb..c7a2943796eb 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_TRACING) += trace.o
22obj-$(CONFIG_TRACING) += trace_clock.o 22obj-$(CONFIG_TRACING) += trace_clock.o
23obj-$(CONFIG_TRACING) += trace_output.o 23obj-$(CONFIG_TRACING) += trace_output.o
24obj-$(CONFIG_TRACING) += trace_stat.o 24obj-$(CONFIG_TRACING) += trace_stat.o
25obj-$(CONFIG_TRACING) += trace_printk.o
25obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o 26obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
26obj-$(CONFIG_SYSPROF_TRACER) += trace_sysprof.o 27obj-$(CONFIG_SYSPROF_TRACER) += trace_sysprof.o
27obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o 28obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o
@@ -41,5 +42,6 @@ obj-$(CONFIG_WORKQUEUE_TRACER) += trace_workqueue.o
41obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o 42obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o
42obj-$(CONFIG_EVENT_TRACER) += trace_events.o 43obj-$(CONFIG_EVENT_TRACER) += trace_events.o
43obj-$(CONFIG_EVENT_TRACER) += events.o 44obj-$(CONFIG_EVENT_TRACER) += events.o
45obj-$(CONFIG_EVENT_TRACER) += trace_export.o
44 46
45libftrace-y := ftrace.o 47libftrace-y := ftrace.o
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 5a3a06b21eee..d33d306bdcf4 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -218,10 +218,8 @@ static void ftrace_update_pid_func(void)
218{ 218{
219 ftrace_func_t func; 219 ftrace_func_t func;
220 220
221 mutex_lock(&ftrace_lock);
222
223 if (ftrace_trace_function == ftrace_stub) 221 if (ftrace_trace_function == ftrace_stub)
224 goto out; 222 return;
225 223
226 func = ftrace_trace_function; 224 func = ftrace_trace_function;
227 225
@@ -238,9 +236,6 @@ static void ftrace_update_pid_func(void)
238#else 236#else
239 __ftrace_trace_function = func; 237 __ftrace_trace_function = func;
240#endif 238#endif
241
242 out:
243 mutex_unlock(&ftrace_lock);
244} 239}
245 240
246/* set when tracing only a pid */ 241/* set when tracing only a pid */
@@ -1869,21 +1864,21 @@ ftrace_notrace_release(struct inode *inode, struct file *file)
1869 return ftrace_regex_release(inode, file, 0); 1864 return ftrace_regex_release(inode, file, 0);
1870} 1865}
1871 1866
1872static struct file_operations ftrace_avail_fops = { 1867static const struct file_operations ftrace_avail_fops = {
1873 .open = ftrace_avail_open, 1868 .open = ftrace_avail_open,
1874 .read = seq_read, 1869 .read = seq_read,
1875 .llseek = seq_lseek, 1870 .llseek = seq_lseek,
1876 .release = ftrace_avail_release, 1871 .release = ftrace_avail_release,
1877}; 1872};
1878 1873
1879static struct file_operations ftrace_failures_fops = { 1874static const struct file_operations ftrace_failures_fops = {
1880 .open = ftrace_failures_open, 1875 .open = ftrace_failures_open,
1881 .read = seq_read, 1876 .read = seq_read,
1882 .llseek = seq_lseek, 1877 .llseek = seq_lseek,
1883 .release = ftrace_avail_release, 1878 .release = ftrace_avail_release,
1884}; 1879};
1885 1880
1886static struct file_operations ftrace_filter_fops = { 1881static const struct file_operations ftrace_filter_fops = {
1887 .open = ftrace_filter_open, 1882 .open = ftrace_filter_open,
1888 .read = ftrace_regex_read, 1883 .read = ftrace_regex_read,
1889 .write = ftrace_filter_write, 1884 .write = ftrace_filter_write,
@@ -1891,7 +1886,7 @@ static struct file_operations ftrace_filter_fops = {
1891 .release = ftrace_filter_release, 1886 .release = ftrace_filter_release,
1892}; 1887};
1893 1888
1894static struct file_operations ftrace_notrace_fops = { 1889static const struct file_operations ftrace_notrace_fops = {
1895 .open = ftrace_notrace_open, 1890 .open = ftrace_notrace_open,
1896 .read = ftrace_regex_read, 1891 .read = ftrace_regex_read,
1897 .write = ftrace_notrace_write, 1892 .write = ftrace_notrace_write,
@@ -2423,7 +2418,7 @@ ftrace_pid_write(struct file *filp, const char __user *ubuf,
2423 return cnt; 2418 return cnt;
2424} 2419}
2425 2420
2426static struct file_operations ftrace_pid_fops = { 2421static const struct file_operations ftrace_pid_fops = {
2427 .read = ftrace_pid_read, 2422 .read = ftrace_pid_read,
2428 .write = ftrace_pid_write, 2423 .write = ftrace_pid_write,
2429}; 2424};
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index f7473645b9c6..178858492a89 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -2606,7 +2606,7 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
2606 return cnt; 2606 return cnt;
2607} 2607}
2608 2608
2609static struct file_operations rb_simple_fops = { 2609static const struct file_operations rb_simple_fops = {
2610 .open = tracing_open_generic, 2610 .open = tracing_open_generic,
2611 .read = rb_simple_read, 2611 .read = rb_simple_read,
2612 .write = rb_simple_write, 2612 .write = rb_simple_write,
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index c0e9c1263393..cc94f8642485 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1169,6 +1169,67 @@ void trace_graph_return(struct ftrace_graph_ret *trace)
1169} 1169}
1170#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 1170#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
1171 1171
1172
1173/**
1174 * trace_vprintk - write binary msg to tracing buffer
1175 *
1176 */
1177int trace_vprintk(unsigned long ip, int depth, const char *fmt, va_list args)
1178{
1179 static DEFINE_SPINLOCK(trace_buf_lock);
1180 static u32 trace_buf[TRACE_BUF_SIZE];
1181
1182 struct ring_buffer_event *event;
1183 struct trace_array *tr = &global_trace;
1184 struct trace_array_cpu *data;
1185 struct print_entry *entry;
1186 unsigned long flags;
1187 int resched;
1188 int cpu, len = 0, size, pc;
1189
1190 if (unlikely(tracing_selftest_running || tracing_disabled))
1191 return 0;
1192
1193 /* Don't pollute graph traces with trace_vprintk internals */
1194 pause_graph_tracing();
1195
1196 pc = preempt_count();
1197 resched = ftrace_preempt_disable();
1198 cpu = raw_smp_processor_id();
1199 data = tr->data[cpu];
1200
1201 if (unlikely(atomic_read(&data->disabled)))
1202 goto out;
1203
1204 spin_lock_irqsave(&trace_buf_lock, flags);
1205 len = vbin_printf(trace_buf, TRACE_BUF_SIZE, fmt, args);
1206
1207 if (len > TRACE_BUF_SIZE || len < 0)
1208 goto out_unlock;
1209
1210 size = sizeof(*entry) + sizeof(u32) * len;
1211 event = trace_buffer_lock_reserve(tr, TRACE_PRINT, size, flags, pc);
1212 if (!event)
1213 goto out_unlock;
1214 entry = ring_buffer_event_data(event);
1215 entry->ip = ip;
1216 entry->depth = depth;
1217 entry->fmt = fmt;
1218
1219 memcpy(entry->buf, trace_buf, sizeof(u32) * len);
1220 ring_buffer_unlock_commit(tr->buffer, event);
1221
1222out_unlock:
1223 spin_unlock_irqrestore(&trace_buf_lock, flags);
1224
1225out:
1226 ftrace_preempt_enable(resched);
1227 unpause_graph_tracing();
1228
1229 return len;
1230}
1231EXPORT_SYMBOL_GPL(trace_vprintk);
1232
1172enum trace_file_type { 1233enum trace_file_type {
1173 TRACE_FILE_LAT_FMT = 1, 1234 TRACE_FILE_LAT_FMT = 1,
1174 TRACE_FILE_ANNOTATE = 2, 1235 TRACE_FILE_ANNOTATE = 2,
@@ -1564,7 +1625,7 @@ static enum print_line_t print_printk_msg_only(struct trace_iterator *iter)
1564 1625
1565 trace_assign_type(field, entry); 1626 trace_assign_type(field, entry);
1566 1627
1567 ret = trace_seq_printf(s, "%s", field->buf); 1628 ret = trace_seq_bprintf(s, field->fmt, field->buf);
1568 if (!ret) 1629 if (!ret)
1569 return TRACE_TYPE_PARTIAL_LINE; 1630 return TRACE_TYPE_PARTIAL_LINE;
1570 1631
@@ -1882,14 +1943,14 @@ static int show_traces_open(struct inode *inode, struct file *file)
1882 return ret; 1943 return ret;
1883} 1944}
1884 1945
1885static struct file_operations tracing_fops = { 1946static const struct file_operations tracing_fops = {
1886 .open = tracing_open, 1947 .open = tracing_open,
1887 .read = seq_read, 1948 .read = seq_read,
1888 .llseek = seq_lseek, 1949 .llseek = seq_lseek,
1889 .release = tracing_release, 1950 .release = tracing_release,
1890}; 1951};
1891 1952
1892static struct file_operations show_traces_fops = { 1953static const struct file_operations show_traces_fops = {
1893 .open = show_traces_open, 1954 .open = show_traces_open,
1894 .read = seq_read, 1955 .read = seq_read,
1895 .release = seq_release, 1956 .release = seq_release,
@@ -1982,7 +2043,7 @@ err_unlock:
1982 return err; 2043 return err;
1983} 2044}
1984 2045
1985static struct file_operations tracing_cpumask_fops = { 2046static const struct file_operations tracing_cpumask_fops = {
1986 .open = tracing_open_generic, 2047 .open = tracing_open_generic,
1987 .read = tracing_cpumask_read, 2048 .read = tracing_cpumask_read,
1988 .write = tracing_cpumask_write, 2049 .write = tracing_cpumask_write,
@@ -2134,7 +2195,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2134 return cnt; 2195 return cnt;
2135} 2196}
2136 2197
2137static struct file_operations tracing_iter_fops = { 2198static const struct file_operations tracing_iter_fops = {
2138 .open = tracing_open_generic, 2199 .open = tracing_open_generic,
2139 .read = tracing_trace_options_read, 2200 .read = tracing_trace_options_read,
2140 .write = tracing_trace_options_write, 2201 .write = tracing_trace_options_write,
@@ -2167,7 +2228,7 @@ tracing_readme_read(struct file *filp, char __user *ubuf,
2167 readme_msg, strlen(readme_msg)); 2228 readme_msg, strlen(readme_msg));
2168} 2229}
2169 2230
2170static struct file_operations tracing_readme_fops = { 2231static const struct file_operations tracing_readme_fops = {
2171 .open = tracing_open_generic, 2232 .open = tracing_open_generic,
2172 .read = tracing_readme_read, 2233 .read = tracing_readme_read,
2173}; 2234};
@@ -2927,25 +2988,25 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
2927 return cnt; 2988 return cnt;
2928} 2989}
2929 2990
2930static struct file_operations tracing_max_lat_fops = { 2991static const struct file_operations tracing_max_lat_fops = {
2931 .open = tracing_open_generic, 2992 .open = tracing_open_generic,
2932 .read = tracing_max_lat_read, 2993 .read = tracing_max_lat_read,
2933 .write = tracing_max_lat_write, 2994 .write = tracing_max_lat_write,
2934}; 2995};
2935 2996
2936static struct file_operations tracing_ctrl_fops = { 2997static const struct file_operations tracing_ctrl_fops = {
2937 .open = tracing_open_generic, 2998 .open = tracing_open_generic,
2938 .read = tracing_ctrl_read, 2999 .read = tracing_ctrl_read,
2939 .write = tracing_ctrl_write, 3000 .write = tracing_ctrl_write,
2940}; 3001};
2941 3002
2942static struct file_operations set_tracer_fops = { 3003static const struct file_operations set_tracer_fops = {
2943 .open = tracing_open_generic, 3004 .open = tracing_open_generic,
2944 .read = tracing_set_trace_read, 3005 .read = tracing_set_trace_read,
2945 .write = tracing_set_trace_write, 3006 .write = tracing_set_trace_write,
2946}; 3007};
2947 3008
2948static struct file_operations tracing_pipe_fops = { 3009static const struct file_operations tracing_pipe_fops = {
2949 .open = tracing_open_pipe, 3010 .open = tracing_open_pipe,
2950 .poll = tracing_poll_pipe, 3011 .poll = tracing_poll_pipe,
2951 .read = tracing_read_pipe, 3012 .read = tracing_read_pipe,
@@ -2953,13 +3014,13 @@ static struct file_operations tracing_pipe_fops = {
2953 .release = tracing_release_pipe, 3014 .release = tracing_release_pipe,
2954}; 3015};
2955 3016
2956static struct file_operations tracing_entries_fops = { 3017static const struct file_operations tracing_entries_fops = {
2957 .open = tracing_open_generic, 3018 .open = tracing_open_generic,
2958 .read = tracing_entries_read, 3019 .read = tracing_entries_read,
2959 .write = tracing_entries_write, 3020 .write = tracing_entries_write,
2960}; 3021};
2961 3022
2962static struct file_operations tracing_mark_fops = { 3023static const struct file_operations tracing_mark_fops = {
2963 .open = tracing_open_generic, 3024 .open = tracing_open_generic,
2964 .write = tracing_mark_write, 3025 .write = tracing_mark_write,
2965}; 3026};
@@ -3240,7 +3301,7 @@ tracing_read_dyn_info(struct file *filp, char __user *ubuf,
3240 return r; 3301 return r;
3241} 3302}
3242 3303
3243static struct file_operations tracing_dyn_info_fops = { 3304static const struct file_operations tracing_dyn_info_fops = {
3244 .open = tracing_open_generic, 3305 .open = tracing_open_generic,
3245 .read = tracing_read_dyn_info, 3306 .read = tracing_read_dyn_info,
3246}; 3307};
@@ -3714,84 +3775,6 @@ static __init int tracer_init_debugfs(void)
3714 return 0; 3775 return 0;
3715} 3776}
3716 3777
3717int trace_vprintk(unsigned long ip, int depth, const char *fmt, va_list args)
3718{
3719 static raw_spinlock_t trace_buf_lock = __RAW_SPIN_LOCK_UNLOCKED;
3720 static char trace_buf[TRACE_BUF_SIZE];
3721
3722 struct ring_buffer_event *event;
3723 struct trace_array *tr = &global_trace;
3724 struct trace_array_cpu *data;
3725 int cpu, len = 0, size, pc;
3726 struct print_entry *entry;
3727 unsigned long irq_flags;
3728
3729 if (tracing_disabled || tracing_selftest_running)
3730 return 0;
3731
3732 pc = preempt_count();
3733 preempt_disable_notrace();
3734 cpu = raw_smp_processor_id();
3735 data = tr->data[cpu];
3736
3737 if (unlikely(atomic_read(&data->disabled)))
3738 goto out;
3739
3740 pause_graph_tracing();
3741 raw_local_irq_save(irq_flags);
3742 __raw_spin_lock(&trace_buf_lock);
3743 len = vsnprintf(trace_buf, TRACE_BUF_SIZE, fmt, args);
3744
3745 len = min(len, TRACE_BUF_SIZE-1);
3746 trace_buf[len] = 0;
3747
3748 size = sizeof(*entry) + len + 1;
3749 event = trace_buffer_lock_reserve(tr, TRACE_PRINT, size, irq_flags, pc);
3750 if (!event)
3751 goto out_unlock;
3752 entry = ring_buffer_event_data(event);
3753 entry->ip = ip;
3754 entry->depth = depth;
3755
3756 memcpy(&entry->buf, trace_buf, len);
3757 entry->buf[len] = 0;
3758 ring_buffer_unlock_commit(tr->buffer, event);
3759
3760 out_unlock:
3761 __raw_spin_unlock(&trace_buf_lock);
3762 raw_local_irq_restore(irq_flags);
3763 unpause_graph_tracing();
3764 out:
3765 preempt_enable_notrace();
3766
3767 return len;
3768}
3769EXPORT_SYMBOL_GPL(trace_vprintk);
3770
3771int __trace_printk(unsigned long ip, const char *fmt, ...)
3772{
3773 int ret;
3774 va_list ap;
3775
3776 if (!(trace_flags & TRACE_ITER_PRINTK))
3777 return 0;
3778
3779 va_start(ap, fmt);
3780 ret = trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap);
3781 va_end(ap);
3782 return ret;
3783}
3784EXPORT_SYMBOL_GPL(__trace_printk);
3785
3786int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap)
3787{
3788 if (!(trace_flags & TRACE_ITER_PRINTK))
3789 return 0;
3790
3791 return trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap);
3792}
3793EXPORT_SYMBOL_GPL(__ftrace_vprintk);
3794
3795static int trace_panic_handler(struct notifier_block *this, 3778static int trace_panic_handler(struct notifier_block *this,
3796 unsigned long event, void *unused) 3779 unsigned long event, void *unused)
3797{ 3780{
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 8beff03fda68..2bfb7d11fc17 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -121,7 +121,8 @@ struct print_entry {
121 struct trace_entry ent; 121 struct trace_entry ent;
122 unsigned long ip; 122 unsigned long ip;
123 int depth; 123 int depth;
124 char buf[]; 124 const char *fmt;
125 u32 buf[];
125}; 126};
126 127
127#define TRACE_OLD_SIZE 88 128#define TRACE_OLD_SIZE 88
@@ -195,7 +196,7 @@ struct kmemtrace_free_entry {
195 * trace_flag_type is an enumeration that holds different 196 * trace_flag_type is an enumeration that holds different
196 * states when a trace occurs. These are: 197 * states when a trace occurs. These are:
197 * IRQS_OFF - interrupts were disabled 198 * IRQS_OFF - interrupts were disabled
198 * IRQS_NOSUPPORT - arch does not support irqs_disabled_flags 199 * IRQS_NOSUPPORT - arch does not support irqs_disabled_flags
199 * NEED_RESCED - reschedule is requested 200 * NEED_RESCED - reschedule is requested
200 * HARDIRQ - inside an interrupt handler 201 * HARDIRQ - inside an interrupt handler
201 * SOFTIRQ - inside a softirq handler 202 * SOFTIRQ - inside a softirq handler
@@ -298,7 +299,7 @@ extern void __ftrace_bad_type(void);
298 IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry, \ 299 IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry, \
299 TRACE_GRAPH_RET); \ 300 TRACE_GRAPH_RET); \
300 IF_ASSIGN(var, ent, struct hw_branch_entry, TRACE_HW_BRANCHES);\ 301 IF_ASSIGN(var, ent, struct hw_branch_entry, TRACE_HW_BRANCHES);\
301 IF_ASSIGN(var, ent, struct trace_power, TRACE_POWER); \ 302 IF_ASSIGN(var, ent, struct trace_power, TRACE_POWER); \
302 IF_ASSIGN(var, ent, struct kmemtrace_alloc_entry, \ 303 IF_ASSIGN(var, ent, struct kmemtrace_alloc_entry, \
303 TRACE_KMEM_ALLOC); \ 304 TRACE_KMEM_ALLOC); \
304 IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \ 305 IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \
@@ -321,8 +322,8 @@ enum print_line_t {
321 * flags value in struct tracer_flags. 322 * flags value in struct tracer_flags.
322 */ 323 */
323struct tracer_opt { 324struct tracer_opt {
324 const char *name; /* Will appear on the trace_options file */ 325 const char *name; /* Will appear on the trace_options file */
325 u32 bit; /* Mask assigned in val field in tracer_flags */ 326 u32 bit; /* Mask assigned in val field in tracer_flags */
326}; 327};
327 328
328/* 329/*
@@ -331,7 +332,7 @@ struct tracer_opt {
331 */ 332 */
332struct tracer_flags { 333struct tracer_flags {
333 u32 val; 334 u32 val;
334 struct tracer_opt *opts; 335 struct tracer_opt *opts;
335}; 336};
336 337
337/* Makes more easy to define a tracer opt */ 338/* Makes more easy to define a tracer opt */
@@ -386,7 +387,7 @@ struct tracer {
386 int (*set_flag)(u32 old_flags, u32 bit, int set); 387 int (*set_flag)(u32 old_flags, u32 bit, int set);
387 struct tracer *next; 388 struct tracer *next;
388 int print_max; 389 int print_max;
389 struct tracer_flags *flags; 390 struct tracer_flags *flags;
390 struct tracer_stat *stats; 391 struct tracer_stat *stats;
391}; 392};
392 393
diff --git a/kernel/trace/trace_event_types.h b/kernel/trace/trace_event_types.h
new file mode 100644
index 000000000000..fb4eba166433
--- /dev/null
+++ b/kernel/trace/trace_event_types.h
@@ -0,0 +1,165 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM ftrace
3
4/*
5 * We cheat and use the proto type field as the ID
6 * and args as the entry type (minus 'struct')
7 */
8TRACE_EVENT_FORMAT(function, TRACE_FN, ftrace_entry, ignore,
9 TRACE_STRUCT(
10 TRACE_FIELD(unsigned long, ip, ip)
11 TRACE_FIELD(unsigned long, parent_ip, parent_ip)
12 ),
13 TPRAWFMT(" %lx <-- %lx")
14);
15
16TRACE_EVENT_FORMAT(funcgraph_entry, TRACE_GRAPH_ENT,
17 ftrace_graph_ent_entry, ignore,
18 TRACE_STRUCT(
19 TRACE_FIELD(unsigned long, graph_ent.func, func)
20 TRACE_FIELD(int, graph_ent.depth, depth)
21 ),
22 TPRAWFMT("--> %lx (%d)")
23);
24
25TRACE_EVENT_FORMAT(funcgraph_exit, TRACE_GRAPH_RET,
26 ftrace_graph_ret_entry, ignore,
27 TRACE_STRUCT(
28 TRACE_FIELD(unsigned long, ret.func, func)
29 TRACE_FIELD(int, ret.depth, depth)
30 ),
31 TPRAWFMT("<-- %lx (%d)")
32);
33
34TRACE_EVENT_FORMAT(wakeup, TRACE_WAKE, ctx_switch_entry, ignore,
35 TRACE_STRUCT(
36 TRACE_FIELD(unsigned int, prev_pid, prev_pid)
37 TRACE_FIELD(unsigned char, prev_prio, prev_prio)
38 TRACE_FIELD(unsigned char, prev_state, prev_state)
39 TRACE_FIELD(unsigned int, next_pid, next_pid)
40 TRACE_FIELD(unsigned char, next_prio, next_prio)
41 TRACE_FIELD(unsigned char, next_state, next_state)
42 TRACE_FIELD(unsigned int, next_cpu, next_cpu)
43 ),
44 TPRAWFMT("%u:%u:%u ==+ %u:%u:%u [%03u]")
45);
46
47TRACE_EVENT_FORMAT(context_switch, TRACE_CTX, ctx_switch_entry, ignore,
48 TRACE_STRUCT(
49 TRACE_FIELD(unsigned int, prev_pid, prev_pid)
50 TRACE_FIELD(unsigned char, prev_prio, prev_prio)
51 TRACE_FIELD(unsigned char, prev_state, prev_state)
52 TRACE_FIELD(unsigned int, next_pid, next_pid)
53 TRACE_FIELD(unsigned char, next_prio, next_prio)
54 TRACE_FIELD(unsigned char, next_state, next_state)
55 TRACE_FIELD(unsigned int, next_cpu, next_cpu)
56 ),
57 TPRAWFMT("%u:%u:%u ==+ %u:%u:%u [%03u]")
58);
59
60TRACE_EVENT_FORMAT(special, TRACE_SPECIAL, special_entry, ignore,
61 TRACE_STRUCT(
62 TRACE_FIELD(unsigned long, arg1, arg1)
63 TRACE_FIELD(unsigned long, arg2, arg2)
64 TRACE_FIELD(unsigned long, arg3, arg3)
65 ),
66 TPRAWFMT("(%08lx) (%08lx) (%08lx)")
67);
68
69/*
70 * Stack-trace entry:
71 */
72
73/* #define FTRACE_STACK_ENTRIES 8 */
74
75TRACE_EVENT_FORMAT(kernel_stack, TRACE_STACK, stack_entry, ignore,
76 TRACE_STRUCT(
77 TRACE_FIELD(unsigned long, caller[0], stack0)
78 TRACE_FIELD(unsigned long, caller[1], stack1)
79 TRACE_FIELD(unsigned long, caller[2], stack2)
80 TRACE_FIELD(unsigned long, caller[3], stack3)
81 TRACE_FIELD(unsigned long, caller[4], stack4)
82 TRACE_FIELD(unsigned long, caller[5], stack5)
83 TRACE_FIELD(unsigned long, caller[6], stack6)
84 TRACE_FIELD(unsigned long, caller[7], stack7)
85 ),
86 TPRAWFMT("\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n"
87 "\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n")
88);
89
90TRACE_EVENT_FORMAT(user_stack, TRACE_USER_STACK, userstack_entry, ignore,
91 TRACE_STRUCT(
92 TRACE_FIELD(unsigned long, caller[0], stack0)
93 TRACE_FIELD(unsigned long, caller[1], stack1)
94 TRACE_FIELD(unsigned long, caller[2], stack2)
95 TRACE_FIELD(unsigned long, caller[3], stack3)
96 TRACE_FIELD(unsigned long, caller[4], stack4)
97 TRACE_FIELD(unsigned long, caller[5], stack5)
98 TRACE_FIELD(unsigned long, caller[6], stack6)
99 TRACE_FIELD(unsigned long, caller[7], stack7)
100 ),
101 TPRAWFMT("\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n"
102 "\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n")
103);
104
105TRACE_EVENT_FORMAT(print, TRACE_PRINT, print_entry, ignore,
106 TRACE_STRUCT(
107 TRACE_FIELD(unsigned long, ip, ip)
108 TRACE_FIELD(unsigned int, depth, depth)
109 TRACE_FIELD_ZERO_CHAR(buf)
110 ),
111 TPRAWFMT("%08lx (%d) %s")
112);
113
114TRACE_EVENT_FORMAT(branch, TRACE_BRANCH, trace_branch, ignore,
115 TRACE_STRUCT(
116 TRACE_FIELD(unsigned int, line, line)
117 TRACE_FIELD_SPECIAL(char func[TRACE_FUNC_SIZE+1], func, func)
118 TRACE_FIELD_SPECIAL(char file[TRACE_FUNC_SIZE+1], file, file)
119 TRACE_FIELD(char, correct, correct)
120 ),
121 TPRAWFMT("%u:%s:%s (%u)")
122);
123
124TRACE_EVENT_FORMAT(hw_branch, TRACE_HW_BRANCHES, hw_branch_entry, ignore,
125 TRACE_STRUCT(
126 TRACE_FIELD(u64, from, from)
127 TRACE_FIELD(u64, to, to)
128 ),
129 TPRAWFMT("from: %llx to: %llx")
130);
131
132TRACE_EVENT_FORMAT(power, TRACE_POWER, trace_power, ignore,
133 TRACE_STRUCT(
134 TRACE_FIELD(ktime_t, state_data.stamp, stamp)
135 TRACE_FIELD(ktime_t, state_data.end, end)
136 TRACE_FIELD(int, state_data.type, type)
137 TRACE_FIELD(int, state_data.state, state)
138 ),
139 TPRAWFMT("%llx->%llx type:%u state:%u")
140);
141
142TRACE_EVENT_FORMAT(kmem_alloc, TRACE_KMEM_ALLOC, kmemtrace_alloc_entry, ignore,
143 TRACE_STRUCT(
144 TRACE_FIELD(enum kmemtrace_type_id, type_id, type_id)
145 TRACE_FIELD(unsigned long, call_site, call_site)
146 TRACE_FIELD(const void *, ptr, ptr)
147 TRACE_FIELD(size_t, bytes_req, bytes_req)
148 TRACE_FIELD(size_t, bytes_alloc, bytes_alloc)
149 TRACE_FIELD(gfp_t, gfp_flags, gfp_flags)
150 TRACE_FIELD(int, node, node)
151 ),
152 TPRAWFMT("type:%u call_site:%lx ptr:%p req:%lu alloc:%lu"
153 " flags:%x node:%d")
154);
155
156TRACE_EVENT_FORMAT(kmem_free, TRACE_KMEM_FREE, kmemtrace_free_entry, ignore,
157 TRACE_STRUCT(
158 TRACE_FIELD(enum kmemtrace_type_id, type_id, type_id)
159 TRACE_FIELD(unsigned long, call_site, call_site)
160 TRACE_FIELD(const void *, ptr, ptr)
161 ),
162 TPRAWFMT("type:%u call_site:%lx ptr:%p")
163);
164
165#undef TRACE_SYSTEM
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 210e71ff82db..4488d90e75ef 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -656,11 +656,13 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
656 return -1; 656 return -1;
657 } 657 }
658 658
659 entry = debugfs_create_file("enable", 0644, call->dir, call, 659 if (call->regfunc) {
660 &ftrace_enable_fops); 660 entry = debugfs_create_file("enable", 0644, call->dir, call,
661 if (!entry) 661 &ftrace_enable_fops);
662 pr_warning("Could not create debugfs " 662 if (!entry)
663 "'%s/enable' entry\n", call->name); 663 pr_warning("Could not create debugfs "
664 "'%s/enable' entry\n", call->name);
665 }
664 666
665 /* Only let type be writable, if we can change it */ 667 /* Only let type be writable, if we can change it */
666 entry = debugfs_create_file("type", 668 entry = debugfs_create_file("type",
diff --git a/kernel/trace/trace_events_stage_2.h b/kernel/trace/trace_events_stage_2.h
index b1cebba1d9b4..d24a97e74aea 100644
--- a/kernel/trace/trace_events_stage_2.h
+++ b/kernel/trace/trace_events_stage_2.h
@@ -75,56 +75,5 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
75 75
76#include <trace/trace_event_types.h> 76#include <trace/trace_event_types.h>
77 77
78/* 78#include "trace_format.h"
79 * Setup the showing format of trace point.
80 *
81 * int
82 * ftrace_format_##call(struct trace_seq *s)
83 * {
84 * struct ftrace_raw_##call field;
85 * int ret;
86 *
87 * ret = trace_seq_printf(s, #type " " #item ";"
88 * " size:%d; offset:%d;\n",
89 * sizeof(field.type),
90 * offsetof(struct ftrace_raw_##call,
91 * item));
92 *
93 * }
94 */
95
96#undef TRACE_FIELD
97#define TRACE_FIELD(type, item, assign) \
98 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
99 "offset:%lu;\tsize:%lu;\n", \
100 offsetof(typeof(field), item), \
101 sizeof(field.item)); \
102 if (!ret) \
103 return 0;
104
105
106#undef TRACE_FIELD_SPECIAL
107#define TRACE_FIELD_SPECIAL(type_item, item, cmd) \
108 ret = trace_seq_printf(s, "\tfield special:" #type_item ";\t" \
109 "offset:%lu;\tsize:%lu;\n", \
110 offsetof(typeof(field), item), \
111 sizeof(field.item)); \
112 if (!ret) \
113 return 0;
114
115#undef TRACE_EVENT_FORMAT
116#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
117int \
118ftrace_format_##call(struct trace_seq *s) \
119{ \
120 struct ftrace_raw_##call field; \
121 int ret; \
122 \
123 tstruct; \
124 \
125 trace_seq_printf(s, "\nprint fmt: \"%s\"\n", tpfmt); \
126 \
127 return ret; \
128}
129
130#include <trace/trace_event_types.h> 79#include <trace/trace_event_types.h>
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c
new file mode 100644
index 000000000000..0fb7be73e31c
--- /dev/null
+++ b/kernel/trace/trace_export.c
@@ -0,0 +1,81 @@
1/*
2 * trace_export.c - export basic ftrace utilities to user space
3 *
4 * Copyright (C) 2009 Steven Rostedt <srostedt@redhat.com>
5 */
6#include <linux/stringify.h>
7#include <linux/kallsyms.h>
8#include <linux/seq_file.h>
9#include <linux/debugfs.h>
10#include <linux/uaccess.h>
11#include <linux/ftrace.h>
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/fs.h>
15
16#include "trace_output.h"
17
18#include "trace_format.h"
19
20#undef TRACE_FIELD_ZERO_CHAR
21#define TRACE_FIELD_ZERO_CHAR(item) \
22 ret = trace_seq_printf(s, "\tfield: char " #item ";\t" \
23 "offset:%lu;\tsize:0;\n", \
24 offsetof(typeof(field), item)); \
25 if (!ret) \
26 return 0;
27
28
29#undef TPRAWFMT
30#define TPRAWFMT(args...) args
31
32#undef TRACE_EVENT_FORMAT
33#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
34static int \
35ftrace_format_##call(struct trace_seq *s) \
36{ \
37 struct args field; \
38 int ret; \
39 \
40 tstruct; \
41 \
42 trace_seq_printf(s, "\nprint fmt: \"%s\"\n", tpfmt); \
43 \
44 return ret; \
45}
46
47#include "trace_event_types.h"
48
49#undef TRACE_ZERO_CHAR
50#define TRACE_ZERO_CHAR(arg)
51
52#undef TRACE_FIELD
53#define TRACE_FIELD(type, item, assign)\
54 entry->item = assign;
55
56#undef TRACE_FIELD
57#define TRACE_FIELD(type, item, assign)\
58 entry->item = assign;
59
60#undef TPCMD
61#define TPCMD(cmd...) cmd
62
63#undef TRACE_ENTRY
64#define TRACE_ENTRY entry
65
66#undef TRACE_FIELD_SPECIAL
67#define TRACE_FIELD_SPECIAL(type_item, item, cmd) \
68 cmd;
69
70#undef TRACE_EVENT_FORMAT
71#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
72 \
73static struct ftrace_event_call __used \
74__attribute__((__aligned__(4))) \
75__attribute__((section("_ftrace_events"))) event_##call = { \
76 .name = #call, \
77 .id = proto, \
78 .system = __stringify(TRACE_SYSTEM), \
79 .show_format = ftrace_format_##call, \
80}
81#include "trace_event_types.h"
diff --git a/kernel/trace/trace_format.h b/kernel/trace/trace_format.h
new file mode 100644
index 000000000000..03f9a4c165ca
--- /dev/null
+++ b/kernel/trace/trace_format.h
@@ -0,0 +1,55 @@
1/*
2 * Setup the showing format of trace point.
3 *
4 * int
5 * ftrace_format_##call(struct trace_seq *s)
6 * {
7 * struct ftrace_raw_##call field;
8 * int ret;
9 *
10 * ret = trace_seq_printf(s, #type " " #item ";"
11 * " size:%d; offset:%d;\n",
12 * sizeof(field.type),
13 * offsetof(struct ftrace_raw_##call,
14 * item));
15 *
16 * }
17 */
18
19#undef TRACE_STRUCT
20#define TRACE_STRUCT(args...) args
21
22#undef TRACE_FIELD
23#define TRACE_FIELD(type, item, assign) \
24 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
25 "offset:%lu;\tsize:%lu;\n", \
26 offsetof(typeof(field), item), \
27 sizeof(field.item)); \
28 if (!ret) \
29 return 0;
30
31
32#undef TRACE_FIELD_SPECIAL
33#define TRACE_FIELD_SPECIAL(type_item, item, cmd) \
34 ret = trace_seq_printf(s, "\tfield special:" #type_item ";\t" \
35 "offset:%lu;\tsize:%lu;\n", \
36 offsetof(typeof(field), item), \
37 sizeof(field.item)); \
38 if (!ret) \
39 return 0;
40
41#undef TRACE_EVENT_FORMAT
42#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
43static int \
44ftrace_format_##call(struct trace_seq *s) \
45{ \
46 struct ftrace_raw_##call field; \
47 int ret; \
48 \
49 tstruct; \
50 \
51 trace_seq_printf(s, "\nprint fmt: \"%s\"\n", tpfmt); \
52 \
53 return ret; \
54}
55
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index e527f2f66c73..453ebd3b636e 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -742,7 +742,11 @@ print_graph_comment(struct print_entry *trace, struct trace_seq *s,
742 } 742 }
743 743
744 /* The comment */ 744 /* The comment */
745 ret = trace_seq_printf(s, "/* %s", trace->buf); 745 ret = trace_seq_printf(s, "/* ");
746 if (!ret)
747 return TRACE_TYPE_PARTIAL_LINE;
748
749 ret = trace_seq_bprintf(s, trace->fmt, trace->buf);
746 if (!ret) 750 if (!ret)
747 return TRACE_TYPE_PARTIAL_LINE; 751 return TRACE_TYPE_PARTIAL_LINE;
748 752
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c
index c401b908e805..23e346a734ca 100644
--- a/kernel/trace/trace_mmiotrace.c
+++ b/kernel/trace/trace_mmiotrace.c
@@ -254,15 +254,18 @@ static enum print_line_t mmio_print_mark(struct trace_iterator *iter)
254{ 254{
255 struct trace_entry *entry = iter->ent; 255 struct trace_entry *entry = iter->ent;
256 struct print_entry *print = (struct print_entry *)entry; 256 struct print_entry *print = (struct print_entry *)entry;
257 const char *msg = print->buf;
258 struct trace_seq *s = &iter->seq; 257 struct trace_seq *s = &iter->seq;
259 unsigned long long t = ns2usecs(iter->ts); 258 unsigned long long t = ns2usecs(iter->ts);
260 unsigned long usec_rem = do_div(t, 1000000ULL); 259 unsigned long usec_rem = do_div(t, USEC_PER_SEC);
261 unsigned secs = (unsigned long)t; 260 unsigned secs = (unsigned long)t;
262 int ret; 261 int ret;
263 262
264 /* The trailing newline must be in the message. */ 263 /* The trailing newline must be in the message. */
265 ret = trace_seq_printf(s, "MARK %u.%06lu %s", secs, usec_rem, msg); 264 ret = trace_seq_printf(s, "MARK %u.%06lu ", secs, usec_rem);
265 if (!ret)
266 return TRACE_TYPE_PARTIAL_LINE;
267
268 ret = trace_seq_bprintf(s, print->fmt, print->buf);
266 if (!ret) 269 if (!ret)
267 return TRACE_TYPE_PARTIAL_LINE; 270 return TRACE_TYPE_PARTIAL_LINE;
268 271
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index 306fef84c503..ef8fd661b217 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -53,6 +53,25 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
53 return len; 53 return len;
54} 54}
55 55
56int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
57{
58 int len = (PAGE_SIZE - 1) - s->len;
59 int ret;
60
61 if (!len)
62 return 0;
63
64 ret = bstr_printf(s->buffer + s->len, len, fmt, binary);
65
66 /* If we can't write it all, don't bother writing anything */
67 if (ret >= len)
68 return 0;
69
70 s->len += ret;
71
72 return len;
73}
74
56/** 75/**
57 * trace_seq_puts - trace sequence printing of simple string 76 * trace_seq_puts - trace sequence printing of simple string
58 * @s: trace sequence descriptor 77 * @s: trace sequence descriptor
@@ -814,18 +833,22 @@ static struct trace_event trace_user_stack_event = {
814}; 833};
815 834
816/* TRACE_PRINT */ 835/* TRACE_PRINT */
817static enum print_line_t trace_print_print(struct trace_iterator *iter, 836static enum print_line_t
818 int flags) 837trace_print_print(struct trace_iterator *iter, int flags)
819{ 838{
820 struct print_entry *field; 839 struct trace_entry *entry = iter->ent;
821 struct trace_seq *s = &iter->seq; 840 struct trace_seq *s = &iter->seq;
841 struct print_entry *field;
822 842
823 trace_assign_type(field, iter->ent); 843 trace_assign_type(field, entry);
824 844
825 if (!seq_print_ip_sym(s, field->ip, flags)) 845 if (!seq_print_ip_sym(s, field->ip, flags))
826 goto partial; 846 goto partial;
827 847
828 if (!trace_seq_printf(s, ": %s", field->buf)) 848 if (!trace_seq_puts(s, ": "))
849 goto partial;
850
851 if (!trace_seq_bprintf(s, field->fmt, field->buf))
829 goto partial; 852 goto partial;
830 853
831 return TRACE_TYPE_HANDLED; 854 return TRACE_TYPE_HANDLED;
@@ -834,13 +857,18 @@ static enum print_line_t trace_print_print(struct trace_iterator *iter,
834 return TRACE_TYPE_PARTIAL_LINE; 857 return TRACE_TYPE_PARTIAL_LINE;
835} 858}
836 859
860
837static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags) 861static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags)
838{ 862{
839 struct print_entry *field; 863 struct print_entry *field;
864 struct trace_seq *s = &iter->seq;
840 865
841 trace_assign_type(field, iter->ent); 866 trace_assign_type(field, iter->ent);
842 867
843 if (!trace_seq_printf(&iter->seq, "# %lx %s", field->ip, field->buf)) 868 if (!trace_seq_printf(s, ": %lx : ", field->ip))
869 goto partial;
870
871 if (!trace_seq_bprintf(s, field->fmt, field->buf))
844 goto partial; 872 goto partial;
845 873
846 return TRACE_TYPE_HANDLED; 874 return TRACE_TYPE_HANDLED;
@@ -849,6 +877,7 @@ static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags)
849 return TRACE_TYPE_PARTIAL_LINE; 877 return TRACE_TYPE_PARTIAL_LINE;
850} 878}
851 879
880
852static struct trace_event trace_print_event = { 881static struct trace_event trace_print_event = {
853 .type = TRACE_PRINT, 882 .type = TRACE_PRINT,
854 .trace = trace_print_print, 883 .trace = trace_print_print,
diff --git a/kernel/trace/trace_output.h b/kernel/trace/trace_output.h
index 8a34d688ed63..3b90e6ade1aa 100644
--- a/kernel/trace/trace_output.h
+++ b/kernel/trace/trace_output.h
@@ -18,6 +18,8 @@ struct trace_event {
18extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) 18extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
19 __attribute__ ((format (printf, 2, 3))); 19 __attribute__ ((format (printf, 2, 3)));
20extern int 20extern int
21trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary);
22extern int
21seq_print_ip_sym(struct trace_seq *s, unsigned long ip, 23seq_print_ip_sym(struct trace_seq *s, unsigned long ip,
22 unsigned long sym_flags); 24 unsigned long sym_flags);
23extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, 25extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c
new file mode 100644
index 000000000000..a50aea22e929
--- /dev/null
+++ b/kernel/trace/trace_printk.c
@@ -0,0 +1,138 @@
1/*
2 * trace binary printk
3 *
4 * Copyright (C) 2008 Lai Jiangshan <laijs@cn.fujitsu.com>
5 *
6 */
7#include <linux/kernel.h>
8#include <linux/ftrace.h>
9#include <linux/string.h>
10#include <linux/ctype.h>
11#include <linux/list.h>
12#include <linux/mutex.h>
13#include <linux/slab.h>
14#include <linux/module.h>
15#include <linux/seq_file.h>
16#include <linux/fs.h>
17#include <linux/marker.h>
18#include <linux/uaccess.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 */
28static LIST_HEAD(trace_bprintk_fmt_list);
29
30/* serialize accesses to trace_bprintk_fmt_list */
31static DEFINE_MUTEX(btrace_mutex);
32
33struct trace_bprintk_fmt {
34 struct list_head list;
35 char fmt[0];
36};
37
38static inline struct trace_bprintk_fmt *lookup_format(const char *fmt)
39{
40 struct trace_bprintk_fmt *pos;
41 list_for_each_entry(pos, &trace_bprintk_fmt_list, list) {
42 if (!strcmp(pos->fmt, fmt))
43 return pos;
44 }
45 return NULL;
46}
47
48static
49void hold_module_trace_bprintk_format(const char **start, const char **end)
50{
51 const char **iter;
52
53 mutex_lock(&btrace_mutex);
54 for (iter = start; iter < end; iter++) {
55 struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter);
56 if (tb_fmt) {
57 *iter = tb_fmt->fmt;
58 continue;
59 }
60
61 tb_fmt = kmalloc(offsetof(struct trace_bprintk_fmt, fmt)
62 + strlen(*iter) + 1, GFP_KERNEL);
63 if (tb_fmt) {
64 list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list);
65 strcpy(tb_fmt->fmt, *iter);
66 *iter = tb_fmt->fmt;
67 } else
68 *iter = NULL;
69 }
70 mutex_unlock(&btrace_mutex);
71}
72
73static int module_trace_bprintk_format_notify(struct notifier_block *self,
74 unsigned long val, void *data)
75{
76 struct module *mod = data;
77 if (mod->num_trace_bprintk_fmt) {
78 const char **start = mod->trace_bprintk_fmt_start;
79 const char **end = start + mod->num_trace_bprintk_fmt;
80
81 if (val == MODULE_STATE_COMING)
82 hold_module_trace_bprintk_format(start, end);
83 }
84 return 0;
85}
86
87#else /* !CONFIG_MODULES */
88__init static int
89module_trace_bprintk_format_notify(struct notifier_block *self,
90 unsigned long val, void *data)
91{
92 return 0;
93}
94#endif /* CONFIG_MODULES */
95
96
97__initdata_or_module static
98struct notifier_block module_trace_bprintk_format_nb = {
99 .notifier_call = module_trace_bprintk_format_notify,
100};
101
102int __trace_printk(unsigned long ip, const char *fmt, ...)
103 {
104 int ret;
105 va_list ap;
106
107 if (unlikely(!fmt))
108 return 0;
109
110 if (!(trace_flags & TRACE_ITER_PRINTK))
111 return 0;
112
113 va_start(ap, fmt);
114 ret = trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap);
115 va_end(ap);
116 return ret;
117}
118EXPORT_SYMBOL_GPL(__trace_printk);
119
120int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap)
121 {
122 if (unlikely(!fmt))
123 return 0;
124
125 if (!(trace_flags & TRACE_ITER_PRINTK))
126 return 0;
127
128 return trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap);
129}
130EXPORT_SYMBOL_GPL(__ftrace_vprintk);
131
132
133static __init int init_trace_printk(void)
134{
135 return register_module_notifier(&module_trace_bprintk_format_nb);
136}
137
138early_initcall(init_trace_printk);
diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c
index c771af4e8f1a..91fd19c2149f 100644
--- a/kernel/trace/trace_sysprof.c
+++ b/kernel/trace/trace_sysprof.c
@@ -314,7 +314,7 @@ sysprof_sample_write(struct file *filp, const char __user *ubuf,
314 return cnt; 314 return cnt;
315} 315}
316 316
317static struct file_operations sysprof_sample_fops = { 317static const struct file_operations sysprof_sample_fops = {
318 .read = sysprof_sample_read, 318 .read = sysprof_sample_read,
319 .write = sysprof_sample_write, 319 .write = sysprof_sample_write,
320}; 320};
diff --git a/lib/Kconfig b/lib/Kconfig
index daa481824d9c..206f36a9efb4 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -2,6 +2,9 @@
2# Library configuration 2# Library configuration
3# 3#
4 4
5config BINARY_PRINTF
6 def_bool n
7
5menu "Library routines" 8menu "Library routines"
6 9
7config BITREVERSE 10config BITREVERSE
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 0fbd0121d91d..25f01578c856 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -396,7 +396,38 @@ static noinline char* put_dec(char *buf, unsigned long long num)
396#define SMALL 32 /* Must be 32 == 0x20 */ 396#define SMALL 32 /* Must be 32 == 0x20 */
397#define SPECIAL 64 /* 0x */ 397#define SPECIAL 64 /* 0x */
398 398
399static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type) 399enum format_type {
400 FORMAT_TYPE_NONE, /* Just a string part */
401 FORMAT_TYPE_WITDH,
402 FORMAT_TYPE_PRECISION,
403 FORMAT_TYPE_CHAR,
404 FORMAT_TYPE_STR,
405 FORMAT_TYPE_PTR,
406 FORMAT_TYPE_PERCENT_CHAR,
407 FORMAT_TYPE_INVALID,
408 FORMAT_TYPE_LONG_LONG,
409 FORMAT_TYPE_ULONG,
410 FORMAT_TYPE_LONG,
411 FORMAT_TYPE_USHORT,
412 FORMAT_TYPE_SHORT,
413 FORMAT_TYPE_UINT,
414 FORMAT_TYPE_INT,
415 FORMAT_TYPE_NRCHARS,
416 FORMAT_TYPE_SIZE_T,
417 FORMAT_TYPE_PTRDIFF
418};
419
420struct printf_spec {
421 enum format_type type;
422 int flags; /* flags to number() */
423 int field_width; /* width of output field */
424 int base;
425 int precision; /* # of digits/chars */
426 int qualifier;
427};
428
429static char *number(char *buf, char *end, unsigned long long num,
430 struct printf_spec spec)
400{ 431{
401 /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ 432 /* we are called with base 8, 10 or 16, only, thus don't need "G..." */
402 static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ 433 static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
@@ -404,32 +435,32 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int
404 char tmp[66]; 435 char tmp[66];
405 char sign; 436 char sign;
406 char locase; 437 char locase;
407 int need_pfx = ((type & SPECIAL) && base != 10); 438 int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
408 int i; 439 int i;
409 440
410 /* locase = 0 or 0x20. ORing digits or letters with 'locase' 441 /* locase = 0 or 0x20. ORing digits or letters with 'locase'
411 * produces same digits or (maybe lowercased) letters */ 442 * produces same digits or (maybe lowercased) letters */
412 locase = (type & SMALL); 443 locase = (spec.flags & SMALL);
413 if (type & LEFT) 444 if (spec.flags & LEFT)
414 type &= ~ZEROPAD; 445 spec.flags &= ~ZEROPAD;
415 sign = 0; 446 sign = 0;
416 if (type & SIGN) { 447 if (spec.flags & SIGN) {
417 if ((signed long long) num < 0) { 448 if ((signed long long) num < 0) {
418 sign = '-'; 449 sign = '-';
419 num = - (signed long long) num; 450 num = - (signed long long) num;
420 size--; 451 spec.field_width--;
421 } else if (type & PLUS) { 452 } else if (spec.flags & PLUS) {
422 sign = '+'; 453 sign = '+';
423 size--; 454 spec.field_width--;
424 } else if (type & SPACE) { 455 } else if (spec.flags & SPACE) {
425 sign = ' '; 456 sign = ' ';
426 size--; 457 spec.field_width--;
427 } 458 }
428 } 459 }
429 if (need_pfx) { 460 if (need_pfx) {
430 size--; 461 spec.field_width--;
431 if (base == 16) 462 if (spec.base == 16)
432 size--; 463 spec.field_width--;
433 } 464 }
434 465
435 /* generate full string in tmp[], in reverse order */ 466 /* generate full string in tmp[], in reverse order */
@@ -441,10 +472,10 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int
441 tmp[i++] = (digits[do_div(num,base)] | locase); 472 tmp[i++] = (digits[do_div(num,base)] | locase);
442 } while (num != 0); 473 } while (num != 0);
443 */ 474 */
444 else if (base != 10) { /* 8 or 16 */ 475 else if (spec.base != 10) { /* 8 or 16 */
445 int mask = base - 1; 476 int mask = spec.base - 1;
446 int shift = 3; 477 int shift = 3;
447 if (base == 16) shift = 4; 478 if (spec.base == 16) shift = 4;
448 do { 479 do {
449 tmp[i++] = (digits[((unsigned char)num) & mask] | locase); 480 tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
450 num >>= shift; 481 num >>= shift;
@@ -454,12 +485,12 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int
454 } 485 }
455 486
456 /* printing 100 using %2d gives "100", not "00" */ 487 /* printing 100 using %2d gives "100", not "00" */
457 if (i > precision) 488 if (i > spec.precision)
458 precision = i; 489 spec.precision = i;
459 /* leading space padding */ 490 /* leading space padding */
460 size -= precision; 491 spec.field_width -= spec.precision;
461 if (!(type & (ZEROPAD+LEFT))) { 492 if (!(spec.flags & (ZEROPAD+LEFT))) {
462 while(--size >= 0) { 493 while(--spec.field_width >= 0) {
463 if (buf < end) 494 if (buf < end)
464 *buf = ' '; 495 *buf = ' ';
465 ++buf; 496 ++buf;
@@ -476,23 +507,23 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int
476 if (buf < end) 507 if (buf < end)
477 *buf = '0'; 508 *buf = '0';
478 ++buf; 509 ++buf;
479 if (base == 16) { 510 if (spec.base == 16) {
480 if (buf < end) 511 if (buf < end)
481 *buf = ('X' | locase); 512 *buf = ('X' | locase);
482 ++buf; 513 ++buf;
483 } 514 }
484 } 515 }
485 /* zero or space padding */ 516 /* zero or space padding */
486 if (!(type & LEFT)) { 517 if (!(spec.flags & LEFT)) {
487 char c = (type & ZEROPAD) ? '0' : ' '; 518 char c = (spec.flags & ZEROPAD) ? '0' : ' ';
488 while (--size >= 0) { 519 while (--spec.field_width >= 0) {
489 if (buf < end) 520 if (buf < end)
490 *buf = c; 521 *buf = c;
491 ++buf; 522 ++buf;
492 } 523 }
493 } 524 }
494 /* hmm even more zero padding? */ 525 /* hmm even more zero padding? */
495 while (i <= --precision) { 526 while (i <= --spec.precision) {
496 if (buf < end) 527 if (buf < end)
497 *buf = '0'; 528 *buf = '0';
498 ++buf; 529 ++buf;
@@ -504,7 +535,7 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int
504 ++buf; 535 ++buf;
505 } 536 }
506 /* trailing space padding */ 537 /* trailing space padding */
507 while (--size >= 0) { 538 while (--spec.field_width >= 0) {
508 if (buf < end) 539 if (buf < end)
509 *buf = ' '; 540 *buf = ' ';
510 ++buf; 541 ++buf;
@@ -512,17 +543,17 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int
512 return buf; 543 return buf;
513} 544}
514 545
515static char *string(char *buf, char *end, char *s, int field_width, int precision, int flags) 546static char *string(char *buf, char *end, char *s, struct printf_spec spec)
516{ 547{
517 int len, i; 548 int len, i;
518 549
519 if ((unsigned long)s < PAGE_SIZE) 550 if ((unsigned long)s < PAGE_SIZE)
520 s = "<NULL>"; 551 s = "<NULL>";
521 552
522 len = strnlen(s, precision); 553 len = strnlen(s, spec.precision);
523 554
524 if (!(flags & LEFT)) { 555 if (!(spec.flags & LEFT)) {
525 while (len < field_width--) { 556 while (len < spec.field_width--) {
526 if (buf < end) 557 if (buf < end)
527 *buf = ' '; 558 *buf = ' ';
528 ++buf; 559 ++buf;
@@ -533,7 +564,7 @@ static char *string(char *buf, char *end, char *s, int field_width, int precisio
533 *buf = *s; 564 *buf = *s;
534 ++buf; ++s; 565 ++buf; ++s;
535 } 566 }
536 while (len < field_width--) { 567 while (len < spec.field_width--) {
537 if (buf < end) 568 if (buf < end)
538 *buf = ' '; 569 *buf = ' ';
539 ++buf; 570 ++buf;
@@ -541,21 +572,24 @@ static char *string(char *buf, char *end, char *s, int field_width, int precisio
541 return buf; 572 return buf;
542} 573}
543 574
544static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags) 575static char *symbol_string(char *buf, char *end, void *ptr,
576 struct printf_spec spec)
545{ 577{
546 unsigned long value = (unsigned long) ptr; 578 unsigned long value = (unsigned long) ptr;
547#ifdef CONFIG_KALLSYMS 579#ifdef CONFIG_KALLSYMS
548 char sym[KSYM_SYMBOL_LEN]; 580 char sym[KSYM_SYMBOL_LEN];
549 sprint_symbol(sym, value); 581 sprint_symbol(sym, value);
550 return string(buf, end, sym, field_width, precision, flags); 582 return string(buf, end, sym, spec);
551#else 583#else
552 field_width = 2*sizeof(void *); 584 spec.field_width = 2*sizeof(void *);
553 flags |= SPECIAL | SMALL | ZEROPAD; 585 spec.flags |= SPECIAL | SMALL | ZEROPAD;
554 return number(buf, end, value, 16, field_width, precision, flags); 586 spec.base = 16;
587 return number(buf, end, value, spec);
555#endif 588#endif
556} 589}
557 590
558static char *resource_string(char *buf, char *end, struct resource *res, int field_width, int precision, int flags) 591static char *resource_string(char *buf, char *end, struct resource *res,
592 struct printf_spec spec)
559{ 593{
560#ifndef IO_RSRC_PRINTK_SIZE 594#ifndef IO_RSRC_PRINTK_SIZE
561#define IO_RSRC_PRINTK_SIZE 4 595#define IO_RSRC_PRINTK_SIZE 4
@@ -564,7 +598,11 @@ static char *resource_string(char *buf, char *end, struct resource *res, int fie
564#ifndef MEM_RSRC_PRINTK_SIZE 598#ifndef MEM_RSRC_PRINTK_SIZE
565#define MEM_RSRC_PRINTK_SIZE 8 599#define MEM_RSRC_PRINTK_SIZE 8
566#endif 600#endif
567 601 struct printf_spec num_spec = {
602 .base = 16,
603 .precision = -1,
604 .flags = SPECIAL | SMALL | ZEROPAD,
605 };
568 /* room for the actual numbers, the two "0x", -, [, ] and the final zero */ 606 /* room for the actual numbers, the two "0x", -, [, ] and the final zero */
569 char sym[4*sizeof(resource_size_t) + 8]; 607 char sym[4*sizeof(resource_size_t) + 8];
570 char *p = sym, *pend = sym + sizeof(sym); 608 char *p = sym, *pend = sym + sizeof(sym);
@@ -576,17 +614,18 @@ static char *resource_string(char *buf, char *end, struct resource *res, int fie
576 size = MEM_RSRC_PRINTK_SIZE; 614 size = MEM_RSRC_PRINTK_SIZE;
577 615
578 *p++ = '['; 616 *p++ = '[';
579 p = number(p, pend, res->start, 16, size, -1, SPECIAL | SMALL | ZEROPAD); 617 num_spec.field_width = size;
618 p = number(p, pend, res->start, num_spec);
580 *p++ = '-'; 619 *p++ = '-';
581 p = number(p, pend, res->end, 16, size, -1, SPECIAL | SMALL | ZEROPAD); 620 p = number(p, pend, res->end, num_spec);
582 *p++ = ']'; 621 *p++ = ']';
583 *p = 0; 622 *p = 0;
584 623
585 return string(buf, end, sym, field_width, precision, flags); 624 return string(buf, end, sym, spec);
586} 625}
587 626
588static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width, 627static char *mac_address_string(char *buf, char *end, u8 *addr,
589 int precision, int flags) 628 struct printf_spec spec)
590{ 629{
591 char mac_addr[6 * 3]; /* (6 * 2 hex digits), 5 colons and trailing zero */ 630 char mac_addr[6 * 3]; /* (6 * 2 hex digits), 5 colons and trailing zero */
592 char *p = mac_addr; 631 char *p = mac_addr;
@@ -594,16 +633,17 @@ static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width,
594 633
595 for (i = 0; i < 6; i++) { 634 for (i = 0; i < 6; i++) {
596 p = pack_hex_byte(p, addr[i]); 635 p = pack_hex_byte(p, addr[i]);
597 if (!(flags & SPECIAL) && i != 5) 636 if (!(spec.flags & SPECIAL) && i != 5)
598 *p++ = ':'; 637 *p++ = ':';
599 } 638 }
600 *p = '\0'; 639 *p = '\0';
640 spec.flags &= ~SPECIAL;
601 641
602 return string(buf, end, mac_addr, field_width, precision, flags & ~SPECIAL); 642 return string(buf, end, mac_addr, spec);
603} 643}
604 644
605static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width, 645static char *ip6_addr_string(char *buf, char *end, u8 *addr,
606 int precision, int flags) 646 struct printf_spec spec)
607{ 647{
608 char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */ 648 char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */
609 char *p = ip6_addr; 649 char *p = ip6_addr;
@@ -612,16 +652,17 @@ static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width,
612 for (i = 0; i < 8; i++) { 652 for (i = 0; i < 8; i++) {
613 p = pack_hex_byte(p, addr[2 * i]); 653 p = pack_hex_byte(p, addr[2 * i]);
614 p = pack_hex_byte(p, addr[2 * i + 1]); 654 p = pack_hex_byte(p, addr[2 * i + 1]);
615 if (!(flags & SPECIAL) && i != 7) 655 if (!(spec.flags & SPECIAL) && i != 7)
616 *p++ = ':'; 656 *p++ = ':';
617 } 657 }
618 *p = '\0'; 658 *p = '\0';
659 spec.flags &= ~SPECIAL;
619 660
620 return string(buf, end, ip6_addr, field_width, precision, flags & ~SPECIAL); 661 return string(buf, end, ip6_addr, spec);
621} 662}
622 663
623static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width, 664static char *ip4_addr_string(char *buf, char *end, u8 *addr,
624 int precision, int flags) 665 struct printf_spec spec)
625{ 666{
626 char ip4_addr[4 * 4]; /* (4 * 3 decimal digits), 3 dots and trailing zero */ 667 char ip4_addr[4 * 4]; /* (4 * 3 decimal digits), 3 dots and trailing zero */
627 char temp[3]; /* hold each IP quad in reverse order */ 668 char temp[3]; /* hold each IP quad in reverse order */
@@ -637,8 +678,9 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
637 *p++ = '.'; 678 *p++ = '.';
638 } 679 }
639 *p = '\0'; 680 *p = '\0';
681 spec.flags &= ~SPECIAL;
640 682
641 return string(buf, end, ip4_addr, field_width, precision, flags & ~SPECIAL); 683 return string(buf, end, ip4_addr, spec);
642} 684}
643 685
644/* 686/*
@@ -663,41 +705,234 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
663 * function pointers are really function descriptors, which contain a 705 * function pointers are really function descriptors, which contain a
664 * pointer to the real address. 706 * pointer to the real address.
665 */ 707 */
666static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags) 708static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
709 struct printf_spec spec)
667{ 710{
668 if (!ptr) 711 if (!ptr)
669 return string(buf, end, "(null)", field_width, precision, flags); 712 return string(buf, end, "(null)", spec);
670 713
671 switch (*fmt) { 714 switch (*fmt) {
672 case 'F': 715 case 'F':
673 ptr = dereference_function_descriptor(ptr); 716 ptr = dereference_function_descriptor(ptr);
674 /* Fallthrough */ 717 /* Fallthrough */
675 case 'S': 718 case 'S':
676 return symbol_string(buf, end, ptr, field_width, precision, flags); 719 return symbol_string(buf, end, ptr, spec);
677 case 'R': 720 case 'R':
678 return resource_string(buf, end, ptr, field_width, precision, flags); 721 return resource_string(buf, end, ptr, spec);
679 case 'm': 722 case 'm':
680 flags |= SPECIAL; 723 spec.flags |= SPECIAL;
681 /* Fallthrough */ 724 /* Fallthrough */
682 case 'M': 725 case 'M':
683 return mac_address_string(buf, end, ptr, field_width, precision, flags); 726 return mac_address_string(buf, end, ptr, spec);
684 case 'i': 727 case 'i':
685 flags |= SPECIAL; 728 spec.flags |= SPECIAL;
686 /* Fallthrough */ 729 /* Fallthrough */
687 case 'I': 730 case 'I':
688 if (fmt[1] == '6') 731 if (fmt[1] == '6')
689 return ip6_addr_string(buf, end, ptr, field_width, precision, flags); 732 return ip6_addr_string(buf, end, ptr, spec);
690 if (fmt[1] == '4') 733 if (fmt[1] == '4')
691 return ip4_addr_string(buf, end, ptr, field_width, precision, flags); 734 return ip4_addr_string(buf, end, ptr, spec);
692 flags &= ~SPECIAL; 735 spec.flags &= ~SPECIAL;
736 break;
737 }
738 spec.flags |= SMALL;
739 if (spec.field_width == -1) {
740 spec.field_width = 2*sizeof(void *);
741 spec.flags |= ZEROPAD;
742 }
743 spec.base = 16;
744
745 return number(buf, end, (unsigned long) ptr, spec);
746}
747
748/*
749 * Helper function to decode printf style format.
750 * Each call decode a token from the format and return the
751 * number of characters read (or likely the delta where it wants
752 * to go on the next call).
753 * The decoded token is returned through the parameters
754 *
755 * 'h', 'l', or 'L' for integer fields
756 * 'z' support added 23/7/1999 S.H.
757 * 'z' changed to 'Z' --davidm 1/25/99
758 * 't' added for ptrdiff_t
759 *
760 * @fmt: the format string
761 * @type of the token returned
762 * @flags: various flags such as +, -, # tokens..
763 * @field_width: overwritten width
764 * @base: base of the number (octal, hex, ...)
765 * @precision: precision of a number
766 * @qualifier: qualifier of a number (long, size_t, ...)
767 */
768static int format_decode(const char *fmt, struct printf_spec *spec)
769{
770 const char *start = fmt;
771 bool sign = false;
772
773 /* we finished early by reading the field width */
774 if (spec->type == FORMAT_TYPE_WITDH) {
775 if (spec->field_width < 0) {
776 spec->field_width = -spec->field_width;
777 spec->flags |= LEFT;
778 }
779 spec->type = FORMAT_TYPE_NONE;
780 goto precision;
781 }
782
783 /* we finished early by reading the precision */
784 if (spec->type == FORMAT_TYPE_PRECISION) {
785 if (spec->precision < 0)
786 spec->precision = 0;
787
788 spec->type = FORMAT_TYPE_NONE;
789 goto qualifier;
790 }
791
792 /* By default */
793 spec->type = FORMAT_TYPE_NONE;
794
795 for (; *fmt ; ++fmt) {
796 if (*fmt == '%')
797 break;
798 }
799
800 /* Return the current non-format string */
801 if (fmt != start || !*fmt)
802 return fmt - start;
803
804 /* Process flags */
805 spec->flags = 0;
806
807 while (1) { /* this also skips first '%' */
808 bool found = true;
809
810 ++fmt;
811
812 switch (*fmt) {
813 case '-': spec->flags |= LEFT; break;
814 case '+': spec->flags |= PLUS; break;
815 case ' ': spec->flags |= SPACE; break;
816 case '#': spec->flags |= SPECIAL; break;
817 case '0': spec->flags |= ZEROPAD; break;
818 default: found = false;
819 }
820
821 if (!found)
822 break;
823 }
824
825 /* get field width */
826 spec->field_width = -1;
827
828 if (isdigit(*fmt))
829 spec->field_width = skip_atoi(&fmt);
830 else if (*fmt == '*') {
831 /* it's the next argument */
832 spec->type = FORMAT_TYPE_WITDH;
833 return ++fmt - start;
834 }
835
836precision:
837 /* get the precision */
838 spec->precision = -1;
839 if (*fmt == '.') {
840 ++fmt;
841 if (isdigit(*fmt)) {
842 spec->precision = skip_atoi(&fmt);
843 if (spec->precision < 0)
844 spec->precision = 0;
845 } else if (*fmt == '*') {
846 /* it's the next argument */
847 spec->type = FORMAT_TYPE_WITDH;
848 return ++fmt - start;
849 }
850 }
851
852qualifier:
853 /* get the conversion qualifier */
854 spec->qualifier = -1;
855 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
856 *fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
857 spec->qualifier = *fmt;
858 ++fmt;
859 if (spec->qualifier == 'l' && *fmt == 'l') {
860 spec->qualifier = 'L';
861 ++fmt;
862 }
863 }
864
865 /* default base */
866 spec->base = 10;
867 switch (*fmt) {
868 case 'c':
869 spec->type = FORMAT_TYPE_CHAR;
870 return ++fmt - start;
871
872 case 's':
873 spec->type = FORMAT_TYPE_STR;
874 return ++fmt - start;
875
876 case 'p':
877 spec->type = FORMAT_TYPE_PTR;
878 return fmt - start;
879 /* skip alnum */
880
881 case 'n':
882 spec->type = FORMAT_TYPE_NRCHARS;
883 return ++fmt - start;
884
885 case '%':
886 spec->type = FORMAT_TYPE_PERCENT_CHAR;
887 return ++fmt - start;
888
889 /* integer number formats - set up the flags and "break" */
890 case 'o':
891 spec->base = 8;
892 break;
893
894 case 'x':
895 spec->flags |= SMALL;
896
897 case 'X':
898 spec->base = 16;
899 break;
900
901 case 'd':
902 case 'i':
903 sign = true;
904 case 'u':
693 break; 905 break;
906
907 default:
908 spec->type = FORMAT_TYPE_INVALID;
909 return fmt - start;
694 } 910 }
695 flags |= SMALL; 911
696 if (field_width == -1) { 912 if (spec->qualifier == 'L')
697 field_width = 2*sizeof(void *); 913 spec->type = FORMAT_TYPE_LONG_LONG;
698 flags |= ZEROPAD; 914 else if (spec->qualifier == 'l') {
915 if (sign)
916 spec->type = FORMAT_TYPE_LONG;
917 else
918 spec->type = FORMAT_TYPE_ULONG;
919 } else if (spec->qualifier == 'Z' || spec->qualifier == 'z') {
920 spec->type = FORMAT_TYPE_SIZE_T;
921 } else if (spec->qualifier == 't') {
922 spec->type = FORMAT_TYPE_PTRDIFF;
923 } else if (spec->qualifier == 'h') {
924 if (sign)
925 spec->type = FORMAT_TYPE_SHORT;
926 else
927 spec->type = FORMAT_TYPE_USHORT;
928 } else {
929 if (sign)
930 spec->type = FORMAT_TYPE_INT;
931 else
932 spec->type = FORMAT_TYPE_UINT;
699 } 933 }
700 return number(buf, end, (unsigned long) ptr, 16, field_width, precision, flags); 934
935 return ++fmt - start;
701} 936}
702 937
703/** 938/**
@@ -726,18 +961,9 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field
726int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) 961int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
727{ 962{
728 unsigned long long num; 963 unsigned long long num;
729 int base;
730 char *str, *end, c; 964 char *str, *end, c;
731 965 int read;
732 int flags; /* flags to number() */ 966 struct printf_spec spec = {0};
733
734 int field_width; /* width of output field */
735 int precision; /* min. # of digits for integers; max
736 number of chars for from string */
737 int qualifier; /* 'h', 'l', or 'L' for integer fields */
738 /* 'z' support added 23/7/1999 S.H. */
739 /* 'z' changed to 'Z' --davidm 1/25/99 */
740 /* 't' added for ptrdiff_t */
741 967
742 /* Reject out-of-range values early. Large positive sizes are 968 /* Reject out-of-range values early. Large positive sizes are
743 used for unknown buffer sizes. */ 969 used for unknown buffer sizes. */
@@ -758,184 +984,144 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
758 size = end - buf; 984 size = end - buf;
759 } 985 }
760 986
761 for (; *fmt ; ++fmt) { 987 while (*fmt) {
762 if (*fmt != '%') { 988 const char *old_fmt = fmt;
763 if (str < end)
764 *str = *fmt;
765 ++str;
766 continue;
767 }
768 989
769 /* process flags */ 990 read = format_decode(fmt, &spec);
770 flags = 0;
771 repeat:
772 ++fmt; /* this also skips first '%' */
773 switch (*fmt) {
774 case '-': flags |= LEFT; goto repeat;
775 case '+': flags |= PLUS; goto repeat;
776 case ' ': flags |= SPACE; goto repeat;
777 case '#': flags |= SPECIAL; goto repeat;
778 case '0': flags |= ZEROPAD; goto repeat;
779 }
780 991
781 /* get field width */ 992 fmt += read;
782 field_width = -1;
783 if (isdigit(*fmt))
784 field_width = skip_atoi(&fmt);
785 else if (*fmt == '*') {
786 ++fmt;
787 /* it's the next argument */
788 field_width = va_arg(args, int);
789 if (field_width < 0) {
790 field_width = -field_width;
791 flags |= LEFT;
792 }
793 }
794 993
795 /* get the precision */ 994 switch (spec.type) {
796 precision = -1; 995 case FORMAT_TYPE_NONE: {
797 if (*fmt == '.') { 996 int copy = read;
798 ++fmt; 997 if (str < end) {
799 if (isdigit(*fmt)) 998 if (copy > end - str)
800 precision = skip_atoi(&fmt); 999 copy = end - str;
801 else if (*fmt == '*') { 1000 memcpy(str, old_fmt, copy);
802 ++fmt;
803 /* it's the next argument */
804 precision = va_arg(args, int);
805 } 1001 }
806 if (precision < 0) 1002 str += read;
807 precision = 0; 1003 break;
808 } 1004 }
809 1005
810 /* get the conversion qualifier */ 1006 case FORMAT_TYPE_WITDH:
811 qualifier = -1; 1007 spec.field_width = va_arg(args, int);
812 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || 1008 break;
813 *fmt =='Z' || *fmt == 'z' || *fmt == 't') {
814 qualifier = *fmt;
815 ++fmt;
816 if (qualifier == 'l' && *fmt == 'l') {
817 qualifier = 'L';
818 ++fmt;
819 }
820 }
821 1009
822 /* default base */ 1010 case FORMAT_TYPE_PRECISION:
823 base = 10; 1011 spec.precision = va_arg(args, int);
1012 break;
824 1013
825 switch (*fmt) { 1014 case FORMAT_TYPE_CHAR:
826 case 'c': 1015 if (!(spec.flags & LEFT)) {
827 if (!(flags & LEFT)) { 1016 while (--spec.field_width > 0) {
828 while (--field_width > 0) {
829 if (str < end)
830 *str = ' ';
831 ++str;
832 }
833 }
834 c = (unsigned char) va_arg(args, int);
835 if (str < end)
836 *str = c;
837 ++str;
838 while (--field_width > 0) {
839 if (str < end) 1017 if (str < end)
840 *str = ' '; 1018 *str = ' ';
841 ++str; 1019 ++str;
842 }
843 continue;
844
845 case 's':
846 str = string(str, end, va_arg(args, char *), field_width, precision, flags);
847 continue;
848
849 case 'p':
850 str = pointer(fmt+1, str, end,
851 va_arg(args, void *),
852 field_width, precision, flags);
853 /* Skip all alphanumeric pointer suffixes */
854 while (isalnum(fmt[1]))
855 fmt++;
856 continue;
857
858 case 'n':
859 /* FIXME:
860 * What does C99 say about the overflow case here? */
861 if (qualifier == 'l') {
862 long * ip = va_arg(args, long *);
863 *ip = (str - buf);
864 } else if (qualifier == 'Z' || qualifier == 'z') {
865 size_t * ip = va_arg(args, size_t *);
866 *ip = (str - buf);
867 } else {
868 int * ip = va_arg(args, int *);
869 *ip = (str - buf);
870 }
871 continue;
872 1020
873 case '%': 1021 }
1022 }
1023 c = (unsigned char) va_arg(args, int);
1024 if (str < end)
1025 *str = c;
1026 ++str;
1027 while (--spec.field_width > 0) {
874 if (str < end) 1028 if (str < end)
875 *str = '%'; 1029 *str = ' ';
876 ++str; 1030 ++str;
877 continue; 1031 }
1032 break;
878 1033
879 /* integer number formats - set up the flags and "break" */ 1034 case FORMAT_TYPE_STR:
880 case 'o': 1035 str = string(str, end, va_arg(args, char *), spec);
881 base = 8; 1036 break;
882 break;
883 1037
884 case 'x': 1038 case FORMAT_TYPE_PTR:
885 flags |= SMALL; 1039 str = pointer(fmt+1, str, end, va_arg(args, void *),
886 case 'X': 1040 spec);
887 base = 16; 1041 while (isalnum(*fmt))
888 break; 1042 fmt++;
1043 break;
889 1044
890 case 'd': 1045 case FORMAT_TYPE_PERCENT_CHAR:
891 case 'i': 1046 if (str < end)
892 flags |= SIGN; 1047 *str = '%';
893 case 'u': 1048 ++str;
894 break; 1049 break;
895 1050
896 default: 1051 case FORMAT_TYPE_INVALID:
1052 if (str < end)
1053 *str = '%';
1054 ++str;
1055 if (*fmt) {
897 if (str < end) 1056 if (str < end)
898 *str = '%'; 1057 *str = *fmt;
899 ++str; 1058 ++str;
900 if (*fmt) { 1059 } else {
901 if (str < end) 1060 --fmt;
902 *str = *fmt; 1061 }
903 ++str; 1062 break;
904 } else { 1063
905 --fmt; 1064 case FORMAT_TYPE_NRCHARS: {
906 } 1065 int qualifier = spec.qualifier;
907 continue; 1066
1067 if (qualifier == 'l') {
1068 long *ip = va_arg(args, long *);
1069 *ip = (str - buf);
1070 } else if (qualifier == 'Z' ||
1071 qualifier == 'z') {
1072 size_t *ip = va_arg(args, size_t *);
1073 *ip = (str - buf);
1074 } else {
1075 int *ip = va_arg(args, int *);
1076 *ip = (str - buf);
1077 }
1078 break;
908 } 1079 }
909 if (qualifier == 'L') 1080
910 num = va_arg(args, long long); 1081 default:
911 else if (qualifier == 'l') { 1082 switch (spec.type) {
912 num = va_arg(args, unsigned long); 1083 case FORMAT_TYPE_LONG_LONG:
913 if (flags & SIGN) 1084 num = va_arg(args, long long);
914 num = (signed long) num; 1085 break;
915 } else if (qualifier == 'Z' || qualifier == 'z') { 1086 case FORMAT_TYPE_ULONG:
916 num = va_arg(args, size_t); 1087 num = va_arg(args, unsigned long);
917 } else if (qualifier == 't') { 1088 break;
918 num = va_arg(args, ptrdiff_t); 1089 case FORMAT_TYPE_LONG:
919 } else if (qualifier == 'h') { 1090 num = va_arg(args, long);
920 num = (unsigned short) va_arg(args, int); 1091 break;
921 if (flags & SIGN) 1092 case FORMAT_TYPE_SIZE_T:
922 num = (signed short) num; 1093 num = va_arg(args, size_t);
923 } else { 1094 break;
924 num = va_arg(args, unsigned int); 1095 case FORMAT_TYPE_PTRDIFF:
925 if (flags & SIGN) 1096 num = va_arg(args, ptrdiff_t);
926 num = (signed int) num; 1097 break;
1098 case FORMAT_TYPE_USHORT:
1099 num = (unsigned short) va_arg(args, int);
1100 break;
1101 case FORMAT_TYPE_SHORT:
1102 num = (short) va_arg(args, int);
1103 break;
1104 case FORMAT_TYPE_UINT:
1105 num = va_arg(args, unsigned int);
1106 break;
1107 default:
1108 num = va_arg(args, unsigned int);
1109 }
1110
1111 str = number(str, end, num, spec);
927 } 1112 }
928 str = number(str, end, num, base,
929 field_width, precision, flags);
930 } 1113 }
1114
931 if (size > 0) { 1115 if (size > 0) {
932 if (str < end) 1116 if (str < end)
933 *str = '\0'; 1117 *str = '\0';
934 else 1118 else
935 end[-1] = '\0'; 1119 end[-1] = '\0';
936 } 1120 }
1121
937 /* the trailing null byte doesn't count towards the total */ 1122 /* the trailing null byte doesn't count towards the total */
938 return str-buf; 1123 return str-buf;
1124
939} 1125}
940EXPORT_SYMBOL(vsnprintf); 1126EXPORT_SYMBOL(vsnprintf);
941 1127
@@ -1058,6 +1244,372 @@ int sprintf(char * buf, const char *fmt, ...)
1058} 1244}
1059EXPORT_SYMBOL(sprintf); 1245EXPORT_SYMBOL(sprintf);
1060 1246
1247#ifdef CONFIG_BINARY_PRINTF
1248/*
1249 * bprintf service:
1250 * vbin_printf() - VA arguments to binary data
1251 * bstr_printf() - Binary data to text string
1252 */
1253
1254/**
1255 * vbin_printf - Parse a format string and place args' binary value in a buffer
1256 * @bin_buf: The buffer to place args' binary value
1257 * @size: The size of the buffer(by words(32bits), not characters)
1258 * @fmt: The format string to use
1259 * @args: Arguments for the format string
1260 *
1261 * The format follows C99 vsnprintf, except %n is ignored, and its argument
1262 * is skiped.
1263 *
1264 * The return value is the number of words(32bits) which would be generated for
1265 * the given input.
1266 *
1267 * NOTE:
1268 * If the return value is greater than @size, the resulting bin_buf is NOT
1269 * valid for bstr_printf().
1270 */
1271int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args)
1272{
1273 struct printf_spec spec = {0};
1274 char *str, *end;
1275 int read;
1276
1277 str = (char *)bin_buf;
1278 end = (char *)(bin_buf + size);
1279
1280#define save_arg(type) \
1281do { \
1282 if (sizeof(type) == 8) { \
1283 unsigned long long value; \
1284 str = PTR_ALIGN(str, sizeof(u32)); \
1285 value = va_arg(args, unsigned long long); \
1286 if (str + sizeof(type) <= end) { \
1287 *(u32 *)str = *(u32 *)&value; \
1288 *(u32 *)(str + 4) = *((u32 *)&value + 1); \
1289 } \
1290 } else { \
1291 unsigned long value; \
1292 str = PTR_ALIGN(str, sizeof(type)); \
1293 value = va_arg(args, int); \
1294 if (str + sizeof(type) <= end) \
1295 *(typeof(type) *)str = (type)value; \
1296 } \
1297 str += sizeof(type); \
1298} while (0)
1299
1300
1301 while (*fmt) {
1302 read = format_decode(fmt, &spec);
1303
1304 fmt += read;
1305
1306 switch (spec.type) {
1307 case FORMAT_TYPE_NONE:
1308 break;
1309
1310 case FORMAT_TYPE_WITDH:
1311 case FORMAT_TYPE_PRECISION:
1312 save_arg(int);
1313 break;
1314
1315 case FORMAT_TYPE_CHAR:
1316 save_arg(char);
1317 break;
1318
1319 case FORMAT_TYPE_STR: {
1320 const char *save_str = va_arg(args, char *);
1321 size_t len;
1322 if ((unsigned long)save_str > (unsigned long)-PAGE_SIZE
1323 || (unsigned long)save_str < PAGE_SIZE)
1324 save_str = "<NULL>";
1325 len = strlen(save_str);
1326 if (str + len + 1 < end)
1327 memcpy(str, save_str, len + 1);
1328 str += len + 1;
1329 break;
1330 }
1331
1332 case FORMAT_TYPE_PTR:
1333 save_arg(void *);
1334 /* skip all alphanumeric pointer suffixes */
1335 while (isalnum(*fmt))
1336 fmt++;
1337 break;
1338
1339 case FORMAT_TYPE_PERCENT_CHAR:
1340 break;
1341
1342 case FORMAT_TYPE_INVALID:
1343 if (!*fmt)
1344 --fmt;
1345 break;
1346
1347 case FORMAT_TYPE_NRCHARS: {
1348 /* skip %n 's argument */
1349 int qualifier = spec.qualifier;
1350 void *skip_arg;
1351 if (qualifier == 'l')
1352 skip_arg = va_arg(args, long *);
1353 else if (qualifier == 'Z' || qualifier == 'z')
1354 skip_arg = va_arg(args, size_t *);
1355 else
1356 skip_arg = va_arg(args, int *);
1357 break;
1358 }
1359
1360 default:
1361 switch (spec.type) {
1362
1363 case FORMAT_TYPE_LONG_LONG:
1364 save_arg(long long);
1365 break;
1366 case FORMAT_TYPE_ULONG:
1367 case FORMAT_TYPE_LONG:
1368 save_arg(unsigned long);
1369 break;
1370 case FORMAT_TYPE_SIZE_T:
1371 save_arg(size_t);
1372 break;
1373 case FORMAT_TYPE_PTRDIFF:
1374 save_arg(ptrdiff_t);
1375 break;
1376 case FORMAT_TYPE_USHORT:
1377 case FORMAT_TYPE_SHORT:
1378 save_arg(short);
1379 break;
1380 default:
1381 save_arg(int);
1382 }
1383 }
1384 }
1385 return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf;
1386
1387#undef save_arg
1388}
1389EXPORT_SYMBOL_GPL(vbin_printf);
1390
1391/**
1392 * bstr_printf - Format a string from binary arguments and place it in a buffer
1393 * @buf: The buffer to place the result into
1394 * @size: The size of the buffer, including the trailing null space
1395 * @fmt: The format string to use
1396 * @bin_buf: Binary arguments for the format string
1397 *
1398 * This function like C99 vsnprintf, but the difference is that vsnprintf gets
1399 * arguments from stack, and bstr_printf gets arguments from @bin_buf which is
1400 * a binary buffer that generated by vbin_printf.
1401 *
1402 * The format follows C99 vsnprintf, but has some extensions:
1403 * %pS output the name of a text symbol
1404 * %pF output the name of a function pointer
1405 * %pR output the address range in a struct resource
1406 * %n is ignored
1407 *
1408 * The return value is the number of characters which would
1409 * be generated for the given input, excluding the trailing
1410 * '\0', as per ISO C99. If you want to have the exact
1411 * number of characters written into @buf as return value
1412 * (not including the trailing '\0'), use vscnprintf(). If the
1413 * return is greater than or equal to @size, the resulting
1414 * string is truncated.
1415 */
1416int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
1417{
1418 unsigned long long num;
1419 char *str, *end, c;
1420 const char *args = (const char *)bin_buf;
1421
1422 struct printf_spec spec = {0};
1423
1424 if (unlikely((int) size < 0)) {
1425 /* There can be only one.. */
1426 static char warn = 1;
1427 WARN_ON(warn);
1428 warn = 0;
1429 return 0;
1430 }
1431
1432 str = buf;
1433 end = buf + size;
1434
1435#define get_arg(type) \
1436({ \
1437 typeof(type) value; \
1438 if (sizeof(type) == 8) { \
1439 args = PTR_ALIGN(args, sizeof(u32)); \
1440 *(u32 *)&value = *(u32 *)args; \
1441 *((u32 *)&value + 1) = *(u32 *)(args + 4); \
1442 } else { \
1443 args = PTR_ALIGN(args, sizeof(type)); \
1444 value = *(typeof(type) *)args; \
1445 } \
1446 args += sizeof(type); \
1447 value; \
1448})
1449
1450 /* Make sure end is always >= buf */
1451 if (end < buf) {
1452 end = ((void *)-1);
1453 size = end - buf;
1454 }
1455
1456 while (*fmt) {
1457 int read;
1458 const char *old_fmt = fmt;
1459
1460 read = format_decode(fmt, &spec);
1461
1462 fmt += read;
1463
1464 switch (spec.type) {
1465 case FORMAT_TYPE_NONE: {
1466 int copy = read;
1467 if (str < end) {
1468 if (copy > end - str)
1469 copy = end - str;
1470 memcpy(str, old_fmt, copy);
1471 }
1472 str += read;
1473 break;
1474 }
1475
1476 case FORMAT_TYPE_WITDH:
1477 spec.field_width = get_arg(int);
1478 break;
1479
1480 case FORMAT_TYPE_PRECISION:
1481 spec.precision = get_arg(int);
1482 break;
1483
1484 case FORMAT_TYPE_CHAR:
1485 if (!(spec.flags & LEFT)) {
1486 while (--spec.field_width > 0) {
1487 if (str < end)
1488 *str = ' ';
1489 ++str;
1490 }
1491 }
1492 c = (unsigned char) get_arg(char);
1493 if (str < end)
1494 *str = c;
1495 ++str;
1496 while (--spec.field_width > 0) {
1497 if (str < end)
1498 *str = ' ';
1499 ++str;
1500 }
1501 break;
1502
1503 case FORMAT_TYPE_STR: {
1504 const char *str_arg = args;
1505 size_t len = strlen(str_arg);
1506 args += len + 1;
1507 str = string(str, end, (char *)str_arg, spec);
1508 break;
1509 }
1510
1511 case FORMAT_TYPE_PTR:
1512 str = pointer(fmt+1, str, end, get_arg(void *), spec);
1513 while (isalnum(*fmt))
1514 fmt++;
1515 break;
1516
1517 case FORMAT_TYPE_PERCENT_CHAR:
1518 if (str < end)
1519 *str = '%';
1520 ++str;
1521 break;
1522
1523 case FORMAT_TYPE_INVALID:
1524 if (str < end)
1525 *str = '%';
1526 ++str;
1527 if (*fmt) {
1528 if (str < end)
1529 *str = *fmt;
1530 ++str;
1531 } else {
1532 --fmt;
1533 }
1534 break;
1535
1536 case FORMAT_TYPE_NRCHARS:
1537 /* skip */
1538 break;
1539
1540 default:
1541 switch (spec.type) {
1542
1543 case FORMAT_TYPE_LONG_LONG:
1544 num = get_arg(long long);
1545 break;
1546 case FORMAT_TYPE_ULONG:
1547 num = get_arg(unsigned long);
1548 break;
1549 case FORMAT_TYPE_LONG:
1550 num = get_arg(unsigned long);
1551 break;
1552 case FORMAT_TYPE_SIZE_T:
1553 num = get_arg(size_t);
1554 break;
1555 case FORMAT_TYPE_PTRDIFF:
1556 num = get_arg(ptrdiff_t);
1557 break;
1558 case FORMAT_TYPE_USHORT:
1559 num = get_arg(unsigned short);
1560 break;
1561 case FORMAT_TYPE_SHORT:
1562 num = get_arg(short);
1563 break;
1564 case FORMAT_TYPE_UINT:
1565 num = get_arg(unsigned int);
1566 break;
1567 default:
1568 num = get_arg(int);
1569 }
1570
1571 str = number(str, end, num, spec);
1572 }
1573 }
1574
1575 if (size > 0) {
1576 if (str < end)
1577 *str = '\0';
1578 else
1579 end[-1] = '\0';
1580 }
1581
1582#undef get_arg
1583
1584 /* the trailing null byte doesn't count towards the total */
1585 return str - buf;
1586}
1587EXPORT_SYMBOL_GPL(bstr_printf);
1588
1589/**
1590 * bprintf - Parse a format string and place args' binary value in a buffer
1591 * @bin_buf: The buffer to place args' binary value
1592 * @size: The size of the buffer(by words(32bits), not characters)
1593 * @fmt: The format string to use
1594 * @...: Arguments for the format string
1595 *
1596 * The function returns the number of words(u32) written
1597 * into @bin_buf.
1598 */
1599int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...)
1600{
1601 va_list args;
1602 int ret;
1603
1604 va_start(args, fmt);
1605 ret = vbin_printf(bin_buf, size, fmt, args);
1606 va_end(args);
1607 return ret;
1608}
1609EXPORT_SYMBOL_GPL(bprintf);
1610
1611#endif /* CONFIG_BINARY_PRINTF */
1612
1061/** 1613/**
1062 * vsscanf - Unformat a buffer into a list of arguments 1614 * vsscanf - Unformat a buffer into a list of arguments
1063 * @buf: input buffer 1615 * @buf: input buffer