public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug debug/105108] New: incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant
@ 2022-03-30 14:38 assaiante at diag dot uniroma1.it
  2022-03-31  6:39 ` [Bug debug/105108] " rguenth at gcc dot gnu.org
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: assaiante at diag dot uniroma1.it @ 2022-03-30 14:38 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108

            Bug ID: 105108
           Summary: incomplete/incorrect DWARF information at -O1 and -Og
                    after inlining a function returning a constant
           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, variable l_144 is not available when debugging
(optimized out) when used in the assignment of variable a.

We found this odd since -O2/-O3 generate nearly identical ASM but with complete
debug information for l_144. At -O1/-Og the DIE of the variable misses instead
the const value attribute.

We were not able to pinpoint the root cause to a specific compilation option,
but suspect an interaction of inlining and constant propagation. We provide
below additional analysis for x64.

Then, much to our surprise, when we modify line 4 to assign l_144 with e.g. 8,
the debugger shows 8 instead of 0 as its value at line 7, therefore exposing
incorrect debug information. At a first look, this happened also with -O2/O3:
however, we then found -O2/-O3 DWARF information to be correct (also, lldb
displays 0), with the issue likely being a bug in gdb that we will report
separately.

$ cat a.c
int a;
char b() { return 0; }
int main() {
 char l_144;
 short l_165 = 128;
 l_144 = b();
 a = l_144 != l_165;
}


GCC and GDB version (GCC commit id: 500d3f0a302):
> gcc (GCC) 12.0.0 20211227 (experimental)
> GNU gdb (GDB) 11.2

GDB trace:
$ gcc -Og -g a.c -o opt
$ gdb opt
Reading symbols from opt...
(gdb) b 7
Breakpoint 1 at 0x40048c: file a.c, line 7.
(gdb) r
Starting program: /home/stepping/35/reduce/opt 

Breakpoint 1, main () at a.c:7
7         a = l_144 != l_165;
(gdb) info locals
l_144 = <optimized out>
l_165 = 128


ASM at Og (identical at O1):
000000000040048c <main>:
 40048c:       c7 05 96 0b 20 00 01    movl   $0x1,0x200b96(%rip)        #
60102c <a>
 400493:       00 00 00  
 400496:       b8 00 00 00 00          mov    $0x0,%eax
 40049b:       c3                      retq    
 40049c:       0f 1f 40 00             nopl   0x0(%rax)

DWARF at Og (identical at O1):
0x00000049:   DW_TAG_subprogram
                DW_AT_external  (true)
                DW_AT_name      ("main")
                DW_AT_decl_file ("/home/stepping/35/reduce/a.c")
                DW_AT_decl_line (3)
                DW_AT_decl_column       (0x05)
                DW_AT_type      (0x00000042 "int")
                DW_AT_low_pc    (0x000000000040048c)
                DW_AT_high_pc   (0x000000000040049c)
                DW_AT_frame_base        (DW_OP_call_frame_cfa)
                DW_AT_call_all_calls    (true)
                DW_AT_sibling   (0x00000085)

0x0000006b:     DW_TAG_variable
                  DW_AT_name    ("l_144")
                  DW_AT_decl_file       ("/home/stepping/35/reduce/a.c")
                  DW_AT_decl_line       (4)
                  DW_AT_decl_column     (0x08)
                  DW_AT_type    (0x00000085 "char")

0x00000077:     DW_TAG_variable
                  DW_AT_name    ("l_165")
                  DW_AT_decl_file       ("/home/stepping/35/reduce/a.c")
                  DW_AT_decl_line       (5)
                  DW_AT_decl_column     (0x09)
                  DW_AT_type    (0x0000008c "short int")
                  DW_AT_const_value     (0x80)


At higher optimization levels the ASM is nearly the same, except the use of xor
instead of mov to set the return value to zero:

00000000004003a0 <main>:
 4003a0:       c7 05 82 0c 20 00 01    movl   $0x1,0x200c82(%rip)        #
60102c <a>
 4003a7:       00 00 00  
 4003aa:       31 c0                   xor    %eax,%eax
 4003ac:       c3                      retq    
 4003ad:       0f 1f 00                nopl   (%rax)

But the variable is correctly visible when stepping on line 7 since the const
value attribute is present in its debug information:

0x00000045:   DW_TAG_subprogram
                DW_AT_external  (true)
                DW_AT_name      ("main")
                DW_AT_decl_file ("/home/stepping/35/reduce/a.c")
                DW_AT_decl_line (3)
                DW_AT_decl_column       (0x05)
                DW_AT_type      (0x0000003e "int")
                DW_AT_low_pc    (0x00000000004003a0)
                DW_AT_high_pc   (0x00000000004003ad)
                DW_AT_frame_base        (DW_OP_call_frame_cfa)
                DW_AT_call_all_calls    (true)
                DW_AT_sibling   (0x00000080)

0x00000067:     DW_TAG_variable
                  DW_AT_name    ("l_144")
                  DW_AT_decl_line       (4)
                  DW_AT_decl_column     (0x08)
                  DW_AT_type    (0x00000080 "char")
                  DW_AT_const_value     (0x00)

0x00000073:     DW_TAG_variable
                  DW_AT_name    ("l_165")
                  DW_AT_decl_line       (5)
                  DW_AT_decl_column     (0x09)
                  DW_AT_type    (0x00000087 "short int")
                  DW_AT_const_value     (0x80)

We also tested the program with older gcc (6, 7, 8, 9, 10, 11) versions. In
gcc-{6,7}, the information about the variable l_144 value is never generated at
any optimization level. From gcc-8 to gcc-11, we encounter the same exact
behavior as in the git version we have tested, including the variant where
variable l_144 is assigned upon its definition. In fact, also in older gcc
versions, such assignment ultimately leads to a wrong value available during
debugging when optimization level is Og or O1. At higher levels, the debug
information is correctly generated but, as mentioned before, a potential gdb
bug leads to a wrong value being displayed.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug debug/105108] incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant
  2022-03-30 14:38 [Bug debug/105108] New: incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant assaiante at diag dot uniroma1.it
@ 2022-03-31  6:39 ` rguenth at gcc dot gnu.org
  2022-03-31  9:20 ` jakub at gcc dot gnu.org
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: rguenth at gcc dot gnu.org @ 2022-03-31  6:39 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
     Ever confirmed|0                           |1
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2022-03-31

--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
Confirmed.  At -O2 we end up with

int main ()
{
  <bb 2> [local count: 1073741824]:
  [t.c:4:2] # DEBUG BEGIN_STMT
  [t.c:5:2] # DEBUG BEGIN_STMT
  [t.c:5:8] # DEBUG l_165 => 128
  [t.c:6:2] # DEBUG BEGIN_STMT
  [t.c:6:10] # DEBUG l_144 => 0
  [t.c:7:2] # DEBUG BEGIN_STMT
  [t.c:7:4] a = 1; 
  [<built-in>:0:0] return 0;

}

while -O1 has

int main ()
{
  <bb 2> [local count: 1073741824]:
  [t.c:4:2] # DEBUG BEGIN_STMT
  [t.c:5:2] # DEBUG BEGIN_STMT
  [t.c:5:8] # DEBUG l_165 => 128
  [t.c:6:2] # DEBUG BEGIN_STMT
  [t.c:7:2] # DEBUG BEGIN_STMT
  [t.c:7:4] a = 1; 
  [<built-in>:0:0] return 0;

with -O1 we do not inline b() but instead CCP uses value-range info to
determine
that l_144 cannot be 128 and thus the call to b() is DCEd before it is
inlined.  So indeed at -O1 we do not know the value of l_144, we only know
that it cannot be 128.

Not sure what we can do about the missing debug info - IIRC we cannot
encode in DWARF that l_144 has the value of 'b()' (which is discovered
to have no side-effects besides the return value).

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug debug/105108] incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant
  2022-03-30 14:38 [Bug debug/105108] New: incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant assaiante at diag dot uniroma1.it
  2022-03-31  6:39 ` [Bug debug/105108] " rguenth at gcc dot gnu.org
@ 2022-03-31  9:20 ` jakub at gcc dot gnu.org
  2022-03-31  9:25 ` jakub at gcc dot gnu.org
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-03-31  9:20 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Yeah, there is nothing we can do in the debug info about this.
We really can't inline just for the purposes of debug stmts or something
similar.
Another similar case would be if l_144 is assigned b() but isn't actually used
at all, if b() is pure (explicitly or implicitly detected), the call will be
DCEd and there is no way how to express it in the debug info.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug debug/105108] incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant
  2022-03-30 14:38 [Bug debug/105108] New: incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant assaiante at diag dot uniroma1.it
  2022-03-31  6:39 ` [Bug debug/105108] " rguenth at gcc dot gnu.org
  2022-03-31  9:20 ` jakub at gcc dot gnu.org
@ 2022-03-31  9:25 ` jakub at gcc dot gnu.org
  2022-03-31 10:20 ` rguenth at gcc dot gnu.org
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-03-31  9:25 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108

--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
And I certainly can't reproduce the wrong-debug issue you're talking about.
If I change it to char l_144 = 8;
then optimized dump has:
  <bb 2> [local count: 1073741824]:
  # DEBUG BEGIN_STMT
  # DEBUG l_144 => 8
  # DEBUG BEGIN_STMT
  # DEBUG l_165 => 128
  # DEBUG BEGIN_STMT
  # DEBUG l_144 => NULL
  # DEBUG BEGIN_STMT
  a = 1;
  return 0;
and in the debugger it correctly says that
(gdb) p l_144
$1 = <optimized out>
because at the a = 1 store the value is unknown.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug debug/105108] incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant
  2022-03-30 14:38 [Bug debug/105108] New: incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant assaiante at diag dot uniroma1.it
                   ` (2 preceding siblings ...)
  2022-03-31  9:25 ` jakub at gcc dot gnu.org
@ 2022-03-31 10:20 ` rguenth at gcc dot gnu.org
  2022-03-31 10:32 ` jakub at gcc dot gnu.org
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: rguenth at gcc dot gnu.org @ 2022-03-31 10:20 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #2)
> Yeah, there is nothing we can do in the debug info about this.
> We really can't inline just for the purposes of debug stmts or something
> similar.
> Another similar case would be if l_144 is assigned b() but isn't actually
> used at all, if b() is pure (explicitly or implicitly detected), the call
> will be DCEd and there is no way how to express it in the debug info.

I wondered if one could extend DWARF to have an expression op that says
'call this abstract function described in DIE x [with arguments from stack]
and push the result'.  That could also be used to maybe abstract parts of
DWARF expressions into DWARF expression functions and in theory we could
compile functions into DWARF bytecode if there's no native copy emitted
to be called from the debugger in inferior context (to some extent at least).

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug debug/105108] incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant
  2022-03-30 14:38 [Bug debug/105108] New: incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant assaiante at diag dot uniroma1.it
                   ` (3 preceding siblings ...)
  2022-03-31 10:20 ` rguenth at gcc dot gnu.org
@ 2022-03-31 10:32 ` jakub at gcc dot gnu.org
  2022-03-31 10:36 ` jakub at gcc dot gnu.org
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-03-31 10:32 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |mark at gcc dot gnu.org

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Guess that would be certainly possible, but best would be to propose such an
extension for inclusion into DWARF 6 because we are really tight in the
DW_OP_GNU_* opcode space.

BTW, if it would be IPA-VRP we could perhaps replace in debug stmts calls to
the singleton value range (if any), but in this case it is removed purely
because it is a const call and a signed char will never be equal to 128 (at
least on most -fsigned-char targets).

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug debug/105108] incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant
  2022-03-30 14:38 [Bug debug/105108] New: incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant assaiante at diag dot uniroma1.it
                   ` (4 preceding siblings ...)
  2022-03-31 10:32 ` jakub at gcc dot gnu.org
@ 2022-03-31 10:36 ` jakub at gcc dot gnu.org
  2022-03-31 10:41 ` jakub at gcc dot gnu.org
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-03-31 10:36 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108

--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Note, for computations expressible in DWARF expressions DWARF already has
DW_OP_call* which doesn't actually mean a call in the inferior call sense, but
a call in the DWARF expression evaluation sense, so one can create artificial
DW_TAG_dwarf_procedure and have its location expression be some DWARF
expression and use that to decrease size of emitted DWARF or even to emit code
to evaluate optimized away simple functions.
But what is missing is a way to request evaluation of an inferior call.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug debug/105108] incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant
  2022-03-30 14:38 [Bug debug/105108] New: incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant assaiante at diag dot uniroma1.it
                   ` (5 preceding siblings ...)
  2022-03-31 10:36 ` jakub at gcc dot gnu.org
@ 2022-03-31 10:41 ` jakub at gcc dot gnu.org
  2022-03-31 16:55 ` assaiante at diag dot uniroma1.it
  2022-03-31 16:55 ` assaiante at diag dot uniroma1.it
  8 siblings, 0 replies; 10+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-03-31 10:41 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
There can be security concerns with that though if just print variable
in a debugger lets you format your disk etc. though, while DWARF expressions
can do a lot, they can't modify registers or memory of the debugged program,
perform I/O etc., while this would allow it to be done under the hood without
the user knowing it is happening.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug debug/105108] incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant
  2022-03-30 14:38 [Bug debug/105108] New: incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant assaiante at diag dot uniroma1.it
                   ` (6 preceding siblings ...)
  2022-03-31 10:41 ` jakub at gcc dot gnu.org
@ 2022-03-31 16:55 ` assaiante at diag dot uniroma1.it
  2022-03-31 16:55 ` assaiante at diag dot uniroma1.it
  8 siblings, 0 replies; 10+ messages in thread
From: assaiante at diag dot uniroma1.it @ 2022-03-31 16:55 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108

--- Comment #8 from Cristian Assaiante <assaiante at diag dot uniroma1.it> ---
(In reply to Jakub Jelinek from comment #3)
> And I certainly can't reproduce the wrong-debug issue you're talking about.
> If I change it to char l_144 = 8;
> then optimized dump has:
>   <bb 2> [local count: 1073741824]:
>   # DEBUG BEGIN_STMT
>   # DEBUG l_144 => 8
>   # DEBUG BEGIN_STMT
>   # DEBUG l_165 => 128
>   # DEBUG BEGIN_STMT
>   # DEBUG l_144 => NULL
>   # DEBUG BEGIN_STMT
>   a = 1;
>   return 0;
> and in the debugger it correctly says that
> (gdb) p l_144
> $1 = <optimized out>
> because at the a = 1 store the value is unknown.

I have tested again the C example with l_144 = 8 and in gdb l_144 is not marked
as optimized out, instead it has 8 as value:

$ cat a.c
int a;
char b() { return 0; }
int main() {
 char l_144 = 8;
 short l_165 = 128;
 l_144 = b();
 a = l_144 != l_165;
}

$ gcc -Og -g a.c -o opt

DWARF info for l_144:
0x0000006b:     DW_TAG_variable
                  DW_AT_name    ("l_144")
                  DW_AT_decl_file       ("/home/stepping/a.c")
                  DW_AT_decl_line       (4)
                  DW_AT_decl_column     (0x07)
                  DW_AT_type    (0x0000008d "char")
                  DW_AT_location        (0x0000000e: 
                     [0x000000000040048c, 0x000000000040048c): DW_OP_lit8,
DW_OP_stack_value)
                  DW_AT_GNU_locviews    (0x0000000c)

GDB trace:
Reading symbols from opt...
(gdb) b 6
Breakpoint 1 at 0x40048c: file a.c, line 6.
(gdb) r
Starting program: /home/stepping/opt 

Breakpoint 1, main () at a.c:7
7        a = l_144 != l_165;
(gdb) p l_144
$1 = 8 '\b'


I will add the executable file as an attachment.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug debug/105108] incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant
  2022-03-30 14:38 [Bug debug/105108] New: incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant assaiante at diag dot uniroma1.it
                   ` (7 preceding siblings ...)
  2022-03-31 16:55 ` assaiante at diag dot uniroma1.it
@ 2022-03-31 16:55 ` assaiante at diag dot uniroma1.it
  8 siblings, 0 replies; 10+ messages in thread
From: assaiante at diag dot uniroma1.it @ 2022-03-31 16:55 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108

--- Comment #9 from Cristian Assaiante <assaiante at diag dot uniroma1.it> ---
Created attachment 52728
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=52728&action=edit
Executable file at -Og with l_144 = 8

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-03-31 16:55 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-30 14:38 [Bug debug/105108] New: incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant assaiante at diag dot uniroma1.it
2022-03-31  6:39 ` [Bug debug/105108] " rguenth at gcc dot gnu.org
2022-03-31  9:20 ` jakub at gcc dot gnu.org
2022-03-31  9:25 ` jakub at gcc dot gnu.org
2022-03-31 10:20 ` rguenth at gcc dot gnu.org
2022-03-31 10:32 ` jakub at gcc dot gnu.org
2022-03-31 10:36 ` jakub at gcc dot gnu.org
2022-03-31 10:41 ` jakub at gcc dot gnu.org
2022-03-31 16:55 ` assaiante at diag dot uniroma1.it
2022-03-31 16:55 ` assaiante at diag dot uniroma1.it

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).