Skip to content
  • Joel Brobecker's avatar
    Add support for dynamic DW_AT_byte_stride. · a405673c
    Joel Brobecker authored
    This patch adds support for DW_AT_byte_stride, using Ada as one
    example of where this would be useful. However, the implementation
    is language-agnostic.
    
    Consider the following Ada code:
    
       procedure Nested (L, U : Integer) is
          subtype Small_Type is Integer range L .. U;
          type Record_Type (I : Small_Type := L) is record
             S : String (1 .. I);
          end record;
          type Array_Type is array (Integer range <>) of Record_Type;
    
          A1 : Array_Type :=
            (1 => (I => 0, S => <>),
             2 => (I => 1, S => "A"),
             3 => (I => 2, S => "AB"));
    
          procedure Discard (R : Record_Type) is
          begin
             null;
          end Discard;
    
       begin
          Discard (A1 (1));  -- STOP
       end;
    
    It defines an array A1 of Record_Type, which is a variant record
    type whose maximum size actually depends on the value of the
    parameters passed when calling Nested. As a result, the stride
    of the array A1 cannot be known statically, which leads the compiler
    to generate a dynamic DW_AT_byte_stride attribute for our type.
    Here is what the debugging info looks like with GNAT:
    
            .uleb128 0x10   # (DIE (0x14e) DW_TAG_array_type)
            .long   .LASF17 # DW_AT_name: "foo__nested__T18b"
            .long   0x141   # DW_AT_byte_stride
            .long   0xdc    # DW_AT_type
            .uleb128 0x11   # (DIE (0x15f) DW_TAG_subrange_type)
            .long   0x166   # DW_AT_type
            .byte   0x3     # DW_AT_upper_bound
            .byte   0       # end of children of DIE 0x14e
    
    There DW_AT_byte_stride is a reference to a local (internal)
    variable:
    
            .uleb128 0x9    # (DIE (0x141) DW_TAG_variable)
            .long   .LASF6  # DW_AT_name: "foo__nested__T18b___PAD___XVZ"
    
    This patch enhances GDB to handle this dynamic byte stride attribute
    by first adding a new dynamic_prop_node_kind (DYN_PROP_BYTE_STRIDE)
    to store the array dynamic stride info (when dynamic). It then enhances
    the dynamic type resolver to handle this dynamic property.
    
    Before applying this patch, trying to print the value of some of
    A1's elements after having stopped at the "STOP" comment does not
    work. For instance:
    
        (gdb) p a1(2)
        Cannot access memory at address 0x80000268dec0
    
    With this patch applied, GDB now prints the value of all 3 elements
    correctly:
    
        (gdb) print A1(1)
        $1 = (i => 0, s => "")
        (gdb) print A1(2)
        $2 = (i => 1, s => "A")
        (gdb) print A1(3)
        $3 = (i => 2, s => "AB")
    
    gdb/ChangeLog:
    
            * gdbtypes.h (enum dynamic_prop_node_kind) <DYN_PROP_BYTE_STRIDE>:
            New enum value.
            (create_array_type_with_stride): Add byte_stride_prop parameter.
            * gdbtypes.c (create_array_type_with_stride) <byte_stride_prop>:
            New parameter.  Update all callers in this file.
            (array_type_has_dynamic_stride): New function.
            (is_dynamic_type_internal, resolve_dynamic_array): Add handling
            of arrays with dynamic byte strides.
            * dwarf2read.c (read_array_type): Add support for dynamic
            DW_AT_byte_stride attributes.
    
    gdb/testsuite/ChangeLog:
    
            * gdb.ada/dyn_stride: New testcase.
    
    Tested on x86_64-linux.
    a405673c
To find the state of this project's repository at the time of any of these versions, check out the tags.