aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Martin <Dave.Martin@arm.com>2015-01-28 07:48:53 -0500
committerSteven Rostedt <rostedt@goodmis.org>2015-01-28 10:34:47 -0500
commit6ea22486ba46bcb665de36514094d74575cd1330 (patch)
treeb0db72c5d2b7dc79a7937f05443a05f1ac5a64c4
parent69a1c994cc540cc84469acf9952f72b899b38e8b (diff)
tracing: Add array printing helper
If a trace event contains an array, there is currently no standard way to format this for text output. Drivers are currently hacking around this by a) local hacks that use the trace_seq functionailty directly, or b) just not printing that information. For fixed size arrays, formatting of the elements can be open-coded, but this gets cumbersome for arrays of non-trivial size. These approaches result in non-standard content of the event format description delivered to userspace, so userland tools needs to be taught to understand and parse each array printing method individually. This patch implements a __print_array() helper that tracepoint implementations can use instead of reinventing it. A simple C-style syntax is used to delimit the array and its elements {like,this}. So that the helpers can be used with large static arrays as well as dynamic arrays, they take a pointer and element count: they can be used with __get_dynamic_array() for use with dynamic arrays. Link: http://lkml.kernel.org/r/1422449335-8289-2-git-send-email-javi.merino@arm.com Cc: Ingo Molnar <mingo@redhat.com> Signed-off-by: Dave Martin <Dave.Martin@arm.com> Signed-off-by: Javi Merino <javi.merino@arm.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--include/linux/ftrace_event.h4
-rw-r--r--include/trace/ftrace.h9
-rw-r--r--kernel/trace/trace_output.c44
3 files changed, 57 insertions, 0 deletions
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 0bebb5c348b8..5aa4a9269547 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -44,6 +44,10 @@ const char *ftrace_print_bitmask_seq(struct trace_seq *p, void *bitmask_ptr,
44const char *ftrace_print_hex_seq(struct trace_seq *p, 44const char *ftrace_print_hex_seq(struct trace_seq *p,
45 const unsigned char *buf, int len); 45 const unsigned char *buf, int len);
46 46
47const char *ftrace_print_array_seq(struct trace_seq *p,
48 const void *buf, int buf_len,
49 size_t el_size);
50
47struct trace_iterator; 51struct trace_iterator;
48struct trace_event; 52struct trace_event;
49 53
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 139b5067345b..304901fc5f34 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -263,6 +263,14 @@
263#undef __print_hex 263#undef __print_hex
264#define __print_hex(buf, buf_len) ftrace_print_hex_seq(p, buf, buf_len) 264#define __print_hex(buf, buf_len) ftrace_print_hex_seq(p, buf, buf_len)
265 265
266#undef __print_array
267#define __print_array(array, count, el_size) \
268 ({ \
269 BUILD_BUG_ON(el_size != 1 && el_size != 2 && \
270 el_size != 4 && el_size != 8); \
271 ftrace_print_array_seq(p, array, count, el_size); \
272 })
273
266#undef DECLARE_EVENT_CLASS 274#undef DECLARE_EVENT_CLASS
267#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 275#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
268static notrace enum print_line_t \ 276static notrace enum print_line_t \
@@ -674,6 +682,7 @@ static inline void ftrace_test_probe_##call(void) \
674#undef __get_dynamic_array_len 682#undef __get_dynamic_array_len
675#undef __get_str 683#undef __get_str
676#undef __get_bitmask 684#undef __get_bitmask
685#undef __print_array
677 686
678#undef TP_printk 687#undef TP_printk
679#define TP_printk(fmt, args...) "\"" fmt "\", " __stringify(args) 688#define TP_printk(fmt, args...) "\"" fmt "\", " __stringify(args)
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index b77b9a697619..692bf7184c8c 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -177,6 +177,50 @@ ftrace_print_hex_seq(struct trace_seq *p, const unsigned char *buf, int buf_len)
177} 177}
178EXPORT_SYMBOL(ftrace_print_hex_seq); 178EXPORT_SYMBOL(ftrace_print_hex_seq);
179 179
180const char *
181ftrace_print_array_seq(struct trace_seq *p, const void *buf, int buf_len,
182 size_t el_size)
183{
184 const char *ret = trace_seq_buffer_ptr(p);
185 const char *prefix = "";
186 void *ptr = (void *)buf;
187
188 trace_seq_putc(p, '{');
189
190 while (ptr < buf + buf_len) {
191 switch (el_size) {
192 case 1:
193 trace_seq_printf(p, "%s0x%x", prefix,
194 *(u8 *)ptr);
195 break;
196 case 2:
197 trace_seq_printf(p, "%s0x%x", prefix,
198 *(u16 *)ptr);
199 break;
200 case 4:
201 trace_seq_printf(p, "%s0x%x", prefix,
202 *(u32 *)ptr);
203 break;
204 case 8:
205 trace_seq_printf(p, "%s0x%llx", prefix,
206 *(u64 *)ptr);
207 break;
208 default:
209 trace_seq_printf(p, "BAD SIZE:%zu 0x%x", el_size,
210 *(u8 *)ptr);
211 el_size = 1;
212 }
213 prefix = ",";
214 ptr += el_size;
215 }
216
217 trace_seq_putc(p, '}');
218 trace_seq_putc(p, 0);
219
220 return ret;
221}
222EXPORT_SYMBOL(ftrace_print_array_seq);
223
180int ftrace_raw_output_prep(struct trace_iterator *iter, 224int ftrace_raw_output_prep(struct trace_iterator *iter,
181 struct trace_event *trace_event) 225 struct trace_event *trace_event)
182{ 226{