baksmali.java revision 68564258a316e41cb014f98d2777b5944bf37de3
17faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez/* 27faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * [The "BSD licence"] 37faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Copyright (c) 2010 Ben Gruver (JesusFreke) 47faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * All rights reserved. 57faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 67faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Redistribution and use in source and binary forms, with or without 77faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * modification, are permitted provided that the following conditions 87faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * are met: 97faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 1. Redistributions of source code must retain the above copyright 107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * notice, this list of conditions and the following disclaimer. 117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 2. Redistributions in binary form must reproduce the above copyright 127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * notice, this list of conditions and the following disclaimer in the 137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * documentation and/or other materials provided with the distribution. 147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 3. The name of the author may not be used to endorse or promote products 157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * derived from this software without specific prior written permission. 167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezpackage org.jf.baksmali; 307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport com.google.common.collect.ImmutableList; 327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport com.google.common.collect.Iterables; 337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport com.google.common.collect.Lists; 347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport com.google.common.collect.Ordering; 357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport org.jf.baksmali.Adaptors.ClassDefinition; 367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport org.jf.dexlib2.analysis.ClassPath; 377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport org.jf.dexlib2.iface.ClassDef; 387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport org.jf.dexlib2.iface.DexFile; 397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport org.jf.dexlib2.util.SyntheticAccessorResolver; 407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport org.jf.util.ClassFileNameHandler; 417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport org.jf.util.IndentingWriter; 427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport org.xml.sax.Attributes; 437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport org.xml.sax.SAXException; 447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport org.xml.sax.helpers.DefaultHandler; 457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport java.io.*; 477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport java.util.List; 487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport java.util.Map.Entry; 497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport java.util.concurrent.*; 507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport javax.xml.parsers.SAXParser; 527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport javax.xml.parsers.SAXParserFactory; 537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezimport javax.xml.parsers.ParserConfigurationException; 547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezpublic class baksmali { 567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez public static boolean disassembleDexFile(DexFile dexFile, final baksmaliOptions options) { 587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (options.registerInfo != 0 || options.deodex) { 597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez try { 607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez Iterable<String> extraClassPathEntries; 617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (options.extraClassPathEntries != null) { 627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez extraClassPathEntries = options.extraClassPathEntries; 637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } else { 647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez extraClassPathEntries = ImmutableList.of(); 657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez options.classPath = ClassPath.fromClassPath(options.bootClassPathDirs, 687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez Iterables.concat(options.bootClassPathEntries, extraClassPathEntries), dexFile, 697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez options.apiLevel); 707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } catch (Exception ex) { 717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez System.err.println("\n\nError occurred while loading boot class path files. Aborting."); 727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez ex.printStackTrace(System.err); 737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return false; 747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (options.resourceIdFileEntries != null) { 787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez class PublicHandler extends DefaultHandler { 797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez String prefix = null; 807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez public PublicHandler(String prefix) { 817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez super(); 827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez this.prefix = prefix; 837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez public void startElement(String uri, String localName, 867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez String qName, Attributes attr) throws SAXException { 877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (qName.equals("public")) { 887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez String type = attr.getValue("type"); 897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez String name = attr.getValue("name").replace('.', '_'); 907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez Integer public_key = Integer.decode(attr.getValue("id")); 917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez String public_val = new StringBuffer() 927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez .append(prefix) 937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez .append(".") 947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez .append(type) 957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez .append(".") 967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez .append(name) 977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez .toString(); 987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez options.resourceIds.put(public_key, public_val); 997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez }; 1027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (Entry<String,String> entry: options.resourceIdFileEntries.entrySet()) { 1047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez try { 1057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez SAXParser saxp = SAXParserFactory.newInstance().newSAXParser(); 1067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez String prefix = entry.getValue(); 1077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez saxp.parse(entry.getKey(), new PublicHandler(prefix)); 1087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } catch (ParserConfigurationException e) { 1097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez continue; 1107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } catch (SAXException e) { 1117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez continue; 1127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } catch (IOException e) { 1137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez continue; 1147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez File outputDirectoryFile = new File(options.outputDirectory); 1197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (!outputDirectoryFile.exists()) { 1207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (!outputDirectoryFile.mkdirs()) { 1217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez System.err.println("Can't create the output directory " + options.outputDirectory); 1227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return false; 1237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //sort the classes, so that if we're on a case-insensitive file system and need to handle classes with file 1277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //name collisions, then we'll use the same name for each class, if the dex file goes through multiple 1287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //baksmali/smali cycles for some reason. If a class with a colliding name is added or removed, the filenames 1297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //may still change of course 1307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez List<? extends ClassDef> classDefs = Ordering.natural().sortedCopy(dexFile.getClasses()); 1317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (!options.noAccessorComments) { 1337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez options.syntheticAccessorResolver = new SyntheticAccessorResolver(classDefs); 1347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez final ClassFileNameHandler fileNameHandler = new ClassFileNameHandler(outputDirectoryFile, ".smali"); 1377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez ExecutorService executor = Executors.newFixedThreadPool(options.jobs); 1397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez List<Future<Boolean>> tasks = Lists.newArrayList(); 1407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (final ClassDef classDef: classDefs) { 1427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez tasks.add(executor.submit(new Callable<Boolean>() { 1437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez @Override public Boolean call() throws Exception { 1447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return disassembleClass(classDef, fileNameHandler, options); 1457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez })); 1477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez boolean errorOccurred = false; 1507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (Future<Boolean> task: tasks) { 1517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez while(true) { 1527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez try { 1537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (!task.get()) { 1547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez errorOccurred = true; 1557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } catch (InterruptedException ex) { 1577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez continue; 1587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } catch (ExecutionException ex) { 1597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez throw new RuntimeException(ex); 1607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez break; 1627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez executor.shutdown(); 1667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return !errorOccurred; 1677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez private static boolean disassembleClass(ClassDef classDef, ClassFileNameHandler fileNameHandler, 1707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez baksmaliOptions options) { 1717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez /** 1727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * The path for the disassembly file is based on the package name 1737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * The class descriptor will look something like: 1747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Ljava/lang/Object; 1757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Where the there is leading 'L' and a trailing ';', and the parts of the 1767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * package name are separated by '/' 1777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 1787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez String classDescriptor = classDef.getType(); 1797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //validate that the descriptor is formatted like we expect 1817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (classDescriptor.charAt(0) != 'L' || 1827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez classDescriptor.charAt(classDescriptor.length()-1) != ';') { 1837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez System.err.println("Unrecognized class descriptor - " + classDescriptor + " - skipping class"); 1847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return false; 1857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez File smaliFile = fileNameHandler.getUniqueFilenameForClass(classDescriptor); 1887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //create and initialize the top level string template 1907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez ClassDefinition classDefinition = new ClassDefinition(options, classDef); 1917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //write the disassembly 1937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez Writer writer = null; 1947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez try 1957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 1967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez File smaliParent = smaliFile.getParentFile(); 1977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (!smaliParent.exists()) { 1987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (!smaliParent.mkdirs()) { 1997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // check again, it's likely it was created in a different thread 2007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (!smaliParent.exists()) { 2017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez System.err.println("Unable to create directory " + smaliParent.toString() + " - skipping class"); 2027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return false; 2037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 2047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 2057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 2067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 2077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (!smaliFile.exists()){ 2087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (!smaliFile.createNewFile()) { 2097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez System.err.println("Unable to create file " + smaliFile.toString() + " - skipping class"); 2107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return false; 2117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 2127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 2137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 2147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez BufferedWriter bufWriter = new BufferedWriter(new OutputStreamWriter( 2157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez new FileOutputStream(smaliFile), "UTF8")); 2167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 2177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez writer = new IndentingWriter(bufWriter); 2187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez classDefinition.writeTo((IndentingWriter)writer); 2197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } catch (Exception ex) { 2207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez System.err.println("\n\nError occurred while disassembling class " + classDescriptor.replace('/', '.') + " - skipping class"); 2217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez ex.printStackTrace(); 2227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // noinspection ResultOfMethodCallIgnored 2237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez smaliFile.delete(); 2247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return false; 2257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 2267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez finally 2277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 2287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (writer != null) { 2297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez try { 2307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez writer.close(); 2317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } catch (Throwable ex) { 2327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez System.err.println("\n\nError occurred while closing file " + smaliFile.toString()); 2337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez ex.printStackTrace(); 2347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 2357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 2367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 2377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return true; 2387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 2397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} 2407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez