Introduction to Libc-free programming
In the realm of software development, dependencies can be both a boon and a bane. On one hand, they expedite the development process, offering ready-made solutions for complex problems. On the other hand, they introduce a web of interdependencies, making projects vulnerable to version conflicts, security vulnerabilities, and bloated codebases.
What is libc?
The C standard library or libc is the standard library for the C programming language, as specified in the ISO C standard. Starting from the original ANSI C standard, it was developed at the same time as the C library POSIX specification, which is a superset of it. Since ANSI C was adopted by the International Organization for Standardization, the C standard library is also called the ISO C library. The C standard library provides macros, type definitions, and functions for tasks such as string handling, mathematical computations, input/output processing, memory management, and several other operating system services.
How can we write an application without libc?
To make it short, we’d need to contact the OS directly about what we want and provide our own functionality for managing the resources.
But, how do we make syscalls?
At low-level, we put some data in CPU registers, execute the syscall CPU instruction, and access the result in the returning register. CPU registers are super fast but have small storage which is built inside the CPU. We used them for various tasks like our use-case asking the OS to do an operation.
A typical syscall looks like this in Assembly. Some CPU instructions have no operands, some have 1, 2, 3, or more. A move instruction takes two operands (destination, source), and a syscall instruction takes no operands.
mov <REGISTER>, <DATA>
mov <REGISTER>, <DATA>
...
syscall
What register do we store this data? What are the data?
Short answer: Depends on the OS and the CPU architecture.
Read the next article to find out what syscalls look like in Linux.