mstackalign vs rbp order in gcc optimization level epilogue/prologue - O2/O3
AJ D
aatsnps@gmail.com
Tue Sep 29 07:46:49 GMT 2020
Hi,
I was looking at the implementation of mstackalign in gcc (O2/O3) and it
looks like we generate code for mstackalign (i.e. generate instructions for
stack alignment) before pushing $rbp to stack/setting $rbp. In the
epilogue, we do the same in reverse order.
some_routine:
0x0000000000400860 <+0>: lea 0x8(%rsp),%r10
0x0000000000400865 <+5>: and $0xfffffffffffffff0,%rsp
0x0000000000400869 <+9>: pushq -0x8(%r10)
0x000000000040086d <+13>: push %rbp
0x000000000040086e <+14>: mov %rsp,%rbp
:
0x0000000000400983 <+291>: pop %rbp
>> 0x0000000000400984 <+292>: lea -0x8(%r10),%rsp
0x0000000000400988 <+296>: retq
In gdb, when I single-step to IP (Instruction Pointer) 0x0000000000400984
(shown above) and try to get my stack trace using ‘gdb - where’, I do not
get my full stack trace, this is what I get:
(gdb) where
#0 0x00000000004009e3 in backtrace() ()
#1 0x0000000000400b18 in fac(int) ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb)
And of course, if I just do one more ‘single stepi’ and stop at the next
instruction retq / IP: 0x0000000000400988, then everything works fine.
(gdb) si
0x00000000004009e7 in backtrace() ()
(gdb) where
#0 0x00000000004009e7 in backtrace() ()
#1 0x0000000000400b18 in fac(int) ()
#2 0x0000000000400b49 in func1(int) ()
#3 0x0000000000400b69 in func2(int) ()
#4 0x000000000040078a in main ()
(gdb)
It looks like this issue is showing up due to the order in which ‘%rbp’ is
saved/restored w.r.t the ‘stack alignment code’ execution.
In CLANG, %rbp is pushed/set first, then the stack is aligned, here is the
CLANG generated code:
Some_func:
0x0000000000400850 <+0>: push %rbp
0x0000000000400851 <+1>: mov %rsp,%rbp
:
0x000000000040085d <+13>: and $0xfffffffffffffff0,%rsp
0x0000000000400861 <+17>: sub $0x8d0,%rsp
0x0000000000400868 <+24>: lea 0x520(%rsp),%r14
0x0000000000400870 <+32>: mov %r14,%rdi
:
0x000000000040093a <+234>: lea -0x28(%rbp),%rsp
:
0x0000000000400947 <+247>: pop %rbp
0x0000000000400948 <+248>: retq
And with the CLANG generated code, ‘gdb – where’ works fine at every
instruction pointer.
Whereas, in GCC, the stack is aligned first, then the %rbp is pushed/set
and that seems to be opening up a few instruction holes where 'gdb - where'
wouldn't work.
Would you folks consider this as a GCC bug? Do you folks see any issue in
the CLANG approach? Is there a way (any switch) in gcc which would reverse
the order of ‘setting %rbp’ vs ‘stack alignment code’ (like CLANG)?
I used -mstackrealign with -O3 and -fomit-frame-pointer for generating my
code.
More information about the Gcc
mailing list