mirror of
https://github.com/revanced/smali.git
synced 2025-05-21 08:27:05 +02:00
Add support for generating register information
This commit is contained in:
parent
8887625162
commit
c91b03ba45
@ -33,8 +33,12 @@ import org.jf.baksmali.Adaptors.Debug.DebugMethodItem;
|
||||
import org.jf.baksmali.Adaptors.Format.InstructionMethodItemFactory;
|
||||
import org.jf.baksmali.baksmali;
|
||||
import org.jf.dexlib2.AccessFlags;
|
||||
import org.jf.dexlib2.Format;
|
||||
import org.jf.dexlib2.Opcode;
|
||||
import org.jf.dexlib2.ReferenceType;
|
||||
import org.jf.dexlib2.analysis.AnalysisException;
|
||||
import org.jf.dexlib2.analysis.AnalyzedInstruction;
|
||||
import org.jf.dexlib2.analysis.MethodAnalyzer;
|
||||
import org.jf.dexlib2.iface.*;
|
||||
import org.jf.dexlib2.iface.debug.DebugItem;
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
@ -73,7 +77,6 @@ public class MethodDefinition {
|
||||
this.method = method;
|
||||
this.methodImpl = methodImpl;
|
||||
|
||||
|
||||
try {
|
||||
//TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh.
|
||||
|
||||
@ -265,8 +268,11 @@ public class MethodDefinition {
|
||||
private List<MethodItem> getMethodItems() {
|
||||
ArrayList<MethodItem> methodItems = new ArrayList<MethodItem>();
|
||||
|
||||
//TODO: addAnalyzedInstructionMethodItems
|
||||
addInstructionMethodItems(methodItems);
|
||||
if ((baksmali.registerInfo != 0) || (baksmali.deodex && needsAnalyzed())) {
|
||||
addAnalyzedInstructionMethodItems(methodItems);
|
||||
} else {
|
||||
addInstructionMethodItems(methodItems);
|
||||
}
|
||||
|
||||
addTries(methodItems);
|
||||
if (baksmali.outputDebugInfo) {
|
||||
@ -286,6 +292,15 @@ public class MethodDefinition {
|
||||
return methodItems;
|
||||
}
|
||||
|
||||
private boolean needsAnalyzed() {
|
||||
for (Instruction instruction: methodImpl.getInstructions()) {
|
||||
if (instruction.getOpcode().odexOnly()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addInstructionMethodItems(List<MethodItem> methodItems) {
|
||||
int currentCodeAddress = 0;
|
||||
for (int i=0; i<instructions.size(); i++) {
|
||||
@ -338,43 +353,31 @@ public class MethodDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: uncomment
|
||||
/*private void addAnalyzedInstructionMethodItems(List<MethodItem> methodItems) {
|
||||
methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex, baksmali.inlineResolver);
|
||||
private void addAnalyzedInstructionMethodItems(List<MethodItem> methodItems) {
|
||||
MethodAnalyzer methodAnalyzer = new MethodAnalyzer(baksmali.classPath, method, baksmali.inlineResolver);
|
||||
|
||||
methodAnalyzer.analyze();
|
||||
|
||||
ValidationException validationException = methodAnalyzer.getValidationException();
|
||||
if (validationException != null) {
|
||||
AnalysisException analysisException = methodAnalyzer.getAnalysisException();
|
||||
if (analysisException != null) {
|
||||
methodItems.add(new CommentMethodItem(
|
||||
String.format("ValidationException: %s" ,validationException.getMessage()),
|
||||
validationException.getCodeAddress(), Integer.MIN_VALUE));
|
||||
} else if (baksmali.verify) {
|
||||
methodAnalyzer.verify();
|
||||
|
||||
validationException = methodAnalyzer.getValidationException();
|
||||
if (validationException != null) {
|
||||
methodItems.add(new CommentMethodItem(
|
||||
String.format("ValidationException: %s" ,validationException.getMessage()),
|
||||
validationException.getCodeAddress(), Integer.MIN_VALUE));
|
||||
}
|
||||
String.format("AnalysisException: %s" ,analysisException.getMessage()),
|
||||
analysisException.codeAddress, Integer.MIN_VALUE));
|
||||
}
|
||||
|
||||
List<AnalyzedInstruction> instructions = methodAnalyzer.getInstructions();
|
||||
List<AnalyzedInstruction> instructions = methodAnalyzer.getAnalyzedInstructions();
|
||||
|
||||
int currentCodeAddress = 0;
|
||||
for (int i=0; i<instructions.size(); i++) {
|
||||
AnalyzedInstruction instruction = instructions.get(i);
|
||||
|
||||
MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this,
|
||||
encodedMethod.codeItem, currentCodeAddress, instruction.getInstruction());
|
||||
MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(
|
||||
this, currentCodeAddress, instruction.getInstruction());
|
||||
|
||||
methodItems.add(methodItem);
|
||||
|
||||
if (instruction.getInstruction().getFormat() == Format.UnresolvedOdexInstruction) {
|
||||
if (instruction.getInstruction().getOpcode().format == Format.UnresolvedOdexInstruction) {
|
||||
methodItems.add(new CommentedOutMethodItem(
|
||||
InstructionMethodItemFactory.makeInstructionFormatMethodItem(this,
|
||||
encodedMethod.codeItem, currentCodeAddress, instruction.getOriginalInstruction())));
|
||||
InstructionMethodItemFactory.makeInstructionFormatMethodItem(
|
||||
this, currentCodeAddress, instruction.getOriginalInstruction())));
|
||||
}
|
||||
|
||||
if (i != instructions.size() - 1) {
|
||||
@ -392,23 +395,24 @@ public class MethodDefinition {
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write("#@");
|
||||
writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFF);
|
||||
writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFFL);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (baksmali.registerInfo != 0 && !instruction.getInstruction().getFormat().variableSizeFormat) {
|
||||
if (baksmali.registerInfo != 0 && !instruction.getInstruction().getOpcode().format.isPayloadFormat) {
|
||||
methodItems.add(
|
||||
new PreInstructionRegisterInfoMethodItem(instruction, methodAnalyzer, currentCodeAddress));
|
||||
new PreInstructionRegisterInfoMethodItem(
|
||||
methodAnalyzer, registerFormatter, instruction, currentCodeAddress));
|
||||
|
||||
methodItems.add(
|
||||
new PostInstructionRegisterInfoMethodItem(instruction, methodAnalyzer, currentCodeAddress));
|
||||
new PostInstructionRegisterInfoMethodItem(registerFormatter, instruction, currentCodeAddress));
|
||||
}
|
||||
|
||||
currentCodeAddress += instruction.getInstruction().getSize(currentCodeAddress);
|
||||
currentCodeAddress += instruction.getInstruction().getCodeUnits();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
private void addTries(List<MethodItem> methodItems) {
|
||||
List<? extends TryBlock> tryBlocks = methodImpl.getTryBlocks();
|
||||
|
@ -28,16 +28,26 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
//TODO: uncomment
|
||||
/*public class PostInstructionRegisterInfoMethodItem extends MethodItem {
|
||||
private final AnalyzedInstruction analyzedInstruction;
|
||||
private final MethodAnalyzer methodAnalyzer;
|
||||
import org.jf.baksmali.baksmali;
|
||||
import org.jf.baksmali.main;
|
||||
import org.jf.dexlib2.analysis.AnalyzedInstruction;
|
||||
import org.jf.dexlib2.analysis.RegisterType;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
public PostInstructionRegisterInfoMethodItem(AnalyzedInstruction analyzedInstruction, MethodAnalyzer methodAnalyzer,
|
||||
int codeAddress) {
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.util.BitSet;
|
||||
|
||||
public class PostInstructionRegisterInfoMethodItem extends MethodItem {
|
||||
@Nonnull private final RegisterFormatter registerFormatter;
|
||||
@Nonnull private final AnalyzedInstruction analyzedInstruction;
|
||||
|
||||
public PostInstructionRegisterInfoMethodItem(@Nonnull RegisterFormatter registerFormatter,
|
||||
@Nonnull AnalyzedInstruction analyzedInstruction,
|
||||
int codeAddress) {
|
||||
super(codeAddress);
|
||||
this.registerFormatter = registerFormatter;
|
||||
this.analyzedInstruction = analyzedInstruction;
|
||||
this.methodAnalyzer = methodAnalyzer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -74,8 +84,6 @@ package org.jf.baksmali.Adaptors;
|
||||
}
|
||||
|
||||
private boolean writeRegisterInfo(IndentingWriter writer, BitSet registers) throws IOException {
|
||||
ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod();
|
||||
|
||||
int registerNum = registers.nextSetBit(0);
|
||||
if (registerNum < 0) {
|
||||
return false;
|
||||
@ -83,19 +91,13 @@ package org.jf.baksmali.Adaptors;
|
||||
|
||||
writer.write('#');
|
||||
for (; registerNum >= 0; registerNum = registers.nextSetBit(registerNum + 1)) {
|
||||
|
||||
RegisterType registerType = analyzedInstruction.getPostInstructionRegisterType(registerNum);
|
||||
|
||||
RegisterFormatter.writeTo(writer, encodedMethod.codeItem, registerNum);
|
||||
registerFormatter.writeTo(writer, registerNum);
|
||||
writer.write('=');
|
||||
|
||||
if (registerType == null) {
|
||||
writer.write("null");
|
||||
} else {
|
||||
registerType.writeTo(writer);
|
||||
}
|
||||
registerType.writeTo(writer);
|
||||
writer.write(';');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
@ -28,16 +28,31 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
//TODO: uncomment
|
||||
/*public class PreInstructionRegisterInfoMethodItem extends MethodItem {
|
||||
private final AnalyzedInstruction analyzedInstruction;
|
||||
private final MethodAnalyzer methodAnalyzer;
|
||||
import org.jf.baksmali.baksmali;
|
||||
import org.jf.baksmali.main;
|
||||
import org.jf.dexlib2.analysis.AnalyzedInstruction;
|
||||
import org.jf.dexlib2.analysis.MethodAnalyzer;
|
||||
import org.jf.dexlib2.analysis.RegisterType;
|
||||
import org.jf.dexlib2.iface.instruction.*;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
public PreInstructionRegisterInfoMethodItem(AnalyzedInstruction analyzedInstruction, MethodAnalyzer methodAnalyzer,
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.util.BitSet;
|
||||
|
||||
public class PreInstructionRegisterInfoMethodItem extends MethodItem {
|
||||
@Nonnull private final MethodAnalyzer methodAnalyzer;
|
||||
@Nonnull private final RegisterFormatter registerFormatter;
|
||||
@Nonnull private final AnalyzedInstruction analyzedInstruction;
|
||||
|
||||
public PreInstructionRegisterInfoMethodItem(@Nonnull MethodAnalyzer methodAnalyzer,
|
||||
@Nonnull RegisterFormatter registerFormatter,
|
||||
@Nonnull AnalyzedInstruction analyzedInstruction,
|
||||
int codeAddress) {
|
||||
super(codeAddress);
|
||||
this.analyzedInstruction = analyzedInstruction;
|
||||
this.methodAnalyzer = methodAnalyzer;
|
||||
this.registerFormatter = registerFormatter;
|
||||
this.analyzedInstruction = analyzedInstruction;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -84,25 +99,25 @@ package org.jf.baksmali.Adaptors;
|
||||
RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.getInstruction();
|
||||
|
||||
registers.set(instruction.getStartRegister(),
|
||||
instruction.getStartRegister() + instruction.getRegCount());
|
||||
instruction.getStartRegister() + instruction.getRegisterCount());
|
||||
} else if (analyzedInstruction.getInstruction() instanceof FiveRegisterInstruction) {
|
||||
FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
int regCount = instruction.getRegCount();
|
||||
int regCount = instruction.getRegisterCount();
|
||||
switch (regCount) {
|
||||
case 5:
|
||||
registers.set(instruction.getRegisterA());
|
||||
//fall through
|
||||
case 4:
|
||||
registers.set(instruction.getRegisterG());
|
||||
//fall through
|
||||
case 3:
|
||||
case 4:
|
||||
registers.set(instruction.getRegisterF());
|
||||
//fall through
|
||||
case 2:
|
||||
case 3:
|
||||
registers.set(instruction.getRegisterE());
|
||||
//fall through
|
||||
case 1:
|
||||
case 2:
|
||||
registers.set(instruction.getRegisterD());
|
||||
//fall through
|
||||
case 1:
|
||||
registers.set(instruction.getRegisterC());
|
||||
}
|
||||
} else if (analyzedInstruction.getInstruction() instanceof ThreeRegisterInstruction) {
|
||||
ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
@ -113,8 +128,8 @@ package org.jf.baksmali.Adaptors;
|
||||
TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
registers.set(instruction.getRegisterA());
|
||||
registers.set(instruction.getRegisterB());
|
||||
} else if (analyzedInstruction.getInstruction() instanceof SingleRegisterInstruction) {
|
||||
SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
} else if (analyzedInstruction.getInstruction() instanceof OneRegisterInstruction) {
|
||||
OneRegisterInstruction instruction = (OneRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
registers.set(instruction.getRegisterA());
|
||||
}
|
||||
}
|
||||
@ -137,19 +152,13 @@ package org.jf.baksmali.Adaptors;
|
||||
for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) {
|
||||
if (predecessor.getPostInstructionRegisterType(registerNum) != mergedRegisterType) {
|
||||
registers.set(registerNum);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addParamRegs(BitSet registers, int registerCount) {
|
||||
ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod();
|
||||
int parameterRegisterCount = encodedMethod.method.getPrototype().getParameterRegisterCount();
|
||||
if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) {
|
||||
parameterRegisterCount++;
|
||||
}
|
||||
|
||||
int parameterRegisterCount = methodAnalyzer.getParamRegisterCount();
|
||||
registers.set(registerCount-parameterRegisterCount, registerCount);
|
||||
}
|
||||
|
||||
@ -159,8 +168,6 @@ package org.jf.baksmali.Adaptors;
|
||||
return false;
|
||||
}
|
||||
|
||||
ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod();
|
||||
|
||||
boolean firstRegister = true;
|
||||
|
||||
for (int registerNum=0; registerNum<registerCount; registerNum++) {
|
||||
@ -169,7 +176,7 @@ package org.jf.baksmali.Adaptors;
|
||||
|
||||
for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) {
|
||||
RegisterType predecessorRegisterType = predecessor.getPostInstructionRegisterType(registerNum);
|
||||
if (predecessorRegisterType.category != RegisterType.Category.Unknown &&
|
||||
if (predecessorRegisterType.category != RegisterType.UNKNOWN &&
|
||||
predecessorRegisterType != mergedRegisterType) {
|
||||
|
||||
addRegister = true;
|
||||
@ -188,7 +195,7 @@ package org.jf.baksmali.Adaptors;
|
||||
}
|
||||
|
||||
writer.write('#');
|
||||
RegisterFormatter.writeTo(writer, encodedMethod.codeItem, registerNum);
|
||||
registerFormatter.writeTo(writer, registerNum);
|
||||
writer.write('=');
|
||||
analyzedInstruction.getPreInstructionRegisterType(registerNum).writeTo(writer);
|
||||
writer.write(":merge{");
|
||||
@ -221,10 +228,7 @@ package org.jf.baksmali.Adaptors;
|
||||
return !firstRegister;
|
||||
}
|
||||
|
||||
private boolean writeRegisterInfo(IndentingWriter writer, BitSet registers,
|
||||
boolean addNewline) throws IOException {
|
||||
ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod();
|
||||
|
||||
private boolean writeRegisterInfo(IndentingWriter writer, BitSet registers, boolean addNewline) throws IOException {
|
||||
int registerNum = registers.nextSetBit(0);
|
||||
if (registerNum < 0) {
|
||||
return false;
|
||||
@ -233,21 +237,18 @@ package org.jf.baksmali.Adaptors;
|
||||
if (addNewline) {
|
||||
writer.write('\n');
|
||||
}
|
||||
|
||||
writer.write('#');
|
||||
for (; registerNum >= 0; registerNum = registers.nextSetBit(registerNum + 1)) {
|
||||
|
||||
RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(registerNum);
|
||||
|
||||
RegisterFormatter.writeTo(writer, encodedMethod.codeItem, registerNum);
|
||||
registerFormatter.writeTo(writer, registerNum);
|
||||
writer.write('=');
|
||||
|
||||
if (registerType == null) {
|
||||
writer.write("null");
|
||||
} else {
|
||||
registerType.writeTo(writer);
|
||||
}
|
||||
registerType.writeTo(writer);
|
||||
writer.write(';');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
@ -28,8 +28,11 @@
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import org.jf.baksmali.Adaptors.ClassDefinition;
|
||||
import org.jf.dexlib2.analysis.ClassPath;
|
||||
import org.jf.dexlib2.analysis.InlineMethodResolver;
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.jf.dexlib2.iface.DexFile;
|
||||
@ -38,10 +41,7 @@ import org.jf.util.ClassFileNameHandler;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -56,6 +56,7 @@ public class baksmali {
|
||||
public static InlineMethodResolver inlineResolver = null;
|
||||
public static int registerInfo = 0;
|
||||
public static String bootClassPath;
|
||||
public static ClassPath classPath = null;
|
||||
|
||||
public static SyntheticAccessorResolver syntheticAccessorResolver = null;
|
||||
|
||||
@ -76,43 +77,34 @@ public class baksmali {
|
||||
baksmali.registerInfo = registerInfo;
|
||||
baksmali.bootClassPath = bootClassPath;
|
||||
|
||||
//TODO: uncomment
|
||||
/*if (registerInfo != 0 || deodex || verify) {
|
||||
if (registerInfo != 0 || deodex) {
|
||||
try {
|
||||
String[] extraBootClassPathArray = null;
|
||||
Iterable<String> extraBootClassPaths = null;
|
||||
if (extraBootClassPath != null && extraBootClassPath.length() > 0) {
|
||||
assert extraBootClassPath.charAt(0) == ':';
|
||||
extraBootClassPathArray = extraBootClassPath.substring(1).split(":");
|
||||
}
|
||||
|
||||
if (dexFile.isOdex() && bootClassPath == null) {
|
||||
//ext.jar is a special case - it is typically the 2nd jar in the boot class path, but it also
|
||||
//depends on classes in framework.jar (typically the 3rd jar in the BCP). If the user didn't
|
||||
//specify a -c option, we should add framework.jar to the boot class path by default, so that it
|
||||
//"just works"
|
||||
if (extraBootClassPathArray == null && isExtJar(dexFilePath)) {
|
||||
extraBootClassPathArray = new String[] {"framework.jar"};
|
||||
}
|
||||
ClassPath.InitializeClassPathFromOdex(classPathDirs, extraBootClassPathArray, dexFilePath, dexFile,
|
||||
checkPackagePrivateAccess);
|
||||
extraBootClassPaths = Splitter.on(':').split(extraBootClassPath.substring(1));
|
||||
} else {
|
||||
String[] bootClassPathArray = null;
|
||||
if (bootClassPath != null) {
|
||||
bootClassPathArray = bootClassPath.split(":");
|
||||
}
|
||||
ClassPath.InitializeClassPath(classPathDirs, bootClassPathArray, extraBootClassPathArray,
|
||||
dexFilePath, dexFile, checkPackagePrivateAccess);
|
||||
extraBootClassPaths = ImmutableList.of();
|
||||
}
|
||||
|
||||
if (inlineTable != null) {
|
||||
inlineResolver = new CustomInlineMethodResolver(inlineTable);
|
||||
Iterable<String> bootClassPaths = null;
|
||||
if (bootClassPath != null) {
|
||||
bootClassPaths = Splitter.on(':').split(bootClassPath);
|
||||
}
|
||||
|
||||
classPath = ClassPath.fromClassPath(Arrays.asList(classPathDirs),
|
||||
Iterables.concat(bootClassPaths, extraBootClassPaths), dexFile);
|
||||
|
||||
// TODO: uncomment
|
||||
/*if (inlineTable != null) {
|
||||
inlineResolver = new CustomInlineMethodResolver(inlineTable);
|
||||
}*/
|
||||
} catch (Exception ex) {
|
||||
System.err.println("\n\nError occured while loading boot class path files. Aborting.");
|
||||
ex.printStackTrace(System.err);
|
||||
System.exit(1);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
File outputDirectoryFile = new File(outputDirectory);
|
||||
if (!outputDirectoryFile.exists()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user