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
add .debug_line support and integrate it with incremental compilation #5963
Comments
* the .debug_line header is written properly * link.File.Elf gains: - SrcFn, which is now a field in Module.Fn - SrcFile, which is now a field in Module.Scope.File * link.File.Elf gets a whole *Package field rather than only root_src_dir_path. * the fields first_dbg_line_file and last_dbg_line_file tell where the Line Number Program begins and ends, which alows moving files when the header gets too big, and allows appending files to the end. * codegen is passed a buffer for emitting .debug_line Line Number Program opcodes for functions. See #5963 There is some work-in-progress code here, but I need to go make some experimental changes to changing how to represent source locations and I want to do that in a separate commit.
* the .debug_line header is written properly * link.File.Elf gains: - SrcFn, which is now a field in Module.Fn - SrcFile, which is now a field in Module.Scope.File * link.File.Elf gets a whole *Package field rather than only root_src_dir_path. * the fields first_dbg_line_file and last_dbg_line_file tell where the Line Number Program begins and ends, which alows moving files when the header gets too big, and allows appending files to the end. * codegen is passed a buffer for emitting .debug_line Line Number Program opcodes for functions. See #5963 There is some work-in-progress code here, but I need to go make some experimental changes to changing how to represent source locations and I want to do that in a separate commit.
We're going to have to adjust this based on the fact that it's a common bug in debugging tooling to not properly handle extended opcodes in the vendor-speciifc range. Thanks to Tom de Vries this is now fixed in GDB, however it will take several years before this fix is widely available, and this bug is apparently also present in lldb. That leaves us the 2-byte NOPs as the only way to pad the program, which represents a serious performance cost, especially when building a compilation for the first time. Every time a function is compiled, it would mean moving all those NOPs and the other functions in the file to make room for the new function to be inserted into sorted order. So here's the new plan forward. It's simpler.
Now it's only functions we have to care about, not files, and they can be in any order. The tradeoff here is that when a file is modified, all functions in the file that have their line numbers shifted must get their I filed a DWARF specification proposal to add DW_LNS_jmp. If that proposal is accepted, then this can be improved, however, it is now my belief that unless that happens, the above scheme is the best way to do incremental compilation with line numbers. |
Landed in 952a397 |
@andrewrk I am handling the dwarf proposal that you submitted. Would it be possible for you to provide some examples of how this new opcode will be used and what problem will it solve. |
@abidh ah thank you for reminding me. I just remembered that I didn't reply to your email yet, I will do that this week. |
Zig self-hosted .debug_line layout (DWARF v5)
Strategy
The header is treated as a separate component that can be written without modifying the line number
program for the files. It becomes "dirty" and rewritten when the size of the global line number program
for the compilation unit changes, or when any directories or files are modified. If it grows so
much that it fills all the padding, then any overlapped files are moved to the end.
A two-byte NOP can be represented as {DW_LNS_negate_stmt, DW_LNS_negate_stmt}.
Each file is treated as a separate component that can be moved within the global line number program.
When a file is moved, no modifications need to be made to the line number program. A file becomes
"dirty" when its file index is changed. It is not planned to support moving file indexes, and so
it is not planned for a file to ever get dirty.
Each function is treated as a separate component that can be moved within the file.
However, the order of functions within a file must match the order of functions within the source
file, because the line offsets are intentionally relative to the previous function, so that when
incrementally compiling a function, only one line number offset needs to be modified.
During incremental compilation, functions are sometimes relocated to a different virtual address.
When this happens, the DW_LNE_set_address instruction is updated with the new
virtual address of the function. The rest of the program is unmodified.
During incremental compilation, new lines of code are sometimes added to a function.
When this happens, the machine code and debug info for the function will be re-generated,
and the DW_LNS_advance_line in the prologue, which is relative to the previous function's line end,
will be updated to be correct. This will cause the following functions in the file to have correct
line number information without being updated.
During incremental compilation, blank lines are sometimes added between functions, without any modifications to the function bodies. When this happens, the function following the added whitespace has its prologue DW_LNS_advance_line value updated to make up the difference. This is a single-byte write to the ELF file. The rest of the line number program remains unchanged.
The text was updated successfully, but these errors were encountered: