views:

185

answers:

3

When -fomit-frame-pointer is used (automatic for various -O settings), performing a backtrace is problematic. I am wondering if there is a way of determining at compile time that the code is compiled with this switch? In that case, I could put in an #ifndef to guard against backtracing when ill-advised.

Is any macro set when this -fomit-frame-pointer switch is on?

Thanks,

SetJmp

+2  A: 

I just tried this:

gcc -E -fomit-frame-pointer -Wp,-dM foo.c > fpo.out
gcc -E -Wp,-dM foo.c > no-fpo.out
diff no-fpo.out fpo.out

where foo.c is a simple "Hello World" program, and got no results. This means all of the preprocessor macros were identical, whether -fomit-frame-pointer was used or not. So I think the answer to your question is "no".

Probably the best you can do is modify your Makefile (or whatever your build process uses) to define your own macro (e.g. -DNO_FRAME_POINTERS, or something) when using -fomit-frame-pointer.

Dan Moulding
Optimisation implies -fomit-frame-pointer, and I guess that's the main problem.
qrdl
According to the gcc docs, optimization doesn't always imply -fomit-frame-pointer. It can depend on the architecture, and how that particular optimization affects the ability to debug. From the man page: "-O also turns on -fomit-frame-pointer on machines where doing so does not interfere with debugging."
Dan Moulding
A: 

You cannot do it at compile time, but at runtime you can check whether your program optimised or not.

Write a code that definitely will be changes by optimiser, like mixing non-volatile variable with setjmp/longjmp, and by the value of that variable you will know whether your program is optimised or not.

#include <setjmp.h>
#include <stdio.h>

int is_optimised(void) {
    int i = 1;
    jmp_buf jmp_loc;

    if (setjmp(jmp_loc)) {
        return i;  // optimiser changes it to "return 1"
    }

    i = 0;
    longjmp(jmp_loc, 1);

    return 0;
}

int main(int argc, char *argv[]) {
    printf("%soptimised\n", is_optimised() ? "" : "non-");

    return 0;
}

If compiled with GCC without -O switch it prints "non-optimised", for switches -O1 to -O4 it prints "optimised".

Of course your mileage (with other compilers) may vary.

qrdl
+1  A: 

As for the check, at runtime check if ebp register (adjust for your architecture) points to a few bytes below the top of the stack and then if following the pointer stored at [ebp] makes sense.

Joshua