我正在尝试调试TI am 3358单片机中一个非常低级别的数据故障。它来自浮点数学。
系统使用TI RTOS、GNU7.3.1编译器和VFPv3 ( VFP是编译器设置吗?)FP数学库?我不清楚浮点代码的生成)。因此,虽然我有反汇编列表片段,但修复需要在C代码级别。
这是两个部分的问题:
首先,我正确地理解了助记符吗?为什么有些没有被列出来?
我注意到反汇编有没有记忆的操作码。这是一个列表片段,这里不需要详细说明。请注意,助记符缺失了,我不认为它们是即时数据(我在反向设计编译代码时添加了注释):
8003ced0: EEF1FA10 vmrs apsr_nzcv, fpscr ; Pull STAT reg to ARM MCU
8003ced4: DA000041 ble #0x8003cfe0 ; branch less-equal to x0x...3cfe0
8003ced8: EEFD7BE0 .word 0xeefd7be0 ; ??? What is this
8003cedc: EDC47A0A vstr s15, [r4, #0x28] ; Store S15 <- r4+28 = st->f2.z
8003cee0: E584702C str r7, [r4, #0x2c] ; Store r7 <- r4+2c = st->f2.a
8003cee4: E3A03000 mov r3, #0
8003cee8: E5843030 str r3, [r4, #0x30]
8003ceec: EE07CA90 vmov s15, r12 ; ( I decode this below)
8003cef0: EEF80BE7 .word 0xeef80be7 ; ???
8003cef4: EE702BA2 .word 0xee702ba2 ; ???
8003cef8: EEFD7BE2 .word 0xeefd7be2 ; ???
8003cefc: EDC47A0D vstr s15, [r4, #0x34]
8003cf00: E5845018 str r5, [r4, #0x18]
8003cf04: EE701BA1 .word 0xee701ba1
8003cf08: EEFD7BE1 .word 0xeefd7be1为了确保我能够理解VFPv3记忆学,我将地址8002 sure解码如下:
8003ceec: EE07CA90 vmov s15, r12
VMOV (between ARM core register and single-precision register)
1110 unconditional
1110
0000 opt = 0: so this is TO the VFP
0111 Vn = 7 (but still need one more bit from nibble 1)
1100 Rt = 12
1010
1001 N = 1 (so n = 01111 =S15)
0000它来自https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-instructions/VMOV--between-ARM-core-register-and-single-precision-register-?lang=en,(我很确定我得到了正确的,如果不是,任何更正欢迎)
那么,op代码0xeef80be7,0xee702ba2等等是什么呢?我无法在ARM的书籍或网站上破解它们。遵循VFP/NEON模式,这是某种“无条件的移动”,但除此之外,我无法将位模式与任何东西相匹配(而且网站非常不友好地进行这种搜索,我下载了PDF并进行了一些搜索)。
至于第二个问题,如果有一个简单而明显的答案,我会很感激被引导到正确的方向。
这是一个编译后的C函数,它传递一个指向结构的指针。然后把成员从里面拉出来,做一些浮点数的计算。我确定了结构地址存储在R4中。
示例原型将是
int Function(int x, int y, struct *a);被称为(虚构的例子)
Function (5,5,&st[0]);稍后
Function (5,7,&st[1]);只有在访问第二种结构时才会发生数据中止崩溃。从不访问第一个。只有当VFP/Neon正在访问它时,才没有正常的ARM寄存器。
进入代码的泥泞中,R4是传入的结构的地址:
8003cfe0: EEFD7BE0 .word 0xeefd7be0 ; branch lands here
8003cfe4: EDC47A06 vstr s15, [r4, #0x18] ; CRASH Store S15 <- r4+24 = st->f1.x
8003cfe8: E584C01C str r12, [r4, #0x1c] ; r12 = st->f1.y
8003cfec: E3A03000 mov r3, #0
8003cff0: E5843020 str r3, [r4, #0x20]我从指针中验证了成员的所有偏移量,一切都是正确的。
重复,崩溃发生在地址8003cfe4,但只有当R4指针指向st1时才发生,而不是在指向st时。
我知道“数据中止”来自试图访问MMU未配置权限的内存。然而,其他一切都可以访问st1的所有成员。这只是当VFP代码试图访问的时候。
实际上,在地址8003cec、8003cee0和8003cee8 (它们都在地址8003cfe4之前执行),可以愉快地访问该结构的成员。这让我相信这不是MMU的访问问题?
这可能是缓存丢失的结果吗?或者是否还有其他VFP问题试图在VFP系统和内存之间移动?还是协处理器还没有准备好的问题呢?
通过去掉所有浮点的数学,我就能避免这次坠机。但这确实损害了应用程序的功能。我更希望浮点数学正确。
任何想法都会受到欢迎。
-Scotty
发布于 2022-02-07 19:39:28
虽然我对未知的op代码没有答案,但是在对第二部分的回答中,VFP协处理器必须在适当的边界上将数据传输到和输出它,在这里是4个字节。
虽然结构的偏移对齐是正确的,但结构本身的基础却不对齐。它开始(由于包装)在地址0x.2931。因此,(+0x28)中40字节处的偏移量位于奇数地址上。
简单添加
} __attribute__ ((aligned (4)))在结构声明的末尾解决了这个问题。
*更新*
我尝试了许多方法在代码片段中复制这个问题。在所有情况下,编译器都会生成代码,将32位值从内存中移到寄存器中,然后再移动到neon处理器中。
我通过内联汇编程序语句试图将未对齐的数据直接从奇数地址移动到neon处理器,从而强制造成数据错误。
asm("vstr s15, [r0, #0x4] ");(R0包含以x1结尾的基地址)
因此,这很可能是GNU编译器中的一个优化错误。
如果其他人被这个问题咬了,我会发这个帖子。
发布于 2022-08-10 18:57:20
由于我目前正在编写反汇编程序,我很快将问题中的十六进制抛到了它身上,并得到了以下结果--没有保证或道歉!
EEF1FA10h,fmstat
DA000041h,ble #000083AC
EEFD7BE0h,ftosizd s15,d0
EDC47A0Ah,fsts s15,[r4+40]
E584702Ch,str r7, [r4+44]
E3A03000h,mov r3, 0
E5843030h,str r3, [r4+48]
EE07CA90h,fmsr s15,r12
EEF80BE7h,fsitod d0,s15
EE702BA2h,faddd d2,d0,d2
EEFD7BE2h,ftosizd s15,d2
EDC47A0Dh,fsts s15,[r4+52]
E5845018h,str r5, [r4+24]
EE701BA1h,faddd d1,d0,d1
EEFD7BE1h,ftosizd s15,d1https://stackoverflow.com/questions/71000084
复制相似问题