Search code examples
csystemglibclibclow-level

Implement my own syscalls


Follow-up to this question. I'm writing my own (very basic) standard library (compiling with the -nostdlib gcc option). It seems that the base of almost everything is write, read, creat, open, close, etc.

It's my understanding that glibc simply uses stubs, SYSCALL_INTERNAL macros, etc. to provide those functions. I'm not using glibc and I don't want to get very complicated.

My question. How can I call Unix low-level functions such as write and read without glibc?


Solution

  • You can make system calls directly from assembly language, for example, for Linux x86_64:

    main.c:

    long mywrite(int, const void *, unsigned long);
    
    int main(void)
    {
        char buffer[] = "Hello, world!\n";
        mywrite(1, buffer, 14);
        return 0;
    }
    

    write.S:

    .global mywrite
    
    .text
    
    mywrite:
            push    %rbp
            mov     %rsp, %rbp
            mov     $1, %rax
            syscall
            leave
            ret
    

    with output:

    paul@thoth:~/src/sandbox/syscall$ gcc -o sc main.c write.S
    paul@thoth:~/src/sandbox/syscall$ ./sc
    Hello, world!
    paul@thoth:~/src/sandbox/syscall$ 
    

    Obviously this implementation doesn't set errno or anything like that, but that's unrelated to actually making the system calls. It'll be easier to implement a single syscall() function in assembly, and then have regular C functions to call it.