inconsistent stepping in gdb

29593ed
Opened by Tom Tromey at 2023-04-05 17:45:43

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  }
  1. This will hopefully get some more attention again once we switch to MIR for code generation.

    Michael Woerister at 2016-04-19 18:58:34

  2. Latest rust (cb1f6492) 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 (?).

    Xan López at 2017-02-27 12:08:30

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

    Tom Tromey at 2017-02-27 14:34:17

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

    Xan López at 2017-02-27 14:59:02

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

    Xan López at 2017-03-01 17:50:45

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

    Tom Tromey at 2017-03-01 17:55:36

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

    Xan López at 2017-03-01 18:11:20

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

    Tom Tromey at 2017-03-01 18:29:04

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

    Wesley Wiser at 2022-05-16 14:53:41