You want to link with libc.so
. Try adding -lc
in the link step in your makefiles.
Update after Better Understanding of the Question
The Baking Pi examples build a kernel.img
that runs in place of the usual Linux kernel. This means that the C standard library is not available. You'll need to supply your own sprintf()
implementation, e.g.:
- Adapt this BSD licensed ee_printf.c
- Remove
uart_send_char()
- Adapt
ee_printf()
into sprintf()
by making buf
a function parameter
Why a Userspace libc Wouldn't Work Without Source Modifications in any Kernel
Conceptually:
- The C standard library contains facilities dealing with dynamic memory allocation (
malloc
, free
), the file system (fopen
, fclose
and all of stdio), environment variables (getenv
), error handling facilities like setjmp
longjmp
and more.
- Consider: how would you implement
malloc
in a program running under an operating system?
- Answer: You'd need some interface to request additional memory from the OS, such as
brk
, sbrk
and mmap
under Linux.
- In an OS kernel,
brk
, mmap
etc wouldn't be the right interfaces to allocate memory.
- Thus though most non-toy kernels provide
malloc
like facilities, they won't be able to use the userspace malloc
implementations unmodified.
- In an OS kernel, functions like
fopen
, getenv
are not really that useful. Most kernel writers choose not to include them.
- Thus most kernels don't include complete C standard library implementations but only the functions that the kernel writers find useful.
In a more mechanical sense:
- The Baking Pi Makefile produces the kernel ELF image with the command
$(ARMGNU)-ld --no-undefined $(OBJECTS) -Map $(MAP) -o $(BUILD)output.elf -T $(LINKER)
. This doesn't link build/output.elf
with any libc implementation so the linker wouldn't be able to find a symbol named sprintf
.
- When you build a program with
gcc T.c -o T
, gcc implicitly links in libc unless an option like -nostdlib
is passed.
But the conceptually important points are:
- The parts of the C standard library that are useful in a kernel would require different implementations
- A lot of other parts of libc wouldn't be that useful in a kernel
There are C standard library implementations targeting bare metal environments. See for example, newlib.