博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WebView兼容问题分析报告
阅读量:6268 次
发布时间:2019-06-22

本文共 3174 字,大约阅读时间需要 10 分钟。

【NE现场】

pid: 6715, tid: 6719, name: Signal Catcher >>> com.android.contacts <<

从调用栈来看,是SignalCacher线程在打印其他线程的调用栈时出现异常。

 

【问题分析】

先通过addr2line工具确定出问题的代码:

static intload_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local){  ...  f = fopen (file, "r");  if (!f)    return 1;  if (fread (&ehdr, sizeof (Elf_W (Ehdr)), 1, f) != 1)    goto file_error;  shstrndx = ehdr.e_shstrndx;  Debug (4, "opened file '%s'. Section header at offset %d\n",         file, (int) ehdr.e_shoff);  fseek (f, ehdr.e_shoff, SEEK_SET);  sec_hdrs = calloc (ehdr.e_shnum, sizeof (Elf_W (Shdr)));  if (sec_hdrs == NULL || fread (sec_hdrs, sizeof (Elf_W (Shdr)), ehdr.e_shnum, f) != ehdr.e_shnum)    goto file_error;  Debug (4, "loading string table of size %ld\n",       (long) sec_hdrs[shstrndx].sh_size);  size_t sec_size = sec_hdrs[shstrndx].sh_size;  <<<

看起来是shstrndx太大,数组访问越界导致的。而

shstrndx = ehdr.e_shstrndx

这个值是从elfheader中获取的,可能是elf文件格式有问题。

 

通过objdump反汇编,确定这里ehdr的地址是x27值,也就是0000007f951f3338

再通过tombstone,确定这个ehdr的值为:

memory near x27:    0000007f951f3318 0000007f8371b214 0000007f951f3bb0  ..q......;......    0000007f951f3328 0000007f95c31000 0000007f95c31000  ................    0000007f951f3338 0800000a04034b50 c1963a2100000000  PK..........!:..    0000007f951f3348 3b4e00013b4e66df 7361000d001d0001  .fN;..N;......as    0000007f951f3358 7268632f73746573 5f3030315f656d6f  sets/chrome_100_    0000007f951f3368 2e746e6563726570 350000cafe6b6170  percent.pak....5    0000007f951f3378 2190b2bd990eaa19 0000007f951f3470  .......!p4......

标准的elf文件,它的文件头是一个magic numbers = 7f 45 4c 46,如:

$ xxd symbols/system/bin/linker0000000: 7f45 4c46 0101 0100 0000 0000 0000 0000  .ELF............0000010: 0300 2800 0100 0000 5816 0000 3400 0000  ..(.....X...4...0000020: a430 1800 0000 0005 3400 2000 0a00 2800  .0......4. ...(.0000030: 2300 2000 0600 0000 3400 0000 3400 0000  #. .....4...4...0000040: 3400 0000 4001 0000 4001 0000 0400 0000  4...@...@.......

而上面的magic numbers是PK,这个是apk包的magic numbers。

当前被解析的时apk包,这个并不是一个elf文件,因此unwind解析时会出错。

下一步就需要找到这个elf文件。为此我们首先得找到正在被打印的目标线程。

 

我们可以在tombstone中搜索[vdso]就能找到这个正在被打印的线程,如:

pid: 6715, tid: 6762, name: Chrome_FileUser >>> com.android.contacts <<

这里的vdso是放信号处理函数的内存段:

...    0000007f'993ae000-0000007f'993aefff r-x         0      1000  [vdso]    0000007f'993af000-0000007f'993affff r--     32000      1000  /system/bin/linker64    0000007f'993b0000-0000007f'993b1fff rw-     33000      2000  /system/bin/linker64    ...

 

【打印目标线程调用栈过程】

1、给目标线程发送特殊的signal,触发目标线程的信号处理函数。

2、内核调用信号处理函数时,会将当前目标线程的CPU上下文以参数的形式传给信号处理函数。这样信号处理函数中,就能得到这个上下文。

3、得到这个上下文后,当前线程就将这个上下文传给Signal Catcher线程,然后自己进入wait状态。

4、Signal Catcher线程得到这个上下文后,就可以调用unwind库,来打印目标线程的调用栈,打印完在wake目标线程。

 

当前的NE就是第4个阶段,也就是Signal Cacher线程拿到目标线程上下文后,再调用unwind库解析目标线程的调用栈时出的问题。

从调用栈中可以清楚的看到,是调用栈中有WebViewGoogle.apk这个文件,和之前的推理吻合。

查看WebViewGoogle.apk的内容,也和前面解析的文件头内容相同。

 

【解决方案】

在unwind中,读取文件头后,先判断是否有elf的magic number即可,如:

if (fread (&ehdr, sizeof (Elf_W (Ehdr)), 1, f) != 1)    goto file_error;  /* Verify this is actually an elf file. */+ if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0)+   goto file_error;  shstrndx = ehdr.e_shstrndx;

 

aosp中也有相同change:

 

转载于:https://www.cnblogs.com/YYPapa/p/6848462.html

你可能感兴趣的文章
Hadoop1.2.1 全然分布式集群搭建实操笔记
查看>>
第三百二十七节,web爬虫讲解2—urllib库爬虫—基础使用—超时设置—自动模拟http请求...
查看>>
MVC总结--MVC简单介绍以及和WebForm差别
查看>>
tiny4412 裸机程序 五、控制icache【转】
查看>>
VB.NET多线程入门
查看>>
国外物联网平台初探(二) ——微软Azure IoT
查看>>
findlibrary returned null产生的联想,Android ndk开发打包时我们应该怎样注意平台的兼容(x86,arm,arm-v7a)...
查看>>
Android事件分发机制源代码分析
查看>>
《设计模式》结构型模式
查看>>
[javase学习笔记]-8.3 statickeyword使用的注意细节
查看>>
Spring集成RabbitMQ-使用RabbitMQ更方便
查看>>
Nginx 设置域名转向配置
查看>>
.net core 实现简单爬虫—抓取博客园的博文列表
查看>>
FP-Tree算法的实现
查看>>
Android 用Handler和Message实现计时效果及其中一些疑问
查看>>
Dos命令删除添加新服务
查看>>
C#.NET常见问题(FAQ)-索引器indexer有什么用
查看>>
hadoop YARN配置参数剖析—MapReduce相关参数
查看>>
Java 正则表达式详细使用
查看>>
【ADO.NET】SqlBulkCopy批量添加DataTable
查看>>