轻松检查共享库中未解析的符号?

2022-01-11 00:00:00 shared-libraries linker c++

我正在编写一个相当大的 C++ 共享对象库,但遇到了一个让调试很痛苦的小问题:

I am writing a fairly large C++ shared-object library, and have run into a small issue that makes debugging a pain:

如果我在头文件中定义了一个函数/方法,并且忘记为它创建一个存根(在开发过程中),因为我正在构建一个共享对象库而不是一个可执行文件,所以在编译时不会出现错误告诉我忘了实现那个功能.我发现问题的唯一方法是在运行时,当最终链接到该库的应用程序因未定义符号"错误而崩溃时.

If I define a function/method in a header file, and forget to create a stub for it (during development), since I am building as a shared object library rather than an executable, no errors appear at compile-time telling me I have forgotten to implement that function. The only way I find out something is wrong is at runtime, when eventually an application linking against this library falls over with an 'undefined symbol' error.

我正在寻找一种简单的方法来检查我是否拥有编译时需要的所有符号,也许我可以添加到我的 Makefile 中.

I am looking for an easy way to check if I have all the symbols I need at compile time, perhaps something I can add to my Makefile.

我提出的一个解决方案是通过 nm -C -U 运行已编译的库,以获取所有未定义引用的解组列表.问题是这也会列出其他库中的所有引用,例如 GLibC,当最终应用程序组合在一起时,这些引用当然会与这个库一起链接.可以通过我所有的头文件将 nm 的输出用于 grep 并查看是否有任何对应的名称..但这似乎很疯狂.当然这不是一个不常见的问题,有更好的解决方法吗?

One solution I did come up with is to run the compiled library through nm -C -U to get a demangled list of all undefined references. The problem is this also comes up with the list of all references that are in other libraries, such as GLibC, which of course will be linked against along with this library when the final application is put together. It would be possible to use the output of nm to grep through all my header files and see if any of the names corresponding.. but this seems insane. Surely this is not an uncommon issue and there is a better way of solving it?

推荐答案

查看链接器选项 -z defs/--no-undefined.创建共享对象时,如果有未解析的符号会导致链接失败.

Check out the linker option -z defs / --no-undefined. When creating a shared object, it will cause the link to fail if there are unresolved symbols.

如果您使用 gcc 调用链接器,您将使用编译器 -Wl 选项将选项传递给链接器:

If you are using gcc to invoke the linker, you'll use the compiler -Wl option to pass the option to the linker:

gcc -shared ... -Wl,-z,defs

例如,考虑以下文件:

#include <stdio.h>

void forgot_to_define(FILE *fp);

void doit(const char *filename)
{
    FILE *fp = fopen(filename, "r");
    if (fp != NULL)
    {
        forgot_to_define(fp);
        fclose(fp);
    }
}

现在,如果您将其构建到共享对象中,它将成功:

Now, if you build that into a shared object, it will succeed:

> gcc -shared -fPIC -o libsilly.so silly.c && echo succeeded || echo failed
succeeded

但是如果你添加 -z defs,链接会失败并告诉你你丢失的符号:

But if you add -z defs, the link will fail and tell you about your missing symbol:

> gcc -shared -fPIC -o libsilly.so silly.c -Wl,-z,defs && echo succeeded || echo failed
/tmp/cccIwwbn.o: In function `doit':
silly.c:(.text+0x2c): undefined reference to `forgot_to_define'
collect2: ld returned 1 exit status
failed

相关文章