Issues caused by virtual function call or function pointer call

几个对象释放后虚方法调用产生的错误;同时简记虚方法表的GCC实现和结构。注意默认虚析构函数,和虚方法表的负偏移结构。

1.

pid: 1082, tid: 1082, name: d.process.media >>> android.process.media <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000
r0 40192d1c r1 58d78db8 r2 4fa08856 r3 00000000
r4 403b4778 r5 40c2b2a0 r6 00000000 r7 56e9ed60
r8 bea29570 r9 56e9ed58 sl 40c2b2b0 fp bea29584
ip 401a1f74 sp bea29568 lr 51152891 pc 00000000 cpsr 60000010
d0 0000000000000000 d1 0000000000000000
d2 000003e800000000 d3 0000000000000004
d4 007000700061002e d5 007400630041002e
d6 0074006900760069 d7 0072006800540079
d8 0000000000000000 d9 0000000000000000
d10 0000000000000000 d11 0000000000000000
d12 0000000000000000 d13 0000000000000000
d14 0000000000000000 d15 0000000000000000
d16 6f632074726f6261 d17 6e6f697463656e6e
d18 0000000000000000 d19 0076006f00720070
d20 0072006500640069 d21 0065006d002e0073
d22 002e006100690064 d23 005300700074004d
d24 3fede16b9c24a98f d25 3fe55559ee5e69f9
d26 0000000000000000 d27 0000000000000000
d28 0000000000000005 d29 0000000000000000
d30 0000000000000000 d31 0000000000000000
scr 6000001c

backtrace:
#00 pc 00000000 <unknown>
#01 pc 0000e88f /system/lib/libmtp.so (android::MtpServer::abort()+26)
#02 pc 00020490 /system/lib/libdvm.so (dvmPlatformInvoke+112)
#03 pc 0004fd79 /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+396)
#04 pc 00029920 /system/lib/libdvm.so
#05 pc 0002dc44 /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
#06 pc 000628e3 /system/lib/libdvm.so (dvmInvokeMethod(Object*, Method const*, ArrayObject*, ArrayObject*, ClassObject*, bool)+374)
#07 pc 0006a1e1 /system/lib/libdvm.so
#08 pc 00029920 /system/lib/libdvm.so
#09 pc 0002dc44 /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
#10 pc 0006260d /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272)
#11 pc 0004c2ab /system/lib/libdvm.so
#12 pc 0004f0b5 /system/lib/libandroid_runtime.so
#13 pc 0004fd77 /system/lib/libandroid_runtime.so (android::AndroidRuntime::start(char const*, char const*)+390)
#14 pc 00000db7 /system/bin/app_process
#15 pc 0001273f /system/lib/libc.so (__libc_init+38)
#16 pc 00000ae8 /system/bin/app_process

2.

pid: 1037, tid: 1037, name: d.process.media >>> android.process.media <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0000001a
r0 402a5d14 r1 5c6a2020 r2 c4d14163 r3 0000001b
r4 404256d0 r5 410261c0 r6 00000000 r7 400c2d60
r8 beaef570 r9 400c2d58 sl 410261d0 fp beaef584
ip 400fef74 sp beaef568 lr 5afb679d pc 0000001a cpsr 60000030
d0 0000000000000000 d1 0000000000000000
d2 000003e800000000 d3 0000000000000004
d4 007000700061002e d5 007400630041002e
d6 0074006900760069 d7 0072006800540079
d8 0000000000000000 d9 0000000000000000
d10 0000000000000000 d11 0000000000000000
d12 0000000000000000 d13 0000000000000000
d14 0000000000000000 d15 0000000000000000
d16 6f632074726f6261 d17 6e6f697463656e6e
d18 002e00640069006f d19 0076006f00720070
d20 0072006500640069 d21 0065006d002e0073
d22 002e006100690064 d23 005300700074004d
d24 3fede16b9c24a98f d25 3fe55559ee5e69f9
d26 0000000000000000 d27 0000000000000000
d28 0000000000000005 d29 0000000000000000
d30 0000000000000000 d31 0000000000000000
scr 6000001c

backtrace:
#00 pc 0000001a <unknown>
#01 pc 0000e79b /system/lib/libmtp.so (android::MtpServer::abort()+26)
#02 pc 00020050 /system/lib/libdvm.so (dvmPlatformInvoke+112)
#03 pc 0004f871 /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+396)
#04 pc 000294e0 /system/lib/libdvm.so
#05 pc 0002d73c /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
#06 pc 000623db /system/lib/libdvm.so (dvmInvokeMethod(Object*, Method const*, ArrayObject*, ArrayObject*, ClassObject*, bool)+374)
#07 pc 00069cd9 /system/lib/libdvm.so
#08 pc 000294e0 /system/lib/libdvm.so
#09 pc 0002d73c /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
#10 pc 00062105 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272)
#11 pc 0004bda3 /system/lib/libdvm.so
#12 pc 0004ef8d /system/lib/libandroid_runtime.so
#13 pc 0004fc4f /system/lib/libandroid_runtime.so (android::AndroidRuntime::start(char const*, char const*)+390)
#14 pc 00000db7 /system/bin/app_process
#15 pc 0001273f /system/lib/libc.so (__libc_init+38)
#16 pc 00000ae8 /system/bin/app_process

3.

pid: 18663, tid: 18663, name: d.process.media >>> android.process.media <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000006
r0 4025c5e4 r1 5c8c3c20 r2 400d9010 r3 00000007
r4 56ef8730 r5 400d9010 r6 00000000 r7 401dbd64
r8 befe86e8 r9 401dbd5c sl 400d9020 fp befe86fc
ip 5ac86f40 sp befe86e0 lr 5aa4f563 pc 00000006 cpsr 20000030
d0 0000000000000000 d1 0000000000000000
d2 000003e800000000 d3 0000000000000004
d4 006c0061006e0072 d5 006f007400730020
d6 0065006700610072 d7 0020007300690020
d8 0000000000000000 d9 0000000000000000
d10 0000000000000000 d11 0000000000000000
d12 0000000000000000 d13 0000000000000000
d14 0000000000000000 d15 0000000000000000
d16 0074006900760069 d17 006e0061004d0079
d18 002e00640069006f d19 0076006f00720070
d20 0072006500640069 d21 0065006d002e0073
d22 002e006100690064 d23 005300700074004d
d24 3fede16b9c24a98f d25 3fe55559ee5e69f9
d26 0000000000000000 d27 0000000000000000
d28 0000000000000005 d29 0000000000000000
d30 0000000000000000 d31 0000000000000000
scr 80000010

backtrace:
#00 pc 00000006 <unknown>
#01 pc 0000e561 /system/lib/libmtp.so (android::MtpServer::abort()+10)
#02 pc 0001fb70 /system/lib/libdvm.so (dvmPlatformInvoke+112)
#03 pc 0004e919 /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+360)
#04 pc 00029020 /system/lib/libdvm.so
#05 pc 0002d84c /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+180)
#06 pc 0006025b /system/lib/libdvm.so (dvmInvokeMethod(Object*, Method const*, ArrayObject*, ArrayObject*, ClassObject*, bool)+374)
#07 pc 00067201 /system/lib/libdvm.so
#08 pc 00029020 /system/lib/libdvm.so
#09 pc 0002d84c /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+180)
#10 pc 0005ffb1 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272)
#11 pc 0004af47 /system/lib/libdvm.so
#12 pc 000490cd /system/lib/libandroid_runtime.so
#13 pc 00049ae9 /system/lib/libandroid_runtime.so (android::AndroidRuntime::start(char const*, char const*)+368)
#14 pc 00000dcf /system/bin/app_process

由bugreport可以看出,fault addr是pc指向的地址,说明是取指时,mmu发生地址映射错误,内核发出SIGSEGV : SEGV_MAPERR信号。

猜测是虚函数调用时,对象已经删除从而得到错误的虚方法表地址,因为虚方法表被改写的概率比较低;如果是c中,则大约是调用野函数指针。

以第一个为例进行分析,MtpServer::abort()的代码如下:

292void MtpServer::abort() {
293    ALOGD("abort connection");
294    if(mTransport)
295        mTransport->abort();
296}

从汇编代码可以确认是调用虚函数abort时出错,

Dump of assembler code for function android::MtpServer::abort():
0x0000e874 <+0>: ldr r1, [pc, #28] ; (0xe894 <android::MtpServer::abort()+32>)
0x0000e876 <+2>: ldr r2, [pc, #32] ; (0xe898 <android::MtpServer::abort()+36>)
0x0000e878 <+4>: push {r4, lr}
0x0000e87a <+6>: add r1, pc
0x0000e87c <+8>: mov r4, r0
0x0000e87e <+10>: add r2, pc
0x0000e880 <+12>: movs r0, #3
0x0000e882 <+14>: blx 0xa5fc
0x0000e886 <+18>: ldr r0, [r4, #4]  // MtpServer::mTransport
0x0000e888 <+20>: cbz r0, 0xe890 <android::MtpServer::abort()+28>
0x0000e88a <+22>: ldr r1, [r0, #0]  // virtual function table for MtpTransport subclass
0x0000e88c <+24>: ldr r3, [r1, #28] // virtual function abort() (double destructors ocupy two slots)
0x0000e88e <+26>: blx r3            // call abort()
0x0000e890 <+28>: pop {r4, pc}
0x0000e892 <+30>: nop

MtpServer和MtpTransport的定义如下:

42class MtpServer {
43
44private:
45 // file descriptor for MTP kernel driver
46 //int mFD;
47
48 // transport layer abstraction
49 MtpTransport* mTransport;
...
}

16class MtpTransport
17{
18public: 
…..
36 virtual int ioctl(unsigned int nFlags, unsigned long lValue) = 0;
37
38 virtual int abort() = 0;   // the 7th virtual function including default virtual destructor
...
}

MtpTransport是抽象类,具体类是MTP在USB和IP上的具体实现MtpUsbTransport和MtpIpTransport。这些crash发生在USB做为MTP传输层情景中。

由寄存器使用可以看出

MtpServer object is at 0x403b4778
mTransport is at 0x40192d1c
virtual function table of MtpTransport is at 0x58d78db8 in this issue, which is not a reasonable value.
The address of abort() at slot 7 (zero index based) is zero.

MtpUsbTransport虚方法表的地址为0x58d78db8,不太像是一个有效数据(0x40nnnnnn),从而引用到一个错误的虚函数地址。

MtpServer::run主循环体退出后,MtpTransport即被释放;

162void MtpServer::run() {
163    ALOGV("MtpServer::run");
164    mVendorHandler = new MtpVendorHandler(mTransport, mVendorInterface);
.....
       while(1) {
       }   
283    if (mSessionOpen)
284        mDatabase->sessionEnded();
285    mTransport->close();
286
287    // this memory was allocated in android_mtp_MtpServer_setup
288    delete mTransport;
289    mTransport = NULL;
290}

假若在mTransport赋值NULL前,控制MtpServer停止的abort()函数从另一线程中调用,而mTransport指向的内存已被重新使用,那么if(mTransport)评估通过后,调用mTransport->abort()就会发成错误。

可以加互斥量或者将MtpTransport->abort的释放做到MtpServer::run循环中而MtpServer::abort()向run循环发送命令。

 

[END]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值