А как дергать системные вызовы из C?

Как напрямую использовать системные вызовы из C, при -nostdlib? Код:

int main() {
    write(1, "It works\n", 10);
    return 0;
}
 ~ $ gcc print.c -nostdlib
ld.lld: undefined symbol write

Постойте, write() же системный вызов... Тот же ассемблер все системные вызовы осуществляет без библиотек (даже статических, ну а иначе не было бы этих ваших реверс шеллов на 237 байт). Так а на более простом и родном C или C++ как это сделать-то?


Ответы (1 шт):

Автор решения: x_error

Чтобы использовать системные вызовы без библиотек нужно самому определить интерфейс для системных вызовов и использовать ассемблер для их вызова:

// syscalls.c
#define SYSCALL_WRITE 1
#define SYSCALL_EXIT 60

void _start() {
    const char *msg = "Hello, World!\n";
    // Делаем системный вызов write
    asm volatile (
        "mov rax, %0\n"   // номер системного вызова (1 - write)
        "mov rdi, 1\n"    // file descriptor (1 - stdout)
        "mov rsi, %1\n"   // указатель на буфер
        "mov rdx, %2\n"   // размер буфера
        "syscall\n"
        :
        : "r"(SYSCALL_WRITE), "r"(msg), "r"(13)  // 13 - длина строки
        : "rax", "rdi", "rsi", "rdx"
    );

    // Делаем системный вызов exit
    asm volatile (
        "mov rax, %0\n"// номер системного 
   вызова (60 - exit)
        "xor rdi, rdi\n"  // код возврата 0
        "syscall\n"
        :
        : "r"(SYSCALL_EXIT)
        : "rax", "rdi"
    );
}
→ Ссылка