Arush Agarampur
Arush Agarampur

Reputation: 1420

Dropping C library on Linux w/GCC

I'm trying to create a basic application which is heavy on raw syscalls only, and I don't need the C library. I'm also trying to keep size to an absolute minimum. For functions like strcpy, strcmp, I'm hoping to use compiler intrinsics.

On Windows with MSVC/GCC I can use /NODEFAULTLIB or -nostdlib to detach from the C standard library. Then I'll simply link to kernel32.lib, user32.lib, to use functions like WriteFile, CreateWindowExW, etc. I'm trying to do the same on linux but I'm running into a few problems.

It seems like for some reason, the code of the syscalls read, write, ptrace, process_vm_readv, etc are actaully in gclib? I tried to use syscall(SYS_write, ...) as well as I was hoping that'd be inlined into my program somehow but that still needs gclib. Is there a way to call these syscalls like on Windows, where I'd link to a system library instead of the C library? I'd like to avoid writing the syscall stubs myself using inline ASM. I'm starting to work with linux programming like this so I'm not too sure. Here's a simple test application I'm using (which isn't compiling):

#include <unistd.h>

void ProcessEntry()
{
    write(STDOUT_FILENO, "Detached from CRT", 18);
    _exit(0);
}

I'm using the command: gcc -c program.c and ld program.o -nostdlib -e ProcessEntry.

Upvotes: 0

Views: 170

Answers (1)

Zan Lynx
Zan Lynx

Reputation: 54325

Here is what I got:

#include <sys/syscall.h>

// Copied from MUSL libc
// There are more at
// http://git.musl-libc.org/cgit/musl/tree/arch/x86_64/syscall_arch.h
static __inline long __syscall1(long n, long a1) {
  unsigned long ret;
  __asm__ __volatile__("syscall"
                       : "=a"(ret)
                       : "a"(n), "D"(a1)
                       : "rcx", "r11", "memory");
  return ret;
}

void do_exit(int status) { __syscall1(SYS_exit, status); }

void entry() { do_exit(5); }

Saved as syscall.c and compiled with

cc -Wall -W -pedantic -static -O3 -march=native -flto -fno-fat-lto-objects  -fPIC -fPIE -fstack-protector-strong -std=gnu18 -nostdlib -e entry  syscall.c   -o syscall

And this is the entire disassembly of the 9,224 byte program:

0000000000001000 <entry>:
    1000:   f3 0f 1e fa             endbr64
    1004:   b8 3c 00 00 00          mov    $0x3c,%eax
    1009:   bf 05 00 00 00          mov    $0x5,%edi
    100e:   0f 05                   syscall
    1010:   c3                      retq

Upvotes: 3

Related Questions