我正在构建一个构建多个共享库和可执行文件的项目。用于构建这些二进制文件的所有源文件都位于单个 /src 目录中。因此,要弄清楚哪些源文件用于构建每个二进制文件并不明显(存在多对多关系)。
我的目标是编写一个脚本,为每个二进制文件解析一组 C 文件,并确保只从它们调用正确的函数。
一种选择似乎是尝试从 Makefile 中提取此信息。但这不适用于生成的文件和标题(由于依赖于包含)。
另一种选择可能是简单地浏览调用图,但这会变得复杂,因为很多函数都是通过使用函数指针来调用的。
还有其他想法吗?
您可以首先使用调试信息 (gcc -g) 编译您的项目,并使用objdump它来获取包含哪些源文件。
objdump -W <some_compiled_binary>
Dwarf 格式应包含您要查找的信息。
<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
< c> DW_AT_producer : (indirect string, offset: 0x5f): GNU C 4.4.3
<10> DW_AT_language : 1 (ANSI C)
<11> DW_AT_name : (indirect string, offset: 0x28): test_3.c
<15> DW_AT_comp_dir : (indirect string, offset: 0x36): /home/auselen/trials
<19> DW_AT_low_pc : 0x82f0
<1d> DW_AT_high_pc : 0x8408
<21> DW_AT_stmt_list : 0x0
在这个例子中,我从 test_3 编译了目标文件,它位于 .../trials 目录中。然后当然你需要围绕这个编写一些脚本来收集相关的源文件名。
这是一个想法,需要根据您的具体构建进行改进。进行构建,使用脚本(例如script log.txt make clean all)记录它。最后一个(或最后一个)步骤应该是目标文件的链接。(提示:寻找cc -o <your_binary_name>)。该行应该链接所有在你的树.o中应该有相应文件的文件。.c然后为所有包含的头文件 grep 这些.c文件。
如果您.c在树中的文件中有重复名称,那么我们需要查看链接器行中的完整路径或从Makefile.
Mahmood 下面的建议也应该有效。如果你有一个带有符号的图像,strings <debug_image> | grep <full_path_of_src_directory>应该给你一个 C 文件列表。
首先,您需要将调试符号与刚刚编译的二进制文件分开。检查这个问题如何做到这一点: 如何在构建目标之外生成 gcc 调试符号?
然后你可以尝试自己解析这个文件。我知道如何为 Visual Studio 这样做,但是当您使用 GCC 时,我将无法进一步帮助您。
您可以使用 unixnm工具。它显示对象中定义的所有符号。所以你需要:
nm并获取所有未定义的符号ldd以获取其所有动态依赖项的列表(您的二进制文件链接到的.so 文件)nm每个文件运行。.so这将为您提供二进制文件使用的动态符号的完整列表。
例子:
nm -C --dynamic /bin/ls
....skipping.....
00000000006186d0 A _edata
0000000000618c70 A _end
U _exit
0000000000410e34 T _fini
0000000000401d88 T _init
U _obstack_begin
U _obstack_newchunk
U _setjmp
U abort
U acl_extended_file
U bindtextdomain
U calloc
U clock_gettime
U closedir
U dcgettext
U dirfd
ls 命令使用所有带有大写“U”的符号。
如果您的目标是分析 C 源文件,您可以通过自定义 GCC 编译器来实现。您可以为此目的使用MELT(MELT 是一种高级域特定语言来扩展 GCC)-在 GCC 中添加您自己的用 MELT 编码的分析通行证-但您应该首先了解 GCC 中端内部表示(Gimple、Tree , ...)。
Customizing GCC takes several days of work (mostly because GCC internals are quite complex in the details).
Feel free to ask me more about MELT.