Add gdb-repr directive for tests/debuginfo - #160377
Conversation
|
|
| class ReprCommand(gdb.Command): | ||
| def __init__(self): | ||
| super().__init__("repr", gdb.COMMAND_OBSCURE) | ||
|
|
||
| def invoke(self, argument: str, from_tty: bool): | ||
| print(f"(gdb) repr {argument}") | ||
|
|
||
| global REPR_COMMAND_RUN | ||
| REPR_COMMAND_RUN = True | ||
| try: | ||
| if check(argument) == Result.Mismatch: | ||
| global REPR_ERROR | ||
| REPR_ERROR = True | ||
| except Exception as e: | ||
| import sys | ||
| import traceback | ||
|
|
||
| traceback.print_exception(type(e), e, e.__traceback__, file=sys.stdout) | ||
| gdb.execute("exit 1") | ||
|
|
||
|
|
||
| ReprCommand() | ||
|
|
||
|
|
||
| class ReprFinalize(gdb.Command): | ||
| def __init__(self): | ||
| super().__init__("repr_finalize", gdb.COMMAND_OBSCURE) | ||
|
|
||
| def invoke(self, argument: str, from_tty: bool): | ||
| if not REPR_COMMAND_RUN: | ||
| return | ||
|
|
||
| if not tested_all_variables() or not tested_all_types(): | ||
| gdb.execute("exit 1") | ||
|
|
||
| if BLESS and not REPR_ERROR: | ||
| gdb_version = gdb.execute("show version", to_string=True).splitlines()[0] | ||
| metadata = BlessMetadata(sys.version, gdb_version) | ||
| INPUT_DATA.save_blessing(metadata) | ||
|
|
||
|
|
||
| ReprFinalize() |
There was a problem hiding this comment.
Here's where we create and register the custom CLI commands.
| TYPES_TESTED: dict[str, Result] = {} | ||
| """Since types are unique and unchanging, we only need to test each type once. This also helps | ||
| ensure we have tested all types in `INPUT_DATA` | ||
| """ | ||
|
|
||
|
|
||
| VARS_TESTED: list[dict[str, Result]] = [] | ||
| """Used to help ensure all expected variables were tested. Each element of the list corresponds to a | ||
| breakpoint, and contains a set of all of the variable names tested for that breakpoint.""" | ||
|
|
||
|
|
||
| def tested_all_types() -> bool: | ||
| """Returns true if all types in INPUT_DATA were tested this run.""" | ||
|
|
||
| expected_types = set(INPUT_DATA.types) | ||
| untested_types = expected_types.difference(TYPES_TESTED.keys()) | ||
|
|
||
| if len(untested_types) != 0: | ||
| print( | ||
| f"{ANSI_RED}[repr error]{ANSI_END} The following types were expected, but were not \ | ||
| tested:\n {untested_types}" | ||
| ) | ||
|
|
||
| return len(untested_types) == 0 | ||
|
|
||
|
|
||
| def tested_all_variables() -> bool: | ||
| expected_vars = [set(vars) for vars in INPUT_DATA.breakpoints] | ||
| untested_vars = [ | ||
| expected.difference(tested.keys()) | ||
| for expected, tested in zip(expected_vars, VARS_TESTED) | ||
| ] | ||
|
|
||
| tested_not_expected = [ | ||
| set(tested.keys()).difference(expected) | ||
| for expected, tested in zip(expected_vars, VARS_TESTED) | ||
| ] | ||
|
|
||
| result = True | ||
|
|
||
| for i, v in enumerate(untested_vars): | ||
| if len(v) == 0: | ||
| continue | ||
|
|
||
| result = False | ||
| print( | ||
| f"{ANSI_RED}[repr error]{ANSI_END} The following variables were expected at \ | ||
| breakpoint#{i}, but were not tested:\n {v}" | ||
| ) | ||
|
|
||
| for i, v in enumerate(tested_not_expected): | ||
| if len(v) == 0: | ||
| continue | ||
|
|
||
| result = False | ||
| print( | ||
| f"{ANSI_RED}[repr error]{ANSI_END} The following variables were tested, but do not \ | ||
| exist in the input data at breakpoint#{i}:\n {v}" | ||
| ) | ||
|
|
||
| return result |
There was a problem hiding this comment.
These were just moved from check_lldb.py.
I might be able to factor more of the checking logic out and share it between lldb and gdb. There are less differences for their API than I was expecting. It would probably require passing a few wrappers to the check function that abstract away the debugger-specific accesses, but we'll see.
| gdb.args(debugger_opts).env("PYTHONPATH", pythonpath); | ||
| gdb.args(debugger_opts) | ||
| .env("PYTHONPATH", pythonpath) | ||
| .env("BATCHMODE_DEBUGGER", "gdb") |
There was a problem hiding this comment.
The bike-shedding I mentioned more or less has to do with these env vars and the lldb_batchmode package. With GDB support, we'll probably want to re-name lldb_batchmode (and probably rename runner.py to lldb_batchmode.py), but I'm not super happy with any of the names that came to mind. Maybe just batchmode?
There was a problem hiding this comment.
Batchmode sounds really opaque. I would suggest BATCHMODE => DEBUGGER_TESTER, or something like that.
This comment has been minimized.
This comment has been minimized.
|
Oh yeah, i need to gate it so it doesn't check for the file path until a |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
77e4567 to
170c054
Compare
|
There's probably more I can refactor to share more code between LLDB and GDB, but for now it should be good enough. |
|
Some changes occurred in src/tools/compiletest cc @jieyouxu
|
There was a problem hiding this comment.
It looks like a non-trivial amount of code is shared with LLDB, that's good! Left some comments.
I tried it locally with GDB 15.1, and it failed with the following:
compiletest output
failures:
---- [debuginfo-gdb] tests/debuginfo/basic-types/main.rs stdout ----
NOTE: compiletest thinks it is using GDB version 15001000
------gdb stdout------------------------------
GNU gdb (Ubuntu 15.1-1ubuntu1~24.04.1) 15.1
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
To enable execution of this file add
add-auto-load-safe-path /projects/personal/rust/rust/src/etc/gdb_load_rust_pretty_printers.py
line to your configuration file "/home/kobzol/.config/gdb/gdbinit".
To completely disable this security protection add
set auto-load safe-path /
line to your configuration file "/home/kobzol/.config/gdb/gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual. E.g., run from the shell:
info "(gdb)Auto-loading safe path"
Breakpoint 1 at 0x1a81: file tests/debuginfo/basic-types/main.rs, line 112.
This GDB supports auto-downloading debuginfo from the following URLs:
<https://debuginfod.ubuntu.com>
Enable debuginfod for this session? (y or [n]) [answered N; input not from terminal]
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, main::main () at tests/debuginfo/basic-types/main.rs:112
112 _zzz(); // #break
------gdb stderr------------------------------
warning: File "/projects/personal/rust/rust/src/etc/gdb_load_rust_pretty_printers.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
Python Exception <class 'RuntimeError'>: pretty-printer already registered: builtin
/projects/personal/rust/rust/build/x86_64-unknown-linux-gnu/test/debuginfo/basic-types/main.gdb/main.debugger.script:10: Error in sourced command file:
Error occurred in Python: pretty-printer already registered: builtin
------------------------------------------
error: gdb failed to execute
status: exit status: 1
command: BATCHMODE_DEBUGGER="gdb" LLDB_BATCHMODE_BLESS_TEST_DATA="0" LLDB_BATCHMODE_INPUT_DATA_PATH="/projects/personal/rust/rust/tests/debuginfo/basic-types/gdb_input/non_windows.json" LLDB_BATCHMODE_TARGET_TRIPLE="x86_64-unknown-linux-gnu" PYTHONPATH="/projects/personal/rust/rust/src/etc" "gdb" "-quiet" "-batch" "-nx" "-command=/projects/personal/rust/rust/build/x86_64-unknown-linux-gnu/test/debuginfo/basic-types/main.gdb/main.debugger.script"
--- stdout -------------------------------
GNU gdb (Ubuntu 15.1-1ubuntu1~24.04.1) 15.1
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
To enable execution of this file add
add-auto-load-safe-path /projects/personal/rust/rust/src/etc/gdb_load_rust_pretty_printers.py
line to your configuration file "/home/kobzol/.config/gdb/gdbinit".
To completely disable this security protection add
set auto-load safe-path /
line to your configuration file "/home/kobzol/.config/gdb/gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual. E.g., run from the shell:
info "(gdb)Auto-loading safe path"
Breakpoint 1 at 0x1a81: file tests/debuginfo/basic-types/main.rs, line 112.
This GDB supports auto-downloading debuginfo from the following URLs:
<https://debuginfod.ubuntu.com>
Enable debuginfod for this session? (y or [n]) [answered N; input not from terminal]
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, main::main () at tests/debuginfo/basic-types/main.rs:112
112 _zzz(); // #break
------------------------------------------
--- stderr -------------------------------
warning: File "/projects/personal/rust/rust/src/etc/gdb_load_rust_pretty_printers.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
Python Exception <class 'RuntimeError'>: pretty-printer already registered: builtin
/projects/personal/rust/rust/build/x86_64-unknown-linux-gnu/test/debuginfo/basic-types/main.gdb/main.debugger.script:10: Error in sourced command file:
Error occurred in Python: pretty-printer already registered: builtin
------------------------------------------
---- [debuginfo-gdb] tests/debuginfo/basic-types/main.rs stdout end ----
failures:
[debuginfo-gdb] tests/debuginfo/basic-types/main.rs
| summary_ok | ||
| & synthetic_ok | ||
| & format_ok | ||
| & pretty_type_name_ok | ||
| & pretty_print_ok, |
There was a problem hiding this comment.
| summary_ok | |
| & synthetic_ok | |
| & format_ok | |
| & pretty_type_name_ok | |
| & pretty_print_ok, | |
| summary_ok | |
| and synthetic_ok | |
| and format_ok | |
| and pretty_type_name_ok | |
| and pretty_print_ok, |
| gdb.args(debugger_opts).env("PYTHONPATH", pythonpath); | ||
| gdb.args(debugger_opts) | ||
| .env("PYTHONPATH", pythonpath) | ||
| .env("BATCHMODE_DEBUGGER", "gdb") |
There was a problem hiding this comment.
Batchmode sounds really opaque. I would suggest BATCHMODE => DEBUGGER_TESTER, or something like that.
Hmmm. I don't have super easy access to gdb 15 atm, but my best guess is it's a bug with importing GDB twice in the same script? OTOH it seems like CI runs gdb 16.3 anyway, so we should be able to just |
|
Some changes occurred in tests/debuginfo/basic-stepping.rs cc @Enselic |
This comment has been minimized.
This comment has been minimized.
|
@bors try jobs=x86_64-gnu |
This comment has been minimized.
This comment has been minimized.
Add `gdb-repr` directive for `tests/debuginfo` try-job: x86_64-gnu
|
(just adding the |
There was a problem hiding this comment.
Thank you, the restructuralization looks good to me. I'll let @jieyouxu take a look too.
|
(Out today but have time tmrw) |
Rerun `tests/debuginfo` tests if repr data has changed Resolves rust-lang#161138 This also includes the necessary checking for GDB's data even though none exists atm (rust-lang#160377 will contain the first set). The extra handling doesn't hurt anything since we have to account for all the other tests that don't have repr data anyway. In a followup, I can rename the `lldb_input` directory to something else (see: rust-lang#160137 (comment)). Doing so requires me to touch a bunch of other places where the name is used, so it should probably be it's own PR. Making sure the tests rerun when the data changes is higher priority though atm. r? @jieyouxu , @Kobzol cc @Mark-Simulacrum
Rerun `tests/debuginfo` tests if repr data has changed Resolves rust-lang#161138 This also includes the necessary checking for GDB's data even though none exists atm (rust-lang#160377 will contain the first set). The extra handling doesn't hurt anything since we have to account for all the other tests that don't have repr data anyway. In a followup, I can rename the `lldb_input` directory to something else (see: rust-lang#160137 (comment)). Doing so requires me to touch a bunch of other places where the name is used, so it should probably be it's own PR. Making sure the tests rerun when the data changes is higher priority though atm. r? @jieyouxu , @Kobzol cc @Mark-Simulacrum
Rollup merge of #161967 - Walnut356:stamp_repr_data, r=jieyouxu Rerun `tests/debuginfo` tests if repr data has changed Resolves #161138 This also includes the necessary checking for GDB's data even though none exists atm (#160377 will contain the first set). The extra handling doesn't hurt anything since we have to account for all the other tests that don't have repr data anyway. In a followup, I can rename the `lldb_input` directory to something else (see: #160137 (comment)). Doing so requires me to touch a bunch of other places where the name is used, so it should probably be it's own PR. Making sure the tests rerun when the data changes is higher priority though atm. r? @jieyouxu , @Kobzol cc @Mark-Simulacrum
This comment has been minimized.
This comment has been minimized.
8c0ba6e to
3f61874
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
This comment has been minimized.
This comment has been minimized.
3f61874 to
7a8852b
Compare
View all comments
Part of #148483 and followup to #158298. Applies (approximately) identical logic to GDB.
I still need to test things on
windows-gnu(and locally try a few more tests to see if there's any glaring issues). There's also a few bike-sheddy things.The main way this differs from the LLDB implementation is that GDB doesn't use
lldb_batchmode/runner.pyto orchestrate the commands. Instead, I havecompiletestimportfrom_gdb.pywhich registers a customreprCLI command. GDB's batch processing works as normal, but dispatches to our logic automatically whenever it encountersrepr <var_name>.An additional
repr-finalizeCLI command is also registered to implement the checks that ensure we encountered all expected types/vars, and verifies that there were no errors before saving blessed data.r? @Kobzol, @jieyouxu