Split the logic for generating the instruction method items depending on whether we need to use the MethodAnalyzer or not

git-svn-id: https://smali.googlecode.com/svn/trunk@736 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
JesusFreke@JesusFreke.com 2010-06-12 15:55:36 +00:00
parent 41265daa5a
commit f7344d33d0
2 changed files with 124 additions and 52 deletions

View File

@ -43,7 +43,35 @@ public class InstructionMethodItemFactory {
public static InstructionMethodItem makeInstructionFormatMethodItem(MethodDefinition methodDefinition,
CodeItem codeItem,
int codeAddress, boolean dead,
int codeAddress,
Instruction instruction) {
if (instruction instanceof OffsetInstruction) {
return new OffsetInstructionFormatMethodItem(methodDefinition.getLabelCache(), codeItem, codeAddress,
instruction);
}
switch (instruction.getFormat()) {
case ArrayData:
return new ArrayDataMethodItem(codeItem, codeAddress, false,
(ArrayDataPseudoInstruction)instruction);
case PackedSwitchData:
return new PackedSwitchMethodItem(methodDefinition, codeItem, codeAddress, false,
(PackedSwitchDataPseudoInstruction)instruction);
case SparseSwitchData:
return new SparseSwitchMethodItem(methodDefinition, codeItem, codeAddress, false,
(SparseSwitchDataPseudoInstruction)instruction);
case UnresolvedNullReference:
assert false;
throw new RuntimeException("UnresolvedNullReference not supported, use " +
"makeAnalyzedInstructionFormatMethodItem instead");
default:
return new InstructionMethodItem(codeItem, codeAddress, instruction);
}
}
public static InstructionMethodItem makeAnalyzedInstructionFormatMethodItem(MethodDefinition methodDefinition,
CodeItem codeItem, int codeAddress,
boolean isDead,
Instruction instruction,
boolean isLastInstruction) {
if (instruction instanceof OffsetInstruction) {
@ -53,13 +81,13 @@ public class InstructionMethodItemFactory {
switch (instruction.getFormat()) {
case ArrayData:
return new ArrayDataMethodItem(codeItem, codeAddress, dead,
return new ArrayDataMethodItem(codeItem, codeAddress, isDead,
(ArrayDataPseudoInstruction)instruction);
case PackedSwitchData:
return new PackedSwitchMethodItem(methodDefinition, codeItem, codeAddress, dead,
return new PackedSwitchMethodItem(methodDefinition, codeItem, codeAddress, isDead,
(PackedSwitchDataPseudoInstruction)instruction);
case SparseSwitchData:
return new SparseSwitchMethodItem(methodDefinition, codeItem, codeAddress, dead,
return new SparseSwitchMethodItem(methodDefinition, codeItem, codeAddress, isDead,
(SparseSwitchDataPseudoInstruction)instruction);
case UnresolvedNullReference:
return new UnresolvedNullReferenceMethodItem(codeItem, codeAddress,

View File

@ -49,7 +49,7 @@ import java.util.*;
public class MethodDefinition {
private final ClassDataItem.EncodedMethod encodedMethod;
private final MethodAnalyzer methodAnalyzer;
private MethodAnalyzer methodAnalyzer;
private final LabelCache labelCache = new LabelCache();
@ -66,29 +66,28 @@ public class MethodDefinition {
//TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh.
if (encodedMethod.codeItem != null) {
methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex);
List<AnalyzedInstruction> instructions = methodAnalyzer.getInstructions();
Instruction[] instructions = encodedMethod.codeItem.getInstructions();
packedSwitchMap = new SparseIntArray(1);
sparseSwitchMap = new SparseIntArray(1);
instructionMap = new SparseIntArray(instructions.size());
instructionMap = new SparseIntArray(instructions.length);
int currentCodeAddress = 0;
for (int i=0; i<instructions.size(); i++) {
AnalyzedInstruction instruction = instructions.get(i);
if (instruction.getInstruction().opcode == Opcode.PACKED_SWITCH) {
for (int i=0; i<instructions.length; i++) {
Instruction instruction = instructions[i];
if (instruction.opcode == Opcode.PACKED_SWITCH) {
packedSwitchMap.append(
currentCodeAddress +
((OffsetInstruction)instruction.getInstruction()).getTargetAddressOffset(),
((OffsetInstruction)instruction).getTargetAddressOffset(),
currentCodeAddress);
} else if (instruction.getInstruction().opcode == Opcode.SPARSE_SWITCH) {
} else if (instruction.opcode == Opcode.SPARSE_SWITCH) {
sparseSwitchMap.append(
currentCodeAddress +
((OffsetInstruction)instruction.getInstruction()).getTargetAddressOffset(),
((OffsetInstruction)instruction).getTargetAddressOffset(),
currentCodeAddress);
}
instructionMap.append(currentCodeAddress, i);
currentCodeAddress += instruction.getInstruction().getSize(currentCodeAddress);
currentCodeAddress += instruction.getSize(currentCodeAddress);
}
} else {
packedSwitchMap = null;
@ -281,13 +280,78 @@ public class MethodDefinition {
}
private List<MethodItem> getMethodItems() {
List<MethodItem> methodItems = new ArrayList<MethodItem>();
ArrayList<MethodItem> methodItems = new ArrayList<MethodItem>();
if (encodedMethod.codeItem == null) {
return methodItems;
}
if (baksmali.registerInfo != 0 || baksmali.deodex || baksmali.verify) {
addAnalyzedInstructionMethodItems(methodItems);
} else {
addInstructionMethodItems(methodItems);
}
addTries(methodItems);
addDebugInfo(methodItems);
if (baksmali.useSequentialLabels) {
setLabelSequentialNumbers();
}
for (LabelMethodItem labelMethodItem: labelCache.getLabels()) {
if (labelMethodItem.isCommentedOut()) {
methodItems.add(new CommentedOutMethodItem(labelMethodItem));
} else {
methodItems.add(labelMethodItem);
}
}
Collections.sort(methodItems);
return methodItems;
}
private void addInstructionMethodItems(List<MethodItem> methodItems) {
Instruction[] instructions = encodedMethod.codeItem.getInstructions();
int currentCodeAddress = 0;
for (int i=0; i<instructions.length; i++) {
Instruction instruction = instructions[i];
MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this,
encodedMethod.codeItem, currentCodeAddress, instruction);
methodItems.add(methodItem);
if (i != instructions.length - 1) {
methodItems.add(new BlankMethodItem(currentCodeAddress));
}
if (baksmali.addCodeOffsets) {
methodItems.add(new MethodItem(currentCodeAddress) {
@Override
public double getSortOrder() {
return -1000;
}
@Override
public boolean writeTo(IndentingWriter writer) throws IOException {
writer.write("#@");
writer.printLongAsHex(codeAddress & 0xFFFFFFFF);
return true;
}
});
}
currentCodeAddress += instruction.getSize(currentCodeAddress);
}
}
private void addAnalyzedInstructionMethodItems(List<MethodItem> methodItems) {
methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex);
methodAnalyzer.analyze();
ValidationException validationException = methodAnalyzer.getValidationException();
@ -305,7 +369,7 @@ public class MethodDefinition {
validationException.getCodeAddress(), Integer.MIN_VALUE));
}
}
}
List<AnalyzedInstruction> instructions = methodAnalyzer.getInstructions();
AnalyzedInstruction lastInstruction = null;
@ -325,7 +389,7 @@ public class MethodDefinition {
for (int i=0; i<instructions.size(); i++) {
AnalyzedInstruction instruction = instructions.get(i);
MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this,
MethodItem methodItem = InstructionMethodItemFactory.makeAnalyzedInstructionFormatMethodItem(this,
encodedMethod.codeItem, currentCodeAddress, instruction.isDead(), instruction.getInstruction(),
instruction == lastInstruction);
@ -350,9 +414,9 @@ public class MethodDefinition {
if (instruction.getInstruction().getFormat() == Format.UnresolvedNullReference) {
methodItems.add(new CommentedOutMethodItem(
InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, encodedMethod.codeItem,
currentCodeAddress, instruction.isDead(), instruction.getOriginalInstruction(),
false)));
InstructionMethodItemFactory.makeAnalyzedInstructionFormatMethodItem(this,
encodedMethod.codeItem, currentCodeAddress, instruction.isDead(),
instruction.getOriginalInstruction(), false)));
}
if (i != instructions.size() - 1) {
@ -386,26 +450,6 @@ public class MethodDefinition {
currentCodeAddress += instruction.getInstruction().getSize(currentCodeAddress);
}
addTries(methodItems);
addDebugInfo(methodItems);
if (baksmali.useSequentialLabels) {
setLabelSequentialNumbers();
}
for (LabelMethodItem labelMethodItem: labelCache.getLabels()) {
if (labelMethodItem.isCommentedOut()) {
methodItems.add(new CommentedOutMethodItem(labelMethodItem));
} else {
methodItems.add(labelMethodItem);
}
}
Collections.sort(methodItems);
return methodItems;
}
private void addTries(List<MethodItem> methodItems) {