簡體   English   中英

基於 CentOS 6 x64 構建的 32 位版本的應用程序在 `dl_iterate_phdr` 中的異常期間崩潰,當在較新的 Linux 上啟動時

[英]A 32bit version of an application, built on CentOS 6 x64, crashes during exceptions in `dl_iterate_phdr`, when started on newer Linux

TL;博士; 我的研究表明,如果我在較舊的 Linux 上構建應用程序(及其依賴項),例如CentOS 6 (帶有GLIBC 2.12 ),它應該可以在任何其他具有新GLIBC 2.12 的 ZEDC9F0A5A5D57797BF6.BC 發行版、 這個假設不正確嗎?


對不起,這將是一個很長的帖子,但這不是一個微不足道的問題。

這是構建機器:

$ 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)

應用程序與幾乎所有內容都靜態鏈接,因此:

$ 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)

所以:

  • linux-gateld-linux不完全是庫,所以它們不能被部署;
  • libdllibrtlibmlibpthreadlibcGLIBC的一部分,因此也不應該部署它們(特別是考慮到 GNU C 庫的向后兼容性);
  • libstdc++libgcc_s與二進制文件一起“部署”(取自構建機器)

試驗機:

$ lsb_release -a
  Description:  Debian GNU/Linux 10 (buster)
$ ldd --version
  ldd (Debian GLIBC 2.28-10) 2.28

64 位構建(及其libstdc++libgcc_s )似乎工作得很好。

問題在於 32 位構建 - 它會在引發異常時崩潰(並非針對所有異常,但似乎是一致的)。 以下是堆棧跟蹤的有趣之處:

 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

我可以在這里看到兩個可能的選項:

  1. 32 位版本有一些問題(盡管它可以正常工作);
  2. 我對這件事確實有一些很大的誤解。

有任何想法嗎?

我懷疑如果您從構建機器“部署” GCC 庫(g++/gcc)到具有不同操作系統或操作系統版本的目標,那么您的應用程序(或其依賴項之一)實際上可以使用來自目標系統的 GCC 庫和其他依賴項使用您部署的庫,從而導致潛在的不兼容性。

在目標框上構建應用程序或使用交叉編譯來准確指定目標框操作系統和版本要安全得多。

此外,將動態鏈接與系統庫一起使用更安全,否則您最終可能會遇到在一個應用程序中混合 static 和動態庫的情況,這可能會導致問題(例如 gcc 庫中的某些全局變量的兩個實例)。

您需要檢查整個庫依賴關系樹,以確保每個庫只有一個實例從同一位置加載。 例如,您的應用程序依賴於./libgcc_s.so.1./libstdc++.so.6./libstdc++.so.6可能依賴於系統的libgcc_s.so

您可以在 Internet 上搜索有關在非目標框上構建應用程序的這些和其他陷阱。 例如 這里

因此,僅在較舊的發行版上編譯您的應用程序是不夠的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM