问题
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
回答1:
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.
- Add the flag
--specs=nano.specs
to your compiler and linker options. - Create the following function somewhere in your compiled code:
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.
回答2:
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
回答3:
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
.
来源:https://stackoverflow.com/questions/48711221/how-to-prevent-inclusion-of-c-library-destructors-and-atexit