This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

arm-none-eabi-nm: some symbols are not related to any source file

In my embedded project I compile `amazon-freertos/lib/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c` in this way:

/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-gcc \
	-std=gnu11 \
	-mcpu=cortex-m7 \
	-mthumb \
	-mapcs \
	-mfloat-abi=hard \
	-mfpu=fpv5-d16 \
	-fno-common \
	-fno-math-errno \
	-fsingle-precision-constant \
	-fno-trapping-math \
	-fno-signaling-nans \
	-fno-builtin \
	-fstrict-aliasing \
	-fstack-usage \
	-Wstack-usage=300 \
	-DCPU_MIMXRT1051DVL6B  \
	-D__FREERTOS__=1 \
	-DFSL_RTOS_FREE_RTOS \
	-DFSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE \
	-D__MCUXPRESSO \
	-D__USE_CMSIS \
	-DARM_MATH_CM7 \
	-D__NEWLIB__ \
	-DDEBUG=0 \
	-IDSP/source/ \
	-Iamazon-freertos/lib/FreeRTOS-Plus-TCP/ \
	-Iamazon-freertos/lib/FreeRTOS-Plus-TCP/portable/BufferManagement/ \
	-Iamazon-freertos/lib/FreeRTOS-Plus-TCP/portable/NetworkInterface/imxrt105x/ \
	-Iamazon-freertos/lib/FreeRTOS/ \
	-Iamazon-freertos/lib/include/ \
	-Iamazon-freertos/lib/FreeRTOS/portable/GCC/ARM_CM4F/ \
	-Iamazon-freertos/lib/FreeRTOS/portable/MemMang/ \
	-Og \
	-g3 \
	-Wall \
	-ffunction-sections \
	-fdata-sections \
	-c \
	-MMD \
	-MP \
	-Werror \
	-D"ARCPRINTF( ... )=(void)0" \
	--specs=nano.specs  \
	-Wa,-anhlmsd=build/DSP/amazon-freertos/lib/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.lst \
	-o build/DSP/amazon-freertos/lib/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.o amazon-freertos/lib/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c 

I have `ipconfigUSE_TCP` set to 1 in `amazon-freertos/lib/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfig.h`

`FreeRTOS_Sockets.c` declares `xBoundUDPSocketsList` and `xBoundTCPSocketsList`

/* The list that contains mappings between sockets and port numbers.  Accesses
to this list must be protected by critical sections of one kind or another. */
List_t xBoundUDPSocketsList;

#if ipconfigUSE_TCP == 1
	List_t xBoundTCPSocketsList;
#endif /* ipconfigUSE_TCP == 1 */

Once I have my elf executable linked, run this command:

$ /opt/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-nm -a -l -n -t x --print-size image/DSP.elf | grep -E '^[[:xdigit:]]{8} [[:xdigit:]]{8} B' | grep SocketsList
2001ac7c 00000014 B xBoundTCPSocketsList
2001ac90 00000014 B xBoundUDPSocketsList	/home/max/Lavori/4202/src/repos/toremove/FW/amazon-freertos/lib/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c:162

Both symbols exist in the executable, but one (`xBoundTCPSocketsList`) does not seem to belong to any .c source.
Both appear in the map file:

$ grep -n -A 1 -E 'xBoundTCPSocketsList|xBoundUDPSocketsList' image/DSP.map
61974: .bss.xBoundTCPSocketsList
61975-                0x000000002001ac7c       0x14 ./build/DSP/amazon-freertos/lib/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.o
61976:                0x000000002001ac7c                xBoundTCPSocketsList
61977: .bss.xBoundUDPSocketsList
61978-                0x000000002001ac90       0x14 ./build/DSP/amazon-freertos/lib/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.o
61979:                0x000000002001ac90                xBoundUDPSocketsList

Even addr2line fails:

$ arm-none-eabi-addr2line -a -e image/DSP.elf  2001ac7c 2001ac90
0x2001ac7c
??:0
0x2001ac90
/home/max/Lavori/4202/src/repos/toremove/FW/amazon-freertos/lib/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c:162

even the `FreeRTOS_Sockets.lst` doesn't tell me anything more:

 7337              		.global	xBoundTCPSocketsList
 7338              		.global	xBoundUDPSocketsList
 7339              		.section	.bss.xBoundTCPSocketsList,"aw",%nobits
 7340              		.align	2
 7341              		.set	.LANCHOR2,. + 0
 7344              	xBoundTCPSocketsList:
 7345 0000 00000000 		.space	20
 7345      00000000 
 7345      00000000 
 7345      00000000 
 7345      00000000 
 7346              		.section	.bss.xBoundUDPSocketsList,"aw",%nobits
 7347              		.align	2
 7348              		.set	.LANCHOR1,. + 0
 7351              	xBoundUDPSocketsList:
 7352 0000 00000000 		.space	20
 7352      00000000 
 7352      00000000 
 7352      00000000 
 7352      00000000 

There are many other symbols present in the executable but which do not seem to be associated with any .c source file.

Why this behavior? What changes between the two symbols `xBoundTCPSocketsList` and `xBoundUDPSocketsList`? Am I getting it wrong or omitting some debugging parameters when compiling? How do I get either nm or some other way to get the .c source where a symbol is declared?

best regards

Max

Parents
  • The variable xBoundTCPSocketsList is declared as extern in a header FreeRTOS_IP_Private.h. It is defined in the file FreeRTOS_Sockets.c which also happens to include FreeRTOS_IP_Private.h. As a result, the extern declaration and the definition of the variable are forced to appear, in that order, in the same file FreeRTOS_Sockets.c. This situation causes the dwarf debug information about the variable to be split into two entries. It is likely that the tools nm/objdump aren't able to cope with this split. I do not know if there's a switch that they take to force them to consider such splits.

    But, I was able to workaround this situation by avoiding inserting the extern declaration for the variable in the FreeRTOS_Sockets.c file. Below are the steps:

    1. At the top of FreeRTOS_Sockets.c file, right before the first #include and right after the license block, define a new, non-existing macro, for e.g. FREERTOS_SOCKETS_C_FILE. At the very end of the file, add a line to undefine that same macro. See code snippet below.
    2. In the FreeRTOS_IP_Private.h file, restrict the extern declaration of that variable to be included in the files which do not define the macro FREERTOS_SOCKETS_C_FILE. 

    /* FreeRTOS_IP_Private.h */
    
    /* Replace the preprocessor directives surrounding
     * the extern declaration, as shown below
     */
     
    /* Defined in FreeRTOS_Sockets.c */
    #if ( ipconfigUSE_TCP == 1 ) && (!defined(FREERTOS_SOCKETS_C_FILE))
    	extern List_t xBoundTCPSocketsList;
    #endif

    Edit: I think it is also possible to modify the step#1 to define-undefine the new macro, insideFreeRTOS_Sockets.c, just around the #include "FreeRTOS_IP_Private.h", instead of around the whole file.

    Step#1 can then be alternatively written, in a more succint manner, as:

    /* FreeRTOS_Sockets.c */
    
    /* ... */
    
    #define FREERTOS_SOCKETS_C_FILE
    #include "FreeRTOS_IP_Private.h"
    #undef FREERTOS_SOCKETS_C_FILE
    
    /* ... */

    Edit2: Here is a bug in gcc, where an extern declaration and the corresponding definition, both seperate statements but still in the same file - a situation seen above, of an array resulted in gcc not placing the array bounds in the dwarf debug information, causing gdb to output incorrect size of the array.

Reply
  • The variable xBoundTCPSocketsList is declared as extern in a header FreeRTOS_IP_Private.h. It is defined in the file FreeRTOS_Sockets.c which also happens to include FreeRTOS_IP_Private.h. As a result, the extern declaration and the definition of the variable are forced to appear, in that order, in the same file FreeRTOS_Sockets.c. This situation causes the dwarf debug information about the variable to be split into two entries. It is likely that the tools nm/objdump aren't able to cope with this split. I do not know if there's a switch that they take to force them to consider such splits.

    But, I was able to workaround this situation by avoiding inserting the extern declaration for the variable in the FreeRTOS_Sockets.c file. Below are the steps:

    1. At the top of FreeRTOS_Sockets.c file, right before the first #include and right after the license block, define a new, non-existing macro, for e.g. FREERTOS_SOCKETS_C_FILE. At the very end of the file, add a line to undefine that same macro. See code snippet below.
    2. In the FreeRTOS_IP_Private.h file, restrict the extern declaration of that variable to be included in the files which do not define the macro FREERTOS_SOCKETS_C_FILE. 

    /* FreeRTOS_IP_Private.h */
    
    /* Replace the preprocessor directives surrounding
     * the extern declaration, as shown below
     */
     
    /* Defined in FreeRTOS_Sockets.c */
    #if ( ipconfigUSE_TCP == 1 ) && (!defined(FREERTOS_SOCKETS_C_FILE))
    	extern List_t xBoundTCPSocketsList;
    #endif

    Edit: I think it is also possible to modify the step#1 to define-undefine the new macro, insideFreeRTOS_Sockets.c, just around the #include "FreeRTOS_IP_Private.h", instead of around the whole file.

    Step#1 can then be alternatively written, in a more succint manner, as:

    /* FreeRTOS_Sockets.c */
    
    /* ... */
    
    #define FREERTOS_SOCKETS_C_FILE
    #include "FreeRTOS_IP_Private.h"
    #undef FREERTOS_SOCKETS_C_FILE
    
    /* ... */

    Edit2: Here is a bug in gcc, where an extern declaration and the corresponding definition, both seperate statements but still in the same file - a situation seen above, of an array resulted in gcc not placing the array bounds in the dwarf debug information, causing gdb to output incorrect size of the array.

Children