[lldb-dev] [RFC] lldb integration with (user mode) qemu

Pavel Labath via lldb-dev lldb-dev at lists.llvm.org
Thu Oct 28 06:33:12 PDT 2021

Hello everyone,

I'd like to propose a new plugin for better lldb+qemu integration.

As you're probably aware qemu has an integrated gdb stub. Lldb is able
to communicate with it, but currently this process is somewhat tedious.
One has to manually start qemu, giving it a port number, and then
separately start lldb, and have it connect to that port.

The chief purpose of this feature would be to automate this behavior,
ideally to the point where one can just point lldb to an executable,
type "run", and everything would just work. It would take the form of a
platform plugin (PlatformQemuUser, perhaps). This would be a non-host,
always-connected plugin, and it's heart would be the DebugProcess
method, which would ensure the emulator gets started when the user wants
to start debugging. It would operate the same way as our host platforms
do, except that it would start qemu instead of debug/lldb-server. Most
of the other methods would be implemented by delegating to the host
platform (as the process will be running on the host), possibly with
some minor adjustments like prepending sysroot to the paths, etc. (My
initial proof-of-concept implementation was 200 LOC.)

The plugin would be configured via multiple settings, which would let
the user specify, the path to the emulator, the kind of cpu it should
emulate and the path to the system libraries, and any other arguments
that the user wishes to pass to the emulator. The user could then
configure it in their lldbinit file to match their system setup.

The needs of this plugin should match the existing Platform abstraction
fairly well, so I don't anticipate (*) the need to add new entry points
or modify existing ones. There is one tricky aspect which I see, and it
relates to platform selection. Our current platform selection code gives
each platform instance (while preferring the current platform) a chance
to "claim" an executable, and aborts if the choice is ambiguous. The
introduction of a qemu platform would introduce such an ambiguity, since
(when running on a linux host) a linux executable would be claimed by
both the qemu plugin and the existing remote-linux platform. This would
prevent "target create arm-linux.exe" from working out-of-the-box.

To resolve this, I'd like to create some kind of a mechanism to give
preference to some plugin. This could either be something internal,
where a plugin indicates "strong" preference for an executable (the qemu
platform could e.g. do this when the user sets the emulator path, the
remote platform when it is connected), or some external mechanism like a
global setting giving the preferred platform order. I'd very much like
hear your thoughts on this.

I'm also not sure how to handle the case of multiple emulated
architectures. Qemu can emulate any processor architecture (of those
that lldb supports, anyway), but the path to the emulator, sysroot, and
probably other settings as well are going to be different. I see two
possible ways to go about this:

a) have just a single set of settings, effectively limiting the user to
emulating just a single architecture per session. While it would most
likely be enough for most use cases, this kind of limitation seems
artificial. It would also likely require the introduction of another
setting, which would specify which architecture the plugin should
actually emulate (and return from GetSupportedArchitectureAtIndex,
etc.). On the flip side, this would be consistent with the how our
remote-plugins work, although there it is given by the need to connect
to something, and the supported architecture is then determined by the
remote machine.

b) have multiple platform instances for each architecture. This solution
be a more general solution, but it would mean that our "platform list"
output would double, and half of it would consist of qemu platforms

As far as testing is concerned I'm planning to reuse parts of our
gdb-client test suite for this. Namely, I want to write a small python
script which would act as a fake emulator. It would be sending out
pre-programmed gdb-remote responses, much like our client test suite
does. Since the main purpose of this is to validate that the emulator
was started with the correct arguments, I don't expect the need for
emulating any complex behavior -- the existing client classes should
completely suffice.

If you got all the way here, I want to thank you for taking your time to
read this, and urge you to let me know what you think.


(*) There is one refactor of the Platform class implementations that I'd 
like to do first, but this (a) is not strictly necessary for this; and 
(b) is valueable independently of this RFC; so I am leaving that for a 
separate discussion.

More information about the lldb-dev mailing list