Using arm-none-eabi-gcc for Cortex-M4 (baremetal application), the code for malloc is also emitted even though I never use malloc in my code.
S
So here's the workaround that I'm using. Not perfect, but good enough.
Using the --wrap option of ld, I can provide my own definition for atexit that doesn't do anything.
int __wrap_atexit(void __attribute__((unused)) (*function)(void)) {
return -1;
}
and then link with --wrap=atexit option.
Now, atexit does not call any other functions and the -ffunction-sections and --gc-sections options ensure that malloc is not included in the output file.
Additionally, to enforce that malloc isn't included, a --wrap=malloc option can be passed while linking without defining __wrap_malloc anywhere. This will fail with a link error if some other function happens to use malloc.