Merge "Add support for proguard deobfuscation."
diff --git a/tools/ahat/Android.mk b/tools/ahat/Android.mk
index ebf087d..27c2054 100644
--- a/tools/ahat/Android.mk
+++ b/tools/ahat/Android.mk
@@ -55,11 +55,23 @@
include $(BUILD_HOST_JAVA_LIBRARY)
AHAT_TEST_JAR := $(LOCAL_BUILT_MODULE)
+# Rule to generate the proguard configuration for the test-dump program.
+# We copy the configuration to the intermediates directory because jack will
+# output the proguard map in that same directory.
+AHAT_TEST_DUMP_PROGUARD_CONFIG := $(intermediates.COMMON)/config.pro
+AHAT_TEST_DUMP_PROGUARD_MAP := $(intermediates.COMMON)/proguard.map
+$(AHAT_TEST_DUMP_PROGUARD_CONFIG): PRIVATE_AHAT_PROGUARD_CONFIG_IN := $(LOCAL_PATH)/test-dump/config.pro
+$(AHAT_TEST_DUMP_PROGUARD_CONFIG): PRIVATE_AHAT_PROGUARD_CONFIG := $(AHAT_TEST_DUMP_PROGUARD_CONFIG)
+$(AHAT_TEST_DUMP_PROGUARD_CONFIG): $(LOCAL_PATH)/test-dump/config.pro
+ cp $(PRIVATE_AHAT_PROGUARD_CONFIG_IN) $(PRIVATE_AHAT_PROGUARD_CONFIG)
+
# --- ahat-test-dump.jar --------------
include $(CLEAR_VARS)
LOCAL_MODULE := ahat-test-dump
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under, test-dump)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(AHAT_TEST_DUMP_PROGUARD_CONFIG)
+LOCAL_JACK_FLAGS := --config-proguard $(AHAT_TEST_DUMP_PROGUARD_CONFIG)
include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
# Determine the location of the test-dump.jar and test-dump.hprof files.
@@ -84,12 +96,15 @@
.PHONY: ahat-test
ahat-test: PRIVATE_AHAT_TEST_DUMP_HPROF := $(AHAT_TEST_DUMP_HPROF)
ahat-test: PRIVATE_AHAT_TEST_JAR := $(AHAT_TEST_JAR)
+ahat-test: PRIVATE_AHAT_PROGUARD_MAP := $(AHAT_TEST_DUMP_PROGUARD_MAP)
ahat-test: $(AHAT_TEST_JAR) $(AHAT_TEST_DUMP_HPROF)
- java -Dahat.test.dump.hprof=$(PRIVATE_AHAT_TEST_DUMP_HPROF) -jar $(PRIVATE_AHAT_TEST_JAR)
+ java -Dahat.test.dump.hprof=$(PRIVATE_AHAT_TEST_DUMP_HPROF) -Dahat.test.dump.map=$(PRIVATE_AHAT_PROGUARD_MAP) -jar $(PRIVATE_AHAT_TEST_JAR)
# Clean up local variables.
AHAT_TEST_DUMP_DEPENDENCIES :=
AHAT_TEST_DUMP_HPROF :=
AHAT_TEST_DUMP_JAR :=
+AHAT_TEST_DUMP_PROGUARD_CONFIG :=
+AHAT_TEST_DUMP_PROGUARD_MAP :=
AHAT_TEST_JAR :=
diff --git a/tools/ahat/README.txt b/tools/ahat/README.txt
index dbc1102..8dfb4ab 100644
--- a/tools/ahat/README.txt
+++ b/tools/ahat/README.txt
@@ -1,12 +1,14 @@
AHAT - Android Heap Analysis Tool
Usage:
- java -jar ahat.jar [-p port] FILE
+ java -jar ahat.jar [-p port] [--proguard-map FILE] FILE
Launch an http server for viewing the given Android heap-dump FILE.
Options:
-p <port>
Serve pages on the given port. Defaults to 7100.
+ --proguard-map FILE
+ Use the proguard map FILE to deobfuscate the heap dump.
TODO:
* Have a way to diff two heap dumps.
@@ -84,7 +86,7 @@
Target Java 1.7.
0.6 Jun 21, 2016
- Add support for proguard deobfuscation (pending AOSP push of perflib)
+ Add support for proguard deobfuscation.
0.5 Apr 19, 2016
Update perflib to perflib-25.0.0 to improve processing performance.
diff --git a/tools/ahat/src/AhatSnapshot.java b/tools/ahat/src/AhatSnapshot.java
index a8205c7..ba8243f 100644
--- a/tools/ahat/src/AhatSnapshot.java
+++ b/tools/ahat/src/AhatSnapshot.java
@@ -20,6 +20,7 @@
import com.android.tools.perflib.heap.ClassObj;
import com.android.tools.perflib.heap.Heap;
import com.android.tools.perflib.heap.Instance;
+import com.android.tools.perflib.heap.ProguardMap;
import com.android.tools.perflib.heap.RootObj;
import com.android.tools.perflib.heap.RootType;
import com.android.tools.perflib.heap.Snapshot;
@@ -71,8 +72,8 @@
/**
* Create an AhatSnapshot from an hprof file.
*/
- public static AhatSnapshot fromHprof(File hprof) throws IOException {
- Snapshot snapshot = Snapshot.createSnapshot(new MemoryMappedFileBuffer(hprof));
+ public static AhatSnapshot fromHprof(File hprof, ProguardMap map) throws IOException {
+ Snapshot snapshot = Snapshot.createSnapshot(new MemoryMappedFileBuffer(hprof), map);
snapshot.computeDominators();
return new AhatSnapshot(snapshot);
}
diff --git a/tools/ahat/src/Main.java b/tools/ahat/src/Main.java
index fdc5a86..c79b578 100644
--- a/tools/ahat/src/Main.java
+++ b/tools/ahat/src/Main.java
@@ -16,24 +16,28 @@
package com.android.ahat;
+import com.android.tools.perflib.heap.ProguardMap;
import com.sun.net.httpserver.HttpServer;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
+import java.text.ParseException;
import java.util.concurrent.Executors;
public class Main {
public static void help(PrintStream out) {
- out.println("java -jar ahat.jar [-p port] FILE");
+ out.println("java -jar ahat.jar [-p port] [--proguard-map FILE] FILE");
out.println(" Launch an http server for viewing "
+ "the given Android heap-dump FILE.");
out.println("");
out.println("Options:");
out.println(" -p <port>");
out.println(" Serve pages on the given port. Defaults to 7100.");
+ out.println(" --proguard-map FILE");
+ out.println(" Use the proguard map FILE to deobfuscate the heap dump.");
out.println("");
}
@@ -47,10 +51,19 @@
}
File hprof = null;
+ ProguardMap map = new ProguardMap();
for (int i = 0; i < args.length; i++) {
if ("-p".equals(args[i]) && i + 1 < args.length) {
i++;
port = Integer.parseInt(args[i]);
+ } else if ("--proguard-map".equals(args[i]) && i + 1 < args.length) {
+ i++;
+ try {
+ map.readFromFile(new File(args[i]));
+ } catch (IOException|ParseException ex) {
+ System.out.println("Unable to read proguard map: " + ex);
+ System.out.println("The proguard map will not be used.");
+ }
} else {
if (hprof != null) {
System.err.println("multiple input files.");
@@ -74,7 +87,7 @@
HttpServer server = HttpServer.create(addr, 0);
System.out.println("Processing hprof file...");
- AhatSnapshot ahat = AhatSnapshot.fromHprof(hprof);
+ AhatSnapshot ahat = AhatSnapshot.fromHprof(hprof, map);
server.createContext("/", new AhatHttpHandler(new OverviewHandler(ahat, hprof)));
server.createContext("/rooted", new AhatHttpHandler(new RootedHandler(ahat)));
server.createContext("/object", new AhatHttpHandler(new ObjectHandler(ahat)));
diff --git a/tools/ahat/test-dump/config.pro b/tools/ahat/test-dump/config.pro
new file mode 100644
index 0000000..0cf7a87
--- /dev/null
+++ b/tools/ahat/test-dump/config.pro
@@ -0,0 +1,15 @@
+# The goal of this proguard configuration is to obfuscate the test-dump
+# program so that the heap dump it generates is an obfuscated heap dump.
+# This allows us to test that deobfuscation of the generated heap dump is
+# working properly.
+
+# All we care about is obfuscation. Don't do any other optimizations.
+-dontpreverify
+-dontoptimize
+-dontshrink
+
+-keep public class Main {
+ public static void main(java.lang.String[]);
+}
+
+-printmapping proguard.map
diff --git a/tools/ahat/test/TestDump.java b/tools/ahat/test/TestDump.java
index c3a76e4..ebce61c 100644
--- a/tools/ahat/test/TestDump.java
+++ b/tools/ahat/test/TestDump.java
@@ -19,8 +19,10 @@
import com.android.tools.perflib.heap.ClassObj;
import com.android.tools.perflib.heap.Field;
import com.android.tools.perflib.heap.Instance;
+import com.android.tools.perflib.heap.ProguardMap;
import java.io.File;
import java.io.IOException;
+import java.text.ParseException;
import java.util.Map;
/**
@@ -44,11 +46,21 @@
* For example:
* java -Dahat.test.dump.hprof=test-dump.hprof -jar ahat-tests.jar
*
- * An IOException is thrown if there is a failure reading the hprof file.
+ * An IOException is thrown if there is a failure reading the hprof file or
+ * the proguard map.
*/
private TestDump() throws IOException {
String hprof = System.getProperty("ahat.test.dump.hprof");
- mSnapshot = AhatSnapshot.fromHprof(new File(hprof));
+
+ String mapfile = System.getProperty("ahat.test.dump.map");
+ ProguardMap map = new ProguardMap();
+ try {
+ map.readFromFile(new File(mapfile));
+ } catch (ParseException e) {
+ throw new IOException("Unable to load proguard map", e);
+ }
+
+ mSnapshot = AhatSnapshot.fromHprof(new File(hprof), map);
}
/**