aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-03-09 17:14:30 -0400
committerSteven Rostedt <srostedt@redhat.com>2009-03-10 00:35:07 -0400
commitda4d03020c2af32f73e8bfbab0a66620d85bb9bb (patch)
tree3ee6d7d69754df7910454315a6011c14d8664d01 /kernel
parent9cc26a261d43e5898287a1f5808132f8f05ceb1c (diff)
tracing: new format for specialized trace points
Impact: clean up and enhancement The TRACE_EVENT_FORMAT macro looks quite ugly and is limited in its ability to save data as well as to print the record out. Working with Ingo Molnar, we came up with a new format that is much more pleasing to the eye of C developers. This new macro is more C style than the old macro, and is more obvious to what it does. Here's the example. The only updated macro in this patch is the sched_switch trace point. The old method looked like this: TRACE_EVENT_FORMAT(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next), TP_ARGS(rq, prev, next), TP_FMT("task %s:%d ==> %s:%d", prev->comm, prev->pid, next->comm, next->pid), TRACE_STRUCT( TRACE_FIELD(pid_t, prev_pid, prev->pid) TRACE_FIELD(int, prev_prio, prev->prio) TRACE_FIELD_SPECIAL(char next_comm[TASK_COMM_LEN], next_comm, TP_CMD(memcpy(TRACE_ENTRY->next_comm, next->comm, TASK_COMM_LEN))) TRACE_FIELD(pid_t, next_pid, next->pid) TRACE_FIELD(int, next_prio, next->prio) ), TP_RAW_FMT("prev %d:%d ==> next %s:%d:%d") ); The above method is hard to read and requires two format fields. The new method: /* * Tracepoint for task switches, performed by the scheduler: * * (NOTE: the 'rq' argument is not used by generic trace events, * but used by the latency tracer plugin. ) */ TRACE_EVENT(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next), TP_ARGS(rq, prev, next), TP_STRUCT__entry( __array( char, prev_comm, TASK_COMM_LEN ) __field( pid_t, prev_pid ) __field( int, prev_prio ) __array( char, next_comm, TASK_COMM_LEN ) __field( pid_t, next_pid ) __field( int, next_prio ) ), TP_printk("task %s:%d [%d] ==> %s:%d [%d]", __entry->prev_comm, __entry->prev_pid, __entry->prev_prio, __entry->next_comm, __entry->next_pid, __entry->next_prio), TP_fast_assign( memcpy(__entry->next_comm, next->comm, TASK_COMM_LEN); __entry->prev_pid = prev->pid; __entry->prev_prio = prev->prio; memcpy(__entry->prev_comm, prev->comm, TASK_COMM_LEN); __entry->next_pid = next->pid; __entry->next_prio = next->prio; ) ); This macro is called TRACE_EVENT, it is broken up into 5 parts: TP_PROTO: the proto type of the trace point TP_ARGS: the arguments of the trace point TP_STRUCT_entry: the structure layout of the entry in the ring buffer TP_printk: the printk format TP_fast_assign: the method used to write the entry into the ring buffer The structure is the definition of how the event will be saved in the ring buffer. The printk is used by the internal tracing in case of an oops, and the kernel needs to print out the format of the record to the console. This the TP_printk gives a means to show the records in a human readable format. It is also used to print out the data from the trace file. The TP_fast_assign is executed directly. It is basically like a C function, where the __entry is the handle to the record. Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace.h5
-rw-r--r--kernel/trace/trace_event_types.h3
-rw-r--r--kernel/trace/trace_events.c159
-rw-r--r--kernel/trace/trace_events_stage_1.h28
-rw-r--r--kernel/trace/trace_events_stage_2.h89
-rw-r--r--kernel/trace/trace_events_stage_3.h34
-rw-r--r--kernel/trace/trace_export.c23
7 files changed, 124 insertions, 217 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 2bfb7d11fc17..c5e1d8865fe4 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -751,12 +751,7 @@ struct ftrace_event_call {
751 int (*regfunc)(void); 751 int (*regfunc)(void);
752 void (*unregfunc)(void); 752 void (*unregfunc)(void);
753 int id; 753 int id;
754 struct dentry *raw_dir;
755 int raw_enabled;
756 int type;
757 int (*raw_init)(void); 754 int (*raw_init)(void);
758 int (*raw_reg)(void);
759 void (*raw_unreg)(void);
760 int (*show_format)(struct trace_seq *s); 755 int (*show_format)(struct trace_seq *s);
761}; 756};
762 757
diff --git a/kernel/trace/trace_event_types.h b/kernel/trace/trace_event_types.h
index d94179aa1fc2..5cca4c978bde 100644
--- a/kernel/trace/trace_event_types.h
+++ b/kernel/trace/trace_event_types.h
@@ -106,9 +106,10 @@ TRACE_EVENT_FORMAT(print, TRACE_PRINT, print_entry, ignore,
106 TRACE_STRUCT( 106 TRACE_STRUCT(
107 TRACE_FIELD(unsigned long, ip, ip) 107 TRACE_FIELD(unsigned long, ip, ip)
108 TRACE_FIELD(unsigned int, depth, depth) 108 TRACE_FIELD(unsigned int, depth, depth)
109 TRACE_FIELD(char *, fmt, fmt)
109 TRACE_FIELD_ZERO_CHAR(buf) 110 TRACE_FIELD_ZERO_CHAR(buf)
110 ), 111 ),
111 TP_RAW_FMT("%08lx (%d) %s") 112 TP_RAW_FMT("%08lx (%d) fmt:%p %s")
112); 113);
113 114
114TRACE_EVENT_FORMAT(branch, TRACE_BRANCH, trace_branch, ignore, 115TRACE_EVENT_FORMAT(branch, TRACE_BRANCH, trace_branch, ignore,
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index fa32ca320767..1880a6438097 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -59,22 +59,12 @@ static void ftrace_event_enable_disable(struct ftrace_event_call *call,
59 call->enabled = 0; 59 call->enabled = 0;
60 call->unregfunc(); 60 call->unregfunc();
61 } 61 }
62 if (call->raw_enabled) {
63 call->raw_enabled = 0;
64 call->raw_unreg();
65 }
66 break; 62 break;
67 case 1: 63 case 1:
68 if (!call->enabled && 64 if (!call->enabled) {
69 (call->type & TRACE_EVENT_TYPE_PRINTF)) {
70 call->enabled = 1; 65 call->enabled = 1;
71 call->regfunc(); 66 call->regfunc();
72 } 67 }
73 if (!call->raw_enabled &&
74 (call->type & TRACE_EVENT_TYPE_RAW)) {
75 call->raw_enabled = 1;
76 call->raw_reg();
77 }
78 break; 68 break;
79 } 69 }
80} 70}
@@ -300,7 +290,7 @@ event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
300 struct ftrace_event_call *call = filp->private_data; 290 struct ftrace_event_call *call = filp->private_data;
301 char *buf; 291 char *buf;
302 292
303 if (call->enabled || call->raw_enabled) 293 if (call->enabled)
304 buf = "1\n"; 294 buf = "1\n";
305 else 295 else
306 buf = "0\n"; 296 buf = "0\n";
@@ -346,107 +336,6 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
346 return cnt; 336 return cnt;
347} 337}
348 338
349static ssize_t
350event_type_read(struct file *filp, char __user *ubuf, size_t cnt,
351 loff_t *ppos)
352{
353 struct ftrace_event_call *call = filp->private_data;
354 char buf[16];
355 int r = 0;
356
357 if (call->type & TRACE_EVENT_TYPE_PRINTF)
358 r += sprintf(buf, "printf\n");
359
360 if (call->type & TRACE_EVENT_TYPE_RAW)
361 r += sprintf(buf+r, "raw\n");
362
363 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
364}
365
366static ssize_t
367event_type_write(struct file *filp, const char __user *ubuf, size_t cnt,
368 loff_t *ppos)
369{
370 struct ftrace_event_call *call = filp->private_data;
371 char buf[64];
372
373 /*
374 * If there's only one type, we can't change it.
375 * And currently we always have printf type, and we
376 * may or may not have raw type.
377 *
378 * This is a redundant check, the file should be read
379 * only if this is the case anyway.
380 */
381
382 if (!call->raw_init)
383 return -EPERM;
384
385 if (cnt >= sizeof(buf))
386 return -EINVAL;
387
388 if (copy_from_user(&buf, ubuf, cnt))
389 return -EFAULT;
390
391 buf[cnt] = 0;
392
393 if (!strncmp(buf, "printf", 6) &&
394 (!buf[6] || isspace(buf[6]))) {
395
396 call->type = TRACE_EVENT_TYPE_PRINTF;
397
398 /*
399 * If raw enabled, the disable it and enable
400 * printf type.
401 */
402 if (call->raw_enabled) {
403 call->raw_enabled = 0;
404 call->raw_unreg();
405
406 call->enabled = 1;
407 call->regfunc();
408 }
409
410 } else if (!strncmp(buf, "raw", 3) &&
411 (!buf[3] || isspace(buf[3]))) {
412
413 call->type = TRACE_EVENT_TYPE_RAW;
414
415 /*
416 * If printf enabled, the disable it and enable
417 * raw type.
418 */
419 if (call->enabled) {
420 call->enabled = 0;
421 call->unregfunc();
422
423 call->raw_enabled = 1;
424 call->raw_reg();
425 }
426 } else
427 return -EINVAL;
428
429 *ppos += cnt;
430
431 return cnt;
432}
433
434static ssize_t
435event_available_types_read(struct file *filp, char __user *ubuf, size_t cnt,
436 loff_t *ppos)
437{
438 struct ftrace_event_call *call = filp->private_data;
439 char buf[16];
440 int r = 0;
441
442 r += sprintf(buf, "printf\n");
443
444 if (call->raw_init)
445 r += sprintf(buf+r, "raw\n");
446
447 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
448}
449
450#undef FIELD 339#undef FIELD
451#define FIELD(type, name) \ 340#define FIELD(type, name) \
452 #type, #name, (unsigned int)offsetof(typeof(field), name), \ 341 #type, #name, (unsigned int)offsetof(typeof(field), name), \
@@ -470,6 +359,7 @@ static int trace_write_header(struct trace_seq *s)
470 FIELD(int, pid), 359 FIELD(int, pid),
471 FIELD(int, tgid)); 360 FIELD(int, tgid));
472} 361}
362
473static ssize_t 363static ssize_t
474event_format_read(struct file *filp, char __user *ubuf, size_t cnt, 364event_format_read(struct file *filp, char __user *ubuf, size_t cnt,
475 loff_t *ppos) 365 loff_t *ppos)
@@ -527,13 +417,6 @@ static const struct seq_operations show_set_event_seq_ops = {
527 .stop = t_stop, 417 .stop = t_stop,
528}; 418};
529 419
530static const struct file_operations ftrace_avail_fops = {
531 .open = ftrace_event_seq_open,
532 .read = seq_read,
533 .llseek = seq_lseek,
534 .release = seq_release,
535};
536
537static const struct file_operations ftrace_set_event_fops = { 420static const struct file_operations ftrace_set_event_fops = {
538 .open = ftrace_event_seq_open, 421 .open = ftrace_event_seq_open,
539 .read = seq_read, 422 .read = seq_read,
@@ -548,17 +431,6 @@ static const struct file_operations ftrace_enable_fops = {
548 .write = event_enable_write, 431 .write = event_enable_write,
549}; 432};
550 433
551static const struct file_operations ftrace_type_fops = {
552 .open = tracing_open_generic,
553 .read = event_type_read,
554 .write = event_type_write,
555};
556
557static const struct file_operations ftrace_available_types_fops = {
558 .open = tracing_open_generic,
559 .read = event_available_types_read,
560};
561
562static const struct file_operations ftrace_event_format_fops = { 434static const struct file_operations ftrace_event_format_fops = {
563 .open = tracing_open_generic, 435 .open = tracing_open_generic,
564 .read = event_format_read, 436 .read = event_format_read,
@@ -647,9 +519,6 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
647 } 519 }
648 } 520 }
649 521
650 /* default the output to printf */
651 call->type = TRACE_EVENT_TYPE_PRINTF;
652
653 call->dir = debugfs_create_dir(call->name, d_events); 522 call->dir = debugfs_create_dir(call->name, d_events);
654 if (!call->dir) { 523 if (!call->dir) {
655 pr_warning("Could not create debugfs " 524 pr_warning("Could not create debugfs "
@@ -665,21 +534,6 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
665 "'%s/enable' entry\n", call->name); 534 "'%s/enable' entry\n", call->name);
666 } 535 }
667 536
668 /* Only let type be writable, if we can change it */
669 entry = debugfs_create_file("type",
670 call->raw_init ? 0644 : 0444,
671 call->dir, call,
672 &ftrace_type_fops);
673 if (!entry)
674 pr_warning("Could not create debugfs "
675 "'%s/type' entry\n", call->name);
676
677 entry = debugfs_create_file("available_types", 0444, call->dir, call,
678 &ftrace_available_types_fops);
679 if (!entry)
680 pr_warning("Could not create debugfs "
681 "'%s/available_types' entry\n", call->name);
682
683 /* A trace may not want to export its format */ 537 /* A trace may not want to export its format */
684 if (!call->show_format) 538 if (!call->show_format)
685 return 0; 539 return 0;
@@ -704,13 +558,6 @@ static __init int event_trace_init(void)
704 if (!d_tracer) 558 if (!d_tracer)
705 return 0; 559 return 0;
706 560
707 entry = debugfs_create_file("available_events", 0444, d_tracer,
708 (void *)&show_event_seq_ops,
709 &ftrace_avail_fops);
710 if (!entry)
711 pr_warning("Could not create debugfs "
712 "'available_events' entry\n");
713
714 entry = debugfs_create_file("set_event", 0644, d_tracer, 561 entry = debugfs_create_file("set_event", 0644, d_tracer,
715 (void *)&show_set_event_seq_ops, 562 (void *)&show_set_event_seq_ops,
716 &ftrace_set_event_fops); 563 &ftrace_set_event_fops);
diff --git a/kernel/trace/trace_events_stage_1.h b/kernel/trace/trace_events_stage_1.h
index 3830a731424c..edfcbd3a0d1b 100644
--- a/kernel/trace/trace_events_stage_1.h
+++ b/kernel/trace/trace_events_stage_1.h
@@ -18,19 +18,23 @@
18#define TRACE_FORMAT(call, proto, args, fmt) 18#define TRACE_FORMAT(call, proto, args, fmt)
19 19
20#undef TRACE_EVENT_FORMAT 20#undef TRACE_EVENT_FORMAT
21#define TRACE_EVENT_FORMAT(name, proto, args, fmt, tstruct, tpfmt) \ 21#define TRACE_EVENT_FORMAT(name, proto, args, fmt, tstruct, tpfmt)
22 struct ftrace_raw_##name { \ 22
23 struct trace_entry ent; \ 23#undef __array
24 tstruct \ 24#define __array(type, item, len) type item[len];
25 }; \
26 static struct ftrace_event_call event_##name
27 25
28#undef TRACE_STRUCT 26#undef __field
29#define TRACE_STRUCT(args...) args 27#define __field(type, item) type item;
30 28
31#define TRACE_FIELD(type, item, assign) \ 29#undef TP_STRUCT__entry
32 type item; 30#define TP_STRUCT__entry(args...) args
33#define TRACE_FIELD_SPECIAL(type_item, item, cmd) \ 31
34 type_item; 32#undef TRACE_EVENT
33#define TRACE_EVENT(name, proto, args, tstruct, print, assign) \
34 struct ftrace_raw_##name { \
35 struct trace_entry ent; \
36 tstruct \
37 }; \
38 static struct ftrace_event_call event_##name
35 39
36#include <trace/trace_event_types.h> 40#include <trace/trace_event_types.h>
diff --git a/kernel/trace/trace_events_stage_2.h b/kernel/trace/trace_events_stage_2.h
index 8e2e0f56c2a8..d91bf4c56661 100644
--- a/kernel/trace/trace_events_stage_2.h
+++ b/kernel/trace/trace_events_stage_2.h
@@ -32,23 +32,14 @@
32 * in binary. 32 * in binary.
33 */ 33 */
34 34
35#undef TRACE_STRUCT 35#undef __entry
36#define TRACE_STRUCT(args...) args 36#define __entry field
37 37
38#undef TRACE_FIELD 38#undef TP_printk
39#define TRACE_FIELD(type, item, assign) \ 39#define TP_printk(fmt, args...) fmt "\n", args
40 field->item,
41 40
42#undef TRACE_FIELD_SPECIAL 41#undef TRACE_EVENT
43#define TRACE_FIELD_SPECIAL(type_item, item, cmd) \ 42#define TRACE_EVENT(call, proto, args, tstruct, print, assign) \
44 field->item,
45
46
47#undef TP_RAW_FMT
48#define TP_RAW_FMT(args...) args
49
50#undef TRACE_EVENT_FORMAT
51#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
52enum print_line_t \ 43enum print_line_t \
53ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \ 44ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
54{ \ 45{ \
@@ -66,14 +57,76 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
66 \ 57 \
67 field = (typeof(field))entry; \ 58 field = (typeof(field))entry; \
68 \ 59 \
69 ret = trace_seq_printf(s, tpfmt "%s", tstruct "\n"); \ 60 ret = trace_seq_printf(s, print); \
70 if (!ret) \ 61 if (!ret) \
71 return TRACE_TYPE_PARTIAL_LINE; \ 62 return TRACE_TYPE_PARTIAL_LINE; \
72 \ 63 \
73 return TRACE_TYPE_HANDLED; \ 64 return TRACE_TYPE_HANDLED; \
74} 65}
75 66
76#include <trace/trace_event_types.h> 67#include <trace/trace_event_types.h>
77 68
78#include "trace_format.h" 69/*
70 * Setup the showing format of trace point.
71 *
72 * int
73 * ftrace_format_##call(struct trace_seq *s)
74 * {
75 * struct ftrace_raw_##call field;
76 * int ret;
77 *
78 * ret = trace_seq_printf(s, #type " " #item ";"
79 * " size:%d; offset:%d;\n",
80 * sizeof(field.type),
81 * offsetof(struct ftrace_raw_##call,
82 * item));
83 *
84 * }
85 */
86
87#undef TP_STRUCT__entry
88#define TP_STRUCT__entry(args...) args
89
90#undef __field
91#define __field(type, item) \
92 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
93 "offset:%u;\tsize:%u;\n", \
94 (unsigned int)offsetof(typeof(field), item), \
95 (unsigned int)sizeof(field.item)); \
96 if (!ret) \
97 return 0;
98
99#undef __array
100#define __array(type, item, len) \
101 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \
102 "offset:%u;\tsize:%u;\n", \
103 (unsigned int)offsetof(typeof(field), item), \
104 (unsigned int)sizeof(field.item)); \
105 if (!ret) \
106 return 0;
107
108#undef __entry
109#define __entry "REC"
110
111#undef TP_printk
112#define TP_printk(fmt, args...) "%s, %s\n", #fmt, #args
113
114#undef TP_fast_assign
115#define TP_fast_assign(args...) args
116
117#undef TRACE_EVENT
118#define TRACE_EVENT(call, proto, args, tstruct, print, func) \
119static int \
120ftrace_format_##call(struct trace_seq *s) \
121{ \
122 struct ftrace_raw_##call field; \
123 int ret; \
124 \
125 tstruct; \
126 \
127 trace_seq_printf(s, "\nprint fmt: " print); \
128 \
129 return ret; \
130}
131
79#include <trace/trace_event_types.h> 132#include <trace/trace_event_types.h>
diff --git a/kernel/trace/trace_events_stage_3.h b/kernel/trace/trace_events_stage_3.h
index 41b82b93c9c7..8e398d864096 100644
--- a/kernel/trace/trace_events_stage_3.h
+++ b/kernel/trace/trace_events_stage_3.h
@@ -144,27 +144,15 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
144 .unregfunc = ftrace_unreg_event_##call, \ 144 .unregfunc = ftrace_unreg_event_##call, \
145} 145}
146 146
147#undef TRACE_FIELD 147#undef TRACE_EVENT_FORMAT
148#define TRACE_FIELD(type, item, assign)\ 148#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, raw) \
149 entry->item = assign; 149 TRACE_FORMAT(call, PARAMS(proto), PARAMS(args), PARAMS(fmt))
150
151#undef TRACE_FIELD
152#define TRACE_FIELD(type, item, assign)\
153 entry->item = assign;
154
155#undef TP_CMD
156#define TP_CMD(cmd...) cmd
157
158#undef TRACE_ENTRY
159#define TRACE_ENTRY entry
160 150
161#undef TRACE_FIELD_SPECIAL 151#undef __entry
162#define TRACE_FIELD_SPECIAL(type_item, item, cmd) \ 152#define __entry entry
163 cmd;
164 153
165#undef TRACE_EVENT_FORMAT 154#undef TRACE_EVENT
166#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \ 155#define TRACE_EVENT(call, proto, args, tstruct, print, assign) \
167_TRACE_FORMAT(call, PARAMS(proto), PARAMS(args), PARAMS(fmt)) \
168 \ 156 \
169static struct ftrace_event_call event_##call; \ 157static struct ftrace_event_call event_##call; \
170 \ 158 \
@@ -185,7 +173,7 @@ static void ftrace_raw_event_##call(proto) \
185 return; \ 173 return; \
186 entry = ring_buffer_event_data(event); \ 174 entry = ring_buffer_event_data(event); \
187 \ 175 \
188 tstruct; \ 176 assign; \
189 \ 177 \
190 trace_current_buffer_unlock_commit(event, irq_flags, pc); \ 178 trace_current_buffer_unlock_commit(event, irq_flags, pc); \
191} \ 179} \
@@ -226,10 +214,8 @@ __attribute__((__aligned__(4))) \
226__attribute__((section("_ftrace_events"))) event_##call = { \ 214__attribute__((section("_ftrace_events"))) event_##call = { \
227 .name = #call, \ 215 .name = #call, \
228 .system = __stringify(TRACE_SYSTEM), \ 216 .system = __stringify(TRACE_SYSTEM), \
229 .regfunc = ftrace_reg_event_##call, \
230 .unregfunc = ftrace_unreg_event_##call, \
231 .raw_init = ftrace_raw_init_event_##call, \ 217 .raw_init = ftrace_raw_init_event_##call, \
232 .raw_reg = ftrace_raw_reg_event_##call, \ 218 .regfunc = ftrace_raw_reg_event_##call, \
233 .raw_unreg = ftrace_raw_unreg_event_##call, \ 219 .unregfunc = ftrace_raw_unreg_event_##call, \
234 .show_format = ftrace_format_##call, \ 220 .show_format = ftrace_format_##call, \
235} 221}
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c
index e62bc10f8103..23ae78430d58 100644
--- a/kernel/trace/trace_export.c
+++ b/kernel/trace/trace_export.c
@@ -15,7 +15,28 @@
15 15
16#include "trace_output.h" 16#include "trace_output.h"
17 17
18#include "trace_format.h" 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:%u;\tsize:%u;\n", \
26 (unsigned int)offsetof(typeof(field), item), \
27 (unsigned int)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:%u;\tsize:%u;\n", \
36 (unsigned int)offsetof(typeof(field), item), \
37 (unsigned int)sizeof(field.item)); \
38 if (!ret) \
39 return 0;
19 40
20#undef TRACE_FIELD_ZERO_CHAR 41#undef TRACE_FIELD_ZERO_CHAR
21#define TRACE_FIELD_ZERO_CHAR(item) \ 42#define TRACE_FIELD_ZERO_CHAR(item) \