[Dwarf-Discuss] Location of a returned value?

Jason Molenda jmolenda at apple.com
Thu Jan 15 13:35:29 PST 2009


Just to help argue your point for you :) - at one point our compiler  
at Apple had an alternate calling convention for functions with static  
linkage that it would use on occasion which caused us troubles.  We  
used symbol name decoration (foo$FASTCALL or whatever it was) to  
indicate to the debugger what was going on.  In our particular case it  
was only used for a small number of functions, only on i386, and IIRC  
the ABI difference was only related to parameter passing.

But yes, in this case having the ability to describe the return  
location could have been beneficial.

J

On Jan 15, 2009, at 10:34 AM, Andrew Cagney wrote:

> True; it's typically possible; if very tedious.
>
> This starts to breakdown though when the compiler starts looking to
> violate the ABI, for instance when trying to optimize "local" function
> calls (how real this is currently I don't know) or when using
> alternative calling conventions.  I think, rather than rely on the
> ABI, there may be an opportunity here for DWARF to describe what is
> really going on.
>
> Any way, without real code, this is somewhat theoretical.
>
> Andrew
>
>
> On Tue, Jan 6, 2009 at 4:54 PM, Jason Molenda <jmolenda at apple.com>  
> wrote:
>> 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
>> {
>> public:
>> 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.
>>
>>
>> J
>>
>>
>> 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
>>>  RETURN
>>>
>>> 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