【问题标题】:Building portable apps on newer systems to support older glibc在较新的系统上构建便携式应用程序以支持较旧的 glibc
【发布时间】:2023-01-30 20:50:19
【问题描述】:

我正在尝试构建一个支持旧版本 GLIBC 的应用程序,我的目标是 GLIBC 2.17。这个应用程序使用了几个静态库(curl、openssl)。它是在带有 GLIBC 2.28 的系统上构建的。目前它需要 GLIBC 2.25(它确实需要 2.28,但我解决了这个问题,请参阅帖子后面的内容以获取更多信息)。它目前不在安装了 GLIBC 2.17 的系统上运行,

./myApp: /lib64/libc.so.6: version 'GLIBC_2.25' not found (required by ./myApp)

我的研究指出了构建我的应用程序的几种方法,因此它支持旧系统。

  1. 我的大部分研究表明在我想要支持的最旧系统上的应用程序上构建它。因此,在这种情况下,构建在具有 GLIBC 2.17 的系统上。我已经简要探讨了这个选项。使用 GLIBC 2.17 设置构建系统一直很困难。例如 Centos7 梯级 GLIC 2.17,但似乎 mingw64 不再可用(我也在将应用程序交叉编译到 Windows,创建第二个构建系统并不理想,因为它会增加复杂性)。所以我想把它作为最后的手段,并探索其他选择,如果它们存在的话。
  2. 在目标主机上升级/运行多个版本的 GLIBC - 不可能。我无法控制终端系统
  3. 将 glibc 作为静态库包含在应用程序中 - 根据我的阅读,这不是一个好主意。
  4. 改用 musl - 简单地尝试了一下,无法编译。我可以继续尝试这个方法
  5. 或通过此参考创建便携式应用程序:https://insanecoding.blogspot.com/2012/07/creating-portable-linux-binaries.html

    我的应用程序当前的 GLIBC 要求,GLIC2.25 是它要求的最高版本。

    ldd -v myApp 
            linux-vdso.so.1 (0x00007fff799d6000)
            libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f11232f1000)
            libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1123130000)
            /lib64/ld-linux-x86-64.so.2 (0x00007f1123805000)
    
            Version information:
            ./myApp:
                    libpthread.so.0 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libpthread.so.0
                    libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.3) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.25) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.7) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.17) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
            /lib/x86_64-linux-gnu/libpthread.so.0:
                    ld-linux-x86-64.so.2 (GLIBC_2.2.5) => /lib64/ld-linux-x86-64.so.2
                    ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2
                    libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.3.2) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_PRIVATE) => /lib/x86_64-linux-gnu/libc.so.6
            /lib/x86_64-linux-gnu/libc.so.6:
                    ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2
                    ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2
    

    我目前正在探索选项 5,我相信我已经将它缩小到一个需要 GLIBC 2.25 的函数,getentropy

    objdump -T myApp | grep GLIBC_ | grep 2.25
    0000000000000000  w   DF *UND*  0000000000000000  GLIBC_2.25  getentropy
    

    我不直接调用该函数,我可能会间接调用,但我不知道。我做了一些挖掘,看起来在 libcrypto 中调用了该函数。我能够通过构建动态库并通过 objdump 运行它来找到它

    objdump -T libcrypto.so | grep getentropy
    0000000000000000  w   DF *UND*  0000000000000000  GLIBC_2.25  getentropy
    

    静态库

    nm -g libcrypto.a | grep getentropy
                     w getentropy
    

    我创建了一个运行 GLIBC 2.17 的 Centos 7 docker 容器并重建了静态库。注意我正在使用 vcpkg 构建静态库。将静态库移至运行 GLIBC 2.28 的主构建系统后,我仍然需要 GLIBC 2.25

    ldd -v myApp 
            linux-vdso.so.1 (0x00007fff799d6000)
            libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f11232f1000)
            libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1123130000)
            /lib64/ld-linux-x86-64.so.2 (0x00007f1123805000)
    
            Version information:
            ./myApp:
                    libpthread.so.0 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libpthread.so.0
                    libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.3) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.25) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.7) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.17) => /lib/x86_64-linux-gnu/libc.so.6
                    libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
    
                
    

    该应用程序不会在运行 GLIBC 2.17 的目标系统上运行。

    请注意,myApp 最初需要 GLIBC 2.28,通过 objdump 的过程,我能够将它缩小到 libcurl 中的 fcntl64。通过在 CentOS7 上构建 libcurl,我能够删除 GLIBC 2.28 要求。

    通过构建的二进制文件,我发现了这个:

    nm -g newAgent | grep getentropy
                     w getentropy@@GLIBC_2.25
                 
    

    如果我在 CentOS 7 上构建所有内容,我会看到:

    ldd -v myApp 
            linux-vdso.so.1 =>  (0x00007fff4b734000)
            libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f9ea4eef000)
            libc.so.6 => /lib64/libc.so.6 (0x00007f9ea4b21000)
            /lib64/ld-linux-x86-64.so.2 (0x00007f9ea510b000)
    
            Version information:
            ./myApp:
                    libpthread.so.0 (GLIBC_2.2.5) => /lib64/libpthread.so.0
                    libc.so.6 (GLIBC_2.14) => /lib64/libc.so.6
                    libc.so.6 (GLIBC_2.3.4) => /lib64/libc.so.6
                    libc.so.6 (GLIBC_2.3) => /lib64/libc.so.6
                    libc.so.6 (GLIBC_2.7) => /lib64/libc.so.6
                    libc.so.6 (GLIBC_2.17) => /lib64/libc.so.6
                    libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
            .....
    [root@f89001979d38 agent_code]# nm -g myApp | grep getentropy
                     w getentropy
    

    它没有链接到 GLIBC 2.25。我认为“w”表示它是一个弱符号。我对弱符号的理解是库定义了 getentropy 的代码,但如果找到另一个版本,比如 GLIBC,那么它将使用该版本。

    我猜我的客人

    1. 我是否遗漏了什么,是否有其他东西可能使该应用程序需要 GLIBC 2.25?
    2. 我能否传递参数或以某种方式编译我的代码,以便它不搜索 GLIBC getentropy?我的最终目标是在具有 GLIC 2.17 的系统上运行它

【问题讨论】:

  • “例如 Centos 7 支持 GLIBC 2.17,但似乎 mingw64 不再适用于它。” --@987654330怎么样@相关的你在做什么?
  • 我正在交叉编译应用程序以在 Windows 上运行。只是想添加一些关于为什么使用旧的构建系统很困难的上下文
  • “我正在交叉编译应用程序以在 Windows 上工作”——你的问题似乎是自我强加的。没有充分的理由在同一个系统上构建所有目标。您可以在 VM-old-linux 中为“旧 Linux”构建,并在 VM-new-linux 中为 Windows 交叉编译。两个虚拟机都可以在同一个“新 Linux”物理主机上运行。它们也不需要是完整的虚拟机——docker 容器应该可以正常工作。

标签: glibc


【解决方案1】:

所以不确定这是否是最好的方法,但我能够消除对 getentropy 的依赖。我正在使用 vcpkg 构建库,并且能够在代码中找到它定义 getentropy 的位置。然后使用这个https://stackoverflow.com/a/72778459/4400676我能够应用那个补丁并删除外部依赖。

ldd -v myApp
        linux-vdso.so.1 (0x00007fff57baa000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f2a4c8f7000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f2a4c000000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f2a4c8fe000)

        Version information:
        ./myApp:
                libpthread.so.0 (GLIBC_2.2.5) => /lib64/libpthread.so.0
                libc.so.6 (GLIBC_2.14) => /lib64/libc.so.6
                libc.so.6 (GLIBC_2.3.4) => /lib64/libc.so.6
                libc.so.6 (GLIBC_2.3) => /lib64/libc.so.6
                libc.so.6 (GLIBC_2.7) => /lib64/libc.so.6
                libc.so.6 (GLIBC_2.17) => /lib64/libc.so.6
                libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
        /lib64/libpthread.so.0:
                libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
        /lib64/libc.so.6:
                ld-linux-x86-64.so.2 (GLIBC_2.2.5) => /lib64/ld-linux-x86-64.so.2
                ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2
                ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2

【讨论】:

    猜你喜欢
    • 2016-06-27
    • 1970-01-01
    • 2019-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多