记录一次app崩溃信息调试

收到了崩溃信息,如下

 *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
2022-01-28 18:33:21.183 15634-15634/? A/DEBUG: Build fingerprint: 'Lenovo/LenovoTB-J706F_PRC/J706F:10/QKQ1.200329.002/12.0.497_210315:user/release-keys'
2022-01-28 18:33:21.183 15634-15634/? A/DEBUG: Revision: '0'
2022-01-28 18:33:21.183 15634-15634/? A/DEBUG: ABI: 'arm64'
2022-01-28 18:33:21.184 15634-15634/? A/DEBUG: Timestamp: 2022-01-28 18:33:21+0800
2022-01-28 18:33:21.184 15634-15634/? A/DEBUG: pid: 15450, tid: 15625, name: GLThread 39207  >>> com.zhidao.navi.demo.vr <<<
2022-01-28 18:33:21.184 15634-15634/? A/DEBUG: uid: 11258
2022-01-28 18:33:21.184 15634-15634/? A/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x70000fff8000d
2022-01-28 18:33:21.184 15634-15634/? A/DEBUG:     x0  00070000fff80005  x1  00000071b3e4f6a8  x2  0000000000000000  x3  0000000000000001
2022-01-28 18:33:21.184 15634-15634/? A/DEBUG:     x4  0000000000000002  x5  00000071bd1069bc  x6  213a478c213a4789  x7  213a478c213a4789
2022-01-28 18:33:21.184 15634-15634/? A/DEBUG:     x8  0000000000000006  x9  1e23ad8302c00826  x10 00000071b3e50020  x11 0000000000000010
2022-01-28 18:33:21.184 15634-15634/? A/DEBUG:     x12 000000000360d700  x13 0000000000000008  x14 0000000000000010  x15 0000000000000000
2022-01-28 18:33:21.184 15634-15634/? A/DEBUG:     x16 00000072ab1d38f0  x17 00000072ab1c5080  x18 00000071b0154000  x19 00000071b3e4fbb8
2022-01-28 18:33:21.184 15634-15634/? A/DEBUG:     x20 0000000000000000  x21 00000071b3e4fbf8  x22 000000721cc30650  x23 0000000000000006
2022-01-28 18:33:21.184 15634-15634/? A/DEBUG:     x24 0000000000000001  x25 00000071b1d067c0  x26 00000071b1d067c0  x27 0000000000000001
2022-01-28 18:33:21.184 15634-15634/? A/DEBUG:     x28 00000071b1cfe688  x29 00000071b3e4fb00
2022-01-28 18:33:21.184 15634-15634/? A/DEBUG:     sp  00000071b3e4fac0  lr  00000071bb4cea34  pc  00000071bb4cea44
2022-01-28 18:33:21.187 15634-15634/? A/DEBUG: backtrace:
2022-01-28 18:33:21.188 15634-15634/? A/DEBUG:       #00 pc 0000000000148a44  /data/app/com.zhidao.navi.demo.vr-vc9KlaFHCXK9G1d47N5hNQ==/lib/arm64/libmap.so (Com::Autonavi::Maps::Internal::MapDataMgrGetLabelData(Com::Autonavi::Maps::Internal::tagMapDataMgr*, Com::Autonavi::Maps::Internal::tagMapEnvelope*, Com::Autonavi::Maps::Internal::tagMapQueryObj*, float, Com::Autonavi::Maps::Internal::tagLabelData*)+120) (BuildId: 175a92028548a89d9f1f84bb39791563d08a16a1)
2022-01-28 18:33:21.188 15634-15634/? A/DEBUG:       #01 pc 00000000001441a0  /data/app/com.zhidao.navi.demo.vr-vc9KlaFHCXK9G1d47N5hNQ==/lib/arm64/libmap.so (Com::Autonavi::Maps::Internal::LabelContextUpdateRoutine(Com::Autonavi::Maps::Internal::tagLabelContext*)+1124) (BuildId: 175a92028548a89d9f1f84bb39791563d08a16a1)
2022-01-28 18:33:21.188 15634-15634/? A/DEBUG:       #02 pc 0000000000147e64  /data/app/com.zhidao.navi.demo.vr-vc9KlaFHCXK9G1d47N5hNQ==/lib/arm64/libmap.so (_ZNSt6__ndk114__thread_proxyINS_5tupleIJNS_10unique_ptrINS_15__thread_structENS_14default_deleteIS3_EEEEPFvPN3Com8Autonavi4Maps8Internal15tagLabelContextEESC_EEEEEPvSG_+44) (BuildId: 175a92028548a89d9f1f84bb39791563d08a16a1)
2022-01-28 18:33:21.188 15634-15634/? A/DEBUG:       #03 pc 00000000000e68a0  /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+36) (BuildId: 87ed7ba713785c50670d166a6a1664a7)
2022-01-28 18:33:21.188 15634-15634/? A/DEBUG:       #04 pc 0000000000084b6c  /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 87ed7ba713785c50670d166a6a1664a7)


获取具体行号

用addr2line工具获得崩溃位置的具体行号

$ ./aarch64-linux-android-addr2line.exe -C -f -e libmap.so 148a44
Com::Autonavi::Maps::Internal::MapDataMgrGetLabelData(Com::Autonavi::Maps::Internal::tagMapDataMgr*, Com::Autonavi::Maps::Internal::tagMapEnvelope*, Com::Autonavi::Maps::Internal::tagMapQueryObj*, float, Com::Autonavi::Maps::Internal::tagLabelData*)
/root/.jenkins/workspace/MAP-JNI/app/src/main/cpp/mr/MapDataMgr.cpp:97

代码如下
在这里插入图片描述

int MapDataMgrGetLabelData(MapDataMgr * pMgr, MapEnvelope * pEnv, MapQueryObj * pPolygon, float zoom, LabelData * pRes)
{
    int res = 0;
    if(NULL == pMgr || NULL == pMgr->m_pUpdateRegionList)
        return res;
    for(int i = 0;i < pMgr->m_pUpdateRegionList->m_iLength;i++){
        UpdateRegion * pUR = (UpdateRegion*)ArrayListGet(pMgr->m_pUpdateRegionList, i);
        res += UpdateRegionGetLabelData(pUR, pEnv, pPolygon, zoom, pRes);
    }
    return res;
}

崩溃在for循环头部,软件运行在多线程情况下。怀疑pMgr->m_pUpdateRegionList在另外一个线程有写操作,但找了很久,也没找到会同时有写的情况。继续寻找。

反汇编

反汇编得到
objdump.exe -d libmap.so

00000000001489cc <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE>:
1489cc: fc1b0fe8 str d8, [sp,#-80]!
1489d0: a9015ff8 stp x24, x23, [sp,#16]
1489d4: a90257f6 stp x22, x21, [sp,#32]
1489d8: a9034ff4 stp x20, x19, [sp,#48]
1489dc: a9047bfd stp x29, x30, [sp,#64]
1489e0: 910103fd add x29, sp, #0x40
1489e4: b4000380 cbz x0, 148a54 <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE+0x88>
1489e8: aa0003f6 mov x22, x0
1489ec: f9400000 ldr x0, [x0]
1489f0: b4000320 cbz x0, 148a54 <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE+0x88>
1489f4: b9400808 ldr w8, [x0,#8]
1489f8: 7100051f cmp w8, #0x1
1489fc: 540002cb b.lt 148a54 <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE+0x88>
148a00: aa0303f3 mov x19, x3
148a04: 4ea01c08 mov v8.16b, v0.16b
148a08: aa0203f4 mov x20, x2
148a0c: aa0103f5 mov x21, x1
148a10: 2a1f03f8 mov w24, wzr
148a14: 2a1f03f7 mov w23, wzr
148a18: 2a1803e1 mov w1, w24
148a1c: 97fcee81 bl 84420 <ArrayListGet@plt>
148a20: aa1503e1 mov x1, x21
148a24: aa1403e2 mov x2, x20
148a28: 4ea81d00 mov v0.16b, v8.16b
148a2c: aa1303e3 mov x3, x19
148a30: 97fce8ec bl 82de0 <_ZN3Com8Autonavi4Maps8Internal24UpdateRegionGetLabelDataEPNS2_15tagUpdateRegionEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE@plt>
148a34: 2a0003e8 mov w8, w0
148a38: f94002c0 ldr x0, [x22]
148a3c: 11000718 add w24, w24, #0x1
148a40: 0b170117 add w23, w8, w23
148a44: b9400809 ldr w9, [x0,#8] //崩溃点
148a48: 6b09031f cmp w24, w9
148a4c: 54fffe6b b.lt 148a18 <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE+0x4c>
148a50: 14000002 b 148a58 <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE+0x8c>
148a54: 2a1f03f7 mov w23, wzr
148a58: 2a1703e0 mov w0, w23
148a5c: a9447bfd ldp x29, x30, [sp,#64]
148a60: a9434ff4 ldp x20, x19, [sp,#48]
148a64: a94257f6 ldp x22, x21, [sp,#32]
148a68: a9415ff8 ldp x24, x23, [sp,#16]
148a6c: fc4507e8 ldr d8, [sp],#80
148a70: d65f03c0 ret

崩溃点在148a44: b9400809 ldr w9, [x0,#8]
这条指令的含义是将x0中的值+8作为内存地址,取出该内存地址对应值放到寄存器x9的低16位。

结构体的定义如下

typedef struct tagMapDataMgr MapDataMgr;
struct tagMapDataMgr
{
    ArrayList *    m_pUpdateRegionList;
 	LineDataMgr * m_pLineDataMgr;
};
typedef struct tagArrayList
{
   void ** m_pBuffer;
   int m_iLength; //#8
   int m_iSize;
}ArrayList;

分析上下文得到寄存器和变量对应的关系

x0  00070000fff80005   m_pUpdateRegionList
x8  0000000000000006   UpdateRegionGetLabelData函数的返回值
x22 000000721cc30650   pMgr
x23 0000000000000006   res
x24 0000000000000001   i

i==1,for循环体已经执行了一次,那么第一次执行是对的。[x0,#8]对应取pMgr->m_pUpdateRegionList->m_iLength的值。问题在于x0 ==00070000fff80005,即m_pUpdateRegionList值为00070000fff80005 ,该变量保存的是地址,但00070000fff80005字节没对齐而且值过大。再看崩溃信息中有fault addr 0x70000fff8000d,正好是0x00070000fff80005 + 0x8
所以可以确定,m_pUpdateRegionList值出现了问题。

确认

上面的崩溃信息,是由jenkins构建的包产生的。自己想断点调试的话,只能本地测试了,所以libmap.so使用本地的。

  • 反汇编
0000000000336c1c <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE>:
 336c1c: d10183ff sub sp, sp, #0x60
 336c20: a9057bfd stp x29, x30, [sp,#80]
 336c24: 910143fd add x29, sp, #0x50
 336c28: d2800008 mov x8, #0x0 // #0
 336c2c: f81f03a0 stur x0, [x29,#-16]
 336c30: f81e83a1 stur x1, [x29,#-24]
 336c34: f81e03a2 stur x2, [x29,#-32]
 336c38: bc1dc3a0 stur s0, [x29,#-36]
 336c3c: f90013e3 str x3, [sp,#32]
 336c40: b9001fff str wzr, [sp,#28]
 336c44: f85f03a0 ldur x0, [x29,#-16]
 336c48: eb00011f cmp x8, x0
 336c4c: 1a9f17e9 cset w9, eq
 336c50: f90007e8 str x8, [sp,#8]
 336c54: 37000109 tbnz w9, #0, 336c74 <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE+0x58>
 336c58: f85f03a8 ldur x8, [x29,#-16]
 336c5c: f9400108 ldr x8, [x8]
 336c60: f94007e9 ldr x9, [sp,#8]
 336c64: eb08013f cmp x9, x8
 336c68: 1a9f17ea cset w10, eq
 336c6c: 3700004a tbnz w10, #0, 336c74 <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE+0x58>
 336c70: 14000004 b 336c80 <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE+0x64>
 336c74: b9401fe8 ldr w8, [sp,#28]
 336c78: b81fc3a8 stur w8, [x29,#-4]
 336c7c: 1400001e b 336cf4 <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE+0xd8>
 336c80: b9001bff str wzr, [sp,#24]
 336c84: b9401be8 ldr w8, [sp,#24]
 336c88: f85f03a9 ldur x9, [x29,#-16]
 336c8c: f9400129 ldr x9, [x9]
 336c90: b940092a ldr w10, [x9,#8]
 336c94: 6b0a011f cmp w8, w10
 336c98: 1a9fa7e8 cset w8, lt
 336c9c: 37000048 tbnz w8, #0, 336ca4 <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE+0x88>
 336ca0: 14000013 b 336cec <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE+0xd0>
 336ca4: f85f03a8 ldur x8, [x29,#-16]
 336ca8: f9400100 ldr x0, [x8]
 336cac: b9401be1 ldr w1, [sp,#24]
 336cb0: 97f8f23c bl 1735a0 <ArrayListGet@plt>
 336cb4: f9000be0 str x0, [sp,#16]
 336cb8: f9400be0 ldr x0, [sp,#16]
 336cbc: f85e83a1 ldur x1, [x29,#-24]
 336cc0: f85e03a2 ldur x2, [x29,#-32]
 336cc4: bc5dc3a0 ldur s0, [x29,#-36]
 336cc8: f94013e3 ldr x3, [sp,#32]
 336ccc: 97f8e101 bl 16f0d0 <_ZN3Com8Autonavi4Maps8Internal24UpdateRegionGetLabelDataEPNS2_15tagUpdateRegionEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE@plt>
 336cd0: b9401fe9 ldr w9, [sp,#28]
 336cd4: 0b000129 add w9, w9, w0
 336cd8: b9001fe9 str w9, [sp,#28]
 336cdc: b9401be8 ldr w8, [sp,#24]
 336ce0: 11000508 add w8, w8, #0x1
 336ce4: b9001be8 str w8, [sp,#24]
 336ce8: 17ffffe7 b 336c84 <_ZN3Com8Autonavi4Maps8Internal22MapDataMgrGetLabelDataEPNS2_13tagMapDataMgrEPNS2_14tagMapEnvelopeEPNS2_14tagMapQueryObjEfPNS2_12tagLabelDataE+0x68>
 336cec: b9401fe8 ldr w8, [sp,#28]
 336cf0: b81fc3a8 stur w8, [x29,#-4]
 336cf4: b85fc3a0 ldur w0, [x29,#-4]
 336cf8: a9457bfd ldp x29, x30, [sp,#80]
 336cfc: 910183ff add sp, sp, #0x60
 336d00: d65f03c0 ret

通过断点,查到m_pUpdateRegionList的值为0x00000076fe03f670。

在这里插入图片描述
分析汇编代码,发现x9寄存器保存的是m_pUpdateRegionList的值,通过lldb查看x9寄存器的值,发现正好是0x00000076fe03f670。
在这里插入图片描述

可见,由汇编指令,对比寄存器的值,寻找对应变量的值,方法可行。

知识点

  • arm64-v8a中有30个通用寄存器,以x0,x1…x29命名,w0表示x0的低32位。
  • ldr w9, [x0,#8],表示读出x0中存储的地址+8表示的地址,放入x9寄存器的低32位。
  • android studio中的lldb可以查看寄存器值,register read 以16进制显示,register read/d 以10进制显示。
  • 通过对比寄存器值和汇编指令,可以找到崩溃时一些变量的值。

qa

汇编指令直接操作寄存器,那么

  • 被调函数和调用者同时操作相同的寄存器,产生冲突。
  • 两个线程同时调用一个函数,也会操作相同的寄存器,产生冲突。

对于函数调用,调用之前会保存寄存器状态,子函数返回后,会恢复,所以不会有冲突。
对于多线程,如果是伪并发,也会保存/恢复寄存器。如果是真并发,每个线程都有自己的寄存器集,也不会有冲突。

我们平常所说的2核4线程,每个核都有一个独立的cpu,即有自己的寄存器,alu等全套资源,然而线程只拥有一部分,但至少包含寄存器集,要不根据汇编指令找对应的寄存器就不准了,还咋并发。

Does each core in a processor have its own set of registers? Does each
thread in a core have its own set of registers?

In short, yes and yes.

In a true multi-core processor, each of the cores is functionally
equivalent to an individual CPU. They may be fabricated on the same
silicon die, and there are normally some shared components such as
clock generators, power control circuits, and higher-level caches but…
basically each core is a separate processor which can work
independently of the others. That means each core has its own
registers, its own ALU, and its own copy of all the other parts of the
execution pipeline.

So-called “multithreading” CPU cores are a little bit more varied in
their designs. The basic idea is that a “multi-threaded” core contains
multiple copies of some—but not all—of the hardware necessary to
execute a program. The extra hardware allows the CPU core to execute
multiple threads or processes more efficiently, but without the
expense of adding a whole extra CPU core. In all of the real-world
implementations that I’ve heard of (including Intel Hyper-threading),
there is a separate set of general-purpose registers for each thread.
This makes context switches faster, because the core can switch
between executing multiple threads without saving all of the registers
to memory.

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值