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 #99

Open
daniel5151 opened this issue Feb 20, 2022 · 4 comments
Open

LLDB Compatibility #99

daniel5151 opened this issue Feb 20, 2022 · 4 comments
Labels
design-required Getting this right will require some thought help wanted Extra attention is needed lldb-compat LLDB-specific protocol extension

Comments

@daniel5151
Copy link
Owner

This is a meta-issue to discuss + track gdbstub's LLDB compatibility story.

Overview

LLDB uses the GDB Remote Serial Protocol for remote debugging, and for the most part, LLDB works "out of the box" with GDB server implementations. Unfortunately, there are some differences between how LLDB and GDB implement the Remote Serial Protocol, resulting in potential issues when mixing and matching servers/clients.

In some cases, LLDB has added new protocol extensions that are disjoint from (and therefore backwards compatible with) the base GDB protocol. The de-facto documentation for these LLDB specific extensions can be found here:

Unfortunately, there are some cases where LLDB happened to implement certain packets differently from GDB, resulting in breaking incompatibilities. The most pertinent example of this is wrt how LLDB handles vFile packets. This blog post does a good job providing an overview of the various LLDB-GDB RSP compatibility hazards: https://www.moritz.systems/blog/improving-gdb-protocol-compatibility-in-lldb/

Moreover, as mentioned in the blog post above, LLDB has actually made breaking changes to its RSP between versions! Unlike GDB, using a newer LLDB client with an older LLDB server is not supported!

Supporting LLDB clients in gdbstub

With these challenges in mind, what would be the best way to support LLDB clients in gdbstub?

For the most part, it should be pretty straightforward to support arbitrary LLDB extensions in gdbstub. After all, adding support for any particular LLDB packet should be no different from adding support for a new GDB packet.

Indeed, the bulk of the complexity in supporting LLDB clients is figuring out how to handle the inconsistencies between the LLDB and GDB RSPs.

  • Should gdbstub include some kind of configuration to target a specific LLDB protocol version?
  • Would it be feasible to somehow support all LLDB clients via some kind of version-detection mechanism?
  • Should LLDB extensions "bleed into" the existing APIs, or should LLDB extensions be clearly marked as "separate" from the main GDB protocol?
    • e.g: should the existing vFile:open API be updated to include LLDB-specific vFile:open flags?
  • Older versions of LLDB used a custom qRegisterInfo packet to fetch a target's register description, though newer versions of LLDB support parsing target.xml data. Should gdbstub attempt to "unify" qRegisterInfo with target.xml via the Arch trait, thereby enabling transparent support across all GDB and LLDB clients?

These are open questions, and ones that I don't have answers to just yet. I suspect the only way to answer these questions will be by someone putting in the legwork to try some ideas out, and seeing how the things look.

@daniel5151 daniel5151 added help wanted Extra attention is needed design-required Getting this right will require some thought lldb-compat LLDB-specific protocol extension labels Feb 20, 2022
@daniel5151
Copy link
Owner Author

#100 merged in the first bit of explicit LLVM compat to gdbstub.

Admittedly, these changes were merged in a pretty "laissez faire" manner, as they were fairly minor (allowing a few more bits to fall through the packet validation logic), and are entirely backwards compatible with GDB. I'm not convinced this sort of attitude will be applicable for more involved LLVM compat scenarios, but it's a reasonable way to enable a particular user's use case for now.

At a certain point, it'd be a good idea to re-evaluate this approach, and consider alternative ways of enabling LLVM compat in the vFile API (e.g: changing the API to pass a enum HostIoOpenFlags with HostIoOpenFlags::{Gdb,Lldb,LldbLegacy} variants, using a separate IDET, etc...)

@daniel5151
Copy link
Owner Author

daniel5151 commented Jun 5, 2022

Ah, interesting! Reading through the LLDB GDB RSP spec doc, it looks like LLDB adds a qGDBServerVersion packet, which allows servers to report what "version" of the LLDB protocol is being used. Assuming the LLDB client is actually using + respecting this identifier (which is a big assumption), it could be a useful tool to manage any protocol ambiguities that might come up.

Depending on how early in the handshake LLDB sends this packet, it could serve double-duty as a way to dynamically detect when a LLDB client is connected, and swap into a LLDB "quirks" mode. Of course, this assumes that gdbstub would introduce some formal notion of "LLDB mode" to begin with, the details and implementation of which are still undecided.

@danlehmann
Copy link
Contributor

Hi! I noticed that lldb works, but only if the list of registers is explicitly 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).

Would you take a patch that addresses this?

I'd apply this to rv32, rv64 and arm. Those are the three platforms where I observed this, though I wouldn't be surprised if this is a universal issue.

@danlehmann
Copy link
Contributor

Actually, I filed a separate task to not clutter this one: #148

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design-required Getting this right will require some thought help wanted Extra attention is needed lldb-compat LLDB-specific protocol extension
Projects
None yet
Development

No branches or pull requests

2 participants