Proguard mapping文件的理解及Decode 堆栈信息

在Android应用发布时,通过Proguard混淆可以提高代码安全性。当出现错误堆栈信息时,由于混淆,定位问题变得困难。通过保留mapping文件,可以解析堆栈信息。例如,给定的堆栈信息中,通过mapping文件找到DashboardModel.java的buildLoadDataRequest方法在混淆后的位置。Proguard提供了retrace工具或GUI界面,帮助将混淆的堆栈信息转换为可读形式,便于调试。

低功耗蓝牙项目,需要一块懂省电的板

思澈 SF32LB52 芯片,BLE 协议栈深度优化,上手即开发

Release出去的产品如果出现了问题, 客户给了堆栈信息,由于我们的Android apk都是经过Proguard进行混淆过的, 那么如何才能还原当时的情景呢,至少我们应该知道是代码哪里出了错吧。。。

       首先,每个release版本出去,必须要保留当时的mapping文件,这对于事后追踪bug很有必要,比如我们的产品有这样的文件:attnav-mapping-5.5.3.2.8402166.txt, 每个release 版本都会有这样的文件。那么问题来了,如何看这些文件呢。

     比如, 客户报出了这样的堆栈信息:

    Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.os.Bundle.containsKey(java.lang.String)' on a null object reference
       at com.telenav.scout.module.dashboard.DashboardModel.buildLoadDataRequest(DashboardModel.java:25546)
       at com.telenav.scout.module.BaseFragmentActivityHelper$1.com.telenav.scout.module.BaseModel.baseDoInBackground(BaseFragmentActivityHelper.java:1156)
       at com.telenav.scout.module.BaseFragmentActivityHelper$1.loadInBackground(BaseFragmentActivityHelper.java:42)
       at android.support.v4.content.AsyncTaskLoader$LoadTask.android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:1296)
       at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground$42af7916(AsyncTaskLoader.java:42)
       at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:128)
       at java.util.concurrent.FutureTask.run(FutureTask.java:237)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
       at java.lang.Thread.run(Thread.java:818)

这个其实还是没怎么混淆过的代码,至少我们可以看出来是这个DashboardModel类出现了问题, 但是接下来又困惑了,DashboardModel.java:25546 貌似是这行抛出来的,可

是仔细去代码里查了,没有这一行?!。。。 这个时候我们需要看这个Mapping文件了

看原始类(部分代码):

 

mapping文件:


com.telenav.scout.module.dashboard.DashboardModel -> com.telenav.scout.module.dashboard.af:
    android.app.Activity ownActivity -> b
    long resumeTime -> c
    com.telenav.scout.module.common.search.CommonSearchModelHelper commonSearchModelHelper -> d
    94:97:void <init>(com.telenav.scout.module.IBaseFragment) -> <init>
    100:108:void onResume() -> d
    1062:1063:void com.telenav.core.media.TnAudioPlayer.setAudioSuspendDuringCall(boolean):62:63 -> d
    1062:1063:void onResume():103 -> d
    111:114:void onPause() -> e
    118:185:com.telenav.scout.module.ResponseStatus doInBackground(java.lang.String) -> c
    1283:1314:void buildFindMeRequest(com.telenav.scout.module.ResponseStatus,android.location.Location):283:314 -> c
    1283:1314:com.telenav.scout.module.ResponseStatus doInBackground(java.lang.String):141 -> c
    2030:2031:void com.telenav.foundation.vo.BaseServiceRequest.setContext(com.telenav.foundation.vo.ServiceContext):30:31 -> c
    2030:2031:void buildFindMeRequest(com.telenav.scout.module.ResponseStatus,android.location.Location):288 -> c
    2030:2031:com.telenav.scout.module.ResponseStatus doInBackground(java.lang.String):141 -> c
    2033:2034:void com.telenav.foundation.vo.LatLon.setLat(double):33:34 -> c

。。。。还有很多

 

注意看上面的数字:

94:97  94行到97行 构造函数 init

100:108  100行到108行 void onResume() -> d 方法onResume被混淆成了d

1062:1063:void com.telenav.core.media.TnAudioPlayer.setAudioSuspendDuringCall(boolean):62:63 -> d

这一行有点困惑了 别急

看这里 62到63行 setAudioSuspendDuringCall方法

1062:1063:void onResume():103 -> d  OnResume 103行里调用的setAudioSuspendDuringCall 被混淆成d

1283:1314:void buildFindMeRequest(com.telenav.scout.module.ResponseStatus,android.location.Location):283:314 -> c

注意 buildFindMeRequest进去283到314行是这个方法体,被混淆成c

以下同理

 

终于在这里面找到堆栈里的那个抛异常的那个方法了

25541:25555:void buildLoadDataRequest():541:555 -> c

DashboardModel.java:25546 不出意外,在541行到555行里找,546行就是抛异常的那个地方了。

结果是的。

 

另外,这只是简单的不怎么混淆的类和方法,对于那种根本看不出什么类什么方法的,我们该怎么办呢,比如

Caused by: java.lang.NullPointerException
at net.simplyadvanced.ltediscovery.be.u(Unknown Source)
at net.simplyadvanced.ltediscovery.at.v(Unknown Source)
at net.simplyadvanced.ltediscovery.at.d(Unknown Source)
at net.simplyadvanced.ltediscovery.av.onReceive(Unknown Source)

 

类似这样的,我们可以用proguard提供给我们的强大工具:

1.当混淆后的代码输出一个堆栈信息时,方法名是不可识别的,这使得调试变得很困难,甚至是不可能的。

幸运的是,当ProGuard运行时,它都会输出一个<project_root>/bin/proguard/mapping.txt文件,而这个文件中包含了原始的类,方法和字段名被映射成的混淆名字。


retrace.bat脚本(Window)或retrace.sh脚本(Linux,Mac OS X)可以将一个被混淆过的堆栈跟踪信息还原成一个可读的信息。它位于<sdk_root>/tools/proguard文件夹中。执行retrace工具的语法如下:

retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]

例如:

retrace.bat -verbose mapping.txt obfuscated_trace.txt

如果你没有指定<stacktrace_file>,retrace工具会从标准输入读取。

当然 你也可以使用工具 在tools/proguard/bin/ 下面 运行proguardGUI.bat 会运行一个GUI页面,操作方式很简单的 就选择这三个红款里面的东西就可以了。

 

当然,最好是理解下proguard的原理以及使用。

可参考:http://m.blog.csdn.net/blog/xiaoli519/49330995

 

低功耗蓝牙项目,需要一块懂省电的板

思澈 SF32LB52 芯片,BLE 协议栈深度优化,上手即开发

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值