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
用于反汇编查看目标文件或者可执行文件的信息。
工具位置:/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:
@ Read options from
-a --addresses Show addresses
-b --target= Set the binary file format
-e --exe= Set the input file name (default is a.out)
-i --inlines Unwind inlined functions
-j --section= 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 :
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
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
58: e3500000 cmp r0, #0
5c: ba00003d blt 158
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
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
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
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
}
*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
164: e3a01010 mov r1, #16
168: e08f2002 add r2, pc, r2
16c: ebfffffe bl 0
return AVERROR(EINVAL);
170: e3e00015 mvn r0, #21
174: eafffff7 b 158
178: 00000008 .word 0x00000008
Disassembly of section .text.unlikely:
00000000 :
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 .
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
@ Read options from
-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这两个工具参数就不展开介绍了,网上资料很多。