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.
Seeing the assembly output with arm-none-eabi-objdump -xS obj.elf
, it seems that malloc
is called by __register_exitproc
called by atexit
called by register_fini
004036a8 <register_fini>:
4036a8: 4b02 ldr r3, [pc, #8] ; (4036b4 <register_fini+0xc>)
4036aa: b113 cbz r3, 4036b2 <register_fini+0xa>
4036ac: 4802 ldr r0, [pc, #8] ; (4036b8 <register_fini+0x10>)
4036ae: f000 b805 b.w 4036bc <atexit>
4036b2: 4770 bx lr
4036b4: 00000000 .word 0x00000000
4036b8: 004036c9 .word 0x004036c9
However, register_fini
is never called in the code. main()
is called using the following startup code, so even if main exits, the destructors (or functions registered with atexit()
) will not get called.
/**
* \brief This is the code that gets called on processor reset.
* To initialize the device, and call the main() routine.
*/
void Reset_Handler(void)
{
uint32_t *pSrc, *pDest;
/* Initialize the relocate segment */
pSrc = &_etext;
pDest = &_srelocate;
if (pSrc > pDest) {
for (; pDest < &_erelocate;) {
*pDest++ = *pSrc++;
}
} else if (pSrc < pDest) {
uint32_t nb_bytes = (uint32_t)&_erelocate - (uint32_t)&_srelocate;
pSrc = (uint32_t*)((uint32_t)pSrc + nb_bytes) - 1;
pDest = (uint32_t*)((uint32_t)pDest + nb_bytes) - 1;
for (;nb_bytes;nb_bytes -= 4) {
*pDest-- = *pSrc--;
}
}
__NOP();
/* Clear the zero segment */
for (pDest = &_szero; pDest < &_ezero;) {
*pDest++ = 0;
}
/* Set the vector table base address */
pSrc = (uint32_t *) & _sfixed;
SCB->VTOR = ((uint32_t) pSrc);
/* Initialize the C library */
__libc_init_array();
/* Branch to main function */
main();
/* Infinite loop */
while (1);
}
The code is compiled with -ffunction-sections
and -fdata-sections
and linked with the flag --gc-sections
so that any unreachable code/functions are not included in the output file.
So, how can I prevent these functions (register_fini
, atexit
, malloc
, etc) that are never used in my code from being included in the object file?
Compile options
arm-none-eabi-gcc -o build/main.o -c -mcpu=cortex-m4 -mthumb -pipe -g3 -Wall -Wextra -Wno-expansion-to-defined -Werror -std=gnu11 -fno-strict-aliasing -ffunction-sections -fdata-sections -DARM_MATH_CM4=true -D__SAM4SD32C__ -Ibunch -Iof -Iinclude -Idirs src/main.c
Link options
arm-none-eabi-g++ -o build/tnc.elf -mcpu=cortex-m4 -mthumb -pipe -Wl,--entry=Reset_Handler -Wl,--gc-sections -Wl,--script my/linker/script.ld build/src/bunch.o build/src/of.o build/src/object.o build/src/files.o build/src/main.o -lm
Probably you need -fno-use-cxa-atexit
argument for compiler.
Look on this simple example to get working C++ code on pure bare-metal: https://github.com/cortexm/baremetal
In an environment with limited memory such as the Cortex M4, another option is to use newlib-nano. It provides a __register_exitproc()
that is weakly linked. Therefore it is easy to override with your own empty function that avoids calling malloc()
. This will have the additional benefit of removing __call_exitprocs()
from your binary as well.
--specs=nano.specs
to your compiler and linker options.void __register_exitproc(void) { }
Note that this will prevent destructors being called for static instances of classes. This seems appropriate in your example.
See the comments in the newlib source for more details.
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
.
-nostartfiles
and -nostdlib
worked for me in a similar context.
User contributions licensed under CC BY-SA 3.0