The C runtime
Even though C is a relatively low-level language, some assembly code is needed to get the process in an acceptable state to the language standard.
First of all, main
isn't the standard entry point, _start
is. This function
is provided by your compiler, typically from a file called crt*.o
. This
function:
- aligns the stack
- reads
argc
,argv
,environ
and the auxiliary vector from the stack - sets up TLS, locales, and other crap
- calls
__libc_start_user
, which first calls the constructors of all global (C++) variables, then callsmain
, andexit
automatically as well.
Of course, it's huge, but we can provide our own: step 3 can be skipped, 1 and 2
are really small to implement in assembly, and 4 is replaced by calling main
.
Of course, the second step can be skipped as well when you don't need
args/environ.
However, when external libs need to read from the environment (eg. X11 needs
$DISPLAY
), you still have to call __libc_start_user
; it's a portable
interface that asks for argc
, argv
, envp
and main
. With smol, this
isn't exactly a hassle anymore.
For exiting the program when not using __libc_start_main
, you can just use a
bare syscall, or int3
.