kotlin混淆后mapping定位

Posted 涂程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kotlin混淆后mapping定位相关的知识,希望对你有一定的参考价值。

作者:玉刚说

这个文章聊下kotlin的mapping文件的定位,以具体一个线上崩溃为例

线上崩溃日志

Caused by: java.lang.IndexOutOfBoundsException: toIndex = 10
at java.util.AbstractList.subListRangeCheck(AbstractList.java:507)
at java.util.ArrayList$SubList.subList(ArrayList.java:1238)
at b.a.a.a.p.y1.i(SearchRecordFragment.kt:12)
at b.a.a.a.p.f0.run(lambda:6)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:264)
at android.app.ActivityThread.main(ActivityThread.java:8306)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:632)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1049)

通过上面的崩溃日志,可以发现具体崩溃的代码是这里

at java.util.ArrayList$SubList.subList(ArrayList.java:1238)
at b.a.a.a.p.y1.i(SearchRecordFragment.kt:12)

这里b.a.a.a.p.y1代表某个类,最后的i代表的是一个方法,或者变量,这里实际是一个方法,因为有前后调用堆栈,这里调用到sublist方法导致的崩溃,最后的kt:12代表的是混淆后的行数是12行

解析mapping,定位具体代码

接下来,我们打开mapping文件,搜索b.a.a.a.p.y1这个字符串,结果如下

找到对应的类下的mapping信息,接下来就是找i,可以发现这个类里面有很多i的声明,比如下面这几种,都不是我们要找的i

// 这个i是一个Lzay类型的变量
kotlin.Lazy lateSearchRecordAdapter$delegate -> i
// 前面的3:4的行数不对,我们要找的是12
3:4:void com.ygp.mro.app.search.adapter.SearchRecordAdapter.setShowExpandView(boolean):50:51 -> i

继续找,找到了最终匹配的位置,如下

    11:11:java.util.List com.ygp.mro.app.search.adapter.SearchRecordAdapter.getData():22:22 -> i
    11:11:void initListShowExpand():185 -> i
    12:13:void initListShowExpand():185:186 -> i
    14:14:void com.ygp.mro.app.search.adapter.SearchRecordAdapter.setData(java.util.List):0:0 -> i
    14:14:void initListShowExpand():186 -> i

上面的中间那行,就是我们要的结果12:13:void initListShowExpand():185:186 -> i,混淆后的12:13对应的真实的行数是185:186,所以实际崩溃的就是185行

看下对应的源码

源码这里也有调用到sublist方法,跟崩溃调用的方法一致,于是确定是这里导致的崩溃了

进一步验证

通过源码跟mapping,都可以发现,崩溃的方法是initListShowExpand,那这个方法又是哪里调用的呢?我们通过查看,有两个地方调用到

具体崩溃的时候,是哪里调用的,再看下崩溃的log

at b.a.a.a.p.y1.i(SearchRecordFragment.kt:12)
at b.a.a.a.p.f0.run(lambda:6)
at android.os.Handler.handleCallback(Handler.java:938)

是这里的b.a.a.a.p.f0的run方法,而run方法又是handler回调的,继续去mapping文件搜索b.a.a.a.p.f0

找到了很多run的调用,而方法后面有这个lambda:6,我们找对应的6这个地方,找到了

6:6:void com.ygp.mro.app.search.SearchRecordFragment$initListener$2.onGlobalLayout$lambda-1(com.ygp.mro.app.search.SearchRecordFragment):151:151 -> run
    6:6:void com.ygp.mro.app.search.SearchRecordFragment$initListener$2.lambda$EpImLmOa5i7W3KU8Q9jIBuQ78Gk(com.ygp.mro.app.search.SearchRecordFragment):0 -> run
    6:6:void run():0 -> run

对应的是源码的151行,查看源码,找到了调用的代码了

所以结果是151行调用initListShowExpand方法,然后在方法内部的185行发生了崩溃

以上是关于kotlin混淆后mapping定位的主要内容,如果未能解决你的问题,请参考以下文章

全网首发:ScrollBarUI混淆后效果错误的分析

android查看混淆代码后apk跑出来的日志记录

如何混淆我用 kotlin 编码的 sdk(并摆脱元数据)

Android Kotlin ProGuard 规则错误?

Map定位

kotlin-----集合list、map和set