Issue 030812.1: Return Address Clarification

Author: Unclear
Champion: Todd Allen
Date submitted: 2003-08-12
Date revised:
Date closed:
Type: Editorial
Status: Accepted pending revision
DWARF Version: 3
PROBLEM: Getting the call address context correct can be difficult.

Andrew Cagney, Todd Allen, Chris Quenelle, Ron Brender
all described manifestations of the following problem:

 Functions (depending on hardware and software architectures)
 generate a 'return address register value'
 which is what dwarf can record in
 the Call Frame Information.

 If the function is known not to return the compiler may elid
 cleanup instructions.  Consequently the 'return address'
 may point to a context which is actually in a different
 function or a different source line or a completely different function.

Hardware architectures that have instructions of different lengths
often have no way to turn the 'return address' into a reliable
'calling address'.

------- Andrew Cagney's initial example where 'return address'
points to another function ----
The problem I've encountered is that the RA provided by func's CFI could
end up pointing at totally unrelated instruction  For instance the code:

    bar()
    {
      func () // no return
    }

    baz ()
    {
      ...

could become:

    bar:
        push arguments
        call func
    baz:
        prologue of baz <- RA

leading to a bogus unwind (other more edgy cases occure when the call is
at the end of a block - this one is easier to explain :-).
-------------

A typical workaround for the ia36 architecture is always to
subtract 1 from the return address to get the right 'context'
(even though the address involved may not be the beginning of the call
instruction, it is 'inside' the call instruction, so in the right
context).

PROPOSAL:

Add italics in the CFI information section.

 6.4.3  Call Frame Instruction usage


At the end of this section, add

"Typically one of the registers restored by Call Frame Information
is the Return Address register.   When a debugger unwinds call
information it really normally wants the call-site address, but
that is normally not recorded anywhere.

"In most cases the return address is the same context as the
call, but that need not be the case, especially if the
compiler knows (in some way) the call will never return.
The context of the 'return address' might be off the end
of the calling function entirely. As a result, a stack traceback
may partially or completely fail.

"For example, the x86
architecture has variable length instructions
so there is no certain way to get back from the 'return address'
to the 'call instruction'.
A simple workaround adopted by debugger implementations is
to subtract 1 from the 'return address'. While
This does not get the caller address, it does get an address
inside the calling instruction, so the right context is known
and a traceback can function reasonably."