================
@@ -274,23 +295,31 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const
RegisterInfo *reg_info) {
success = false;
else {
// Read the containing register if it hasn't already been read
- if (!GetRegisterIsValid(prim_reg))
+ if (GetRegisterIsUnfetched(prim_reg))
success = GetPrimordialRegister(prim_reg_info, gdb_comm);
----------------
jasonmolenda wrote:
Just working through this in my head a little bit. We have two places where we
decide what to do with a successfully read register (all bytes provided), a
failed read (no bytes) or a partial read (fewer bytes than needed) --
`PrivateSetRegisterValue` for an actual register ("primordial") and then in
`ReadRegisterBytes` for a "slice" register (slice "w0" in the primordial x0 on
AArch64, slice "eax" in the primordial rax on x86_64) where we need to read one
or more primordial registers, and behave the same as `PrivateSetRegisterValue`
based on the results of all primordials.
FTR when a register is a slice register ("w0"), it has one or more
`RegisterInfo::value_regs` which are the primordial registers ("x0") that have
the actual bytes. I don't think there's any target which has a slice register
that spans multiple real (primordial) registers, but shrug the capability
exists.
`PrivateSetRegisterValue` returns `true` if the full number of bytes needed for
a register are provided. If an insufficient number of bytes is provided, the
register is marked as `Unfetched` so we will try to read it again. `false` is
returned if 0 bytes, or an insufficient number of bytes, were provided.
(I'm not convinced about marking a fewer-than-needed bytes as `Unfetched` -
we'll surely get the same result again if the user tries to read the register a
second time. But from a perf point of view, I don't care if we try to read it
again, it's one packet. And this preserves the current lldb behavior, before
my PR)
In `ReadRegisterBytes` we try to read all primordial registers (`value_regs`)
that provide the bytes for the register. We return `success=true` if we have a
RegisterInfo for all value_regs listed (primordial registers), we have the data
or we were able to read the data. If there was a value_reg we don't have a
RegisterInfo for, or we can't get the lldb reg number for it, we return
`success=false`. If `GetRegisterIsUnavailable(prim_reg)` -- that is, we tried
to read the register at this stop previously, and could not, then we return
`success=false`.
I think this last behavior - if a register is marked as `Unavailable`, then we
tried to read it earlier, and it was expedited as not available - is a
reasonable one.
For each primordial register that is Unfetched, and not marked as Unavailable,
we do
```
// Read the containing register if it hasn't already been read
if (GetRegisterIsUnfetched(prim_reg))
success = GetPrimordialRegister(prim_reg_info, gdb_comm);
```
and if `success==false`, that exits our loop and we do
```
if (success) {
// If we reach this point, all primordial register requests have
// succeeded. Validate this composite register.
SetRegisterIsValid(reg_info);
} else {
SetRegisterIsUnavailable(reg_info);
}
```
and here we see my preference expressed in the code - if we failed to read all
the bytes for one of the registers, we mark this slice register as Unavailable.
You are right that the primordial register `PrivateSetRegisterValue` will set
the primordial register to `Unfetched` if it got too few bytes, but I don't
think that's helping anything, it's assuming that re-reading a register will
get different results the second time, if the user tries to do it. It doesn't
seem that bad to mark the slice register Unavailable here, to me.
I'll think about this more, but I think if anything, I would more aggressively
mark a register as Unavailable (instead of `Unfetched`, meaning we can try
again) if we get a short data reply or such, in all the different places we do
this.
https://github.com/llvm/llvm-project/pull/193894
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits