Hi Mark,
On Mon, Jun 29, 2026 at 4:45 PM Mark Wielaard <[email protected]> wrote:
>
> The offset_size_flag is an DWARF 6 extension described in
> https://dwarfstd.org/issues/220708.2.html
>
> While writing tests for eu-dwp some issues with the eu-readelf display
> of the .debug_cu_index were found. The offset_size_flag was only used
> for the offsets table, not the size (lengths) table. And if the flag
> was set only 4 bytes of the offset were read (instead of 8 bytes).
>
> * src/readelf.c (print_cu_index_section): Calculate
> lengths_end using off_bytes, use read_8ubyte_unaligned to
> read offsets when offset_size_flag is set, calculate prow
> using off_bytes, read and print sizes based on off_bytes.
>
> Signed-off-by: Mark Wielaard <[email protected]>
LGTM.
Aaron
> ---
> src/readelf.c | 29 +++++++++++++++++++----------
> 1 file changed, 19 insertions(+), 10 deletions(-)
>
> diff --git a/src/readelf.c b/src/readelf.c
> index 8d7950d3a6c8..9d3bbbf6f240 100644
> --- a/src/readelf.c
> +++ b/src/readelf.c
> @@ -12290,6 +12290,7 @@ print_cu_index_section (Dwfl_Module *dwflmod
> __attribute__ ((unused)),
> readp++;
> }
>
> + /* Both offsets and sizes are either 32 or 64 bits (4 or 8 bytes). */
> const unsigned char off_bytes = offset_size_flag == 0 ? 4 : 8;
>
> if (unlikely (readp > dataend - 4))
> @@ -12325,17 +12326,17 @@ print_cu_index_section (Dwfl_Module *dwflmod
> __attribute__ ((unused)),
> the hash table (ids of 8 bytes). */
> const unsigned char *indices = hash_table + slot_count * 8;
> /* Sections used starts after the indices, indices and hash table
> - have the same number of slots, indeces are 4 bytes each, */
> + have the same number of slots, indices are 4 bytes each, */
> const unsigned char *sections = indices + slot_count * 4;
> /* Offset slots for each section follow the one row of sections. */
> const unsigned char *offsets = sections + section_count * 4;
> /* Size slots for each section follow the offsets (used rows). */
> const unsigned char *lengths = (offsets +
> unit_count * section_count * off_bytes);
> - /* The size table has one row of section_count 4-byte slots per unit,
> + /* The size table has one row of section_count slots per unit,
> just like the offset table, so it spans unit_count rows (not one). */
> const unsigned char *lengths_end = (lengths +
> - unit_count * section_count * 4);
> + unit_count * section_count * off_bytes);
>
> /* Sanity check the above against dataend. */
> if ((slot_count > UINT32_MAX / 8)
> @@ -12395,7 +12396,7 @@ print_cu_index_section (Dwfl_Module *dwflmod
> __attribute__ ((unused)),
> else
> for (size_t j = 0; j < section_count; j++)
> {
> - uint64_t off = read_4ubyte_unaligned (dbg, prow + j * 8);
> + uint64_t off = read_8ubyte_unaligned (dbg, prow + j * 8);
> fprintf (out, " %6" PRIu64, off);
> }
> fprintf (out, "\n");
> @@ -12433,12 +12434,20 @@ print_cu_index_section (Dwfl_Module *dwflmod
> __attribute__ ((unused)),
> continue;
> }
> /* Note row is one based, not zero based. */
> - const unsigned char *prow = lengths + (row - 1) * section_count * 4;
> - for (size_t j = 0; j < section_count; j++)
> - {
> - uint32_t off = read_4ubyte_unaligned (dbg, prow + j * 4);
> - fprintf (out, " %6" PRIu32, off);
> - }
> + const unsigned char *prow = (lengths
> + + (row - 1) * section_count *
> off_bytes);
> + if (off_bytes == 4)
> + for (size_t j = 0; j < section_count; j++)
> + {
> + uint32_t sz = read_4ubyte_unaligned (dbg, prow + j * 4);
> + fprintf (out, " %6" PRIu32, sz);
> + }
> + else
> + for (size_t j = 0; j < section_count; j++)
> + {
> + uint64_t sz = read_8ubyte_unaligned (dbg, prow + j * 8);
> + fprintf (out, " %6" PRIu64, sz);
> + }
> fprintf (out, "\n");
> }
> }
> --
> 2.54.0
>