查找目录中的所有符号

Find all symbols in a directory

我想弄清楚在编译将其作为头文件包含的程序时要包含哪个 C 库,在本例中为 #include <pcre2.h>。我能够找出我需要的文件位置的唯一方法是检查我知道需要导出的特定符号。例如:

$ ls
CMakeCache.txt       Makefile             install_manifest.txt  libpcre2-posix.pc   pcre2_grep_test.sh
CMakeFiles           a.out                libpcre2-8.a          pcre2-config        pcre2_test.sh
CTestCustom.ctest    cmake_install.cmake  libpcre2-8.pc         pcre2.h             pcre2grep
CTestTestfile.cmake  config.h             libpcre2-posix.a      pcre2_chartables.c  pcre2test
$ objdump -t libpcre2-8.a|grep pcre2_compile
pcre2_compile.c.o:     file format elf64-x86-64
0000000000000000 l    df *ABS*  0000000000000000 pcre2_compile.c
00000000000100bc g     F .text  00000000000019dd pcre2_compile_8
0000000000000172 g     F .text  00000000000000e3 pcre2_compile_context_create_8
0000000000000426 g     F .text  0000000000000055 pcre2_compile_context_copy_8
0000000000000557 g     F .text  0000000000000032 pcre2_compile_context_free_8

并且因为符号 pcre2_compile_8 存在于该文件中(在尝试所有其他文件之后......)我知道我需要包含的库是 pcre2-8,也就是说,我编译我的代码:

$ gcc myfile.c -lpcre2-8 -o myfile; ./myfile

两个与此相关的问题:

  1. 有没有更简单的方法在一批文件(其中一些不是elf文件)中找到一个符号?例如,像 objdump -t * 这样的东西?或者最接近的做法是什么?
  2. 有没有更好的方法来找出 -l<library> 的库值是多少?或者,当有人下载​​一个新的 C 程序时,他们知道要将什么添加到他们的命令行以便程序运行,通常的方法是什么? (对我来说,我刚刚花了最后一个小时弄清楚它是 -lpcre2-8 而不是 -lpcre-lpcre2

通常,您从库中调用的函数将是该库定义的符号。但是在PCRE2中,由于不同的代码单元大小,你调用的函数(例如pcre2_compile)实际上通过预处理器宏(例如pcre2_compile_8)变成了不同的符号。您可以通过编译程序并检查未定义的符号来从库中找到您需要的符号:

$ cat test.c 
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>

int main() {
  pcre2_compile("",0,0,NULL,NULL,NULL);
}
$ gcc -c test.c
$ nm -u test.o 
                 U _GLOBAL_OFFSET_TABLE_
                 U pcre2_compile_8

Is there a simpler way to find a symbols in a batch of files?

您可以在目录(/usr/lib/ 下面)中搜索库文件(下面的 .a.so 扩展名),运行 nm 每个并搜索未定义的符号(改编自 this question):

$ for lib in $(find /usr/lib/ -name \*.a -o -name \*.so)
> do
>     nm -A --defined-only $lib 2>/dev/null| grep pcre2_compile_8
> done
/usr/lib/x86_64-linux-gnu/libpcre2-8.a:libpcre2_8_la-pcre2_compile.o:0000000000007f40 T pcre2_compile_8

Is there a better way to find out what the library value of -l is?

它通常通过库文档传达。对于 PCRE2,the second page of the documentation 讨论了提供适当标志的 pcre-config 工具:

pcre2-config returns the configuration of the installed PCRE2 libraries and the options required to compile a program to use them. Some of the options apply only to the 8-bit, or 16-bit, or 32-bit libraries, respectively, and are not available for libraries that have not been built.

[...]

--libs8 Writes to the standard output the command line options required to link with the 8-bit PCRE2 library (-lpcre2-8 on many systems).

[...]

--cflags Writes to the standard output the command line options required to compile files that use PCRE2 (this may include some -I options, but is blank on many systems).

因此,对于这个特定的库,推荐的构建方式 link 是:

gcc -c $(pcre2-config --cflags) test.c -o test.o
gcc test.o -o test $(pcre2-config --libs8)