4

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.

Saul
  • 992
  • 1
  • 13
  • 26
  • why do you need a frame pointer register for a call stack? I am confused. frame pointer registers are a lazy solution, just use the stack pointer and not waste another register. just compile some C code and see how the compiler does it then mimic that. – old_timer Oct 29 '13 at 00:55
  • actually thumb with the armv7m thumb 2 extensions (about 140-150 additional instructions) which means you could use an arm-like solution. – old_timer Oct 29 '13 at 00:57
  • 1
    I can't just use the stack pointer because I don't know the size of each stack frame in the calling functions. Also in regards to wasting a register, GCC's ARM assembly output is very strange in that uses a register as a near duplicate of the stack pointer (although I am compiling with `-OO`) – Saul Oct 29 '13 at 01:05
  • Doesn't GCC use r7 as FP under thumb mode? – auselen Oct 29 '13 at 10:31
  • I'm not sure because it's not reliably documented (or I'm looking in the wrong place!) See my comments on SilverCode's answer as to why `r7` is not usable as a frame pointer. – Saul Oct 29 '13 at 10:31
  • I didn't get why r7 can't be used. – auselen Oct 29 '13 at 10:38
  • Because it just points to the base of the stack for the current function. It doesn't point to the previous stack frame. – Saul Oct 29 '13 at 13:42
  • do you have a solution? I'm trying to do the same thing. – Dill Nov 19 '13 at 20:32
  • Unfortunately not. If you find one please post your answer here! – Saul Nov 20 '13 at 21:36

1 Answers1

2

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.

SilverCode
  • 189
  • 4
  • How do I tell GCC to use EABI? Also, doesn't the stack pointer point to the start of local variables that didn't fit into registers? – Saul Oct 28 '13 at 23:13
  • Correct, sp will point to the 5th parameter on entry to a 'function' e.g. foo( 1,2,3,4,5 ) The caller will store '5' at the sp location, r0..r4 will contain 1,2,3,4 The callee will read '5' from the sp location. Note that the stack is 'decrement before write' – SilverCode Oct 28 '13 at 23:59
  • I cannot use GDB as I have no OS, and the image running on the MBED board is not ELF, just the binary machine code. You are correct in saying that I'm trying to generate a call trace. This is not possible without a frame pointer as I can't walk the stack. Therefore my question is how do I force GCC to use a frame pointer (as `-fno-omit-frame-pointer` doesn't seem to have any effect), or rather, how can I find the address of the calling function, and the address of the calling function before that, ad infinitum. – Saul Oct 29 '13 at 00:01
  • Ah, I was using gdb with a JTAG (openocd) - it works really well. Otherwise you will probably have to do it the hard way with something like this: arm-none-eabi-objdump -D a.out > dis then look at the amount of stack used in each call It takes ages to do by hand. – SilverCode Oct 29 '13 at 00:09
  • 1
    -fno-omit-frame -pointer is working. The frame pointer gets stored in r7 in the tests I just run. – SilverCode Oct 29 '13 at 05:34
  • `add r7, sp, #0`: `r7` is just the stack pointer. This is what I was referring to when I said " GCC's ARM assembly output is very strange in that uses a register as a near duplicate of the stack pointer". – Saul Oct 29 '13 at 09:56
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/40201/discussion-between-silvercode-and-saul-rennison) – SilverCode Oct 29 '13 at 15:13
  • The "AAPCS Arm calling standard" link in this answer is now dead. An archive version pretty close to the date this answer was posted is: "https://web.archive.org/web/20131014052710/http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042e/IHI0042E_aapcs.pdf" – AJM Jul 27 '22 at 15:33