2012-10-13 8 views
5

ho funzione: foo()problema #define se chiamato dall'interno di un caso() bloccare

voglio scrivere un #define di mettere 'Infront' di foo() (uno spessore immagino) per aggiungere il debug al fronte di foo(). Così il #define dovrebbe guardare questo questo:

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

E poi ho rinominare foo()-foo_orig().

Questo funziona bene se foo() funzione viene chiamata in 'isolamento' in questo modo:

foo(dev); 

MA, se la sua chiamata all'interno di un if(), allora è un problema di compilazione ...

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

Ho spiegato il problema? e c'è una soluzione per questo?

Il problema è che ho davvero bisogno dello shim come definito perché ho bisogno del codice per vivere nella funzione chiamante anziché foo(). [La ragione di questo è perché ho bisogno di scaricare l'EIP la funzione della chiamata per motivi di debug (vale a dire Ho bisogno di sapere chi sta chiamando foo()]

+1

Perché non fare una funzione invece di una macro che chiama printk e poi restituisce il valore di foo_orig? – PherricOxide

+0

Non sai quale compilatore usi ma dovresti essere in grado di espandere le direttive del preprocessore e guardare il codice che il compilatore vede (e non piace) dopo l'espansione –

risposta

2

per quanto ne so l'operatore virgola dovrebbe funzionare:.

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

Perché il downvote? – Pubby

+0

+1 Questo dovrebbe funzionare, assumendo che 'printk' non sia' void'. – dasblinkenlight

+0

@dasblinkenlight Sto compilando bene se l'espressione sinistra della virgola è 'void'. Forse stai pensando a argomenti di funzione? – Pubby

-1

la ragione di questo è b/ci hanno bisogno di scaricare l'EIP la funzione chiamante per motivi di debug (vale a dire ho bisogno di sapere chi sta chiamando foo()

Beh, si può solo scrivere qualche assemblea per cercare th e indirizzo di ritorno in pila; ma in realtà, la maggior parte dei compilatori ha già una funzione per rispondere a questa esigenza; vedi here per GCC (per Clang è lo stesso), here per VC++ (e sul compilatore Intel è lo stesso).

Basta scrivere il vostro spessore all'interno del vero foo e utilizzare _ReturnAddress()/__builtin_return_address(0) per ottenere l'indirizzo di ritorno della funzione (vale a dire un'istruzione dopo l'istruzione call che ha iniziato la funzione).

+0

Il problema non è ottenere l'indirizzo ... il 'printk' dovrebbe funzionare bene. –

0

#define è come fare una ricerca e sostituirla. Quindi la tua istruzione "if" diventa la seguente in fase di compilazione:

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

Ciò dovrebbe spiegare l'errore del compilatore.

+0

Perché è stato downvoted? Non è sbagliato. – rmaddy

1

presumo che si sta utilizzando GCC, allora questo dovrebbe aiutare:

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

Il punto chiave è parentesi intorno parentesi graffe.

GCC: Statements and Declarations in Expressions

0

Utilizzare l'operatore virgola:

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

Con C99 è possibile utilizzare una funzione inline

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

Forse sostituire i punti e virgola ; nel vostro #define con le virgole ,, e rimuovere le parentesi graffe/parentesi {}.

Oppure, nell'istruzione if, sostituire foo(dev) con (foo)(dev).

+0

e qual è il valore restituito? –

+1

@Thomas Berger: il valore restituito dall'operatore virgola è RHS. –

+0

right, thx to late here too;) –

1

Il problema è come funziona #define.

Nella fase di pre-elaborazione, il compilatore sostituirà qualsiasi occorrenza di foo con il testo definito. Quindi, il codice sarà simile a questa:

// 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 soluzione potrebbe essere quella di utilizzare una funzione reale per il debug, come questo

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