【问题标题】:Changing main of a C++ project without using the -nostartfiles option在不使用 -nostartfiles 选项的情况下更改 C++ 项目的 main
【发布时间】:2018-12-08 05:14:18
【问题描述】:

在给定的 C++ 项目中,我正在尝试将 main 更改为我的 newEntry.cpp:

void entry(){
...
}

根据一些在线帖子,要做到这一点,您应该使用这些链接器选项:

-e entry newEntry.cpp -nostartfiles

-e "symbol" "file" 将新的主文件提供给链接器,而 -nostartfiles 省略了 crt* 文件,因此它不提供实际的主文件。

问题是crt.*中定义了一个隐藏符号_dso_handler,所以通过使用这种方法,你最终会得到这个错误:

/usr/include/c++/4.7/iostream:75: undefined reference to `__dso_handle'

-nostartfiles 在这里引起了一个新问题。我怎么能解决这个问题?
我可以尝试提供 _dso_handle (我不知道如何),但我怀疑新的错误来自于 crt* 文件被省略的事实。我在一些帖子上读到,使用 -nostartfiles 更改 C/C++ 项目的入口点今天已经过时了。

那么还有其他方法可以更改我的项目的主要内容吗?

提前感谢您的帮助

【问题讨论】:

  • 你不能简单地做int main() { entry(); }有什么具体原因吗?
  • 是的,我在运行实际的 main 时遇到了段错误。
  • 其实main 不是入口点。相反,这是一个符号_start。此函数执行 crt* 文件成员的初始化(动态链接所需的数据为 __dso_handle、静态变量的动态初始化、线程本地管理的数据等)。在执行完这些初始化之后,它会调用 main,并且在 main 返回之后,它会执行清理。所以可能不想改变入口点!您需要以某种方式重命名符号main 或插入main(在crt1.so 中引用)。
  • 所以要么重新编译 crt1.so 的源文件(我想它是在 glibc 中定义的)。或者,链接器脚本可能会完成我不是魔术师链接器大师无法完成的工作或事情。
  • 最后我在 glibc/sysdeps../start.S 中发现你可以提供你的“入口点”,这些入口点将在进程初始化之前和之后执行。这里有一个很好的解释:dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html

标签: c++ gcc compilation linker


【解决方案1】:

我刚刚找到了最方便的解决方案:使用ld wrap main, demo:

#include <iostream>

extern "C" int __real_main(int argc,char* argv[]);//other name for main
extern "C" int __wrap_main(int argc,char* argv[]){//called in place of main
   std::cout << "Executing " << argv[0] << std::endl;
   int ret = __real_main(argc,argv);
   std::cout << "main returned " << ret << std::endl;
   return ret;
   }
 int main(int argc,char* argv[]){
   std::cout << "Main execution" << std::endl;
   return 42;
   }

使用链接器选项--wrap=mainc++ -Wl,--wrap=main file.cpp 进行编译。瞧!

Live demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-23
    • 1970-01-01
    • 2019-05-09
    相关资源
    最近更新 更多