大型C项目可能有包含佶屈聱牙的宏,令人大为头痛,如何看到宏替换后的结果,自然会极大地帮助理解。而这本来就是预处理程序cpp的工作,只
是我们习惯了gcc一杆到底,反而忘了cpp的好处,即只是替换,没有编译链接,只需要把所有相关宏聚到一起就可以看到结果。
下
面的示例文件macro.c
前面部分来自linux-2.6.38-rc6/include/trace/ftrace.h 的stage 4部分(以及该部分要用到的来自其他文件
宏,注意不能用错,因为里面包含大量的重名宏),ftrace.h是一个非常复杂的文件。为了展开,我们在macro.c尾部添加一个宏的引用,来自
include/trace/events/syscalls.h。
#define PARAMS(args...) args
#define TP_PROTO(args...) args
#define TP_ARGS(args...) args
#define TP_STRUCT__entry(args...) args
#define TRACE_EVENT_FN(name, proto, args, tstruct, \
assign, print, reg, unreg) \
TRACE_EVENT(name, PARAMS(proto), PARAMS(args), \
PARAMS(tstruct), PARAMS(assign), PARAMS(print)) \
#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \
DECLARE_EVENT_CLASS(name, \
PARAMS(proto), \
PARAMS(args), \
PARAMS(tstruct), \
PARAMS(assign), \
PARAMS(print));
#undef __entry
#define __entry entry
#undef __field
#define __field(type, item)
#undef __array
#define __array(type, item, len)
#undef __dynamic_array
#define __dynamic_array(type, item, len) \
TRUCT__entry(args...) args
#undef __string
#define __string(item, src) __dynamic_array(char, item, -1) \
#undef __assign_str
#define __assign_str(dst, src) \
strcpy(__get_str(dst), src);
#undef TP_fast_assign
#define TP_fast_assign(args...) args
#undef TP_perf_assign
#define TP_perf_assign(args...)
#undef DECLARE_EVENT_CLASS
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
\
static notrace void \
ftrace_raw_event_##call(void *__data, proto) \
{ \
struct ftrace_event_call *event_call = __data; \
struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
struct ring_buffer_event *event; \
struct ftrace_raw_##call *entry; \
struct ring_buffer *buffer; \
unsigned long irq_flags; \
int __data_size; \
int pc; \
\
local_save_flags(irq_flags); \
pc = preempt_count(); \
\
__data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
\
event = trace_current_buffer_lock_reserve(&buffer, \
event_call->event.type, \
sizeof(*entry) + __data_size, \
irq_flags, pc); \
if (!event) \
return; \
entry = ring_buffer_event_data(event); \
\
tstruct \
\
{ assign; } \
\
if (!filter_current_check_discard(buffer, event_call, entry, event)) \
trace_nowake_buffer_unlock_commit(buffer, \
event, irq_flags, pc); \
}
TRACE_EVENT_FN(sys_enter,
TP_PROTO(struct pt_regs *regs, long id),
TP_ARGS(regs, id),
TP_STRUCT__entry(
__field( long, id )
__array( unsigned long, args, 6 )
),
TP_fast_assign(
__entry->id = id;
syscall_get_arguments(current, regs, 0, 6, __entry->args);
),
TP_printk("NR %ld (%lx, %lx, %lx, %lx, %lx, %lx)",
__entry->id,
__entry->args[0], __entry->args[1], __entry->args[2],
__entry->args[3], __entry->args[4], __entry->args[5]),
syscall_regfunc, syscall_unregfunc
);
下面利用cpp来展开,用indent修整输出文件后,赏心悦目的C代码出现了。
[user@localhost ~]$ cpp -P macro.c out.c
[user@localhost ~]$ indent out.c
[user@localhost ~]$ cat out.c
static notrace void
ftrace_raw_event_sys_enter (void *__data, struct pt_regs *regs, long id)
{
struct ftrace_event_call *event_call = __data;
struct ftrace_data_offsets_sys_enter __maybe_unused __data_offsets;
struct ring_buffer_event *event;
struct ftrace_raw_sys_enter *entry;
struct ring_buffer *buffer;
unsigned long irq_flags;
int __data_size;
int pc;
local_save_flags (irq_flags);
pc = preempt_count ();
__data_size = ftrace_get_offsets_sys_enter (&__data_offsets, regs, id);
event =
trace_current_buffer_lock_reserve (&buffer, event_call->event.type,
sizeof (*entry) + __data_size,
irq_flags, pc);
if (!event)
return;
entry = ring_buffer_event_data (event);
{
entry->id = id;
syscall_get_arguments (current, regs, 0, 6, entry->args);;
}
if (!filter_current_check_discard (buffer, event_call, entry, event))
trace_nowake_buffer_unlock_commit (buffer, event, irq_flags, pc);
};;
阅读(1802) | 评论(0) | 转发(0) |