美文网首页
JNI SO库崩溃异常与库信息

JNI SO库崩溃异常与库信息

作者: 码上述Andy | 来源:发表于2019-07-05 16:37 被阅读0次

    1.前言

    为了编译根据so库崩溃指令地址,能快速定位到导致崩溃函数。

    2.工具介绍

    1.1addr2line:

    可以通过指令地址映射出成JNI对应的文件名,函数名,行数的工具。
    工具位置:/Users/zhouwen/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-addr2line
    工具使用: arm-linux-androideabi-addr2line -C -f -e<参数> libnative-lib2.so<动态库> 崩溃地址

    1.2.objdump:

    Display information from object <file(s)>----根据objdump --help里描述
    用于反汇编查看目标文件或者可执行文件的信息。
    工具位置:/Users/zhouwen/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-objdump

    3.工具使用:

    异常分析

    3.1.addr2line
    抛出致命异常
    JNIEXPORT void JNICALL Java_jni_chowen_com_nativeapp_MainActivity_throwException
            (JNIEnv *env, jobject jobject1, jstring jstring1) {
        jclass  jclass1 = env->FindClass("java/io/IOException");
        const char* c = env->GetStringUTFChars(jstring1, 0);
    
        env->FatalError(c); // 抛出一个致命异常
    
        jthrowable jthrowable1 = env->ExceptionOccurred();
    
        if (env->ThrowNew(jclass1, c) == JNI_OK){
            if(jthrowable1){
                LOGE("JNI throw suc ExceptionOccurred");
            }
            env->ExceptionDescribe();
    
            LOGE("JNI throw suc");
        } else {
            LOGE("JNI throw failed");
        }
    }
    
    backtrace信息:
    backtrace:
    2019-07-05 14:18:22.078 8767-8767/? A/DEBUG:     #00 pc 00000ac4  [vdso:b660f000] (__kernel_vsyscall+16)
    2019-07-05 14:18:22.078 8767-8767/? A/DEBUG:     #01 pc 0001edf8  /system/lib/libc.so (syscall+40)
    2019-07-05 14:18:22.078 8767-8767/? A/DEBUG:     #02 pc 0001f073  /system/lib/libc.so (abort+115)
    2019-07-05 14:18:22.078 8767-8767/? A/DEBUG:     #03 pc 0054d4fb  /system/lib/libart.so (art::Runtime::Abort(char const*)+603)
    2019-07-05 14:18:22.078 8767-8767/? A/DEBUG:     #04 pc 0011fb23  /system/lib/libart.so (_ZNSt3__110__function6__funcIPFvPKcENS_9allocatorIS5_EES4_EclEOS3_+35)
    2019-07-05 14:18:22.078 8767-8767/? A/DEBUG:     #05 pc 0065f2eb  /system/lib/libart.so (android::base::LogMessage::~LogMessage()+1051)
    2019-07-05 14:18:22.078 8767-8767/? A/DEBUG:     #06 pc 003e25a4  /system/lib/libart.so (art::JNI::FatalError(_JNIEnv*, char const*)+180)
    2019-07-05 14:18:22.078 8767-8767/? A/DEBUG:     #07 pc 0013818c  /system/lib/libart.so (art::CheckJNI::FatalError(_JNIEnv*, char const*)+924)
    2019-07-05 14:18:22.078 8767-8767/? A/DEBUG:     #08 pc 0003754b  /data/app/jni.chowen.com.nativeapp-v1AIqpkS5gwn6UB76ahh8A==/lib/x86/libnative-lib2.so (_JNIEnv::FatalError(char const*)+59)
    2019-07-05 14:18:22.078 8767-8767/? A/DEBUG:     #09 pc 0003736a  /data/app/jni.chowen.com.nativeapp-v1AIqpkS5gwn6UB76ahh8A==/lib/x86/libnative-lib2.so 
    
    执行命令arm-linux-androideabi-addr2line
    /Users/zhouwen/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-addr2line -C -f -e /Users/zhouwen/work/NativeApp/app/build/intermediates/cmake/debug/obj/x86/libnative-lib2.so 0003736a
    Java_jni_chowen_com_nativeapp_MainActivity_throwException
    /Users/zhouwen/work/NativeApp/app/src/main/cpp/native-lib.cpp:52
    
    addr2line参数:

    libnative-lib2.so为崩溃的SO动态库
    0003736a:指令地址
    Java_jni_chowen_com_nativeapp_MainActivity_throwException:解析出JNI里对应的函数名称
    /Users/zhouwen/work/NativeApp/app/src/main/cpp/native-lib.cpp:52:对应的指令地址解析出来对应的文件及函数对应的行数为第52行。

    ➜  ~ /Users/zhouwen/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-addr2line --help
    Usage: /Users/zhouwen/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-addr2line [option(s)] [addr(s)]
     Convert addresses into line number/file name pairs.
     If no addresses are specified on the command line, they will be read from stdin
     The options are:
      @<file>                Read options from <file>
      -a --addresses         Show addresses
      -b --target=<bfdname>  Set the binary file format
      -e --exe=<executable>  Set the input file name (default is a.out)
      -i --inlines           Unwind inlined functions
      -j --section=<name>    Read section-relative offsets instead of addresses
      -p --pretty-print      Make the output easier to read for humans
      -s --basenames         Strip directory names
      -f --functions         Show function names
      -C --demangle[=style]  Demangle function names
      -h --help              Display this information
      -v --version           Display the program's version
    

    3.2.objdump

    查看.o文件信息
     /Users/zhouwen/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-objdump -S /Users/zhouwen/Desktop/ffmpeg/ffmpeg-4.1.3/libavcodec/yuv4dec.o
    /Users/zhouwen/Desktop/ffmpeg/ffmpeg-4.1.3/libavcodec/yuv4dec.o:     file format elf32-littlearm
    
    
    Disassembly of section .text:
    
    00000000 <yuv4_decode_frame>:
        AVFrame *pic = data;
        const uint8_t *src = avpkt->data;
        uint8_t *y, *u, *v;
        int i, j, ret;
    
        if (avpkt->size < 6 * (avctx->width + 1 >> 1) * (avctx->height + 1 >> 1)) {
       0:   e590c05c    ldr ip, [r0, #92]   ; 0x5c
    {
       4:   e92d4ff0    push    {r4, r5, r6, r7, r8, r9, sl, fp, lr}
        if (avpkt->size < 6 * (avctx->width + 1 >> 1) * (avctx->height + 1 >> 1)) {
       8:   e28cc001    add ip, ip, #1
       c:   e590e060    ldr lr, [r0, #96]   ; 0x60
      10:   e1a0c0cc    asr ip, ip, #1
      14:   e08cc08c    add ip, ip, ip, lsl #1
      18:   e28ee001    add lr, lr, #1
      1c:   e1a0e0ce    asr lr, lr, #1
      20:   e1a0c08c    lsl ip, ip, #1
    {
      24:   e24dd00c    sub sp, sp, #12
        if (avpkt->size < 6 * (avctx->width + 1 >> 1) * (avctx->height + 1 >> 1)) {
      28:   e00c0c9e    mul ip, lr, ip
    {
      2c:   e58d3004    str r3, [sp, #4]
        if (avpkt->size < 6 * (avctx->width + 1 >> 1) * (avctx->height + 1 >> 1)) {
      30:   e1a0e003    mov lr, r3
      34:   e593301c    ldr r3, [r3, #28]
    {
      38:   e1a07000    mov r7, r0
        if (avpkt->size < 6 * (avctx->width + 1 >> 1) * (avctx->height + 1 >> 1)) {
      3c:   e153000c    cmp r3, ip
    {
      40:   e58d2000    str r2, [sp]
        const uint8_t *src = avpkt->data;
      44:   e59e5018    ldr r5, [lr, #24]
        if (avpkt->size < 6 * (avctx->width + 1 >> 1) * (avctx->height + 1 >> 1)) {
      48:   ba000044    blt 160 <yuv4_decode_frame+0x160>
            av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n");
            return AVERROR(EINVAL);
        }
    
        if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
      4c:   e3a02000    mov r2, #0
      50:   e1a06001    mov r6, r1
      54:   ebfffffe    bl  0 <ff_get_buffer>
      58:   e3500000    cmp r0, #0
      5c:   ba00003d    blt 158 <yuv4_decode_frame+0x158>
    
        y = pic->data[0];
        u = pic->data[1];
        v = pic->data[2];
    
        for (i = 0; i < (avctx->height + 1) >> 1; i++) {
      60:   e5973060    ldr r3, [r7, #96]   ; 0x60
        pic->key_frame = 1;
      64:   e3a02001    mov r2, #1
        for (i = 0; i < (avctx->height + 1) >> 1; i++) {
      68:   e0833002    add r3, r3, r2
      6c:   e1530002    cmp r3, r2
        pic->key_frame = 1;
      70:   e5862054    str r2, [r6, #84]   ; 0x54
        pic->pict_type = AV_PICTURE_TYPE_I;
      74:   e5862058    str r2, [r6, #88]   ; 0x58
        v = pic->data[2];
      78:   e8960610    ldm r6, {r4, r9, sl}
        for (i = 0; i < (avctx->height + 1) >> 1; i++) {
      7c:   da000030    ble 144 <yuv4_decode_frame+0x144>
      80:   e597c05c    ldr ip, [r7, #92]   ; 0x5c
      84:   e3a08000    mov r8, #0
      88:   e08cc002    add ip, ip, r2
            for (j = 0; j < (avctx->width + 1) >> 1; j++) {
      8c:   e35c0001    cmp ip, #1
      90:   da000023    ble 124 <yuv4_decode_frame+0x124>
      94:   e2853006    add r3, r5, #6
      98:   e249b001    sub fp, r9, #1
      9c:   e24ae001    sub lr, sl, #1
      a0:   e1a00004    mov r0, r4
      a4:   e3a02000    mov r2, #0
                u[j] = *src++ ^ 0x80;
      a8:   e5531006    ldrb    r1, [r3, #-6]
                v[j] = *src++ ^ 0x80;
                y[                   2 * j    ] = *src++;
                y[                   2 * j + 1] = *src++;
                y[pic->linesize[0] + 2 * j    ] = *src++;
                y[pic->linesize[0] + 2 * j + 1] = *src++;
      ac:   e084c082    add ip, r4, r2, lsl #1
                u[j] = *src++ ^ 0x80;
      b0:   e221107f    eor r1, r1, #127    ; 0x7f
      b4:   e1e01001    mvn r1, r1
      b8:   e5eb1001    strb    r1, [fp, #1]!
                v[j] = *src++ ^ 0x80;
      bc:   e5531005    ldrb    r1, [r3, #-5]
      c0:   e2800002    add r0, r0, #2
      c4:   e221107f    eor r1, r1, #127    ; 0x7f
      c8:   e1e01001    mvn r1, r1
      cc:   e5ee1001    strb    r1, [lr, #1]!
                y[                   2 * j    ] = *src++;
      d0:   e5531004    ldrb    r1, [r3, #-4]
      d4:   e7c41082    strb    r1, [r4, r2, lsl #1]
                y[                   2 * j + 1] = *src++;
      d8:   e5531003    ldrb    r1, [r3, #-3]
      dc:   e5401001    strb    r1, [r0, #-1]
                y[pic->linesize[0] + 2 * j    ] = *src++;
      e0:   e5961020    ldr r1, [r6, #32]
      e4:   e5535002    ldrb    r5, [r3, #-2]
      e8:   e0841001    add r1, r4, r1
      ec:   e7c15082    strb    r5, [r1, r2, lsl #1]
                y[pic->linesize[0] + 2 * j + 1] = *src++;
      f0:   e5965020    ldr r5, [r6, #32]
      f4:   e5531001    ldrb    r1, [r3, #-1]
      f8:   e08cc005    add ip, ip, r5
      fc:   e5cc1001    strb    r1, [ip, #1]
            for (j = 0; j < (avctx->width + 1) >> 1; j++) {
     100:   e597c05c    ldr ip, [r7, #92]   ; 0x5c
     104:   e2822001    add r2, r2, #1
     108:   e28cc001    add ip, ip, #1
     10c:   e15200cc    cmp r2, ip, asr #1
     110:   e1a05003    mov r5, r3
     114:   e2833006    add r3, r3, #6
     118:   baffffe2    blt a8 <yuv4_decode_frame+0xa8>
     11c:   e5973060    ldr r3, [r7, #96]   ; 0x60
     120:   e2833001    add r3, r3, #1
            }
    
            y += 2 * pic->linesize[0];
            u +=     pic->linesize[1];
            v +=     pic->linesize[2];
     124:   e2860020    add r0, r6, #32
     128:   e8900007    ldm r0, {r0, r1, r2}
        for (i = 0; i < (avctx->height + 1) >> 1; i++) {
     12c:   e2888001    add r8, r8, #1
     130:   e15800c3    cmp r8, r3, asr #1
            y += 2 * pic->linesize[0];
     134:   e0844080    add r4, r4, r0, lsl #1
            u +=     pic->linesize[1];
     138:   e0899001    add r9, r9, r1
            v +=     pic->linesize[2];
     13c:   e08aa002    add sl, sl, r2
        for (i = 0; i < (avctx->height + 1) >> 1; i++) {
     140:   baffffd1    blt 8c <yuv4_decode_frame+0x8c>
        }
    
        *got_frame = 1;
     144:   e59d2000    ldr r2, [sp]
     148:   e3a03001    mov r3, #1
     14c:   e5823000    str r3, [r2]
    
        return avpkt->size;
     150:   e59d3004    ldr r3, [sp, #4]
     154:   e593001c    ldr r0, [r3, #28]
    }
     158:   e28dd00c    add sp, sp, #12
     15c:   e8bd8ff0    pop {r4, r5, r6, r7, r8, r9, sl, fp, pc}
            av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n");
     160:   e59f2010    ldr r2, [pc, #16]   ; 178 <yuv4_decode_frame+0x178>
     164:   e3a01010    mov r1, #16
     168:   e08f2002    add r2, pc, r2
     16c:   ebfffffe    bl  0 <av_log>
            return AVERROR(EINVAL);
     170:   e3e00015    mvn r0, #21
     174:   eafffff7    b   158 <yuv4_decode_frame+0x158>
     178:   00000008    .word   0x00000008
    
    Disassembly of section .text.unlikely:
    
    00000000 <yuv4_decode_init>:
        if (avpkt->size < 6 * (avctx->width + 1 >> 1) * (avctx->height + 1 >> 1)) {
       0:   e3a03000    mov r3, #0
    {
       4:   e5803070    str r3, [r0, #112]  ; 0x70
        if (avpkt->size < 6 * (avctx->width + 1 >> 1) * (avctx->height + 1 >> 1)) {
       8:   e1a00003    mov r0, r3
       c:   e12fff1e    bx  lr
    
    查看.a静态库中.o文件信息
    ➜  ~ /Users/zhouwen/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-objdump -a /Users/zhouwen/Desktop/ffmpeg/ffmpeg-4.1.3/android/armv7-a/lib/libswscale.a
    In archive /Users/zhouwen/Desktop/ffmpeg/ffmpeg-4.1.3/android/armv7-a/lib/libswscale.a:
    
    alphablend.o:     file format elf32-littlearm
    rw-r--r-- 0/0   4244 Jan  1 08:00 1970 alphablend.o
    
    
    gamma.o:     file format elf32-littlearm
    rw-r--r-- 0/0   1224 Jan  1 08:00 1970 gamma.o
    
    
    hscale.o:     file format elf32-littlearm
    rw-r--r-- 0/0   4320 Jan  1 08:00 1970 hscale.o
    
    
    hscale_fast_bilinear.o:     file format elf32-littlearm
    rw-r--r-- 0/0   1204 Jan  1 08:00 1970 hscale_fast_bilinear.o
    
    
    input.o:     file format elf32-littlearm
    rw-r--r-- 0/0  46804 Jan  1 08:00 1970 input.o
    
    
    options.o:     file format elf32-littlearm
    rw-r--r-- 0/0   5660 Jan  1 08:00 1970 options.o
    
    
    output.o:     file format elf32-littlearm
    rw-r--r-- 0/0 162388 Jan  1 08:00 1970 output.o
    
    
    rgb2rgb.o:     file format elf32-littlearm
    rw-r--r-- 0/0  11336 Jan  1 08:00 1970 rgb2rgb.o
    
    
    slice.o:     file format elf32-littlearm
    rw-r--r-- 0/0   5480 Jan  1 08:00 1970 slice.o
    
    
    swscale.o:     file format elf32-littlearm
    rw-r--r-- 0/0  15288 Jan  1 08:00 1970 swscale.o
    
    
    swscale_unscaled.o:     file format elf32-littlearm
    rw-r--r-- 0/0  66444 Jan  1 08:00 1970 swscale_unscaled.o
    
    
    utils.o:     file format elf32-littlearm
    rw-r--r-- 0/0  39388 Jan  1 08:00 1970 utils.o
    
    
    vscale.o:     file format elf32-littlearm
    rw-r--r-- 0/0   5372 Jan  1 08:00 1970 vscale.o
    
    
    yuv2rgb.o:     file format elf32-littlearm
    rw-r--r-- 0/0  35260 Jan  1 08:00 1970 yuv2rgb.o
    
    objdump参数:

    ../Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-objdump --help

    Display information from object <file(s)>.
     At least one of the following switches must be given:
      -a, --archive-headers    Display archive header information
      -f, --file-headers       Display the contents of the overall file header
      -p, --private-headers    Display object format specific file header contents
      -P, --private=OPT,OPT... Display object format specific contents
      -h, --[section-]headers  Display the contents of the section headers
      -x, --all-headers        Display the contents of all headers
      -d, --disassemble        Display assembler contents of executable sections
      -D, --disassemble-all    Display assembler contents of all sections
      -S, --source             Intermix source code with disassembly
      -s, --full-contents      Display the full contents of all sections requested
      -g, --debugging          Display debug information in object file
      -e, --debugging-tags     Display debug information using ctags style
      -G, --stabs              Display (in raw form) any STABS info in the file
      -W[lLiaprmfFsoRt] or
      --dwarf[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,
              =frames-interp,=str,=loc,=Ranges,=pubtypes,
              =gdb_index,=trace_info,=trace_abbrev,=trace_aranges,
              =addr,=cu_index]
                               Display DWARF info in the file
      -t, --syms               Display the contents of the symbol table(s)
      -T, --dynamic-syms       Display the contents of the dynamic symbol table
      -r, --reloc              Display the relocation entries in the file
      -R, --dynamic-reloc      Display the dynamic relocation entries in the file
      @<file>                  Read options from <file>
      -v, --version            Display this program's version number
      -i, --info               List object formats and architectures supported
      -H, --help               Display this information
    
     The following switches are optional:
      -b, --target=BFDNAME           Specify the target object format as BFDNAME
      -m, --architecture=MACHINE     Specify the target architecture as MACHINE
      -j, --section=NAME             Only display information for section NAME
      -M, --disassembler-options=OPT Pass text OPT on to the disassembler
      -EB --endian=big               Assume big endian format when disassembling
      -EL --endian=little            Assume little endian format when disassembling
          --file-start-context       Include context from start of file (with -S)
      -I, --include=DIR              Add DIR to search list for source files
      -l, --line-numbers             Include line numbers and filenames in output
      -F, --file-offsets             Include file offsets when displaying information
      -C, --demangle[=STYLE]         Decode mangled/processed symbol names
                                      The STYLE, if specified, can be `auto', `gnu',
                                      `lucid', `arm', `hp', `edg', `gnu-v3', `java'
                                      or `gnat'
      -w, --wide                     Format output for more than 80 columns
      -z, --disassemble-zeroes       Do not skip blocks of zeroes when disassembling
          --start-address=ADDR       Only process data whose address is >= ADDR
          --stop-address=ADDR        Only process data whose address is <= ADDR
          --prefix-addresses         Print complete address alongside disassembly
          --[no-]show-raw-insn       Display hex alongside symbolic disassembly
          --insn-width=WIDTH         Display WIDTH bytes on a single line for -d
          --adjust-vma=OFFSET        Add OFFSET to all displayed section addresses
          --special-syms             Include special symbols in symbol dumps
          --prefix=PREFIX            Add PREFIX to absolute paths for -S
          --prefix-strip=LEVEL       Strip initial directory names for -S
          --dwarf-depth=N        Do not display DIEs at depth N or greater
          --dwarf-start=N        Display DIEs starting with N, at the same depth
                                 or deeper
          --dwarf-check          Make additional dwarf internal consistency checks.  
    

    4.That's All

    addr2line和objdump这两个工具参数就不展开介绍了,网上资料很多。

    相关文章

      网友评论

          本文标题:JNI SO库崩溃异常与库信息

          本文链接:https://www.haomeiwen.com/subject/njefcctx.html