public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug debug/114144] New: Variables optimized out by -Og
@ 2024-02-28  7:18 lukas.graetz@tu-darmstadt.de
  2024-02-28  7:47 ` [Bug debug/114144] " pinskia at gcc dot gnu.org
  0 siblings, 1 reply; 2+ messages in thread
From: lukas.graetz@tu-darmstadt.de @ 2024-02-28  7:18 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 114144
           Summary: Variables optimized out by -Og
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: debug
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lukas.graetz@tu-darmstadt.de
  Target Milestone: ---

-Og seems to <optimize out> some variable values: On x86-64, function
parameters are lost after calling other functions, they were not saved (to the
stack). This could be undesired when debugging. Consider the following example:

===== foo.c ========================
int foo (int i) {
    return i + 1;
}

===== caller.c =====================
extern int foo(int);
int main(int argc, char **argv) {
    int i = foo(argc);
    int v = foo(i);
    return v;
}
====================================

   Compile on x86-64:

$ gcc -Og -g caller.c foo.c -o caller

   Debug with breakpoint after calling foo():

$ gdb caller

Reading symbols from caller...
(gdb) break caller.c:5
Breakpoint 1 at 0x401116: file caller.c, line 5.
(gdb) run
Starting program: /home/lukas/test/caller 

Breakpoint 1, main (argc=<optimised out>, argv=<optimised out>) at caller.c:5
5           return v;
(gdb) print argc
$1 = <optimised out>
(gdb) print i
$2 = <optimised out>
(gdb) print v
$3 = 3

-----------------------------------------------

For 32-bit x86 with "-m32 -Og -g" we would get argc and argv because the
calling conventions put them on the stack and not a caller-saved variable.
However, the variable i would still be <optimised out> at the breakpoint.

-----------------------------------------------
EXPECTED RESULT by compiling the same with -O0:

$ gcc -O0 -g caller.c foo.c -o caller

$ gdb caller

(gdb) break caller.c:5
Breakpoint 1 at 0x40112f: file caller.c, line 5.
(gdb) run
Starting program: /home/lukas/test/caller

Breakpoint 1, main (argc=1, argv=0x7fffffffdc98) at caller.c:5
5           return 0;
(gdb) print argc
$1 = 1
(gdb) print i
$2 = 2
(gdb) print v
$3 = 3
-----------------------------------------------

This is not a problem of the debugger gdb: By looking at the DWARF debugging
info, it turns out that argc has indeed been optimised out:


$ objdump -W caller
[...]
 <2><6d>: Abbrev Number: 1 (DW_TAG_formal_parameter)
    <6e>   DW_AT_name        : (indirect string, offset: 0x11): argc
    <72>   DW_AT_decl_file   : 1
    <72>   DW_AT_decl_line   : 2
    <72>   DW_AT_decl_column : 14
    <73>   DW_AT_type        : <0x44>
    <77>   DW_AT_location    : 0x10 (location list)
    <7b>   DW_AT_GNU_locviews: 0xc
[...]
Contents of the .debug_loclists section:
[...]
    00000010 v000000000000000 v000000000000000 views at 0000000c for:
             0000000000401106 000000000040110e (DW_OP_reg5 (rdi))
    00000015 v000000000000000 v000000000000000 views at 0000000e for:
             000000000040110e 000000000040111b (DW_OP_entry_value: (DW_OP_reg5
(rdi)); DW_OP_stack_value)
    0000001d <End of list>
[...]


Our breakpoint at location 0x401116 is inside the second range of the loclist.
However, we cannot compute "DW_OP_entry_value: (DW_OP_reg5 (rdi))" at 0x401116,
since it refers to a state at a previous location (the value of rdi at the
subprogram entry). Also, from the disasambly you can clearly see that
caller-saved registers %edi and %eax are not saved (neither to the stack nor to
callee-saved registers) before calling foo:

$ objdump -d caller
[...]
0000000000401106 <main>:
  401106:       48 83 ec 08             sub    $0x8,%rsp
  40110a:       e8 0c 00 00 00          callq  40111b <foo>
  40110f:       89 c7                   mov    %eax,%edi
  401111:       e8 05 00 00 00          callq  40111b <foo>
  401116:       48 83 c4 08             add    $0x8,%rsp
  40111a:       c3                      retq   
[...]


And if you don't like breakpoints, you could modify caller.c as follows to
automatically break by calling abort:

===== caller2.c =====================
#include <stdlib.h>
extern int foo(int);
int main(int argc, char **argv) {
    int i = foo(argc);
    int v = foo(i);
    abort();
}
=====================================

$ gcc -Og -g caller2.c foo.c -o caller2
$ gdb ./caller2
(gdb) run
Program received signal SIGABRT, Aborted.
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff7dcd859 in __GI_abort () at abort.c:79
#2  0x000000000040113b in main (argc=<optimised out>, argv=<optimised out>)
    at caller2.c:6

Here, too, we have argc=<optimised out>.


----------------------------------------------------------
According to the documentation of -Og:

"-Og should be the optimization level of choice for the standard
edit-compile-debug cycle, offering a reasonable level of optimization while
maintaining fast compilation and a good debugging experience."

"It is a better choice than -O0 for producing debuggable code because some
compiler passes that collect debug information are disabled at -O0."

But for many cases, -O0 currently seems to be the better choice. Because -O0
saves all values to the stack, they will not be <optimized out>. If -Og is
working as designed, then the documentation is misleading. In this case, I
would suggest to add something like the following to the documentation:

"-Og might also make the code less debuggable than -O0, because of some
optimizations for speed and size."

Observed in PR 38534.

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

* [Bug debug/114144] Variables optimized out by -Og
  2024-02-28  7:18 [Bug debug/114144] New: Variables optimized out by -Og lukas.graetz@tu-darmstadt.de
@ 2024-02-28  7:47 ` pinskia at gcc dot gnu.org
  0 siblings, 0 replies; 2+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-02-28  7:47 UTC (permalink / raw)
  To: gcc-bugs

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

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |DUPLICATE
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Yep this is a dup of bug 78685.

*** This bug has been marked as a duplicate of bug 78685 ***

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

end of thread, other threads:[~2024-02-28  7:47 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-28  7:18 [Bug debug/114144] New: Variables optimized out by -Og lukas.graetz@tu-darmstadt.de
2024-02-28  7:47 ` [Bug debug/114144] " pinskia at gcc dot gnu.org

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).