【问题标题】:How to find out *.c and *.h files that were used to build a binary?如何找出用于构建二进制文件的 *.c 和 *.h 文件?
【发布时间】:2012-08-24 13:52:33
【问题描述】:

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

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

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

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

还有其他想法吗?

【问题讨论】:

标签: c linux gcc build


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    首先,您需要将调试符号与刚刚编译的二进制文件分开。检查这个问题如何做到这一点: How to generate gcc debug symbol outside the build target?

    然后你可以尝试自己解析这个文件。我知道如何为 Visual Studio 执行此操作,但由于您使用的是 GCC,我将无法进一步帮助您。

    【讨论】:

      【解决方案3】:

      这是一个想法,需要根据您的具体构建进行改进。进行构建,使用脚本记录它(例如script log.txt make clean all)。最后一个(或最后一个)步骤应该是目标文件的链接。 (提示:寻找cc -o &lt;your_binary_name&gt;)。该行应该链接所有.o 文件,这些文件应该在您的树中具有相应的.c 文件。然后 grep 那些 .c 文件以获取所有包含的头文件。

      如果您在树中的 .c 文件中有重复名称,那么我们需要查看链接器行中的完整路径或从 Makefile 工作。

      Mahmood 下面的建议也应该有效。如果你有一个带有符号的图像,strings &lt;debug_image&gt; | grep &lt;full_path_of_src_directory&gt; 应该会给你一个 C 文件列表。

      【讨论】:

      • 好主意。但是我不熟悉 GCC 的 Makefile,但我使用 VS 并且 VS 不会详细显示该步骤,它会简单地列出您链接的库文件。
      【解决方案4】:

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

      1. 在您的二进制文件上运行 nm 并获取所有未定义的符号
      2. 在您的二进制文件上运行 ldd 以获取其所有动态依赖项的列表(您的二进制文件链接到的.so 文件)
      3. 在步骤 2 中找到的每个 .so 文件上运行 nm

      这将为您提供二进制文件使用的动态符号的完整列表。

      例子:

      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
      

      所有大写“U”的符号都被ls命令使用。

      【讨论】:

        【解决方案5】:

        如果您的目标是分析 C 源文件,您可以通过自定义 GCC 编译器来实现。您可以为此目的使用MELT(MELT 是一种高级域特定语言来扩展 GCC)-在 GCC 中添加您自己的用 MELT 编码的分析通行证-,但您应该首先了解 GCC 中端内部表示(Gimple , 树, ...)。

        定制 GCC 需要几天的工作(主要是因为 GCC 内部在细节上相当复杂)。

        请随时向我询问有关 MELT 的更多信息。

        【讨论】:

          猜你喜欢
          • 2016-05-30
          • 2021-10-25
          • 2023-03-03
          • 1970-01-01
          • 2017-11-22
          • 1970-01-01
          • 1970-01-01
          • 2012-04-30
          • 2011-06-12
          相关资源
          最近更新 更多