https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104891
Bug ID: 104891 Summary: Possibly wrong location definition in DWARF with -fschedule-insns2 at -O2/-O3 Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: debug Assignee: unassigned at gcc dot gnu.org Reporter: assaiante at diag dot uniroma1.it Target Milestone: --- In this minimized C example variables l_29 and l_30, which are defined and used in the scope within brackets spanning lines 4-8, are associated to DWARF symbols having a possibly wrong location definition, which causes variables to not be available during debugging, despite their DIEs being correctly defined. We observe the bug at -O2 and -O3 with the cause likely being -fschedule-insns2. Please find below a detailed analysis for -O3 on x64, including a comparison with prior gcc versions where the bug is sometimes not present. $ cat a.c volatile char a; int main() { int print_hash_value = 0; { int l_29 = 7, l_30 = 9551615; a = l_30 >= l_29; printf("%X\n", 0); } } GCC and GDB version (GCC commit id: 500d3f0a302): $ gcc --version gcc (GCC) 12.0.0 20211227 (experimental) Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ gdb --version GNU gdb (GDB) 11.2 Copyright (C) 2022 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. GDB trace: $ gcc -O3 -g a.c -o opt $ gdb -q opt Reading symbols from opt... (gdb) b 6 Breakpoint 1 at 0x400410: file a.c, line 6. (gdb) r Starting program: /home/stepping/debuginfo-analysis/dd-mismatches/66/reduce/opt Breakpoint 1, main () at a.c:6 6 a = l_30 >= l_29; (gdb) info locals print_hash_value = 0 By dumping the DWARF info, we can see how the location of the lexical block associated to the inner scope is defined by ranges where the first one is empty (400410-400410), while the values for l_29 and l_30 are correctly specified: ASM: 0000000000400410 <main>: 400410: 48 83 ec 08 sub $0x8,%rsp 400414: 31 f6 xor %esi,%esi 400416: bf a4 05 40 00 mov $0x4005a4,%edi 40041b: 31 c0 xor %eax,%eax 40041d: c6 05 0d 0c 20 00 01 movb $0x1,0x200c0d(%rip) # 601031 <a> 400424: e8 d7 ff ff ff call 400400 <printf@plt> 400429: 31 c0 xor %eax,%eax 40042b: 48 83 c4 08 add $0x8,%rsp 40042f: c3 ret DWARF info: 0x0000007d: DW_TAG_lexical_block DW_AT_ranges (0x0000000c [0x0000000000400410, 0x0000000000400410) [0x0000000000400414, 0x0000000000400429)) 0x00000082: DW_TAG_variable DW_AT_name ("l_29") DW_AT_decl_file ("/home/test/dd/66/reduce/a.c") DW_AT_decl_line (5) DW_AT_decl_column (0x09) DW_AT_type (0x000000d6 "int") DW_AT_const_value (0x07) 0x0000008e: DW_TAG_variable DW_AT_name ("l_30") DW_AT_decl_file ("/home/test/dd/66/reduce/a.c") DW_AT_decl_line (5) DW_AT_decl_column (0x13) DW_AT_type (0x000000d6 "int") DW_AT_const_value (0x0091beff) When we manually patch the first range to be (400410-400414), the variables are displayed correctly in gdb. Through some testing we found out that the optimization flag that introduces the bug is likely -fschedule-insns2. If we add -fno-schedule-insns2 to the compilation command line used above, variables l_29 and l_30 appear in the current frame with their values correctly available at line 6. The location of the lexical block appears now to be correctly defined (see low pc and high pc attributes): ASM with -fno-schedule-insns2: 0000000000400410 <main>: 400410: 48 83 ec 08 sub $0x8,%rsp 400414: c6 05 16 0c 20 00 01 movb $0x1,0x200c16(%rip) # 601031 <a> 40041b: 31 f6 xor %esi,%esi 40041d: bf a4 05 40 00 mov $0x4005a4,%edi 400422: 31 c0 xor %eax,%eax 400424: e8 d7 ff ff ff call 400400 <printf@plt> 400429: 31 c0 xor %eax,%eax 40042b: 48 83 c4 08 add $0x8,%rsp 40042f: c3 ret DWARF info with -fno-schedule-insns2: 0x0000007d: DW_TAG_lexical_block DW_AT_low_pc (0x0000000000400414) DW_AT_high_pc (0x0000000000400429) And the DWARF information for variable values is identical to when using -O3 -g alone. We also tested the program against older versions of gcc (6, 7, 8, 9, 10, 11) and the issue is present in all of them except 6 and 7: when debugging the executable generated from either, variables are displayed and more generally debug info looks correct. ASM from gcc-7: 0000000000000540 <main>: 540: 48 8d 3d bd 01 00 00 lea 0x1bd(%rip),%rdi # 704 <_IO_stdin_used+0x4> 547: 48 83 ec 08 sub $0x8,%rsp 54b: 31 f6 xor %esi,%esi 54d: 31 c0 xor %eax,%eax 54f: c6 05 bb 0a 20 00 01 movb $0x1,0x200abb(%rip) # 201011 <a> 556: e8 c5 ff ff ff call 520 <printf@plt> 55b: 31 c0 xor %eax,%eax 55d: 48 83 c4 08 add $0x8,%rsp 561: c3 ret DWARF info from gcc-7: 0x0000007a: DW_TAG_lexical_block DW_AT_ranges (0x00000000 [0x0000000000000540, 0x0000000000000547) [0x000000000000054b, 0x000000000000055b)) 0x0000007f: DW_TAG_variable DW_AT_name ("l_29") DW_AT_decl_file ("/home/test/dd/66/reduce/a.c") DW_AT_decl_line (5) DW_AT_type (0x000000d2 "int") DW_AT_const_value (0x07) 0x0000008b: DW_TAG_variable DW_AT_name ("l_30") DW_AT_decl_file ("/home/test/dd/66/reduce/a.c") DW_AT_decl_line (5) DW_AT_type (0x000000d2 "int") DW_AT_const_value (0x0091beff) We also tested the program against different gdb versions but this factor does not appear to affect the bug.