5

I have function: foo()

I want to write a #define to put 'infront' of foo() (a shim I guess) to add debug to the front of foo(). So the #define should look this this:

   #define foo(dev) {                         \
      printk("%s: get %lx\n", (dev)->name);   \
      foo_orig(dev);                          \
   }

And then I rename foo() to foo_orig().

This works OK if foo() function is called in 'isolation' like this:

   foo(dev);

BUT, if its called within an if() then it is a compile problem...

   if (something() && foo(dev)) {
     ..

Have I explained the issue? and Is there a solution for this?

The problem is that I really need the shim as define because I need the code to live in the calling function rather than foo(). [The reason for this is because I need to dump out the EIP the the calling function for debug reasons (i.e. I need to know who is calling foo()].

4

7 回答 7

2

AFAIK 逗号运算符应该可以工作:

#define foo(dev) (printk("%s: get %lx\n", (dev)->name), foo_orig(dev))
于 2012-10-13T01:17:50.687 回答
1

我假设您使用的是 GCC,那么这应该会有所帮助:

#define foo(dev) ({                           \
      printk("%s: get %lx\n", (dev)->name);   \
      foo_orig(dev);                          \
   })

关键点是花括号周围的括号。

GCC:表达式中的语句和声明

于 2012-10-13T01:18:37.000 回答
1

问题是如何#define工作。

在预处理阶段,编译器将用foo定义的文本替换任何出现的 。因此,您的代码将如下所示:

  // call to foo() -> valid
  printk("%s: get %lx\n", (dev)->name);
  foo_orig(dev);    

  // within a parenthesis - invalid 
  if (something() && printk("%s: get %lx\n", (dev)->name);
          foo_orig(dev);) {

一种解决方案是使用真正的函数进行调试,像这样

foo_dbg(type *dev) {
   printk("%s: get %lx\n", (dev)->name);
   return foo_orig(dev);
}
#ifdef DEBUG
   #define foo(dev) foo_dbg(dev)
#else
   #define foo(dev) foo_orig(dev)
#endif
于 2012-10-13T01:21:42.327 回答
0

#define 就像进行搜索和替换。因此,您的“if”语句在编译时变为以下内容:

if (something() && { print(....); foo_orig(dev);}) {
}

那应该解释编译器错误。

于 2012-10-13T01:18:27.753 回答
0

使用逗号运算符:

#define foo(dev) (printk(blah, blah), foo_orig(dev))

使用 C99,您可以使用内联函数

static inline rtype foo (type *dev) { printk(blah, blah); return foo_orig(dev); }
于 2012-10-13T01:18:37.720 回答
0

也许用逗号替换;你的分号,并删除大括号/方括号。#define,{}

或者,在您的if声明中,替换foo(dev)(foo)(dev).

于 2012-10-13T01:21:24.740 回答
-1

原因是 b/ci 出于调试原因需要转储 EIP 调用函数(即我需要知道谁在调用 foo()

好吧,您可以编写一些程序集来查找堆栈上的返回地址;但实际上,大多数编译器已经有一个内置函数来解决这个需求;看到这里的 GCC(对于 Clang 是一样的),这里是 VC++(在英特尔编译器上是一样的)。

只需将您的 shim 写入 realfoo并使用_ReturnAddress()/__builtin_return_address(0)来获取函数的返回地址(即在call启动函数的指令之后的一条指令)。

于 2012-10-13T01:18:25.133 回答