0

Add -funwind-tables when cross-compiling, you can successfully unwind backtrace through the interface(_Unwind_Backtrace and _Unwind_VRS_Get) in the libgcc library. But when I added the -O2 option at cross-compiling time, unwind backtrace would fail. I pass -Q -O2 --help=optimizers print out the optimization and testing, but the results and -O2 is different, very strange,

W_xy
  • 1
  • Did you look and see what `-O2` actually does? What the entire set of optimization options it enables? And what those options do? – Andrew Henle Dec 26 '19 at 10:20
  • I use `-Q -O2 -help=optimizers` lists the O2 optimized option,unwind related programming optimization have been tested, the strange thing is not found abnormal optimization options – W_xy Dec 26 '19 at 11:41

1 Answers1

0

You haven't told us which ARM architecture you are building for - but assuming it's a 32-bit architecture, enabling -O2 has also enabled -fomit-frame-pointer-fomit-frame-pointer)

The frame-pointer

The frame pointer contains the base of the current function's stack frame (and with the knowledge that the caller's frame pointer is stored on the stack, a linked list of all stack frames in the call-tree). It's usually described as fp in documentation - a synonym for r11.

Omitting the frame-pointer

The ARM register file is small at 16 registers - one of which is the program counter. The frame pointer is one of the 15 that remains and is used only for debugging and diagnostics - specifically to provide stack walk-backs and symbolic debugging.

-fomit-frame-pointer tells the compiler to not maintain a frame pointer, thus liberating the r11 for other uses, and potentially avoiding spill of variables to the stack from registers. It also saves 4 bytes per stack-frame of stack storage and a store and load to the stack.

Naturally, if fp is used as general purpose register, its contents are undefined and walk-backs won't work.

You probably want to reenable the frame pointer with -fno-omit-frame-pointer for your own sanity.

marko
  • 9,029
  • 4
  • 30
  • 46
  • The device is a 32bit armv7 architecture, and when I cross-compiled I chose the `-fomit-frame-pointer` and `-funwind-tables` options, and although there was no stack frame, the stack backtrace was OK. When I added `-O2` and `-funwind-tables`, I could no longer do stack backtracking, which I didn't think was relevant. I have checked relevant information, the unwind way stack backtrace of ARM architecture is mainly carried out through`.ARM.exidx` section, I suspect that `-O2` option has affected `.ARM.exidx` section, – W_xy Dec 27 '19 at 01:16
  • unwind-tables are used for C++ exception handling. In `-O0` the compiler isn't trying very hard or at all?) to avoid spilling registers - so `r11` is unlikely to get used as a general purpose register and will at least contain something - even it's a calling function's frame-pointer. – marko Dec 28 '19 at 16:48
  • what's meaning? – W_xy Dec 30 '19 at 01:06
  • I think O2 may have optimized some registers, causing the stack backtrace to fail,but I can't find the relevant optimization options – W_xy Dec 31 '19 at 10:50
  • Many optimisations have the potential to make temporary variables in programs invisible to the debugger - possibly because they are never computed at all - or are computed as part of a bigger operation or as a side-effect. I just did an experiment with CompilerExplorer - https://godbolt.org/z/wJbRpk - I tried to build a function which would result in use of the frame pointer - it was surprisingly difficult. `-fomit-frame-pointer` definitely inhibited it being written to the stack-frame. – marko Dec 31 '19 at 11:56
  • In addition to the above methods, do you know any other methods of process stack tracing? – W_xy Jan 13 '20 at 08:45