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

LLDB compatibility: Send complete register definitions in target.xml #148

Open
danlehmann opened this issue Aug 6, 2024 · 3 comments
Open
Labels
gdbstub_arch Related to code in `gdbstub_arch` lldb-compat LLDB-specific protocol extension

Comments

@danlehmann
Copy link
Contributor

LLDB requires that the full list of registers is provided.

For example, for rv32, this string is currently returned:

fn target_description_xml() -> Option<&'static str> {
    Some(r#"<target version="1.0"><architecture>riscv:rv32</architecture></target>"#)
}

This works fine with gdb (it seems to be ignore the register list), but llvm cares. To fix it, I changed it to this:

<target version="1.0">
<architecture>riscv:rv32</architecture>
<feature name="org.gnu.gdb.riscv.cpu">
  <reg name="zero" bitsize="32" type="int" regnum="0"/>
  <reg name="ra" bitsize="32" type="code_ptr"/>
  <reg name="sp" bitsize="32" type="data_ptr"/>
  <reg name="gp" bitsize="32" type="data_ptr"/>
  <reg name="tp" bitsize="32" type="data_ptr"/>
  <reg name="t0" bitsize="32" type="int"/>
  <reg name="t1" bitsize="32" type="int"/>
  <reg name="t2" bitsize="32" type="int"/>
  <reg name="fp" bitsize="32" type="data_ptr"/>
  // remaining registers
</feature>
</architecture>

With that, lldb works out of the box; gdb is unaffected.

I think, lldb is actually within the spec to require this. See https://sourceware.org/gdb/current/onlinedocs/gdb.html/RISC_002dV-Features.html:

The ‘org.gnu.gdb.riscv.cpu’ feature is required for RISC-V targets. It should contain the registers ‘x0’ through ‘x31’, and ‘pc’. Either the architectural names (‘x0’, ‘x1’, etc) can be used, or the ABI names (‘zero’, ‘ra’, etc).

I'm working on a patch to address this.

@danlehmann
Copy link
Contributor Author

danlehmann commented Aug 6, 2024

To show the problem, this is the trace when connecting to the short target_description_xml in my risc-v 32 bit emulator:

 TRACE gdbstub::protocol::recv_packet > <-- +
 TRACE gdbstub::protocol::recv_packet > <-- $QStartNoAckMode#b0
 TRACE gdbstub::protocol::response_writer > --> $OK#9a
 TRACE gdbstub::protocol::recv_packet     > <-- +
 TRACE gdbstub::protocol::recv_packet     > <-- $qSupported:xmlRegisters=i386,arm,mips,arc;multiprocess+;fork-events+;vfork-events+#2e
 TRACE gdbstub::protocol::response_writer > --> $PacketSize=1000;vContSupported+;multiprocess+;QStartNoAckMode+;swbreak+;qXfer:features:read+#fd
 TRACE gdbstub::protocol::recv_packet     > <-- $QThreadSuffixSupported#e4
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("QThreadSuffixSupported")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $QListThreadsInStopReply#21
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("QListThreadsInStopReply")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $vCont?#49
 TRACE gdbstub::protocol::response_writer > --> $vCont;c;C;s;S#62
 TRACE gdbstub::protocol::recv_packet     > <-- $qVAttachOrWaitSupported#38
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qVAttachOrWaitSupported")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $QEnableErrorStrings#8c
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("QEnableErrorStrings")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qHostInfo#9b
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qHostInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qProcessInfo#dc
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qProcessInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qC#b4
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qC")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qfThreadInfo#bb
 TRACE gdbstub::protocol::response_writer > --> $mp01.01#cd
 TRACE gdbstub::protocol::recv_packet     > <-- $qsThreadInfo#c8
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $?#3f
 TRACE gdbstub::protocol::response_writer > --> $T05thread:p01.01;#06
 TRACE gdbstub::protocol::recv_packet     > <-- $qProcessInfo#dc
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qProcessInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:features:read:target.xml:0,fff#7d
 TRACE gdbstub::protocol::response_writer > --> $m<target version="1.0"><architecture>riscv:rv32</architecture></target>#ab
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:features:read:target.xml:46,fff#b7
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $qRegisterInfo0#72
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qRegisterInfo0")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $Hg1#e0
 TRACE gdbstub::protocol::response_writer > --> $OK#9a
 TRACE gdbstub::protocol::recv_packet     > <-- $p0#a0
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("p0")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qProcessInfo#dc
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qProcessInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qProcessInfo#dc
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qProcessInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qProcessInfo#dc
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qProcessInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qOffsets#4b
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qOffsets")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qStructuredDataPlugins#02
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qStructuredDataPlugins")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qSymbol::#5b
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qSymbol::")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qfThreadInfo#bb
 TRACE gdbstub::protocol::response_writer > --> $mp01.01#cd
 TRACE gdbstub::protocol::recv_packet     > <-- $qsThreadInfo#c8
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $jThreadsInfo#c1
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("jThreadsInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $jThreadExtendedInfo:#b9
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("jThreadExtendedInfo:")
 TRACE gdbstub::protocol::response_writer > --> $#00

Registers are never queried.

@danlehmann
Copy link
Contributor Author

Once I add the registers, things look as expected:

 TRACE gdbstub::protocol::recv_packet > <-- +
 TRACE gdbstub::protocol::recv_packet > <-- $QStartNoAckMode#b0
 TRACE gdbstub::protocol::response_writer > --> $OK#9a
 TRACE gdbstub::protocol::recv_packet     > <-- +
 TRACE gdbstub::protocol::recv_packet     > <-- $qSupported:xmlRegisters=i386,arm,mips,arc;multiprocess+;fork-events+;vfork-events+#2e
 TRACE gdbstub::protocol::response_writer > --> $PacketSize=1000;vContSupported+;multiprocess+;QStartNoAckMode+;swbreak+;qXfer:features:read+#fd
 TRACE gdbstub::protocol::recv_packet     > <-- $QThreadSuffixSupported#e4
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("QThreadSuffixSupported")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $QListThreadsInStopReply#21
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("QListThreadsInStopReply")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $vCont?#49
 TRACE gdbstub::protocol::response_writer > --> $vCont;c;C;s;S#62
 TRACE gdbstub::protocol::recv_packet     > <-- $qVAttachOrWaitSupported#38
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qVAttachOrWaitSupported")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $QEnableErrorStrings#8c
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("QEnableErrorStrings")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qHostInfo#9b
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qHostInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qProcessInfo#dc
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qProcessInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qC#b4
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qC")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qfThreadInfo#bb
 TRACE gdbstub::protocol::response_writer > --> $mp01.01#cd
 TRACE gdbstub::protocol::recv_packet     > <-- $qsThreadInfo#c8
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $?#3f
 TRACE gdbstub::protocol::response_writer > --> $T05thread:p01.01;#06
 TRACE gdbstub::protocol::recv_packet     > <-- $qProcessInfo#dc
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qProcessInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:features:read:target.xml:0,fff#7d
 TRACE gdbstub::protocol::response_writer > --> $m<target version="1.0">
<architecture>riscv:rv32</architecture>
<feature name="org.gnu.gdb.riscv.cpu">
  <reg name="zero" bitsize="32" type="int" regnum="0"/>
  <reg name="ra" bitsize="32" type="code_ptr"/>
  <reg name="sp" bitsize="32" type="data_ptr"/>
  <reg name="gp" bitsize="32" type="data_ptr"/>
  <reg name="tp" bitsize="32" type="data_ptr"/>
  <reg name="t0" bitsize="32" type="int"/>
  <reg name="t1" bitsize="32" type="int"/>
  <reg name="t2" bitsize="32" type="int"/>
  <reg name="fp" bitsize="32" type="data_ptr"/>
  <reg name="s1" bitsize="32" type="int"/>
  <reg name="a0" bitsize="32" type="int"/>
  <reg name="a1" bitsize="32" type="int"/>
  <reg name="a2" bitsize="32" type="int"/>
  <reg name="a3" bitsize="32" type="int"/>
  <reg name="a4" bitsize="32" type="int"/>
  <reg name="a5" bitsize="32" type="int"/>
  <reg name="a6" bitsize="32" type="int"/>
  <reg name="a7" bitsize="32" type="int"/>
  <reg name="s2" bitsize="32" type="int"/>
  <reg name="s3" bitsize="32" type="int"/>
  <reg name="s4" bitsize="32" type="int"/>
  <reg name="s5" bitsize="32" type="int"/>
  <reg name="s6" bitsize="32" type="int"/>
  <reg name="s7" bitsize="32" type="int"/>
  <reg name="s8" bitsize="32" type="int"/>
  <reg name="s9" bitsize="32" type="int"/>
  <reg name="s10" bitsize="32" type="int"/>
  <reg name="s11" bitsize="32" type="int"/>
  <reg name="t3" bitsize="32" type="int"/>
  <reg name="t4" bitsize="32" type="int"/>
  <reg name="t5" bitsize="32" type="int"/>
  <reg name="t6" bitsize="32" type="int"/>
  <reg name="pc" bitsize="32" type="code_ptr"/>
</feature>
</target>#50
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:features:read:target.xml:632,fff#e8
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $Hg1#e0
 TRACE gdbstub::protocol::response_writer > --> $OK#9a
 TRACE gdbstub::protocol::recv_packet     > <-- $p0#a0
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("p0")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qProcessInfo#dc
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qProcessInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qProcessInfo#dc
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qProcessInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qProcessInfo#dc
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qProcessInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qOffsets#4b
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qOffsets")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qStructuredDataPlugins#02
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qStructuredDataPlugins")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qSymbol::#5b
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qSymbol::")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qfThreadInfo#bb
 TRACE gdbstub::protocol::response_writer > --> $mp01.01#cd
 TRACE gdbstub::protocol::recv_packet     > <-- $qsThreadInfo#c8
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $g#67
 TRACE gdbstub::protocol::response_writer > --> $000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042#ce
 TRACE gdbstub::protocol::recv_packet     > <-- $qMemoryRegionInfo:42000000#9a
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qMemoryRegionInfo:42000000")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $jThreadsInfo#c1
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("jThreadsInfo")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $jThreadExtendedInfo:#b9
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("jThreadExtendedInfo:")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $x0,0#04
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("x0,0")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $m42000000,200#b1
 TRACE gdbstub::protocol::response_writer > --> $1711c8fd130101001725c8fd1305852497a5c8fd938585216307b500232005001105e34db5fe1715c8fd1305a5fd9725c8fd9385252217d61d001306a69c6308b500044204c111051106e34cb5fe97d00700e78060f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000097501300e780007d2571232e1118232c8118232a91182328211923263119232441192322511923206119232e7117232c8117232a91172328a1172326b1170013ae892324a4e63705fdfc130ac5cf37f5f0f0930a050f37c5c0c0130b050c37050303930b3530130cc4e69304c4e8130600142685814597701900e780801d814c03c5190083c5090003c6290083c6390022054d8d4206e206558e518d83c5590003c6490083c6690003c77900a205d18dc2066207d98ed58d03c6990083c6890003c7a90083c7b9002206558e4207e2075d8f598e83c6d90003c7c90083c7e90003c8f900a206d98ec20762083367f800d98e13571500298fb757555593875755#0a

@daniel5151 daniel5151 added the lldb-compat LLDB-specific protocol extension label Aug 6, 2024
@daniel5151
Copy link
Owner

Reviewing the GDB RSP spec (at https://sourceware.org/gdb/current/onlinedocs/gdb.html/Target-Description-Format.html#Target-Description-Format), it does seem that gdbstub_arch is technically allowed to send over just the architecture string.

That's not to say this is strictly the best idea. If upstream GDB changes the built-in target.xml structure for an architecture, gdbstub_arch could go out-of-sync, and send registers over in the wrong order. While it does seem that GDB make those sorts of breaking changes often (if ever), its always possible they might...

In any case - I'm not at all surprised that lldb might not be a fan of getting a "partial" XML like this, as presumably, most other GDB stubs will either send over no target.xml at all, or send over a fully-featured target.xml in its entirety.

I think its quite reasonable that gdbstub_arch implementations could be updated to send over fully-featured target.xml files.

In the future, it might be nice to address this alongside #143 or #12, but I think manually adding these XML defns here is totally reasonable for now.


Given that this might be a general problem (not specific to just RISC-V), we should avoid having #149 auto-close this issue. Can you update its description accordingly?

I'll go ahead and review that RISC-V PR, and we'll get it in to fix your use case :)

@daniel5151 daniel5151 added the gdbstub_arch Related to code in `gdbstub_arch` label Aug 12, 2024
@daniel5151 daniel5151 changed the title LLDB compatibility: Need full register definition LLDB compatibility: Send complete register definitions in target.xml Aug 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gdbstub_arch Related to code in `gdbstub_arch` lldb-compat LLDB-specific protocol extension
Projects
None yet
Development

No branches or pull requests

2 participants