/* * dex2jar - Tools to work with android .dex and java .class files * Copyright (c) 2009-2012 Panxiaobo * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.googlecode.dex2jar.tools; import com.googlecode.d2j.Method; import com.googlecode.d2j.dex.BaseDexExceptionHandler; import com.googlecode.d2j.dex.Dex2jar; import com.googlecode.d2j.node.DexMethodNode; import com.googlecode.d2j.reader.DexFileReader; import com.googlecode.d2j.smali.BaksmaliDumper; import com.googlecode.d2j.smali.Smali; import com.googlecode.dex2jar.ir.ET; import org.objectweb.asm.MethodVisitor; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.text.SimpleDateFormat; import java.util.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class BaksmaliBaseDexExceptionHandler extends BaseDexExceptionHandler { private Map<DexMethodNode, Exception> exceptionMap = new HashMap<>(); private List<Exception> fileExceptions = new ArrayList<>(); boolean hasException() { return exceptionMap.size() > 0 || fileExceptions.size() > 0; } @Override public void handleFileException(Exception e) { super.handleFileException(e); fileExceptions.add(e); } @Override public void handleMethodTranslateException(Method method, DexMethodNode methodNode, MethodVisitor mv, Exception e) { super.handleMethodTranslateException(method, methodNode, mv, e); exceptionMap.put(methodNode, e); } public static String getVersionString() { List<String> vs = new ArrayList<>(); doAddVersion(vs, "dex-reader", DexFileReader.class); doAddVersion(vs, "dex-reader-api", Method.class); doAddVersion(vs, "dex-ir", ET.class); doAddVersion(vs, "d2j-smali", Smali.class); doAddVersion(vs, "d2j-base-cmd", BaseCmd.class); doAddVersion(vs, "dex-tools", Dex2jarCmd.class); doAddVersion(vs, "dex-translator", Dex2jar.class); return vs.toString(); } private static void doAddVersion(List<String> vs, String pkg, Class<?> clz) { try { vs.add(pkg + "-" + clz.getPackage().getImplementationVersion()); } catch (Exception ignore) { // ignored } } public void dump(Path exFile, String[] orginalArgs) { try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(exFile))) { BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(zos, StandardCharsets.UTF_8)); // dump summary: timestamp, version, cmdline zos.putNextEntry(new ZipEntry("summary.txt")); if (fileExceptions.size() > 0) { writer.append(String.format("There are %d fails.", fileExceptions.size())); writer.newLine(); } if (exceptionMap.size() > 0) { writer.append(String.format("There are %d methods fail to translate.", exceptionMap.size())); writer.newLine(); } SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); writer.append(sdf.format(new Date())); writer.newLine(); writer.append("version: "); writer.append(getVersionString()); writer.newLine(); writer.append("cmdline: "); writer.append(Arrays.asList(orginalArgs).toString()); writer.newLine(); writer.append("env:"); writer.newLine(); Properties properties = System.getProperties(); for (String key : properties.stringPropertyNames()) { if (key.startsWith("java.") && !key.toLowerCase().contains("pass")) { writer.append(key).append(": ").append(properties.getProperty(key)); writer.newLine(); } } PrintWriter p = new PrintWriter(writer, true); for (Exception ex : fileExceptions) { ex.printStackTrace(p); } writer.flush(); zos.closeEntry(); // dump each method int i = 0; BaksmaliDumper baksmaliDumper = new BaksmaliDumper(); for (Map.Entry<DexMethodNode, Exception> e : exceptionMap.entrySet()) { zos.putNextEntry(new ZipEntry("m-" + i++ + ".txt")); writer.append(e.getKey().method.toString()); writer.newLine(); writer.flush(); e.getValue().printStackTrace(new PrintWriter(writer, true)); writer.newLine(); baksmaliDumper.baksmaliMethod(e.getKey(), writer); writer.flush(); zos.closeEntry(); } zos.setComment("This file is generated by dex2jar,\n Please report this file to http://code.google.com/p/dex2jar/issues/entry if possible."); zos.flush(); } catch (IOException e) { throw new RuntimeException(e); } } }