/*
* 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);
}
}
}