Hi Omar,

On Wed, Sep 27, 2023 at 11:21:02AM -0700, Omar Sandoval wrote:
> The final piece of DWARF package file support is that offsets have to be
> interpreted relative to the section offset from the package index.
> .debug_abbrev.dwo is already covered, so sprinkle around calls to
> dwarf_cu_dwp_section_info for the remaining sections: .debug_line.dwo,
> .debug_loclists.dwo/.debug_loc.dwo, .debug_str_offsets.dwo,
> .debug_macro.dwo/.debug_macinfo.dwo, and .debug_rnglists.dwo.  With all
> of that in place, we can finally test various libdw functions on dwp
> files.

This looks good, but obviously needs some earlier patches.

> diff --git a/libdw/ChangeLog b/libdw/ChangeLog
> index f37d9411..08b2c3e6 100644
> --- a/libdw/ChangeLog
> +++ b/libdw/ChangeLog
> @@ -12,10 +12,13 @@
>       * dwarf_getmacros.c (get_macinfo_table): Replace assignment of
>       table->is_64bit with assignments of table->address_size and
>       table->offset_size.  Assume default DW_AT_stmt_list of 0 for split
> -     DWARF.  Set table->dbg.
> +     DWARF.  Set table->dbg.  Call dwarf_cu_dwp_section_info and add offset
> +     to line_offset.
>       (get_table_for_offset): Ditto.
>       (read_macros): Get fake CU offset_size from table->offset_size instead
>       of table->is_64bit.
> +     (get_offset_from): Call dwarf_cu_dwp_section_info and add offset to
> +     *retp.
>       * dwarf_macro_getsrcfiles.c (dwarf_macro_getsrcfiles): Get
>       address_size for __libdw_getsrclines from table->address_size instead
>       of table->is_64bit.  Get dbg for __libdw_getsrclines from table->dbg
> @@ -36,6 +39,9 @@
>       (__libdw_set_debugdir): New declaration.
>       (__libdw_dwp_findcu_id): New declaration.
>       (__libdw_link_skel_split): Handle .debug_addr for dwp.
> +     (str_offsets_base_off): Call dwarf_cu_dwp_section_info and add offset.
> +     (__libdw_cu_ranges_base): Ditto.
> +     (__libdw_cu_locs_base): Ditto.
>       * dwarf_begin_elf.c (dwarf_scnnames): Add IDX_debug_cu_index and
>       IDX_debug_tu_index.
>       (scn_to_string_section_idx): Ditto.
> @@ -60,6 +66,8 @@
>       __libdw_dwp_find_unit, and use it to adjust abbrev_offset and assign
>       newp->dwp_row.
>       * dwarf_cu_dwp_section_info.c: New file.
> +     * dwarf_getlocation.c (initial_offset): Call dwarf_cu_dwp_section_info
> +     and add offset to start_offset.
>  
>  2023-02-22  Mark Wielaard  <m...@klomp.org>
>  
> diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
> index 553fdc98..37b32fc1 100644
> --- a/libdw/dwarf_getlocation.c
> +++ b/libdw/dwarf_getlocation.c
> @@ -812,6 +812,12 @@ initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset)
>                           : DWARF_E_NO_DEBUG_LOCLISTS),
>                           NULL, &start_offset) == NULL)
>       return -1;
> +
> +      Dwarf_Off loc_off;
> +      if (INTUSE(dwarf_cu_dwp_section_info) (attr->cu, DW_SECT_LOCLISTS,
> +                                          &loc_off, NULL) != 0)
> +     return -1;
> +      start_offset += loc_off;
>      }
>  
>    *offset = start_offset;

OK. This already handled DW_FORM_loclistx, now also other loclist
refs.

> diff --git a/libdw/dwarf_getmacros.c b/libdw/dwarf_getmacros.c
> index a3a78884..2667eb45 100644
> --- a/libdw/dwarf_getmacros.c
> +++ b/libdw/dwarf_getmacros.c
> @@ -47,7 +47,15 @@ get_offset_from (Dwarf_Die *die, int name, Dwarf_Word 
> *retp)
>      return -1;
>  
>    /* Offset into the corresponding section.  */
> -  return INTUSE(dwarf_formudata) (&attr, retp);
> +  if (INTUSE(dwarf_formudata) (&attr, retp) != 0)
> +    return -1;
> +
> +  Dwarf_Off offset;
> +  if (INTUSE(dwarf_cu_dwp_section_info) (die->cu, DW_SECT_MACRO, &offset, 
> NULL)
> +      != 0)
> +    return -1;
> +  *retp += offset;
> +  return 0;
>  }

OK.

>  static int
> @@ -131,6 +139,14 @@ get_macinfo_table (Dwarf *dbg, Dwarf_Word macoff, 
> Dwarf_Die *cudie)
>    else if (cudie->cu->unit_type == DW_UT_split_compile
>          && dbg->sectiondata[IDX_debug_line] != NULL)
>      line_offset = 0;
> +  if (line_offset != (Dwarf_Off) -1)
> +    {
> +      Dwarf_Off dwp_offset;
> +      if (INTUSE(dwarf_cu_dwp_section_info) (cudie->cu, DW_SECT_LINE,
> +                                          &dwp_offset, NULL) != 0)
> +     return NULL;
> +      line_offset += dwp_offset;
> +    }

OK.
 
>    Dwarf_Macro_Op_Table *table = libdw_alloc (dbg, Dwarf_Macro_Op_Table,
>                                            macinfo_data_size, 1);
> @@ -188,6 +204,14 @@ get_table_for_offset (Dwarf *dbg, Dwarf_Word macoff,
>       if (unlikely (INTUSE(dwarf_formudata) (attr, &line_offset) != 0))
>         return NULL;
>      }
> +  if (line_offset != (Dwarf_Off) -1 && cudie != NULL)
> +    {
> +      Dwarf_Off dwp_offset;
> +      if (INTUSE(dwarf_cu_dwp_section_info) (cudie->cu, DW_SECT_LINE,
> +                                          &dwp_offset, NULL) != 0)
> +     return NULL;
> +      line_offset += dwp_offset;
> +    }
>  
>    uint8_t address_size;
>    if (cudie != NULL)

OK.

> diff --git a/libdw/libdwP.h b/libdw/libdwP.h
> index 16355274..bdbf5e5a 100644
> --- a/libdw/libdwP.h
> +++ b/libdw/libdwP.h
> @@ -1111,25 +1111,27 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
>       cu = first_cu;
>      }
>  
> +  Dwarf_Off off = 0;
>    if (cu != NULL)
>      {
>        if (cu->str_off_base == (Dwarf_Off) -1)
>       {
> +       dwarf_cu_dwp_section_info (cu, DW_SECT_STR_OFFSETS, &off, NULL);
>         Dwarf_Die cu_die = CUDIE(cu);
>         Dwarf_Attribute attr;
>         if (dwarf_attr (&cu_die, DW_AT_str_offsets_base, &attr) != NULL)
>           {
> -           Dwarf_Word off;
> -           if (dwarf_formudata (&attr, &off) == 0)
> +           Dwarf_Word base;
> +           if (dwarf_formudata (&attr, &base) == 0)
>               {
> -               cu->str_off_base = off;
> +               cu->str_off_base = off + base;
>                 return cu->str_off_base;
>               }
>           }
>         /* For older DWARF simply assume zero (no header).  */
>         if (cu->version < 5)
>           {
> -           cu->str_off_base = 0;
> +           cu->str_off_base = off;
>             return cu->str_off_base;
>           }
>  
> @@ -1142,7 +1144,6 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
>  
>    /* No str_offsets_base attribute, we have to assume "zero".
>       But there could be a header first.  */
> -  Dwarf_Off off = 0;
>    if (dbg == NULL)
>      goto no_header;
>  
> @@ -1184,7 +1185,7 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
>    /* padding */
>    read_2ubyte_unaligned_inc (dbg, readp);
>  
> -  off = (Dwarf_Off) (readp - start);
> +  off += (Dwarf_Off) (readp - start);
>  
>   no_header:
>    if (cu != NULL)


OK, so the dwp section offset gets added to the base attribute offset.

> @@ -1222,18 +1223,22 @@ __libdw_cu_ranges_base (Dwarf_CU *cu)
>       }
>        else
>       {
> +       Dwarf_Off dwp_offset = 0;
> +       dwarf_cu_dwp_section_info (cu, DW_SECT_RNGLISTS, &dwp_offset, NULL);

Shouldn't we check there wasn't an error?

> +       offset = dwp_offset;
> +
>         if (dwarf_attr (&cu_die, DW_AT_rnglists_base, &attr) != NULL)
>           {
>             Dwarf_Word off;
>             if (dwarf_formudata (&attr, &off) == 0)
> -             offset = off;
> +             offset += off;
>           }
>  
>         /* There wasn't an rnglists_base, if the Dwarf does have a
>            .debug_rnglists section, then it might be we need the
>            base after the first header. */
>         Elf_Data *data = cu->dbg->sectiondata[IDX_debug_rnglists];
> -       if (offset == 0 && data != NULL)
> +       if (offset == dwp_offset && data != NULL)
>           {
>             Dwarf *dbg = cu->dbg;
>             const unsigned char *readp = data->d_buf;
> @@ -1279,8 +1284,8 @@ __libdw_cu_ranges_base (Dwarf_CU *cu)
>             if (unit_length - 8 < needed)
>               goto no_header;
>  
> -           offset = (Dwarf_Off) (offset_array_start
> -                                 - (unsigned char *) data->d_buf);
> +           offset += (Dwarf_Off) (offset_array_start
> +                                  - (unsigned char *) data->d_buf);
>           }
>       }
>      no_header:

OK, same for ranges.

> @@ -1297,21 +1302,24 @@ __libdw_cu_locs_base (Dwarf_CU *cu)
>  {
>    if (cu->locs_base == (Dwarf_Off) -1)
>      {
> -      Dwarf_Off offset = 0;
> +      Dwarf_Off dwp_offset = 0;
> +      dwarf_cu_dwp_section_info (cu, DW_SECT_LOCLISTS, &dwp_offset, NULL);

No error check?

> +      Dwarf_Off offset = dwp_offset;
> +
>        Dwarf_Die cu_die = CUDIE(cu);
>        Dwarf_Attribute attr;
>        if (dwarf_attr (&cu_die, DW_AT_loclists_base, &attr) != NULL)
>       {
>         Dwarf_Word off;
>         if (dwarf_formudata (&attr, &off) == 0)
> -         offset = off;
> +         offset += off;
>       }
>  
>        /* There wasn't an loclists_base, if the Dwarf does have a
>        .debug_loclists section, then it might be we need the
>        base after the first header. */
>        Elf_Data *data = cu->dbg->sectiondata[IDX_debug_loclists];
> -      if (offset == 0 && data != NULL)
> +      if (offset == dwp_offset && data != NULL)
>       {
>         Dwarf *dbg = cu->dbg;
>         const unsigned char *readp = data->d_buf;
> @@ -1357,8 +1365,8 @@ __libdw_cu_locs_base (Dwarf_CU *cu)
>         if (unit_length - 8 < needed)
>           goto no_header;
>  
> -       offset = (Dwarf_Off) (offset_array_start
> -                             - (unsigned char *) data->d_buf);
> +       offset += (Dwarf_Off) (offset_array_start
> +                              - (unsigned char *) data->d_buf);
>       }
>  
>      no_header:

OK. Same for loclists.

> diff --git a/tests/ChangeLog b/tests/ChangeLog
> index 97261444..93503f57 100644
> --- a/tests/ChangeLog
> +++ b/tests/ChangeLog
> @@ -1,6 +1,7 @@
>  2023-09-27  Omar Sandoval  <osan...@fb.com>
>  
> -     * run-varlocs.sh: Add entry PC to split units.
> +     * run-varlocs.sh: Add entry PC to split units.  Check testfile-dwp-5
> +     and testfile-dwp-4.
>       * Makefile.am (check_PROGRAMS): Add cu-dwp-section-info.
>       (TESTS): Add run-cu-dwp-section-info.sh
>       (EXTRA_DIST): Add run-cu-dwp-section-info.sh and new test files.
> @@ -20,6 +21,11 @@
>       (getmacros): New function.
>       (main): If second argument is empty, call getmacros on every unit.
>       Otherwise, call getmacros on given unit.
> +     * run-all-dwarf-ranges.sh: Check testfile-dwp-5 and testfile-dwp-4.
> +     * run-dwarf-getmacros.sh: Check testfile-dwp-5 and
> +     testfile-dwp-4-strict.
> +     * run-get-units-split.sh: Check testfile-dwp-5, testfile-dwp-4, and
> +     testfile-dwp-4-strict.

Nice collection of tests.

Thanks,

Mark

Reply via email to