[v3,4/4] libdw: Handle overflowed DW_SECT_INFO offsets in DWARF package file indexes

Message ID de329ffa627bb8d50176d275f8938a51597fd938.1708974560.git.osandov@fb.com
State Committed
Headers
Series elfutils: DWARF package (.dwp) file support |

Commit Message

Omar Sandoval Feb. 26, 2024, 7:32 p.m. UTC
  From: Omar Sandoval <osandov@fb.com>

Meta uses DWARF package files for our large, statically-linked C++
applications.  Some of our largest applications have more than 4GB in
.debug_info.dwo, but the section offsets in .debug_cu_index and
.debug_tu_index are 32 bits; see the discussion here [1].  We
implemented a workaround/extension for this in LLVM.  Implement the
equivalent in libdw.

To test this, we need files with more than 4GB in .debug_info.dwo.  I
created these artificially by editing GCC's assembly output.  They
compress down to 6KB.  I test them from run-large-elf-file.sh to take
advantage of the existing checks for large file support.

1: https://discourse.llvm.org/t/dwarf-dwp-4gb-limit/63902.

 	* libdw/dwarf_end.c (dwarf_package_index_free): New function.
	* tests/testfile-dwp-4-cu-index-overflow.bz2: New test file.
	* tests/testfile-dwp-4-cu-index-overflow.dwp.bz2: New test file.
	* tests/testfile-dwp-5-cu-index-overflow.bz2: New test file.
	* tests/testfile-dwp-5-cu-index-overflow.dwp.bz2: New test file.
	* tests/testfile-dwp-cu-index-overflow.source: New file.
	* tests/run-large-elf-file.sh: Check
	testfile-dwp-5-cu-index-overflow and
	testfile-dwp-4-cu-index-overflow.

Signed-off-by: Omar Sandoval <osandov@fb.com>
---
 libdw/dwarf_cu_dwp_section_info.c             | 147 ++++++++++++++-
 libdw/dwarf_end.c                             |  15 +-
 libdw/libdwP.h                                |   3 +
 tests/Makefile.am                             |   7 +-
 tests/run-large-elf-file.sh                   | 174 ++++++++++++++++++
 tests/testfile-dwp-4-cu-index-overflow.bz2    | Bin 0 -> 4490 bytes
 .../testfile-dwp-4-cu-index-overflow.dwp.bz2  | Bin 0 -> 5584 bytes
 tests/testfile-dwp-5-cu-index-overflow.bz2    | Bin 0 -> 4544 bytes
 .../testfile-dwp-5-cu-index-overflow.dwp.bz2  | Bin 0 -> 5790 bytes
 tests/testfile-dwp-cu-index-overflow.source   |  86 +++++++++
 10 files changed, 426 insertions(+), 6 deletions(-)
 create mode 100755 tests/testfile-dwp-4-cu-index-overflow.bz2
 create mode 100644 tests/testfile-dwp-4-cu-index-overflow.dwp.bz2
 create mode 100755 tests/testfile-dwp-5-cu-index-overflow.bz2
 create mode 100644 tests/testfile-dwp-5-cu-index-overflow.dwp.bz2
 create mode 100644 tests/testfile-dwp-cu-index-overflow.source

new file mode 100644
index 0000000000000000000000000000000000000000..0718c1b2c40310655cdb78ae9859b7b682a5fcaf
GIT binary patch
literal 5584
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
Pwxd_;8J$6MsC@D-pOqt+

literal 0
HcmV?d00001

new file mode 100644
index 0000000000000000000000000000000000000000..dce34e3f51d637e4773c3c8e4ebeb4666b4c0571
GIT binary patch
literal 5790
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
ZQVs!Wj1ebEH_TeZF<rUYrnf)Q{|jo{jkEv&

literal 0
HcmV?d00001
  

Comments

Mark Wielaard March 1, 2024, 2:59 p.m. UTC | #1
Hi Omar,

On Mon, 2024-02-26 at 11:32 -0800, Omar Sandoval wrote:
> Meta uses DWARF package files for our large, statically-linked C++
> applications.  Some of our largest applications have more than 4GB in
> .debug_info.dwo, but the section offsets in .debug_cu_index and
> .debug_tu_index are 32 bits; see the discussion here [1].  We
> implemented a workaround/extension for this in LLVM.  Implement the
> equivalent in libdw.
> 
> To test this, we need files with more than 4GB in .debug_info.dwo.  I
> created these artificially by editing GCC's assembly output.  They
> compress down to 6KB.  I test them from run-large-elf-file.sh to take
> advantage of the existing checks for large file support.
> 
> 1: https://discourse.llvm.org/t/dwarf-dwp-4gb-limit/63902.
> 
>  	* libdw/dwarf_end.c (dwarf_package_index_free): New function.
> 	* tests/testfile-dwp-4-cu-index-overflow.bz2: New test file.
> 	* tests/testfile-dwp-4-cu-index-overflow.dwp.bz2: New test file.
> 	* tests/testfile-dwp-5-cu-index-overflow.bz2: New test file.
> 	* tests/testfile-dwp-5-cu-index-overflow.dwp.bz2: New test file.
> 	* tests/testfile-dwp-cu-index-overflow.source: New file.
> 	* tests/run-large-elf-file.sh: Check
> 	testfile-dwp-5-cu-index-overflow and
> 	testfile-dwp-4-cu-index-overflow.

The hack is kind of horrible, but given that this doesn't really
impacts "normal" dwp files and it does work with clang/lldb, lets just
support it too.

> Signed-off-by: Omar Sandoval <osandov@fb.com>
> ---
>  libdw/dwarf_cu_dwp_section_info.c             | 147 ++++++++++++++-
>  libdw/dwarf_end.c                             |  15 +-
>  libdw/libdwP.h                                |   3 +
>  tests/Makefile.am                             |   7 +-
>  tests/run-large-elf-file.sh                   | 174 ++++++++++++++++++
>  tests/testfile-dwp-4-cu-index-overflow.bz2    | Bin 0 -> 4490 bytes
>  .../testfile-dwp-4-cu-index-overflow.dwp.bz2  | Bin 0 -> 5584 bytes
>  tests/testfile-dwp-5-cu-index-overflow.bz2    | Bin 0 -> 4544 bytes
>  .../testfile-dwp-5-cu-index-overflow.dwp.bz2  | Bin 0 -> 5790 bytes
>  tests/testfile-dwp-cu-index-overflow.source   |  86 +++++++++
>  10 files changed, 426 insertions(+), 6 deletions(-)
>  create mode 100755 tests/testfile-dwp-4-cu-index-overflow.bz2
>  create mode 100644 tests/testfile-dwp-4-cu-index-overflow.dwp.bz2
>  create mode 100755 tests/testfile-dwp-5-cu-index-overflow.bz2
>  create mode 100644 tests/testfile-dwp-5-cu-index-overflow.dwp.bz2
>  create mode 100644 tests/testfile-dwp-cu-index-overflow.source
> 
> diff --git a/libdw/dwarf_cu_dwp_section_info.c b/libdw/dwarf_cu_dwp_section_info.c
> index 298f36f9..3d11c87a 100644
> --- a/libdw/dwarf_cu_dwp_section_info.c
> +++ b/libdw/dwarf_cu_dwp_section_info.c
> @@ -30,6 +30,8 @@
>  # include <config.h>
>  #endif
>  
> +#include <assert.h>
> +
>  #include "libdwP.h"
>  
>  static Dwarf_Package_Index *
> @@ -110,7 +112,9 @@ __libdw_read_package_index (Dwarf *dbg, bool tu)
>  
>    index->dbg = dbg;
>    /* Set absent sections to UINT32_MAX.  */
> -  memset (index->sections, 0xff, sizeof (index->sections));
> +  for (size_t i = 0;
> +       i < sizeof (index->sections) / sizeof (index->sections[0]); i++)
> +    index->sections[i] = UINT32_MAX;
>    for (size_t i = 0; i < section_count; i++)
>      {
>        uint32_t section = read_4ubyte_unaligned (dbg, sections + i * 4);
> @@ -161,6 +165,7 @@ __libdw_read_package_index (Dwarf *dbg, bool tu)
>    index->indices = indices;
>    index->section_offsets = section_offsets;
>    index->section_sizes = section_sizes;
> +  index->debug_info_offsets = NULL;
>  
>    return index;
>  }
> @@ -177,6 +182,137 @@ __libdw_package_index (Dwarf *dbg, bool tu)
>    if (index == NULL)
>      return NULL;
>  
> +  /* Offsets in the section offset table are 32-bit unsigned integers.  In
> +     practice, the .debug_info.dwo section for very large executables can be
> +     larger than 4GB.  GNU dwp as of binutils 2.41 and llvm-dwp before LLVM 15
> +     both accidentally truncate offsets larger than 4GB.
> +
> +     LLVM 15 detects the overflow and errors out instead; see LLVM commit
> +     f8df8114715b ("[DWP][DWARF] Detect and error on debug info offset
> +     overflow").  However, lldb in LLVM 16 supports using dwp files with
> +     truncated offsets by recovering them directly from the unit headers in the
> +     .debug_info.dwo section; see LLVM commit c0db06227721 ("[DWARFLibrary] Add
> +     support to re-construct cu-index").  Since LLVM 17, the overflow error can
> +     be turned into a warning instead; see LLVM commit 53a483cee801 ("[DWP] add
> +     overflow check for llvm-dwp tools if offset overflow").
> +
> +     LLVM's support for > 4GB offsets is effectively an extension to the DWARF
> +     package file format, which we implement here.  The strategy is to walk the
> +     unit headers in .debug_info.dwo in lockstep with the DW_SECT_INFO columns
> +     in the section offset tables.  As long as they are in the same order
> +     (which they are in practice for both GNU dwp and llvm-dwp), we can
> +     correlate the truncated offset and produce a corrected array of offsets.
> +
> +     Note that this will be fixed properly in DWARF 6:
> +     https://dwarfstd.org/issues/220708.2.html.  */
> +  if (index->sections[DW_SECT_INFO - 1] != UINT32_MAX
> +      && dbg->sectiondata[IDX_debug_info]->d_size > UINT32_MAX)
> +    {
> +      Dwarf_Package_Index *cu_index, *tu_index = NULL;
> +      if (tu)
> +	{
> +	  tu_index = index;
> +	  assert (dbg->cu_index == NULL);
> +	  cu_index = __libdw_read_package_index (dbg, false);
> +	  if (cu_index == NULL)
> +	    {
> +	      free(index);
> +	      return NULL;
> +	    }
> +	}
> +      else
> +	{
> +	  cu_index = index;
> +	  if (dbg->sectiondata[IDX_debug_tu_index] != NULL
> +	      && dbg->sectiondata[IDX_debug_types] == NULL)
> +	    {
> +	      assert (dbg->tu_index == NULL);
> +	      tu_index = __libdw_read_package_index (dbg, true);
> +	      if (tu_index == NULL)
> +		{
> +		  free(index);
> +		  return NULL;
> +		}
> +	    }
> +	}
> +
> +      cu_index->debug_info_offsets = malloc (cu_index->unit_count
> +					     * sizeof (Dwarf_Off));
> +      if (cu_index->debug_info_offsets == NULL)
> +	{
> +	  free (tu_index);
> +	  free (cu_index);
> +	  __libdw_seterrno (DWARF_E_NOMEM);
> +	  return NULL;
> +	}
> +      if (tu_index != NULL)
> +	{
> +	  tu_index->debug_info_offsets = malloc (tu_index->unit_count
> +						 * sizeof (Dwarf_Off));
> +	  if (tu_index->debug_info_offsets == NULL)
> +	    {
> +	      free (tu_index);
> +	      free (cu_index->debug_info_offsets);
> +	      free (cu_index);
> +	      __libdw_seterrno (DWARF_E_NOMEM);
> +	      return NULL;
> +	    }
> +	}
> +
> +      Dwarf_Off off = 0;
> +      uint32_t cui = 0, tui = 0;
> +      uint32_t cu_count = cu_index->unit_count;
> +      const unsigned char *cu_offset
> +	= cu_index->section_offsets + cu_index->sections[DW_SECT_INFO - 1] * 4;
> +      uint32_t tu_count = 0;
> +      const unsigned char *tu_offset;
> +      if (tu_index != NULL)
> +	{
> +	  tu_count = tu_index->unit_count;
> +	  tu_offset = tu_index->section_offsets
> +		      + tu_index->sections[DW_SECT_INFO - 1] * 4;
> +	}
> +      while (cui < cu_count || tui < tu_count)
> +	{
> +	  Dwarf_Off next_off;
> +	  uint8_t unit_type;
> +	  if (__libdw_next_unit (dbg, false, off, &next_off, NULL, NULL,
> +				 &unit_type, NULL, NULL, NULL, NULL, NULL)
> +	      != 0)
> +	    {
> +	    not_sorted:
> +	      free (cu_index->debug_info_offsets);
> +	      cu_index->debug_info_offsets = NULL;
> +	      if (tu_index != NULL)
> +		{
> +		  free (tu_index->debug_info_offsets);
> +		  tu_index->debug_info_offsets = NULL;
> +		}
> +	      break;
> +	    }
> +	  if (unit_type != DW_UT_split_type && cui < cu_count)
> +	    {
> +	      if ((off & UINT32_MAX) != read_4ubyte_unaligned (dbg, cu_offset))
> +		goto not_sorted;
> +	      cu_index->debug_info_offsets[cui++] = off;
> +	      cu_offset += cu_index->section_count * 4;
> +	    }
> +	  else if (unit_type == DW_UT_split_type && tui < tu_count)
> +	    {
> +	      if ((off & UINT32_MAX) != read_4ubyte_unaligned (dbg, tu_offset))
> +		goto not_sorted;
> +	      tu_index->debug_info_offsets[tui++] = off;
> +	      tu_offset += tu_index->section_count * 4;
> +	    }
> +	  off = next_off;
> +	}
> +
> +      if (tu)
> +	dbg->cu_index = cu_index;
> +      else if (tu_index != NULL)
> +	dbg->tu_index = tu_index;
> +    }
> +
>    if (tu)
>      dbg->tu_index = index;
>    else

This looks correct, but gcc noticed a path to use tu_offset (and
tu_index) if they weren't initialized or NULL:

In file included from /home/mark/src/elfutils/libdw/libdwP.h:684,
                 from /home/mark/src/elfutils/libdw/dwarf_cu_dwp_section_info.c:35:
In function ‘read_4ubyte_unaligned_1’,
    inlined from ‘__libdw_package_index’ at /home/mark/src/elfutils/libdw/dwarf_cu_dwp_section_info.c:302:34:
/home/mark/src/elfutils/libdw/memory-access.h:291:12: error: ‘tu_offset’ may be used uninitialized [-Werror=maybe-uninitialized]
  291 |   return up->u4;
      |          ~~^~~~
/home/mark/src/elfutils/libdw/dwarf_cu_dwp_section_info.c: In function ‘__libdw_package_index’:
/home/mark/src/elfutils/libdw/dwarf_cu_dwp_section_info.c:268:28: note: ‘tu_offset’ was declared here
  268 |       const unsigned char *tu_offset;
      |                            ^~~~~~~~~
cc1: all warnings being treated as errors

I couldn't immediately disprove gcc here, so I think it is a good idea
to add an explicit check for tu_index != NULL.

diff --git a/libdw/dwarf_cu_dwp_section_info.c b/libdw/dwarf_cu_dwp_section_info.c
index 3d11c87a..9fdc15bf 100644
--- a/libdw/dwarf_cu_dwp_section_info.c
+++ b/libdw/dwarf_cu_dwp_section_info.c
@@ -297,7 +297,8 @@ __libdw_package_index (Dwarf *dbg, bool tu)
              cu_index->debug_info_offsets[cui++] = off;
              cu_offset += cu_index->section_count * 4;
            }
-         else if (unit_type == DW_UT_split_type && tui < tu_count)
+         else if (unit_type == DW_UT_split_type && tu_index != NULL
+                  && tui < tu_count)
            {
              if ((off & UINT32_MAX) != read_4ubyte_unaligned (dbg, tu_offset))
                goto not_sorted;

Which makes gcc happy again.

> @@ -244,8 +380,13 @@ __libdw_dwp_section_info (Dwarf_Package_Index *index, uint32_t unit_row,
>    size_t i = (size_t)(unit_row - 1) * index->section_count
>  	     + index->sections[section - 1];
>    if (offsetp != NULL)
> -    *offsetp = read_4ubyte_unaligned (index->dbg,
> -				      index->section_offsets + i * 4);
> +    {
> +      if (section == DW_SECT_INFO && index->debug_info_offsets != NULL)
> +	*offsetp = index->debug_info_offsets[unit_row - 1];
> +      else
> +	*offsetp = read_4ubyte_unaligned (index->dbg,
> +					  index->section_offsets + i * 4);
> +    }
>    if (sizep != NULL)
>      *sizep = read_4ubyte_unaligned (index->dbg,
>  				    index->section_sizes + i * 4);

OK.

> diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
> index 78224ddb..ed8d27be 100644
> --- a/libdw/dwarf_end.c
> +++ b/libdw/dwarf_end.c
> @@ -40,6 +40,17 @@
>  #include "cfi.h"
>  
>  
> +static void
> +dwarf_package_index_free (Dwarf_Package_Index *index)
> +{
> +  if (index != NULL)
> +    {
> +      free (index->debug_info_offsets);
> +      free (index);
> +    }
> +}
> +
> +
>  static void
>  noop_free (void *arg __attribute__ ((unused)))
>  {
> @@ -79,8 +90,8 @@ dwarf_end (Dwarf *dwarf)
>  {
>    if (dwarf != NULL)
>      {
> -      free (dwarf->tu_index);
> -      free (dwarf->cu_index);
> +      dwarf_package_index_free (dwarf->tu_index);
> +      dwarf_package_index_free (dwarf->cu_index);
>  
>        if (dwarf->cfi != NULL)
>  	/* Clean up the CFI cache.  */

OK.

> diff --git a/libdw/libdwP.h b/libdw/libdwP.h
> index 1a0a4df3..6018399c 100644
> --- a/libdw/libdwP.h
> +++ b/libdw/libdwP.h
> @@ -371,6 +371,9 @@ typedef struct Dwarf_Package_Index_s
>    const unsigned char *indices;
>    const unsigned char *section_offsets;
>    const unsigned char *section_sizes;
> +  /* If DW_SECT_INFO section offsets were truncated to 32 bits, recovered
> +     64-bit offsets.  */
> +  Dwarf_Off *debug_info_offsets;
>  } Dwarf_Package_Index;
>  
>  /* CU representation.  */

OK.

> diff --git a/tests/Makefile.am b/tests/Makefile.am
> index 3f80c451..98131a6b 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -641,7 +641,12 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
>  	     testfile-dwp-4.bz2 testfile-dwp-4.dwp.bz2 \
>  	     testfile-dwp-4-strict.bz2 testfile-dwp-4-strict.dwp.bz2 \
>  	     testfile-dwp-5.bz2 testfile-dwp-5.dwp.bz2 testfile-dwp.source \
> -	     run-cu-dwp-section-info.sh run-declfiles.sh
> +	     run-cu-dwp-section-info.sh run-declfiles.sh \
> +	     testfile-dwp-5-cu-index-overflow \
> +	     testfile-dwp-5-cu-index-overflow.dwp \
> +	     testfile-dwp-4-cu-index-overflow \
> +	     testfile-dwp-4-cu-index-overflow.dwp \
> +	     testfile-dwp-cu-index-overflow.source
>  
>  
>  if USE_VALGRIND

You mean the .bz2 files here. Fixed.

diff --git a/tests/Makefile.am b/tests/Makefile.am
index 98131a6b..9141074f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -642,10 +642,10 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
             testfile-dwp-4-strict.bz2 testfile-dwp-4-strict.dwp.bz2 \
             testfile-dwp-5.bz2 testfile-dwp-5.dwp.bz2 testfile-dwp.source \
             run-cu-dwp-section-info.sh run-declfiles.sh \
-            testfile-dwp-5-cu-index-overflow \
-            testfile-dwp-5-cu-index-overflow.dwp \
-            testfile-dwp-4-cu-index-overflow \
-            testfile-dwp-4-cu-index-overflow.dwp \
+            testfile-dwp-5-cu-index-overflow.bz2 \
+            testfile-dwp-5-cu-index-overflow.dwp.bz2 \
+            testfile-dwp-4-cu-index-overflow.bz2 \
+            testfile-dwp-4-cu-index-overflow.dwp.bz2 \
             testfile-dwp-cu-index-overflow.source
 
 
Thanks for the new tests.

Pushed with the fixlets above.

Cheers,

Mark
  
Mark Wielaard March 1, 2024, 4:11 p.m. UTC | #2
Hi,

On Fri, 2024-03-01 at 15:59 +0100, Mark Wielaard wrote:
> This looks correct, but gcc noticed a path to use tu_offset (and
> tu_index) if they weren't initialized or NULL:
> 
> In file included from /home/mark/src/elfutils/libdw/libdwP.h:684,
>                  from /home/mark/src/elfutils/libdw/dwarf_cu_dwp_section_info.c:35:
> In function ‘read_4ubyte_unaligned_1’,
>     inlined from ‘__libdw_package_index’ at /home/mark/src/elfutils/libdw/dwarf_cu_dwp_section_info.c:302:34:
> /home/mark/src/elfutils/libdw/memory-access.h:291:12: error: ‘tu_offset’ may be used uninitialized [-Werror=maybe-uninitialized]
>   291 |   return up->u4;
>       |          ~~^~~~
> /home/mark/src/elfutils/libdw/dwarf_cu_dwp_section_info.c: In function ‘__libdw_package_index’:
> /home/mark/src/elfutils/libdw/dwarf_cu_dwp_section_info.c:268:28: note: ‘tu_offset’ was declared here
>   268 |       const unsigned char *tu_offset;
>       |                            ^~~~~~~~~
> cc1: all warnings being treated as errors
> 
> I couldn't immediately disprove gcc here, so I think it is a good idea
> to add an explicit check for tu_index != NULL.
> 
> diff --git a/libdw/dwarf_cu_dwp_section_info.c b/libdw/dwarf_cu_dwp_section_info.c
> index 3d11c87a..9fdc15bf 100644
> --- a/libdw/dwarf_cu_dwp_section_info.c
> +++ b/libdw/dwarf_cu_dwp_section_info.c
> @@ -297,7 +297,8 @@ __libdw_package_index (Dwarf *dbg, bool tu)
>               cu_index->debug_info_offsets[cui++] = off;
>               cu_offset += cu_index->section_count * 4;
>             }
> -         else if (unit_type == DW_UT_split_type && tui < tu_count)
> +         else if (unit_type == DW_UT_split_type && tu_index != NULL
> +                  && tui < tu_count)
>             {
>               if ((off & UINT32_MAX) != read_4ubyte_unaligned (dbg, tu_offset))
>                 goto not_sorted;
> 
> Which makes gcc happy again.

But not all gcc versions apparently. So I added the following on top.
  
Omar Sandoval March 1, 2024, 10:36 p.m. UTC | #3
On Fri, Mar 01, 2024 at 03:59:22PM +0100, Mark Wielaard wrote:
> Hi Omar,
> 
> On Mon, 2024-02-26 at 11:32 -0800, Omar Sandoval wrote:
> > Meta uses DWARF package files for our large, statically-linked C++
> > applications.  Some of our largest applications have more than 4GB in
> > .debug_info.dwo, but the section offsets in .debug_cu_index and
> > .debug_tu_index are 32 bits; see the discussion here [1].  We
> > implemented a workaround/extension for this in LLVM.  Implement the
> > equivalent in libdw.
> > 
> > To test this, we need files with more than 4GB in .debug_info.dwo.  I
> > created these artificially by editing GCC's assembly output.  They
> > compress down to 6KB.  I test them from run-large-elf-file.sh to take
> > advantage of the existing checks for large file support.
> > 
> > 1: https://discourse.llvm.org/t/dwarf-dwp-4gb-limit/63902.
> > 
> >  	* libdw/dwarf_end.c (dwarf_package_index_free): New function.
> > 	* tests/testfile-dwp-4-cu-index-overflow.bz2: New test file.
> > 	* tests/testfile-dwp-4-cu-index-overflow.dwp.bz2: New test file.
> > 	* tests/testfile-dwp-5-cu-index-overflow.bz2: New test file.
> > 	* tests/testfile-dwp-5-cu-index-overflow.dwp.bz2: New test file.
> > 	* tests/testfile-dwp-cu-index-overflow.source: New file.
> > 	* tests/run-large-elf-file.sh: Check
> > 	testfile-dwp-5-cu-index-overflow and
> > 	testfile-dwp-4-cu-index-overflow.
> 
> The hack is kind of horrible, but given that this doesn't really
> impacts "normal" dwp files and it does work with clang/lldb, lets just
> support it too.

Yup, I hate it, too. Thanks for merging this series and for the followup
fixes!
  

Patch

diff --git a/libdw/dwarf_cu_dwp_section_info.c b/libdw/dwarf_cu_dwp_section_info.c
index 298f36f9..3d11c87a 100644
--- a/libdw/dwarf_cu_dwp_section_info.c
+++ b/libdw/dwarf_cu_dwp_section_info.c
@@ -30,6 +30,8 @@ 
 # include <config.h>
 #endif
 
+#include <assert.h>
+
 #include "libdwP.h"
 
 static Dwarf_Package_Index *
@@ -110,7 +112,9 @@  __libdw_read_package_index (Dwarf *dbg, bool tu)
 
   index->dbg = dbg;
   /* Set absent sections to UINT32_MAX.  */
-  memset (index->sections, 0xff, sizeof (index->sections));
+  for (size_t i = 0;
+       i < sizeof (index->sections) / sizeof (index->sections[0]); i++)
+    index->sections[i] = UINT32_MAX;
   for (size_t i = 0; i < section_count; i++)
     {
       uint32_t section = read_4ubyte_unaligned (dbg, sections + i * 4);
@@ -161,6 +165,7 @@  __libdw_read_package_index (Dwarf *dbg, bool tu)
   index->indices = indices;
   index->section_offsets = section_offsets;
   index->section_sizes = section_sizes;
+  index->debug_info_offsets = NULL;
 
   return index;
 }
@@ -177,6 +182,137 @@  __libdw_package_index (Dwarf *dbg, bool tu)
   if (index == NULL)
     return NULL;
 
+  /* Offsets in the section offset table are 32-bit unsigned integers.  In
+     practice, the .debug_info.dwo section for very large executables can be
+     larger than 4GB.  GNU dwp as of binutils 2.41 and llvm-dwp before LLVM 15
+     both accidentally truncate offsets larger than 4GB.
+
+     LLVM 15 detects the overflow and errors out instead; see LLVM commit
+     f8df8114715b ("[DWP][DWARF] Detect and error on debug info offset
+     overflow").  However, lldb in LLVM 16 supports using dwp files with
+     truncated offsets by recovering them directly from the unit headers in the
+     .debug_info.dwo section; see LLVM commit c0db06227721 ("[DWARFLibrary] Add
+     support to re-construct cu-index").  Since LLVM 17, the overflow error can
+     be turned into a warning instead; see LLVM commit 53a483cee801 ("[DWP] add
+     overflow check for llvm-dwp tools if offset overflow").
+
+     LLVM's support for > 4GB offsets is effectively an extension to the DWARF
+     package file format, which we implement here.  The strategy is to walk the
+     unit headers in .debug_info.dwo in lockstep with the DW_SECT_INFO columns
+     in the section offset tables.  As long as they are in the same order
+     (which they are in practice for both GNU dwp and llvm-dwp), we can
+     correlate the truncated offset and produce a corrected array of offsets.
+
+     Note that this will be fixed properly in DWARF 6:
+     https://dwarfstd.org/issues/220708.2.html.  */
+  if (index->sections[DW_SECT_INFO - 1] != UINT32_MAX
+      && dbg->sectiondata[IDX_debug_info]->d_size > UINT32_MAX)
+    {
+      Dwarf_Package_Index *cu_index, *tu_index = NULL;
+      if (tu)
+	{
+	  tu_index = index;
+	  assert (dbg->cu_index == NULL);
+	  cu_index = __libdw_read_package_index (dbg, false);
+	  if (cu_index == NULL)
+	    {
+	      free(index);
+	      return NULL;
+	    }
+	}
+      else
+	{
+	  cu_index = index;
+	  if (dbg->sectiondata[IDX_debug_tu_index] != NULL
+	      && dbg->sectiondata[IDX_debug_types] == NULL)
+	    {
+	      assert (dbg->tu_index == NULL);
+	      tu_index = __libdw_read_package_index (dbg, true);
+	      if (tu_index == NULL)
+		{
+		  free(index);
+		  return NULL;
+		}
+	    }
+	}
+
+      cu_index->debug_info_offsets = malloc (cu_index->unit_count
+					     * sizeof (Dwarf_Off));
+      if (cu_index->debug_info_offsets == NULL)
+	{
+	  free (tu_index);
+	  free (cu_index);
+	  __libdw_seterrno (DWARF_E_NOMEM);
+	  return NULL;
+	}
+      if (tu_index != NULL)
+	{
+	  tu_index->debug_info_offsets = malloc (tu_index->unit_count
+						 * sizeof (Dwarf_Off));
+	  if (tu_index->debug_info_offsets == NULL)
+	    {
+	      free (tu_index);
+	      free (cu_index->debug_info_offsets);
+	      free (cu_index);
+	      __libdw_seterrno (DWARF_E_NOMEM);
+	      return NULL;
+	    }
+	}
+
+      Dwarf_Off off = 0;
+      uint32_t cui = 0, tui = 0;
+      uint32_t cu_count = cu_index->unit_count;
+      const unsigned char *cu_offset
+	= cu_index->section_offsets + cu_index->sections[DW_SECT_INFO - 1] * 4;
+      uint32_t tu_count = 0;
+      const unsigned char *tu_offset;
+      if (tu_index != NULL)
+	{
+	  tu_count = tu_index->unit_count;
+	  tu_offset = tu_index->section_offsets
+		      + tu_index->sections[DW_SECT_INFO - 1] * 4;
+	}
+      while (cui < cu_count || tui < tu_count)
+	{
+	  Dwarf_Off next_off;
+	  uint8_t unit_type;
+	  if (__libdw_next_unit (dbg, false, off, &next_off, NULL, NULL,
+				 &unit_type, NULL, NULL, NULL, NULL, NULL)
+	      != 0)
+	    {
+	    not_sorted:
+	      free (cu_index->debug_info_offsets);
+	      cu_index->debug_info_offsets = NULL;
+	      if (tu_index != NULL)
+		{
+		  free (tu_index->debug_info_offsets);
+		  tu_index->debug_info_offsets = NULL;
+		}
+	      break;
+	    }
+	  if (unit_type != DW_UT_split_type && cui < cu_count)
+	    {
+	      if ((off & UINT32_MAX) != read_4ubyte_unaligned (dbg, cu_offset))
+		goto not_sorted;
+	      cu_index->debug_info_offsets[cui++] = off;
+	      cu_offset += cu_index->section_count * 4;
+	    }
+	  else if (unit_type == DW_UT_split_type && tui < tu_count)
+	    {
+	      if ((off & UINT32_MAX) != read_4ubyte_unaligned (dbg, tu_offset))
+		goto not_sorted;
+	      tu_index->debug_info_offsets[tui++] = off;
+	      tu_offset += tu_index->section_count * 4;
+	    }
+	  off = next_off;
+	}
+
+      if (tu)
+	dbg->cu_index = cu_index;
+      else if (tu_index != NULL)
+	dbg->tu_index = tu_index;
+    }
+
   if (tu)
     dbg->tu_index = index;
   else
@@ -244,8 +380,13 @@  __libdw_dwp_section_info (Dwarf_Package_Index *index, uint32_t unit_row,
   size_t i = (size_t)(unit_row - 1) * index->section_count
 	     + index->sections[section - 1];
   if (offsetp != NULL)
-    *offsetp = read_4ubyte_unaligned (index->dbg,
-				      index->section_offsets + i * 4);
+    {
+      if (section == DW_SECT_INFO && index->debug_info_offsets != NULL)
+	*offsetp = index->debug_info_offsets[unit_row - 1];
+      else
+	*offsetp = read_4ubyte_unaligned (index->dbg,
+					  index->section_offsets + i * 4);
+    }
   if (sizep != NULL)
     *sizep = read_4ubyte_unaligned (index->dbg,
 				    index->section_sizes + i * 4);
diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index 78224ddb..ed8d27be 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -40,6 +40,17 @@ 
 #include "cfi.h"
 
 
+static void
+dwarf_package_index_free (Dwarf_Package_Index *index)
+{
+  if (index != NULL)
+    {
+      free (index->debug_info_offsets);
+      free (index);
+    }
+}
+
+
 static void
 noop_free (void *arg __attribute__ ((unused)))
 {
@@ -79,8 +90,8 @@  dwarf_end (Dwarf *dwarf)
 {
   if (dwarf != NULL)
     {
-      free (dwarf->tu_index);
-      free (dwarf->cu_index);
+      dwarf_package_index_free (dwarf->tu_index);
+      dwarf_package_index_free (dwarf->cu_index);
 
       if (dwarf->cfi != NULL)
 	/* Clean up the CFI cache.  */
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 1a0a4df3..6018399c 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -371,6 +371,9 @@  typedef struct Dwarf_Package_Index_s
   const unsigned char *indices;
   const unsigned char *section_offsets;
   const unsigned char *section_sizes;
+  /* If DW_SECT_INFO section offsets were truncated to 32 bits, recovered
+     64-bit offsets.  */
+  Dwarf_Off *debug_info_offsets;
 } Dwarf_Package_Index;
 
 /* CU representation.  */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 3f80c451..98131a6b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -641,7 +641,12 @@  EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 	     testfile-dwp-4.bz2 testfile-dwp-4.dwp.bz2 \
 	     testfile-dwp-4-strict.bz2 testfile-dwp-4-strict.dwp.bz2 \
 	     testfile-dwp-5.bz2 testfile-dwp-5.dwp.bz2 testfile-dwp.source \
-	     run-cu-dwp-section-info.sh run-declfiles.sh
+	     run-cu-dwp-section-info.sh run-declfiles.sh \
+	     testfile-dwp-5-cu-index-overflow \
+	     testfile-dwp-5-cu-index-overflow.dwp \
+	     testfile-dwp-4-cu-index-overflow \
+	     testfile-dwp-4-cu-index-overflow.dwp \
+	     testfile-dwp-cu-index-overflow.source
 
 
 if USE_VALGRIND
diff --git a/tests/run-large-elf-file.sh b/tests/run-large-elf-file.sh
index 7116de53..8108cb4b 100755
--- a/tests/run-large-elf-file.sh
+++ b/tests/run-large-elf-file.sh
@@ -122,4 +122,178 @@  test_file testfile38
 # 64bit, big endian, non-rel
 test_file testfile27
 
+# See testfile-dwp-cu-index-overflow.source
+testfiles testfile-dwp-5-cu-index-overflow testfile-dwp-5-cu-index-overflow.dwp
+
+testrun_compare ${abs_builddir}/cu-dwp-section-info testfile-dwp-5-cu-index-overflow.dwp << EOF
+file: testfile-dwp-5-cu-index-overflow.dwp
+INFO: 0x0 0x8000004c
+TYPES: 0x0 0x0
+ABBREV: 0x0 0x50
+LINE: 0x0 0x61
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x0 0x1c
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x8000004c 0x6f
+TYPES: 0x0 0x0
+ABBREV: 0x50 0x15e
+LINE: 0x61 0x63
+LOCLISTS: 0x0 0xd4
+STR_OFFSETS: 0x1c 0x24
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x22
+
+INFO: 0x800000bb 0xff
+TYPES: 0x0 0x0
+ABBREV: 0x50 0x15e
+LINE: 0x61 0x63
+LOCLISTS: 0x0 0xd4
+STR_OFFSETS: 0x1c 0x24
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x22
+
+INFO: 0x800001ba 0x8000004c
+TYPES: 0x0 0x0
+ABBREV: 0x1ae 0x50
+LINE: 0xc4 0x61
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x40 0x1c
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x100000206 0x6c
+TYPES: 0x0 0x0
+ABBREV: 0x1fe 0xc8
+LINE: 0x125 0x63
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x5c 0x20
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x100000272 0x6f
+TYPES: 0x0 0x0
+ABBREV: 0x1fe 0xc8
+LINE: 0x125 0x63
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x5c 0x20
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x1000002e1 0x182
+TYPES: 0x0 0x0
+ABBREV: 0x2c6 0x188
+LINE: 0x188 0x65
+LOCLISTS: 0xd4 0xee
+STR_OFFSETS: 0x7c 0x44
+MACRO: 0x0 0x0
+RNGLISTS: 0x22 0x43
+
+EOF
+
+testrun_compare ${abs_builddir}/get-units-split testfile-dwp-5-cu-index-overflow << EOF
+file: testfile-dwp-5-cu-index-overflow
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: filler1.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: foo.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: filler2.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: bar.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: main.cc
+
+EOF
+
+rm -f testfile-dwp-5-cu-index-overflow testfile-dwp-5-cu-index-overflow.dwp
+
+# See testfile-dwp-cu-index-overflow.source
+testfiles testfile-dwp-4-cu-index-overflow testfile-dwp-4-cu-index-overflow.dwp
+
+testrun_compare ${abs_builddir}/cu-dwp-section-info testfile-dwp-4-cu-index-overflow.dwp << EOF
+file: testfile-dwp-4-cu-index-overflow.dwp
+INFO: 0x0 0x8000004b
+TYPES: 0x0 0x0
+ABBREV: 0x0 0x58
+LINE: 0x0 0x2c
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x0 0x14
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x8000004b 0x116
+TYPES: 0x0 0x0
+ABBREV: 0x58 0x16f
+LINE: 0x2c 0x34
+LOCLISTS: 0x0 0x110
+STR_OFFSETS: 0x14 0x1c
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x80000161 0x8000004b
+TYPES: 0x0 0x0
+ABBREV: 0x1c7 0x58
+LINE: 0x60 0x2c
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x30 0x14
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x1000001ac 0x6e
+TYPES: 0x0 0x0
+ABBREV: 0x21f 0xd4
+LINE: 0x8c 0x34
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x44 0x18
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x10000021a 0x1b5
+TYPES: 0x0 0x0
+ABBREV: 0x2f3 0x19b
+LINE: 0xc0 0x35
+LOCLISTS: 0x110 0x12a
+STR_OFFSETS: 0x5c 0x3c
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x0 0x0
+TYPES: 0x0 0x6e
+ABBREV: 0x58 0x16f
+LINE: 0x2c 0x34
+LOCLISTS: 0x0 0x110
+STR_OFFSETS: 0x14 0x1c
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x0 0x0
+TYPES: 0x6e 0x6b
+ABBREV: 0x21f 0xd4
+LINE: 0x8c 0x34
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x44 0x18
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+EOF
+
+testrun_compare ${abs_builddir}/get-units-split testfile-dwp-4-cu-index-overflow << EOF
+file: testfile-dwp-4-cu-index-overflow
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: filler1.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: foo.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: filler2.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: bar.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: main.cc
+
+EOF
+
+rm -f testfile-dwp-4-cu-index-overflow testfile-dwp-4-cu-index-overflow.dwp
+
 exit 0
diff --git a/tests/testfile-dwp-4-cu-index-overflow.bz2 b/tests/testfile-dwp-4-cu-index-overflow.bz2
new file mode 100755
index 0000000000000000000000000000000000000000..2aaa4f40b8d0bacf75f617a9ad642a6ead10a6ef
GIT binary patch
literal 4490
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

literal 0
HcmV?d00001

diff --git a/tests/testfile-dwp-4-cu-index-overflow.dwp.bz2 b/tests/testfile-dwp-4-cu-index-overflow.dwp.bz2
diff --git a/tests/testfile-dwp-5-cu-index-overflow.bz2 b/tests/testfile-dwp-5-cu-index-overflow.bz2
new file mode 100755
index 0000000000000000000000000000000000000000..07185fe56fcbfcf9a6fa01e6ef9428fee3843f34
GIT binary patch
literal 4544
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

literal 0
HcmV?d00001

diff --git a/tests/testfile-dwp-5-cu-index-overflow.dwp.bz2 b/tests/testfile-dwp-5-cu-index-overflow.dwp.bz2
diff --git a/tests/testfile-dwp-cu-index-overflow.source b/tests/testfile-dwp-cu-index-overflow.source
new file mode 100644
index 00000000..2de15441
--- /dev/null
+++ b/tests/testfile-dwp-cu-index-overflow.source
@@ -0,0 +1,86 @@ 
+# Dummy program that we patch to generate a dwp file with more than 4GB of
+# .debug_info.
+
+# Generate 2 dummy files that result in DWARF blocks.
+$ for (( i = 1; i <= 2; i++ )); do echo 'constexpr int filler'$i'[] = { 1 };' > filler$i.cc; done
+$ g++ -O2 -g -gsplit-dwarf -fdebug-types-section -dA -S filler{1,2}.cc foo.cc bar.cc main.cc
+# Patch the DWARF blocks to be 2GB.
+$ for (( i = 1; i <= 2; i++ )); do patch -p1 << EOF
+--- a/filler$i.s
++++ b/filler$i.s
+@@ -7,5 +7,5 @@
+ 	.section	.debug_info.dwo,"e",@progbits
+ .Ldebug_info0:
+-	.long	0x49	# Length of Compilation Unit Info
++	.long	0x80000048	# Length of Compilation Unit Info
+ 	.value	0x5	# DWARF version number
+ 	.byte	0x5	# DW_UT_split_compile
+@@ -51,9 +51,6 @@
+ 	.long	0x29	# DW_AT_type
+ 			# DW_AT_const_expr
+-	.byte	0x4	# DW_AT_const_value
+-	.byte	0x1	# fp or vector constant word 0
+-	.byte	0	# fp or vector constant word 1
+-	.byte	0	# fp or vector constant word 2
+-	.byte	0	# fp or vector constant word 3
++	.long	0x80000000	# DW_AT_const_value
++	.fill	0x80000000
+ 	.byte	0	# end of children of DIE 0x14
+ 	.section	.debug_info,"",@progbits
+@@ -171,5 +168,5 @@
+ 	.uleb128 0x19	# (DW_FORM_flag_present)
+ 	.uleb128 0x1c	# (DW_AT_const_value)
+-	.uleb128 0xa	# (DW_FORM_block1)
++	.uleb128 0x4	# (DW_FORM_block4)
+ 	.byte	0
+ 	.byte	0
+EOF
+done
+$ for (( i = 1; i <= 2; i++ )); do as filler$i.s -o filler$i.o; done
+$ as foo.s -o foo.o
+$ as bar.s -o bar.o
+$ as main.s -o main.o
+$ g++ filler1.o foo.o filler2.o bar.o main.o -o testfile-dwp-5-cu-index-overflow
+# -continue-on-cu-index-overflow was added in LLVM 17:
+# https://reviews.llvm.org/D144565.
+$ llvm-dwp -continue-on-cu-index-overflow filler1.o foo.o filler2.o bar.o main.o -o testfile-dwp-5-cu-index-overflow.dwp
+
+# Same thing for DWARF 4.
+$ g++ -O2 -g -gdwarf-4 -gsplit-dwarf -fdebug-types-section -dA -S filler{1,2}.cc foo.cc bar.cc main.cc
+$ for (( i = 1; i <= 2; i++ )); do patch -p1 << EOF
+--- a/filler$i.s
++++ b/filler$i.s
+@@ -6,5 +6,5 @@
+ 	.section	.debug_info.dwo,"e",@progbits
+ .Ldebug_info0:
+-	.long	0x48	# Length of Compilation Unit Info
++	.long	0x80000047	# Length of Compilation Unit Info
+ 	.value	0x4	# DWARF version number
+ 	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+@@ -49,9 +49,6 @@
+ 	.long	0x28	# DW_AT_type
+ 			# DW_AT_const_expr
+-	.byte	0x4	# DW_AT_const_value
+-	.byte	0x1	# fp or vector constant word 0
+-	.byte	0	# fp or vector constant word 1
+-	.byte	0	# fp or vector constant word 2
+-	.byte	0	# fp or vector constant word 3
++	.long	0x80000000	# DW_AT_const_value
++	.fill	0x80000000
+ 	.byte	0	# end of children of DIE 0xb
+ 	.section	.debug_info,"",@progbits
+@@ -172,5 +169,5 @@
+ 	.uleb128 0x19	# (DW_FORM_flag_present)
+ 	.uleb128 0x1c	# (DW_AT_const_value)
+-	.uleb128 0xa	# (DW_FORM_block1)
++	.uleb128 0x4	# (DW_FORM_block4)
+ 	.byte	0
+ 	.byte	0
+EOF
+done
+$ for (( i = 1; i <= 2; i++ )); do as filler$i.s -o filler$i.o; done
+$ as foo.s -o foo.o
+$ as bar.s -o bar.o
+$ as main.s -o main.o
+$ g++ filler1.o foo.o filler2.o bar.o main.o -o testfile-dwp-4-cu-index-overflow
+$ llvm-dwp -continue-on-cu-index-overflow filler1.o foo.o filler2.o bar.o main.o -o testfile-dwp-4-cu-index-overflow.dwp