On 10/6/22 11:12, Daniel P. Berrangé wrote:
On Tue, Oct 04, 2022 at 07:59:18AM -0700, Richard Henderson wrote:
On 10/4/22 05:00, Daniel P. Berrangé wrote:
g_slice uses a one-time initializer to check the G_SLICE env variable
making it hard for QEMU to set the env before any GLib API call has
triggered the initializer. Even attribute((constructor)) is not
sufficient as QEMU has many constructors and there is no ordering
guarantee between them.
There are orderings for constructors, see
__attribute__((constructor(priority))).
Oh, thanks for pointing that out. I tried it, but glib threw
a bag of rocks at me ;-P
The priority works for ordering within the scope of the binary
containing the constructor.
Yes.
libglib.so itself has a constructor function registered, and that
calls APIs that trigger GSlice initialization:
Ah. I had been hoping that gslice would be initialized on first use, so as long as we
could get the setenv done before any other qemu code ran, we'd be fine.
This all takes place when libglib.so is loaded, which happens prior
to any code in QEMU being loaded / executed. So no constructor in
QEMU code can ever pre-empt this in dynamic builds.
Shared libraries have a defined initialization order too, but we'd have to play real
irritating games to make this happen, installing a shared library of our own (linked later
in the sequence to qemu, and itself *not* linked to libglib.so). Not worth it.
The only possible silver linining is that in static linked builds,
it appears that a QEMU constructor with priority 101, will pre-empt
the constructor from any library. This is kind of crazy, as it means
if any library or app code uses priorities, it'll get totally different
execution ordering depending on whether it is dynamic or statically
built.
Plausible...
I guess we could rely on this hack if we declare that everyone using
binfmt is probably relying on static linked QEMU, and in non-binfmt
cases people can set the env var themselves. It still feels pretty
dirty.
... but as you say, dirty.
Alternately, report it as a bug to glib, because we can't be the only project impacted by
this.
r~