Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try harder to locate libMangoHud_opengl.so #1540

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

smcv
Copy link
Contributor

@smcv smcv commented Jan 23, 2025

  • shim: Show error messages from dlopen() where appropriate

    If dlopen() returns null, then a subsequent dlerror() tells you why.

  • shim: Try to locate an adjacent libMangoHud_opengl.so using dladdr1()

    When the Steam Linux Runtime's container tool pressure-vessel finds a
    LD_PRELOAD module, it must map it into the filesystem namespace of the
    container, and its procedure to achieve this in the presence of $LIB
    and other dynamic string tokens involves symbolic links in a temporary
    directory.

    However, this means we end up with a symlink to libMangoHud_shim.so in
    $LD_PRELOAD, and no corresponding symlink to libMangoHud_opengl.so in
    the same directory, because pressure-vessel has no way to know that
    we'll load the latter. In this situation, libdl expands ${ORIGIN}
    to the directory containing the symlink, and not the directory below
    /run/host that it points into.

    We can improve on this by finding out the path to libMangoHud_shim.so
    by looking up information about one of our own symbols, then using
    realpath() to resolve that to a physical path somewhere below /run/host,
    and resolving libMangoHud_opengl.so relative to that physical path.
    The result is that we can find the implementation library.

    steamrt/tasks#595

smcv added 2 commits January 23, 2025 20:39
If dlopen() returns null, then a subsequent dlerror() tells you why.

Signed-off-by: Simon McVittie <[email protected]>
When the Steam Linux Runtime's container tool pressure-vessel finds a
LD_PRELOAD module, it must map it into the filesystem namespace of the
container, and its procedure to achieve this in the presence of `$LIB`
and other dynamic string tokens involves symbolic links in a temporary
directory.

However, this means we end up with a symlink to libMangoHud_shim.so in
`$LD_PRELOAD`, and no corresponding symlink to libMangoHud_opengl.so in
the same directory, because pressure-vessel has no way to know that
we'll load the latter. In this situation, libdl expands `${ORIGIN}`
to the directory containing the symlink, and not the directory below
/run/host that it points into.

We can improve on this by finding out the path to libMangoHud_shim.so
by looking up information about one of our own symbols, then using
realpath() to resolve that to a physical path somewhere below /run/host,
and resolving libMangoHud_opengl.so relative to that physical path.
The result is that we can find the implementation library.

steamrt/tasks#595

Signed-off-by: Simon McVittie <[email protected]>
@Etaash-mathamsetty
Copy link
Contributor

just curious: why dladdr instead of dlinfo ?

@smcv
Copy link
Contributor Author

smcv commented Jan 27, 2025

just curious: why dladdr instead of dlinfo ?

dlinfo() requires a handle to the module, which would require doing some suitable dlopen() to reopen the LD_PRELOAD module. Possibly dlopen("${ORIGIN}", ...) would be enough, but that still feels like overcomplicating things.

dladdr1() just needs the address of any function or variable in the module, which we can provide very easily without an additional function call.

@smcv
Copy link
Contributor Author

smcv commented Jan 27, 2025

Or, we could have passed dlopen(NULL, ...) to dlinfo() to get an entry in the link map (a linked list of struct link_map) and then walked the linked list to find libMangoHud_shim.so, but then that still means having to be able to recognise which link map entry is libMangoHud_shim.so, and using a heuristic such as "if the name ends with /libMangoHud_shim.so then it's probably me" seems more error-prone than using dladdr1() to get it right every time.

libsteam-runtime-tools already uses this technique with dladdr1(), although it's more difficult there because it's sometimes statically linked into the main executable. libMangoHud_shim.so doesn't have that problem because LD_PRELOAD modules are always dynamically loaded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants