Related to this other question. I am trying to run this simple C program in gem5:
int main() {
int a=1, b=2;
int c=a+b;
return c;
}
And it fails because gem5 doesn't have some syscalls implemented.
My question is, why would a simple program like this require syscalls? This should run bare-metal without trouble. Is there a way to compile this to avoid syscalls? I am using arm-linux-gnueabi-gcc -static -DUNIX to compile it.
Without syscalls the program cannot exit. The way it works is typically something like this:
// Not how it's actually implemented... just a sketch.
void _start() {
char **argv = ...;
int argc = ...;
// ... other initialization code ...
int retcode = main(argc, argv);
exit(retcode);
}
The exact details depend on the operating system, but exit(), which terminates the process, typically has to be a system call or is implemented with system calls.
Note that this is true for "hosted" C implementations, not for "freestanding" C implementations, and is highly operating-system specific. There are freestanding C implementations can run on bare metal, but hosted C implementations usually need an operating system.
You can compile without standard libraries and without the runtime but your entry point cannot return... there is nothing to return to, without a runtime.
It is generally possible to compile programs capable of running baremetal.
Use -ffreestanding. This makes GCC generate code that does not assume that the standard library is available (and has other effects).
Use -nostdlib. This will prevent GCC from linking with the standard library. Note that memcmp, memset, memcpy, and memmove calls may be generated anyway, so you may have to provide these yourself.
At this point you can write your program, but you typically have to use _start instead of main:
void _start(void) {
while (1) { }
}
Note that you can't return from _start! Think about it... there is nowhere to return to. When you compile a program like this you can see that it doesn't use any system calls and doesn't have a loader.
$ gcc -ffreestanding -nostdlib test.c
We can verify that it loads no libraries:
$ ldd a.out
statically linked
$ readelf -d a.out
Dynamic section at offset 0xf30 contains 8 entries:
Tag Type Name/Value
0x000000006ffffef5 (GNU_HASH) 0x278
0x0000000000000005 (STRTAB) 0x2b0
0x0000000000000006 (SYMTAB) 0x298
0x000000000000000a (STRSZ) 1 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x000000006ffffffb (FLAGS_1) Flags: PIE
0x0000000000000000 (NULL) 0x0
We can also see that it doesn't contain any code that makes system calls:
$ objdump -d a.out a.out: file format elf64-x86-64 Disassembly of section .text: 00000000000002c0 <_start>: 2c0: eb fe jmp 2c0 <_start>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With