如何使用gcc更改C程序的入口点?

如何使用gcc更改C程序的入口点?,c,main,entry-point,C,Main,Entry Point,如何更改使用gcc编译的C程序的入口点? 就像下面的代码一样 #include<stdio.h> int entry() //entry is the entry point instead of main { return 0; } #包括 int entry()//entry是入口点,而不是main { 返回0; } 这是一个链接器设置: -Wl,-eentry -Wl,东西将参数传递给链接器,链接器使用-e参数设置输入函数您可以将源代码修改为: #include

如何更改使用gcc编译的C程序的入口点?
就像下面的代码一样

#include<stdio.h>
int entry()  //entry is the entry point instead of main
 {
   return 0;
 }
#包括
int entry()//entry是入口点,而不是main
{
返回0;
}
这是一个链接器设置:

-Wl,-eentry

-Wl,
东西将参数传递给链接器,链接器使用
-e
参数设置输入函数

您可以将源代码修改为:

#include<stdio.h>

const char my_interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";

int entry()  //entry is the entry point instead of main
{
   exit(0);
}

如果您使用的系统提供(如Linux), 您可以使用
objcopy
命令 使任意函数成为新的入口点

假设一个名为
program.c
的文件包含
entry
函数:

$ cat > program.c
#include <stdio.h>
int entry()
{
    return 0;
}
^D
  • 然后将
    条目重新定义为
    main

    $ objcopy --redefine-sym entry=main program.o
    
  • 现在使用gcc编译新的对象文件:

    $ gcc -c program.c -o program.o
    
    $ gcc program.o -o program
    
  • 注意:如果您的程序已经有一个名为
    main
    的函数,在步骤2之前,您可以执行单独的
    objcopy
    调用:

    objcopy --redefine-sym oldmain=main program.o
    

    最小可运行示例和其他答案的注释

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    
    int mymain(void) {
        puts("hello");
        exit(0);
    }
    
    附注:

    • 如果没有
      -nostartfiles
      ,链接将失败:

      /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
      (.text+0x20): undefined reference to `main'
      collect2: error: ld returned 1 exit status
      
      大概是因为
      \u start
      中的glibc设置代码通常调用
      main

    • 命令行参数不是为您设置的,可能是因为它们是由在main之前运行的glibc代码设置的,所以尝试使用它们会打印未定义的值。我还没有找到适合他们的方法


    在Ubuntu20.10中测试。

    这是我用这个选项编译hello world C程序时得到的:
    $gcc-Wl,-emymain t27.C/usr/lib/gcc/i686 redhat linux/4.8.2/../../../crt1.o:在函数“\u start”:(.text+0x18):对“main”的未定义引用。
    @LeeDuhem,这是因为您将程序与标准c运行时库链接。与c运行时库链接的程序中的入口点是_start。Start引用了程序的main()(它希望程序使用main()func而不是自定义func)。尽量不要链接到crt并指定一个入口点作为您的\u main,看看会发生什么。@LeeDuhem,-nostlibs该标志是什么。
    -nostartfiles
    是您想要的实际标志,它省略了包含\u start的crt*.o文件,但仍然允许您使用libc(除非您也使用-nostlib或-nodefaultlibs,在这种情况下,您仍然可以使用-lc-lgcc等手动指定它们。)我相信有一个输入错误:应该是
    -Wl,--entry=“MyCutomEntryFunction”
    -Wl,-e=“MyCutomEntryFunction”
    什么是
    entry
    函数的调用约定?C-runtime是否以这种方式初始化?请您解释一下“将程序构建为可执行的共享库”是什么意思怎么可能两者都是?@harper:这不是一个与C兼容的调用约定。ELF入口点ABI的主参数在堆栈指针中,指向一个“数组”由argc、argv指针、null、env指针、null、辅助向量表组成。某些ARCH在特定寄存器中有其他arg。不起作用..I get:无法执行二进制文件:Exec格式error@iandotkelly不是OP,但我需要使用一个检查点库,它要求我将main()更改为其他内容;)@Nubcake您知道链接器的选项
    --wrap=xxx
    ?它将
    xxx
    的所有引用替换为
    \uuuuwrap\uxxx
    ,将
    xxx
    的所有定义替换为
    \uuuuureal\uxxx
    。我成功地将其用于测试
    main()
    。不起作用,显然警告很严重。@ScottFranco您的GCC版本/OS版本是什么?C:\projects\petit\u ami>GCC-v。。。gcc版本9.2.0(MinGW.org gcc Build-2)@ScottFranco警告是由小的打字错误引起的
    -eentry=
    应该是
    --entry=
    ;我已经相应地编辑了答案。@Demi Lune接球不错!我想知道在我的测试中它是如何与打字错误一起工作的!
    gcc -nostartfiles -Wl,--entry=mymain -o main.out main.c
    # or -Wl,-emymain
    ./main.out 1 2 3
    
    /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
    (.text+0x20): undefined reference to `main'
    collect2: error: ld returned 1 exit status