Skip to content

inconsistent stepping in gdb #33013

Closed

Description

@tromey

While experimenting with gdb I found I couldn't really predict what statements I might step to. Consider this test program:

fn main () {
    let a = ();
    let b : [i32; 0] = [];
    let mut c = 27;
    let d = c = 99;
    let e = "hi bob";
    let f = b"hi bob";
    let g = b'9';
    let h = ["whatever"; 8];
    let i = [1,2,3,4];
    let j = (23, "hi");
    let k = 2..3;
    let l = &i[k];
    let m: *const() = &a;
}

If I break step::main and run in gdb, stepping stops on many of these lines, but not all of them:

Breakpoint 1, step::main () at step.rs:4
4       let mut c = 27;
(gdb) n
5       let d = c = 99;
(gdb) 
7       let f = b"hi bob";
(gdb) 
8       let g = b'9';
(gdb) 
12      let k = 2..3;
(gdb) 
13      let l = &i[k];
(gdb) 
14      let m: *const() = &a;
(gdb) 
15  }

Activity

  1. added
    A-debuginfoArea: Debugging information in compiled programs (DWARF, PDB, etc.)
    on Apr 15, 2016
  2. michaelwoerister commented on Apr 19, 2016

    @michaelwoerister
    Member

    This will hopefully get some more attention again once we switch to MIR for code generation.

  3. xanlpz commented on Feb 27, 2017

    @xanlpz

    Latest rust (cb1f649) steps through every line now, although it will step through 'l' twice in my machine. Also it won't break in either 'a' or 'b', but I'm guessing this is intended (?).

  4. tromey commented on Feb 27, 2017

    @tromey
    ContributorAuthor

    Also it won't break in either 'a' or 'b', but I'm guessing this is intended (?).

    It's not explicit but I think that's part of the original bug -- breaking in this main skips the first two lines, while stepping to many of the remaining lines.

  5. xanlpz commented on Feb 27, 2017

    @xanlpz

    Alright, then the two remaining issues would be to fix that (which was already present in April) and to figure out why it's going through 'l' twice now.

  6. xanlpz commented on Mar 1, 2017

    @xanlpz

    About not breaking in the first two lines: I can reproduce this in a C program like:

    void main()
    {
        int a;
        int b;
    
        int c = 0;
    }
    

    gdb won't break in 'a' or 'b' either, no matter if this is compiled with GCC or clang. Looking at the IR if I compile this with clang it shares with the rust program the fact that there are actually no instructions generated, while the 'c' declaration has a 'store'. I'm guessing this is what makes gdb break in there in the end.

    So not sure if we want to actually fix this, but if we do it is an issue shared with other languages. I'll look into the double step now.

  7. tromey commented on Mar 1, 2017

    @tromey
    ContributorAuthor

    gdb won't break in 'a' or 'b' either, no matter if this is compiled with GCC or clang

    I wouldn't expect it in this case, as these are just declarations.

    Whether Rust code should stop on a simple initialization-by-constant doesn't matter so much to me -- I just think the results should be consistent. That is, either it ought to stop at each of those lines, or none of them. (Though now that I write that, stopping at none of them might be weird.)

  8. xanlpz commented on Mar 1, 2017

    @xanlpz

    Oh, I see now. I guess the issue is that the code looks similar but the generated IR is different, for 'a' and 'b' LLVM has enough with the alloca's, but for other variables it generates stores, etc. I guess one option might be to generate some dummy instruction to make debuggers stop there, but I'll also have a look at this then.

  9. tromey commented on Mar 1, 2017

    @tromey
    ContributorAuthor

    LLVM has enough with the alloca's, but for other variables it generates stores

    Thanks, that makes sense to me; I hadn't really thought about that. TBH I doubt it is worth pessimizing code to make this work.

  10. added
    E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.
    on May 16, 2022
  11. wesleywiser commented on May 16, 2022

    @wesleywiser
    Member

    Visited during wg-debugging triage. Currently, the stepping behavior behaves consistently for all lines except for the ZSTs a and b. We've decided to create a new issue for that specifically and therefore this ticket just needs a test and can then be closed.

  12. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Apr 5, 2023
  13. Enselic commented on Jul 26, 2025

    @Enselic
    Member

    Unfortunately this regressed in nightly-2023-04-24. A test to prevent further regressions is added in #144497.

    The following uses the test in that PR.

    curl -L -o /tmp/basic-stepping.rs https://raw.githubusercontent.com/rust-lang/rust/534b1355efe3fc0dc/tests/debuginfo/basic-stepping.rs
    for toolchain in nightly-2023-04-23 \
                     nightly-2023-04-24; do
        rustup --quiet install $toolchain --profile minimal
        rustc +$toolchain -g --allow unused_assignments --allow unused_variables /tmp/basic-stepping.rs -o /tmp/basic-stepping
        gdb -batch /tmp/basic-stepping -ex "break basic-stepping.rs:37" -ex "run" -ex "next" -ex "quit"
    done
      nightly-2023-04-23-x86_64-unknown-linux-gnu unchanged - rustc 1.71.0-nightly (b628260df 2023-04-22)
    
    Breakpoint 1, basic_stepping::main () at /tmp/basic-stepping.rs:37
    37          let d = c = 99;
    38          let e = "hi bob";
    
      nightly-2023-04-24-x86_64-unknown-linux-gnu unchanged - rustc 1.71.0-nightly (7f94b314c 2023-04-23)
    
    Breakpoint 1, basic_stepping::main () at /tmp/basic-stepping.rs:37
    37          let d = c = 99;
    41          let h = ["whatever"; 8];
    

    Note that lines are consecutive with nightly-2023-04-23 but not with nightly-2023-04-24.

    Here is the list of candidates:

    git log ^b628260df 7f94b314c --no-merges --oneline

    173845c Remove the size of locals heuristic in MIR inlining
    b8c67d8 Fortify test.
    4e8b642 Turn on ConstDebugInfo pass.
    4ad04ad Set debug location to debug operand spill.
    da5d01d Remove unused synstructure dep
    f77541a Update chrono/spdx-rs
    3344232 Run check_match and check_liveness when MIR is built instead of having an explicit phase for them
    5bb58a6 Make check_match and check_liveness take a LocalDefId
    1ce80e2 Allow LocalDefId as the argument to def_path_str
    e18d1f8 Leave it to the query system to invoke the typeck query instead of invoking it eagerly.
    f74fe8b Limit read size in File::read_to_end loop
    99962a8 Refactor SyntaxContext::ctxt logic.
    2e98368 make sysroot finding compatible with multiarch systems

    Probably 4e8b642 or 4ad04ad but none of those revert cleanly any longer.

    Update 2025-10-07

    I have bisected it further. It regressed with 4e8b642. I also updated the reproducer above.

  14. removed
    E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.
    on Jul 26, 2025
  15. 16 remaining items

  16. Enselic commented on Mar 16, 2026

    @Enselic
    Member
  17. added 4 commits that reference this issue on Apr 13, 2026
  18. added a commit that references this issue on Apr 13, 2026
  19. added 3 commits that reference this issue on Apr 25, 2026
  20. added a commit that references this issue on Apr 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-debuginfoArea: Debugging information in compiled programs (DWARF, PDB, etc.)C-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions