This is an archive of the discontinued LLVM Phabricator instance.

[lldb/qemu] Separate host and target environments
ClosedPublic

Authored by labath on Dec 7 2021, 5:48 AM.

Details

Summary

Qemu normally forwards its (host) environment variables to the emulated
process. While this works fine for most variables, there are some (few, but
fairly important) variables where this is not possible. LD_LIBRARY_PATH
is the probably the most important of those -- we don't want the library
search path for the emulated libraries to interfere with the libraries
that the emulator itself needs.

For this reason, qemu provides a mechanism (QEMU_SET_ENV,
QEMU_UNSET_ENV) to set variables only for the emulated process. This
patch makes use of that functionality to pass any user-provided
variables to the emulated process. Since we're piggy-backing on the
normal lldb environment-handling mechanism, all the usual mechanism to
provide environment (target.env-vars setting, SBLaunchInfo, etc.) work
out-of-the-box, and the only thing we need to do is to properly
construct the qemu environment variables.

This patch also adds a new setting -- target-env-vars, which represents
environment variables which are added (on top of the host environment)
to the default launch environments of all (qemu) targets. The reason for
its existence is to enable the configuration (e.g., from a startup
script) of the default launch environment, before any target is created.
The idea is that this would contain the variables (like the
aforementioned LD_LIBRARY_PATH) common to all targets being debugged on
the given system. The user is, of course, free to customize the
environment for a particular target in the usual manner.

The reason I do not want to use/recommend the "global" version of the
target.env-vars setting for this purpose is that the setting would apply
to all targets, whereas the settings (their values) I have mentioned
would be specific to the given platform.

Diff Detail

Event Timeline

labath requested review of this revision.Dec 7 2021, 5:48 AM
labath created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptDec 7 2021, 5:48 AM
DavidSpickett added inline comments.Dec 7 2021, 6:47 AM
lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp
121

Please comment with the meaning here. Which I think is if this var is not set for the host, or it is set but to a different value.

127

And here you're saying if the setting is set for host but not target, unset it?

And then I thought doesn't this just leave you with the content of target but that's not the goal here. You start with:
target environment
host environment

You want:
host environment plus QEMU_SET/UNSET_ENV based on the target environment's content

Since you might still need some of the vars that get unset, before the point where qemu's emulation begins, right? So maybe a bad example idk, but you might want LD_LIBRARY_PATH set to one thing to run qemu properly, but then you want it to be changed when qemu does its emulation.

Which is why you can't just use the target environment and discard the host completely.

Could you add a motivating example as a comment to the function? I think it's quite clearly written but easy to come to that incorrect conclusion on first read.

lldb/source/Plugins/Platform/QemuUser/PlatformQemuUserProperties.td
18

"to emulated target environment", just to be super clear?

lldb/test/API/qemu/qemu.py
65

Do you do this so that you know you have a copy, or because os.environ is not quite acting like a dictionary enough?

A quick check shows it does set/get key but I'm sure it's not 100% like a plain dict somehow.

If it's to ensure a copy, not a reference to the object please note that in a comment.

Oh and:

This patch also adds a new setting -- target-env-vars

Might want to clarify that it adds this setting to the qemu user platform.

labath marked 3 inline comments as done.Dec 8 2021, 1:33 AM
labath added inline comments.
lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp
127

Yes, that's the general idea, though it's not that the target environment "replaces" the host one after qemu is "done" with it. It's more like qemu maintaining an emulated version of the environment for the benefit of the emulated program (well, the program maintains it itself, qemu just passes the appropriate data structures when it launches it).

I've also refactored the function to be more... functional. I originally thought I would be doing some in-place modifications of the target environment, but with the current implementation, it just looked confusing.

lldb/test/API/qemu/qemu.py
65

It's mainly because the json library is not able to serialize the magic object. Having a copy is kinda nice, as I do not intend to modify the actual environment, but it does not really matter.

labath updated this revision to Diff 392680.Dec 8 2021, 1:33 AM
labath marked an inline comment as done.
  • add some explanatory comments
  • make the function return a new environment
DavidSpickett accepted this revision.Dec 8 2021, 2:08 AM

LGTM assuming that qemu passing on the SET/UNSET vars is what you've observed.

lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp
139

I glossed over this the first time, I assume you've observed this in testing. My first assumption was that qemu wouldn't pass them on but hard to tell from the sources. Probably some use case for it (emulating a second qemu-user?).

This revision is now accepted and ready to land.Dec 8 2021, 2:08 AM
labath marked an inline comment as done.Dec 8 2021, 2:53 AM
labath added inline comments.
lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp
139

I'm not sure what's the use case, but yes, that is how it works. My guess it that it is simply because that is the easiest thing to do, and the user can always unset them himself in case he wants to (most of the time, it doesn't matter).

labath added a comment.Dec 8 2021, 2:56 AM

Thanks for all the reviews. I'll probably take a break with this now. I'll need to integrate the existing stuff into our internal infrastructure before adding more features.

This revision was automatically updated to reflect the committed changes.