2010-10-20 2 views
5

Zum Beispiel gibt es die Quelle:Wie gcc zu sagen, um den Code mit Aufrufen meiner eigenen Funktion jedes _line_ des Codes zu instrumentieren?

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(); 
    } 
} 

Es als kompilieren sollte:

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

Natürlich sollte my_special_debugging_function der Lage sein, verwenden backtrace Funktion.

Gibt es die Option von gcc, es zu tun? Oder gibt es ein Tool, um es auf Souce-Code-Ebene zu tun?

@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

Nicht genau das. Sie sollten jedoch die Makros "__FILE__", "__LINE__" und "__func__" kennen. – nategoose

Antwort

4

Siehe -finstrument-functions in der GCC-Dokumentation (z andere C Souce mit meiner Funktion erzeugen). Möglicherweise möchten Sie dladdr() in der Debugging-Funktion verwenden, die auch eine Verknüpfung mit erfordert.

+2

'-Filter-Funktionen' arbeiten auf Funktionsebene. Wie schafft man es, zeilenweise zu arbeiten? –

+0

@Vi: Ich denke nicht, dass es irgendeine Möglichkeit gibt, GCC das zu sagen, ohne Vorprozesstricks und Änderungen am Quellcode. – nategoose

+0

@nategoose, OK, erneut nach Tricks für den Quellcode fragen: http://stackoverflow.com/questions/3989992/how-to-interleave-cc-souce-with-my-string-only-inside-functions-at -appropri –

0

Wie in der anderen Antwort erwähnt, 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

Wenn Sie eine gcc-Version> = 4.5 verwenden, können Sie write a gcc plugin, die das AST in der Art und Weise verarbeitet, die Sie mögen. Aber diese Lösung wäre compilerabhängig.

Sie können auch obtain AST from eclipse CDT und C-Code von diesem Eingang neu generieren.

0

Sie können es einfach mit aspectC++ tun. Holen Sie sich diesen Compiler von aspectc.org Hier ist ein einfacher Aspekt, der Ihre Anforderungen erfüllt. 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 

Kompilieren diesen Aspekt mit Ihrem Projekt aC++ Compiler dann das Programm ausführen. Dann sollten Sie die Spur in der Konsole sehen. Happy Tracing!

Verwandte Themen