askme765cs / Wine-QQ-TIM

提供在Linux上运行最新版腾讯QQ与TIM的解决方案 Easiest Way to Run QQ&TIM on Linux
3.2k stars 294 forks source link

Bundle ld-linux.so.2 so that it can run on 64-bit systems without 32-bit libs installed #49

Open probonopd opened 6 years ago

probonopd commented 6 years ago

为了运行32位Windows应用程序,必须使用32位Windows,这又需要32位ld-linux.so.2glibc。但是现在大多数64位系统都没有安装32位兼容性库。

对于其他程序,通常可以手动加载32位ELF文件,并使用一个私有的“ld-linux.so.2”捆绑版本,如下所示:

wget -c http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6-i386_2.24-9ubuntu2.2_amd64.deb
dpkg -x ./libc6*.deb .

HERE="$(dirname "$(readlink -f "${0}")")"

WINEPREFIX="$HERE/wineprefix/" \
  "$HERE/lib32/ld-linux.so.2"  \
  --library-path "$HERE/lib32" \
  "$HERE/wine-stable/bin/wine" \
  "$WINEPREFIX/drive_c/Program Files/App/App.exe"  "$@"

但是,对于WINE,这是行不通的。我的猜测是,WINE通过后台的其他机制启动其他的WINE实例,而后者不会使用指定的 "$HERE/lib32/ld-linux.so.2"--library-path "$HERE/lib32"

葡萄酒开发商亚历山大Julliard [葡萄酒开发回答](https://www.winehq.org/pipermail/wine-devel/2017-November/119944.html):

It's not possible in standard Wine, but you could probably hack wine_exec_wine_binary() in libs/wine/config.c to add your special magic.

:建设:这需要完成。我们将非常欢迎捐款。

与此同时,我们可以通过在/ tmp这个固定位置放置一个符号链接到我们自定义的ld-linux.so.2来避开这个限制,但这是一个很丑恶的事情。


In order to run 32-bit Windows applications, 32-bit Windows must be used, which in turn requires 32-bit ld-linux.so.2 and glibc. But most 64-bit systems these days don't have the 32-bit compatibility libraries installed anymore.

With other programs it is usually possible to manually load the 32-bit ELF file with a private, bundled version of ld-linux.so.2 like so:

wget -c http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6-i386_2.24-9ubuntu2.2_amd64.deb
dpkg -x ./libc6*.deb .

HERE="$(dirname "$(readlink -f "${0}")")"

WINEPREFIX="$HERE/wineprefix/" \
  "$HERE/lib32/ld-linux.so.2"  \
  --library-path "$HERE/lib32" \
  "$HERE/wine-stable/bin/wine" \
  "$WINEPREFIX/drive_c/Program Files/App/App.exe"  "$@"

However, with WINE, this does not work. My guess is that WINE launches other WINE instances through other mechanisms in the background, which in turn don't get loaded using the specified "$HERE/lib32/ld-linux.so.2" and --library-path "$HERE/lib32".

WINE developer Alexandre Julliard answered on wine-devel:

It's not possible in standard Wine, but you could probably hack wine_exec_wine_binary() in libs/wine/config.c to add your special magic.

:construction: This needs to be done. We would highly welcome contributions.

In the meantime, we may get around this limitation by placing a symlink to our custom ld-linux.so.2 at a fixed location such as /tmp, but it is an ugly hack.

askme765cs commented 6 years ago

Thanks for your great contribution to the project ,Mr probonopd,I will try to solve this problem in the next versions

askme765cs commented 6 years ago

The thorniest problem is the handling of the ldlinux.so file in the / tmp directory First, if we do not delete it, we will complain the next time we start it. (Maybe cancel this error is a method? Or there may be a potential risk of incompatibility) Paradoxically, however, if we delete it directly, this will cause those programs to unexpectedly quit if there are other programs that also need it 最棘手的问题是/tmp目录下ldlinux.so文件的处理 首先,如果我们不删除它,下次启动就会报错。(也许取消这个报错是一种方法?又或者会有潜在的不兼容风险) 但是矛盾的是,如果我们直接删除,如果有其他同样需要这个文件的程序正在运行,这个做法就会让那些程序意外退出

probonopd commented 6 years ago

将符号链接放在 /tmp 中是一件很丑恶的事情。 正确的解决方案是在Alexandre Julliard建议的 libs/wine/config.c 中为 wine_exec_wine_binary() 写一个补丁。 那么 /tmp 中不需要符号链接。

https://www.winehq.org/pipermail/wine-devel/2017-November/119944.html


Putting symlinks in /tmp is an ugly hack. Proper solution is to write a patch for wine_exec_wine_binary() in libs/wine/config.c as suggested by Alexandre Julliard. Then no need for symlinks in /tmp.

https://www.winehq.org/pipermail/wine-devel/2017-November/119944.html

shouhuanxiaoji commented 6 years ago

@probonopd wo have started do the patch, thanks for a lot.

linweilian03 commented 6 years ago

@probonopd I think we can write relative path in ELF header with patchelf. Maybe using relative path can solve this problem. You can use $ORIGIN as the current directory path in the RPATH. For example, $ORIGIN/lib means ./lib However, it can't solve the ld-linux.so.2 problem. I will try to find more way to do this.

probonopd commented 6 years ago

However, it can't solve the ld-linux.so.2 problem.

Yes, exactly. I came to the same conclusion.

linweilian03 commented 6 years ago

@askme765cs You can set different interpreter path for different app to solve this problem. For example you can set the interpreter path as /tmp/Tim.v1.so for the wine in TIM appdir and /tmp/QQ.v2.so for wine in QQ appdir. In the meantime, you should also set different dir for the symbol link in different appimage. Besides, you should also modify the Apprun.

linweilian03 commented 6 years ago

@probonopd I found that the rpath of wine is relative path. So we just need to hack the wine to set its interpreter to a path and link a 32bit dynamic linker to that path. Besides, the path name is not limited by its longer, which means you can set interpreter path as something like /tmp/QQ.20180121.ld-linux.so.2 . Next step, we just need to link a 32bit dynamic linker to the path, and we don't need to hack the dynamic linker and other files. By doing so, run appimage will just add a symbolic link in tmp, and the name of link can be anything. It will be much more clean and beautiful.

askme765cs commented 6 years ago

@linweilian03 Thanks for your suggestion, we have done (set different interpreterpath) this for the new version Wine-QQ&TIM.We are testing it now.It will come out soon.

linweilian03 commented 6 years ago

@probonopd I find a more reliable way to solve dependencies problem, especially the hard coded path problem. Because the unshare command can create a new namespace which can seperate the file system. First, suppose we want to run program "QQ". We mkdir Temp and write these in AppRun:

!/bin/bash

HERE=$(cd "$(dirname "$0")";pwd) unshare -mr $HERE/runqq

It will create a namespace which can seperate filesystem mouting and run the runqq script. There will be two lines in runqq script to solve dependencies problem. mount --bind /usr/lib $HERE/Temp $HERE/usr/bin/unionfs-fuse -o use_ino,nonempty,uid=$UID $HERE/usr/lib/=RO:$HERE/Temp /usr/lib/

probonopd commented 6 years ago

unshare mount --bind

Doesn't this need root rights?

linweilian03 commented 6 years ago

@probonopd It doesn't need root rights. However it needs the kernel to support this. The ubuntu supports this, but the debian disable it in default. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=808915

probonopd commented 6 years ago

debian disable it in default

That's very bad - then it doesn't work everywhere. So not a viable general solution.

linweilian03 commented 6 years ago

@probonopd So I want to find an unprivileged container or namespace tool which can be supported in default.

probonopd commented 6 years ago

Or hack wine_exec_wine_binary() in libs/wine/config.c. May be easier.