Skip to content

arguments <optimized out> when optimizations remove unused data fields #46698

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
nikomatsakis opened this issue Dec 12, 2017 · 11 comments
Open
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@nikomatsakis
Copy link
Contributor

This program:

use std::env;

#[inline(never)]
fn foo(x: &str, y: &str) -> usize {
    x.len() + y.len()
}

fn main() {
    let mut args = env::args();

    let x = args.next().unwrap();
    let y = args.next().unwrap();
    let z = foo(&x, &y);
    println!("z={:?}", z);
}

when compiled with optimizations enabled, seems to strip out all of the local variable information:

lunch-box. rustc +nightly -O -g ~/tmp/foo.rs
lunch-box. gdb foo
Error in sitecustomize; set PYTHONVERBOSE for traceback:
AttributeError: module 'sys' has no attribute 'setdefaultencoding'
GNU gdb (Ubuntu 7.12.50.20170314-0ubuntu1.1) 7.12.50.20170314-git
Copyright (C) 2017 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.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from foo...done.
warning: Missing auto-load script at offset 0 in section .debug_gdb_scripts
of file /home/nmatsakis/tmp/foo.
Use `info auto-load python-scripts [REGEXP]' to list them.
(gdb) break 3
Breakpoint 1 at 0x7264: file /home/nmatsakis/tmp/foo.rs, line 3.
(gdb) r a b
Starting program: /home/nmatsakis/tmp/foo a b
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, foo::foo (x=..., y=...) at /home/nmatsakis/tmp/foo.rs:5
5       x.len() + y.len()
(gdb) p x
$1 = <optimized out>

cc @tromey

@nikomatsakis nikomatsakis added A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Dec 12, 2017
@tromey
Copy link
Contributor

tromey commented Dec 13, 2017

Our first theory when talking about it was that it was from the call to LLVMRustDIBuilderCreateCompileUnit, but from reading the source it appears that the isOptimized flag there is only used for sticking DW_AT_APPLE_optimized a DIE.

@XAMPPRocky XAMPPRocky added the C-bug Category: This is a bug. label Mar 26, 2018
@steveklabnik
Copy link
Member

Triage: this reproduces today on pc-windows-gnu:

Reading symbols from foo...done.
(gdb) break 3
Breakpoint 1 at 0x401650: file .\foo.rs, line 3.
(gdb) r a b
Starting program: C:\Users\steve\tmp\foo.exe a b
[New Thread 8680.0x484c]
[New Thread 8680.0x31fc]
[New Thread 8680.0x38c]
[New Thread 8680.0x20a8]

Breakpoint 1, foo::foo::hf83f4f51e74e413b (x=..., y=...) at .\foo.rs:5
5           x.len() + y.len()
(gdb) p x
$1 = <optimized out>

@norcalli
Copy link
Contributor

norcalli commented Feb 6, 2020

I've been running into this a lot lately with -O3 (on Rust 1.41.0). Most of the variables are optimized out, and our debug build is very slow compared to the release build, so it feels like a blocker for me.

@HadrienG2
Copy link

HadrienG2 commented Feb 6, 2020

Did you try running your debug builds at an intermediary optimization level of 1 or 2? Tuning my debug builds to opt-level=1 proved to be a good way to handle the debuginfo vs optimization tradeoff on some of my projects where opt-level=0 is unbearably slow.

@norcalli
Copy link
Contributor

I tried opt-level=1 and it's still optimized out entirely.

@wesleywiser
Copy link
Member

Visited during wg-debugging triage. LLVM is doing something interesting here (testing with Rust 1.68):

; example::foo
; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind nonlazybind readnone willreturn uwtable
define internal fastcc noundef i64 @_ZN7example3foo17ha5f3a2efc30301c8E(i64 noundef %x.1, i64 noundef %y.1) unnamed_addr #2 !dbg !760 {
start:
  call void @llvm.dbg.value(metadata ptr poison, metadata !766, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64)), !dbg !768
  call void @llvm.dbg.value(metadata i64 %x.1, metadata !766, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 64)), !dbg !768
  call void @llvm.dbg.value(metadata ptr poison, metadata !767, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64)), !dbg !768
  call void @llvm.dbg.value(metadata i64 %y.1, metadata !767, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 64)), !dbg !768
  %0 = add i64 %y.1, %x.1, !dbg !769
  ret i64 %0, !dbg !770
}

LLVM has observed that of the pair of str pointer and length values we pass into the function, only the length field is read and has changed the function signature to only take the length as an argument. As a result, within the function it isn't possible to reconstruct the string slice because the pointer wasn't passed into the function at all! More recent versions of gdb give a different error:

(gdb) info args
x = <error reading variable: Cannot access memory at address 0x8>
y = <error reading variable: Cannot access memory at address 0x8>

which is probably because the debuginfo still describes the types of the arguments as being &str with locations that seem incorrect:

0x00002f22:     DW_TAG_subprogram
                  DW_AT_low_pc  (0x0000000000008870)
                  DW_AT_high_pc (0x0000000000008875)
                  DW_AT_frame_base      (DW_OP_reg7 RSP)
                  DW_AT_linkage_name    ("_ZN7opt_out3foo17hb12c5e7bdd3575eaE")
                  DW_AT_name    ("foo")
                  DW_AT_decl_file       ("/tmp/opt_out.rs")
                  DW_AT_decl_line       (4)
                  DW_AT_calling_convention      (DW_CC_nocall)
                  DW_AT_type    (0x00002df2 "usize")

0x00002f40:       DW_TAG_formal_parameter
                    DW_AT_location      (0x00001915:
                       [0x0000000000008870, 0x0000000000008875): DW_OP_piece 0x8, DW_OP_reg5 RDI, DW_OP_piece 0x8)
                    DW_AT_name  ("x")
                    DW_AT_decl_file     ("/tmp/opt_out.rs")
                    DW_AT_decl_line     (4)
                    DW_AT_type  (0x000036f6 "&str")

0x00002f4f:       DW_TAG_formal_parameter
                    DW_AT_location      (0x0000194c:
                       [0x0000000000008870, 0x0000000000008875): DW_OP_piece 0x8, DW_OP_reg4 RSI, DW_OP_piece 0x8)
                    DW_AT_name  ("y")
                    DW_AT_decl_file     ("/tmp/opt_out.rs")
                    DW_AT_decl_line     (4)
                    DW_AT_type  (0x000036f6 "&str")

Improving/fixing the locations would probably give us back the "optimized out" gdb message which seems entirely accurate in this case. I don't think it's going to be generally possible to make info args work correctly though.

@wesleywiser wesleywiser changed the title variables declared as <optimized out> when optimizations are enabled arguments <optimized out> when optimizations remove unused data fields Apr 17, 2023
@khuey
Copy link
Contributor

khuey commented Feb 28, 2024

I believe the compiler output is correct and it's the debuggers that are wrong here. I sent https://lists.dwarfstd.org/pipermail/dwarf-discuss/2024-February/002375.html about clarifying the DWARF spec.

@tromey
Copy link
Contributor

tromey commented Feb 28, 2024

I tried this again today.

First, I don't think gdb has an issue with an empty leading piece. See https://sourceware.org/bugzilla/show_bug.cgi?id=31427

I filed https://sourceware.org/bugzilla/show_bug.cgi?id=31431 for the gdb side. Note that currently I get this output, which isn't great but also isn't really incorrect:

(gdb) info args
x = <error reading variable: value has been optimized out>
y = <error reading variable: value has been optimized out>

@khuey
Copy link
Contributor

khuey commented Feb 28, 2024

Ah, interesting. Personally I think gdb's set lang c output is the correct output. I suppose there's some Rust slice/str printing code in gdb that's swallowing it.

@riking
Copy link

riking commented Feb 29, 2024

Could we get LLVM to emit altered debug info in the form of a variable record for x.len and y.len?

@khuey
Copy link
Contributor

khuey commented Mar 1, 2024

Debuggers are supposed to present a source level view. It would be weird to rewrite the function signature in the debug info.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

9 participants