当前位置 博文首页 > 想要去旅行:记一次uboot 中出现的 data abort 错误

    想要去旅行:记一次uboot 中出现的 data abort 错误

    作者:[db:作者] 时间:2021-08-31 15:58

    最近调试 uboot 遇到一个很顽固的错误,遇到我是一脸懵啊,花了一天的时间去解决。

    fs_open() 100,p=45fb0a2d len=1436 H
    fs_open() 108
    data abort
    pc : [<45f9b688>]          lr : [<45fa4d29>]
    reloc pc : [<4a024688>]    lr : [<4a02dd29>]
    sp : 41f63b38  ip : 00000006     fp : 00006401
    r10: 45ffc678  r9 : 41f67ee0     r8 : 45ffc018
    r7 : 80000000  r6 : 45fb0a2d     r5 : 0000059c  r4 : 00000000
    r3 : 000002ce  r2 : 45fb0a2b     r1 : 01c20c00  r0 : 45fb0fc7
    Flags: Nzcv  IRQs off  FIQs off  Mode SVC_32
    Resetting CPU ...
    
    resetting ...
    

    首先感谢 BeanHuo 的博客,提供了解决思路 ----博文链接:关于uboot下data abort的问题

    结合我实际的log ,可以看出在 0x4a024688 位置除了错,接下来用 objdump -S u-boot 来找到对应的汇编指令

    4a024684:	4620      	mov	r0, r4
    4a024686:	bd70      	pop	{r4, r5, r6, pc}
        acc += *sdata;
    4a024688:	f832 1f02 	ldrh.w	r1, [r2, #2]!
    4a02468c:	440c      	add	r4, r1
    4a02468e:	b2a4      	uxth	r4, r4
        if(acc < *sdata) {
    4a024690:	42a1      	cmp	r1, r4
          ++acc;
    4a024692:	bf84      	itt	hi
    4a024694:	3401      	addhi	r4, #1
    4a024696:	b2a4      	uxthhi	r4, r4
    4a024698:	e7df      	b.n	4a02465a 
    	...
    
    

    发现出错的汇编指令 对应的代码函数如下,在执行 acc += *sdata 的时候出了错误。

    u16_t
    uip_chksum(u16_t *sdata, u16_t len)
    {
      u16_t acc = 0;
    
      for(acc = 0; len > 1; len -= 2) {  	
        acc += *sdata;
        if(acc < *sdata) {
          /* Overflow, so we add the carry to acc (i.e., increase by
             one). */
          ++acc;
        }
        ++sdata;
      }
      
      /* add up any odd byte */
      if(len == 1) {
        acc += htons(((u16_t)(*(u8_t *)sdata)) << 8);
        if(acc < htons(((u16_t)(*(u8_t *)sdata)) << 8)) {
          ++acc;
        }
      }
      
      return acc;
    }
    

    为什么在执行 acc += *sdata 的时候出了错误。sdata 指针位置这哪里?
    方法1,可以加打印看。
    方法2,根据汇编推算。
    这里直接看汇编:

        acc += *sdata;
    4a024688:	f832 1f02 	ldrh.w	r1, [r2, #2]!
    4a02468c:	440c      	add	r4, r1
    4a02468e:	b2a4      	uxth	r4, r4
    

    这里需要知道 r2 的值, r2 的值根据出错时的打印可以看到

    pc : [<45f9b688>]          lr : [<45fa4d29>]
    reloc pc : [<4a024688>]    lr : [<4a02dd29>]
    sp : 41f63b38  ip : 00000006     fp : 00006401
    r10: 45ffc678  r9 : 41f67ee0     r8 : 45ffc018
    r7 : 80000000  r6 : 45fb0a2d     r5 : 0000059c  r4 : 00000000
    r3 : 000002ce  r2 : 45fb0a2b     r1 : 01c20c00  r0 : 45fb0fc7
    

    r2 = 45fb0a2b
    [r2, #2] 得到 45fb0a2d

    需要找到 45fb0a2d 对应的 位置, 先根据 pc , reloc pc 得到 offset
    offset = reloc pc - pc = 4a024688 - 45f9b688 = 4089000

    45fb0a2d - offset = 45fb0a2d - 4089000 = 4a039a2d

    在 u-boot.map 文集中找到 4a039a2d 对应的位置

    6110: .rodata.data_flashing_html
    6111-                0x000000004a039a2d      0x59d httpd/built-in.o
    6112: .rodata.data_index_html
    

    这是一个 const char 数组。
    为什么会导致 data abort ??????

    百思不得解,
    百思不得解,
    百思不得解,

    终于在重新翻看文章时,注意到这么一段话

    其实在出错时,uboot已经告诉我们如何去找出问题所在,如上面的问题,我们可以通过查看doc/README.arm-unaligned-accesses来找到出错的位置。

    arm-unaligned-accesses ? 非对齐地址访问 ?
    查找相关资料后,找到一篇有帮助的文章:内存不对齐访问(unaligned access)及汇编下宕机

    文中指出,开启内存地址对齐错误的检查功能时,进行对齐地址访问会导致宕机,data abort

    在这里插入图片描述

    uboot的cpu内核初始化阶段,启动了内存地址对齐错误的检查功能;然后用ldr加载和str存储内存地址不对齐的空间会发生什么事情?

    参考ARM架构手册中如下表,可知将因指令的地址对齐错误导致数据中止异常。如果你用如下指令将SCTLR.A置为0,将不会产生异常,实现了不对齐访问,较早的ARM架构不支持这种功能,ARMv7上可以支持。

    再看这次的 45fb0a2d ,地址为奇数,刚好就是非对齐地址,难怪总是出错!!!
    如何解决?
    正好的我的是 ARMv7 , 是可以支持不对齐访问的,只要在Start.s 中将 Align 检测功能去掉。

    在这里插入图片描述
    重新编译运行,一切正常!
    再次感谢以上两位博主的文章!

    cs
    下一篇:没有了