记录一次非常神奇的调试经历

最近真的是有些忙,好就好及都没有更新了,可能也是因为最近调试都比较顺利,没有碰到什么特别值得记录的bug,哈哈。

不过这次真的是有bug还有闲,所以就记录一下。

问题描述

首先我们还是按照惯例对问题进行一个简单的说明,这次问题出现在对一个CM0+的芯片调试上,程序采用gcc编译,调试是使用的Ozone,这个应该算是一个非常不典型的工具链了,但是我对这个还是比较偏爱的,因为这套工具链是全平台的,并且工具都比较简洁,对于命令行的支持都比较好,选择Ozone主要是功能全面,工具小巧,相比gdb还有非常好用的GUI,也就没必要用gdb找虐了。好了,我们回到问题本身,当我在运行一个程序的时候,每次运行到memset的时候就会产生hardfault这个就比较奇怪了,因为这个memsetnewlib里面的一个程序,我也没法改,以前用似乎也没啥问题,但是这次运行总是出错。

调试经历

没有办法,只能祭出我的汇编调试大法,打开ozone的反汇编,memset上打个断点,然后我发现memset这个程序真的会往一个非法地址跳转,如下图所示。

ozone_ams.png

看看上图里面的诡异的反汇编,啥事没干就直接往0x00001766跳转了,这明显是抽风的节奏呀,这他妹的是怎么回事?没办法,看看gcc那边出来的汇编是啥情况把,打开lst文件,找到memset汇编如下:

gcc_ams.png

嗯,地址累加比较,赋值,跳转,嗯,简单有效的memset函数,似乎没啥问题,但是为啥到了ozone就成了另外一套汇编了?难道是我的机器码出问题了?比较一下0xE1A030000xe0802002,看起来也都一样,只不过gcc这边是32位的指令编码,到了ozone就成了16位的了,难道是thumb模式出来问题?这要是去调试core就蛋疼了,另外,要真的是这个问题,应该早就暴露出来了吧,我在这个平台上已经跑了很多程序都没问题呀?着实郁闷。

问题解决

为了搞定这个问题,我试了各种方法,各种调节gcc的参数,试了很多spec都是一样的,都是在memset这里出问题,这个其实还是蛮有规律的,因为我自己写的程序怎么跑都没有问题,就是搞这个newlib库里面的函数会有问题,偶然间我怀疑是不是因为我这个链接库调错了,然后把link命令搞出来看看,发现link的时候真的没有指定CPU类型,好家伙,真的是给我乱调库,简单解决一下即使把编译的参数直接加到link的参数列表里面就好了,修正之后跑起来美美的。

以后碰到这种汇编不一致的情况就有经验了,毕竟工具还是比较靠谱的,不要怀疑工具,出错的只可能是你自己!另外比较纳闷,从SDK里面搞出来的makefile还有这个问题,真的怀疑怎么测试的。


本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。

相关文章

已有 2 条评论
  1. didi

    没太看懂是什么问题,为啥两个代码的汇编不一样啊?elf不是静态链接了memset吗,也不是动态链接的啊,怎么会不一样呢?

    didi 回复
    1. Major

      @didi

      这里是因为编译器链接的时候调用了默认的一个库,这个库并不是我期望的MCU 架构,所以指令都是不支持的指令。

      Major 回复
发表新评论