【问题标题】:Understanding why gcc/ld are linking a symbol from a particular library using readelf了解为什么 gcc/ld 使用 readelf 链接来自特定库的符号
【发布时间】:2014-08-14 23:20:18
【问题描述】:

我在 gcc (-llapacke -llapack -lcblas) 中包含了几个库,并且我收到“未定义引用”错误,除非我明确链接到其中一个库的静态版本 (lapacke)。我试图通过使用nmreadelf 搜索违规库的各种变体来了解原因。让我们以“未定义”函数zsysv_rook_

% readelf -Wa /usr/lib/liblapacke.so | grep zsysv_rook_

00000000003c3978  000008d600000007 R_X86_64_JUMP_SLOT     000000000016e340 LAPACKE_zsysv_rook_work + 0
00000000003c5f20  000003c300000007 R_X86_64_JUMP_SLOT     0000000000000000 zsysv_rook_ + 0
   963: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND zsysv_rook_
  2262: 000000000016e340   884 FUNC    GLOBAL DEFAULT   11 LAPACKE_zsysv_rook_work

这就是动态变体。这是静态变体:

% readelf -Wa /usr/lib/liblapacke.a | grep zsysv_rook_
00000000000000b2  0000000d00000004 R_X86_64_PLT32         0000000000000000 LAPACKE_zsysv_rook_work - 4
0000000000000146  0000000d00000004 R_X86_64_PLT32         0000000000000000 LAPACKE_zsysv_rook_work - 4
    13: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND LAPACKE_zsysv_rook_work
File: /usr/lib/liblapacke.a(lapacke_zsysv_rook_work.o)
0000000000000186  0000000f00000004 R_X86_64_PLT32         0000000000000000 zsysv_rook_ - 4
0000000000000264  0000000f00000004 R_X86_64_PLT32         0000000000000000 zsysv_rook_ - 4
     9: 0000000000000000   884 FUNC    GLOBAL DEFAULT    1 LAPACKE_zsysv_rook_work
    15: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND zsysv_rook_

为什么只编译静态版本?

【问题讨论】:

    标签: gcc linker static-libraries dynamic-library readelf


    【解决方案1】:

    符号zsysv_rook_ 没有被任何一个库定义,所以库中的某些东西引用了它。

    静态库基本上是对象文件的存档,链接器查看存档并链接到解决程序中未定义引用的每个对象。如果存在定义程序不需要的符号的对象,则不会链接到这些对象。我假设正在发生的事情是引用 zsysv_rook_ 的对象没有定义您需要的任何符号,因此该对象没有链接到,并且您的程序不需要解析 zsysv_rook_ 符号。

    当您链接到动态库时(默认情况下),您需要解析库中任何内容所需的所有未定义引用,因此由于库的某些部分引用了zsysv_rook_,您需要链接到提供它的任何内容。

    所以如果你想使用动态库,你需要弄清楚哪个库定义了zsysv_rook_ 并链接到它。它可能是其他 LAPACK 库之一,也可能是您已经链接到的库之一,但您可能将 -l 选项放在链接命令中的错误位置 - 提供 zsysv_rook_ 的库需要在 -llapacke 之后为了解决对它的引用。

    【讨论】:

    • 另外两个库是 blas 和 lapack,据我所知,它们都没有定义 zsysv_rook_。我实际上并没有在任何地方调用 zsysv_rook_,因此它可能会被我调用的函数之一调用。不幸的是,我不知道如何找到。
    • 如果它是由您调用的函数调用的,那么您将无法链接到静态库。您可以链接到静态库的事实意味着您不需要该符号,这就是我在回答中试图解释的。看起来zsysv_rook_ 是 LAPACK 的一部分,在一个名为 zsysv_rook.f 的文件中定义,所以我希望它在 lapack 库中。
    • 如果zsysv_rook_ 是我使用-llapack 包含的lapack 库的一部分,我不应该能够使用nm 或readelf 看到它吗?我在任何liblapack.* 中看到的唯一内容是FUNC GLOBAL DEFAULT 1 zsysv_。如果我不需要它,为什么我会得到未定义的符号?我已经尝试了链接器中库的所有排列。很抱歉把它拖出来,但我对此有点陌生。
    • 是的,我希望你能看到它。至于“为什么我得到未定义的符号?”我已经在上面回答过了,再读一遍:当你链接到一个动态库时(默认情况下),你需要解析库中任何东西所需的所有未定义引用,所以因为库的某些部分引用了zsysv_rook_ 你需要链接到任何提供它的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    • 2023-03-11
    • 2012-02-14
    • 2013-09-04
    相关资源
    最近更新 更多