7

我正在构建一个构建多个共享库和可执行文件的项目。用于构建这些二进制文件的所有源文件都位于单个 /src 目录中。因此,要弄清楚哪些源文件用于构建每个二进制文件并不明显(存在多对多关系)。

我的目标是编写一个脚本,为每个二进制文件解析一组 C 文件,并确保只从它们调用正确的函数。

一种选择似乎是尝试从 Makefile 中提取此信息。但这不适用于生成的文件和标题(由于依赖于包含)。

另一种选择可能是简单地浏览调用图,但这会变得复杂,因为很多函数都是通过使用函数指针来调用的。

还有其他想法吗?

4

5 回答 5

10

您可以首先使用调试信息 (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 目录中。然后当然你需要围绕这个编写一些脚本来收集相关的源文件名。

于 2012-08-29T21:38:49.583 回答
2

这是一个想法,需要根据您的具体构建进行改进。进行构建,使用脚本(例如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 文件列表。

于 2012-08-29T21:22:02.203 回答
2

首先,您需要将调试符号与刚刚编译的二进制文件分开。检查这个问题如何做到这一点: 如何在构建目标之外生成 gcc 调试符号?

然后你可以尝试自己解析这个文件。我知道如何为 Visual Studio 这样做,但是当您使用 GCC 时,我将无法进一步帮助您。

于 2012-08-29T21:23:22.207 回答
2

您可以使用 unixnm工具。它显示对象中定义的所有符号。所以你需要:

  1. 在您的二进制文件上运行nm并获取所有未定义的符号
  2. 在您的二进制文件上运行ldd以获取其所有动态依赖项的列表(您的二进制文件链接到的.so 文件)
  3. 对您在步骤 2 中找到的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”的符号。

于 2012-08-29T21:34:04.020 回答
1

如果您的目标是分析 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.

于 2012-08-30T08:22:44.943 回答