How to change the entry point of a C program compiled with gcc ?
Just like in the following code
#include<stdio.h>
int entry() //entry is the entry point instead of main
{
return 0;
}
How to change the entry point of a C program compiled with gcc ?
Just like in the following code
#include<stdio.h>
int entry() //entry is the entry point instead of main
{
return 0;
}
It's a linker setting:
-Wl,-eentry
the -Wl,...
thing passes arguments to the linker, and the linker takes a -e
argument to set the entry function
$ gcc -Wl,-emymain t27.c /usr/lib/gcc/i686-redhat-linux/4.8.2/../../../crt1.o: In function '_start': (.text+0x18): undefined reference to 'main'
–
Challis -nostartfiles
is the actual flag you want, this omits the crt*.o files containing _start, but still allows you to use a libc (unless you also use -nostdlib or -nodefaultlibs, in which case you can still manually specify them using -lc -lgcc etc...) –
Varga -Wl,--entry="MyCutomEntryFunction"
or -Wl,-e="MyCutomEntryFunction"
–
Mcmullen If you are on a system that provides GNU Binutils (like Linux),
you can use the objcopy
command
to make an arbitrary function the new entry point.
Suppose a file called program.c
containing the entry
function:
$ cat > program.c
#include <stdio.h>
int entry()
{
return 0;
}
^D
You first compile it using -c
to generate a relocatable object file:
$ gcc -c program.c -o program.o
Then you redefine entry
to be main
:
$ objcopy --redefine-sym entry=main program.o
Now use gcc to compile the new object file:
$ gcc program.o -o program
NOTE: If your program already has a function called main
, before step 2, you can perform a separate objcopy
invocation:
objcopy --redefine-sym oldmain=main program.o
You can modify your source code as:
#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);
}
The ".interp" section will let your program able to call external shared library. The exit call will make your entry function to exit program instead of return.
Then build the program as a shared library which is executable:
$ gcc -shared -fPIC -e entry test_main.c -o test_main.so
$ ./test_main
entry
function? Is the C-runtime initialized in this way? –
Ruthy Minimal runnable example and notes on other answers
main.c
#include <stdio.h>
#include <stdlib.h>
int mymain(void) {
puts("hello");
}
compile and run:
gcc -nostartfiles -Wl,--entry=mymain -o main.out main.c
# or -Wl,-emymain
./main.out 1 2 3
The notes:
without -nostartfiles
, the link fails with:
/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
presumably because the glibc setup code that runs before main in _start
normally calls main
.
command line arguments are not setup for you, presumably because they would be setup by the glibc code that runs before main, so trying to use them prints undefined values. I haven't found a method that works for them.
Another option is to remove -nostartfiles
is to just define a dummy main
:
#include <stdio.h>
#include <stdlib.h>
int main(void) {}
int mymain(int argc, char **argv) {
(void)argv;
printf("%d\n", argc);
exit(0);
}
which then compile and runs fine with:
gcc -nostartfiles -Wl,--entry=mymain -o main.out main.c
# or -Wl,-emymain
./main.out 1 2 3
CLI args are still broken, but perhaps more things stdlib things will work like this.
Tested in Ubuntu 23.10.
-eentry=
should have been --entry=
; I've edited the answer accordingly. –
Record -nostartfiles
is not guaranteed to work I think. –
Stomatology If you're doing this on a hosted environment (i.e. Linux, Windows etc.) it's probably a much better idea to use the linker to redefine which function becomes main()
with this:
-Wl,--defsym=main=some_other_entry_point
This way, the function being called at startup is still main()
, so your operating system's _start()
code will still work as normal. If you try to actually change the entry point name with --entry
, you'll probably run into a lot of issues because the OS's _start
won't be called.
#include <stdio.h>
int main(void) {
printf("wrong\n");
}
int some_other_entry_point(void) {
printf("right\n");
}
gcc -Wl,--defsym=main=some_other_entry_point -o test test.c
$ ./test
right
© 2022 - 2024 — McMap. All rights reserved.
--wrap=xxx
? It replaces all references ofxxx
by__wrap_xxx
and all definitions ofxxx
by__real_xxx
. I used it successfully for testing amain()
. – Waxler