mirror of
https://github.com/revanced/smali.git
synced 2025-05-29 20:20:12 +02:00
Complete and fix-up the implementation of autofixing instructions
git-svn-id: https://smali.googlecode.com/svn/trunk@511 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
8d1bb1cc83
commit
311ee79fab
@ -526,8 +526,8 @@ public class MethodDefinition {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (CodeItem.TryItem tryItem: codeItem.getTries()) {
|
for (CodeItem.TryItem tryItem: codeItem.getTries()) {
|
||||||
int startAddress = tryItem.startAddress;
|
int startAddress = tryItem.getStartAddress();
|
||||||
int endAddress = tryItem.startAddress + tryItem.instructionCount;
|
int endAddress = tryItem.getStartAddress() + tryItem.getInstructionCount();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The end address points to the address immediately after the end of the last
|
* The end address points to the address immediately after the end of the last
|
||||||
|
@ -31,6 +31,8 @@ package org.jf.dexlib;
|
|||||||
import org.jf.dexlib.Code.*;
|
import org.jf.dexlib.Code.*;
|
||||||
import org.jf.dexlib.Code.Format.Instruction20t;
|
import org.jf.dexlib.Code.Format.Instruction20t;
|
||||||
import org.jf.dexlib.Code.Format.Instruction30t;
|
import org.jf.dexlib.Code.Format.Instruction30t;
|
||||||
|
import org.jf.dexlib.Code.Format.Instruction21c;
|
||||||
|
import org.jf.dexlib.Code.Format.Instruction31c;
|
||||||
import org.jf.dexlib.Util.*;
|
import org.jf.dexlib.Util.*;
|
||||||
import org.jf.dexlib.Debug.DebugInstructionIterator;
|
import org.jf.dexlib.Debug.DebugInstructionIterator;
|
||||||
|
|
||||||
@ -400,43 +402,61 @@ public class CodeItem extends Item<CodeItem> {
|
|||||||
*
|
*
|
||||||
* The above fixes are applied iteratively, until no more fixes have been performed
|
* The above fixes are applied iteratively, until no more fixes have been performed
|
||||||
*/
|
*/
|
||||||
public void fixInstructions() {
|
public void fixInstructions(boolean fixStringConst, boolean fixGoto) {
|
||||||
boolean didSomething = false;
|
boolean didSomething = false;
|
||||||
|
|
||||||
int currentCodeOffset = 0;
|
do
|
||||||
for (int i=0; i<instructions.length; i++) {
|
{
|
||||||
Instruction instruction = instructions[i];
|
didSomething = false;
|
||||||
|
|
||||||
if (instruction.opcode == Opcode.GOTO) {
|
int currentCodeOffset = 0;
|
||||||
int offset = ((OffsetInstruction)instruction).getOffset();
|
for (int i=0; i<instructions.length; i++) {
|
||||||
|
Instruction instruction = instructions[i];
|
||||||
|
|
||||||
if (((byte)offset) != offset) {
|
if (fixGoto && instruction.opcode == Opcode.GOTO) {
|
||||||
//the offset doesn't fit within a byte, we need to upgrade to a goto/16 or goto/32
|
int offset = ((OffsetInstruction)instruction).getOffset();
|
||||||
|
|
||||||
if ((short)offset == offset) {
|
if (((byte)offset) != offset) {
|
||||||
//the offset fits in a short, so upgrade to a goto/16 h
|
//the offset doesn't fit within a byte, we need to upgrade to a goto/16 or goto/32
|
||||||
replaceInstructionAtOffset(currentCodeOffset, new Instruction20t(Opcode.GOTO_16, offset));
|
|
||||||
|
if ((short)offset == offset) {
|
||||||
|
//the offset fits in a short, so upgrade to a goto/16 h
|
||||||
|
replaceInstructionAtOffset(currentCodeOffset, new Instruction20t(Opcode.GOTO_16, offset));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//The offset won't fit into a short, we have to upgrade to a goto/32
|
||||||
|
replaceInstructionAtOffset(currentCodeOffset, new Instruction30t(Opcode.GOTO_32, offset));
|
||||||
|
}
|
||||||
|
didSomething = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else {
|
} else if (fixGoto && instruction.opcode == Opcode.GOTO_16) {
|
||||||
//The offset won't fit into a short, we have to upgrade to a goto/32
|
int offset = ((OffsetInstruction)instruction).getOffset();
|
||||||
|
|
||||||
|
if (((short)offset) != offset) {
|
||||||
|
//the offset doesn't fit within a short, we need to upgrade to a goto/32
|
||||||
replaceInstructionAtOffset(currentCodeOffset, new Instruction30t(Opcode.GOTO_32, offset));
|
replaceInstructionAtOffset(currentCodeOffset, new Instruction30t(Opcode.GOTO_32, offset));
|
||||||
|
didSomething = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (fixStringConst && instruction.opcode == Opcode.CONST_STRING) {
|
||||||
|
Instruction21c constStringInstruction = (Instruction21c)instruction;
|
||||||
|
if (constStringInstruction.getReferencedItem().getIndex() > 0xFFFF) {
|
||||||
|
replaceInstructionAtOffset(currentCodeOffset, new Instruction31c(Opcode.CONST_STRING_JUMBO,
|
||||||
|
(short)constStringInstruction.getRegisterA(),
|
||||||
|
constStringInstruction.getReferencedItem()));
|
||||||
|
didSomething = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (instruction.opcode == Opcode.GOTO_16) {
|
|
||||||
int offset = ((OffsetInstruction)instruction).getOffset();
|
|
||||||
|
|
||||||
if (((short)offset) != offset) {
|
currentCodeOffset += instruction.getSize(currentCodeOffset);
|
||||||
//the offset doesn't fit within a short, we need to upgrade to a goto/32
|
|
||||||
replaceInstructionAtOffset(currentCodeOffset, new Instruction30t(Opcode.GOTO_32, offset));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}while(didSomething);
|
||||||
currentCodeOffset += instruction.getSize(currentCodeOffset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replaceInstructionAtOffset(int offset, Instruction replacementInstruction) {
|
private void replaceInstructionAtOffset(int offset, Instruction replacementInstruction) {
|
||||||
Instruction originalInstruction = null;
|
Instruction originalInstruction = null;
|
||||||
|
|
||||||
int[] originalInstructionOffsets = new int[instructions.length];
|
int[] originalInstructionOffsets = new int[instructions.length];
|
||||||
SparseIntArray originalSwitchOffsetByOriginalSwitchDataOffset = new SparseIntArray();
|
SparseIntArray originalSwitchOffsetByOriginalSwitchDataOffset = new SparseIntArray();
|
||||||
@ -476,6 +496,7 @@ public class CodeItem extends Item<CodeItem> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: replace these with a callable delegate
|
||||||
final SparseIntArray originalOffsetsByNewOffset = new SparseIntArray();
|
final SparseIntArray originalOffsetsByNewOffset = new SparseIntArray();
|
||||||
final SparseIntArray newOffsetsByOriginalOffset = new SparseIntArray();
|
final SparseIntArray newOffsetsByOriginalOffset = new SparseIntArray();
|
||||||
|
|
||||||
@ -505,8 +526,11 @@ public class CodeItem extends Item<CodeItem> {
|
|||||||
|
|
||||||
assert newOffsetsByOriginalOffset.indexOfKey(originalInstructionTarget) >= 0;
|
assert newOffsetsByOriginalOffset.indexOfKey(originalInstructionTarget) >= 0;
|
||||||
int newInstructionTarget = newOffsetsByOriginalOffset.get(originalInstructionTarget);
|
int newInstructionTarget = newOffsetsByOriginalOffset.get(originalInstructionTarget);
|
||||||
if (newInstructionTarget != originalInstructionTarget) {
|
|
||||||
offsetInstruction.updateOffset(newInstructionTarget);
|
int newOffset = (newInstructionTarget - currentCodeOffset) / 2;
|
||||||
|
|
||||||
|
if (newOffset != offsetInstruction.getOffset()) {
|
||||||
|
offsetInstruction.updateOffset(newOffset);
|
||||||
}
|
}
|
||||||
} else if (instruction instanceof MultiOffsetInstruction) {
|
} else if (instruction instanceof MultiOffsetInstruction) {
|
||||||
MultiOffsetInstruction multiOffsetInstruction = (MultiOffsetInstruction)instruction;
|
MultiOffsetInstruction multiOffsetInstruction = (MultiOffsetInstruction)instruction;
|
||||||
@ -520,39 +544,62 @@ public class CodeItem extends Item<CodeItem> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert newOffsetsByOriginalOffset.indexOfKey(originalSwitchOffset) >= 0;
|
||||||
|
int newSwitchOffset = newOffsetsByOriginalOffset.get(originalSwitchOffset);
|
||||||
|
|
||||||
int[] targets = multiOffsetInstruction.getTargets();
|
int[] targets = multiOffsetInstruction.getTargets();
|
||||||
for (int t=0; t<targets.length; t++) {
|
for (int t=0; t<targets.length; t++) {
|
||||||
int originalTargetOffset = originalSwitchOffset + targets[t];
|
int originalTargetOffset = originalSwitchOffset + targets[t]*2;
|
||||||
assert newOffsetsByOriginalOffset.indexOfKey(originalTargetOffset) >= 0;
|
assert newOffsetsByOriginalOffset.indexOfKey(originalTargetOffset) >= 0;
|
||||||
int newTargetOffset = newOffsetsByOriginalOffset.get(originalTargetOffset);
|
int newTargetOffset = newOffsetsByOriginalOffset.get(originalTargetOffset);
|
||||||
if (newTargetOffset != originalTargetOffset) {
|
int newOffset = (newTargetOffset - newSwitchOffset)/2;
|
||||||
multiOffsetInstruction.updateTarget(t, newTargetOffset);
|
if (newOffset != targets[t]) {
|
||||||
|
multiOffsetInstruction.updateTarget(t, newOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentCodeOffset += instruction.getSize(currentCodeOffset);
|
currentCodeOffset += instruction.getSize(currentCodeOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
final byte[] encodedDebugInfo = debugInfo.getEncodedDebugInfo();
|
if (debugInfo != null) {
|
||||||
|
final byte[] encodedDebugInfo = debugInfo.getEncodedDebugInfo();
|
||||||
|
|
||||||
ByteArrayInput debugInput = new ByteArrayInput(encodedDebugInfo);
|
ByteArrayInput debugInput = new ByteArrayInput(encodedDebugInfo);
|
||||||
|
|
||||||
DebugInstructionFixer debugInstructionFixer = new DebugInstructionFixer(encodedDebugInfo,
|
DebugInstructionFixer debugInstructionFixer = new DebugInstructionFixer(encodedDebugInfo,
|
||||||
newOffsetsByOriginalOffset, originalOffsetsByNewOffset);
|
newOffsetsByOriginalOffset, originalOffsetsByNewOffset);
|
||||||
DebugInstructionIterator.IterateInstructions(debugInput, debugInstructionFixer);
|
DebugInstructionIterator.IterateInstructions(debugInput, debugInstructionFixer);
|
||||||
|
|
||||||
debugInfo.setEncodedDebugInfo(debugInstructionFixer.result);
|
assert debugInstructionFixer.result != null;
|
||||||
|
|
||||||
|
debugInfo.setEncodedDebugInfo(debugInstructionFixer.result);
|
||||||
|
}
|
||||||
|
|
||||||
for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) {
|
if (encodedCatchHandlers != null) {
|
||||||
if (encodedCatchHandler.catchAllHandlerAddress != -1) {
|
for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) {
|
||||||
assert newOffsetsByOriginalOffset.indexOfKey(encodedCatchHandler.catchAllHandlerAddress) >= 0;
|
if (encodedCatchHandler.catchAllHandlerAddress != -1) {
|
||||||
encodedCatchHandler.catchAllHandlerAddress =
|
assert newOffsetsByOriginalOffset.indexOfKey(encodedCatchHandler.catchAllHandlerAddress*2) >= 0;
|
||||||
newOffsetsByOriginalOffset.get(encodedCatchHandler.catchAllHandlerAddress);
|
encodedCatchHandler.catchAllHandlerAddress =
|
||||||
|
newOffsetsByOriginalOffset.get(encodedCatchHandler.catchAllHandlerAddress*2)/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (EncodedTypeAddrPair handler: encodedCatchHandler.handlers) {
|
||||||
|
assert newOffsetsByOriginalOffset.indexOfKey(handler.handlerAddress*2) >= 0;
|
||||||
|
handler.handlerAddress = newOffsetsByOriginalOffset.get(handler.handlerAddress*2)/2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (EncodedTypeAddrPair handler: encodedCatchHandler.handlers) {
|
if (this.tries != null) {
|
||||||
handler.handlerAddress = newOffsetsByOriginalOffset.get(handler.handlerAddress);
|
for (TryItem tryItem: tries) {
|
||||||
|
int startAddress = tryItem.startAddress;
|
||||||
|
int endAddress = tryItem.startAddress + tryItem.instructionCount;
|
||||||
|
|
||||||
|
assert newOffsetsByOriginalOffset.indexOfKey(startAddress * 2) >= 0;
|
||||||
|
tryItem.startAddress = newOffsetsByOriginalOffset.get(startAddress * 2)/2;
|
||||||
|
|
||||||
|
assert newOffsetsByOriginalOffset.indexOfKey(endAddress * 2) >= 0;
|
||||||
|
tryItem.instructionCount = newOffsetsByOriginalOffset.get(endAddress * 2)/2 - tryItem.startAddress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -560,62 +607,62 @@ public class CodeItem extends Item<CodeItem> {
|
|||||||
private class DebugInstructionFixer extends DebugInstructionIterator.ProcessRawDebugInstructionDelegate {
|
private class DebugInstructionFixer extends DebugInstructionIterator.ProcessRawDebugInstructionDelegate {
|
||||||
private int address = 0;
|
private int address = 0;
|
||||||
private SparseIntArray newOffsetsByOriginalOffset;
|
private SparseIntArray newOffsetsByOriginalOffset;
|
||||||
private SparseIntArray originalOffsetByNewOffset;
|
private SparseIntArray originalOffsetsByNewOffset;
|
||||||
private final byte[] originalEncodedDebugInfo;
|
private final byte[] originalEncodedDebugInfo;
|
||||||
public byte[] result = null;
|
public byte[] result = null;
|
||||||
|
|
||||||
public DebugInstructionFixer(byte[] originalEncodedDebugInfo, SparseIntArray newOffsetsbyOriginalOffset,
|
public DebugInstructionFixer(byte[] originalEncodedDebugInfo, SparseIntArray newOffsetsByOriginalOffset,
|
||||||
SparseIntArray originalOffsetsByNewOffset) {
|
SparseIntArray originalOffsetsByNewOffset) {
|
||||||
this.newOffsetsByOriginalOffset = newOffsetsByOriginalOffset;
|
this.newOffsetsByOriginalOffset = newOffsetsByOriginalOffset;
|
||||||
this.originalOffsetByNewOffset = originalOffsetByNewOffset;
|
this.originalOffsetsByNewOffset = originalOffsetsByNewOffset;
|
||||||
this.originalEncodedDebugInfo = originalEncodedDebugInfo;
|
this.originalEncodedDebugInfo = originalEncodedDebugInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void ProcessAdvancePC(int startOffset, int length, int addressDiff) {
|
public void ProcessAdvancePC(int startOffset, int length, int addressDelta) {
|
||||||
if (result != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int newOffset = newOffsetsByOriginalOffset.get((address + addressDiff)*2, -1);
|
|
||||||
assert newOffset != -1;
|
|
||||||
newOffset = newOffset / 2;
|
|
||||||
|
|
||||||
if (newOffset != address) {
|
|
||||||
int newAddressDiff = addressDiff + newOffset - address;
|
|
||||||
assert newAddressDiff > 0;
|
|
||||||
int addressDiffSize = Leb128Utils.unsignedLeb128Size(newAddressDiff);
|
|
||||||
|
|
||||||
result = new byte[originalEncodedDebugInfo.length + addressDiffSize - (length - 1)];
|
|
||||||
|
|
||||||
System.arraycopy(originalEncodedDebugInfo, 0, result, 0, startOffset);
|
|
||||||
|
|
||||||
originalEncodedDebugInfo[startOffset] = 0x01; //DBG_ADVANCE_PC debug opcode
|
|
||||||
Leb128Utils.writeUnsignedLeb128(newAddressDiff, originalEncodedDebugInfo, startOffset+1);
|
|
||||||
|
|
||||||
System.arraycopy(originalEncodedDebugInfo, startOffset+length, originalEncodedDebugInfo,
|
|
||||||
startOffset + addressDiffSize + 1,
|
|
||||||
originalEncodedDebugInfo.length - (startOffset + addressDiffSize + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
address += addressDiff;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void ProcessSpecialOpcode(int startOffset, int debugOpcode, int lineDelta,
|
|
||||||
int addressDelta) {
|
|
||||||
if (result != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
address += addressDelta;
|
address += addressDelta;
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int newOffset = newOffsetsByOriginalOffset.get(address*2, -1);
|
int newOffset = newOffsetsByOriginalOffset.get(address*2, -1);
|
||||||
assert newOffset != -1;
|
assert newOffset != -1;
|
||||||
newOffset = newOffset / 2;
|
newOffset = newOffset / 2;
|
||||||
|
|
||||||
if (newOffset != address) {
|
if (newOffset != address) {
|
||||||
int newAddressDelta = addressDelta + newOffset - address;
|
int newAddressDelta = newOffset - (address - addressDelta);
|
||||||
|
assert newAddressDelta > 0;
|
||||||
|
int addressDiffSize = Leb128Utils.unsignedLeb128Size(newAddressDelta);
|
||||||
|
|
||||||
|
result = new byte[originalEncodedDebugInfo.length + addressDiffSize - (length - 1)];
|
||||||
|
|
||||||
|
System.arraycopy(originalEncodedDebugInfo, 0, result, 0, startOffset);
|
||||||
|
|
||||||
|
result[startOffset] = 0x01; //DBG_ADVANCE_PC debug opcode
|
||||||
|
Leb128Utils.writeUnsignedLeb128(newAddressDelta, result, startOffset+1);
|
||||||
|
|
||||||
|
System.arraycopy(originalEncodedDebugInfo, startOffset+length, result,
|
||||||
|
startOffset + addressDiffSize + 1,
|
||||||
|
originalEncodedDebugInfo.length - (startOffset + addressDiffSize + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ProcessSpecialOpcode(int startOffset, int debugOpcode, int lineDelta,
|
||||||
|
int addressDelta) {
|
||||||
|
address += addressDelta;
|
||||||
|
if (result != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int newOffset = newOffsetsByOriginalOffset.get(address*2, -1);
|
||||||
|
assert newOffset != -1;
|
||||||
|
newOffset = newOffset / 2;
|
||||||
|
|
||||||
|
if (newOffset != address) {
|
||||||
|
int newAddressDelta = newOffset - (address - addressDelta);
|
||||||
assert newAddressDelta > 0;
|
assert newAddressDelta > 0;
|
||||||
|
|
||||||
//if the new address delta won't fit in the special opcode, we need to insert
|
//if the new address delta won't fit in the special opcode, we need to insert
|
||||||
@ -624,7 +671,7 @@ public class CodeItem extends Item<CodeItem> {
|
|||||||
int additionalAddressDelta = newOffset - address;
|
int additionalAddressDelta = newOffset - address;
|
||||||
int additionalAddressDeltaSize = Leb128Utils.signedLeb128Size(additionalAddressDelta);
|
int additionalAddressDeltaSize = Leb128Utils.signedLeb128Size(additionalAddressDelta);
|
||||||
|
|
||||||
result = new byte[result.length + additionalAddressDeltaSize + 1];
|
result = new byte[originalEncodedDebugInfo.length + additionalAddressDeltaSize + 1];
|
||||||
|
|
||||||
System.arraycopy(originalEncodedDebugInfo, 0, result, 0, startOffset);
|
System.arraycopy(originalEncodedDebugInfo, 0, result, 0, startOffset);
|
||||||
result[startOffset] = 0x01; //DBG_ADVANCE_PC
|
result[startOffset] = 0x01; //DBG_ADVANCE_PC
|
||||||
@ -633,7 +680,7 @@ public class CodeItem extends Item<CodeItem> {
|
|||||||
startOffset+additionalAddressDeltaSize+1,
|
startOffset+additionalAddressDeltaSize+1,
|
||||||
result.length - (startOffset+additionalAddressDeltaSize+1));
|
result.length - (startOffset+additionalAddressDeltaSize+1));
|
||||||
} else {
|
} else {
|
||||||
result = new byte[result.length];
|
result = new byte[originalEncodedDebugInfo.length];
|
||||||
System.arraycopy(originalEncodedDebugInfo, 0, result, 0, result.length);
|
System.arraycopy(originalEncodedDebugInfo, 0, result, 0, result.length);
|
||||||
result[startOffset] = DebugInfoBuilder.calculateSpecialOpcode(lineDelta,
|
result[startOffset] = DebugInfoBuilder.calculateSpecialOpcode(lineDelta,
|
||||||
newAddressDelta);
|
newAddressDelta);
|
||||||
@ -646,12 +693,12 @@ public class CodeItem extends Item<CodeItem> {
|
|||||||
/**
|
/**
|
||||||
* The address (in 2-byte words) within the code where the try block starts
|
* The address (in 2-byte words) within the code where the try block starts
|
||||||
*/
|
*/
|
||||||
public final int startAddress;
|
private int startAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of 2-byte words that the try block covers
|
* The number of 2-byte words that the try block covers
|
||||||
*/
|
*/
|
||||||
public final int instructionCount;
|
private int instructionCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The associated exception handler
|
* The associated exception handler
|
||||||
@ -703,6 +750,20 @@ public class CodeItem extends Item<CodeItem> {
|
|||||||
out.writeShort(instructionCount);
|
out.writeShort(instructionCount);
|
||||||
out.writeShort(encodedCatchHandler.getOffsetInList());
|
out.writeShort(encodedCatchHandler.getOffsetInList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The address (in 2-byte words) within the code where the try block starts
|
||||||
|
*/
|
||||||
|
public int getStartAddress() {
|
||||||
|
return startAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The number of 2-byte words that the try block covers
|
||||||
|
*/
|
||||||
|
public int getInstructionCount() {
|
||||||
|
return instructionCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class EncodedCatchHandler {
|
public static class EncodedCatchHandler {
|
||||||
|
@ -166,8 +166,8 @@ public class DeodexUtil {
|
|||||||
handlers[i] = insnsMap.get(tryItem.encodedCatchHandler.handlers[i].getHandlerAddress());
|
handlers[i] = insnsMap.get(tryItem.encodedCatchHandler.handlers[i].getHandlerAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
int insnoffset = tryItem.startAddress;
|
int insnoffset = tryItem.getStartAddress();
|
||||||
while (insnoffset < tryItem.startAddress + tryItem.instructionCount) {
|
while (insnoffset < tryItem.getStartAddress() + tryItem.getInstructionCount()) {
|
||||||
insn i = insnsMap.get(insnoffset);
|
insn i = insnsMap.get(insnoffset);
|
||||||
|
|
||||||
i.exceptionHandlers = handlers;
|
i.exceptionHandlers = handlers;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -47,6 +47,7 @@
|
|||||||
LFormat32x;,
|
LFormat32x;,
|
||||||
LFormat35c;,
|
LFormat35c;,
|
||||||
LFormat3rc;,
|
LFormat3rc;,
|
||||||
LFormat51l;
|
LFormat51l;,
|
||||||
|
LGotoTest;
|
||||||
}
|
}
|
||||||
.end annotation
|
.end annotation
|
File diff suppressed because it is too large
Load Diff
@ -880,11 +880,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters, List<Instruc
|
|||||||
|
|
||||||
int addressOffset = $offset_or_label.offsetValue;
|
int addressOffset = $offset_or_label.offsetValue;
|
||||||
|
|
||||||
if (addressOffset < Byte.MIN_VALUE || addressOffset > Byte.MAX_VALUE) {
|
$instructions.add(new Instruction10t(opcode, addressOffset));
|
||||||
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-128, 127].");
|
|
||||||
}
|
|
||||||
|
|
||||||
$instructions.add(new Instruction10t(opcode, (byte)addressOffset));
|
|
||||||
}
|
}
|
||||||
| //e.g. return
|
| //e.g. return
|
||||||
^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x)
|
^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x)
|
||||||
@ -927,11 +923,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters, List<Instruc
|
|||||||
|
|
||||||
int addressOffset = $offset_or_label.offsetValue;
|
int addressOffset = $offset_or_label.offsetValue;
|
||||||
|
|
||||||
if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) {
|
$instructions.add(new Instruction20t(opcode, addressOffset));
|
||||||
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
|
||||||
}
|
|
||||||
|
|
||||||
$instructions.add(new Instruction20t(opcode, (short)addressOffset));
|
|
||||||
}
|
}
|
||||||
| //e.g. sget_object v0 java/lang/System/out LJava/io/PrintStream;
|
| //e.g. sget_object v0 java/lang/System/out LJava/io/PrintStream;
|
||||||
^(I_STATEMENT_FORMAT21c_FIELD INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field)
|
^(I_STATEMENT_FORMAT21c_FIELD INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field)
|
||||||
|
@ -18,6 +18,10 @@ package org.jf.smali;
|
|||||||
|
|
||||||
import org.apache.commons.cli.*;
|
import org.apache.commons.cli.*;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
|
import org.jf.dexlib.CodeItem;
|
||||||
|
import org.jf.dexlib.Code.InstructionIterator;
|
||||||
|
import org.jf.dexlib.Code.Opcode;
|
||||||
|
import org.jf.dexlib.Code.Format.Format;
|
||||||
import org.jf.dexlib.Util.ByteArrayAnnotatedOutput;
|
import org.jf.dexlib.Util.ByteArrayAnnotatedOutput;
|
||||||
import org.jf.dexlib.Util.FileUtils;
|
import org.jf.dexlib.Util.FileUtils;
|
||||||
import org.antlr.runtime.ANTLRInputStream;
|
import org.antlr.runtime.ANTLRInputStream;
|
||||||
@ -80,6 +84,8 @@ public class main {
|
|||||||
|
|
||||||
boolean sort = false;
|
boolean sort = false;
|
||||||
boolean rewriteLabels = false;
|
boolean rewriteLabels = false;
|
||||||
|
boolean fixStringConst = true;
|
||||||
|
boolean fixGoto = true;
|
||||||
|
|
||||||
String outputDexFile = "out.dex";
|
String outputDexFile = "out.dex";
|
||||||
String dumpFileName = null;
|
String dumpFileName = null;
|
||||||
@ -129,6 +135,14 @@ public class main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (commandLine.hasOption("c")) {
|
||||||
|
fixStringConst = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandLine.hasOption("g")) {
|
||||||
|
fixGoto = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@ -174,6 +188,10 @@ public class main {
|
|||||||
dexFile.setSortAllItems(true);
|
dexFile.setSortAllItems(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fixStringConst || fixGoto) {
|
||||||
|
fixInstructions(dexFile, fixStringConst, fixGoto);
|
||||||
|
}
|
||||||
|
|
||||||
dexFile.place();
|
dexFile.place();
|
||||||
|
|
||||||
ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();
|
ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();
|
||||||
@ -222,6 +240,16 @@ public class main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void fixInstructions(DexFile dexFile, boolean fixStringConst, boolean fixGoto) {
|
||||||
|
dexFile.place();
|
||||||
|
|
||||||
|
byte[] newInsns = null;
|
||||||
|
|
||||||
|
for (CodeItem codeItem: dexFile.CodeItemsSection.getItems()) {
|
||||||
|
codeItem.fixInstructions(fixStringConst, fixGoto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean doRewriteLabels(Set<File> files)
|
private static boolean doRewriteLabels(Set<File> files)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
boolean errorOccurred = false;
|
boolean errorOccurred = false;
|
||||||
@ -345,11 +373,21 @@ public class main {
|
|||||||
.withDescription("rewrite the input smali files, converting any labels in the old (pre .97) format to the new format")
|
.withDescription("rewrite the input smali files, converting any labels in the old (pre .97) format to the new format")
|
||||||
.create("r");
|
.create("r");
|
||||||
|
|
||||||
|
Option noFixStringConstOption = OptionBuilder.withLongOpt("no-fix-string-const")
|
||||||
|
.withDescription("Don't replace string-const instructions with string-const/jumbo where appropriate")
|
||||||
|
.create("c");
|
||||||
|
|
||||||
|
Option noFixGotoOption = OptionBuilder.withLongOpt("no-fix-goto")
|
||||||
|
.withDescription("Don't replace goto type instructions with a larger version where appropriate")
|
||||||
|
.create("g");
|
||||||
|
|
||||||
options.addOption(versionOption);
|
options.addOption(versionOption);
|
||||||
options.addOption(helpOption);
|
options.addOption(helpOption);
|
||||||
options.addOption(dumpOption);
|
options.addOption(dumpOption);
|
||||||
options.addOption(outputOption);
|
options.addOption(outputOption);
|
||||||
options.addOption(sortOption);
|
options.addOption(sortOption);
|
||||||
options.addOption(rewriteLabelOption);
|
options.addOption(rewriteLabelOption);
|
||||||
|
options.addOption(noFixStringConstOption);
|
||||||
|
options.addOption(noFixGotoOption);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user