I want to compile this C code with the GNU C Compiler on Ubuntu without linking any standard libraries, having only the following code execute.
static void exit(long long code)
{asm inline
("movq $60,%%rax\n"
"movq %[code],%%rdi\n"
"syscall"
:
:[code]"rm"(code)
:"rax"
,"rdi");}
static void write(long long fd,char *msg,long long len)
{asm inline
("movq $0x1,%%rax\n"
"movq %[fd],%%rdi\n"
"movq %[msg],%%rsi\n"
"movq %[len],%%rdx\n"
"syscall"
:
:[fd]"rm"(fd)
,[msg]"rm"(msg)
,[len]"rm"(len)
:"rax"
,"rdi"
,"rsi"
,"rdx");}
#define PRINT(msg) write(1,msg,sizeof(msg))
void _start()
{PRINT("Hello World.\n");
exit(0);}
I compiled with cc example.c -ffreestanding -nostartfiles -O3 -o example
.
When I called the output file I saw a lot of extra system calls with strace
that should not have been there:
I then compiled like this: cc example.c -c -O3 -o example.o; ld example.o -o example
and it did not do the extra syscalls. It even made the filesize somewhat smaller.
The objdump -d
of it was exactly the same. In the objdump -D
I found some extra symbols (_DYNAMIC,__GNU_EH_FRAME_HDR,.interp) in the first case compared to the second, but still no sign of any extra syscalls in the code.
Do you know why I get the extra system calls with cc example.c -ffreestanding -nostartfiles -O3 -o example
and not with cc example.c -c -O3 -o example.o; ld example.o -o example
?
I found out what is happening.
If I compile the code with cc example.c -ffreestanding -nostartfiles -O3 -o example
the compiler makes a dynamically linked executable. Dynamically linked executables have an .interp
section. That is what I was seeing in my objdump -D
.
Dynamically linked executables are executing via the program interpreter and the dynamic linker. The additional system calls I saw, came from the dynamic linker. I still do not know why the executable wants to dynamically link anything in a program that does not link any libraries and wants to be freestanding.
If you do not want the extra system calls from the dynamic linker - you should give gcc the extra -static
option. The compiler does not automatically do this if there is no dynamic linking happening.