On Mon, 13 Jul 2026 11:03:23 -0700, Pierrick Bouvier wrote:
On 7/13/2026 10:56 AM, Ziyang Zhang wrote:
On Mon, 13 Jul 2026 10:53:56 -0700, Pierrick Bouvier wrote:
On 7/13/2026 9:34 AM, Ziyang Zhang wrote:
On Mon, 13 Jul 2026 08:31:18 -0700, Pierrick Bouvier wrote:
The problem is that if that the guest program, or the host library
(host
libhello) may depend on libstdc++. If they do and if they depend on a
(newer) symbol not present in lorelei libstdc++, we break ABI. Same
goes
for libgcc.

By not doing this, you'll be forced to provide a lorelei devkit
everytime a new libstdc++ is published, or a distribution updates its
gcc.

The only solution is to embed libstd++ and libgcc statically, or
rely on
host libraries. If you choose the second option, you know have the
opposite problem. So I think the only way to solve it is really static
linking, even if it will slightly increase binaries size.


The devkit already ships libstdc++ and libgcc anyway: its own clang/
LoreTLC link them dynamically, and we bundle them so the toolchain even
starts. So bundling libstdc++ for the thunk flow adds no new dependency,
it just reuses one the devkit must carry. Static-linking the thunks
wouldn't make the devkit any smaller or more self-contained either,
since clang still needs the dynamic libstdc++; we'd only be adding
static copies on top of it.


There is a difference between the toolchain dependencies, and thunks
dependency. For the first one, it's perfectly find to provide libstdc++,
for the second, it can create conflicts at runtime that may be very hard
to diagnose and solve.

On the ABI risk itself: libstdc++ keeps a backward-compatible ABI, and
the copy we bundle is recent, so a thunked host library only breaks if
it was built against a strictly newer libstdc++ and references a new
symbol. Even then it needs no new devkit, because the resolution order
is the integrator's to choose. On a host newer than our bundle, putting
the system libstdc++ ahead of the devkit's on LD_LIBRARY_PATH lets the
host library bind the newest one, while clang and the Lorelei runtime
keep working against it by backward compatibility. So a gcc update on
the host doesn't force us to reship.


Sure can choose indeed. However, he has to find where such libraries are
located on his system, and prepend that to LD_LIBRARY_PATH. Not the most
user-friendly thing to guess and debug IMHO.

There's also an active reason not to static-link. Both the Lorelei
runtime and the generated thunk libraries depend on libstdc++. If we
statically link libstdc++ into a thunk while the host library it
dispatches to links the system libstdc++ dynamically, the process ends
up with two libstdc++ copies on the host side, right across the boundary
where C++ objects and exceptions pass between the thunk and the real
library. That can break:

- Exceptions: one thrown in the host library may not be caught in the
thunk. The two copies have different std::type_info for the same type,
so the match fails and it hits std::terminate.
- dynamic_cast / typeid across the boundary: they assume a single
type_info per type, so they can start returning null or misidentifying
types.
- Duplicated global state: two sets of the iostream objects, the locale/
facets, and the exception emergency buffer.


That's a good point, but does lorelei even provide a solution for that?
I guess that exception raised from an host library and sent back to
guest binary with target specific types will not result in what is
expected at the moment.

Based on the above reasons, I prefer to do that than statically link and
grow the big artifact. Does that hold for you?


Ok.

Thanks,
Ziyang Zhang


Regards,
Pierrick


Wait a second. I missed something.

Sorry, last time I answered without actually checking the libstdc++
situation on the four distros. You were right to push on it, so I looked
properly.

You were right that the x86_64 sysroot is the crux: libc6-amd64-cross
gives /usr/x86_64-linux-gnu/ a libc but no libstdc++, so the guest side
has no system libstdc++ to fall back on. That's the side we should keep
providing ourselves, and the devkit already ships the x86_64 libstdc++
next to the guest runtime for exactly that. It's only a default, though:
if a guest executable needs a newer libstdc++, the user can put a newer
x86_64 libstdc++.so ahead of ours on the guest LD_LIBRARY_PATH (the -E
one) and it takes precedence, while our runtime keeps working against it
by backward compatibility. So we are not locking anyone to our version.

The host side is different, there libstdc++ is reliably present. I
checked each distro's stock minimal base image, with nothing installed
on top:

Debian 12: libstdc++6 12.2.0-14+deb12u1
Ubuntu 24.04: libstdc++6 14.2.0-4ubuntu2~24.04.1
Fedora 40: libstdc++-14.2.1-3.fc40
Arch (2024-08 snapshot): libstdc++.so.6 from gcc-libs 14.2.1
It ships out of the box on all four, and the C compiler pulls it in on
Debian, Ubuntu and Arch.

So the split I'd propose: provide libstdc++ only on the guest side (the
x86_64 sysroot has none), and on the host side rely on the system's, so
the host thunk and the real host library both bind the host's own
libstdc++ rather than a copy we ship. That directly addresses the ABI
point you raised: nothing we ship shadows the host's libstdc++, so a
thunk never forces an older libstdc++ onto a host library built against
a newer one.

Does that split sound right to you?


That's a reasonable default, and Lorelei can be updated for this without
having to update anything on QEMU side (or its documentation).

If I had to choose, I would still do static linking for guest and host
thunks, because I don't think we can handle exceptions correctly anyway.
But the most important is that current example already works out of the
box, which makes this series ready for upstream.

Regards,
Pierrick

Thank you, and thanks for the thorough review across all the revisions. Your feedback made both the plugin and the walkthrough much better than where they started.

The libstdc++ discussion was valuable too. I'll keep static linking for the thunks in mind, and the exception-across-the-boundary case is a fair point I want to revisit properly. Since all of that lives on the Lorelei side, we can iterate on it without touching QEMU.

Thanks,
Ziyang Zhang


Reply via email to