Saul
Saul

Reputation: 1002

ARM: Call stack generation with no frame pointer

I'm trying to construct a call stack on a Cortex-M3 processor (ARMv7-M architecture), no OS (bare metal). However, there is no frame pointer register for this ABI. Therefore I'm struggling to generate the call stack when I have no frame pointer.

Regardless of using -mapcs-frame, -fno-omit-frame-pointer and -O0 options with GCC, no frame pointer is kept. I'm wondering if there's a different ABI I can force GCC to use so I have a frame pointer/stack frame? If not, is there some other reliable method of generating a call stack?

Thanks in advance.

Upvotes: 5

Views: 7702

Answers (1)

SilverCode
SilverCode

Reputation: 209

BTW wrt the comment above, the ARM calling standard is the same as Thumb, see (AAPCS Arm calling standard) The instruction sets are different BUT the CPU register set is not.

I would prefer to ask questions in the comments, but as yet I do not have enough points. With that in mind....

Do you have a binary successfully built and execution, but you are trying to dump some kind of call trace? My confusion is the 'no frame pointer register' statement - r13 is the stack frame pointer. I think you are referring to storing the frame pointer though.

It has been a while but I think these are the options I used

arm-none-eabi-gcc - -nostdlib -ggdb -mthumb -mcpu=cortex-m3 -mtpcs-frame -mtpcs-leaf-frame myfile.c

This was on gcc-arm-none downloaded from linaro. gdb was able to do a backtrace with those options on an Atmel SAM3X. The Thumb ABI was the same as the ARM EABI, or at least appears to be looking at the assembler via objdump -D .

The previous frame pointer gets stored in r7 when -fno-omit-frame-pointer is specified (or implied)

void test2(int i) {}
void main() { test(0); 

Compiled with -fomit-frame-pointer

00008000 <test2>:
    8000:   b082        sub   sp, #8
    8002:   9001        str   r0, [sp, #4]
    8004:   b002        add   sp, #8
    8006:   4770        bx lr

00008008 <main>:
    8008:   b508        push  {r3, lr}
    800a:   f04f 0000   mov.w r0, #0
    800e:   f7ff fff7   bl 8000 <test2>
    8012:   bd08        pop   {r3, pc}

Compiled with -fno-omit-frame-pointer

00008000 <test2>:
    8000:   b480        push  {r7}
    8002:   b083        sub   sp, #12
    8004:   af00        add   r7, sp, #0
    8006:   6078        str   r0, [r7, #4]
    8008:   f107 070c   add.w r7, r7, #12
    800c:   46bd        mov   sp, r7
    800e:   bc80        pop   {r7}
    8010:   4770        bx lr
    8012:   bf00        nop

00008014 <main>:
    8014:   b580        push  {r7, lr}
    8016:   af00        add   r7, sp, #0
    8018:   f04f 0000   mov.w r0, #0
    801c:   f7ff fff0   bl 8000 <test2>
    8020:   bd80        pop   {r7, pc}
    8022:   bf00        nop

So use r7 to get to the previous stack frame, then get the next r7 from that location and so on.

Upvotes: 2

Related Questions