Frame Pointer October 19, 2005

Here’s a short note about GCC, frame pointers and the STABS debugging format. The target processor architecture in these examples is the Hitachi SH. Consider the short C program:

int
main(void)
{
        volatile int            a;
        volatile long long      b;

        return a+b;
}

The program doesn’t perform any actual computation, and will return the sum of two uninitialized automatic variables, a and b. They are defined as volatile to prevent GCC from optimizing away the memory accesses. Compile with sh-coff-gcc -gstabs3 -c -O3 -fomit-frame-pointer test.c
First, looking at the STABS debugging info in the output object file:

test.o:     file format coff-sh

Contents of .stab section:

Symnum n_type n_othr n_desc n_value  n_strx String

-1     HdrSym 0      34     00000394 1
0      SO     0      0      00000000 8      test.c
1      OPT    0      0      00000000 15     gcc2_compiled.
2      LSYM   0      0      00000000 30     int:t(0,1)=r(0,1);-2147483648;2147483647;
3      LSYM   0      0      00000000 72     char:t(0,2)=r(0,2);0;127;
4      LSYM   0      0      00000000 98     long int:t(0,3)=r(0,3);-2147483648;2147483647;
5      LSYM   0      0      00000000 145    unsigned int:t(0,4)=r(0,4);0;4294967295;
6      LSYM   0      0      00000000 186    long unsigned int:t(0,5)=r(0,5);0;4294967295;
7      LSYM   0      0      00000000 232    long long int:t(0,6)=r(0,6);-9223372036854775808;9223372036854775807;
8      LSYM   0      0      00000000 302    long long unsigned int:t(0,7)=r(0,7);0;-1;
9      LSYM   0      0      00000000 345    short int:t(0,8)=r(0,8);-32768;32767;
10     LSYM   0      0      00000000 383    short unsigned int:t(0,9)=r(0,9);0;65535;
11     LSYM   0      0      00000000 425    signed char:t(0,10)=r(0,10);-128;127;
12     LSYM   0      0      00000000 463    unsigned char:t(0,11)=r(0,11);0;255;
13     LSYM   0      0      00000000 500    __int128_t:t(0,12)=r(0,12);0;-1;
14     LSYM   0      0      00000000 533    __uint128_t:t(0,13)=r(0,13);0;-1;
15     LSYM   0      0      00000000 567    float:t(0,14)=r(0,1);4;0;
16     LSYM   0      0      00000000 593    double:t(0,15)=r(0,1);8;0;
17     LSYM   0      0      00000000 620    long double:t(0,16)=r(0,1);8;0;
18     LSYM   0      0      00000000 652    complex int:t(0,17)=s8real:(0,1),0,32;imag:(0,1),32,32;;
19     LSYM   0      0      00000000 709    complex float:t(0,18)=R3;8;0;
20     LSYM   0      0      00000000 739    complex double:t(0,19)=R4;16;0;
21     LSYM   0      0      00000000 771    complex long double:t(0,20)=R4;16;0;
22     LSYM   0      0      00000000 808    __builtin_va_list:t(0,21)=*(0,22)=(0,22)
23     LSYM   0      0      00000000 849    _Bool:t(0,23)=eFalse:0,True:1,;
24     BINCL  0      0      00000000 881    test.c
25     FUN    0      0      00000000 888    main:F(0,1)
26     SLINE  0      3      00000000 0
27     SLINE  0      7      00000008 0
28     SLINE  0      8      00000010 0
29     LSYM   0      0      00000000 900    a:(0,1)
30     LSYM   0      0      00000004 908    b:(0,6)
31     LBRAC  0      0      00000008 0
32     RBRAC  0      0      00000010 0
33     SO     0      0      0000001c 0

The debugging information specifies variable addresses as offsets from the frame pointer.
Symnum 29 and 30 say that variables a and b are at offsets 00000000 and 00000004 from the frame pointer, and that they have types (0,1)(int) and (0,6)(long long int) (You can figure out why from the above (see Symnum 2 and 7), or read this).

The debugging information specifies variable addresses as offsets from the frame pointer.

The upshot of this is, when a debugger is acting on the program, it will read memory at address frame pointer + 0×0 and interpret its contents as the value of variable a and so on.
The code generated by sh-coff-gcc -O3 -fomit-frame-pointer -S test.c looks like

        .file   "test.c"
        .data
        .text
        .align 2
        .global _main
_main:
        mov.l   L2,r0
        sts.l   pr,@-r15
        jsr     @r0
        add     #-12,r15
        mov.l   @(4,r15),r1
        mov.l   @(8,r15),r1
        mov.l   @r15,r0
        add     r1,r0
        add     #12,r15
        lds.l   @r15+,pr
        rts
        nop
L3:
        .align 2
L2:
        .long   ___main
        .ident  "GCC: (GNU) 3.2.3"

In the above, the frame pointer, r14, is not being used at all. Compare this to code generated by sh-coff-gcc -O0 -S test.c:

        .file   "test.c"
        .data
        .text
        .align 2
        .global _main
_main:
        mov.l   r14,@-r15
        sts.l   pr,@-r15
        add     #-12,r15
        mov     r15,r14
        mov.l   L2,r1
        jsr     @r1
        nop
        mov.l   @(4,r14),r1
        mov.l   @(8,r14),r2
        mov.l   @r14,r1
        add     r2,r1
        mov     r1,r0
        add     #12,r14
        mov     r14,r15
        lds.l   @r15+,pr
        mov.l   @r15+,r14
        rts
        nop
L3:
        .align 2
L2:
        .long   ___main
        .ident  "GCC: (GNU) 3.2.3"

That’s all for now.

Tags
Conversation
Related Tags
Comments
Trackback


Leave a Reply

You must be logged in to post a comment.

This entry was posted on Wednesday, October 19th, 2005 at 8:23 am. You can follow any responses to this entry through the RSS 2.0 feed. If you're wondering how to get your own icon next to your comment, go visit gravatar.com and get yourself hooked up.
 steal compass, drive north, disappear...