![](/img/trans.png)
[英]Undefined reference to __dso_handle_ - compiling C++ on cygwin
[英]Undefined reference to _fini and __dso_handle when compiling c++ for arm cortex M3
我正在尝试为 arm cortex-m3 编译 c++ 代码。 当我使用任何 class 的 static 变量时,它具有自定义析构函数(例如 std::function<>),我收到以下错误:
/Applications/ARM/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: CMakeFiles/app.dir/src/acc_lis.cpp.obj: in function `unsigned char* std::__copy_move<false, true, std::random_access_iterator_tag>::__copy_m<unsigned char>(unsigned char const*, unsigned char const*, unsigned char*)':
/Applications/ARM/arm-none-eabi/include/c++/10.3.1/bits/stl_algobase.h:426: undefined reference to `__dso_handle'
/Applications/ARM/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: /Applications/ARM/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp/libg.a(lib_a-fini.o): in function `__libc_fini_array':
fini.c:(.text.__libc_fini_array+0x20): undefined reference to `_fini'
/Applications/ARM/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: app.elf: hidden symbol `__dso_handle' isn't defined
/Applications/ARM/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: final link failed: bad value
根据我的阅读,问题是 c++ 在调用 exit() 后尝试调用析构函数(我没有手动调用)。 __dso_handle 可以通过添加 -fno-use-cxa-atexit 标志来解决,但我不知道如何处理 _fini 符号。
编译器/链接器标志:
set(CMAKE_C_FLAGS "-mcpu=cortex-m3 -mthumb -std=gnu11 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections")
set(CMAKE_C_FLAGS_RELEASE "-Os")
set(CMAKE_C_FLAGS_DEBUG "-g -Og -fno-move-loop-invariants")
set(CMAKE_CXX_FLAGS "-mcpu=cortex-m3 -mthumb -std=c++11 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-exceptions")
set(CMAKE_CXX_FLAGS_RELEASE "-Os")
set(CMAKE_CXX_FLAGS_DEBUG "-g -Og -fno-move-loop-invariants")
set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> -Wl,--start-group <OBJECTS> <LINK_LIBRARIES> -Wl,--end-group -o <TARGET>")
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> -Wl,--start-group <OBJECTS> <LINK_LIBRARIES> -Wl,--end-group -o <TARGET>")
set(CMAKE_EXE_LINKER_FLAGS "-nostartfiles -Xlinker --gc-sections -Xlinker --sort-section -Xlinker alignment --specs=nosys.specs")
SET(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp")
SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
Linker 脚本(部分):
SECTIONS
{
.text :
{
. = ALIGN(4);
KEEP(*(.interrupt_vector))
KEEP(*(.reset))
. = ALIGN(4);
*(.rodata.boot.*)
/* Pre-initialization Code */
. = ALIGN(4);
PROVIDE_HIDDEN (__preinit_array_start__ = .);
/* System initialization and the platform initialization (if present)
* should be first */
KEEP(*(.preinit_array_sysinit .preinit_array_sysinit.*))
KEEP(*(.preinit_array_platform .preinit_array_platform.*))
/* Pre-initialization functions (to be executed before C++
* constructors are run) */
KEEP(*(.preinit_array .preinit_array.*))
PROVIDE_HIDDEN (__preinit_array_end__ = .);
/* Initialization Code */
. = ALIGN(4);
PROVIDE_HIDDEN (__init_array_start__ = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end__ = .);
. = ALIGN(4);
*(.text .text.*) /* all remaining code */
*(.rodata .rodata.*) /* read-only data (constants) */
. = ALIGN(4);
__dsp_start__ = . ;
KEEP(*(.dsp .dsp.*)) /* all remaining DSP code */
__dsp_end__ = . ;
. = ALIGN(4);
} >FLASH
.ARM.exidx :
{
PROVIDE_HIDDEN (__exidx_start = .);
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
PROVIDE_HIDDEN (__exidx_end = .);
} >FLASH
. = ALIGN(4);
__data_init__ = .;
/* Place the SystemClock variable needed for CMSIS in a place that is
* compatible with the ROM's placement of this variable so that the
* variable can be used by CMSIS and the ROM's flash write libary */
.systemclock (NOLOAD) :
{
. = ALIGN(4);
KEEP(*(.systemclock))
} > DRAM
.data : AT ( __data_init__ )
{
. = ALIGN(4);
/* This is used by the startup code to initialize the .data section */
__data_start__ = . ;
*(.data_begin .data_begin.*)
*(.data .data.*)
*(.data_end .data_end.*)
/* Place sleep and wakeup routines in retention RAM
* Wakeup_From_Sleep_Application_asm has to followed directly by
* Wakeup_From_Sleep_Application */
*(.app_wakeup_asm)
KEEP(*(.app_wakeup))
KEEP(*(.sys_powermodes_wakeup_2mbps))
. = ALIGN(4);
/* This is used by the startup code to initialize the .data section */
__data_end__ = . ;
} >DRAM
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss_begin .bss_begin.*)
*(.bss .bss.*)
*(COMMON)
*(.bss_end .bss_end.*)
. = ALIGN(4);
__bss_end__ = .;
} >DRAM
.noinit (NOLOAD) :
{
. = ALIGN(4);
__noinit_start__ = .;
*(.noinit .noinit.*)
. = ALIGN(4) ;
__noinit_end__ = .;
} > DRAM
/* Check if there is enough space to allocate the main stack */
._stack (NOLOAD) :
{
. = ALIGN(4);
. = . + __Main_Stack_Size ;
. = ALIGN(4);
} >DRAM
. = __data_init__ + (__data_end__ - __data_start__);
PROVIDE(__flash_end__ = ALIGN(2048));
PROVIDE(__code_size = __flash_end__ - ORIGIN(FLASH));
}
基于 initfini.c 的libc 源,_fini 和 _init 分别用于模块初始化/取消初始化。 由于嵌入的代码不应该从主程序中退出,__libc_fini_array 不会被调用,而__libc_fini_array 也不会调用 _fini()。 不幸的是,stl 的部分调用 exit() 定义为:
uint8_t i;
for (i = 0; i < atexit_count; i++) {
atexit_funcs[i]();
}
__libc_fini_array();
_exit(return_code);
重新启动整个问题。 使用 nosys.specs 时,没有定义 _fini function,但我们可以定义自己的来解决这个问题。
/* Make sure you have C linkage when defining in c++ file */
extern "C"
void _fini()
{
/* Either leave empty, or infinite loop here */
while (true)
__asm volatile ("NOP");
}
此外,还需要在 linker 脚本中为 __libc_fini_array 提供 __fini_array_start 和 __fini_array_end,但仅此而已。
请注意,如果我们支持动态分配,我们可以通过调用 operator new 来延迟初始化 object 时完全跳过这个问题,或者使用 std::aligned_storage 和placement new 来避免一起调用析构函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.