天天看点

oobe crash 分析

1 现象

    当使用线刷刷入版本的时候,发现oobe第一次必定出现crash的情况。但是以后就再也不会出现crash的情况。

截取关键日志如下:

11-18 15:50:59.130 D/ActionGuard(  656): tag = MainActivity, on = false kkkkkk
11-18 15:50:59.160 F/libc    (  656): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 656 (tws.oobeprocess)
11-18 15:50:59.270 I/DEBUG   (   74): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
11-18 15:50:59.270 I/DEBUG   (   74): Build fingerprint: 'Ingenic/x3_iwop/watch:4.3/JLS36G/66:userdebug/test-keys'
11-18 15:50:59.270 I/DEBUG   (   74): Revision: '0'
11-18 15:50:59.270 I/DEBUG   (   74): pid: 656, tid: 656, name: tws.oobeprocess  >>> com.tencent.tws.oobeprocess <<<
11-18 15:50:59.270 I/DEBUG   (   74): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000
11-18 15:50:59.390 I/DEBUG   (   74):  zr 00000000  at 00000001  v0 58390f70  v1 2b8134f0
11-18 15:50:59.390 I/DEBUG   (   74):  a0 00000000  a1 7fa9cab0  a2 00000000  a3 583a85d8
11-18 15:50:59.390 I/DEBUG   (   74):  t0 2c046ba0  t1 000005e4  t2 00000000  t3 00000000
11-18 15:50:59.390 I/DEBUG   (   74):  t4 00000004  t5 ffffffff  t6 00000003  t7 7fa9cab8
11-18 15:50:59.400 I/DEBUG   (   74):  s0 55d043f0  s1 57feda98  s2 55d043f0  s3 00000001
11-18 15:50:59.400 I/DEBUG   (   74):  s4 2cdee4a0  s5 2ce115c8  s6 7fa9cc68  s7 00000001
11-18 15:50:59.400 I/DEBUG   (   74):  t8 00000001  t9 2cdc5038  k0 8af00025  k1 00000000
11-18 15:50:59.400 I/DEBUG   (   74):  gp 2ce1a270  sp 7fa9ca68  s8 7fa9cb24  ra 2cdca954
11-18 15:50:59.400 I/DEBUG   (   74):  hi 00000000  lo 00000030 bva 00000000 epc 2cdc507c
11-18 15:50:59.400 I/DEBUG   (   74): 
11-18 15:50:59.400 I/DEBUG   (   74): backtrace:
11-18 15:50:59.400 I/DEBUG   (   74):     #00  pc 0002d07c  /system/lib/libhwui.so
11-18 15:50:59.400 I/DEBUG   (   74):     #01  pc 0003294c  /system/lib/libhwui.so
11-18 15:50:59.400 I/DEBUG   (   74):     #02  pc 00032b18  /system/lib/libhwui.so
11-18 15:50:59.400 I/DEBUG   (   74):     #03  pc 000925b8  /system/lib/libandroid_runtime.so
11-18 15:50:59.400 I/DEBUG   (   74):     #04  pc 00022c24  /system/lib/libdvm.so (dvmPlatformInvoke+212)
11-18 15:50:59.400 I/DEBUG   (   74):     #05  pc 00000001  <unknown>
           

     从log来看,很有可能存在空指针的情况。

oobe crash 分析

    在mips架构中,如果是c代码,a0 ~ a3对应前4个实参和arm架构类似。而在c++代码中,a0为对象指针,如果这为空,基本上可以判断对象为空。

2 分析过程

     那么是哪个函数的哪个对象为空呢?

     从backtrace来看,为空的对象应该来自libhwui.so

     因为是源码编译,所以我们可以取到带symbol的so库。路径为:out/target/productsymbols/system/lib$

     可以使用linux 的file命令来确认下这个so库是否真的是带有symbol的。

[email protected]03:~$ file libhwui.so 
libhwui.so: ELF 32-bit LSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, with unknown capability 0xf41 = 0x756e6700, with unknown capability 0x70100 = 0x1040000, not stripped
[email protected]03:~$ 
           

     接下来,我们就可以使用gcc工具来进行分析咯。

     首先,关键是要找到gcc工具的版本及路径。

     一般android源码都会在prebuild目录下面提供toolchain,那么版本是哪个呢,就要从build脚本中去寻找咯。

     我一般会使用grep -r TOOLCHAIN .在build目录下面进行搜索。

    在源代码中,是通过smk.sh中指定了toolchain的路径的。

prebuilts/gcc/linux-x86/mips/mipsel-linux-android-4.7/bin
           

 进入到这个目录下面,就可以看到很多gcc的工具了。

mipsel-linux-android-addr2line  mipsel-linux-android-cpp      mipsel-linux-android-gcc-ar      mipsel-linux-android-gprof    mipsel-linux-android-objdump  mipsel-linux-android-strip
mipsel-linux-android-ar         mipsel-linux-android-elfedit  mipsel-linux-android-gcc-nm      mipsel-linux-android-ld       mipsel-linux-android-ranlib
mipsel-linux-android-as         mipsel-linux-android-g++      mipsel-linux-android-gcc-ranlib  mipsel-linux-android-ld.bfd   mipsel-linux-android-readelf
mipsel-linux-android-c++        mipsel-linux-android-gcc      mipsel-linux-android-gcov        mipsel-linux-android-nm       mipsel-linux-android-size
mipsel-linux-android-c++filt    mipsel-linux-android-gcc-4.7  mipsel-linux-android-gdb         mipsel-linux-android-objcopy  mipsel-linux-android-strings
           

     这里面,我会用到2个工具:objdump 和 C++filter

    首先通过objdump将libhwui.so中的信息dump出来,然后找到出错pc指针的位置区域:

mipsel-linux-android-objdump -S libhwui.so >libhwui_objdump.txt

oobe crash 分析

    2d07c在函数_ZN7android10uirenderer5Layer5flushEv范围内。

oobe crash 分析

 _ZN7android10uirenderer5Layer5flushEv这个是个什么东西呢。接下来就可以有c++filter出场咯。

mipsel-linux-android-4.7/bin$ ./mipsel-linux-android-c++filt _ZN7android10uirenderer5Layer5flushEv
android::uirenderer::Layer::flush()
           

     看到了吧,原来是在函数中。

      接下来就可以来查看源码了。

      在framework/base/libs/hwui/Layer.cpp中。

void Layer::flush() {
    if (deferredList ) {
        renderer->setViewport(layer.getWidth(), layer.getHeight());
        renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom,
                !isBlend());

        deferredList->flush(*renderer, dirtyRect);

        renderer->finish();

        dirtyRect.setEmpty();
        renderNode = NULL;
    }
}
           

  我们大概可以猜测到,应该是renderer可能为空。

于是我们加上一个空指针保护。

void Layer::flush() {
    if (deferredList && renderer) {
        renderer->setViewport(layer.getWidth(), layer.getHeight());
        renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom,
                !isBlend());

        deferredList->flush(*renderer, dirtyRect);

        renderer->finish();

        dirtyRect.setEmpty();
        renderNode = NULL;
    }
}
           

 3 延伸

    上面的renderer为什么会为空,什么情况下会为空呢?

     “renderer is checked as layer may be destroyed/put in layer cache with flush scheduled”

     具体场景还需要继续研究。

继续阅读