[英]A 32bit version of an application, built on CentOS 6 x64, crashes during exceptions in `dl_iterate_phdr`, when started on newer Linux
TL;DR; TL;博士; My research shows that if I build an application (and its dependencies) on older Linux like
CentOS 6
(with GLIBC 2.12
), it is supposed to work perfectly fine on any other Linux distro, which has newer GLIBC
.我的研究表明,如果我在较旧的 Linux 上构建应用程序(及其依赖项),例如
CentOS 6
(带有GLIBC 2.12
),它应该可以在任何其他具有新GLIBC
2.12 的 ZEDC9F0A5A5D57797BF6.BC 发行版、 Isn't this assumption correct?这个假设不正确吗?
Sorry, it's gonna be a long post, but it's not a trivial question.对不起,这将是一个很长的帖子,但这不是一个微不足道的问题。
Here's the build machine:这是构建机器:
$ rpm -q centos-release
centos-release-6-10.el6.centos.12.3.x86_64
$ ldd --version
ldd (GNU libc) 2.12
$ ld -v
GNU ld version 2.30-54.el6
$ gcc --version
gcc (GCC) 8.3.1 20190311 (Red Hat 8.3.1-3)
$ g++ --version
g++ (GCC) 8.3.1 20190311 (Red Hat 8.3.1-3)
The application links with almost everything statically, so:该应用程序与几乎所有内容都静态链接,因此:
$ ldd ./app
linux-gate.so.1 (0xf7f73000)
libdl.so.2 => /lib32/libdl.so.2 (0xf7f4c000)
librt.so.1 => /lib32/librt.so.1 (0xf7f41000)
libstdc++.so.6 => ./libstdc++.so.6 (0xf7e22000)
libm.so.6 => /lib32/libm.so.6 (0xf7d53000)
libgcc_s.so.1 => ./libgcc_s.so.1 (0xf7d35000)
libpthread.so.0 => /lib32/libpthread.so.0 (0xf7d14000)
libc.so.6 => /lib32/libc.so.6 (0xf7b36000)
/lib/ld-linux.so.2 (0xf7f75000)
So:所以:
linux-gate
and ld-linux
aren't exactly libs, so they can't be deployed; linux-gate
和ld-linux
不完全是库,所以它们不能被部署;libdl
, librt
, libm
, libpthread
and libc
are a part of the GLIBC
, so they shouldn't be deployed as well (especially given the backward compatibility of the GNU C library); libdl
、 librt
、 libm
、 libpthread
和libc
是GLIBC
的一部分,因此也不应该部署它们(特别是考虑到 GNU C 库的向后兼容性);libstdc++
and libgcc_s
are "deployed" together with the binary (taken from the build machine) libstdc++
和libgcc_s
与二进制文件一起“部署”(取自构建机器) The test machine:试验机:
$ lsb_release -a
Description: Debian GNU/Linux 10 (buster)
$ ldd --version
ldd (Debian GLIBC 2.28-10) 2.28
The 64bit build (with its libstdc++
and libgcc_s
) seems to work perfectly fine. 64 位构建(及其
libstdc++
和libgcc_s
)似乎工作得很好。
The issue is with the 32bit build - it crashes , when an exception is thrown (not for all exceptions, but seems to be consistent).问题在于 32 位构建 - 它会在引发异常时崩溃(并非针对所有异常,但似乎是一致的)。 Here's how interesting the stack trace is:
以下是堆栈跟踪的有趣之处:
SIGSEGV at 0# __kernel_sigreturn in linux-gate.so.1
1# dl_iterate_phdr in /lib32/libc.so.6
2# _Unwind_Find_FDE in ./libgcc_s.so.1
3# 0xF7D88AAE in ./libgcc_s.so.1
4# 0xF7D89227 in ./libgcc_s.so.1
5# _Unwind_RaiseException in ./libgcc_s.so.1
6# __cxa_throw in ./libstdc++.so.6
7# <some funct> in ./app
7# <some funct> in ./app
7# <some funct> in ./app
7# <some funct> in ./app
7# <some funct> in ./app
7# <some funct> in ./app
13# make_fcontext in ./app
I can see two possible options here:我可以在这里看到两个可能的选项:
Any ideas?有任何想法吗?
I suspect that if you "deploy" GCC libs (g++/gcc) from build machine to target one with different OS or OS version, then your app (or one of its dependencies) can actually use GCC libs from the target system, and other dependencies use libs that you deployed, leading to potential incompatibilities.我怀疑如果您从构建机器“部署” GCC 库(g++/gcc)到具有不同操作系统或操作系统版本的目标,那么您的应用程序(或其依赖项之一)实际上可以使用来自目标系统的 GCC 库和其他依赖项使用您部署的库,从而导致潜在的不兼容性。
It's much safer to build your application on target box, or use cross-compilation specifying exactly target box OS and version.在目标框上构建应用程序或使用交叉编译来准确指定目标框操作系统和版本要安全得多。
Also it's safer to use dynamic linking with system libs because otherwise you may end up with the situation of mixing static and dynamic lib in one app, and this may lead to problems (eg two instances of some global var in gcc lib).此外,将动态链接与系统库一起使用更安全,否则您最终可能会遇到在一个应用程序中混合 static 和动态库的情况,这可能会导致问题(例如 gcc 库中的某些全局变量的两个实例)。
You'll need to check whole tree of lib dependencies to ensure that only one instance of every lib is loaded from the same location.您需要检查整个库依赖关系树,以确保每个库只有一个实例从同一位置加载。 For example your app depends on
./libgcc_s.so.1
and ./libstdc++.so.6
but ./libstdc++.so.6
may depend on system's libgcc_s.so
.例如,您的应用程序依赖于
./libgcc_s.so.1
和./libstdc++.so.6
但./libstdc++.so.6
可能依赖于系统的libgcc_s.so
。
You may search on Internet about these and other pitfalls with building your app on non-target box.您可以在 Internet 上搜索有关在非目标框上构建应用程序的这些和其他陷阱。 Eg here :
例如 这里:
So just compiling your application on an older distribution is not enough.
因此,仅在较旧的发行版上编译您的应用程序是不够的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.