【问题标题】:How do I find out where main() is defined in a big project?如何找出大型项目中 main() 的定义位置?
【发布时间】:2022-01-02 18:43:13
【问题描述】:

假设我有以下程序 (a.c):

#include <stdio.h>

void f()
{
    printf("Hello, world!");
}

int main(void)
{
    f();
    return 0;
}
$ gcc -g a.c

拥有a.out,我如何找出main() 的定义位置?我的意思是,在一个大型项目中,main() 的来源并不总是很清楚。

【问题讨论】:

  • 既然你使用了像“nm”和“objdump”这样的标签,我想你已经知道你的问题的答案了吗?
  • in a big project it's not always clear where main() comes from grep -R main
  • @anatolyg 我知道他们可以给出答案,但我不知道如何解释他们的输出。
  • @KamilCuk 让我show你。
  • ?然后grep -R main | grep -v configure | grep -v aclocal 或使用--include=*.c 选项。还有grep -R 'int[[:space:]]*main[[:space:]]*\(' 或类似的。我猜主要在这里github.com/freedesktop/xorg-xserver/blob/…。还有 ctags、cscope、clangd 和类似的工具。

标签: c objdump dwarf nm readelf


【解决方案1】:

您可以使用gdb。可能有更好的命令,反正我知道:

$ gdb -batch -ex "info function main" a.out
All functions matching regular expression "main":

File a.c:
8:   int main(void);

【讨论】:

  • 这可能是最好的选择。至少它比我想象的要好,因为你不需要打扰 DWARF。不过这里应该注意,doesn't always 给出了正确的结果(这并不奇怪,因为它不适用于-flto)。使用gcc,您至少需要-g,并且不需要-flto。使用 Arch 构建系统,您需要 options=(debug !strip)...
  • ...对于meson,您需要确保没有-D b_lto=true。虽然我尝试使用readelf,但我可能已经找到了一种确定位置的经验方法(理论上这可能并不总是有效)。但我想知道gdb 究竟是如何做到的。那里有多个文件名表。有什么想法吗?
  • 这是不言自明的 - 当然,当可执行文件中没有调试信息或函数被删除或内联时,它不起作用。 C 是一种已编译的编程语言 - 您无法从可执行文件中恢复源代码,这是一种单向连接。 how exactly gdb does it 可执行文件中有一个调试部分,其中包含符号和位置列表,gdb 读取该部分。 file name tables there. Any ideas?什么是“文件名表”? ... 的想法?
  • 好的,有很多链接。我tried你的建议。我的理解是gdb.debug_info中找到一个符号,然后使用DW_AT_decl_file.debug_line中找到文件名。什么我不明白,.debug_line中有多个文件名表,它是怎么选表的?
【解决方案2】:

在可执行文件中通常不是查找函数定义的地方。您可以编译所有源文件并在它们上运行nm(1) 以查看它们是否有main 的定义。可执行文件不是正确的位置,因为它不会引用它来自的模块。源文件将很难遵循(因为有些编译指令可以带有可选编译的代码/带有main 定义,以防您不提供一个/这将使您找到它的位置不确定)但是编译的模块将引用main 以指示它可以获取它的链接器并解决此文件中的所有main 引用。链接器将编译后的输入分成一组段并将它们堆积到处理器内存映射中的适当位置,因此,您会得到一个混乱的最终可执行文件,其中每个模块的部分都混合在一起,这使得检查一个main 定义在那里(它适用于 main 或任何其他函数)

输出应该是这样的:

0000000000000c10 T main

在包含它的文件中。相反,链接器提供的所有需要​​ main 并需要它的文件都显示为:

                 U memset

改为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-16
    • 2018-08-10
    • 2017-02-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-17
    • 2016-01-07
    相关资源
    最近更新 更多