1.启动gdb
gdb可以使用我们源码prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin路径下的arm-eabi-gdb即可,方法是:
在源码根目录下执行:
1) source build/envsetup.sh
2)lunch 对应版本
3)arm-eabi-gdb
2.查看core文件发现出错位置
进入gdb后,默认终端下会有gdb标识,然后执行如下命令
1)使用file命令,关联出问题进程的可执行程序,可执行程序的路径在/symbols/system/bin/下,一般是app_process
(gdb) file./symbols/system/bin/app_process
2)使用set命令,设置默认lib的搜索路径
(gdb) set solib-search-pathsymbols/system/lib/
3.利用core命令 打开响应的coredump文件,coredump文件目前平台统一生成到了mnt/sdcard/slog/corefile下面,命名格式是core-出问题应用进程名字-pid
(gdb) core./core-com.android.mms-19934
如下是执行完core后的显示结果
GDB will be unable to debugshared library initializers
and track explicitly loadeddynamic code.
Core was generated by`com.android.email '.
Program terminated withsignal 11, Segmentation fault.
#0 scanObject(obj=0x40e17b68, ctx=0xa5d750) at dalvik/vm/alloc/MarkSweep.cpp:460
warning: Source file is morerecent than executable.
460 }else if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
2.利用 gdb命令 进行调试 ,常用的gdb命令可以百度一下,
如下实例显示如何使用及结果
1)查看调用堆栈信息,命令:bt
(gdb) bt
#0 scanObject (obj=0x40e17b68,ctx=0xa5d750) at dalvik/vm/alloc/MarkSweep.cpp:460
#1 0x40858d60 inprocessMarkStack (ctx=0xa5d750) at dalvik/vm/alloc/MarkSweep.cpp:479
#2 0x40848ef8 indvmCollectGarbageInternal (spec=0x408db01c) at dalvik/vm/alloc/Heap.cpp:530
#3 0x40849510 intryMalloc (size=1048592, flags=0) at dalvik/vm/alloc/Heap.cpp:228
#4 dvmMalloc(size=1048592, flags=0) at dalvik/vm/alloc/Heap.cpp:357
#5 0x4088a378 inallocArray (arrayClass=0x40b277d8, length=1048576, elemWidth=
atdalvik/vm/oo/Array.cpp:58
#6 0x4088a484 indvmAllocPrimitiveArray (type=
#7 0x4086a4d0 inNewByteArray (env=
#8 0x401f273a in_JNIEnv::NewByteArray (env=0xa5d500, bitmap=0xbeaa54b4, ctable=0x0) atdalvik/libnativehelper/include/nativehelper/jni.h:883
#9 GraphicsJNI::allocateJavaPixelRef (env=0xa5d500, bitmap=0xbeaa54b4, ctable=0x0)
atframeworks/base/core/jni/android/graphics/Graphics.cpp:491
#10 0x401f2782 inJavaPixelAllocator::allocPixelRef (this=0xbeaa552c, bitmap=0xbeaa54b4,ctable=0x0)
atframeworks/base/core/jni/android/graphics/Graphics.cpp:527
#11 0x4066eb24 in SkBitmap::allocPixels(this=0xbeaa54b4, allocator=0x2f1b, ctable=0x0) atexternal/skia/src/core/SkBitmap.cpp:367
#12 0x40663db8 inSkPNGImageDecoder::onDecode (this=
decodedBitmap=
2)查看出问题时的汇编代码.命令 disass
Dump of assembler code forfunction scanObject:
0x40858b40<+0>: push {r4, r5, r6, r7, r8, lr}
0x40858b44<+4>: mov r4, r0
0x40858b48<+8>: ldr r0, [pc,#480] ; 0x40858d30
0x40858b4c<+12>: mov r7, r1
0x40858b50<+16>: ldr r5, [pc, r0]
0x40858b54<+20>: ldr r0, [r4] //从r4地址处读出,保存到r0
0x40858b58<+24>: ldr r3, [r5,#176] ; 0xb0
0x40858b5c<+28>: cmp r0, r3
0x40858b60<+32>: beq 0x40858c50
=> 0x40858b64<+36>: ldr r12, [r0,#32] <<<====出错位置
0x40858b68<+40>: tst r12,#1073741824 ; 0x40000000
0x40858b6c<+44>: beq 0x40858bb8
0x40858b70<+48>: bl 0x4085865c
0x40858b74<+52>: ldr r0, [r4]
0x40858b78<+56>: ldr r3, [r0, #32]
0x40858b7c<+60>: tst r3, #536870912 ; 0x20000000
0x40858b80<+64>: popeq {r4, r5, r6, r7, r8, pc}
0x40858b84<+68>: ldr lr, [r4, #8]
0x40858b88<+72>: add r6, r4, #16
3).查看对应寄存器的值,命令info reg:
(gdb) info reg
r0 0x450053 4522067
r1 0xa5d750 10868560
r2 0x100044 1048644
r3 0x40b261e8 1085432296
r4 0x40e17b68 1088519016
r5 0x408e5088 1083068552
r6 0x408e03a0 1083048864
r7 0xa5d750 10868560
r8 0x0 0
r9 0x0 0
r10 0x317bd3 3242963
r11 0x408e5088 1083068552
r12 0x2f1b 12059
sp 0xbeaa5270 0xbeaa5270
lr 0x40858d60 1082494304
查看当时寄存器的信息及参数变量对应的值,发现obj->clazz与r0寄存器中的值是一样的,然后寻找对应函数的源码为dalvik/vm/alloc/MarkSweep.cpp
static void scanObject(constObject *obj, GcMarkContext *ctx)
{
assert(obj != NULL);
assert(obj->clazz != NULL);
if(obj->clazz == gDvm.classJavaLangClass) {
scanClassObject(obj, ctx);
} else if(IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) { <<<===出错位置
scanArrayObject(obj, ctx);
} else {
scanDataObject(obj, ctx);
}
}
5)可以利用p命令查看变量及函数的值或者地址
6)利用x命令查看某一内存地址附近的信息
在遍历对象的时候某一object的clazz(看源代码该变量表示classobject的一个指针)不对,查看该值附近的内存信息,有内存覆盖的现象
7)当然很重要的一点要看出问题的时候对应的应用进程和线程都进行了哪些操作,这点可以从main&system log中查看