3

I am using Android Studio 4.1.3 and its various bundled tools (AGP 4.1.3, Gradle 6.5, Android SDK Build Tools 31-rc2, Platform Tools 31.0.1, SDK Tools 26.1.1). I am using the default R8 tool.

I am obfuscating release builds like this:

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'
}

My Proguard-rules.pro file has this at the top:

# hide the original source file name.
-renamesourcefileattribute SourceFile

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

After the release build is created, here is an example stack trace - the first line shows that it obfuscated the class name (SplashActivity$a), renamed the source to 'SourceFile', and obfuscated the line number (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)

Using the retrace.bat tool (located in ~\SDK\tools\proguard\bin) with the appropriate mappings.txt file from the release build against that stack trace results in this output:

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)

Notice that the class names properly got de-obfuscated (SplashActivity$a became SplashActivity$1), but the line numbers did not get un-obfuscated (it still shows line 2 which is wrong). Interestingly, if I include this section in 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'
}

For debug builds, the stack trace output has the file name hidden (it shows as 'SourceFile'), the class name is obfuscated, but the line number is left alone:

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)

Why can I not get the original line number back after running retrace on the stack trace from the 'release' build? Why is the line number not being obfuscated in the 'debug' build?

tfrysinger
  • 1,306
  • 11
  • 26

2 Answers2

0

I have been having similar issues. It seems like R8 is not respecting -keepattributes LineNumberTable,SourceFile despite what Google is claiming in https://developer.android.com/studio/build/shrink-code#decode-stack-trace

I ended up using ProGuard instead by setting android.enableR8=false in gradle.properties.

The above solution won't work with Gradle 5 once it's out.

whyp
  • 603
  • 5
  • 14
  • Thanks - I tried this and got 1) deprecation warnings about using 'android.enableR8=false', 2) a failed build with 'class [META-INF/versions/9/module-info.class] unexpectedly contains class [module-info] warnings which produced an I/O exception, 3) tried to insert -ignorewarnings in my rules file which successfully built, but the resulting logs do have the line numbers but are no longer obfuscating the class names! – tfrysinger Apr 08 '21 at 15:08
  • See this SO Post: https://stackoverflow.com/questions/55609008/meta-inf-version-duplicate-error-when-using-proguard – tfrysinger Apr 08 '21 at 15:09
  • I realized that the classes I was looking at descend from Activity, so so are not obfuscated as a result of some internal Proguard rules. Looks like other classes and methods are getting obfuscated properly. – tfrysinger Apr 08 '21 at 15:24
0

The reason line numbers are not deobfuscated properly is that the version of ProGuard bundled with SDK Tools is outdated, and its retracer doesn't support line numbers optimizations. Source: https://issuetracker.google.com/issues/122752644#comment13

So you can download one of the last versions of ProGuard, and it will work correctly with line numbers. I checked it myself with 7.2.2 ProGuard version.

solru
  • 111
  • 1
  • 8