如何将可执行入口点的名称从main更改为其他名称?

时间:2015-02-12 19:07:02

标签: c gcc linker ld elf

我试图在Ubuntu Linux(12.04 x64)上使用gcc 4.8编译第三方源代码,其中包含大量实用程序和测试应用程序,其中可执行入口点不称为main。不要问我为什么 - 我不知道答案。

链接者当然抱怨:

/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status

是否可以强制链接器使用其他方法作为入口点?我尝试将这些链接器选项与gcc一起使用,但它们都不起作用: -Wl,-eWhatever-Wl,--entry=Whatever-Wl,-e,Whatever。全部以相同的错误结束。

1 个答案:

答案 0 :(得分:2)

就像C标准一样,托管环境(我想你的情况是/如果你想使用标准库标题*)强迫你保持main功能。从C11§5.1.2.2.1/ p1(强调我的):

  

程序启动时调用的函数名为main。该   实现声明此函数没有原型。它应该是   定义,返回类型为int且没有参数:

     

int main(void) { /* ... */ }

     

或带有两个参数(此处称为   argc和argv,虽然可以使用任何名称,因为它们是本地的   声明它们的函数:

     

int main(int argc, char *argv[]) { /* ... */ }

     

或等同物; 10)或其他一些   实现定义的方式。

在您的情况下,我可以考虑绕过main功能要求的两个选项:

  1. 使用gcc -c符号创建单独的目标文件(即main),只是(声明和)调用(即包装)自定义入口点(可能通过argcargv调用参数)。这将使链接器变得愉快,就像添加单个makefile规则一样简单。
  2. 将您的计划编译为gcc -DWhatever=main。这基本上用Whatever替换main预处理标记的每个实例,因此链接器认为Whatever是“正确”的主要功能。
  3. *某些标头也必须在独立环境中可用,例如<stddef.h><float.h>,有关完整列表,请参阅§4/ p6。

    以下是两种选择的基本说明。每个假设foo.c如下:

    foo.c

    #include <stdio.h>
    
    void foo(void)
    {
        printf("foo\n");
    }
    

    第一种方法:

    main.c

    /* declare an entry point */
    void foo(void);
    
    /* define main as wrapper function */
    int main(void)
    {
        foo();
    
        return 0;
    }
    

    编译&amp;运行:

    $ gcc -c main.c
    $ gcc foo.c main.o
    $ ./a.out
    foo
    

    第二种方法:

    $ gcc -Dfoo=main foo.c 
    $ ./a.out
    foo
    

    有些事情可能需要更多调整,但我希望你能抓住这个想法。