use*_*551 9 c embedded gcc arm bare-metal
对于Cortex-M4(裸机应用程序)使用arm-none-eabi-gcc,malloc即使我从未malloc在我的代码中使用过,也会发出代码.
看到程序集输出arm-none-eabi-objdump -xS obj.elf,似乎malloc通过被__register_exitproc调用来atexit调用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
Run Code Online (Sandbox Code Playgroud)
但是,register_fini从未在代码中调用过.main()使用以下启动代码调用,因此即使主要退出,atexit()也不会调用析构函数(或注册的函数).
/**
* \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);
}
Run Code Online (Sandbox Code Playgroud)
代码编译与-ffunction-sections和-fdata-sections,并与标志链接的--gc-sections,以便任何可达代码/功能不包括在输出文件中.
所以,我怎样才能阻止这些功能(register_fini,atexit,malloc等),这些从来没有在我的代码中使用被包含在目标文件中?
编译选项
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
Run Code Online (Sandbox Code Playgroud)
链接选项
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
Run Code Online (Sandbox Code Playgroud)
这是我正在使用的解决方法。不完美,但足够好。
使用--wrap的选项ld,我可以提供我自己的定义,但atexit它不会执行任何操作。
int __wrap_atexit(void __attribute__((unused)) (*function)(void)) {
return -1;
}
Run Code Online (Sandbox Code Playgroud)
然后与--wrap=atexit选项链接。
现在,atexit不调用任何其他函数,并且-ffunction-sections和--gc-sections选项确保它malloc不包含在输出文件中。
此外,为了强制malloc不包含该内容,--wrap=malloc可以在链接时传递一个选项,而无需在任何地方进行定义__wrap_malloc。如果某些其他函数碰巧使用了 ,这将失败并出现链接错误malloc。