Why would a simple C program need syscalls?

雨燕双飞 提交于 2020-01-02 06:14:05

问题


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.


回答1:


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.

Creating a baremetal program

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>



回答2:


My question is, why would a simple program like this require syscalls?

The run-time loader ld.so does syscalls. The C run-time does syscalls. Do strace <application> and see.




回答3:


There are some parameters to gcc you might want to checkout. Among others:

  • -ffreestanding
  • -nostdlib
  • -nodefaultlibs

My question is, why would a simple program like this require syscalls?

Because entering main and exiting the program is based on syscalls.




回答4:


Compiling with arm-unknown-linux-uclibcgnueabi solved the issue. Apparently uclibc implementation doesn't use the syscalls that gem5 doesn't have implemented.



来源:https://stackoverflow.com/questions/51270445/why-would-a-simple-c-program-need-syscalls

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!