[Bug gdb/34431] New: [gdb] value_as_mpz ignores its DW_AT_data_bit_offset byte slice

firmiana402 at gmail dot com via Gdb-prs <[email protected]>
Newsgroups gmane.comp.gdb.bugs.discuss
Message-ID <[email protected]/bugzilla/>
https://sourceware.org/bugzilla/show_bug.cgi?id=34431

            Bug ID: 34431
           Summary: [gdb] value_as_mpz ignores its DW_AT_data_bit_offset
                    byte slice
           Product: gdb
           Version: HEAD
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: gdb
          Assignee: unassigned at sourceware dot org
          Reporter: firmiana402 at gmail dot com
  Target Milestone: ---

DWARF v5 Section 5.1 allows a base type's logical value to occupy
only part of a larger storage unit.  DW_AT_bit_size gives the value
width, and DW_AT_data_bit_offset gives its position from the beginning
of the containing storage.

Consider this little-endian base type:

    DW_TAG_base_type
      DW_AT_encoding         DW_ATE_unsigned
      DW_AT_byte_size        2
      DW_AT_bit_size         8
      DW_AT_data_bit_offset  8

For storage bytes [0xaa, 0xbb], the logical value is 0xbb.

In gdb/value.c, value_as_mpz calculates the correct source byte range:

    gdb::array_view<const gdb_byte> valbytes = val->contents ();
    ...
    unsigned n_bytes = ((bit_off % 8) + bit_size + 7) / 8;
    valbytes = valbytes.slice (bit_off / 8, n_bytes);

For this type, valbytes becomes the one-byte slice containing 0xbb.
However, the subsequent import ignores valbytes and reads the original
full storage again:

    result.read (val->contents (), byte_order,
                 type->is_unsigned ());

The later mask therefore keeps 0xaa, the low byte of the unsliced
little-endian storage, rather than 0xbb from the computed slice.

For example, let T reference the type above:

    DW_OP_const_type T, 2, [0xaa, 0xbb]
    DW_OP_convert 0
    DW_OP_constu 0xbb
    DW_OP_eq
    DW_OP_stack_value

The required result is 1.  GDB produces 0 because value_as_mpz imports
the wrong byte range.

The local variable valbytes is already adjusted for both the byte
offset and the number of bytes.  The import should use that view:

    result.read (valbytes, byte_order, type->is_unsigned ());

instead of obtaining the full storage again from val->contents ().

-- 
You are receiving this mail because:
You are on the CC list for the bug.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.