Chinaunix首页 | 论坛 | 博客
  • 博客访问: 606291
  • 博文数量: 197
  • 博客积分: 7001
  • 博客等级: 大校
  • 技术积分: 2155
  • 用 户 组: 普通用户
  • 注册时间: 2005-02-24 00:29
文章分类

全部博文(197)

文章存档

2022年(1)

2019年(2)

2015年(1)

2012年(100)

2011年(69)

2010年(14)

2007年(3)

2005年(7)

分类: C/C++

2011-03-05 23:24:02

      大型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);
};;


阅读(1798) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~