2012-10-13 83 views
5

Tengo función: foo()tema # define si su llamada desde dentro de un if() bloquear

Quiero escribir un #define para poner 'frente' de foo() (una cuña supongo) para agregar depuración en la parte delantera de foo(). Así que la #define debe mirar esta esto:

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

Y luego cambiar el nombre foo()-foo_orig().

Esto funciona bien si foo() función se llama en 'aislamiento' de esta manera:

foo(dev); 

PERO, si su llamada dentro de un if() entonces es un problema de compilación ...

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

¿He explicado el problema? y ¿hay una solución para esto?

El problema es que realmente necesito el shim como definir porque necesito el código para vivir en la función de llamada en lugar de foo(). [La razón de esto es porque necesito volcar la EIP la función de la llamada por razones de depuración (es decir, lo que necesito saber quién está llamando foo()]

+1

Por qué no hacer una función en lugar de una macro que llama printk y luego devuelve el valor de foo_orig? – PherricOxide

+0

No estoy seguro de qué compilador usa, pero debería poder expandir las directivas de preprocesador y observar el código que el compilador ve (y no le gusta) después de la expansión –

Respuesta

2

yo sepa el operador coma debería funcionar:.

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

¿Por qué el voto a favor? – Pubby

+0

+1 Esto debería funcionar, suponiendo que 'printk' no es' nulo'. – dasblinkenlight

+0

@dasblinkenlight Estoy compilando bien si la expresión de la coma a la izquierda es 'void'. Tal vez su pensamiento de argumentos de función? – Pubby

-1

la razón de esto es B/CI necesita para volcar el EIP del la función de llamada por razones de depuración (es decir, lo que necesito saber quién está llamando foo()

Bueno, sólo podía escribir algunas asamblea para buscar th la dirección de devolución en la pila; pero en realidad, la mayoría de los compiladores ya tienen una función integrada para abordar esta necesidad; ver here para GCC (para Clang es lo mismo), here para VC++ (y en el compilador de Intel es el mismo).

Sólo tiene que escribir su cuña interior de la verdadera foo y utilizar _ReturnAddress()/__builtin_return_address(0) para obtener la dirección de retorno de la función (es decir, una instrucción después de la instrucción call que inicia la función).

+0

El problema no es obtener la dirección ... el 'printk' debería funcionar bien. –

0

#define es como hacer una búsqueda y reemplazar. Entonces su declaración 'if' pasa a ser la siguiente en tiempo de compilación:

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

Eso debería explicar el error del compilador.

+0

¿Por qué se bajó este voto? No está mal. – rmaddy

1

que suponga que está utilizando GCC, entonces esto debería ayudar:

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

El punto clave es paréntesis alrededor de las llaves.

GCC: Statements and Declarations in Expressions

0

Usar el operador coma:

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

Con C99 se puede utilizar una función en línea

static inline rtype foo (type *dev) { printk(blah, blah); return foo_orig(dev); } 
0

Quizás sustituir los puntos y comas ; en su #define por comas ,, y quite los soportes/soportes {}.

O, en su declaración if, reemplace foo(dev) con (foo)(dev).

+0

y ¿cuál es el valor de retorno? –

+1

@Thomas Berger: El valor de retorno del operador de coma es el RHS. –

+0

a la derecha, thx a tarde aquí también;) –

1

El problema es cómo funciona #define.

En la etapa de preprocesamiento, el compilador reemplazará cualquier aparición de foo con el texto definido. Por lo tanto, el código se verá así:

// 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);) { 

Una solución sería utilizar una función real de depuración, como este

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 
Cuestiones relacionadas