Hi Sasha,

On Thu, 2020-11-05 at 22:15 +0000, Sasha Da Rocha Pinheiro via
Elfutils-devel wrote:
> In libdw.h it says: /* The offset can be computed from the address.
>  */
> How do I get the CU DIE offset from the address? Only saving the
> first CU and subtracting it on the others to get the offset?

Yeah, that comment is correct, but not really that helpful. There are
two offsets that might matter. The start of Dwarf (.debug_info) offset
and the start of the Dwarf_CU offset. But getting either by hand is
some work since it depends on the size of the CU header, which can be
different based on the version and type of CU. You can get the
header_size when iterating through the CUs with dwarf_nextcu or
dwarf_next_unit but it is not easily available otherwise.

But given a Dwarf_Die you can get the offsets through dwarf_dieoffset
and dwarf_cuoffset.

Also note that since 0.178 there is dwarf_die_addr_die, which simply
takes the (main) Dwarf object and a Dwarf_Die addr.

/* Given a Dwarf_Die addr returns a (reconstructed) Dwarf_Die, or NULL
   if the given addr didn't come from a valid Dwarf_Die.  In particular
   it will make sure that the correct Dwarf_CU pointer is set for the
   Dwarf_Die, the Dwarf_Abbrev pointer will not be set up yet (it will
   only be once the Dwarf_Die is used to read attributes, children or
   siblings).  This functions can be used to keep a reference to a
   Dwarf_Die which you want to refer to later.  The addr, and the result
   of this function, is only valid while the associated Dwarf is valid.  */

Although the comment doesn't explicitly say so, this also works for
DIEs from the associated alt or split Dwarf objects associated with the
given Dwarf.

> When we go through the .debug_info using dwarf_nextcu, we are getting
> partial units too. How should we deal with them? If they're not
> actually CU, should they not be returned and only used internally by
> libdw in order to 'complete' the other CUs?

You should probably simply skip them because they will ultimately be
imported into a "real" compile unit. Note that there also is
dwarf_get_units () which will directly give you the unit_type
(DW_UT_compile, DW_UT_type or DW_UT_partial) so you can easily skipe
any you are not interested in.

> It seems that libdw is automatically searching and loading the
> supplemental dwz file. Given the following:
> 
> ** file .debug **
> <1><f0d>: Abbrev Number: 37 (DW_TAG_subprogram)
>     <f0e>   DW_AT_abstract_origin: <alt 0x5112>
>     <f12>   DW_AT_low_pc      : 0x8650
>     <f1a>   DW_AT_high_pc     : 229
>     <f1c>   DW_AT_frame_base  : 1 byte block: 9c      
>  (DW_OP_call_frame_cfa)
>     <f1e>   DW_AT_GNU_all_call_sites: 1
>     <f1e>   DW_AT_sibling     : <0x107b>
> ...
>  <4><5112>: Abbrev Number: 0
> 
> ** file dwz **
> <1><5112>: Abbrev Number: 81 (DW_TAG_subprogram)
>     <5113>   DW_AT_external    : 1
>     <5113>   DW_AT_name        : (indirect string, offset: 0x9852):
> iscsi_tcp_free_pdu
>     <5117>   DW_AT_decl_file   : 51
>     <5118>   DW_AT_decl_line   : 142
>     <5119>   DW_AT_decl_column : 1
>     <511a>   DW_AT_prototyped  : 1
>     <511a>   DW_AT_sibling     : <0x5135>
> 
> When I'm parsing f0d, libdw automatically fetches the abstract origin
> on the dwz file. But when we try to parse the abstract origin on our
> own it gives us the one in the same file, which is 0. Is it because
> we should look into the form of the DW_AT_abstract_origin? In this
> case seems to be the GNU_ref_alt, correct?

Yes, if the form is DW_FORM_GNU_ref_alt (or DW_FORM_ref_sup4 or
DW_FORM_ref_sup8 in DWARF5) then the "raw offset" is against the alt
file (which you can get with dwarf_getalt).

But I would recommend you simply use dwarf_formref_die to get the
Dwarf_Die since that has all the logic already to resolve the DIE
whether it is a "global" offset, a CU-relative offset, an alt-reference 
or a type signature.

Cheers,

Mark

Reply via email to