How kernel, compiler, and C library work together: Difference between revisions

m
Cleared up the syntax and layout
[unchecked revision][unchecked revision]
m (→‎__alloca, ___main: minor markup and grammar fixes)
m (Cleared up the syntax and layout)
Line 46:
Some advanced operations (e.g. 64-bits divisions on a 32-bits system) might involve ''compiler-internal'' functions. For [[GCC]], those functions are residing in libgcc.a. The content of this library is agnostic of what OS you use, and it won't taint your compiled kernel with licensing issues of whatever sort, so you are welcome to locate "libgcc.a" and link it with your kernel.
 
== Linker ==
 
A linker takes the object code generated by the compiler / assembler, and ''links'' it against the C library (and / or libgcc.a or whatever link library you provide). This can be done in two ways: static, and dynamic.
 
== =Static Linking ===
 
When linking statically, the linker is invoked during the build process, just after the compiler / assembler run. It takes the object code, checks it for unresolved references, and checks if it can resolve these references from the available libraries. It then adds the binary code from these libraries to the executable; after this process, the executable is ''complete'', i.e. when running it does not require anything but the kernel to be present.
Line 56:
On the downside, the executable can become quite large, and code from the libraries is duplicated over and over, both on disk and in memory.
 
== =Dynamic Linking ===
 
When linking dynamically, the linker is invoked during the ''loading'' of an executable. The unresolved references in the object code are resolved against the libraries currently present in the system. This makes the on-disk executable much smaller, and allows for in-memory space-saving strategies such as ''shared libraries'' (see below).
Line 62:
On the downside, the executable becomes dependent on the presence of the libraries it references; if a system does not have those libraries, the executable cannot run.
 
== =Shared Libraries ===
 
A popular strategy is to ''share'' dynamically linked libraries across multiple executables. This means that, instead of attaching the binary of the library to the executable image, the references in the executable are tweaked, so that all executables refer to the same in-memory representation of the required library.
Line 70:
Second, in a virtual memory environment, it is usually impossible to provide a library to all executables in the system at the same virtual memory address. To access library code at an arbitrary virtual address requires the library code to be ''position independent'' (which can be achieved e.g. by setting the -PIC command line option for the [[GCC]] compiler). This requires support of the feature by the binary format (relocation tables), and can result in slightly less efficient code on some architectures.
 
== =ABI - Application Binary Interface ===
 
The ABI of a system defines how library function calls and kernel system calls are actually done. This includes e.g. whether parameters are passed on the stack or in registers, how function entry points are located in libraries etc.
Line 76:
When using static linkage, the resulting executable is depending on the executing kernel using the same ABI as the one it was built for; when using dynamic linkage, the executable is depending on the libraries' ABI staying the same.
 
== =Unresolved Symbols ===
 
The linker is the stage where you will find out about stuff that has been added without your knowledge, and which is not provided by your environment. This can include references to <tt>alloca()</tt>, <tt>memcpy()</tt>, or several others. This is usually a sign that either your toolchain or your command line options are not correctly set up for compiling your own OS kernel - or that you are using functionality that is not yet implemented in your C library / runtime environment!
Line 84:
Other kind of symbols such as _udiv* or __builtin_saveregs are available in the OS-agnostic "libgcc.a". If get error about missing such symbols, try to link your kernel against that library too. See [[Topic:10783|this thread]] for details.
 
== __alloca, ___main ==
 
<tt>alloca()</tt> is a "semi-standard" C function (from BSD?, but supported by most C implementations) that is used to allocate memory from the stack. On Windows this function is also used for stack probing. As such, <tt>alloca()</tt> is referenced in PE binaries, build e.g. by the Cygwin GCC. You can set <tt>-mno-stack-arg-probe</tt> to suppress those references.
Line 112:
"The alloca() function allocates space in the stack frame of the caller, and returns a pointer to the allocated block. This temporary space is automatically freed when the function from which alloca() is called returns."
 
On Windows:
 
On Windows:
"_alloca allocates size bytes from the program stack. The allocated space is automatically freed when the calling function exits (not when the allocation merely passes out of scope). Therefore, do not pass the pointer value returned by _alloca as an argument to free."
 
Line 128:
</blockquote>
 
== memcpy ==
 
This function is used internally by [[GCC]]. You should set the <tt>--no-builtin</tt> switch, and provide your own implementation of <tt>memcpy()</tt> if you want to be independent of [[GCC]] ([http://my.execpc.com/~geezer/osd/code/ OSD library] just has it ;).
Anonymous user