2010-10-20 27 views
5

Par exemple, il est la source:Comment dire à gcc d'instrumenter le code avec des appels à ma propre fonction chaque _line_ de code?

void my_special_debugging_function(const char* function_name, const char* file_name, int line_number); 

void func1() { 
    func3(); 
    func4(); 
} 

void foo() { 
    func1(); 
    if(qqq) { 
     func2(); 
    }; 
    func3(); 
    func4(); 
    for(...) { 
     func5(); 
    } 
} 

Il devrait compiler comme:

void my_special_debugging_function(const char* function_name, const char* file_name, int line_number); 

void func1() { 
    my_special_debugging_function("func1", "prog.c", 3); 
    func3(); 
    my_special_debugging_function("func1", "prog.c", 4); 
    func4(); 
    my_special_debugging_function("func1", "prog.c", 5); 
} 

void foo() { 
    my_special_debugging_function("foo", "prog.c", 8); 
    func1(); 
    my_special_debugging_function("foo", "prog.c", 9); 
    if(qqq) { 
     my_special_debugging_function("foo", "prog.c", 10); 
     func2(); 
     my_special_debugging_function("foo", "prog.c", 11); 
    }; 
    my_special_debugging_function("foo", "prog.c", 12); 
    func3(); 
    my_special_debugging_function("foo", "prog.c", 13); 
    func4(); 
    my_special_debugging_function("foo", "prog.c", 14); 
    for(...) { 
     my_special_debugging_function("foo", "prog.c", 15); 
     func5(); 
     my_special_debugging_function("foo", "prog.c", 16); 
    } 
    my_special_debugging_function("foo", "prog.c", 17); 
} 

Bien sûr, my_special_debugging_function devrait être en mesure d'utiliser la fonction backtrace.

Y at-il une option de gcc pour le faire? Ou y a-t-il un outil pour le faire au niveau du code source? (Par exemple générer des autres C souce avec ma fonction)

@relatedHow to "interleave" C/C++ souce with my string (only inside functions at appropriate places)?

@relatedWhat profiler should I use to measure _real_ time (including waiting for syscalls) spend in this function, not _CPU_ one

+0

Pas exactement cela. Cependant, vous devez connaître les macros '__FILE__',' __LINE__' et '__func__'. – nategoose

Répondre

4

Voir -finstrument-functions dans la documentation de GCC. Vous pouvez utiliser dladdr() dans la fonction de débogage, ce qui peut également nécessiter une liaison avec -Wl,-export-dynamic.

+2

'-finstrument-functions' fonctionne au niveau de la fonction. Comment faire pour travailler par ligne? –

+0

@Vi: Je ne pense pas qu'il existe un moyen de dire à GCC de le faire, sans astuces de préprocesseur et modifications au code source. – nategoose

+0

@nategoose, OK, re-poser des questions sur les astuces pour le code source: http://stackoverflow.com/questions/3989992/how-to-interleave-cc-souce-with-my-string-only-inside-functions-at -approprié –

0

Comme indiqué dans l'autre réponse, I don't think that there is any way to tell GCC to do that, without preprocessor tricks and edits to the source code. – nategoose

2

Si vous utilisez une version gcc> = 4.5, vous pouvez write a gcc plugin qui traite l'AST de la manière que vous voulez. Mais cette solution dépendrait du compilateur.

Vous pouvez également obtain AST from eclipse CDT et régénérer le code C à partir de cette entrée.

0

Vous pouvez le faire facilement en utilisant aspectC++. Obtenez ce compilateur de aspectc.org Voici un aspect simple qui répond à vos besoins. Trace.ah

#ifndef __trace_ah__ 
#define __trace_ah__ 
#include <cstdio> 
#include <iostream> 
using namespace std; 
template <int I> struct ArgPrinter 
{ 
template <class JP> static inline void work (JP &tjp) { 
ArgPrinter<I - 1>::work (tjp); 
cout << *tjp.template arg<I - 1>() << " "; 
} 
}; 
template <> struct ArgPrinter<0> 
{ 
template <class JP> static inline void work (JP &tjp) {} 
}; 


aspect trace { 
int depth=-1; 
pointcut virtual methods() = "% ...::%(...)"; 

template <class JP> void print_args (JP &tjp) 
    { 
     ArgPrinter<JP::ARGS>::work (tjp); 
    } 

advice execution (methods()) : before() 
{ 
    depth++; 
    cout << "Enter -> " << JoinPoint::signature() <<" Depth:"<<depth<< " ARGS " << JoinPoint::ARGS <<" ("; 
    tjp->arg(0); 
    print_args (*tjp); 
    cout<<")"<<endl; 
    cout<< "console--"<<endl; 
} 

advice execution("% ...::%(...)" && !"void ...::%(...)") : after() 
{ 
    cout<< "--console"<<endl; 
    JoinPoint::Result res = *tjp->result(); 
    cout << "Exit <- " << tjp->signature()<< " Depth: "<<depth<< " RET " << res<<endl; 
    depth--; 
} 
advice execution("void ...::%(...)") : after() 
{ 
    cout<< "--console"<<endl; 
    cout << "Exit <- " << tjp->signature()<< " Depth: "<<depth<< " RET void"<<endl; 
    depth--; 
} 
}; 
#endif 

Compile cet aspect avec votre projet en utilisant le compilateur AC puis exécutez votre programme. Ensuite, vous devriez voir la trace dans la console. Bonne recherche!