FeralInteractive / ferallinuxscripts

General use repository for scripts used by Feral Interactive Linux games
61 stars 5 forks source link

Feral scripts for Linux has to be updated due to glibc changes made upstream #15

Closed Leopard1907 closed 10 months ago

Leopard1907 commented 1 year ago

https://github.com/ValveSoftware/steam-runtime/issues/613

As mentioned here, many ( probably all ) Feral Linux ports are affected by the issue.

I can repro the issue on Medieval 2 Total War port as well.

Leopard1907 commented 10 months ago

Currently all of your ports should be broken OOB for Ubuntu 23.04 as it ships with glibc 2.37, only distro that Feral claims to support officially.

esmithferal commented 10 months ago

This regression in glibc was fixed in glibc v2.38 which is included in 23.10, when the 24.04 LTS is released we would expect v2.38 will also be included.

The LTS release of 22.04 never had this issue. If someone hasn't updated their 23.04 release to a newer version manually updating to v2.38 should fix the regression and allow the games to run without issue.

smcv commented 9 months ago

@esmithferal, are you sure this was caused by a regression that was fixed in glibc 2.38? I can still reproduce the same problem on Arch Linux with glibc 2.39, using Tomb Raider (2013).

Steps to reproduce

Expected result

Game loads successfully

Actual result

.../Tomb Raider/bin/TombRaider: error while loading shared libraries: libicui18n.so.51: cannot open shared object file: No such file or directory

(For other affected games like DiRT 4 and Mad Max, the dependency library might be something different but the "shape" of the problem is the same.)

Root cause

objdump -T -x bin/TombRaider shows that the Dynamic Section has NEEDED libicui18n.so.51 and various other dependency libraries, and RPATH $ORIGIN/../lib.

In the installed game, libicui18n.so.51 and the other dependency libraries are in lib/i686. (For 64-bit games like DiRT 4 that have the same issue, it's lib/x86_64 instead.)

In glibc 2.36 and older, RPATH $ORIGIN/../lib or LD_LIBRARY_PATH=$(pwd)/lib would load libraries from the obvious lib, but it would automatically also try in a subdirectory: lib/i686 for 32-bit games, or lib/x86_64 for 64-bit.

In glibc 2.37 and newer, with the same RPATH or LD_LIBRARY_PATH, the runtime linker will search only the lib directory that it was explicitly told to use. That's why this game regressed.

Workaround suitable for end users

In Steam, set the game's launch options to: LD_LIBRARY_PATH="$(pwd)/lib/x86_64:$(pwd)/lib/i686:$LD_LIBRARY_PATH" %command%

(This is a somewhat generic workaround that applies to both 32- and 64-bit games affected by this issue.)

Solutions suitable for the game developer/publisher

One way to solve this would be to update the game's Steampipe depot by moving or copying the dependency libraries from lib/i686 or lib/x86_64 into lib. This solves the problem without any recompiling.

Or, the developer or publisher could relink the executable with -Wl,-rpath,'$ORIGIN/../lib/i686' for 32-bit games (-Wl,-rpath,'$ORIGIN/../lib/x86_64' for 64-bit games) in addition to -Wl,-rpath,'$ORIGIN/../lib', and ship an updated executable.

Or, the game launch script could extend LD_LIBRARY_PATH to include a path to lib/i686 and/or lib/x86_64 as appropriate, for example:

export LD_LIBRARY_PATH="$GAMEROOT/lib/i686:$GAMEROOT/lib/x86_64:$LD_LIBRARY_PATH"

(In the Steam Runtime, it is particularly important to prepend or append to an existing $LD_LIBRARY_PATH, and not just overwrite it.)

Single-file reproducer

Here is a single-file reproducer that illustrates the problem, by replicating the structure of Tomb Raider (2013) in a very simplified form. Save it as Makefile in an otherwise empty directory, and run make. With glibc 2.36 or older, the expected result is that both bin/exe.i686 and bin/exe.x86_64 will run successfully. With glibc 2.37 or newer, they fail.

bin/exe.i686 is the equivalent of a 32-bit game like Tomb Raider (2013). libreproducer.so.613 is a stand-in for the libcef.so and other dependency libraries included with Tomb Raider.

Similarly, bin/exe.x86_64 is the equivalent of a 64-bit game like DiRT 4.

# Copyright 2024 Collabora Ltd.
# SPDX-License-Identifier: MIT

all:

clean:
    rm -f library.c
    rm -f program.c
    rm -fr bin lib

library.c: Makefile
    echo 'int reproduce_sr613 (void) { return 613; }' > $@

program.c: Makefile
    (\
    echo 'int reproduce_sr613 (void); '; \
    echo 'int main (void) { return (reproduce_sr613() == 613 ? 0 : 1); }' \
    ) > $@

lib/i686/libreproducer.so.613: library.c Makefile
    install -d lib/i686
    $(CC) -m32 -o$@ -shared -Wl,-soname,libreproducer.so.613 library.c

lib/i686/libreproducer.so: lib/i686/libreproducer.so.613 Makefile
    ln -fns libreproducer.so.613 $@

lib/x86_64/libreproducer.so.613: library.c Makefile
    install -d lib/x86_64
    $(CC) -m64 -o$@ -shared -Wl,-soname,libreproducer.so.613 library.c

lib/x86_64/libreproducer.so: lib/x86_64/libreproducer.so.613 Makefile
    ln -fns libreproducer.so.613 $@

bin/exe.i686: lib/i686/libreproducer.so program.c
    install -d bin
    $(CC) -m32 -Llib/i686 -Wl,-rpath,'$${ORIGIN}/../lib' -o$@ program.c -lreproducer
all: bin/exe.i686

bin/exe.x86_64: lib/x86_64/libreproducer.so program.c
    install -d bin
    $(CC) -m64 -Llib/x86_64 -Wl,-rpath,'$${ORIGIN}/../lib' -o$@ program.c -lreproducer
all: bin/exe.x86_64

check: all
    bin/exe.i686
    bin/exe.x86_64