Android异常分析基础之 --- APCS(ARM程序调用标准) --- (三) --- APCS标准

上节对APCS的基本数据类型做了分类和对通用寄存器X0 ~ X30做了标准的说明。

SIMD和浮点寄存器组

现在对SIMD和浮点寄存器组做一个说明。

寄存器特殊命名在函数调用过程中的作用备注
    V16 ~ X31 临时寄存器, 若需要,调用者需要保存数据 
    V8 ~ V15 临时寄存器,被调用者需要保存的寄存器 (只需要保存低64位,如果保存高位,需要调用者保存) 
    V0 ~ V7 参数传递 / 返回寄存器

被用来传入参数或传出结果,也可用来保存函数中数据

 

APCS标准规定,如果不能完全通过寄存器来完成参数的传递,那么,参数的传递也可以通过栈来进行传递。

 

 

参数传递规则定义

参数传递分为两种不同的函数,1. 可变参数函数  2. 非可变参数函数

1: 可变参数函数。 对于可变参数函数来说,调用者是可以完全确定参数传入的数量,类型的。而对于被调用者来说,只能确定参数最小集合。并根据这个最小结合的参数动态确定传入的参数数量和类型。其中,可以确定的参数被称为命名参数(Named Arguments),而不能确定的参数被称为匿名参数(Anonymous Arguments)。

2: 非可变参数函数。 非可变参数函数,可以认为是没有匿名参数的可变参数函数。

 针对代码中的不同情况,APCS提供了针对不同情况的规则定义,其定义如下:

1: 对于无法静态获得大小的组合类型,数据拷贝到内存,参数替代为内存地址指针进行传递

2: 在向量运算中,同类型向量做无修改传递

3: 对于大于16字节的组合类型,调用者负责将数据拷贝到内存,并将内存地址指针作为参数传递

4: 对于组合类型,应以8字节对齐方式保存

5: 对所有浮点类型,不论大小,在8个以内,每个参数使用一个V0 ~ V7中的寄存器按传入顺序进行传递。

6: 向量运算中,在8个以内, 每个同类型向量使用一个V0 ~ V7寄存器按传入顺序进行传递

7: 向量运算中,同类型向量以8字节对齐

8: 若参数是同类型向量,四精度浮点和短向量类型, 则对齐方式以8字节或参数类型的自然对齐数中大的为对齐字节数

9: 若参数是半浮点,单浮点类型,则参数大小扩展为8字节。拷贝至寄存器中时,扩展比特的值为未指定值。

10: 若参数是同类型向量,半浮点,单浮点,四浮点或短向量类型, 则通过内存进行传递参数时,向量被8字节对齐的复制到内存地址中,参数传递区内存容量扩展,并进行传递。

11: 若参数是整型或指针类型等小于等于8字节的数据,在8个以内,每个参数使用一个参数传递寄存器(X0 ~ X7)按传入顺序进行传递

12: 若参数类型是整型且自然对齐是16字节,且目前未被占用的参数传递寄存器还大于2个,则参数扩展到下两个参数传递寄存器(X0 ~ X7)进行传递,前一个寄存器保存低地址位,后一个保存高地址位。

13: 若参数是组合类型,且参数大小在8个字节以内,且目前未被占用的参数传递寄存器还大于1个, 则参数被放置到一个参数传递寄存器(X0 ~ X7)进行传递。就像它们被从一个8字节对齐的内存地址中通过ldr指令加载到寄存器中一样。

14: 通用寄存器进行参数传递最大只有8个。从X0 ~ X7

15: 通过内存地址进行参数传递的,参数是8字节对齐。

16: 如果参数是组合类型,则参数被复制到内存中以8字节对齐方式保存。

17: 如果参数不足8字节,则参数被扩展到8字节通过寄存器操作。扩展为内容未知。

18: 如果参数通过内存传递,则参数传递区内存使用容量随参数递增,参数保存方式以内存对齐方式保存

 

举例

对于上述这些标准内容,我们单看条目,可能很难有具体的理解,接下来我们以一个tombstone为例来说明一下:

 

 

05-06 13:06:40.576  9694 29707 F libc    : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 29707 (pool-16-thread-)
05-06 13:06:40.628   500   500 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
05-06 13:06:40.629   500   500 F DEBUG   : Build fingerprint: 'XXX/XXX/XXX:6.0.1/MMB29M/1.8.119_160503:user/release-keys'
05-06 13:06:40.629   500   500 F DEBUG   : Revision: '0'
05-06 13:06:40.629   500   500 F DEBUG   : ABI: 'arm64'
05-06 13:06:40.629   500   500 F DEBUG   : pid: 9694, tid: 29707, name: pool-16-thread-  >>> com.xxx.mms <<<
05-06 13:06:40.629   500   500 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
05-06 13:06:40.661   500   500 F DEBUG   :     x0   0000000000000000  x1   000000000000000f  x2   0000000000000fde  x3   0000000000000000
05-06 13:06:40.661   500   500 F DEBUG   :     x4   0000007f5fe389c8  x5   0000000000000fcf  x6   00000000000000fc  x7   00000000000000fd
05-06 13:06:40.661   500   500 F DEBUG   :     x8   0000000000000fd0  x9   0000007f5fe39998  x10  00000000000000fd  x11  0000007f5fe39998
05-06 13:06:40.661   500   500 F DEBUG   :     x12  0000000000000038  x13  0000000000000005  x14  0000000000000005  x15  0000000000000005
05-06 13:06:40.661   500   500 F DEBUG   :     x16  0000007f62eb3d60  x17  0000007f7eec8414  x18  0000000000000005  x19  0000007f5fe399a8
05-06 13:06:40.661   500   500 F DEBUG   :     x20  0000000000000000  x21  0000007f5fe38610  x22  0000007f62eb4000  x23  0000007f5fe3eb6c
05-06 13:06:40.661   500   500 F DEBUG   :     x24  0000000000000000  x25  0000007f5fe389b0  x26  0000007f5fe38278  x27  0000007f5fe38270
05-06 13:06:40.661   500   500 F DEBUG   :     x28  0000007f5fe38278  x29  0000007f5fe40118  x30  0000007f62e93f88
05-06 13:06:40.661   500   500 F DEBUG   :     sp   0000007f5fe381c0  pc   0000007f62e93fe4  pstate 0000000020000000
05-06 13:06:40.666   500   500 F DEBUG   : 
05-06 13:06:40.666   500   500 F DEBUG   : backtrace:
05-06 13:06:40.666   500   500 F DEBUG   :     #00 pc 0000000000015fe4  /system/priv-app/XMms/XMms.apk (offset 0xf64000)
05-06 13:06:40.666   500   500 F DEBUG   :     #01 pc 0000000000011e94  /system/priv-app/XMms/XMms.apk (offset 0xf64000)
05-06 13:06:40.666   500   500 F DEBUG   :     #02 pc 0000000000016eec  /system/priv-app/XMms/XMms.apk (offset 0xf64000)
05-06 13:06:40.666   500   500 F DEBUG   :     #03 pc 0000000000007da8  /system/priv-app/XMms/XMms.apk (offset 0xf64000)
05-06 13:06:40.666   500   500 F DEBUG   :     #04 pc 0000000000b8aa14  /system/priv-app/XMms/oat/arm64/XMms.odex (offset 0x75d000)
05-06 13:06:41.406   500   500 F DEBUG   : 
05-06 13:06:41.406   500   500 F DEBUG   : Tombstone written to: /data/tombstones/tombstone_01

 单从上面看,异常错误是一个signal 11的段地址错误。而且显示fault addr 是0x0,这说明是发生了一个空指针的错误。

   15fd8:       6b18001f        cmp     w0, w24

   15fdc:       54000acd        b.le    16134 <calcWords+0x26c>
   15fe0:       f947b2c0        ldr     x0, [x22,#3936]
   15fe4:       f8746800        ldr     x0, [x0,x20]

 

我们追到15fe4这个地址,很明显的可以看到,“ ldr     x0, [x0,x20] ” 这样的取地址指令,这个时候,我们就可以猜想,按照ARM的APCS64的标准, X0寄存器是上一级调用者调用到当前函数传入的第一个非浮点参数(也可能就是第一个参数,取决于参数传入顺序)。普通情况下,如果这个寄存器没有被复写重用,那么,发生异常的情况,就很有可能是传入的第一个非浮点参数出现了问题(有可能传入了一个空指针)。而且,从这里的汇编指令也可以看到,X0确实是被当作一个指针地址来用的。这样,我们就可以排查代码中对应的变量是否存在被赋值为空地址的问题了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值