如何告诉gcc使用我自己的函数调用每个_line_代码来检测代码?

时间:2010-10-20 22:32:44

标签: c gcc profiling instrumentation

例如,有来源:

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

它应编译为:

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

当然,my_special_debugging_function应该能够使用backtrace函数。

gcc可以选择吗?或者是否有工具在源代码级别执行此操作? (例如,用我的功能生成其他C源)

@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

4 个答案:

答案 0 :(得分:4)

请参阅GCC文档中的-finstrument-functions。您可能希望在调试功能中使用dladdr(),这可能还需要与-Wl,-export-dynamic进行链接。

答案 1 :(得分:2)

如果您使用的是gcc版本> = 4.5,您可以write a gcc plugin以您喜欢的方式处理AST。但该解决方案将取决于编译器。

您还可以obtain AST from eclipse CDT并从该输入重新生成C代码。

答案 2 :(得分:0)

如其他答案所述,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

答案 3 :(得分:-1)

您可以使用aspectc ++轻松完成。从 aspectc.org 获取此编译器这是一个符合您要求的简单方面。 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

使用ac ++编译器在项目中编译此方面,然后运行程序。然后你应该在控制台中看到跟踪。 快乐的追踪!