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.

Reply via email to