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
Rust function of sufficient length prevents breakpoints from working #47373
Comments
assigned to @JDevlieghere |
File and line breakpoints use the line table from the debug info. You can look at that in the debug info with dwarfdump --debug-line And you can see it as lldb internalized it with: (lldb) image dump line-table main.rs If the first one doesn't show entries for your function, then something in your toolchain is dropping the line info on the floor. If it is in the DWARF, but not in the "image dump" output then lldb isn't internalizing the DWARF properly. And if it is in the debug info and we show it in image dump, then for some reason the breakpoint resolver is rejecting the matches. |
Appears in the failing cases, Working case:
Failing case:
(Note I don't know why rustc is naming these dSYM's with identical checksum-seeming suffixes (c5baf7da58e66c42). But they are clearly different, and correspond to different versions of the source code.) I expect you'll want to refer this to the Rust compiler. |
Yeah, that definitely is a bug on the producer side. The error message makes it sound like something has gone horribly wrong when producing that file -- it does not even register as a MachO file. Maybe the compiler (or dsymutil?) crashed somehow before it could produce that file? I think the compiler folks would ideally want a way to reproduce this bug, so a small self-contained piece of source code that triggers this would be most helpful (though it sounds like that may be hard in this case).... |
This is now: Actually came across this in a 2nd situation, which proved aways easier to reproduce. Rust's macros (including popular library ones) are perfectly capable of generating these long functions. So, this recreates it: Thanks for checking this out. Let me know if there's anything I can do to close. |
As discussed in the rust-lang issue linked above, this has come back around to dsymutil. labath called it: dsymutil crashed, leaving behind an invalid dSYM. The debug info emitted by Rust DW_TAG_lexical_block DIEs nested almost 900 deep. dsymutil crashes by running out of stack space after around 720 recursive calls to analyzeContextInfo(). To reproduce on macOS:
One simple fix is to increase the stack size. dsymutil runs this code on worker threads with default stack size, which on macOS is only 512 KB. A more robust fix would be to process DIEs without recursive calls. That would be a more difficult change. It also might be ultimately ineffective: it might simply delay the crash until similar recursive code inside the debugger. (A larger discussion: how should Rust represent its variable scopes in debug info? Deeply nested DW_TAG_lexical_block is probably not it.) |
What is running dsymutil? Is it the rust compiler? Sounds like something should at least be better at surfacing the fact that this step did not complete successfully.
Ouch.
We have utilities in llvm to create threads with larger stack space, so this can be increased. That said, 900 is quite a lot, and may end up taxing a lot of other components too...
What do you mean by variables scopes, exactly? Is it for variables that get declared in the middle of a block? I.e., The semantics are not exactly the same ("variable does not exist" vs. "variable exists but we don't know where it is"), but it's close enough for most purposes. |
https://github.com/rust-lang/rust/blob/c9f15013e0edc80989bf40b358bcefee14be5050/src/librustc_trans/debuginfo/create_scope_map.rs#L246 (followed by an example of undesirable gdb behavior without the additional lexical_blocks) Having said that, in my own tests I have seen rustc emit nested lexical_blocks even when the variables don't shadow anything, so there may be a rustc bug to improve here. The DwDemo code actually is a single variable name recycled 900 times; it looks something like this: DW_AT_start_scope should be perfect for Rust, someday. (I had assumed that it could only specify the variable's start location with the end location extending to the rest of the lexical_block, but on closer inspection it also allows discontiguous ranges.) Debuggers would need to correctly handle multiple variables with the same name but non-overlapping locations within a single lexical_block. |
Turns out the rustc implementation I was looking at was years out of date. After a 2016 rewrite rustc now adds a lexical_block even if the new variables don't shadow any old variables. Maybe that can be improved. |
Convert analyzeContextInfo to a work list: https://reviews.llvm.org/D90873 |
Yea, I can see how multiple variables with the same name can be confusing. It sounds like it would be better if the rust compiler avoided creating these where it doesn't need to. Unless, that is, there is something about rust syntax (which I know nearly nothing about) that actually makes creating a lexical block for each new variable actually the right thing to do. Though it that case, I suspect you may run into other components which behave suboptimally with this kind of input. |
Extended Description
Following up on an issue originally reported to the VsCode plug-in CodeLLDB:
vadimcn/codelldb#369
Both the author and I reached the conclusion this comes back to LLDB.
Discovered upon porting an existing (long, ~5k LOC) C function into Rust. With this code in place, breakpoints are not resolved:
This is despite debug info being present:
And confirming this is not an issue with the IDE plug-in, setting the same breakpoints via LLDB command also fails:
All of this is on MacOS, using the stable Rust compiler and LLDB 11.
First time bug-filer here, please let me know what info will help.
The text was updated successfully, but these errors were encountered: