Merge branch 'wip-2.0' of git://github.com/brutall/brut.apktool into brutall-wip-2.0

This commit is contained in:
Connor Tumbleson
2013-05-02 12:56:46 -05:00
8 changed files with 141 additions and 68 deletions

View File

@ -27,6 +27,10 @@ import org.jf.dexlib.Code.Analysis.RegisterType;
*/
public class DebugInjector {
private boolean areParamsInjected;
private int currParam;
private int lastParam;
public static void inject(ListIterator<String> it, StringBuilder out)
throws AndrolibException {
new DebugInjector(it, out).inject();
@ -44,7 +48,7 @@ public class DebugInjector {
nextAndAppend();
return;
}
injectParameters(definition);
parseParamsNumber(definition);
boolean end = false;
while (!end) {
@ -52,24 +56,28 @@ public class DebugInjector {
}
}
private void injectParameters(String definition) throws AndrolibException {
int pos = definition.indexOf('(');
if (pos == -1) {
throw new AndrolibException();
}
int pos2 = definition.indexOf(')', pos);
if (pos2 == -1) {
throw new AndrolibException();
}
String params = definition.substring(pos + 1, pos2);
private void parseParamsNumber(String definition) throws AndrolibException {
int pos = definition.indexOf('(');
if (pos == -1) {
throw new AndrolibException();
}
int pos2 = definition.indexOf(')', pos);
if (pos2 == -1) {
throw new AndrolibException();
}
String params = definition.substring(pos + 1, pos2);
int i = definition.contains(" static ") ? 0 : 1;
int argc = TypeName.listFromInternalName(params).size() + i;
while (i < argc) {
mOut.append(".parameter \"p").append(i).append("\"\n");
i++;
}
}
currParam = definition.contains(" static ") ? 0 : 1;
lastParam = TypeName.listFromInternalName(params).size() + currParam - 1;
}
private void injectRemainingParams() {
areParamsInjected = true;
while(currParam <= lastParam) {
mOut.append(".parameter \"p").append(currParam).append("\"\n");
currParam++;
}
}
private boolean step() {
String line = next();
@ -86,6 +94,9 @@ public class DebugInjector {
case '.':
return processDirective(line);
default:
if (! areParamsInjected) {
injectRemainingParams();
}
return processInstruction(line);
}
}
@ -158,11 +169,19 @@ public class DebugInjector {
private boolean processDirective(String line) {
String line2 = line.substring(1);
if (line2.startsWith("line ") || line2.equals("prologue")
|| line2.startsWith("parameter") || line2.startsWith("local ")
|| line2.startsWith("end local ")) {
return false;
}
if (line2.startsWith("line ") || line2.startsWith("local ") || line2.startsWith("end local ")) {
return false;
}
if (line2.equals("prologue")) {
if (! areParamsInjected) {
injectRemainingParams();
}
return false;
}
if (line2.equals("parameter")) {
mOut.append(".parameter \"p").append(currParam++).append("\"\n");
return false;
}
append(line);
if (line2.equals("end method")) {
@ -193,7 +212,7 @@ public class DebugInjector {
}
private String next() {
return mIt.next().trim();
return mIt.next().split("//", 2)[1].trim();
}
private String nextAndAppend() {

View File

@ -74,19 +74,18 @@ public class SmaliBuilder {
StringBuilder out = new StringBuilder();
List<String> lines = IOUtils.readLines(inStream);
if (!mFlags.containsKey("debug")) {
if (!mFlags.get("debug")) {
final String[] linesArray = lines.toArray(new String[0]);
for (int i = 2; i < linesArray.length - 2; i++) {
out.append(linesArray[i]).append('\n');
for (int i = 1; i < linesArray.length - 1; i++) {
out.append(linesArray[i].split("//", 2)[1]).append('\n');
}
} else {
lines.remove(lines.size() - 1);
lines.remove(lines.size() - 1);
ListIterator<String> it = lines.listIterator(2);
ListIterator<String> it = lines.listIterator(1);
out.append(".source \"").append(inFile.getName()).append("\"\n");
while (it.hasNext()) {
String line = it.next().trim();
String line = it.next().split("//", 2)[1].trim();
if (line.isEmpty() || line.charAt(0) == '#'
|| line.startsWith(".source")) {
continue;

View File

@ -17,10 +17,20 @@
package brut.androlib.src;
import brut.androlib.AndrolibException;
import org.jf.baksmali.baksmali;
import org.jf.dexlib.Code.Analysis.ClassPath;
import org.jf.dexlib.DexFile;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import org.jf.baksmali.baksmali;
import org.jf.dexlib.DexFile;
import java.nio.charset.Charset;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
@ -35,24 +45,62 @@ public class SmaliDecoder {
private SmaliDecoder(File apkFile, File outDir, boolean debug,
boolean bakdeb) {
mApkFile = apkFile;
mOutDir = outDir;
mOutDir = outDir.toPath();
mDebug = debug;
mBakDeb = bakdeb;
}
private void decode() throws AndrolibException {
try {
ClassPath.dontLoadClassPath = mDebug;
baksmali.disassembleDexFile(mApkFile.getAbsolutePath(),
new DexFile(mApkFile), false, mOutDir.getAbsolutePath(),
new DexFile(mApkFile), false, mOutDir.toAbsolutePath().toString(),
null, null, null, false, true, true, mBakDeb, false, false,
0, false, false, null, false);
mDebug ? org.jf.baksmali.main.DIFFPRE : 0, false, false, null, false);
if (mDebug) {
Files.walkFileTree(mOutDir, new SmaliFileVisitor());
}
} catch (IOException ex) {
throw new AndrolibException(ex);
}
}
private final File mApkFile;
private final File mOutDir;
private final Path mOutDir;
private final boolean mDebug;
private final boolean mBakDeb;
private class SmaliFileVisitor extends SimpleFileVisitor<Path> {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String fileName = file.getFileName().toString();
if (! fileName.endsWith(".smali")) {
return FileVisitResult.CONTINUE;
}
fileName = fileName.substring(0, fileName.length() - 6);
try (
BufferedReader in = Files.newBufferedReader(file, Charset.defaultCharset());
BufferedWriter out = Files.newBufferedWriter(
file.resolveSibling(fileName + ".java"), Charset.defaultCharset())
) {
TypeName type = TypeName.fromPath(mOutDir.relativize(file.resolveSibling(fileName)));
out.write("package " + type.package_ + "; class " + type.getName(true, true) + " { void a() { int a;");
out.newLine();
String line;
while ((line = in.readLine()) != null) {
out.write(";// ");
out.write(line);
out.newLine();
}
out.write("}}");
out.newLine();
}
Files.delete(file);
return FileVisitResult.CONTINUE;
}
}
}

View File

@ -18,8 +18,12 @@ package brut.androlib.src;
import brut.androlib.AndrolibException;
import brut.util.Duo;
import com.google.common.base.Joiner;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
@ -120,6 +124,27 @@ public class TypeName {
return types;
}
public static TypeName fromPath(Path path) {
List<String> parts = new ArrayList<>(path.getNameCount());
for (Path p : path) {
parts.add(p.toString());
}
return fromNameParts(parts, 0);
}
public static TypeName fromNameParts(List<String> parts, int array) {
String type = parts.get(parts.size() - 1);
parts = parts.subList(0, parts.size() - 1);
String innerType = null;
int pos = type.indexOf('$');
if (pos != -1) {
innerType = type.substring(pos + 1);
type = type.substring(0, pos);
}
return new TypeName(Joiner.on('.').join(parts), type, innerType, array);
}
public static Duo<TypeName, Integer> fetchFromInternalName(String internal)
throws AndrolibException {
String origInternal = internal;
@ -139,9 +164,7 @@ public class TypeName {
} while (isArray);
int length = array + 1;
String package_ = null;
String type = null;
String innerType = null;
String type;
switch (internal.charAt(0)) {
case 'B':
type = "byte";
@ -176,31 +199,13 @@ public class TypeName {
throw new AndrolibException("Invalid internal name: "
+ origInternal);
}
length += pos;
internal = internal.substring(1, pos);
pos = internal.lastIndexOf('/');
if (pos == -1) {
package_ = "";
type = internal;
} else {
package_ = internal.substring(0, pos).replace('/', '.');
type = internal.substring(pos + 1);
}
pos = type.indexOf('$');
if (pos != -1) {
innerType = type.substring(pos + 1);
type = type.substring(0, pos);
}
break;
return new Duo<>(fromNameParts(Arrays.asList(internal.substring(1, pos).split("/")), array), length + pos);
default:
throw new AndrolibException("Invalid internal name: "
+ origInternal);
}
return new Duo<TypeName, Integer>(new TypeName(package_, type,
innerType, array), length);
return new Duo<>(new TypeName(null, type, null, array), length);
}
private Boolean mIsFileOwner;