记录一次非常神奇的调试经历
最近真的是有些忙,好就好及都没有更新了,可能也是因为最近调试都比较顺利,没有碰到什么特别值得记录的bug,哈哈。
不过这次真的是有bug还有闲,所以就记录一下。
问题描述
首先我们还是按照惯例对问题进行一个简单的说明,这次问题出现在对一个CM0+的芯片调试上,程序采用gcc编译,调试是使用的Ozone,这个应该算是一个非常不典型的工具链了,但是我对这个还是比较偏爱的,因为这套工具链是全平台的,并且工具都比较简洁,对于命令行的支持都比较好,选择Ozone主要是功能全面,工具小巧,相比gdb还有非常好用的GUI,也就没必要用gdb找虐了。好了,我们回到问题本身,当我在运行一个程序的时候,每次运行到memset
的时候就会产生hardfault
这个就比较奇怪了,因为这个memset
是newlib
里面的一个程序,我也没法改,以前用似乎也没啥问题,但是这次运行总是出错。
调试经历
没有办法,只能祭出我的汇编调试大法,打开ozone的反汇编,memset
上打个断点,然后我发现memset
这个程序真的会往一个非法地址跳转,如下图所示。
看看上图里面的诡异的反汇编,啥事没干就直接往0x00001766
跳转了,这明显是抽风的节奏呀,这他妹的是怎么回事?没办法,看看gcc那边出来的汇编是啥情况把,打开lst
文件,找到memset
汇编如下:
嗯,地址累加比较,赋值,跳转,嗯,简单有效的memset
函数,似乎没啥问题,但是为啥到了ozone
就成了另外一套汇编了?难道是我的机器码出问题了?比较一下0xE1A03000
, 0xe0802002
,看起来也都一样,只不过gcc这边是32位的指令编码,到了ozone就成了16位的了,难道是thumb
模式出来问题?这要是去调试core就蛋疼了,另外,要真的是这个问题,应该早就暴露出来了吧,我在这个平台上已经跑了很多程序都没问题呀?着实郁闷。
问题解决
为了搞定这个问题,我试了各种方法,各种调节gcc的参数,试了很多spec
都是一样的,都是在memset
这里出问题,这个其实还是蛮有规律的,因为我自己写的程序怎么跑都没有问题,就是搞这个newlib
库里面的函数会有问题,偶然间我怀疑是不是因为我这个链接库调错了,然后把link
命令搞出来看看,发现link
的时候真的没有指定CPU
类型,好家伙,真的是给我乱调库,简单解决一下即使把编译的参数直接加到link的参数列表里面就好了,修正之后跑起来美美的。
以后碰到这种汇编不一致的情况就有经验了,毕竟工具还是比较靠谱的,不要怀疑工具,出错的只可能是你自己!另外比较纳闷,从SDK里面搞出来的makefile还有这个问题,真的怀疑怎么测试的。
最后更新于 2020-12-13 01:40:49 并被添加「调试 ARM GCC」标签,已有 6229 位童鞋阅读过。
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。
没太看懂是什么问题,为啥两个代码的汇编不一样啊?elf不是静态链接了memset吗,也不是动态链接的啊,怎么会不一样呢?
@didi
这里是因为编译器链接的时候调用了默认的一个库,这个库并不是我期望的MCU 架构,所以指令都是不支持的指令。