https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92775
Bug ID: 92775 Summary: Incorrect expression in DW_AT_byte_stride on an array Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: fortran Assignee: unassigned at gcc dot gnu.org Reporter: andrew.burgess at embecosm dot com Target Milestone: --- Created attachment 47411 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=47411&action=edit Example. 1. Unpack the example, and run 'make'. This creates a test binary called 'test', and the DWARF from that binary is placed into 'test.dwarf'. Initially I'm using GCC 7.4.0. 2. In the generated 'test.dwarf' Find the DW_TAG_variable for 'point_dimension', note its DW_AT_type and DW_AT_location. For me I have: <2><e9>: Abbrev Number: 10 (DW_TAG_variable) <ea> DW_AT_name : (indirect string, offset: 0x0): point_dimension <ee> DW_AT_decl_file : 1 <ef> DW_AT_decl_line : 13 <f0> DW_AT_type : <0x18a> <f4> DW_AT_location : 9 byte block: 3 80 10 60 0 0 0 0 0 (DW_OP_addr: 601080) ... <1><18a>: Abbrev Number: 16 (DW_TAG_array_type) <18b> DW_AT_data_location: 2 byte block: 97 6 (DW_OP_push_object_address; DW_OP_deref) <18e> DW_AT_associated : 4 byte block: 97 6 30 2e (DW_OP_push_object_address; DW_OP_deref; DW_OP_lit0; DW_OP_ne) <193> DW_AT_type : <0x5d> <2><197>: Abbrev Number: 17 (DW_TAG_subrange_type) <198> DW_AT_lower_bound : 4 byte block: 97 23 20 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 32; DW_OP_deref) <19d> DW_AT_upper_bound : 4 byte block: 97 23 28 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 40; DW_OP_deref) <1a2> DW_AT_byte_stride : 15 byte block: 97 23 18 6 3 b0 10 60 0 0 0 0 0 6 1e (DW_OP_push_object_address; DW_OP_plus_uconst: 24; DW_OP_deref; DW_OP_addr: 6010b0; DW_OP_deref; DW_OP_mul) 3. Figure out the expression to read the DW_AT_byte_stride, from the above it will be: ((*(0x601080 + 24)) * (*0x6010b0)) 4. Run the test program, this just confirms what we expect the value of 'point_dimension' to be, which is: { 2, 2, 2, 2, 2, 2, 2, 2, 2 }. 5. Now fire up GDB on the test program: $ gdb test (gdb) break 18 (gdb) run (gdb) p/d ((*(0x601080 + 24)) * (*0x6010b0)) $1 = 24 # So the stride appears to be 24. Now to check, first, where's the # first element: (gdb) p &point_dimension(1) $2 = (PTR TO -> ( integer(kind=8) )) 0x7fffffffccd8 # Now lets check the stride is correct by examining all the # remaining elements: (gdb) x/1w 0x7fffffffccd8 + (24 * 0) 0x7fffffffccd8: 2 (gdb) x/1w 0x7fffffffccd8 + (24 * 1) 0x7fffffffccf0: 2 (gdb) x/1w 0x7fffffffccd8 + (24 * 2) 0x7fffffffcd08: 2 (gdb) x/1w 0x7fffffffccd8 + (24 * 3) 0x7fffffffcd20: 2 (gdb) x/1w 0x7fffffffccd8 + (24 * 4) 0x7fffffffcd38: 2 (gdb) x/1w 0x7fffffffccd8 + (24 * 5) 0x7fffffffcd50: 2 (gdb) x/1w 0x7fffffffccd8 + (24 * 6) 0x7fffffffcd68: 2 (gdb) x/1w 0x7fffffffccd8 + (24 * 7) 0x7fffffffcd80: 2 (gdb) x/1w 0x7fffffffccd8 + (24 * 8) 0x7fffffffcd98: 2 # So it looks like a stride of 24 is correct. Based on the code # this is what I would expect. 6. Now recompile the test with a later version of GCC. I've tested 8.3.0 and 9.2.0, plus a version from trunk from mid-October 2019. The data below is from 9.2.0: <2><e9>: Abbrev Number: 10 (DW_TAG_variable) <ea> DW_AT_name : (indirect string, offset: 0x0): point_dimension <ee> DW_AT_decl_file : 1 <ef> DW_AT_decl_line : 13 <f0> DW_AT_type : <0x10f> <f4> DW_AT_location : 9 byte block: 3 80 10 60 0 0 0 0 0 (DW_OP_addr: 601080) ... <1><10f>: Abbrev Number: 13 (DW_TAG_array_type) <110> DW_AT_data_location: 2 byte block: 97 6 (DW_OP_push_object_address; DW_OP_deref) <113> DW_AT_associated : 4 byte block: 97 6 30 2e (DW_OP_push_object_address; DW_OP_deref; DW_OP_lit0; DW_OP_ne) <118> DW_AT_type : <0x5d> <2><11c>: Abbrev Number: 14 (DW_TAG_subrange_type) <11d> DW_AT_lower_bound : 4 byte block: 97 23 30 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 48; DW_OP_deref) <122> DW_AT_upper_bound : 4 byte block: 97 23 38 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 56; DW_OP_deref) <127> DW_AT_byte_stride : 6 byte block: 97 23 28 6 38 1e (DW_OP_push_object_address; DW_OP_plus_uconst: 40; DW_OP_deref; DW_OP_lit8; DW_OP_mul) 7. Notice that the DW_AT_byte_stride expression has changed, it now looks like this: ((*(0x601080 + 40)) * 8) 8. Before we validate this in GDB, for our sanity rerun the test program and confirm that it does the correct thing at run time, it still prints the array as 9 elements, all containing the value 2. 9. Now fire up GDB on the test program: $ gdb test (gdb) break 18 (gdb) run (gdb) p/d ((*(0x601080 + 40)) * 8) $1 = 8 # So now the stride is reported as 8. This seems unlikely, but # lets try it. Where's the first element. (gdb) p &point_dimension(1) $2 = (PTR TO -> ( integer(kind=8) )) 0x7fffffffcba8 # Now lets check all the other elements are in the correct place: (gdb) x/1w 0x7fffffffcba8 + (8 * 0) 0x7fffffffcba8: 2 (gdb) x/1w 0x7fffffffcba8 + (8 * 1) 0x7fffffffcbb0: 3 (gdb) x/1w 0x7fffffffcba8 + (8 * 2) 0x7fffffffcbb8: 1 (gdb) x/1w 0x7fffffffcba8 + (8 * 3) 0x7fffffffcbc0: 2 (gdb) x/1w 0x7fffffffcba8 + (8 * 4) 0x7fffffffcbc8: 3 (gdb) x/1w 0x7fffffffcba8 + (8 * 5) 0x7fffffffcbd0: 1 (gdb) x/1w 0x7fffffffcba8 + (8 * 6) 0x7fffffffcbd8: 2 (gdb) x/1w 0x7fffffffcba8 + (8 * 7) 0x7fffffffcbe0: 3 (gdb) x/1w 0x7fffffffcba8 + (8 * 8) 0x7fffffffcbe8: 1 # Clearly this is not correct. 10. The conclusion is that the DW_AT_byte_stride attribute of the DW_TAG_subrange_type for Fortran arrays is currently being generated incorrectly.