[Dwarf-Discuss] What to do with Pascal properties?

David Blaikie dblaikie@gmail.com
Sat Jun 5 22:37:46 GMT 2021


On Sat, Jun 5, 2021 at 5:59 AM Joost van der Sluis via Dwarf-Discuss
<dwarf-discuss at lists.dwarfstd.org> wrote:
>
> Op 03-06-2021 om 00:50 schreef David Blaikie via Dwarf-Discuss:
> > On Fri, May 28, 2021 at 8:29 AM Joost van der Sluis via Dwarf-Discuss
> > <dwarf-discuss at lists.dwarfstd.org> wrote:
> >> Now in Pascal there are 'properties'. Maybe you know these from c# which
> >> has something alike. Basically a property is an alias in a structure
> >> that links to other members of the same structure for reading, writing
> >> and/or storage-information.
> >
> > Hmm - so this isn't like C# where you can write arbitrary code for the
> > property? In this case it's only direct access - but you get to choose
> > whether it's read only, read-write, etc, compared to having the member
> > directly be public?
> >
> > That might 'just work' with existing DWARF consumers/debuggers if you
> > had the alias as another member (as you say, with different access
> > level) that happens to have the same data_member_location as the
> > underlying member - you could add an extra/extension attribute to
> > describe it as being read only, etc.
> >
> > I doubt the duplication of the data_member_location would be super
> > expensive - but I could be wrong. Might be worth measuring, especially
> > if this representational choice does get you "free" support in
> > existing DWARF consumers, compared to having to teach them about new
> > attributes, etc.
>
> They can do both - direct access and arbitrary code. And I agree that in
> the case of direct access it is not that expensive.
>
> >> Example:
> >>
> >> type
> >>     TMyClass=class
> >>     private
> >>       FProp: Integer;
> >>       FPropIsStored: Boolean;
> >>     protected
> >>       function GetProp: Integer;
> >>       function GetItem(const Index: Integer): string;
> >>     public
> >>       property IndividualItem[Index: Integer]: string read GetItem;
> >>     published
> >>       property Prop: Integer read GetProp stored FPropIsStored;
> >>       property OtherProp: Integer read FProp write FProp;
> >>       property Item2: string index 2 read GetItem;
> >>     end;
> >>
> >> var
> >>     MyClass = TMyClass;
> >>
> >> Reading MyClass.Prop effectively calls GetProp.
> >>
> >> MyClass.Prop is read-only, and during streaming the information in
> >> FPropIsStored is being used.
> >>
> >> MyClass.OtherProp is read/write, and is more or less an alias for the
> >> private FProp field.
> >>
> >> MyClass.IndividualItem[6] is accessible like it is an array. And Item2
> >> has a fixed index.
> >>
> >> I want to encode this propery into the Dwarf debug-information.
> >
> > First question I usually ask is: Is there any prior art? (does GCC
> > support this situation, what DWARF does it use to describe these
> > entities? What about other DWARF producers?)
>
> Yes, that would be easy. But I do not know of any feature in C or C++ or
> any other language that is comparable to this functionality, except for
> C#, but that does not generate Dwarf debug-information. But I am well
> aware that  do not know all existing languages that well. ;)
>
> >> At this
> >> moment we only generate debug-information for cases similar to
> >> MyClass.OtherProp by duplicating the debug-information of FProp with
> >> another visibility-class.
> >
> > Ah, guess that's my suggestion above?
>
> Yes.
>
> >> I've added the following attributes:
> >>     DW_AT_FPC_property_read (0x3230)
> >>     DW_AT_FPC_property_write (0x3231)
> >>     DW_AT_FPC_property_stored (0x3232)
> >>
> >> And then those attributes contain a link to the corresponding
> >> DW_TAG_members.
> >
> > OK, so FW_AT_FPC_property_stored uses an address form, most likely a
> > CU-local one, like DW_FORM_ref4, etc?
>
> Well, my current implementation always uses DW_FORM_ref_addr, but I now
> realize that this should be a DW_FORM_ref4 most of the time.
> It is possible to reference a member in a another CU, though. So local
> is not always possible.
>
> >> This to keep the debug-information as compact as
> >> possible. Furthermore I've added the tag DW_TAG_FPC_property (0x4230) or
> >> else other debuggers may be confused when they encounter a DW_TAG_member
> >> with only one or more of these specific fpc-attributes.
> >>
> >> I'll also have to add something like DW_AT_FPC_property_index to store
> >> the value of a fixed index.
> >>
> >> I have two questions:
> >> 1. Am I on the good track, or did I miss something?
> >
> > Sounds plausible.
> >
> >> 2. Maybe implementation specific, but maybe someone might have an idea:
> >> to generate the proposed debug-info, I need to add a label to every
> >> DW_TAG_member.
> >
> > The way LLVM deals with CU-local DIE references isn't with labels - it
> > precomputes the offsets of all the DIEs and uses the known offset for
> > the FORM value.
> >
> > You can see that here: https://godbolt.org/z/hqdP4x5eG
> >
> > .long 51 # DW_AT_type
> >
> > But LLVM also uses labels and relocations without issue - especially
> > local labels (as Michael mentioned), section labels, and label
> > differences (the latter is all you'd need if you wanted to do
> > CU-relative references with labels instead of manually computing them)
> > - label differences are resolved at assembly time, so they don't exist
> > by the time the linker sees things & can't complicate that.
>
> Yes, for cu-local references I can use local-labels and use their
> differences.
>
> For cu-global I have to precompute the offsets for a global label, this
> must be doable.

Yep, when doing cross-CU inlining, for instance in LTO. LLVM will
produce two CUs in one object file, but needs to use a
section-relative offset (so it can't hardcode it, even though it knows
the offset within the current .debug_info section - it doesn't know
that more pieces of debug info won't go before this chunk in the final
linked binary)

The assembly that LLVM produces for that looks like this:

.byte   49                              # DW_AT_abstract_origin
.byte   16                              # DW_FORM_ref_addr
...
.long   .debug_info+86                  # DW_AT_abstract_origin

The 86 was precomputed, but could come from a local label difference.

The CU-local reference uses teh constant value, but could use a label offset:

.byte   49                              # DW_AT_abstract_origin
.byte   19                              # DW_FORM_ref4
...
.long   86                              # DW_AT_abstract_origin

>
> Thank you and Michael for the input.
>
> >> Using global labels inside these structures though, may
> >> lead to all kinds of troubles, for example when a linker regards these
> >> labels as the start of a new section. Or on Darwin/macOS. Calculating
> >> the location of these tags is in principle possible I think, but
> >> difficult. Any tips here?
> >>
> >> This is a dwarfdump of the class-definition above with my current additions:
> >>
> >> < 1><0x00000123>    DW_TAG_class_type
> >>                         DW_AT_name                  TMyClass
> >>                         DW_AT_byte_size             0x00000010
> >> < 2><0x0000012e>      DW_TAG_inheritance
> >>                           DW_AT_accessibility         DW_ACCESS_public
> >>                           DW_AT_data_member_location  DW_OP_plus_uconst 0
> >>                           DW_AT_type                  <GOFF=0x00005122>
> >> < 2><0x00000137>      DW_TAG_member
> >>                           DW_AT_name                  FProp
> >>                           DW_AT_data_member_location  DW_OP_plus_uconst 8
> >>                           DW_AT_accessibility         DW_ACCESS_private
> >>                           DW_AT_type                  <GOFF=0x000000f3>
> >> < 2><0x00000146>      DW_TAG_member
> >>                           DW_AT_name                  FPropIsStored
> >>                           DW_AT_data_member_location  DW_OP_plus_uconst 12
> >>                           DW_AT_accessibility         DW_ACCESS_private
> >>                           DW_AT_type                  <GOFF=0x000057a7>
> >> < 2><0x0000015d>      <Unknown TAG value 0x4230>
> >>                           DW_AT_name                  IndividualItem
> >>                           <Unknown AT value 0x3230>   <GOFF=0x0000020c>
> >>                           DW_AT_type                  <GOFF=0x000057c4>
> >> < 2><0x00000175>      <Unknown TAG value 0x4230>
> >>                           DW_AT_name                  Prop
> >>                           <Unknown AT value 0x3230>   <GOFF=0x000001ad>
> >>                           <Unknown AT value 0x3232>   <GOFF=0x00000146>
> >>                           DW_AT_type                  <GOFF=0x000000f3>
> >> < 2><0x00000187>      <Unknown TAG value 0x4230>
> >>                           DW_AT_name                  OtherProp
> >>                           <Unknown AT value 0x3230>   <GOFF=0x00000137>
> >>                           <Unknown AT value 0x3231>   <GOFF=0x00000137>
> >>                           DW_AT_type                  <GOFF=0x000000f3>
> >> < 2><0x0000019e>      <Unknown TAG value 0x4230>
> >>                           DW_AT_name                  Item2
> >>                           <Unknown AT value 0x3230>   <GOFF=0x0000020c>
> >>                           DW_AT_type                  <GOFF=0x000057c4>
> >> < 2><0x000001ad>      DW_TAG_subprogram
> >>                           DW_AT_name                  GetProp
> >>                           DW_AT_prototyped            yes(1)
> >>                           DW_AT_calling_convention
> >> DW_CC_GNU_borland_fastcall_i386
> >>                           DW_AT_external              yes(1)
> >>                           DW_AT_accessibility         DW_ACCESS_protected
> >>                           DW_AT_type                  <GOFF=0x000000f3>
> >>                           DW_AT_low_pc                0x00404840
> >>                           DW_AT_high_pc               0x00404867
> >> < 3><0x000001ce>        DW_TAG_formal_parameter
> >>                             DW_AT_name                  this
> >>                             DW_AT_location              0x7678 DW_OP_breg6-8
> >>                             DW_AT_artificial            yes(1)
> >>                             DW_AT_type                  <GOFF=0x00000110>
> >> < 3><0x000001dc>        DW_TAG_variable
> >>                             DW_AT_name                  $result
> >>                             DW_AT_location              0x7674 DW_OP_breg6-12
> >>                             DW_AT_type                  <GOFF=0x000000f3>
> >> < 3><0x000001ec>        DW_TAG_variable
> >>                             DW_AT_name                  GETPROP
> >>                             DW_AT_location              0x7674 DW_OP_breg6-12
> >>                             DW_AT_type                  <GOFF=0x000000f3>
> >> < 3><0x000001fc>        DW_TAG_variable
> >>                             DW_AT_name                  RESULT
> >>                             DW_AT_location              0x7674 DW_OP_breg6-12
> >>                             DW_AT_type                  <GOFF=0x000000f3>
> >> < 2><0x0000020c>      DW_TAG_subprogram
> >>                           DW_AT_name                  GetItem
> >>                           DW_AT_prototyped            yes(1)
> >>                           DW_AT_calling_convention
> >> DW_CC_GNU_borland_fastcall_i386
> >>                           DW_AT_external              yes(1)
> >>                           DW_AT_accessibility         DW_ACCESS_protected
> >>                           DW_AT_type                  <GOFF=0x000057c4>
> >>                           DW_AT_low_pc                0x00404870
> >>                           DW_AT_high_pc               0x00404889
> >> < 3><0x0000022d>        DW_TAG_formal_parameter
> >>                             DW_AT_name                  this
> >>                             DW_AT_location              0x7670 DW_OP_breg6-16
> >>                             DW_AT_artificial            yes(1)
> >>                             DW_AT_type                  <GOFF=0x00000110>
> >> < 3><0x0000023b>        DW_TAG_variable
> >>                             DW_AT_name                  $result
> >>                             DW_AT_location              0x766806
> >> DW_OP_breg6-24 DW_OP_deref
> >>                             DW_AT_type                  <GOFF=0x000057c4>
> >> < 3><0x0000024c>        DW_TAG_formal_parameter
> >>                             DW_AT_name                  Index
> >>                             DW_AT_location              0x7678 DW_OP_breg6-8
> >>                             DW_AT_type                  <GOFF=0x000000f3>
> >> < 3><0x0000025a>        DW_TAG_variable
> >>                             DW_AT_name                  GETITEM
> >>                             DW_AT_location              0x766806
> >> DW_OP_breg6-24 DW_OP_deref
> >>                             DW_AT_type                  <GOFF=0x000057c4>
> >> < 3><0x0000026b>        DW_TAG_variable
> >>                             DW_AT_name                  RESULT
> >>                             DW_AT_location              0x766806
> >> DW_OP_breg6-24 DW_OP_deref
> >>                             DW_AT_type                  <GOFF=0x000057c4>
> >>
> >>
> >>
> >> _______________________________________________
> >> Dwarf-Discuss mailing list
> >> Dwarf-Discuss at lists.dwarfstd.org
> >> http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
> > _______________________________________________
> > Dwarf-Discuss mailing list
> > Dwarf-Discuss at lists.dwarfstd.org
> > http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
> >
> _______________________________________________
> 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