Force Proguard to give every method in a class a unique name?

android, obfuscation, proguard

Solution

The stack trace has become ambiguous because the line numbers are missing. You can preserve them with these ProGuard options:

-renamesourcefileattribute MyApplication
-keepattributes SourceFile,LineNumberTable

See the ProGuard manual > ReTrace > Usage.

See the ProGuard manual > Examples > Producing useful stack traces

Alternatively, you could assign unique names:

-useuniqueclassmembernames

However. method names can be overloaded to start with, and ProGuard doesn't change that.

Side-note: recent versions of the Android SDK automatically apply the default part of your configuration if you set up project.properties properly:

proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

Problem

I'm using Proguard to obfuscate an Android application. Everything works fine but I'm struggling to retrace stack traces from error reports. Here's an extract of my obfuscated code: ``` private ez a(x paramx) { return (ez)this.J.get(paramx); } private void a(com.b.a.f paramf) { Iterator localIterator = this.K.iterator(); while (true) { if (!localIterator.hasNext()) return; em localem = (em)localIterator.next(); if (localem.a((int)(this.i / this.m - 202.0F), (int)(202.0F + (this.i + this.n) / this.m), (int)(this.j / this.m - 202.0F), (int)(202.0F + (this.j + this.o) / this.m))) localem.a(paramf, this.m, this.i, this.j); } } private void a(com.b.a.f paramf, int paramInt1, int paramInt2, int paramInt3, int paramInt4) { Iterator localIterator = this.J.entrySet().iterator(); while (true) { if (!localIterator.hasNext()) return; ez localez = (ez)((Map.Entry)localIterator.next()).getValue(); if (localez.a(paramInt1, paramInt2, paramInt3, paramInt4)) localez.a(paramf, this.k, this.m, this.i, this.j); } } ``` You'll notice that all 3 methods above (taken from the same class) have the same name = 'a'. Of course this doesn't cause a problem when running because they have different parameters. However in my obfuscated stack trace: ``` java.lang.ArrayIndexOutOfBoundsException: length=0; index=0 at java.util.concurrent.CopyOnWriteArrayList.get(CopyOnWriteArrayList.java:117) at uk.co.ionage.ionage.co.a(Unknown Source) at uk.co.ionage.ionage.co.g(Unknown Source) at uk.co.ionage.ionage.n.b(Unknown Source) at uk.co.ionage.ionage.n.a(Unknown Source) at uk.co.ionage.ionage.co.a(Unknown Source) at uk.co.ionage.ionage.co.a(Unknown Source) at uk.co.ionage.ionage.Gameplay.a(Unknown Source) at uk.co.ionage.ionage.cn.run(Unknown Source) ``` This is a problem. I don't know which 'a' method it refers to. When I use retrace.bat it lists all methods with the name 'a'. Here is my proguard.config: ``` -optimizationpasses 5 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontpreverify -dontwarn android.support.** -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* -keep public class * extends android.app.Activity -keep public class * extends android.app.Application -keep public class * extends android.app.Service -keep public class * extends android.content.BroadcastReceiver -keep public class * extends android.content.ContentProvider -keep public class * extends android.app.backup.BackupAgentHelper -keep public class * extends android.preference.Preference -keep public class com.android.vending.licensing.ILicensingService -keepclasseswithmembernames class * { native <methods>; } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet); } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet, int); } -keepclassmembers class * extends android.app.Activity { public void *(android.view.View); } -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } ##---------------Begin: proguard configuration for Gson ---------- # Gson uses generic type information stored in a class file when working with #fields. Proguard removes such information by default, so configure it to keep #all of it. -keepattributes Signature # For using GSON @Expose annotation -keepattributes *Annotation* # Gson specific classes -keep class sun.misc.Unsafe { *; } #-keep class com.google.gson.stream.** { *; } # Application classes that will be serialized/deserialized over Gson -keep class com.gameanalytics.android.** { *; } ##---------------End: proguard configuration for Gson ---------- ``` It's very typical except I've added a bit at the end to help support my use of JSON/GSON. Can I add an option to force proguard to give every method a different name?

Original source