crash问题千奇百怪,涉及到厂商相关的代码咱们该怎么去剖析。

  • 怎么经过现有crash信息剖析测验复现crash?
  • 怎么快速获取到厂商crash相关代码?
  • 怎么经过反编译和trace手法快速剖析代码逻辑?
  • 怎么利用hook手法做crash维护?

下面经过一个事例和大家共享一下我这边的排查定位维护进程。

Crash排查系列第六篇|记一次厂商兼容问题处理

剖析处理

  1. 从crash大盘中找到该crash呈现频率较多的体系版别和设备型号。

  2. 从crash的url散布发现相关页top1页面,结合剖析东西路径咱们测验复现该仓库

  3. 复现仓库后不一定crash,可是咱们能够经过打印仓库dex location的办法找到代码所在磁盘方位并拉取代码。 线下class location获取办法

    1. 线下获取class dex location办法 ,这点有在widget内存优化文章也有提到。 找到gLogVerbosity这个大局特点后修正class_linker为true

Crash排查系列第六篇|记一次厂商兼容问题处理

Crash排查系列第六篇|记一次厂商兼容问题处理
线上class location获取办法

线上不适合打开调式日志,class_linker的调式日志仍是有点多的。 所以还要找个线上能获取到dex location的办法,毕竟不是每次都能够那么幸运的复现问题。观察了下mirror::class的GetLocation办法 ,其实运用java.lang.Class经过反射拿到dexCache再拿到location就能够。 这样的话线上呈现一些反常仓库咱们也能根据这个拿到代码保存,然后回捞剖析。

try {
Class a =Class.forName("vivo.contentcatcher.ViewAnalyzerFactory");
Field dexCahce = Class.class.getDeclaredField("dexCache");
dexCahce.setAccessible(true);
Object dexCacheInstance = dexCahce.get(a);
Method metaGetDeclaredField = Class.class.getDeclaredMethod("getDeclaredField", String.class);
Field location = (Field) metaGetDeclaredField.invoke(dexCacheInstance.getClass(), "location");
location.setAccessible(true);
Object o = location.get(dexCacheInstance);
Log.i("zzzzz",o.toString());
} catch (Throwable e) {
e.printStackTrace();
}
  1. 反编译代码 检查里面相关的文件 猜想功用,其实这边经过仓库包名也能猜到 往这个方向测试

  2. 长按 触发才智视觉识别功用复现 crash简直必现,而呈现页面常常要长按操作,这也是该页面简单呈现的原因。体系设置页面关闭才智视觉功用后不呈现。

  3. 提交日志,反应vivo,vivo这边确认问题后回复方案推送rom处理(vivo没有回复具体原因,猜想是h5游戏页面用的组件和才智视觉的提取图片功用一同触发的问题)

  4. crash还在一直在上涨,深夜甚至还呈现了告警,后来确认是因为清晨活动重置,玩这个游戏的用户在一个峰值。虽然这个crash不到万分之一的设备crash率,一方面不知道vivo具体推送的rom时刻,一方面玩游戏的闪退的体会的确不好受。为了提高用户体会仍是要想办法去处理这个问题。

  5. 一开始是想经过PLT Hook hook 这个apk文件的打开 直接回来-1。本地机器验证了的确能够,可是有个问题这个apk路径不是固定的,每个手机上都有或许不一样,并且hook的规模也或许稍大了些,所有的io或许都要过一下这个逻辑。

  6. 接下来经过class load的日志和克己的trace打点东西结合perfetto剖析代码逻辑

    1. 第一个图是1秒左右 主线程处理长按事件。
    2. 第二张图是binder线程去加载contentcatcher这个apk的代码和资源
    3. 第三张图的仓库就是导致crash的仓库。

Crash排查系列第六篇|记一次厂商兼容问题处理

Crash排查系列第六篇|记一次厂商兼容问题处理

Crash排查系列第六篇|记一次厂商兼容问题处理

  1. 剖析了contentcatcher的加载流程后,咱们就要想办法去打破这条链路。我这边是找了第二个进程作为突破口,这个进程代码不在contentcatcher.apk 经过class load日志能够发现在vivo的一个framwork jar下 ,相同的办法拉取代码剖析

    1. 发现一个hook点 能够直接修正CONTENT_CATCHER_ID 不去加载功用。直接经过反射修正。

Crash排查系列第六篇|记一次厂商兼容问题处理

Crash排查系列第六篇|记一次厂商兼容问题处理

  1. 一轮灰度后发现还有crash上报,持续剖析相关机型,发现新版别 framework有修正,无法经过修正CONTENT_CATCHER_ID处理,code判断的当地直接写死了。 从头找hook点。

    1. 反射修正sViewAnalyzerClzz让其找不到类。修正后发现是个hide 字段,所以这儿要用双反射绕过。

Crash排查系列第六篇|记一次厂商兼容问题处理

Crash排查系列第六篇|记一次厂商兼容问题处理

  1. 装备中心下发开关hook,crash下降。 待vivo rom推送掩盖后再打开开关。
  2. 厂商相关的问题多种多样,有许多是咱们线下无法复现的。上面举的仅仅最近一个问题剖析的例子,并且代码逻辑在咱们自己进程,咱们能够很便利的去获取代码剖析。还有许多状况代码逻辑是在体系的其他进程的,比如也是最近遇到的,这就需要去剖析相关机器system_server的代码了,hook办法也多种多样,咱们也需要从稳定性以及性能上适当选择。后面章节再和大家一同共享。