调试问题记录

 1.  undefined reference to `__aeabi_dcmpun'

__aeabi_dcmpun这个符号的实现位于libgcc, 但是Linker文件中已包含了libgcc, 为何还提示找不到符号?

问题在于几个lib库的顺序安排,打开linker.ld文件,调整文件末尾的库文件列表顺序,如下:

  /DISCARD/ :
  {
    libgcc.a ( * )
    libc.a ( * )
    libnosys.a ( * )
    /*libm.a ( * )*/
    /*libg.a ( * )*/
  }

调整为

  /DISCARD/ :
  {
    libc.a ( * )
    libnosys.a ( * )
    libgcc.a ( * )
    /*libm.a ( * )*/
    /*libg.a ( * )*/
  }

即可完成编译。

 

2.lib库相互引用,互相依赖(交叉引用)链接解决办法

Linux GCC中,如果lib a依赖b,b又依赖a,链接的时候无论a放在前,还是b放在前,都会提示 undefined reference to `xxx'。

解决办法一:

链接的时候a链接两次,即: -la -lb -la

解决办法二:

在相互依赖的库间加上 -Wl,--start-group    -Wl,--end-group,如果当前的库找不到定义,会在当前的group中从头到尾查询,以找出其定义。

$(CC) -g -o $(TARGET) $(OBJ) $(LIB_FLAG) -Wl,--start-group -lssl -lcrypto -losip2 -leXosip2 -losipparser2 -lpthread -lmd5 -Wl,--end-group

 

3.关于newlib中的libgloss和libnosys

Newlib由三部分构成:libgloss、libc、libm,三者在Newlib源代码中的存储位置如下。

  • newlib-*.*.*
    • libgloss
    • newlib
      • libc
      • libm

libc(同libg)是标准C库,libm是标准数学库,而libgloss是提供启动代码和底层I/O支持的。

例如write.c源文件定义了write函数,当程序中引用了printf等标准输出函数时,最终printf会调用write函数进行输出,如果没有定义write函数,那么链接就失败了。kill.c源文件定义了kill系统函数,getpid.c源文件定义了getpid系统函数,等等。

libgloss目录下除了和处理器相关的子目录外,还有个很特别的子目录,那就是libnosys目录,这个目录下的源文件重新定义了libgloss的所有函数,但是所有函数都是空的,都是stub函数,完全是为了链接通过而定义的。如果程序并不实际使用系统函数,但是某些代码引用了系统函数,那么可以引入libnosys,以便通过编译。

 libgloss和libnosys库文件位于编译器的安装目录,例如./gcc-arm-10.2-2020.11-mingw-w64-i686-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.2.1

libnosys库是一个单一的库文件libnosys.a, 编译时直接指定-lnosys即可。

libgloss除了一个librdimon.a库文件外,还包含了若干启动代码目标文件(crt*.o),编译时如果指定了-lrdimon还提示有符号未定义的话,需要把启动代码目标文件也链接进去。

另外gcc提供了-spec选项,通过该选项可实现libnosyslibrdimon的选择 切换 。

 

4. linker文件中指定常数填充

    .progend :
    {
       . = ALIGN(0x4);
     *(.text2)
    LONG(0xdeadbeef)
     LONG(0xdeadbeef)       
    } >ILM 

 

posted @ 2021-04-27 19:26  DF11G  阅读(721)  评论(0编辑  收藏  举报