-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Experimental debugger API #9604
base: master
Are you sure you want to change the base?
Conversation
We add a new erl_debugger module to the kernel application, that will provides an API for writing debuggers. Here we set up the general interface, with a stub for "setting a breakpoint" as the only debugging primitive. In the next commits we first implement the "breakpoint" primitive, and later add additional ones. About the general design: - A node needs to have debugging support enabled on startup with the `+D` option and this can't be enabled afterwards. This gives admins a way to prevent processes from blocking on prod due to an accidental debugger usage, etc. - Debugging primitives based on code instrumentation can be individually enabled/disabled, etc. - A debugger is an Erlang process; there can be at most one debugger process per node. - The system will communicate with the debugger process via `debugger_events` messages. For now we introduce only one message for notifying that a process hit a breakpoint
On module loading, `debug_line` are currently ignored. Now, when debugger support is enabled (and the line-breakpoint instrumentation enabled), we emit a `i_debug_line` instruction. For now, we only use it to add entries to the line-table, the actual breakpoint instrumentation is introduced next.
The logic was duplicated and out of sync. We want to add another internal function for dealing with breakpoints, so better to have all in one place
We add trampolines on each debug_line instruction, similar to the ones used on function entry. The main difference is that we need to save all live X-registers on the stack before calling `erts_internal:breakpoint/4`, and thus may require a GC.
We want to reuse the logic currently use to flip beakpoints for tracing, etc. However, at the moment, the functions where this happens not only change the code, but also set some flags value that are specific to those cases.. We factor out this part of the code to their own functions. In doing so, we observe that for x86-64, the code was referring to `BEAM_ASM_FUNC_PROLOGUE_SIZE` to determine the offset to use when "disabling" a breakpoint that doesn't seem relevant. The value is indeed 6 (see, e.g., the assertion on the "enabling" case), and this corresponds to: - 1 byte for the NOP 0x90 due to call alignment - 1 byte for the opcode of a `CALL` - 4 bytes for the 32-bit offset of the call target
CT Test Results 4 files 201 suites 1h 55m 13s ⏱️ For more details on these failures, see this check. Results for commit 54a88a9. ♻️ This comment has been updated with latest results. To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass. See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally. Artifacts
// Erlang/OTP Github Action Bot |
This PR is the complement to #9334 (adding the
debug_line
instruction) and together with #8670 (pausing proc timers) add the support on the VM that drives the new edb debugger.These are main parts of the PR:
A new
+D
emulator flag is added. When given, the VM becomes "debuggable", which means that when modules are loaded, thedebug_line
instruction is instrumented similar to what is currently done for tracing-breakpoints, so that one can enable and disable breakpoints on that particular lines.An experimental
erl_debugger
module is added, with a new debugging API. Essentially, it allows a single, local, process to be registered as the "debugger" process for the node. This process is the one that will receive messages notifying that a process hit a breakpoint. This way, we can decouple debugger implementations that consume this API (like edb) from OTP itself.The
erl_debugger
module also exposes new BIFs to inspect X and Y registers of a suspended process. Together with the new code-information BIFs added in Add support for debug information for a native debugger #9334, this let's a debugger show the values of variables in scope for a suspended process.