tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: gcc: optimizations, and stack traces

    Date:        Sun, 11 Feb 2018 09:11:45 +0100
    From:        Maxime Villard <>
    Message-ID:  <>

  | So we have the same problem, and we need to find a way
  | to tell GCC to always push the frame at the beginning of the functions.

Either that or the stack unwind code needs to become smarter - which
would be a better solution, as it avoids dropping (the admittedly minor)
benefit  obtained from deferring the frame pointer update (which to be a
useful solution would need to be universal) and adds a (not insignificant)
cost to the stack unwind code - but performance there usually does
not matter.

We know all the information needed to unwind the stack correctly is
available, as (assuming gdb is not involved at all, and the code just
executes) the stack is correctly unwound when the function returns.

The only issue then is finding it - either the frame pointer or the stack
pointer references the current frame, the return address is obtained
from one or the other (and if needed, so is the previous frame poimter).

We know where the current function starts - the lookup of rip gave us
that info along with the function name, so we can look at that and find
the location where the frame pointer push happens (gdb already knows
how to decode instructions), we should be able to work out (by
simulation the instructions from function entry if needed) whether or
not the frame pointer push happened - at least with a fairly high
degree of confidence - enough to usually get things right.  Once
we know that, we have all the info needed to unwind properly.

Of course, this is no trivial amount of work, but it should be possible
to achieve something reasonable, if you really need it.

Personally, I've never found this kind of thing (including when the
compiler has optimised out tail recursion, and similar) all that
"impossible to debug" - somewhere back in the stack trace you
get accurate information about where a call originated.  From the
deepest such  point you can work out what was called (it is either
obvious, or generally possible to determine by looking at register/mem
contents).   From that, and from knowledge of where the code was when
it stopped it is usually not all that hard to determine what must have
happened - and in the investigation you tend to be forced to look at the
code involved so closely that you sometimes encounter the bug that you
was the cause of the problem before you were actually ready to start
looking for it..


Home | Main Index | Thread Index | Old Index