This should happen "automatically" as long as your libc and linker setup supports it. You haven't told what your platform is, so here is one where it does work.
So, let's create a silly example using snprintf.
/*
* main.c
*/
#include <stdio.h>
int main(int argc, char **argv) {
char l[100];
snprintf(l, 100, "%s %d\n", argv[0], argc);
return 0;
}
try to compile and link it
$ CC=/opt/gcc-arm-none-eabi-4_7-2013q3/bin/arm-none-eabi-gcc
$ CFLAGS="-mcpu=arm926ej-s -Wall -Wextra -O6"
$ LDFLAGS="-nostartfiles -L. -Wl,--gc-sections,-emain"
$ $CC $CFLAGS -c main.c -o main.o
$ $CC $LDFLAGS main.o -o example
/opt/gcc-arm-none-eabi-4_7-2013q3/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0x18): undefined reference to `_sbrk'
collect2: error: ld returned 1 exit status
It needs _sbrk
because newlib *printf
functions use malloc
which needs a way to allocate system memory. Let's provide it a dummy one.
/*
* sbrk.c
*/
#include <stdint.h>
#include <unistd.h>
void *_sbrk(intptr_t increment) {
return 0;
}
and compile it
$ $CC $CFLAGS -c sbrk.c -o sbrk.o
$ $CC $LDFLAGS -Wl,-Map,"sbrk.map" main.o sbrk.o -o with-sbrk
$ /opt/gcc-arm-none-eabi-4_7-2013q3/bin/arm-none-eabi-size with-sbrk
text data bss dec hex filename
28956 2164 56 31176 79c8 with-sbrk
Well, that's the reason you'd like to get rid of printf
and friends, isn't it? Now, replace snprintf
with our function
/*
* replace.c
*/
#include <stdio.h>
#include <string.h>
int snprintf(char *str, size_t size, const char *format, ...) {
return strlen(format);
}
then compile
$ $CC $CFLAGS -c replace.c -o replace.o
$ $CC $LDFLAGS -Wl,-Map,"replace.map" main.o replace.o -o with-replace
$ /opt/gcc-arm-none-eabi-4_7-2013q3/bin/arm-none-eabi-size with-sbrk
text data bss dec hex filename
180 0 0 180 b4 with-replace
Note that we did not use the _sbrk
stub at all. As long as you don't provide _sbrk
, you can be sure that malloc
is not (can't be) linked and used.