1418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file 2418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager// for details. All rights reserved. Use of this source code is governed by a 3418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager// BSD-style license that can be found in the LICENSE file. 4418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerpackage com.android.tools.r8; 5418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 6418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.dex.ApplicationReader; 7418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexApplication; 8418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexEncodedField; 9418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexEncodedMethod; 10418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexField; 11418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexMethod; 12418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexProgramClass; 13418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexType; 14418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.naming.ClassNameMapper; 15418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.naming.MemberNaming.FieldSignature; 16418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.naming.MemberNaming.MethodSignature; 17418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.utils.AndroidApp; 18418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.utils.AndroidApp.Builder; 19418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.utils.InternalOptions; 20418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.utils.ListUtils; 21418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.utils.Timing; 22418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.io.IOException; 23418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.nio.file.Paths; 24418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.Arrays; 25418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.List; 26418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.concurrent.ExecutionException; 27418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.concurrent.ExecutorService; 28418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.concurrent.Executors; 29418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 30418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerpublic class PrintClassList { 31418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 32418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager public static void main(String[] args) throws IOException, ExecutionException { 33418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager List<String> dexFiles = Arrays.asList(args); 34418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Builder builder = AndroidApp.builder(); 35418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (args[0].endsWith("map")) { 36418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager builder.setProguardMapFile(Paths.get(args[0])); 37418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager dexFiles = dexFiles.subList(1, dexFiles.size()); 38418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 398842c41758db478ebc54437f583367750cd18378Alan Leung builder.addProgramFiles(ListUtils.map(dexFiles, Paths::get), false); 40418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 41418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager ExecutorService executorService = Executors.newCachedThreadPool(); 42418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexApplication application = 43418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager new ApplicationReader(builder.build(), new InternalOptions(), new Timing("PrintClassList")) 44418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager .read(executorService); 45418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager ClassNameMapper map = application.getProguardMap(); 46418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (DexProgramClass clazz : application.classes()) { 47418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager System.out.print(maybeDeobfuscateType(map, clazz.type)); 48418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager System.out.println(); 49418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager printMethods(clazz.directMethods(), map); 50418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager printMethods(clazz.virtualMethods(), map); 51418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager printFields(clazz.staticFields(), map); 52418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager printFields(clazz.instanceFields(), map); 53418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 54418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager executorService.shutdown(); 55418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 56418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 57418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static void printMethods(DexEncodedMethod[] methods, ClassNameMapper map) { 58418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (DexEncodedMethod encodedMethod : methods) { 59418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexMethod method = encodedMethod.method; 60418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 61418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (map != null) { 62418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager System.out.println(map.originalNameOf(method)); 63418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } else { 64418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Detour via Signature to get the same formatting. 65418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager MethodSignature signature = MethodSignature.fromDexMethod(method); 66418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager System.out.println(method.holder.toSourceString() + " " + signature); 67418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 68418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 69418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 70418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 71418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static void printFields(DexEncodedField[] fields, ClassNameMapper map) { 72418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (DexEncodedField encodedField : fields) { 73418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexField field = encodedField.field; 74418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (map != null) { 75418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager System.out.println(map.originalNameOf(field)); 76418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } else { 77418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Detour via Signature to get the same formatting. 78418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager FieldSignature signature = new FieldSignature(field.name.toSourceString(), 79418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager field.type.toSourceString()); 80418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager System.out.println(field.clazz.toSourceString() + " " + signature); 81418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 82418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 83418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 84418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 85418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static String maybeDeobfuscateType(ClassNameMapper map, DexType type) { 86418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return map == null ? type.toSourceString() : map.originalNameOf(type); 87418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 88418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager} 89