[Dwarf-Discuss] Location of a returned value?

Jason Molenda jmolenda at apple.com
Tue Jan 6 13:54:47 PST 2009

For i386/x86_64 at least (the two architectures I know best) I think  
it's reasonable to expect the debugger to divine the correct behavior  
from the ABI.  If the debugger knows the function's return type from  
the DWARF and it knows the ABI, it should be able to work out what to  
do.  The one fly in this ointment on i386/x86_64 is with C++ where an  
object with a copy constructor is returned by value.  In this case,  
you've got a bit of a problem on your hands. Concretely,

class f
   int x, y;
   f(const f&z) { x = z.x; y = z.y; }
   f(int a, int b) { x = a; y = b; }

f make_f ()
   f an_f (10, 20);
   return an_f;

int main ()
    f my_f = make_f();
    return my_f.x;

The x86_64 ABI rules would say that a structure of two ints being  
returned uses the small-struct-return aka pcc aka in-register return  
convention.  However the C++ ABI overrides that convention in this  
case and the large-struct-return aka caller-allocated-memory  
convention must be used.  If you're stepping through main() in gdb and  
you call the make_f() function from gdb, make_f() will get a random  
0th argument where it should store its returned structure (which may  
result in the program crashing) and even if it works, gdb won't know  
where to retrieve the return value from so it'll show you random junk.

I brought this up with the dwarf committee a year or two back - I  
always thought the most natural way to handle this particular case was  
to decorate the class type die with an attribute about its special ABI- 
changing nature instead of adding information to the function die  
specifying how its return type is returned.  But I never got much  
interest in this suggestion; I'm guessing other folks aren't seeing  
the problem or have found other ways to work around it.


On Jan 6, 2009, at 7:41 AM, Andrew Cagney wrote:

> Is there an ABI independent way to describe the location of a value
> returned by a function?  For instance:
> struct ret {
>  int i;
>  int j;
> }
> struct ret callee() {
>  struct ret r = { 1, 2 };
>  return r;
> }
> caller() {
>  struct ret r = callee(); // <- HERE
>  use(&r)
> }
> When stepping, out of callee() debuggers like to display the returned
> value.  Traditionally, this as been implemented using ABI specific
> code which, due to the nature of some ABIs it may not be possible to
> determine the location of that return value even though the compiler
> is fully aware of its location.  For instance, an ABI that passes in
> the return value's destination as a hidden address parameter:
>    ENTER
>    ALLOC "sizeof struct ret for r"
>    ALLOC "sizeof struct ret for return value"
>    PUSH "address of return value"
>    // user does a step -over this call leaving the debugger ...
>    CALLL caller
>    // <- ... here
>    MOVE "return value" to "r"
>    PUSH "address of r"
>    CALL use
>    EXIT
> After the return while the compiler knows where the result has been
> stored that information isn't always available to the debugger (other
> than using ABI heuristics such as trusting that the result's address
> is in a specific register).
> Several thoughts:
> - as part of the "step -over", the debugger could capture the return
> value's address using ABI knowledge; but this may not work when
> there's a "step -finish"
> - the callee function's debug info could describe the return value's
> address, if known
> - the caller could, at the return point ("... here", above) describe
> the returned value some how
> others?
> Andrew
> One
> _______________________________________________
> Dwarf-Discuss mailing list
> Dwarf-Discuss at lists.dwarfstd.org
> http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org

More information about the Dwarf-Discuss mailing list