mirror of
https://github.com/revanced/smali.git
synced 2025-05-04 16:44:25 +02:00
Refactor the MethodAnalyzer API so that the instructions are returned as a read-only list
git-svn-id: https://smali.googlecode.com/svn/trunk@662 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
7974e53f15
commit
ef24b31c98
@ -68,17 +68,17 @@ public class MethodDefinition {
|
||||
|
||||
if (encodedMethod.codeItem != null) {
|
||||
methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex);
|
||||
AnalyzedInstruction[] instructions = methodAnalyzer.makeInstructionArray();
|
||||
List<AnalyzedInstruction> instructions = methodAnalyzer.getInstructions();
|
||||
|
||||
packedSwitchMap = new SparseIntArray(1);
|
||||
sparseSwitchMap = new SparseIntArray(1);
|
||||
instructionMap = new SparseIntArray(instructions.length);
|
||||
instructionMap = new SparseIntArray(instructions.size());
|
||||
|
||||
registerCount = encodedMethod.codeItem.getRegisterCount();
|
||||
|
||||
int currentCodeAddress = 0;
|
||||
for (int i=0; i<instructions.length; i++) {
|
||||
AnalyzedInstruction instruction = instructions[i];
|
||||
for (int i=0; i<instructions.size(); i++) {
|
||||
AnalyzedInstruction instruction = instructions.get(i);
|
||||
if (instruction.getInstruction().opcode == Opcode.PACKED_SWITCH) {
|
||||
packedSwitchMap.append(
|
||||
currentCodeAddress + ((OffsetInstruction)instruction.getInstruction()).getTargetAddressOffset(),
|
||||
@ -248,9 +248,8 @@ public class MethodDefinition {
|
||||
return methodItems;
|
||||
}
|
||||
|
||||
AnalyzedInstruction[] instructions;
|
||||
if (baksmali.registerInfo != 0 || baksmali.deodex) {
|
||||
instructions = methodAnalyzer.analyze();
|
||||
methodAnalyzer.analyze();
|
||||
|
||||
ValidationException validationException = methodAnalyzer.getValidationException();
|
||||
if (validationException != null) {
|
||||
@ -258,14 +257,13 @@ public class MethodDefinition {
|
||||
String.format("ValidationException: %s" ,validationException.getMessage()),
|
||||
validationException.getCodeAddress(), Integer.MIN_VALUE));
|
||||
}
|
||||
} else {
|
||||
instructions = methodAnalyzer.makeInstructionArray();
|
||||
}
|
||||
List<AnalyzedInstruction> instructions = methodAnalyzer.getInstructions();
|
||||
|
||||
AnalyzedInstruction lastInstruction = null;
|
||||
|
||||
for (int i=instructions.length-1; i>=0; i--) {
|
||||
AnalyzedInstruction instruction = instructions[i];
|
||||
for (int i=instructions.size()-1; i>=0; i--) {
|
||||
AnalyzedInstruction instruction = instructions.get(i);
|
||||
|
||||
if (!instruction.isDead()) {
|
||||
lastInstruction = instruction;
|
||||
@ -277,8 +275,8 @@ public class MethodDefinition {
|
||||
BitSet printPostRegister = new BitSet(registerCount);
|
||||
|
||||
int currentCodeAddress = 0;
|
||||
for (int i=0; i<instructions.length; i++) {
|
||||
AnalyzedInstruction instruction = instructions[i];
|
||||
for (int i=0; i<instructions.size(); i++) {
|
||||
AnalyzedInstruction instruction = instructions.get(i);
|
||||
|
||||
MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this,
|
||||
encodedMethod.codeItem, currentCodeAddress, stg, instruction.getInstruction(),
|
||||
@ -295,7 +293,7 @@ public class MethodDefinition {
|
||||
encodedMethod.codeItem, currentCodeAddress, stg, instruction.getOriginalInstruction(), false)));
|
||||
}
|
||||
|
||||
if (i != instructions.length - 1) {
|
||||
if (i != instructions.size() - 1) {
|
||||
methodItems.add(new BlankMethodItem(stg, currentCodeAddress));
|
||||
}
|
||||
|
||||
@ -319,7 +317,7 @@ public class MethodDefinition {
|
||||
addArgsRegs(printPreRegister, instruction);
|
||||
}
|
||||
if ((baksmali.registerInfo & main.MERGE) != 0) {
|
||||
addMergeRegs(printPreRegister, instructions, i);
|
||||
addMergeRegs(printPreRegister, instruction);
|
||||
} else if ((baksmali.registerInfo & main.FULLMERGE) != 0 &&
|
||||
(i == 0 || instruction.isBeginningInstruction())) {
|
||||
addParamRegs(printPreRegister);
|
||||
@ -334,7 +332,7 @@ public class MethodDefinition {
|
||||
}
|
||||
|
||||
if ((baksmali.registerInfo & main.FULLMERGE) != 0) {
|
||||
addFullMergeRegs(printPreRegister, methodItems, methodAnalyzer, i, currentCodeAddress);
|
||||
addFullMergeRegs(printPreRegister, methodItems, methodAnalyzer, instruction, currentCodeAddress);
|
||||
}
|
||||
|
||||
if (!printPreRegister.isEmpty()) {
|
||||
@ -417,16 +415,7 @@ public class MethodDefinition {
|
||||
}
|
||||
|
||||
private void addFullMergeRegs(BitSet printPreRegister, List<MethodItem> methodItems, MethodAnalyzer methodAnalyzer,
|
||||
int instructionNum, int currentCodeAddress) {
|
||||
if (instructionNum == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//MethodAnalyzer cached the analyzedInstructions, so we're not actually re-analyzing, just getting the
|
||||
//instructions that have already been analyzed
|
||||
AnalyzedInstruction[] instructions = methodAnalyzer.analyze();
|
||||
AnalyzedInstruction instruction = instructions[instructionNum];
|
||||
|
||||
AnalyzedInstruction instruction, int currentCodeAddress) {
|
||||
if (instruction.getPredecessorCount() <= 1) {
|
||||
return;
|
||||
}
|
||||
@ -482,33 +471,25 @@ public class MethodDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
private void addMergeRegs(BitSet printPreRegister, AnalyzedInstruction instructions[], int instructionNum) {
|
||||
//MethodAnalyzer cached the analyzedInstructions, so we're not actually re-analyzing, just getting the
|
||||
//instructions that have already been analyzed
|
||||
AnalyzedInstruction instruction = instructions[instructionNum];
|
||||
|
||||
if (instructionNum == 0) {
|
||||
private void addMergeRegs(BitSet printPreRegister, AnalyzedInstruction instruction) {
|
||||
if (instruction.isBeginningInstruction()) {
|
||||
addParamRegs(printPreRegister);
|
||||
} else {
|
||||
if (instruction.isBeginningInstruction()) {
|
||||
addParamRegs(printPreRegister);
|
||||
}
|
||||
}
|
||||
|
||||
if (instruction.getPredecessorCount() <= 1) {
|
||||
//in the common case of an instruction that only has a single predecessor which is the previous
|
||||
//instruction, the pre-instruction registers will always match the previous instruction's
|
||||
//post-instruction registers
|
||||
return;
|
||||
}
|
||||
if (instruction.getPredecessorCount() <= 1) {
|
||||
//in the common case of an instruction that only has a single predecessor which is the previous
|
||||
//instruction, the pre-instruction registers will always match the previous instruction's
|
||||
//post-instruction registers
|
||||
return;
|
||||
}
|
||||
|
||||
for (int registerNum=0; registerNum<registerCount; registerNum++) {
|
||||
RegisterType mergedRegisterType = instruction.getPreInstructionRegisterType(registerNum);
|
||||
for (int registerNum=0; registerNum<registerCount; registerNum++) {
|
||||
RegisterType mergedRegisterType = instruction.getPreInstructionRegisterType(registerNum);
|
||||
|
||||
for (AnalyzedInstruction predecessor: instruction.getPredecessors()) {
|
||||
if (predecessor.getPostInstructionRegisterType(registerNum) != mergedRegisterType) {
|
||||
printPreRegister.set(registerNum);
|
||||
continue;
|
||||
}
|
||||
for (AnalyzedInstruction predecessor: instruction.getPredecessors()) {
|
||||
if (predecessor.getPostInstructionRegisterType(registerNum) != mergedRegisterType) {
|
||||
printPreRegister.set(registerNum);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,6 +170,8 @@ public class AnalyzedInstruction implements Comparable<AnalyzedInstruction> {
|
||||
* @return a boolean value indicating whether this instruction is a beginning instruction
|
||||
*/
|
||||
public boolean isBeginningInstruction() {
|
||||
//if this instruction has no predecessors, it is either the fake "StartOfMethod" instruction or it is an
|
||||
//unreachable instruction.
|
||||
if (predecessors.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -110,12 +110,13 @@ public class MethodAnalyzer {
|
||||
return analyzerState == VERIFIED;
|
||||
}
|
||||
|
||||
public AnalyzedInstruction[] analyze() {
|
||||
public void analyze() {
|
||||
assert encodedMethod != null;
|
||||
assert encodedMethod.codeItem != null;
|
||||
|
||||
if (analyzerState >= ANALYZED) {
|
||||
return makeInstructionArray();
|
||||
//the instructions have already been analyzed, so there is nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
CodeItem codeItem = encodedMethod.codeItem;
|
||||
@ -273,7 +274,6 @@ public class MethodAnalyzer {
|
||||
}
|
||||
|
||||
analyzerState = ANALYZED;
|
||||
return makeInstructionArray();
|
||||
}
|
||||
|
||||
private int getThisRegister() {
|
||||
@ -309,12 +309,11 @@ public class MethodAnalyzer {
|
||||
return startOfMethod;
|
||||
}
|
||||
|
||||
public AnalyzedInstruction[] makeInstructionArray() {
|
||||
AnalyzedInstruction[] instructionArray = new AnalyzedInstruction[instructions.size()];
|
||||
for (int i=0; i<instructions.size(); i++) {
|
||||
instructionArray[i] = instructions.valueAt(i);
|
||||
}
|
||||
return instructionArray;
|
||||
/**
|
||||
* @return a read-only list containing the instructions for tihs method.
|
||||
*/
|
||||
public List<AnalyzedInstruction> getInstructions() {
|
||||
return instructions.getValues();
|
||||
}
|
||||
|
||||
public ValidationException getValidationException() {
|
||||
|
@ -16,6 +16,10 @@
|
||||
|
||||
package org.jf.dexlib.Util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* SparseArrays map integers to Objects. Unlike a normal array of Objects,
|
||||
* there can be gaps in the indices. It is intended to be more efficient
|
||||
@ -340,6 +344,14 @@ public class SparseArray<E> {
|
||||
return ~high;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a read-only list of the values in this SparseArray which are in ascending order, based on their
|
||||
* associated key
|
||||
*/
|
||||
public List<E> getValues() {
|
||||
return Collections.unmodifiableList(Arrays.asList((E[])mValues));
|
||||
}
|
||||
|
||||
private int[] mKeys;
|
||||
private Object[] mValues;
|
||||
private int mSize;
|
||||
|
Loading…
x
Reference in New Issue
Block a user