Customized C library startup code and access to C library functions
If you build an application with customized startup code, you must either avoid functions that require initialization or provide the initialization and low-level support functions.
When building an application without the C library, if you create an application that includes a main() function, the linker automatically includes the initialization code necessary for the execution environment. There are situations where this is not desirable or possible. For example, a system running a Real-Time Operating System (RTOS) might have its execution environment configured by the RTOS startup code.
You can create an application that consists of customized startup code and still use many of the library functions. You must either:
Avoid functions that require initialization.
Provide the initialization and low-level support functions.
The functions you must re-implement depend on how much of the library functionality you require:
If you want only the compiler support functions for division, structure copy, and floating-point arithmetic, you must provide __rt_raise(). This also enables very simple library functions such as those in errno.h, setjmp.h, and most of string.h to work.
If you call setlocale() explicitly, locale-dependent functions are activated. This enables you to use the atoi family, sprintf(), sscanf(), and the functions in ctype.h.
Programs that use floating-point must call _fp_init(). If you select software floating-point in --fpmode=ieee_fixed or --fpmode=ieee_full mode, the program must also provide __rt_fp_status_addr().
Implementing high-level input/output support is necessary for functions that use fprintf() or fputs(). The high-level output functions depend on fputc() and ferror(). The high-level input functions depend on fgetc() and __backspace().
Implementing these functions and the heap enables you to use almost the entire library.