如何找到程序的主要(...)功能?

时间:2009-03-05 12:03:38

标签: c++ unix gcc gdb

我目前正在将一个包含几百个代码文件和依赖项的项目移植到几个第三方库到Mac Os。我终于达到了程序在没有警告或错误的情况下编译的程度,但它似乎没有执行我自己的主函数。

相反,它似乎执行一些似乎属于第三方的其他主要功能。此函数将一些诊断外观数据写入控制台并随后退出:

(gdb) continue
Current language:  auto; currently c++
//
// This is an automatically generated file.
// Do not edit.
//

const unsigned short expTable[] =
{
    0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 
...
    0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 
};

Debugger stopped.
Program exited with status value:0.

我无法使用调试器找出此主函数所在的位置,因为虽然堆栈跟踪似乎有效,但gdb没有显示每个堆栈条目的正确行号和文件名(请参阅{{3}有关细节)。

搜索需要几分钟才能完成,但没有返回任何结果。

我的项目在其他库中使用SDL,但我获得了SDL_Main()和潜在的问题,并在一个完美的工作SDL项目模板上构建了我的项目。所以我很确定我自己的主要功能是有效的。

你知道可能出现什么问题吗?我目前没有关于如何查找和删除流氓主要功能的想法。

谢谢,

阿德里安

编辑:正如我刚刚发现的那样,我在使用字符串“这是一个自动生成的”搜索文件时犯了一个错误。我刚刚发现了几十个具有相同字符串的文件,都属于FreeImage,我正在使用的第三方库之一。所以,问题似乎与FreeImage有关,但我仍然不确定如何继续,因为我已经将Freeimage编译为带有封闭的MacOs makefile的库,并且仅包含库。我将尝试重建一个较新版本的FreeImage并查看它是否解决了我的问题。

10 个答案:

答案 0 :(得分:8)

它是否是在调用main()之前失败的静态对象的初始值设定项?

答案 1 :(得分:3)

你在二进制文件中有几个主要内容吗?尝试使用nm(因为ld不会与重复项链接,所以不应该这样,但是进入动态库并在那里寻找_main

nm a.out | grep -5 _main

这应该在二元_main

中找到的任何a.out之前和之后提供5行

如果您有多个,请参阅周围的符号以了解提示它们所在的部分......

下一步可以在使用的每个动态库上执行相同的操作。获取使用的动态库列表 otool

otool -L a.out

答案 2 :(得分:2)

我不确定如何找到另一个,但您可以明确指定自己的入口点,并使另一个未使用。您可以使用GNU链接器ld -e选项设置入口点。

  

-e条目

     

- 条目=条目

     

使用条目作为开始执行的明确符号   程序,而不是默认入口点。如果没有sym-   bol命名条目,链接器将尝试将条目解析为数字,   并将其用作入口地址(该数字将被解释   在基地10;您可以使用前导0x表示基数16或前导0   基地8)。

对于未来的读者,如果您在Windows中遇到此问题。等效的链接器选项是/ENTRY

答案 3 :(得分:1)

您是否尝试通过nm运行可执行文件?它可能会给你一些提示。我不认为将一个程序与多个名为main()的全局可见函数链接起来是不可能的,不确定它是如何实现的。

答案 4 :(得分:1)

查看您包含的头文件,看看是否没有将main重新映射到其他内容的定义。这是一个老技巧,以确保首先调用库的主函数来进行一些设置。通常,它最终会通过引用重新定义的值来调用主函数。

答案 5 :(得分:1)

快速破解:

readelf -s -w my_bin_file > temp.txt

打开temp.txt,搜索main(在一列中使用FUNC) 上去,直到找到第一个FILE列 - 这是带有链接主文件的文件。

编辑:这仅适用于GNU Unix风格和朋友。 OS X使用Mach-O格式,而不是ELF。

答案 6 :(得分:0)

我知道在C中,你可以在main函数之前调用一个不同的入口点,这可能是一个想法。代码通常如下:

void __attribute__ ((constructor)) my_main(void);

也许您可以在代码中搜索类似的内容。

在C中,还有不同的方法来捕获主函数并在“真实”主函数之后调用它。一些线程库有这种黑客攻击,以“准备”环境,调度程序和类似的东西。

这不是很有用,但这可以解释为什么你的主要根本没有被调用。

希望这有帮助!

答案 7 :(得分:0)

另一个注意事项。

WxWidgets也定义了自己的main

来自here

  

与所有程序一样,必须有“主要”功能。在wxWidgets下,main使用这个宏实现,它创建一个应用程序实例并启动程序。

     

IMPLEMENT_APP(MyApp)

答案 8 :(得分:0)

看起来您可以将一个名为b44ExpLogTable.cpp的文件编译到您的二进制文件或某些第三方库中。看起来这个小程序是生成一个exp()表,但不知何故会被导入到你的项目中

请参阅this

中的FreeImage sources和此内容

答案 9 :(得分:0)

生成地图文件。大多数程序实际上并不是从main开始的。来自GCC的mapfile应该告诉你__start或__executable_start的地址,你应该能够进入该地址并逐步查看导致你的程序退出的原因。