On 20/05/2019 18:08, Vicente Bergas wrote: > On Monday, May 20, 2019 6:44:19 PM CEST, Richard Earnshaw (lists) wrote: >> On 20/05/2019 15:45, Vicente Bergas wrote: >>> Hello, >>> i would like to have a debug build with frame pointers on an ARM >>> Cortex-M4 MCU. >>> These are the options passed to GCC 9.1.0: >>> >>> -fno-omit-frame-pointer >>> -mthumb >>> -march=armv7e-m >>> -mtune=cortex-m4 >>> -mcpu=cortex-m4 >>> -mfloat-abi=hard >>> -ffreestanding >>> -std=c11 >>> >>> I also tested several combinations of the following options: >>> >>> -mabi=aapcs >> >> This is the default these days. >> >>> -mabi=atpcs >>> -mapcs-frame >>> -mtpcs-frame >>> -mtpcs-leaf-frame >> >> All of the above are deprecated relics of the old APCS, TPCS and ATPCS >> ABIs. >> >>> -mno-sched-prolog >>> -O1 >>> -O0 >>> >> >> These have no direct effect on use of the frame pointer. >> >>> But never got the fp register (r11) set up. >>> This is one sample function from objdump (fp appears nowhere): >>> >>> 80005c0: b5b0 push {r4, r5, r7, lr} >>> 80005c2: af00 add r7, sp, #0 >>> 80005c4: 4605 mov r5, r0 >>> 80005c6: 2030 movs r0, #48 >>> 80005c8: f7ff ffa6 bl 8000518 >>> 80005cc: 2078 movs r0, #120 >>> 80005ce: f7ff ffa3 bl 8000518 >>> 80005d2: 241c movs r4, #28 >>> 80005d4: fa25 f304 lsr.w r3, r5, r4 >>> 80005d8: f003 030f and.w r3, r3, #15 >>> 80005dc: 2b09 cmp r3, #9 >>> 80005de: bfcc ite gt >>> 80005e0: 2037 movgt r0, #55 >>> 80005e2: 2030 movle r0, #48 >>> 80005e4: 4418 add r0, r3 >>> 80005e6: f7ff ff97 bl 8000518 >>> 80005ea: 3c04 subs r4, #4 >>> 80005ec: f114 0f04 cmn.w r4, #4 >>> 80005f0: d1f0 bne.n 80005d4 >>> 80005f2: bdb0 pop {r4, r5, r7, pc} >>> >>> So, all in all, how can it be done? >> >> In answer to your question, it depends on why you want a frame pointer. >> >> If you mean to address local variables via a register other than SP, >> then -fno-omit-frame-pointer is sufficient, but GCC will currently use >> r7 in this case from thumb code. >> >> If you want to create a frame backtrace structure by which you can walk >> the stack without dwarf based debug information being included, then GCC >> does not currently have any means to do this from thumb2 code. >> >> Sorry. We're thinking about what can be done here, but this is an ABI >> issue and must be resolved there first. >> >> R. > > Thanks Richard for such a quick answer. > I wanted to print a backtrace when the HardFault interrupt is triggered. > From what you say, that is not possible and it is not GCCs fault, is a lack > on the ABI. That also explains why Clang neither keeps track of the frame > pointer. > Why is the register r11 reserved as "fp" and the ABI has no use for it? > > Anyways, i'll put a stack on the application and push to it at every > function entry point and pop from it at exit. Sigh. > > Regards, > Vicenç. > I'm not sure what you mean by 'reserved'. The AAPCS does not reserve it. GCC however, still occasionally needs to use a register for it's own internal purposes of laying out a stack frame (when the value held in SP cannot be kept invariant during a function). In this case it creates what it terms a frame pointer to point to the current stack frame and uses that for addressing the local variables that reside on the stack (normally it can eliminate this use and address such variables directly via SP). However, on Arm there's no mandated layout of the call saved registers relative to where this register points and consequently it's of no use for a forming a frame chain. Things are further complicated due to the history of the architecture. In the early days, when only the Arm (A32) instruction set existed, R11 was initially allocated as a traditional frame pointer and thus known as FP. There was a well formulized sequence for creating a stack frame which included a frame chain. But then the original thumb instruction set came along, which couldn't use r11 for addressing memory (as it wasn't in the register subset r0-r7,sp,pc which had instructions for making such accesses). At such point the APCS frame pointer (r11) became deprecated. Furthermore, compilers started using r7 for the internal uses of a frame pointer when SP could not be used in thumb code, but continued to use r11 in Arm code. But it's then impossible to create a frame chain as Arm and Thumb functions can call each other and it is far to expensive for a function to have to work out which of r7 and r11 is a frame pointer at every call site. Frame pointers, however, were fortunately becoming much less important to debugging by this point as object file formats such as ELF could support rich debug information formats, such as Dwarf. So the decision was taken in the ATPCS to drop the concept of a global frame pointer entirely, allowing compilers do generate whatever code sequences provided the best code and to then use Dwarf to describe to debugging tools how to reconstruct the call hierarchy when necessary. However, there are some environments where a very simple stack-based chain can prove very useful, because it is expensive to have to decode the dwarf unwind data on the fly (it doesn't usually matter in debuggers since the target program is normally stopped when unwinding is being done). So we are looking at what options are available to us at this point. In the mean time your only real option is either something you construct yourself, or to use the information recorded in either the dwarf data or the C++ exception unwinding tables (you can ask GCC to include this even when compiling languages other than C). R.