Skip to content
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

Debugger switches to disassembly when stepping into function even though debug information should be available #251

Open
bluenote10 opened this issue Jan 16, 2020 · 14 comments
Labels
priority:Medium Kinda bad, but can be lived with.

Comments

@bluenote10
Copy link

OS: Linux, Ubuntu 18.04
VSCode version: 1.14.1
Extension version: 1.4.5
Python version: 3.6.9
LLDB version: none

I still have problems with dropping into disassembly, although I think I shouldn't. According to the user manual:

When execution steps into code for which debug info is not available, CodeLLDB will automatically switch to disassembly view.

When I step into a function I almost always end up with the disassembly view, only in rare cases the debugger can follow the Rust source, which makes debugging very hard. For instance, I have a module with the structure:

// example function A
fn order_events<F>(sorted_events: &[Rc<SweepEvent<F>>]) -> Vec<Rc<SweepEvent<F>>>
where
    F: Float,
{
    // ...
}

// example function B
fn next_pos<F>(pos: i32, result_events: &[Rc<SweepEvent<F>>], processed: &mut HashSet<i32>, orig_index: i32) -> i32
where
    F: Float,
{
    // ...
}

// example function C
pub fn connect_edges<F>(sorted_events: &[Rc<SweepEvent<F>>], operation: Operation) -> Vec<Polygon<F>>
where
    F: Float,
{
    // <= break point here
    // somewhere calls A:
    let result_events = order_events(sorted_events);
    // later calls B:
    let pos = next_pos(pos, &result_events, &mut processed, i);
}

When I set a break point in function C, I can successfully step into the call to A, but stepping into the call to B drops to disassembly. According to manual this suggests that debug info is available for A, but not for B. At first I was wondering according to which patterns debug info is available, but then I noticed that putting a break point into B actually allows to debug it. So I would guess debug info is available.

Currently I don't see a pattern when stepping into a function succeeds and when it doesn't, except for maybe that it never works for any function outside the same module.

I have tried several ways to define my entries in launch.json, but the behavior is the same with both:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "lldb",
      "request": "launch",
      "name": "Debug variant 1",
      "cargo": {
        "args": [
          "build",
          "--package=geo-booleanop-tests"
        ]
      },
      "args": [],
      "cwd": "${workspaceFolder}/tests"
    },
    {
      "type": "lldb",
      "request": "launch",
      "name": "Debug variant 2",
      "program": "${workspaceRoot}/target/debug/run_single_test",
      "args": [],
      "cwd": "${workspaceRoot}/tests",
      "sourceLanguages": ["rust"]
    }
  ]
}

Any ideas what could be causing this?

Currently I don't have a minimal reproducing example, but if it helps I can try to build one.

@vadimcn
Copy link
Owner

vadimcn commented Jan 16, 2020

Assuming you are not compiling in --release mode, there's probably some problem with debug info emitted by the compiler. For example, it might be missing line number info for some code range in the function prologue. It's also possible, though less likely, that debug info is ok, but LLDB is not interpreting it correctly.
In either case, I don't think I can do much about it, sorry.

@bluenote10
Copy link
Author

Thanks any way for the clarification!

Do you maybe have an idea how to narrow down the problem, for instance:

  • Is there a manual way to inspect the debug info generated by the compiler to see exactly if/what is missing?
  • Any other compiler settings/switches that may affect debug info emission? (Yes, I wasn't using --release)

Maybe I can also find a minimal reproducing example. The debug experience with vscode-lldb would be really awesome, but switching into disassembly on almost every call totally spoils the process.

@vadimcn
Copy link
Owner

vadimcn commented Jan 19, 2020

Deciding line number debug info is not an easy task.
You can try to have rustc emit assembly file(s) find your function and check if it has .file and .line directives in the prologue.

Which rust version are you using? Can you try upgrading/downgrading? Does this happen with all finctions?

@bluenote10
Copy link
Author

I was on rustc 1.38.0 (625451e37 2019-09-23) and have now switched to rustc 1.40.0 (73528e339 2019-12-16), but I'm getting the same behavior.

So far I have actually only once stepped into a function successfully (this order_events in the example), all other step-into attempts lead to disassembly so far (but I can place break points in these functions). I still don't understand why this one function is different. Will have to do some more digging.

@delbato
Copy link

delbato commented Jan 30, 2020

I second this. I cant debug any of my unit tests because every "step into" turns into disassembly :/

@vadimcn vadimcn closed this as completed Dec 24, 2020
@NickJAllen
Copy link

I also had this problem. What was causing it was that in the launch config file the executable specified for debugging used a symbolic link in the path. When I changed it from using the symbolic link to the absolute path of the executable then I could step into methods and functions again. Hope that helps.

@cmcqueen
Copy link

I'm having this problem too, with debugging tests for a library. But I can't work out how to make use of the comment by @NickJAllen, because launch.json just contains a key "cargo" with a sub-key "args" with the first parameter "test", same as originally reported.

Why did @vadimcn close this as completed? I don't see what was completed.

@vadimcn
Copy link
Owner

vadimcn commented Jun 16, 2022

Sorry, probably closed this by mistake. But I'll need a solid repro case in order to investigate this.

@vadimcn vadimcn reopened this Jun 16, 2022
@cmcqueen
Copy link

cmcqueen commented Jun 17, 2022

Here's what I've been doing. I get the same results whether I'm using Ubuntu 20.04.4 LTS or Windows 10. VS Code 1.68.0 on Ubuntu; 1.65.2 on Windows.

  1. Clone repo for Rust library https://github.com/jamesmunns/cobs.rs
  2. Load that folder in VS Code.
  3. On "Run and Debug" tab, click "Run and Debug" button.
  4. When it says "Cannot start debugging because no launch configuration has been provided.", click Ok.
  5. When it says "Cargo.toml has been detected in this workspace. Would you like to generate launch configurations for its targets?", click Yes.
  6. Put a breakpoint on tests/test.rs, on the one line of the function test_encode_1().
  7. Select "Debug integration test 'test' and click "Start Debugging".
  8. Run to the breakpoint.
  9. Click "Step Into". At this point, I see it jump into assembly on tab @alloc::alloc::exchange_malloc::h6fe387d1b9276998.

If I put the breakpoint within the test_pair() function instead, and then try to step into the encode() function, it also jumps into assembly, but a different location @_$LT$alloc..vec..Vec$LT$T$C$....

@vadimcn
Copy link
Owner

vadimcn commented Jun 17, 2022

@cmcqueen You are directing lldb to step into functions implemented by the standard library, for which lldb doesn't know how to locate the source*. This may not be obvious in the first case because of macro expansion. To get into test_pair, you'll need to do step-out (Shift-F11), step-in, repeat several times till you get to the point of interest.

* If you wish to step into std, you'll need to set up a source map.

@cmcqueen
Copy link

Okay, that makes sense for the first case, because I guess it would need to construct the vectors that are the function parameters, before stepping into the function itself.

But, it doesn't make sense (to me) in the second case—being in test_pair(), and stepping in to the encode() function. The two parameters are just slices. Or is the assembly code because it's calling std code to obtain the slices from the vectors?

@vadimcn
Copy link
Owner

vadimcn commented Jun 21, 2022

Yes, it's stepping into std::ops::Index::index.

I'll note that normally lldb would skip code without debug info, however since std bundled with the compiler does have debug info (it's just that the source cannot be found without a source mapping), this does not happen.

@cmcqueen
Copy link

Yes, it's stepping into std::ops::Index::index.

Thanks for explaining; that does make sense.

normally lldb would skip code without debug info, however since std bundled with the compiler does have debug info (it's just that the source cannot be found without a source mapping), this does not happen.

That sounds a little unexpected to people like me, not an expert in these finer points of lldb. Is it possible to change lldb so that it would skip code that has debug info but no source mapping? (I don't know how to set up source mapping for Rust std in VS Code)

@vadimcn
Copy link
Owner

vadimcn commented Jul 15, 2022

Should be mostly fixed in 1.7.1. CodeLLDB will now set target.process.thread.step-avoid-regexp to ^<?(std|core|alloc)::, which should avoid stepping into std. It still misses some cases involving generic trait impls, because of inconsistent function names rustc emits.

@vadimcn vadimcn added the priority:Medium Kinda bad, but can be lived with. label Jul 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority:Medium Kinda bad, but can be lived with.
Projects
None yet
Development

No branches or pull requests

5 participants