Compiling

現有的 .so 文件即使存在也無法載入,似乎取決於 Docker 主機作業系統

  • April 27, 2022

我在基於 Alma8 的 Docker 容器中建構了 Qt6,Docker 主機是 Fedora 35。

在某些情況下(如下所述),所有 Qt 庫都無法載入libQt6Core.so[.6[.2.4]]. 但是該文件存在並且在正確的目錄中搜尋該文件。libQt6Dbus.so找到並載入其他 Qt 庫(例如)。

廣泛的調試、重建、搜尋網路並沒有產生任何線索,根本原因是什麼以及我如何解決它。

定位問題

我已將問題縮小到以下情況:

  • 我創建了兩個最小的虛擬機,一個使用 centos7,一個使用 alma8。
  • 我從官方倉庫安裝了 Docker 到他們兩個中。
  • 我在兩個 VM 中執行了相同的 Docker 映像並安裝了相同的 qt6 包。
  • 當 Docker 主機是 centos7 時它會中斷。
  • 它在 Docker 主機為 alma8 時工作。

理論與問題

  • Qt6 是在 Alma8 上建構的,並且連結到一些比 Centos7 提供的更新的系統庫,因此 Qt6 不能在 Centos7 下執行(這是完全可以預料的,也可以)。但它應該在 Alma8 Docker 容器中的任何位置執行。
  • 容器鏡像應該能夠在任何地方執行,但在這種情況下,來自主機作業系統的“某些東西”會潛入容器並導致問題——即使兩個容器使用完全相同的鏡像!

問題是:這是什麼“東西”以及它如何/為什麼會破壞建構?

我試過的

我檢查libQt6Gui.so了它是否可以載入libQt6Core.so,我檢查libQt6Core.so了是否有東西看起來是假的:

  • ldd並且LD_DEBUG=libs ldd確實顯示出一些差異(見下文)
  • libtree沒有顯示出任何差異(但是一棵很好的樹:))
  • pyldd(來自 conda-build)
  • readelf -d

我也嘗試過:

  • 設置LD_LIBRARY_PATH(沒有改變任何東西——這並不奇怪,因為我知道總是搜尋正確的路徑)
  • 在帶有 centos7 主機的 alma8 容器中建構 Qt6(建構失敗並顯示“ libQt6Core.so.6:無法打開文件”,與建構的庫相同的錯誤)
  • 在 centos7 容器中建構 Qt6(由於我還無法修復的其他問題,建構失敗)

區別於ldd

在下面的螢幕截圖中,您可以看到左側Centos7 主機上的 Alma8-Docker-Container 和 *右側 Alma8 主機上的 Alma8-Docker-Container。

前兩張圖片顯示了ldd /opt/emsconda/lib/libQt6Gui.so. libQt6Core在左邊找不到,但在右邊找到。

在此處輸入圖像描述

第二個螢幕截圖顯示找到並載入了其他 Qt。左側的 ICU 庫也失去了——也許它們只在 libQt6Core 也被載入時才被載入?

在此處輸入圖像描述

此螢幕截圖顯示了LD_DEBUG=libs ldd .... 您可以看到,在這兩種情況下,libQt6Core都是在正確的位置搜尋 ( /opt/emsconda/lib)。但它只裝載在正確的容器中。左邊的另外一個在 `/opt/emsconda/lib/./ (haha)) 中查找,然後默默地走到下一個 lib …

我找不到任何錯誤消息。這個文件只是沒有打開/載入。

在此處輸入圖像描述

檢查它libQt6Core.so本身可能會給我們一個線索。它連結到一個linux-vdso.so.1.

根據這個 SO question,該文件是作業系統核心注入使用者空間的虛擬庫。

由於 Docker 容器不執行自己的核心,我懷疑該文件來自主機作業系統。也許,libQt6Core依賴於linux-vdso.so.1centos7核心無法提供的某些功能?我不知道 … 在此處輸入圖像描述


由於到目前為止我沒有嘗試過產生錯誤消息,因此我不知道實際問題可能是什麼或如何進行調試。對於任何類型的提示、提示或幫助,我將不勝感激。

這個問題在 Qt 論壇中得到了答案。

概括:

  • .so包含一個 ABI 標記,表示所需的最低核心版本。您可以通過objdump -s -j .note.ABI-tag libQt6Core.so.6.2.4. 結果在最後三個塊中(在我的例子中是0x03 0x11 0x00-> 3.17.0)。
  • 由於 QT 使用了一些僅適用於較新核心的系統呼叫,因此此資訊是故意放置在那裡的。
  • Glibc 在載入共享對象時讀取此資訊並將其與目前核心的版本進行比較。如果不匹配,則不會載入文件。
  • 由於 Docker 沒有自己的核心,因此使用 Docker 主機的核心版本進行比較。因此,即使 Docker 鏡像是 Alma8,在我的例子中,核心仍然是來自 Centos7 主機的舊 v3.10.0。
  • 您可以使用strip --remove-section=.note.ABI-tag libQt6Core.so.6.2.4. Qt 似乎有備份程式碼,所以沒有任何問題。

來源:https ://github.com/Microsoft/WSL/issues/3023

引用自:https://unix.stackexchange.com/questions/700290