[Dwarf-discuss] Enhancement: Dynamic DW_AT_data_bit_offset

2025-04-17 Thread Tom Tromey via Dwarf-discuss
Consider the appended Ada program.  Here, the offset of "Another_Field"
is a non-constant number of bits from the start of the object.

I think there is no way to represent this in DWARF 5.  Section 5.7.6,
page 119 says:

For a DW_AT_data_bit_offset attribute, the value is an integer
constant (see Section 2.19 on page 55) that specifies the number of
bits from the beginning of the containing entity to the beginning of
the data member. This value must be greater than or equal to zero,
but is not limited to less than the number of bits per byte.

GNAT works around this using the deprecated-in-DWARF-4 DW_AT_bit_offset
in conjunction with DW_AT_data_member_location.  (You need a patch to
GNAT to see this in action.)

One way to fix this would be to lift the "integer constant" restriction
and allow an expression here.

thanks,
Tom


procedure Exam is
   type Small is range -7 .. -4;
   for Small'Size use 2;

   type Packed_Array is array (Integer range <>) of Small;
   pragma pack (Packed_Array);

   subtype Range_Int is Natural range 0 .. 7;

   type Some_Packed_Record (Discr : Range_Int := 3) is record
  Array_Field : Packed_Array (1 .. Discr);
  Field: Small;
  case Discr is
 when 3 =>
Another_Field : Small;
 when others =>
null;
  end case;
   end record;
   pragma Pack (Some_Packed_Record);
   pragma No_Component_Reordering (Some_Packed_Record);

   SPR : Some_Packed_Record := (Discr => 3,
Field => -4,
Another_Field => -6,
Array_Field => (-5, -6, -7));

begin
   null;
end Exam;
-- 
Dwarf-discuss mailing list
Dwarf-discuss@lists.dwarfstd.org
https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss


Re: [Dwarf-discuss] Representing captured `this` in C++ lambdas

2025-04-17 Thread Cary Coutant via Dwarf-discuss
Alternatively, what if DW_AT_object_pointer could also take a
locdesc-class with a location description? Then, in cases where 'this' is
not a formal parameter, it could provide a location description in the same
manner as the other captured locals you mentioned (presumably with an
fbreg-based computation).

Whichever way we want to go, it sounds like the DWARF spec should provide
the necessary guidance. This looks like a good start to a proposal—Kyle,
would you like to write one? (See https://dwarfstd.org/comment.html.)

-cary


On Wed, Apr 16, 2025 at 2:11 PM David Blaikie via Dwarf-discuss <
dwarf-discuss@lists.dwarfstd.org> wrote:

>
>
> On Wed, Apr 16, 2025 at 8:59 AM Kyle Huey via Dwarf-discuss <
> dwarf-discuss@lists.dwarfstd.org> wrote:
>
>> This may be more of an implementation question than a spec question,
>> but this seems like the place to have the discussion regardless.
>>
>> C++ debuggers that support expression evaluation need to identify the
>> `this` pointer argument of member functions because C++ permits
>> unqualified access to member variables. DWARF 3 introduced the
>> DW_AT_object_pointer attribute for this purpose, and modern versions
>> of clang and gcc emit it. lldb actually uses this attribute when
>> present to find the this pointer argument, falling back to checking to
>> see if the first formal parameter to the function looks "this-like",
>> while gdb appears to use a name lookup at all times. Regardless, these
>> end up being interoperable for normal member functions.
>>
>> lambdas that capture the `this` of a member function present the same
>> need for debuggers, as unqualified accesses within the lambda can also
>> access member variables of `this`. Both clang and gcc desugar lambdas
>> to an anonymous struct type whose members are the captured variables,
>> with an operator() implementation that contains the body of the
>> lambda. They, however, different in their representation of a captured
>> `this` pointer.
>>
>> In clang's case the DWARF for the operator() contains a
>> DW_TAG_formal_parameter for a `this` parameter which is a pointer to
>> the anonymous struct type. That anonymous struct then contains its own
>> `this` member which is the captured `this`. lldb then contains code in
>> GetLambdaValueObject that recognizes this "double this" pattern and
>> deals with it appropriately.
>>
>> In gcc's case the DWARF for the operator() contains a
>> DW_TAG_formal_parameter for a `__closure` parameter which is a pointer
>> to the anonymous struct type. That anonymous struct contains a
>> `__this` member which is the captured `this`. Additionally, gcc emits
>> a DW_TAG_variable inside the operator() named `this` with the
>> appropriate DW_AT_location that traverses the anonymous struct (as it
>> does for all captured variables).
>>
>> In both cases the compilers emit a DW_AT_object_pointer on the
>> operator() pointing to the anonymous struct pointer parameter.
>>
>> This results in neither debugger being able to understand the output
>> of the opposite compiler. gdb cannot understand what clang has emitted
>> because it looks at the `this` parameter (which points to the
>> anonymous struct) and lldb cannot understand what gcc has emitted
>> because it expects the "double this" pattern. This is also annoying
>> for third party debuggers (like the one I maintain) because we need to
>> recognize and explicitly support both patterns.
>>
>> I haven't done any research into why the compilers chose to emit what
>> they do, but it seems to me[0] like things would be better if clang
>> copied gcc's "repeat the captured variables as locals inside
>> operator()" behavior (which would make gdb understand clang binaries)
>> and then both compilers switched their DW_AT_object_pointers to point
>> to the captured `this` if and only if it exists (which would make lldb
>> understand gcc binaries), ignoring the anonymous compiler-generated
>> struct entirely. Then lambdas that capture `this` would look like
>> member functions to debuggers and "just work" without any special
>> lambda-aware code.
>>
>> This would require at least some clarification in the spec since the
>> subprogram's DW_AT_object_pointer would point to a local, not a
>> parameter, and would point to an object of a different type than the
>> DW_TAG_class_type containing the subprogram (or would exist on a
>> subprogram not contained in a class at all if compilers elided the
>> anonymous struct from DWARF entirely).
>>
>> Any thoughts?
>>
>
> As a clang developer, I've some bias for the Clang representation here -
> and lambdas are classes (per the C++ spec) so it still makes sense to me
> that op() is a member function, though, yeah, having its "this" pointer
> given another name since users can't refer to it by that name.
>
> Introducing a bunch of locals that expose the right names/types - seems OK
> to me.
>
> Using object_pointer to refer to a local "this" could have other uses too
> - some languages (I forget which o