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

2021-10-28 Thread Pavel Labath via lldb-dev

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.

regards,
pavel

(*) 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.

___
lldb-dev mailing list
lldb-dev@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


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

2021-10-28 Thread David Spickett via lldb-dev
Glad to hear the gdb server in qemu plays nicely with lldb. Perhaps
some of that is the compatibility work that has been going on.

> 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.

I assume you wouldn't get a 3 way tie here because in connecting to a
remote-linux you've "disconnected" the host platform, right?

> To resolve this, I'd like to create some kind of a mechanism to give 
> preference to some plugin.

This choosing of plugin, does it mostly take place automatically at
the moment or is there a good spot where we could say "X and Y could
load this file, please choose one/resolve the tie"?

My first thought for automatic resolve is a native/emulator/remote
sort of hierarchy if you were going to order them. (with some nice
message "preferring X to Y because..." when it starts up)

> 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.

One aspect here is the way you configure them if you want to use many
architectures of qemu-user.

If I have only one platform, I set qemu-user.foo to some Arm focused
value. Then if I want to work on AArch64 I edit my lldbinit to switch
it. (or have many init files)
If there's one platform per arch I can set qemu-arm.foo and qemu-aarch64.foo.

Not much between them without having a specific use case for it. You
could work around either in various ways.

Wouldn't most of the platform entries just be subclasses of some
generic qemu-user-platform? So code wise it wouldn't be that much
extra to add them.
You could say it's bad to list qemu-xyz-platform when that isn't
installed, but then again, lldb lists a "local Mac OSX user platform
plug in" even on Linux. So not a big deal.
(and an apt install of qemu-user gives me every arch so easy to fix)

And you have to handle the ambiguity issue either way.


On Thu, 28 Oct 2021 at 14:33, Pavel Labath via lldb-dev
 wrote:
>
> 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
>