WebFreak001 / code-debug

Native debugging for VSCode
The Unlicense
410 stars 115 forks source link

Ignore unfetchable registers #421

Closed chenzhiy2001 closed 2 months ago

chenzhiy2001 commented 7 months ago

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 commented 7 months ago

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 commented 7 months ago

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 commented 7 months ago

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 commented 7 months ago

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 commented 7 months ago

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 commented 7 months ago

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 commented 2 months ago

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 commented 2 months ago

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