所以我有一个可以正常构建和运行的应用程序。 我开始在它链接到的 20 多个静态和动态库中使用一些编译器设置,并且该应用程序在启动时在某个特定点始终崩溃。
我恢复了我的构建系统模组,应用程序又恢复正常了。 (但是,我忘了记下我实际所做的更改...)
纯粹出于兴趣,因为我仍然有一份错误的二进制文件(在调试模式下构建),所以我想尝试对我所做的事情进行逆向工程,以将事情搞砸。 :-)
附加调试器,我可以看到
.so
中的函数正在通过函数调用传递到主应用程序,供主应用程序用作回调的函数指针。
在调用者的框架中(在
.so
中)函数指针只有一个值。 在被调用者的框架中(在主应用程序中),函数指针神奇地具有不同的值。
当主应用程序尝试调用存储的函数指针时,程序会因段错误(映射器错误)而崩溃。 函数指针似乎仍然具有第二个值,这可能是错误的。
关于如何区分这个有什么建议吗?
更新: 根据要求提供更多详细信息。
崩溃地点:
0xfffffffffffeac58 ???????? ()
0x000000000063a040 app_exec_callbacks()
0xfffffd7ffea14514 dynlib_stuff ()
0x000000000063a15e other_app_stuff ()
0x00000000004d10a3 app_stuff ()
0x0000000000499f20 main ()
在此之前,函数
dynlib_do_setup()
通过调用 dynlib_callback_handler()
将函数指针(app_register_callback()
)传递给应用程序。
使用调试器,我可以看到在
dynlib_do_setup()
内函数指针的值为 0xfffffd7ffea13fa0
。在 app_register_callback()
的函数体内,参数突然变为 0xfffffffffffeac58
因此,
0xfffffffffffeac58
的垃圾值存储在应用程序的回调表中,毫不奇怪,当调用该回调地址时应用程序崩溃,如您在上面的堆栈跟踪中看到的那样。
再次,纯粹出于教育兴趣,这种神奇的腐败是如何/为什么会发生的? 如何/为什么恢复我的构建系统更改突然解决了这个问题?
看来你已经明白发生了什么事。也许在链接时发生了一些奇怪的事情(可能与重定位有关?)导致 main() 没有函数指针的正确地址。
找到答案:
编译器错误作为特定优化标志组合的结果。 过去 3 年已知但未修复。 :(