Skip to content
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

Ignore unfetchable registers #421

Open
4 tasks done
chenzhiy2001 opened this issue Apr 5, 2024 · 8 comments · May be fixed by #444
Open
4 tasks done

Ignore unfetchable registers #421

chenzhiy2001 opened this issue Apr 5, 2024 · 8 comments · May be fixed by #444

Comments

@chenzhiy2001
Copy link

chenzhiy2001 commented Apr 5, 2024

  • If you are using gdb
    • gdb --version >= 7.7.1
    • it works on the command line with gdb
    • cwd and target are properly set

Sometimes a register is listed in GDB but its value is actually not fetchable even using command line gdb (I guess it's a bug of Qemu's GDBStub) . I think in this case, that specific register, rather than the whole register list, should be ignored.

In my case it's the "pmpcfg1" register that caused the issue.

The error message says: Could not expand variable: Could not fetch register "pmpcfg1"; remote failure reply 'E14' (from data-list-register-values N)

image

@GitMensch
Copy link
Collaborator

I think in this case, that specific register, rather than the whole register list, should be ignored.

I agree - but we currently get the value of all registers (which also provide us with the names) using data-list-register-values).
But looking at the docs there is an option --skip-unavailable.

Please recheck with plain GDB:
interpreter-exec mi2 "-data-list-register-values N" results in an error interpreter-exec mi2 "-data-list-register-values --skip-unavailable N" works.

If this is the case I can create a PR to include that.

@chenzhiy2001
Copy link
Author

chenzhiy2001 commented Apr 5, 2024

Please recheck with plain GDB:
interpreter-exec mi2 "-data-list-register-values N" results in an error interpreter-exec mi2 "-data-list-register-values --skip-unavailable N" works.

They all result in the same error, how weird. Looks like GDB think that pmpcfg1 is avaliable, which is wrong because pmpcfg1 is specified as "RV32 only" in the RISC-V document (I am debugging an RV64 OS running in qemu-system-riscv64).

Could not fetch register "pmpcfg1"; remote failure reply 'E14' (from data-list-register-values N)
Could not fetch register "pmpcfg1"; remote failure reply 'E14' (from data-list-register-values --skip-unavailable N)

However, this works:

-data-list-register-values N 0 1 2 3 4 5 6 7 

GDB -> App: {
  "token": 86,
  "outOfBandRecord": "[]",
  "resultRecords": {
    "resultClass": "done",
    "results": "[["register-values",[[["number","0"],["value","0"]],[["number","1"],["value","0x8026bdb0 <os::rust_main+528>"]],[["number","2"],["value","0x8035ce70"]],[["number","3"],["value","0x0"]],[["number","4"],["value","0x0"]],[["number","5"],["value","4"]],[["number","6"],["value","2150024030"]],[["number","7"],["value","48"]]]]]"
  }
}

In short, --skip-unavailable won't work due to GDB or QEMU bugs. I thought of some workarounds like adding a "register whitelist" configuration in launch.json but that'll require a lot of extra work. Haven't thought of any simple and elegant solutions yet.

Currently I just changed the line in getRegisterValues() from

const result = await this.sendCommand("data-list-register-values N");

to:

const result = await this.sendCommand("data-list-register-values N 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32");

so at least I can see "regular" risc-v registers.

@GitMensch
Copy link
Collaborator

In short, --skip-unavailable won't work due to GDB or QEMU bugs.

Please double check for a recent GDB, if you have the error there as well report this to GDB buglist.

@GitMensch
Copy link
Collaborator

I thought of some workarounds like adding a "register whitelist" configuration in launch.json but that'll require a lot of extra work.

Hm, would this be more than a single configuration of type string registerLimit or similar? If set then this goes onto the request as-is, otherwise we don't set the limit.

@chenzhiy2001
Copy link
Author

chenzhiy2001 commented Apr 7, 2024

Please double check for a recent GDB, if you have the error there as well report this to GDB buglist.

Upgraded GDB from v12.1 to the newest commit which is still v12.1 and the result is sadly the same. After some search I found that it’s actually QEMU’s fault, rather than GDB’s.

I’m using QEMU 7.0 and the changelog of QEMU 8.0 says they solved the problems related with CSRs including pmpcfg1:

Fixes to gdbstub, CSR accesses, dependencies between the various floating-point exceptions, and XTheadMemPair

I will test that newer version but that requires some time because my QEMU 7.0 has custom patches that enables extra serial ports. In order to let my guest OS running on QEMU 8.0 I have to do the same patch again.

@chenzhiy2001
Copy link
Author

Hm, would this be more than a single configuration of type string registerLimit or similar? If set then this goes onto the request as-is, otherwise we don't set the limit.

I think registerLimit will suffice in most situations since those special registers that caused the trouble are usually placed after the common registers.

If the user wants to watch a fetchable register exceeding registerLimit, he can use custom expressions.

@GitMensch
Copy link
Collaborator

Can you send your QEMU patches upstream for inclusion? Any ETA when your QEMU 8 Test is finished (I think for a plain first test the upstream version would work, no)?

Nonetheless a registerLimit config option of type string - if set then added verbatim to that line

const result = await this.sendCommand("data-list-register-values N");

seems useful some people may only want a handful registers in any case) - could you try adding that and providing a PR for that?

@chenzhiy2001
Copy link
Author

chenzhiy2001 commented Sep 18, 2024

Sorry for the long wait, I have time doing this just recently.

Can you send your QEMU patches upstream for inclusion?

The newest QEMU source code has changed a variable used in the patch (the variable was MachineState *mc in the patch, but MachineState *ms in the latest QEMU code) and I don't know if QEMU devs have changed anything other than the name itself, so I'm not sure whether the patch would work for the newest QEMU code even if I replace all mcs with mss. The QEMU 8.0.5 code has the same problem.

So I gave up patching newer QEMU and uploaded the patch to Github gist for those who is curious about this patch.

Any ETA when your QEMU 8 Test is finished (I think for a plain first test the upstream version would work, no)?

The hobby OS I debugged don't boot on QEMU 8 so I use xv6-labs-2023 to test our issue instead.

When using my patched QEMU 7.0.0, The error is identical with my first post. Since my patch don't interfere with GDBStub, I think plain QEMU 7.0.0 will produce the same result.

When using plain QEMU 8.0.5, all registers including CSRs show up without any problem.

So my assumption is being proven: QEMU 7.0.0's gdbstub is problematic and QEMU 8.0.5 fixed it. It's not the VSCode Plugin's fault.

Nonetheless a registerLimit config option of type string - if set then added verbatim to that line seems useful, some people may only want a handful registers in any case) - could you try adding that and providing a PR for that?

Sure, see #444

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants