6

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_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

Community
  • 1
  • 1
Vi.
  • 37,014
  • 18
  • 93
  • 148
  • Not exactly that. You should be aware of the `__FILE__`, `__LINE__`, and `__func__` macros, though. – nategoose Oct 20 '10 at 23:31
  • @simonhf Does it instrument within functions? Can it add its thing to each source code line inside functions? – Vi. May 05 '20 at 14:51
  • It auto instruments the entry and exit points of each function via `-finstrument-functions`. However, additionally, you can manually add permanent instrumentation macros inside functions. Both auto and manually added macros respect the same individual verbosity set for the function. It's very similar to what you describe above except all the macros in func1() respect a verbosity set for func1(), and all the macros in foo() respect a vebosity set for foo(). – simonhf May 05 '20 at 18:47

4 Answers4

5

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.

jilles
  • 10,509
  • 2
  • 26
  • 39
  • 3
    `-finstrument-functions` work at function level. How to make it to work line-wise? – Vi. Oct 21 '10 at 09:54
  • @Vi: 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 Oct 21 '10 at 15:17
  • @nategoose, OK, re-asking about tricks for source code: http://stackoverflow.com/questions/3989992/how-to-interleave-c-c-souce-with-my-string-only-inside-functions-at-appropri – Vi. Oct 21 '10 at 17:01
2

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.

Aykut Kllic
  • 898
  • 9
  • 14
-1

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!

arefinsami
  • 363
  • 2
  • 7
  • 18
-1

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

Vi.
  • 37,014
  • 18
  • 93
  • 148