Skip to content

Add lldb-repr command for tests/debuginfo#158298

Draft
Walnut356 wants to merge 5 commits into
rust-lang:mainfrom
Walnut356:di_compiletest
Draft

Add lldb-repr command for tests/debuginfo#158298
Walnut356 wants to merge 5 commits into
rust-lang:mainfrom
Walnut356:di_compiletest

Conversation

@Walnut356

Copy link
Copy Markdown
Contributor

Very much so a work in progress, but there's a bunch of stuff that probably needs discussing, so I figured I'd start that up now.

To recap, the control flow is as follows:

  1. lldb-repr is automatically split into, essentially lldb-command:repr var + lldb-check:var: Ok
  2. the relevant target, bless state, paths, etc. are passed to the LLDB command via env vars
  3. The lldb command runs lldb_batchmode.main()
  4. the input commands are executed line by line.
  5. If the command is a repr pseudo-command, it is intercepted and passed to the checking logic
    5a. if blessing, INPUT_DATA is blank. Each check inserts the appropriate var into INPUT_DATA, and then runs the checking logic against INPUT_DATA as normal (for sanity reasons)
    5b. the checking logic checks the variable against INPUT_DATA (<-- this is incomplete atm, see below for what still isn't finished) and prints any mismatches that occur.
  6. Once all commands have been run (or if a quit/exit command is encountered) lldb_batchmode checks 1. have we seen every type that exists in the input data? 2. have we seen every variable that exists in the input data? If not, it reports what was missing and exits with an error code.
    6a. If --bless, and no errors occurred, and at least 1 repr pseudo-command was processed, INPUT_DATA is serialized and written to the input data file.

To preemptively answer the question "When blessing, why not just build a second TargetData instance and compare INPUT_DATA to that?" - the goal of diffing in python (rather than rust) is to still have access to the underlying LLDB objects for error reporting purposes.

Sample Output (`basic-types.rs`) The input data was manually tampered with to force errors (`char32_t` size set to 1, double type renamed to `half`, `int` type deleted)
error: Error while running LLDB
status: exit status: 1
... # skipping to repr output for brevity
repr b
b: Ok
repr i
i: Ok
repr c
  [repr error: type 'char32_t'] size does not match.
    Expected: '1'
    Got: '4'
repr i8
i8: Ok
repr i16
i16: Ok
repr i32
i32: Ok
repr i64
i64: Ok
repr u
u: Ok
repr u8
u8: Ok
repr u16
u16: Ok
repr u32
  [repr error: type 'unsigned int'] type not found in input data
repr u64
u64: Ok
repr f32
f32: Ok
repr f64
  [repr error: type 'double'] type not found in input data
[repr error] The following types were expected, but were not tested:
  {'half'}
Sample Output (`simple-struct.rs`) The input data was manually tampered with to force errors.
  • simple_struct::NoPadding64 field name y to q
  • simple_struct::NoPadding163264 last field moved to first position
  • simple_struct::InternalPadding y field deleted
  • simple_struct::PaddingAtEnd q field added

Keep in mind that I edited the expected data, not the actual structs in the test file, so the output reports the opposite of the changes i made (sortof) i.e. it reports that q was deleted because it exists in the expected data but not in the LLDB object.

repr no_padding16
no_padding16: Ok
repr no_padding32
no_padding32: Ok
repr no_padding64
  [repr error: type 'simple_struct::NoPadding64'] The following field(s) appear to have been renamed. If this is expected,
  consider rerunning with the `--bless` option: 
    ['q -> y']
repr no_padding163264
  [repr error: type 'simple_struct::NoPadding163264'] Field(s) appear to have been rearranged. If this was expected, try re-running with the `--bless` option
    Expected:
[     Field(name='a', type='short', offset=12),
      Field(name='b', type='unsigned short', offset=14),
      Field(name='c', type='int', offset=8),
      Field(name='d', type='unsigned long', offset=0)]
    Got:
[     Field(name='d', type='unsigned long', offset=0),
      Field(name='a', type='short', offset=12),
      Field(name='b', type='unsigned short', offset=14),
      Field(name='c', type='int', offset=8)]
repr internal_padding
  [repr error: type 'simple_struct::InternalPadding'] The following field(s) appear to have been added to the type:
    {Field(name='y', type='long', offset=0)}
repr padding_at_end
  [repr error: type 'simple_struct::PaddingAtEnd'] The following field(s) appear to have been removed from the type:
    {Field(name='q', type='float', offset=12)}
[repr error] The following types were expected, but were not tested:
  {'double', 'long', 'unsigned long'}

The errors are of the form [repr error <error source>] <error info>. The errors are slightly indented to make it easier to scan and associate errors with their source. The formatting is 1st draft and largely abstracted away via these functions. We can pretty trivially change how they're formatted by modifying/replacing these functions.

Also, each type in a test is only tested once per test, regardless of how many variables/fields reference it. When a type is seen a second time, if the prior check was a mismatch, it reports that the type does not match and does not repeat the specific error messages of the mismatch. Instead, it directs people to look at the original type error further up in the output.

TODO

  • Variable child mismatches don't have error reporting
  • Rearrange the checks a bit so the type check happens midway through the variable check. Some of the variable's information is useful for the type's error reporting and vice versa.
  • use some info from lldb_providers and the original SBValue and SBType to improve error messages
  • Some sort of warning if the python/lldb version and/or feature flags don't match
  • A few more tests with input data to help verify behavior (one with generics, one with a synthetic/summary provider, probably need to enforce a formatter for u8/i8 at some point to test that too).
  • Various improvements to the error message wording/information/formatting/consistency.
  • Probably some other stuff i'm forgetting about that I'll add in later

r? @jieyouxu, @Kobzol

@rustbot rustbot added A-compiletest Area: The compiletest test runner A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-compiletest Area: The compiletest test runner A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants