【问题标题】:How can I get correct line numbers using retrace after R8 obfuscation?如何在 R8 混淆后使用回溯获取正确的行号?
【发布时间】:2021-04-08 12:56:37
【问题描述】:

我正在使用 Android Studio 4.1.3 及其各种捆绑工具(AGP 4.1.3、Gradle 6.5、Android SDK Build Tools 31-rc2、Platform Tools 31.0.1、SDK Tools 26.1.1)。我使用的是默认的 R8 工具。

我正在混淆这样的发布版本:

release {
   // Enables code shrinking, obfuscation, and optimization for only
   // your project's release build type.
   minifyEnabled true

   // Enables resource shrinking, which is performed by the
   // Android Gradle plugin.
   shrinkResources false

   // Includes the default ProGuard rules files that are packaged with
   // the Android Gradle plugin. To learn more, go to the section about
   // R8 configuration files.
   proguardFiles getDefaultProguardFile(
           'proguard-android.txt'),
           'proguard-rules.pro'
}

我的 Proguard-rules.pro 文件在顶部有这个:

# hide the original source file name.
-renamesourcefileattribute SourceFile

-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

在创建发布版本后,这里是一个示例堆栈跟踪 - 第一行显示它混淆了类名 (SplashActivity$a),将源重命名为“SourceFile”,并混淆了行号 (2):

at com.reddragon.intouch.ui.SplashActivity$a.onStart(SourceFile:2)
at io.reactivex.rxjava3.observers.DisposableObserver.onSubscribe(SourceFile:2)
at io.reactivex.rxjava3.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.onSubscribe(SourceFile:15)
at io.reactivex.rxjava3.internal.operators.observable.ObservableSubscribeOn.subscribeActual(SourceFile:2)
at io.reactivex.rxjava3.core.Observable.subscribe(SourceFile:12)
at io.reactivex.rxjava3.internal.operators.observable.ObservableObserveOn.subscribeActual(SourceFile:4)
at io.reactivex.rxjava3.core.Observable.subscribe(SourceFile:12)
at io.reactivex.rxjava3.core.Observable.subscribeWith(SourceFile:1)
at com.reddragon.intouch.ui.SplashActivity.onCreate(SourceFile:16)
at android.app.Activity.performCreate(Activity.java:7183)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1220)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2910)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

使用 retrace.bat 工具(位于 ~\SDK\tools\proguard\bin)和发布版本中的相应 mappings.txt 文件针对该堆栈跟踪会产生以下输出:

at com.reddragon.intouch.ui.SplashActivity$1.void onStart()(SourceFile:2)
at io.reactivex.rxjava3.observers.DisposableObserver.void onSubscribe(io.reactivex.rxjava3.disposables.Disposable)(SourceFile:2)
at io.reactivex.rxjava3.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.void onSubscribe(io.reactivex.rxjava3.disposables.Disposable)(SourceFile:15)
at io.reactivex.rxjava3.internal.operators.observable.ObservableSubscribeOn.void subscribeActual(io.reactivex.rxjava3.core.Observer)(SourceFile:2)
at io.reactivex.rxjava3.core.Observable.void subscribe(io.reactivex.rxjava3.core.Observer)(SourceFile:12)
at io.reactivex.rxjava3.internal.operators.observable.ObservableObserveOn.void subscribeActual(io.reactivex.rxjava3.core.Observer)(SourceFile:4)
at io.reactivex.rxjava3.core.Observable.void subscribe(io.reactivex.rxjava3.core.Observer)(SourceFile:12)
at io.reactivex.rxjava3.core.Observable.io.reactivex.rxjava3.core.Observer subscribeWith(io.reactivex.rxjava3.core.Observer)(SourceFile:1)
at com.reddragon.intouch.ui.SplashActivity.void onCreate(android.os.Bundle)(SourceFile:16)
at android.app.Activity.performCreate(Activity.java:7183)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1220)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2910)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

请注意,类名被正确地去混淆了(SplashActivity$a 变成了 SplashActivity$1),但是行号没有被去混淆(它仍然显示第 2 行是错误的)。有趣的是,如果我将此部分包含在 build.gradle 中:

debug {
  debuggable true
  minifyEnabled true

  // Enables resource shrinking, which is performed by the
  // Android Gradle plugin.
  shrinkResources false

  // Includes the default ProGuard rules files that are packaged with
  // the Android Gradle plugin. To learn more, go to the section about
  // R8 configuration files.
  proguardFiles getDefaultProguardFile(
          'proguard-android.txt'),
          'proguard-rules.pro'
}

对于调试版本,堆栈跟踪输出隐藏了文件名(显示为“SourceFile”),类名被混淆,但行号被单独保留:

at com.reddragon.intouch.ui.SplashActivity$a.onStart(SourceFile:313)
at io.reactivex.rxjava3.observers.DisposableObserver.onSubscribe(SourceFile:74)
at io.reactivex.rxjava3.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.onSubscribe(SourceFile:106)
at io.reactivex.rxjava3.internal.operators.observable.ObservableSubscribeOn.subscribeActual(SourceFile:34)
at io.reactivex.rxjava3.core.Observable.subscribe(SourceFile:13095)
at io.reactivex.rxjava3.internal.operators.observable.ObservableObserveOn.subscribeActual(SourceFile:45)
at io.reactivex.rxjava3.core.Observable.subscribe(SourceFile:13095)
at io.reactivex.rxjava3.core.Observable.subscribeWith(SourceFile:13148)
at com.reddragon.intouch.ui.SplashActivity.onCreate(SourceFile:309)
at android.app.Activity.performCreate(Activity.java:7183)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1220)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2910)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

为什么在“发布”版本的堆栈跟踪上运行回溯后无法取回原始行号?为什么在“调试”版本中没有混淆行号?

【问题讨论】:

    标签: android deobfuscation line-numbers android-r8


    【解决方案1】:

    我也遇到过类似的问题。尽管 Google 在 https://developer.android.com/studio/build/shrink-code#decode-stack-trace 中声称,R8 似乎不尊重 -keepattributes LineNumberTable,SourceFile

    我最终通过在gradle.properties 中设置android.enableR8=false 来使用ProGuard。

    上述解决方案一旦推出,将不适用于 Gradle 5。

    【讨论】:

    • 谢谢 - 我试过这个并得到 1) 关于使用 'android.enableR8=false' 的弃用警告,2) 使用 'class [META-INF/versions/9/module-info. class] 意外包含产生 I/O 异常的类 [module-info] 警告,3) 尝试在我成功构建的规则文件中插入 -ignorewarnings,但生成的日志确实有行号,但不再混淆类名字!
    • 我意识到我正在查看的类来自 Activity,因此不会因为某些内部 Proguard 规则而被混淆。看起来其他类和方法正在被正确地混淆。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 1970-01-01
    • 2020-10-05
    • 1970-01-01
    • 2019-01-22
    • 1970-01-01
    相关资源
    最近更新 更多