MainframeReboot commented on issue #12356: URL: https://github.com/apache/nuttx/issues/12356#issuecomment-2133637011
I have dug deeper into the crt0/crt1/crti/crtbegin/crtend/crtn files as well as how .ctors are handled. I've learned that .ctors/.dtors is the old method handling constructors and destructors and that the "new" way is to use the .init_array method. I understand the previous linker script *should* work as, from what I can tell, it's combining .ctors and .init_array into _sctors while combining .dtors and .fini_array into _sdtors. Nonetheless I decided to update things so my crt0.c source uses the .preinit_array, .init_array and .fini_array sections from my linker script. The update also checks to make sure a pointer isn't NULL before it tries to call it. ``` C extern initializer_t __preinit_array_start[]; extern initializer_t __preinit_array_end[]; extern initializer_t __init_array_start[]; extern initializer_t __init_array_end[]; extern initializer_t __fini_array_start[]; extern initializer_t __fini_array_end[]; /**************************************************************************** * Private Functions ****************************************************************************/ #ifdef CONFIG_HAVE_CXX static void exec_preinit(void) { initializer_t *preinit; for(preinit = __preinit_array_start; preinit < __preinit_array_end; preinit++) { initializer_t initializer = *preinit; printf("preinit: %p, initializer: %p\n", preinit, initializer); if (initializer){ printf("Calling preinit %p\n", initializer); }else{ printf("preinit initializer %p is NULL!\n", initializer); } } } static void exec_init(void) { initializer_t *init; for(init = __init_array_start; init < __init_array_end; init++) { initializer_t initializer = *init; printf("init: %p, initializer: %p\n", init, initializer); if (initializer){ printf("Calling init %p\n", initializer); }else{ printf("init initializer %p is NULL!\n", initializer); } } } static void exec_fini(void) { initializer_t *fini; for(fini = __fini_array_start; fini < __fini_array_end; fini++) { initializer_t initializer = *fini; printf("fini: %p, initializer: %p\n", fini, initializer); if (initializer){ printf("Calling fini %p\n", initializer); }else{ printf("fini initializer %p is NULL!\n", initializer); } } } #endif /**************************************************************************** * Public Functions ****************************************************************************/ void __start(int argc, char *argv[]) { int ret; /* Initialize the reserved area at the beginning of the .bss/.data region * that is visible to the RTOS. */ ARCH_DATA_RESERVE->ar_sigtramp = (addrenv_sigtramp_t)sig_trampoline; #ifdef CONFIG_HAVE_CXX /* Call C++ constructors */ exec_preinit(); exec_init(); /* Setup so that C++ destructors called on task exit */ atexit(exec_fini); #endif /* Call the main() entry point passing argc and argv. */ ret = main(argc, argv); /* Call exit() if/when the main() returns */ exit(ret); } ``` The `gnu-elf.ld` linker script was updated to be as follows: ``` SECTIONS { . = 0xC0000000; .text : { _stext = . ; *(.text) *(.text.*) *(.gnu.warning) *(.stub) *(.glue_7) *(.glue_7t) *(.jcr) /* C++ support: The .init and .fini sections contain specific logic * to manage static constructors and destructors. */ *(.gnu.linkonce.t.*) KEEP(*(.init)) /* Old ABI */ KEEP(*(.fini)) /* Old ABI */ _etext = . ; } .rodata : { _srodata = . ; *(.rodata) *(.rodata1) *(.rodata.*) *(.gnu.linkonce.r*) _erodata = . ; } . = 0xC0400000; .data : { _sdata = . ; *(.data) *(.data1) *(.data.*) *(.gnu.linkonce.d*) . = ALIGN(4); _edata = . ; } /* C++ support. For each global and static local C++ object, * GCC creates a small subroutine to construct the object. Pointers * to these routines (not the routines themselves) are stored as * simple, linear arrays in the .ctors section of the object file. * Similarly, pointers to global/static destructor routines are * stored in .dtors. */ .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); } .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) KEEP(*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o) .ctors)) PROVIDE_HIDDEN(__init_array_end = .); } .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) KEEP(*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o) .dtors)) PROVIDE_HIDDEN(__fini_array_end = .); } .bss : { _sbss = . ; *(.bss) *(.bss.*) *(.sbss) *(.sbss.*) *(.gnu.linkonce.b*) *(COMMON) _ebss = . ; } /* Thread local storage support */ .tdata : { _stdata = ABSOLUTE(.); KEEP (*(.tdata .tdata.* .gnu.linkonce.td.*)); _etdata = ABSOLUTE(.); } .tbss : { _stbss = ABSOLUTE(.); KEEP (*(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon)); _etbss = ABSOLUTE(.); } /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } .comment 0 : { *(.comment) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_info 0 : { *(.debug_info) } .debug_line 0 : { *(.debug_line) } .debug_pubnames 0 : { *(.debug_pubnames) } .debug_aranges 0 : { *(.debug_aranges) } } ``` This let me run the helloxx example but the static constructor call failed. Thankfully there was no crash as the null pointer check prevented it. I dumped the .init_array section of helloxx and it shows that the constructor call isn't there at all, it was replaced with the unimp instruction:  Is there some sort of NuttX configuration setting I am missing that would cause this to occur? -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org