Crt0
Set of execution startup routines linked into a C program
- 3 min read
- 2 chapters
Related on Lably
Form and usage
Crt0 generally takes the form of an object file called crt0.o, often originally written in assembly language, which is automatically included by the linker into every executable file it builds.
crt0 contains the most basic parts of the runtime library. As such, the exact work it performs depends on the program's compiler, operating system and C standard library implementation. Beside the initialization work required by the environment and toolchain, crt0 can perform additional operations defined by the programmer, such as executing C++ global constructors and C functions carrying GCC's ((constructor)) attribute.
Usually, crt0 does not contain more complex initialization code like the previously mentioned calling of functions carrying GCC's ((constructor)) attribute. Most modern libc implementations use __libc_start_main, a function written in C, to handle more complex tasks.
"crt" stands for "C runtime", and the zero stands for "the very beginning". However, when programs are compiled using GCC, it is also used for languages other than C. Alternative versions of crt0 are available for special usage scenarios; for example, to enable profiling with gprof, programs must be compiled with gcrt0 instead.
Sign in to keep reading
One more chapter is free with a Lably account.
Example crt0.s
This example is for Linux x86-64 with AT&T syntax, without an actual C runtime.
<span id="mwTg"></span><span class="na" id="mwTw">.text</span> <span class="na" id="mwUA">.globl</span><span class="w" id="mwUQ"> </span><span class="no" id="mwUg">_start</span> <span class="nl" id="mwUw">_start:</span><span class="w" id="mwVA"> </span><span class="c1" id="mwVQ"># _start is the entry point known to the linker</span> <span class="w" id="mwVg"> </span><span class="nf" id="mwVw">xor</span><span class="w" id="mwWA"> </span><span class="nv" id="mwWQ">%ebp</span><span class="p" id="mwWg">,</span><span class="w" id="mwWw"> </span><span class="nv" id="mwXA">%ebp</span><span class="w" id="mwXQ"> </span><span class="c1" id="mwXg"># effectively RBP := 0, mark the end of stack frames</span> <span class="w" id="mwXw"> </span><span class="nf" id="mwYA">mov</span><span class="w" id="mwYQ"> </span><span class="p" id="mwYg">(</span><span class="nv" id="mwYw">%rsp</span><span class="p" id="mwZA">),</span><span class="w" id="mwZQ"> </span><span class="nv" id="mwZg">%edi</span><span class="w" id="mwZw"> </span><span class="c1" id="mwaA"># get argc from the stack (implicitly zero-extended to 64-bit)</span> <span class="w" id="mwaQ"> </span><span class="nf" id="mwag">lea</span><span class="w" id="mwaw"> </span><span class="mi" id="mwbA">8</span><span class="p" id="mwbQ">(</span><span class="nv" id="mwbg">%rsp</span><span class="p" id="mwbw">),</span><span class="w" id="mwcA"> </span><span class="nv" id="mwcQ">%rsi</span><span class="w" id="mwcg"> </span><span class="c1" id="mwcw"># take the address of argv from the stack</span> <span class="w" id="mwdA"> </span><span class="nf" id="mwdQ">lea</span><span class="w" id="mwdg"> </span><span class="mi" id="mwdw">16</span><span class="p" id="mweA">(</span><span class="nv" id="mweQ">%rsp</span><span class="p" id="mweg">,</span><span class="nv" id="mwew">%rdi</span><span class="p" id="mwfA">,</span><span class="mi" id="mwfQ">8</span><span class="p" id="mwfg">),</span><span class="w" id="mwfw"> </span><span class="nv" id="mwgA">%rdx</span><span class="w" id="mwgQ"> </span><span class="c1" id="mwgg"># take the address of envp from the stack</span> <span class="w" id="mwgw"> </span><span class="nf" id="mwhA">xor</span><span class="w" id="mwhQ"> </span><span class="nv" id="mwhg">%eax</span><span class="p" id="mwhw">,</span><span class="w" id="mwiA"> </span><span class="nv" id="mwiQ">%eax</span><span class="w" id="mwig"> </span><span class="c1" id="mwiw"># per ABI and compatibility with icc</span> <span class="w" id="mwjA"> </span><span class="nf" id="mwjQ">call</span><span class="w" id="mwjg"> </span><span class="no" id="mwjw">main</span><span class="w" id="mwkA"> </span><span class="c1" id="mwkQ"># %edi, %rsi, %rdx are the three args (of which first two are C standard) to main</span> <span class="w" id="mwkg"> </span><span class="nf" id="mwkw">mov</span><span class="w" id="mwlA"> </span><span class="nv" id="mwlQ">%eax</span><span class="p" id="mwlg">,</span><span class="w" id="mwlw"> </span><span class="nv" id="mwmA">%edi</span><span class="w" id="mwmQ"> </span><span class="c1" id="mwmg"># transfer the return of main to the first argument of _exit</span> <span class="w" id="mwmw"> </span><span class="nf" id="mwnA">xor</span><span class="w" id="mwnQ"> </span><span class="nv" id="mwng">%eax</span><span class="p" id="mwnw">,</span><span class="w" id="mwoA"> </span><span class="nv" id="mwoQ">%eax</span><span class="w" id="mwog"> </span><span class="c1" id="mwow"># per ABI and compatibility with icc</span> <span class="w" id="mwpA"> </span><span class="nf" id="mwpQ">call</span><span class="w" id="mwpg"> </span><span class="no" id="mwpw">_exit</span><span class="w" id="mwqA"> </span><span class="c1" id="mwqQ"># terminate the program</span>

