- 论坛徽章:
- 0
|
本帖最后由 baozhao 于 2011-03-05 23:36 编辑
http://blog.chinaunix.net/space.php?uid=1858380&do=blog&id=156282
大型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);
- };;
复制代码 |
|