mirror of
https://github.com/revanced/Apktool.git
synced 2025-04-30 22:24:25 +02:00
DebugInjector: types recognition using dexlib code analyzer.
This commit is contained in:
parent
d459a4bb8b
commit
e6d2e9c605
@ -17,7 +17,10 @@
|
|||||||
package brut.androlib.src;
|
package brut.androlib.src;
|
||||||
|
|
||||||
import brut.androlib.AndrolibException;
|
import brut.androlib.AndrolibException;
|
||||||
import java.util.ListIterator;
|
import java.util.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import org.jf.dexlib.Code.Analysis.RegisterType;
|
||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,7 +79,7 @@ public class DebugInjector {
|
|||||||
|
|
||||||
switch (line.charAt(0)) {
|
switch (line.charAt(0)) {
|
||||||
case '#':
|
case '#':
|
||||||
return false;
|
return processComment(line);
|
||||||
case ':':
|
case ':':
|
||||||
append(line);
|
append(line);
|
||||||
return false;
|
return false;
|
||||||
@ -87,6 +90,72 @@ public class DebugInjector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean processComment(String line) {
|
||||||
|
if (mFirstInstruction) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher m = REGISTER_INFO_PATTERN.matcher(line);
|
||||||
|
|
||||||
|
while (m.find()) {
|
||||||
|
String localName = m.group(1);
|
||||||
|
String localType = null;
|
||||||
|
switch (RegisterType.Category.valueOf(m.group(2))) {
|
||||||
|
case Reference:
|
||||||
|
case Null:
|
||||||
|
case UninitRef:
|
||||||
|
case UninitThis:
|
||||||
|
localType = "Ljava/lang/Object;";
|
||||||
|
break;
|
||||||
|
case Boolean:
|
||||||
|
localType = "Z";
|
||||||
|
break;
|
||||||
|
case Integer:
|
||||||
|
case One:
|
||||||
|
case Unknown:
|
||||||
|
localType = "I";
|
||||||
|
break;
|
||||||
|
case Uninit:
|
||||||
|
case Conflicted:
|
||||||
|
if (mInitializedRegisters.remove(localName)) {
|
||||||
|
mOut.append(".end local ").append(localName)
|
||||||
|
.append('\n');
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case Short:
|
||||||
|
case PosShort:
|
||||||
|
localType = "S";
|
||||||
|
break;
|
||||||
|
case Byte:
|
||||||
|
case PosByte:
|
||||||
|
localType = "B";
|
||||||
|
break;
|
||||||
|
case Char:
|
||||||
|
localType = "C";
|
||||||
|
break;
|
||||||
|
case Float:
|
||||||
|
localType = "F";
|
||||||
|
break;
|
||||||
|
case LongHi:
|
||||||
|
case LongLo:
|
||||||
|
localType = "J";
|
||||||
|
break;
|
||||||
|
case DoubleHi:
|
||||||
|
case DoubleLo:
|
||||||
|
localType = "D";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mInitializedRegisters.add(localName);
|
||||||
|
mOut.append(".local ").append(localName).append(", ")
|
||||||
|
.append(localName).append(':').append(localType).append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean processDirective(String line) {
|
private boolean processDirective(String line) {
|
||||||
String line2 = line.substring(1);
|
String line2 = line.substring(1);
|
||||||
if (
|
if (
|
||||||
@ -126,84 +195,9 @@ public class DebugInjector {
|
|||||||
mOut.append(".line ").append(mIt.nextIndex()).append('\n')
|
mOut.append(".line ").append(mIt.nextIndex()).append('\n')
|
||||||
.append(line).append('\n');
|
.append(line).append('\n');
|
||||||
|
|
||||||
int pos = line.indexOf(' ');
|
|
||||||
if (pos == -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Opcode opcode = Opcode.getOpcodeByName(line.substring(0, pos));
|
|
||||||
if (! opcode.setsRegister()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pos2 = line.indexOf(',', pos);
|
|
||||||
String register = pos2 == -1 ? line.substring(pos + 1) :
|
|
||||||
line.substring(pos + 1, pos2);
|
|
||||||
|
|
||||||
mOut.append(".local ").append(register).append(", ").append(register)
|
|
||||||
.append(':').append(getRegisterTypeForOpcode(opcode)).append('\n');
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRegisterTypeForOpcode(Opcode opcode) {
|
|
||||||
switch (opcode.value) {
|
|
||||||
case (byte)0x0d: // ?
|
|
||||||
case (byte)0x1a:
|
|
||||||
case (byte)0x1b:
|
|
||||||
case (byte)0x1c: // ?
|
|
||||||
case (byte)0x22:
|
|
||||||
case (byte)0x23: // ?
|
|
||||||
case (byte)0xf4: // ?
|
|
||||||
return "Ljava/lang/Object;";
|
|
||||||
case (byte)0x1f: // ?
|
|
||||||
case (byte)0x20: // ?
|
|
||||||
return "Z";
|
|
||||||
case (byte)0x21: // ?
|
|
||||||
return "I";
|
|
||||||
}
|
|
||||||
|
|
||||||
String name = opcode.name;
|
|
||||||
int pos = name.lastIndexOf('-');
|
|
||||||
if (pos != -1) {
|
|
||||||
int pos2 = name.indexOf('/');
|
|
||||||
String type = pos2 == -1 ? name.substring(pos + 1) :
|
|
||||||
name.substring(pos + 1, pos2);
|
|
||||||
|
|
||||||
if (type.equals("object")) {
|
|
||||||
return "Ljava/lang/Object;";
|
|
||||||
}
|
|
||||||
if (type.equals("int")) {
|
|
||||||
return "I";
|
|
||||||
}
|
|
||||||
if (type.equals("boolean")) {
|
|
||||||
return "Z";
|
|
||||||
}
|
|
||||||
if (type.equals("float")) {
|
|
||||||
return "F";
|
|
||||||
}
|
|
||||||
if (type.equals("double")) {
|
|
||||||
return "D";
|
|
||||||
}
|
|
||||||
if (type.equals("long")) {
|
|
||||||
return "J";
|
|
||||||
}
|
|
||||||
if (type.equals("byte")) {
|
|
||||||
return "B";
|
|
||||||
}
|
|
||||||
if (type.equals("char")) {
|
|
||||||
return "C";
|
|
||||||
}
|
|
||||||
if (type.equals("short")) {
|
|
||||||
return "S";
|
|
||||||
}
|
|
||||||
if (type.equals("long")) {
|
|
||||||
return "J";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "I";
|
|
||||||
}
|
|
||||||
|
|
||||||
private String next() {
|
private String next() {
|
||||||
return mIt.next().trim();
|
return mIt.next().trim();
|
||||||
}
|
}
|
||||||
@ -222,4 +216,8 @@ public class DebugInjector {
|
|||||||
private final StringBuilder mOut;
|
private final StringBuilder mOut;
|
||||||
|
|
||||||
private boolean mFirstInstruction = true;
|
private boolean mFirstInstruction = true;
|
||||||
|
private final Set<String> mInitializedRegisters = new HashSet<String>();
|
||||||
|
|
||||||
|
private static final Pattern REGISTER_INFO_PATTERN =
|
||||||
|
Pattern.compile("((?:p|v)\\d+)=\\(([^)]+)\\);");
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import java.io.*;
|
|||||||
import org.jf.baksmali.Adaptors.ClassDefinition;
|
import org.jf.baksmali.Adaptors.ClassDefinition;
|
||||||
import org.jf.baksmali.baksmali;
|
import org.jf.baksmali.baksmali;
|
||||||
import org.jf.dexlib.ClassDefItem;
|
import org.jf.dexlib.ClassDefItem;
|
||||||
|
import org.jf.dexlib.Code.Analysis.ClassPath;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,6 +45,10 @@ public class SmaliDecoder {
|
|||||||
try {
|
try {
|
||||||
baksmali.useLocalsDirective = true;
|
baksmali.useLocalsDirective = true;
|
||||||
baksmali.useSequentialLabels = true;
|
baksmali.useSequentialLabels = true;
|
||||||
|
if (mDebug) {
|
||||||
|
baksmali.registerInfo = org.jf.baksmali.main.DIFFPRE;
|
||||||
|
ClassPath.dontLoadClassPath = true;
|
||||||
|
}
|
||||||
|
|
||||||
DexFile dexFile = new DexFile(mApkFile);
|
DexFile dexFile = new DexFile(mApkFile);
|
||||||
for (ClassDefItem classDefItem :
|
for (ClassDefItem classDefItem :
|
||||||
|
Loading…
x
Reference in New Issue
Block a user