How to tell gcc to instrument the code with calls to my own function each _line_ of code?
For example, there is the source:
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();
}
}
It should compile as:
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开发者_如何学JAVA_function("foo", "prog.c", 17);
}
Of course, my_special_debugging_function should be able to use backtrace
function.
Is there option of gcc to do it? Or is there a tool to do it at souce code level? (e.g. generate other C souce with my function)
@related How to "interleave" C/C++ souce with my string (only inside functions at appropriate places)?
@related What profiler should I use to measure _real_ time (including waiting for syscalls) spend in this function, not _CPU_ one
See -finstrument-functions
in the GCC documentation. You may want to use dladdr()
in the debugging function, which may also require linking with -Wl,-export-dynamic
.
If you are using a gcc version >=4.5 you can write a gcc plugin that processes the AST in the way you like. But that solution would be compiler dependent.
You can also obtain AST from eclipse CDT and regenerate C code from that input.
As stated in the other answer, 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
You can do it easily using aspectc++. Get this compiler from aspectc.org Here is a simple aspect which serves your requirements. 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 this aspect with your project using ac++ compiler then run your program. Then you should see the trace in the console. Happy Tracing!
精彩评论