mirror of
https://github.com/revanced/smali.git
synced 2025-05-29 20:20:12 +02:00
General cleanup/refactoring/maintentance
- Added some additional context information for exceptions in various locations - Refactored all code offsets so that they use 2-byte code block address, instead of a byte offset. - Additionally changed all "offset" terminology refering to code offsets to "address" instead - Changed the way the getItemByIndex and getOffsettedItemByOffset work, so that they throw an exception if the index/offset is -1/0. - Added additional getOptionalItemByIndex and getOptionalOffsettedItemByOffset methods, to be used in the cases where an index/offset of -1/0 is valid, to indicate the absence of an item - Other misc cleanup/maintentance git-svn-id: https://smali.googlecode.com/svn/trunk@552 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
3ae5a27b60
commit
16a911620c
@ -35,8 +35,8 @@ import org.antlr.stringtemplate.StringTemplate;
|
||||
public class BlankMethodItem extends MethodItem {
|
||||
private static StringTemplate template;
|
||||
|
||||
public BlankMethodItem(StringTemplateGroup stg, int offset) {
|
||||
super(offset);
|
||||
public BlankMethodItem(StringTemplateGroup stg, int codeAddress) {
|
||||
super(codeAddress);
|
||||
if (template == null) {
|
||||
template = stg.getInstanceOf("Blank");
|
||||
}
|
||||
|
@ -41,17 +41,17 @@ public class CatchMethodItem extends MethodItem {
|
||||
private final LabelMethodItem tryEndLabel;
|
||||
private final LabelMethodItem handlerLabel;
|
||||
|
||||
public CatchMethodItem(MethodDefinition.LabelCache labelCache, int offset, StringTemplateGroup stg,
|
||||
public CatchMethodItem(MethodDefinition.LabelCache labelCache, int codeAddress, StringTemplateGroup stg,
|
||||
TypeIdItem exceptionType, int startAddress, int endAddress, int handlerAddress) {
|
||||
super(offset);
|
||||
super(codeAddress);
|
||||
this.stg = stg;
|
||||
this.exceptionType = exceptionType;
|
||||
|
||||
tryStartLabel = labelCache.internLabel(new LabelMethodItem(startAddress, stg, "try_start_"));
|
||||
tryStartLabel.setUncommented();
|
||||
//use the offset from the last covered instruction, but make the label
|
||||
//use the address from the last covered instruction, but make the label
|
||||
//name refer to the address of the next instruction
|
||||
tryEndLabel = labelCache.internLabel(new EndTryLabelMethodItem(offset, stg, endAddress));
|
||||
tryEndLabel = labelCache.internLabel(new EndTryLabelMethodItem(codeAddress, stg, endAddress));
|
||||
tryEndLabel.setUncommented();
|
||||
|
||||
if (exceptionType == null) {
|
||||
|
@ -36,7 +36,7 @@ public class CommentedOutMethodItem extends MethodItem {
|
||||
private final MethodItem commentedOutMethodItem;
|
||||
|
||||
public CommentedOutMethodItem(StringTemplateGroup stg, MethodItem commentedOutMethodItem) {
|
||||
super(commentedOutMethodItem.getOffset());
|
||||
super(commentedOutMethodItem.getCodeAddress());
|
||||
this.stg = stg;
|
||||
this.commentedOutMethodItem = commentedOutMethodItem;
|
||||
}
|
||||
|
@ -36,8 +36,8 @@ public class DebugMethodItem extends MethodItem {
|
||||
private final String templateName;
|
||||
private final int sortOrder;
|
||||
|
||||
public DebugMethodItem(int offset, StringTemplateGroup stg, String templateName, int sortOrder) {
|
||||
super(offset);
|
||||
public DebugMethodItem(int codeAddress, StringTemplateGroup stg, String templateName, int sortOrder) {
|
||||
super(codeAddress);
|
||||
this.stg = stg;
|
||||
this.templateName = templateName;
|
||||
this.sortOrder = sortOrder;
|
||||
|
@ -31,11 +31,11 @@ package org.jf.baksmali.Adaptors;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
|
||||
public class EndTryLabelMethodItem extends LabelMethodItem {
|
||||
private int labelOffset;
|
||||
private int endTryAddress;
|
||||
|
||||
public EndTryLabelMethodItem(int offset, StringTemplateGroup stg, int labelOffset) {
|
||||
super(offset, stg, "try_end_");
|
||||
this.labelOffset = labelOffset;
|
||||
public EndTryLabelMethodItem(int codeAddress, StringTemplateGroup stg, int endTryAddress) {
|
||||
super(codeAddress, stg, "try_end_");
|
||||
this.endTryAddress = endTryAddress;
|
||||
}
|
||||
|
||||
public int getSortOrder() {
|
||||
@ -43,7 +43,7 @@ public class EndTryLabelMethodItem extends LabelMethodItem {
|
||||
return 101;
|
||||
}
|
||||
|
||||
public String getLabelOffset() {
|
||||
return Integer.toHexString(labelOffset);
|
||||
public String getLabelAddress() {
|
||||
return Integer.toHexString(endTryAddress);
|
||||
}
|
||||
}
|
||||
|
@ -36,9 +36,9 @@ import org.jf.dexlib.CodeItem;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class ArrayDataMethodItem extends InstructionFormatMethodItem<ArrayDataPseudoInstruction> {
|
||||
public ArrayDataMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public ArrayDataMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
ArrayDataPseudoInstruction instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.CodeItem;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
|
||||
public class Instruction10tMethodItem extends OffsetInstructionFormatMethodItem<Instruction10t> {
|
||||
public Instruction10tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
|
||||
public Instruction10tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int codeAddress,
|
||||
StringTemplateGroup stg, Instruction10t instruction) {
|
||||
super(labelCache, codeItem, offset, stg, instruction);
|
||||
super(labelCache, codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected String getLabelPrefix() {
|
||||
|
@ -34,8 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction10x;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction10xMethodItem extends InstructionFormatMethodItem<Instruction10x> {
|
||||
public Instruction10xMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, Instruction10x instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
public Instruction10xMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction10x instruction) {
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction11n;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction11nMethodItem extends InstructionFormatMethodItem<Instruction11n> {
|
||||
public Instruction11nMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction11nMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction11n instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction11x;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction11xMethodItem extends InstructionFormatMethodItem<Instruction11x> {
|
||||
public Instruction11xMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction11xMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction11x instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction12x;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction12xMethodItem extends InstructionFormatMethodItem<Instruction12x> {
|
||||
public Instruction12xMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction12xMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction12x instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.CodeItem;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
|
||||
public class Instruction20tMethodItem extends OffsetInstructionFormatMethodItem<Instruction20t> {
|
||||
public Instruction20tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
|
||||
public Instruction20tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int codeAddress,
|
||||
StringTemplateGroup stg, Instruction20t instruction) {
|
||||
super(labelCache, codeItem, offset, stg, instruction);
|
||||
super(labelCache, codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected String getLabelPrefix() {
|
||||
|
@ -35,9 +35,9 @@ import org.jf.dexlib.Code.Format.Instruction21c;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction21cMethodItem extends InstructionFormatMethodItem<Instruction21c> {
|
||||
public Instruction21cMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction21cMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction21c instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction21h;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction21hMethodItem extends InstructionFormatMethodItem<Instruction21h> {
|
||||
public Instruction21hMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction21hMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction21h instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction21s;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction21sMethodItem extends InstructionFormatMethodItem<Instruction21s> {
|
||||
public Instruction21sMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction21sMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction21s instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -35,9 +35,9 @@ import org.jf.dexlib.CodeItem;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
|
||||
public class Instruction21tMethodItem extends OffsetInstructionFormatMethodItem<Instruction21t> {
|
||||
public Instruction21tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
|
||||
public Instruction21tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int codeAddress,
|
||||
StringTemplateGroup stg, Instruction21t instruction) {
|
||||
super(labelCache, codeItem, offset, stg, instruction);
|
||||
super(labelCache, codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction22b;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction22bMethodItem extends InstructionFormatMethodItem<Instruction22b> {
|
||||
public Instruction22bMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction22bMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction22b instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -35,9 +35,9 @@ import org.jf.dexlib.Code.Format.Instruction22c;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction22cMethodItem extends InstructionFormatMethodItem<Instruction22c> {
|
||||
public Instruction22cMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction22cMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction22c instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
public class Instruction22csMethodItem extends InstructionFormatMethodItem<Instruction22cs> {
|
||||
public Instruction22csMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction22csMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction22cs instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -35,9 +35,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
public class Instruction22csfMethodItem extends InstructionFormatMethodItem<Instruction22csf> {
|
||||
public Instruction22csfMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction22csfMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction22csf instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction22s;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction22sMethodItem extends InstructionFormatMethodItem<Instruction22s> {
|
||||
public Instruction22sMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction22sMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction22s instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -35,9 +35,9 @@ import org.jf.dexlib.CodeItem;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
|
||||
public class Instruction22tMethodItem extends OffsetInstructionFormatMethodItem<Instruction22t> {
|
||||
public Instruction22tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
|
||||
public Instruction22tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int codeAddress,
|
||||
StringTemplateGroup stg, Instruction22t instruction) {
|
||||
super(labelCache, codeItem, offset, stg, instruction);
|
||||
super(labelCache, codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction22x;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction22xMethodItem extends InstructionFormatMethodItem<Instruction22x> {
|
||||
public Instruction22xMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction22xMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction22x instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction23x;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction23xMethodItem extends InstructionFormatMethodItem<Instruction23x> {
|
||||
public Instruction23xMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction23xMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction23x instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.CodeItem;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
|
||||
public class Instruction30tMethodItem extends OffsetInstructionFormatMethodItem<Instruction30t> {
|
||||
public Instruction30tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
|
||||
public Instruction30tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int codeAddress,
|
||||
StringTemplateGroup stg, Instruction30t instruction) {
|
||||
super(labelCache, codeItem, offset, stg, instruction);
|
||||
super(labelCache, codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected String getLabelPrefix() {
|
||||
|
@ -35,9 +35,9 @@ import org.jf.dexlib.Code.Format.Instruction31c;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction31cMethodItem extends InstructionFormatMethodItem<Instruction31c> {
|
||||
public Instruction31cMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction31cMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction31c instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction31i;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction31iMethodItem extends InstructionFormatMethodItem<Instruction31i> {
|
||||
public Instruction31iMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction31iMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction31i instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -36,9 +36,9 @@ import org.jf.dexlib.CodeItem;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
|
||||
public class Instruction31tMethodItem extends OffsetInstructionFormatMethodItem<Instruction31t> {
|
||||
public Instruction31tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
|
||||
public Instruction31tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int codeAddress,
|
||||
StringTemplateGroup stg, Instruction31t instruction) {
|
||||
super(labelCache, codeItem, offset, stg, instruction);
|
||||
super(labelCache, codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction32x;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction32xMethodItem extends InstructionFormatMethodItem<Instruction32x> {
|
||||
public Instruction32xMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction32xMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction32x instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -35,9 +35,9 @@ import org.jf.dexlib.Code.Format.Instruction35c;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction35cMethodItem extends InstructionFormatMethodItem<Instruction35c> {
|
||||
public Instruction35cMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction35cMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction35c instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -36,9 +36,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
public class Instruction35msMethodItem extends InstructionFormatMethodItem<Instruction35ms> {
|
||||
public Instruction35msMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction35msMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction35ms instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -35,9 +35,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
public class Instruction35msfMethodItem extends InstructionFormatMethodItem<Instruction35msf> {
|
||||
public Instruction35msfMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction35msfMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction35msf instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -35,9 +35,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
public class Instruction35sMethodItem extends InstructionFormatMethodItem<Instruction35s> {
|
||||
public Instruction35sMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction35sMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction35s instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -35,9 +35,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
public class Instruction35sfMethodItem extends InstructionFormatMethodItem<Instruction35sf> {
|
||||
public Instruction35sfMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction35sfMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction35sf instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -36,9 +36,9 @@ import org.jf.dexlib.Code.Format.Instruction3rc;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction3rcMethodItem extends InstructionFormatMethodItem<Instruction3rc> {
|
||||
public Instruction3rcMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction3rcMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction3rc instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -35,9 +35,9 @@ import org.jf.dexlib.CodeItem;
|
||||
import org.jf.baksmali.Adaptors.RegisterFormatter;
|
||||
|
||||
public class Instruction3rmsMethodItem extends InstructionFormatMethodItem<Instruction3rms> {
|
||||
public Instruction3rmsMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction3rmsMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction3rms instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -36,9 +36,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
public class Instruction3rmsfMethodItem extends InstructionFormatMethodItem<Instruction3rmsf> {
|
||||
public Instruction3rmsfMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction3rmsfMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction3rmsf instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction51l;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
public class Instruction51lMethodItem extends InstructionFormatMethodItem<Instruction51l> {
|
||||
public Instruction51lMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public Instruction51lMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
Instruction51l instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -41,8 +41,8 @@ public abstract class InstructionFormatMethodItem<T extends Instruction> extends
|
||||
protected final T instruction;
|
||||
|
||||
|
||||
public InstructionFormatMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, T instruction) {
|
||||
super(offset);
|
||||
public InstructionFormatMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg, T instruction) {
|
||||
super(codeAddress);
|
||||
this.codeItem = codeItem;
|
||||
this.stg = stg;
|
||||
this.instruction = instruction;
|
||||
|
@ -40,11 +40,11 @@ public abstract class OffsetInstructionFormatMethodItem<T extends Instruction &
|
||||
extends InstructionFormatMethodItem<T> {
|
||||
protected LabelMethodItem label;
|
||||
|
||||
public OffsetInstructionFormatMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
|
||||
public OffsetInstructionFormatMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int codeAddress,
|
||||
StringTemplateGroup stg, T instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
|
||||
label = new LabelMethodItem(offset + instruction.getOffset(), stg, getLabelPrefix());
|
||||
label = new LabelMethodItem(codeAddress + instruction.getTargetAddressOffset(), stg, getLabelPrefix());
|
||||
label = labelCache.internLabel(label);
|
||||
}
|
||||
|
||||
|
@ -43,15 +43,15 @@ public class PackedSwitchMethodItem extends InstructionFormatMethodItem<PackedSw
|
||||
implements Iterable<LabelMethodItem> {
|
||||
private List<LabelMethodItem> labels = new ArrayList<LabelMethodItem>();
|
||||
|
||||
public PackedSwitchMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
|
||||
public PackedSwitchMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int codeAddress,
|
||||
StringTemplateGroup stg, PackedSwitchDataPseudoInstruction instruction,
|
||||
int baseAddress) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
int baseCodeAddress) {
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
|
||||
Iterator<PackedSwitchDataPseudoInstruction.PackedSwitchTarget> iterator = instruction.iterateKeysAndTargets();
|
||||
while (iterator.hasNext()) {
|
||||
PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next();
|
||||
LabelMethodItem label = new LabelMethodItem(baseAddress + target.target, stg, "pswitch_");
|
||||
LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, stg, "pswitch_");
|
||||
label = labelCache.internLabel(label);
|
||||
labels.add(label);
|
||||
}
|
||||
|
@ -43,10 +43,10 @@ public class SparseSwitchMethodItem extends InstructionFormatMethodItem<SparseSw
|
||||
implements Iterable<LabelMethodItem> {
|
||||
private List<SparseSwitchTarget> targets = new ArrayList<SparseSwitchTarget>();
|
||||
|
||||
public SparseSwitchMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
|
||||
public SparseSwitchMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int targetAddressOffset,
|
||||
StringTemplateGroup stg, SparseSwitchDataPseudoInstruction instruction,
|
||||
int baseAddress) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, targetAddressOffset, stg, instruction);
|
||||
|
||||
|
||||
Iterator<SparseSwitchDataPseudoInstruction.SparseSwitchTarget> iterator = instruction.iterateKeysAndTargets();
|
||||
@ -55,7 +55,7 @@ public class SparseSwitchMethodItem extends InstructionFormatMethodItem<SparseSw
|
||||
SparseSwitchTarget sparseSwitchTarget = new SparseSwitchTarget();
|
||||
sparseSwitchTarget.Key = target.key;
|
||||
|
||||
LabelMethodItem label = new LabelMethodItem(baseAddress + target.target, stg, "sswitch_");
|
||||
LabelMethodItem label = new LabelMethodItem(baseAddress + target.targetAddressOffset, stg, "sswitch_");
|
||||
label = labelCache.internLabel(label);
|
||||
sparseSwitchTarget.Target = label;
|
||||
|
||||
|
@ -44,9 +44,9 @@ public class UnresolvedNullReferenceMethodItem extends InstructionFormatMethodIt
|
||||
this.isLastInstruction = isLastInstruction;
|
||||
}
|
||||
|
||||
public UnresolvedNullReferenceMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
|
||||
public UnresolvedNullReferenceMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
UnresolvedNullReference instruction) {
|
||||
super(codeItem, offset, stg, instruction);
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
|
@ -38,8 +38,8 @@ public class LabelMethodItem extends MethodItem {
|
||||
private int labelSequence;
|
||||
private boolean isCommentedOut = true;
|
||||
|
||||
public LabelMethodItem(int offset, StringTemplateGroup stg, String labelPrefix) {
|
||||
super(offset);
|
||||
public LabelMethodItem(int codeAddress, StringTemplateGroup stg, String labelPrefix) {
|
||||
super(codeAddress);
|
||||
this.stg = stg;
|
||||
this.labelPrefix = labelPrefix;
|
||||
}
|
||||
@ -69,7 +69,7 @@ public class LabelMethodItem extends MethodItem {
|
||||
|
||||
public int hashCode() {
|
||||
//force it to call equals when two labels are at the same address
|
||||
return getOffset();
|
||||
return getCodeAddress();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
@ -86,7 +86,7 @@ public class LabelMethodItem extends MethodItem {
|
||||
if (baksmali.useSequentialLabels) {
|
||||
template.setAttribute("Suffix", Integer.toHexString(labelSequence));
|
||||
} else {
|
||||
template.setAttribute("Suffix", getLabelOffset());
|
||||
template.setAttribute("Suffix", getLabelAddress());
|
||||
}
|
||||
return template.toString();
|
||||
}
|
||||
@ -95,8 +95,8 @@ public class LabelMethodItem extends MethodItem {
|
||||
return labelPrefix;
|
||||
}
|
||||
|
||||
public String getLabelOffset() {
|
||||
return getHexOffset();
|
||||
public String getLabelAddress() {
|
||||
return Integer.toHexString(this.getCodeAddress());
|
||||
}
|
||||
|
||||
public int getLabelSequence() {
|
||||
|
@ -40,10 +40,10 @@ public class LocalDebugMethodItem extends DebugMethodItem {
|
||||
private final String type;
|
||||
private final String signature;
|
||||
|
||||
public LocalDebugMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, String templateName,
|
||||
public LocalDebugMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg, String templateName,
|
||||
int sortOrder, int register, StringIdItem name, TypeIdItem type,
|
||||
StringIdItem signature) {
|
||||
super(offset, stg, templateName, sortOrder);
|
||||
super(codeAddress, stg, templateName, sortOrder);
|
||||
this.register = RegisterFormatter.formatRegister(codeItem, register);
|
||||
this.name = name==null?null:name.getStringValue();
|
||||
this.type = type==null?null:type.getTypeDescriptor();
|
||||
|
@ -206,25 +206,25 @@ public class MethodDefinition {
|
||||
if (baksmali.deodexUtil != null && dexFile.isOdex()) {
|
||||
List<Instruction> instructions = baksmali.deodexUtil.deodexerizeCode(codeItem);
|
||||
|
||||
int offset = 0;
|
||||
int currentCodeAddress = 0;
|
||||
for (Instruction instruction: instructions) {
|
||||
if (instruction.opcode == Opcode.PACKED_SWITCH) {
|
||||
Instruction31t ins = (Instruction31t)instruction;
|
||||
packedSwitchMap.put(offset + ins.getOffset(), offset);
|
||||
packedSwitchMap.put(currentCodeAddress + ins.getTargetAddressOffset(), currentCodeAddress);
|
||||
} else if (instruction.opcode == Opcode.SPARSE_SWITCH) {
|
||||
Instruction31t ins = (Instruction31t)instruction;
|
||||
sparseSwitchMap.put(offset + ins.getOffset(), offset);
|
||||
sparseSwitchMap.put(currentCodeAddress + ins.getTargetAddressOffset(), currentCodeAddress);
|
||||
}
|
||||
|
||||
offset += instruction.getSize(offset*2)/2;
|
||||
currentCodeAddress += instruction.getSize(currentCodeAddress);
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
currentCodeAddress = 0;
|
||||
for (Instruction instruction: instructions) {
|
||||
addMethodItemsForInstruction(offset, instruction, false);
|
||||
blanks.add(new BlankMethodItem(stg, offset));
|
||||
addMethodItemsForInstruction(currentCodeAddress, instruction, false);
|
||||
blanks.add(new BlankMethodItem(stg, currentCodeAddress));
|
||||
|
||||
offset += instruction.getSize(offset*2)/2;
|
||||
currentCodeAddress += instruction.getSize(currentCodeAddress);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -244,25 +244,24 @@ public class MethodDefinition {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int currentCodeOffset = 0;
|
||||
int currentCodeAddress = 0;
|
||||
for (Instruction instruction: codeItem.getInstructions()) {
|
||||
if (instruction.opcode == Opcode.PACKED_SWITCH) {
|
||||
OffsetInstruction offsetInstruction = (OffsetInstruction)instruction;
|
||||
packedSwitchMap.put(currentCodeOffset/2 + offsetInstruction.getOffset(), currentCodeOffset/2);
|
||||
packedSwitchMap.put(currentCodeAddress + offsetInstruction.getTargetAddressOffset(), currentCodeAddress);
|
||||
} else if (instruction.opcode == Opcode.SPARSE_SWITCH) {
|
||||
OffsetInstruction offsetInstruction = (OffsetInstruction)instruction;
|
||||
sparseSwitchMap.put(currentCodeOffset/2 + offsetInstruction.getOffset(), currentCodeOffset/2);
|
||||
sparseSwitchMap.put(currentCodeAddress + offsetInstruction.getTargetAddressOffset(), currentCodeAddress);
|
||||
}
|
||||
|
||||
currentCodeOffset += instruction.getSize(currentCodeOffset);
|
||||
currentCodeAddress += instruction.getSize(currentCodeAddress);
|
||||
}
|
||||
|
||||
currentCodeOffset = 0;
|
||||
currentCodeAddress = 0;
|
||||
for (Instruction instruction: codeItem.getInstructions()) {
|
||||
int offset = currentCodeOffset/2;
|
||||
addMethodItemsForInstruction(offset, instruction, false);
|
||||
blanks.add(new BlankMethodItem(stg, offset));
|
||||
currentCodeOffset += instruction.getSize(currentCodeOffset);
|
||||
addMethodItemsForInstruction(currentCodeAddress, instruction, false);
|
||||
blanks.add(new BlankMethodItem(stg, currentCodeAddress));
|
||||
currentCodeAddress += instruction.getSize(currentCodeAddress);
|
||||
}
|
||||
|
||||
}
|
||||
@ -298,182 +297,182 @@ public class MethodDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
private void addMethodItemsForInstruction(int offset, Instruction instruction, boolean commentedOut) {
|
||||
private void addMethodItemsForInstruction(int codeAddress, Instruction instruction, boolean commentedOut) {
|
||||
switch (instruction.getFormat()) {
|
||||
case Format10t:
|
||||
addOffsetInstructionMethodItem(
|
||||
new Instruction10tMethodItem(labels, codeItem, offset, stg,(Instruction10t)instruction),
|
||||
new Instruction10tMethodItem(labels, codeItem, codeAddress, stg,(Instruction10t)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format10x:
|
||||
addInstructionMethodItem(
|
||||
new Instruction10xMethodItem(codeItem, offset, stg, (Instruction10x)instruction),
|
||||
new Instruction10xMethodItem(codeItem, codeAddress, stg, (Instruction10x)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format11n:
|
||||
addInstructionMethodItem(
|
||||
new Instruction11nMethodItem(codeItem, offset, stg, (Instruction11n)instruction),
|
||||
new Instruction11nMethodItem(codeItem, codeAddress, stg, (Instruction11n)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format11x:
|
||||
addInstructionMethodItem(
|
||||
new Instruction11xMethodItem(codeItem, offset, stg, (Instruction11x)instruction),
|
||||
new Instruction11xMethodItem(codeItem, codeAddress, stg, (Instruction11x)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format12x:
|
||||
addInstructionMethodItem(
|
||||
new Instruction12xMethodItem(codeItem, offset, stg, (Instruction12x)instruction),
|
||||
new Instruction12xMethodItem(codeItem, codeAddress, stg, (Instruction12x)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format20t:
|
||||
addOffsetInstructionMethodItem(
|
||||
new Instruction20tMethodItem(labels, codeItem, offset, stg, (Instruction20t)instruction),
|
||||
new Instruction20tMethodItem(labels, codeItem, codeAddress, stg, (Instruction20t)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format21c:
|
||||
addInstructionMethodItem(
|
||||
new Instruction21cMethodItem(codeItem, offset, stg, (Instruction21c)instruction),
|
||||
new Instruction21cMethodItem(codeItem, codeAddress, stg, (Instruction21c)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format21h:
|
||||
addInstructionMethodItem(
|
||||
new Instruction21hMethodItem(codeItem, offset, stg, (Instruction21h)instruction),
|
||||
new Instruction21hMethodItem(codeItem, codeAddress, stg, (Instruction21h)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format21s:
|
||||
addInstructionMethodItem(
|
||||
new Instruction21sMethodItem(codeItem, offset, stg, (Instruction21s)instruction),
|
||||
new Instruction21sMethodItem(codeItem, codeAddress, stg, (Instruction21s)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format21t:
|
||||
addOffsetInstructionMethodItem(
|
||||
new Instruction21tMethodItem(labels, codeItem, offset, stg, (Instruction21t)instruction),
|
||||
new Instruction21tMethodItem(labels, codeItem, codeAddress, stg, (Instruction21t)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format22b:
|
||||
addInstructionMethodItem(
|
||||
new Instruction22bMethodItem(codeItem, offset, stg, (Instruction22b)instruction),
|
||||
new Instruction22bMethodItem(codeItem, codeAddress, stg, (Instruction22b)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format22c:
|
||||
addInstructionMethodItem(
|
||||
new Instruction22cMethodItem(codeItem, offset, stg, (Instruction22c)instruction),
|
||||
new Instruction22cMethodItem(codeItem, codeAddress, stg, (Instruction22c)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format22cs:
|
||||
addInstructionMethodItem(
|
||||
new Instruction22csMethodItem(codeItem, offset, stg, (Instruction22cs)instruction),
|
||||
new Instruction22csMethodItem(codeItem, codeAddress, stg, (Instruction22cs)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format22csf:
|
||||
addInstructionMethodItem(
|
||||
new Instruction22csfMethodItem(codeItem, offset, stg, (Instruction22csf)instruction),
|
||||
new Instruction22csfMethodItem(codeItem, codeAddress, stg, (Instruction22csf)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format22s:
|
||||
addInstructionMethodItem(
|
||||
new Instruction22sMethodItem(codeItem, offset, stg, (Instruction22s)instruction),
|
||||
new Instruction22sMethodItem(codeItem, codeAddress, stg, (Instruction22s)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format22t:
|
||||
addOffsetInstructionMethodItem(
|
||||
new Instruction22tMethodItem(labels, codeItem, offset, stg, (Instruction22t)instruction),
|
||||
new Instruction22tMethodItem(labels, codeItem, codeAddress, stg, (Instruction22t)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format22x:
|
||||
addInstructionMethodItem(
|
||||
new Instruction22xMethodItem(codeItem, offset, stg, (Instruction22x)instruction),
|
||||
new Instruction22xMethodItem(codeItem, codeAddress, stg, (Instruction22x)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format23x:
|
||||
addInstructionMethodItem(
|
||||
new Instruction23xMethodItem(codeItem, offset, stg, (Instruction23x)instruction),
|
||||
new Instruction23xMethodItem(codeItem, codeAddress, stg, (Instruction23x)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format30t:
|
||||
addOffsetInstructionMethodItem(
|
||||
new Instruction30tMethodItem(labels, codeItem, offset, stg, (Instruction30t)instruction),
|
||||
new Instruction30tMethodItem(labels, codeItem, codeAddress, stg, (Instruction30t)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format31c:
|
||||
addInstructionMethodItem(
|
||||
new Instruction31cMethodItem(codeItem, offset, stg, (Instruction31c)instruction),
|
||||
new Instruction31cMethodItem(codeItem, codeAddress, stg, (Instruction31c)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format31i:
|
||||
addInstructionMethodItem(
|
||||
new Instruction31iMethodItem(codeItem, offset, stg, (Instruction31i)instruction),
|
||||
new Instruction31iMethodItem(codeItem, codeAddress, stg, (Instruction31i)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format31t:
|
||||
addOffsetInstructionMethodItem(
|
||||
new Instruction31tMethodItem(labels, codeItem, offset, stg, (Instruction31t)instruction),
|
||||
new Instruction31tMethodItem(labels, codeItem, codeAddress, stg, (Instruction31t)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format32x:
|
||||
addInstructionMethodItem(
|
||||
new Instruction32xMethodItem(codeItem, offset, stg, (Instruction32x)instruction),
|
||||
new Instruction32xMethodItem(codeItem, codeAddress, stg, (Instruction32x)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format35c:
|
||||
addInstructionMethodItem(
|
||||
new Instruction35cMethodItem(codeItem, offset, stg, (Instruction35c)instruction),
|
||||
new Instruction35cMethodItem(codeItem, codeAddress, stg, (Instruction35c)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format35s:
|
||||
addInstructionMethodItem(
|
||||
new Instruction35sMethodItem(codeItem, offset, stg, (Instruction35s)instruction),
|
||||
new Instruction35sMethodItem(codeItem, codeAddress, stg, (Instruction35s)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format35sf:
|
||||
addInstructionMethodItem(
|
||||
new Instruction35sfMethodItem(codeItem, offset, stg, (Instruction35sf)instruction),
|
||||
new Instruction35sfMethodItem(codeItem, codeAddress, stg, (Instruction35sf)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format35ms:
|
||||
addInstructionMethodItem(
|
||||
new Instruction35msMethodItem(codeItem, offset, stg, (Instruction35ms)instruction),
|
||||
new Instruction35msMethodItem(codeItem, codeAddress, stg, (Instruction35ms)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format35msf:
|
||||
addInstructionMethodItem(
|
||||
new Instruction35msfMethodItem(codeItem, offset, stg, (Instruction35msf)instruction),
|
||||
new Instruction35msfMethodItem(codeItem, codeAddress, stg, (Instruction35msf)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format3rc:
|
||||
addInstructionMethodItem(
|
||||
new Instruction3rcMethodItem(codeItem, offset, stg, (Instruction3rc)instruction),
|
||||
new Instruction3rcMethodItem(codeItem, codeAddress, stg, (Instruction3rc)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format3rms:
|
||||
addInstructionMethodItem(
|
||||
new Instruction3rmsMethodItem(codeItem, offset, stg, (Instruction3rms)instruction),
|
||||
new Instruction3rmsMethodItem(codeItem, codeAddress, stg, (Instruction3rms)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format3rmsf:
|
||||
addInstructionMethodItem(
|
||||
new Instruction3rmsfMethodItem(codeItem, offset, stg, (Instruction3rmsf)instruction),
|
||||
new Instruction3rmsfMethodItem(codeItem, codeAddress, stg, (Instruction3rmsf)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case Format51l:
|
||||
addInstructionMethodItem(
|
||||
new Instruction51lMethodItem(codeItem, offset, stg, (Instruction51l)instruction),
|
||||
new Instruction51lMethodItem(codeItem, codeAddress, stg, (Instruction51l)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case ArrayData:
|
||||
addInstructionMethodItem(
|
||||
new ArrayDataMethodItem(codeItem, offset, stg, (ArrayDataPseudoInstruction)instruction),
|
||||
new ArrayDataMethodItem(codeItem, codeAddress, stg, (ArrayDataPseudoInstruction)instruction),
|
||||
commentedOut);
|
||||
return;
|
||||
case PackedSwitchData:
|
||||
{
|
||||
final Integer baseAddress = packedSwitchMap.get(offset);
|
||||
final Integer baseAddress = packedSwitchMap.get(codeAddress);
|
||||
|
||||
if (baseAddress != null) {
|
||||
PackedSwitchDataPseudoInstruction packedSwitchInstruction =
|
||||
(PackedSwitchDataPseudoInstruction)instruction;
|
||||
|
||||
PackedSwitchMethodItem packedSwitch = new PackedSwitchMethodItem(labels, codeItem, offset, stg,
|
||||
PackedSwitchMethodItem packedSwitch = new PackedSwitchMethodItem(labels, codeItem, codeAddress, stg,
|
||||
packedSwitchInstruction, baseAddress);
|
||||
addInstructionMethodItem(packedSwitch, commentedOut);
|
||||
|
||||
@ -487,13 +486,13 @@ public class MethodDefinition {
|
||||
}
|
||||
case SparseSwitchData:
|
||||
{
|
||||
final Integer baseAddress = sparseSwitchMap.get(offset);
|
||||
final Integer baseAddress = sparseSwitchMap.get(codeAddress);
|
||||
|
||||
if (baseAddress != null) {
|
||||
SparseSwitchDataPseudoInstruction sparseSwitchInstruction =
|
||||
(SparseSwitchDataPseudoInstruction)instruction;
|
||||
|
||||
SparseSwitchMethodItem sparseSwitch = new SparseSwitchMethodItem(labels, codeItem, offset, stg,
|
||||
SparseSwitchMethodItem sparseSwitch = new SparseSwitchMethodItem(labels, codeItem, codeAddress, stg,
|
||||
sparseSwitchInstruction, baseAddress);
|
||||
addInstructionMethodItem(sparseSwitch, commentedOut);
|
||||
|
||||
@ -507,16 +506,16 @@ public class MethodDefinition {
|
||||
}
|
||||
case UnresolvedNullReference:
|
||||
{
|
||||
addInstructionMethodItem(new UnresolvedNullReferenceMethodItem(codeItem, offset, stg,
|
||||
addInstructionMethodItem(new UnresolvedNullReferenceMethodItem(codeItem, codeAddress, stg,
|
||||
(UnresolvedNullReference)instruction), commentedOut);
|
||||
addMethodItemsForInstruction(offset, ((UnresolvedNullReference)instruction).OriginalInstruction,
|
||||
addMethodItemsForInstruction(codeAddress, ((UnresolvedNullReference)instruction).OriginalInstruction,
|
||||
true);
|
||||
return;
|
||||
}
|
||||
case DeadInstruction:
|
||||
{
|
||||
//TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh.
|
||||
addMethodItemsForInstruction(offset, ((DeadInstruction)instruction).OriginalInstruction, true);
|
||||
addMethodItemsForInstruction(codeAddress, ((DeadInstruction)instruction).OriginalInstruction, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -527,14 +526,14 @@ public class MethodDefinition {
|
||||
return;
|
||||
}
|
||||
for (CodeItem.TryItem tryItem: codeItem.getTries()) {
|
||||
int startAddress = tryItem.getStartAddress();
|
||||
int endAddress = tryItem.getStartAddress() + tryItem.getInstructionCount();
|
||||
int startAddress = tryItem.getStartCodeAddress();
|
||||
int endAddress = tryItem.getStartCodeAddress() + tryItem.getTryLength();
|
||||
|
||||
/**
|
||||
* The end address points to the address immediately after the end of the last
|
||||
* instruction that the try block covers. We want the .catch directive and end_try
|
||||
* label to be associated with the last covered instruction, so we need to get
|
||||
* the offset for that instruction
|
||||
* the address for that instruction
|
||||
*/
|
||||
int index = Collections.binarySearch(instructions, new BlankMethodItem(stg, endAddress));
|
||||
if (index < 0) {
|
||||
@ -546,7 +545,7 @@ public class MethodDefinition {
|
||||
//this try item ends at the next to last instruction.
|
||||
//otherwise, if the end address is past the address of the last instruction,
|
||||
//thin this try item ends at the last instruction
|
||||
if (instructions.get(instructions.size() - 1).getOffset() == endAddress) {
|
||||
if (instructions.get(instructions.size() - 1).getCodeAddress() == endAddress) {
|
||||
//get the address for the next to last instruction
|
||||
index -= 2;
|
||||
} else {
|
||||
@ -557,20 +556,20 @@ public class MethodDefinition {
|
||||
index -= 2;
|
||||
}
|
||||
|
||||
int lastInstructionOffset = instructions.get(index).getOffset();
|
||||
int lastInstructionAddress = instructions.get(index).getCodeAddress();
|
||||
|
||||
//add the catch all handler if it exists
|
||||
int catchAllAddress = tryItem.encodedCatchHandler.getCatchAllHandlerAddress();
|
||||
if (catchAllAddress != -1) {
|
||||
CatchMethodItem catchMethodItem = new CatchMethodItem(labels, lastInstructionOffset, stg, null,
|
||||
CatchMethodItem catchMethodItem = new CatchMethodItem(labels, lastInstructionAddress, stg, null,
|
||||
startAddress, endAddress, catchAllAddress);
|
||||
catches.add(catchMethodItem);
|
||||
}
|
||||
|
||||
//add the rest of the handlers
|
||||
for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) {
|
||||
//use the offset from the last covered instruction
|
||||
CatchMethodItem catchMethodItem = new CatchMethodItem(labels, lastInstructionOffset, stg,
|
||||
//use the address from the last covered instruction
|
||||
CatchMethodItem catchMethodItem = new CatchMethodItem(labels, lastInstructionAddress, stg,
|
||||
handler.exceptionType, startAddress, endAddress, handler.getHandlerAddress());
|
||||
catches.add(catchMethodItem);
|
||||
}
|
||||
|
@ -29,26 +29,21 @@
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
public abstract class MethodItem implements Comparable<MethodItem> {
|
||||
private int offset;
|
||||
private int codeAddress;
|
||||
|
||||
protected MethodItem(int offset) {
|
||||
this.offset = offset;
|
||||
protected MethodItem(int codeAddress) {
|
||||
this.codeAddress = codeAddress;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
public int getCodeAddress() {
|
||||
return codeAddress;
|
||||
}
|
||||
|
||||
public String getHexOffset() {
|
||||
return Integer.toHexString(offset);
|
||||
}
|
||||
|
||||
//return an arbitrary integer that determines how this item will be sorted with
|
||||
//others at the same offset
|
||||
//return an arbitrary integer that determines how this item will be sorted with others at the same address
|
||||
public abstract int getSortOrder();
|
||||
|
||||
public int compareTo(MethodItem methodItem) {
|
||||
int result = ((Integer)offset).compareTo(methodItem.offset);
|
||||
int result = ((Integer) codeAddress).compareTo(methodItem.codeAddress);
|
||||
|
||||
if (result == 0){
|
||||
return ((Integer)getSortOrder()).compareTo(methodItem.getSortOrder());
|
||||
|
@ -303,7 +303,7 @@ public class main {
|
||||
|
||||
Option sequentialLabelsOption = OptionBuilder.withLongOpt("sequential-labels")
|
||||
.withDescription("create label names using a sequential numbering scheme per label type, rather than " +
|
||||
"using the bytecode offset")
|
||||
"using the bytecode address")
|
||||
.create("q");
|
||||
|
||||
Option noDebugInfoOption = OptionBuilder.withLongOpt("no-debug-info")
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
package org.jf.dexlib;
|
||||
|
||||
import org.jf.dexlib.Util.ExceptionWithContext;
|
||||
import org.jf.dexlib.Util.Input;
|
||||
import org.jf.dexlib.Util.AnnotatedOutput;
|
||||
|
||||
@ -166,8 +167,8 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void readItem(Input in, ReadContext readContext) {
|
||||
classAnnotations = (AnnotationSetItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_ANNOTATION_SET_ITEM,
|
||||
in.readInt());
|
||||
classAnnotations = (AnnotationSetItem)readContext.getOptionalOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
|
||||
fieldAnnotationFields = new FieldIdItem[in.readInt()];
|
||||
fieldAnnotations = new AnnotationSetItem[fieldAnnotationFields.length];
|
||||
|
||||
@ -178,21 +179,36 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
|
||||
parameterAnnotations = new AnnotationSetRefList[parameterAnnotationMethods.length];
|
||||
|
||||
for (int i=0; i<fieldAnnotations.length; i++) {
|
||||
try {
|
||||
fieldAnnotationFields[i] = dexFile.FieldIdsSection.getItemByIndex(in.readInt());
|
||||
fieldAnnotations[i] = (AnnotationSetItem)readContext.getOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex,
|
||||
"Error occured while reading FieldAnnotation at index " + i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<methodAnnotations.length; i++) {
|
||||
try {
|
||||
methodAnnotationMethods[i] = dexFile.MethodIdsSection.getItemByIndex(in.readInt());
|
||||
methodAnnotations[i] = (AnnotationSetItem)readContext.getOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex,
|
||||
"Error occured while reading MethodAnnotation at index " + i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<parameterAnnotations.length; i++) {
|
||||
try {
|
||||
parameterAnnotationMethods[i] = dexFile.MethodIdsSection.getItemByIndex(in.readInt());
|
||||
parameterAnnotations[i] = (AnnotationSetRefList)readContext.getOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATION_SET_REF_LIST, in.readInt());
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex,
|
||||
"Error occured while reading ParameterAnnotation at index " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,14 +305,18 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */public ItemType getItemType() {
|
||||
/** {@inheritDoc} */
|
||||
public ItemType getItemType() {
|
||||
return ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getConciseIdentity() {
|
||||
if (parent == null) {
|
||||
return "annotation_directory_item @0x" + Integer.toHexString(getOffset());
|
||||
}
|
||||
return "annotation_directory_item @0x" + Integer.toHexString(getOffset()) + " (" + parent.getClassType() + ")";
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int compareTo(AnnotationDirectoryItem o) {
|
||||
@ -327,7 +347,13 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
|
||||
*/
|
||||
public void iterateFieldAnnotations(FieldAnnotationIteratorDelegate delegate) {
|
||||
for (int i=0; i<fieldAnnotationFields.length; i++) {
|
||||
try {
|
||||
delegate.processFieldAnnotations(fieldAnnotationFields[i], fieldAnnotations[i]);
|
||||
} catch (Exception ex) {
|
||||
throw addExceptionContext(ExceptionWithContext.withContext(ex,
|
||||
"Error occured while processing field annotations for field: " +
|
||||
fieldAnnotationFields[i].getFieldString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,7 +374,13 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
|
||||
*/
|
||||
public void iterateMethodAnnotations(MethodAnnotationIteratorDelegate delegate) {
|
||||
for (int i=0; i<methodAnnotationMethods.length; i++) {
|
||||
try {
|
||||
delegate.processMethodAnnotations(methodAnnotationMethods[i], methodAnnotations[i]);
|
||||
} catch (Exception ex) {
|
||||
throw addExceptionContext(ExceptionWithContext.withContext(ex,
|
||||
"Error occured while processing method annotations for method: " +
|
||||
methodAnnotationMethods[i].getMethodString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,7 +401,13 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
|
||||
*/
|
||||
public void iterateParameterAnnotations(ParameterAnnotationIteratorDelegate delegate) {
|
||||
for (int i=0; i<parameterAnnotationMethods.length; i++) {
|
||||
try {
|
||||
delegate.processParameterAnnotations(parameterAnnotationMethods[i], parameterAnnotations[i]);
|
||||
} catch (Exception ex) {
|
||||
throw addExceptionContext(ExceptionWithContext.withContext(ex,
|
||||
"Error occured while processing parameter annotations for method: " +
|
||||
parameterAnnotationMethods[i].getMethodString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ public class AnnotationSetRefList extends Item<AnnotationSetRefList> {
|
||||
annotationSets = new AnnotationSetItem[in.readInt()];
|
||||
|
||||
for (int i=0; i<annotationSets.length; i++) {
|
||||
annotationSets[i] = (AnnotationSetItem)readContext.getOffsettedItemByOffset(
|
||||
annotationSets[i] = (AnnotationSetItem)readContext.getOptionalOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,8 @@
|
||||
|
||||
package org.jf.dexlib;
|
||||
|
||||
import org.jf.dexlib.Util.ExceptionWithContext;
|
||||
|
||||
public enum AnnotationVisibility {
|
||||
BUILD((byte)0),
|
||||
RUNTIME((byte)1),
|
||||
@ -47,7 +49,7 @@ public enum AnnotationVisibility {
|
||||
case (byte)2:
|
||||
return SYSTEM;
|
||||
default:
|
||||
throw new RuntimeException("Invalid annotation visibility value " + value);
|
||||
throw new RuntimeException("Invalid annotation visibility value: " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,24 +122,40 @@ public class ClassDataItem extends Item<ClassDataItem> {
|
||||
|
||||
EncodedField previousEncodedField = null;
|
||||
for (int i=0; i<staticFields.length; i++) {
|
||||
try {
|
||||
staticFields[i] = previousEncodedField = new EncodedField(dexFile, in, previousEncodedField);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error while reading static field at index " + i);
|
||||
}
|
||||
}
|
||||
|
||||
previousEncodedField = null;
|
||||
for (int i=0; i<instanceFields.length; i++) {
|
||||
try {
|
||||
instanceFields[i] = previousEncodedField = new EncodedField(dexFile, in, previousEncodedField);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error while reading instance field at index " + i);
|
||||
}
|
||||
}
|
||||
|
||||
EncodedMethod previousEncodedMethod = null;
|
||||
for (int i=0; i<directMethods.length; i++) {
|
||||
try {
|
||||
directMethods[i] = previousEncodedMethod = new EncodedMethod(dexFile, readContext, in,
|
||||
previousEncodedMethod);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error while reading direct method at index " + i);
|
||||
}
|
||||
}
|
||||
|
||||
previousEncodedMethod = null;
|
||||
for (int i=0; i<virtualMethods.length; i++) {
|
||||
try {
|
||||
virtualMethods[i] = previousEncodedMethod = new EncodedMethod(dexFile, readContext, in,
|
||||
previousEncodedMethod);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error while reading virtual method at index " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,8 +287,11 @@ public class ClassDataItem extends Item<ClassDataItem> {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getConciseIdentity() {
|
||||
if (parent == null) {
|
||||
return "class_data_item @0x" + Integer.toHexString(getOffset());
|
||||
}
|
||||
return "class_data_item @0x" + Integer.toHexString(getOffset()) + " (" + parent.getClassType() +")";
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int compareTo(ClassDataItem other) {
|
||||
@ -459,7 +478,8 @@ public class ClassDataItem extends Item<ClassDataItem> {
|
||||
int previousIndex = previousEncodedMethod==null?0:previousEncodedMethod.method.getIndex();
|
||||
method = dexFile.MethodIdsSection.getItemByIndex(in.readUnsignedLeb128() + previousIndex);
|
||||
accessFlags = in.readUnsignedLeb128();
|
||||
codeItem = (CodeItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_CODE_ITEM, in.readUnsignedLeb128());
|
||||
codeItem = (CodeItem)readContext.getOptionalOffsettedItemByOffset(ItemType.TYPE_CODE_ITEM,
|
||||
in.readUnsignedLeb128());
|
||||
if (codeItem != null) {
|
||||
codeItem.setParent(this);
|
||||
}
|
||||
@ -480,7 +500,7 @@ public class ClassDataItem extends Item<ClassDataItem> {
|
||||
out.annotate("access_flags: " + AccessFlags.formatAccessFlagsForMethod(accessFlags));
|
||||
out.writeUnsignedLeb128(accessFlags);
|
||||
if (codeItem != null) {
|
||||
out.annotate("code_off: 0x" + codeItem.getOffset());
|
||||
out.annotate("code_off: 0x" + Integer.toHexString(codeItem.getOffset()));
|
||||
out.writeUnsignedLeb128(codeItem.getOffset());
|
||||
} else {
|
||||
out.annotate("code_off: 0x0");
|
||||
|
@ -76,6 +76,7 @@ public class ClassDefItem extends Item<ClassDefItem> {
|
||||
AnnotationDirectoryItem annotations, ClassDataItem classData,
|
||||
EncodedArrayItem staticFieldInitializers) {
|
||||
super(dexFile);
|
||||
assert classType != null;
|
||||
this.classType = classType;
|
||||
this.accessFlags = accessFlags;
|
||||
this.superType = superType;
|
||||
@ -131,14 +132,14 @@ public class ClassDefItem extends Item<ClassDefItem> {
|
||||
protected void readItem(Input in, ReadContext readContext) {
|
||||
classType = dexFile.TypeIdsSection.getItemByIndex(in.readInt());
|
||||
accessFlags = in.readInt();
|
||||
superType = dexFile.TypeIdsSection.getItemByIndex(in.readInt());
|
||||
implementedInterfaces = (TypeListItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_TYPE_LIST,
|
||||
superType = dexFile.TypeIdsSection.getOptionalItemByIndex(in.readInt());
|
||||
implementedInterfaces = (TypeListItem)readContext.getOptionalOffsettedItemByOffset(ItemType.TYPE_TYPE_LIST,
|
||||
in.readInt());
|
||||
sourceFile = dexFile.StringIdsSection.getItemByIndex(in.readInt());
|
||||
annotations = (AnnotationDirectoryItem)readContext.getOffsettedItemByOffset(
|
||||
sourceFile = dexFile.StringIdsSection.getOptionalItemByIndex(in.readInt());
|
||||
annotations = (AnnotationDirectoryItem)readContext.getOptionalOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM, in.readInt());
|
||||
classData = (ClassDataItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_CLASS_DATA_ITEM, in.readInt());
|
||||
staticFieldInitializers = (EncodedArrayItem)readContext.getOffsettedItemByOffset(
|
||||
classData = (ClassDataItem)readContext.getOptionalOffsettedItemByOffset(ItemType.TYPE_CLASS_DATA_ITEM, in.readInt());
|
||||
staticFieldInitializers = (EncodedArrayItem)readContext.getOptionalOffsettedItemByOffset(
|
||||
ItemType.TYPE_ENCODED_ARRAY_ITEM, in.readInt());
|
||||
|
||||
if (classData != null) {
|
||||
|
@ -41,10 +41,8 @@ public class ArrayDataPseudoInstruction extends Instruction {
|
||||
private byte[] encodedValues;
|
||||
|
||||
@Override
|
||||
public int getSize(int offset) {
|
||||
assert offset % 2 == 0;
|
||||
int size = getElementWidth() * getElementCount();
|
||||
return size + (size & 0x01) + 8 + (offset % 4);
|
||||
public int getSize(int codeAddress) {
|
||||
return ((encodedValues.length + 1)/2) + 4 + (codeAddress % 2);
|
||||
}
|
||||
|
||||
public ArrayDataPseudoInstruction(int elementWidth, byte[] encodedValues) {
|
||||
@ -77,11 +75,8 @@ public class ArrayDataPseudoInstruction extends Instruction {
|
||||
System.arraycopy(buffer, bufferIndex+8, encodedValues, 0, elementCount * elementWidth);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
//write out padding, if necessary
|
||||
if (out.getCursor() % 4 != 0) {
|
||||
out.writeShort(0);
|
||||
}
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.alignTo(4);
|
||||
|
||||
int elementCount = encodedValues.length / elementWidth;
|
||||
|
||||
@ -90,14 +85,13 @@ public class ArrayDataPseudoInstruction extends Instruction {
|
||||
out.writeShort(elementWidth);
|
||||
out.writeInt(elementCount);
|
||||
out.write(encodedValues);
|
||||
if ((encodedValues.length % 2) != 0) {
|
||||
//must write out an even number of bytes
|
||||
out.writeByte(0);
|
||||
}
|
||||
|
||||
//make sure we're written out an even number of bytes
|
||||
out.alignTo(2);
|
||||
}
|
||||
|
||||
protected void annotateInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
out.annotate(getSize(currentCodeOffset), "[0x" + Integer.toHexString(currentCodeOffset/2) + "] " +
|
||||
protected void annotateInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.annotate(getSize(currentCodeAddress)*2, "[0x" + Integer.toHexString(currentCodeAddress) + "] " +
|
||||
"fill-array-data instruction");
|
||||
}
|
||||
|
||||
@ -149,7 +143,7 @@ public class ArrayDataPseudoInstruction extends Instruction {
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
if (opcode != Opcode.NOP) {
|
||||
throw new RuntimeException("The opcode for an ArrayDataPseudoInstruction must by NOP");
|
||||
throw new RuntimeException("The opcode for an ArrayDataPseudoInstruction must be NOP");
|
||||
}
|
||||
return new ArrayDataPseudoInstruction(buffer, bufferIndex);
|
||||
}
|
||||
|
@ -39,13 +39,13 @@ public class DeadInstruction extends Instruction {
|
||||
this.OriginalInstruction = originalInstruction;
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
//don't write anything
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize(int offset) {
|
||||
return OriginalInstruction.getSize(offset);
|
||||
public int getSize(int codeAddress) {
|
||||
return OriginalInstruction.getSize(codeAddress);
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
|
@ -36,17 +36,17 @@ import org.jf.dexlib.Util.AnnotatedOutput;
|
||||
|
||||
public class Instruction10t extends Instruction implements OffsetInstruction {
|
||||
public static final InstructionFactory Factory = new Factory();
|
||||
private int offset;
|
||||
private int targetAddressOffset;
|
||||
|
||||
public Instruction10t(Opcode opcode, int offA) {
|
||||
super(opcode);
|
||||
this.offset = offA;
|
||||
this.targetAddressOffset = offA;
|
||||
|
||||
if (offset == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
|
||||
if (targetAddressOffset == 0) {
|
||||
throw new RuntimeException("The address offset cannot be 0. Use goto/32 instead.");
|
||||
}
|
||||
|
||||
//allow out of range offsets here, so we have the option of replacing this instruction
|
||||
//allow out of range address offsets here, so we have the option of replacing this instruction
|
||||
//with goto/16 or goto/32 later
|
||||
}
|
||||
|
||||
@ -55,33 +55,33 @@ public class Instruction10t extends Instruction implements OffsetInstruction {
|
||||
|
||||
assert buffer[bufferIndex] == opcode.value;
|
||||
|
||||
this.offset = buffer[bufferIndex + 1];
|
||||
assert offset != 0;
|
||||
this.targetAddressOffset = buffer[bufferIndex + 1];
|
||||
assert targetAddressOffset != 0;
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
if (offset == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead");
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
if (targetAddressOffset == 0) {
|
||||
throw new RuntimeException("The address offset cannot be 0. Use goto/32 instead");
|
||||
}
|
||||
|
||||
if (offset < -128 || offset > 127) {
|
||||
throw new RuntimeException("The offset is out of range. It must be in [-128,-1] or [1, 127]");
|
||||
if (targetAddressOffset < -128 || targetAddressOffset > 127) {
|
||||
throw new RuntimeException("The address offset is out of range. It must be in [-128,-1] or [1, 127]");
|
||||
}
|
||||
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(offset);
|
||||
out.writeByte(targetAddressOffset);
|
||||
}
|
||||
|
||||
public void updateOffset(int offset) {
|
||||
this.offset = offset;
|
||||
public void updateTargetAddressOffset(int targetAddressOffset) {
|
||||
this.targetAddressOffset = targetAddressOffset;
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format10t;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
public int getTargetAddressOffset() {
|
||||
return targetAddressOffset;
|
||||
}
|
||||
|
||||
private static class Factory implements InstructionFactory {
|
||||
|
@ -47,7 +47,7 @@ public class Instruction10x extends Instruction {
|
||||
assert buffer[bufferIndex + 1] == 0x00;
|
||||
}
|
||||
|
||||
public void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
public void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(0);
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ public class Instruction11n extends Instruction implements SingleRegisterInstruc
|
||||
this.litB = NumberUtils.decodeHighSignedNibble(buffer[bufferIndex + 1]);
|
||||
}
|
||||
|
||||
public void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
public void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte((litB << 4) | regA);
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ public class Instruction11x extends Instruction implements SingleRegisterInstruc
|
||||
this.regA = (byte)NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
|
||||
}
|
||||
|
||||
public void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
public void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(regA);
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ public class Instruction12x extends Instruction implements TwoRegisterInstructio
|
||||
this.regB = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
|
||||
}
|
||||
|
||||
public void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
public void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte((regB << 4) | regA);
|
||||
}
|
||||
|
@ -37,17 +37,17 @@ import org.jf.dexlib.Util.NumberUtils;
|
||||
|
||||
public class Instruction20t extends Instruction implements OffsetInstruction {
|
||||
public static final InstructionFactory Factory = new Factory();
|
||||
private int offset;
|
||||
private int targetAddressOffset;
|
||||
|
||||
public Instruction20t(Opcode opcode, int offA) {
|
||||
super(opcode);
|
||||
this.offset = offA;
|
||||
this.targetAddressOffset = offA;
|
||||
|
||||
if (offset == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
|
||||
if (targetAddressOffset == 0) {
|
||||
throw new RuntimeException("The address offset cannot be 0. Use goto/32 instead.");
|
||||
}
|
||||
|
||||
//allow out of range offsets here, so we have the option of replacing this instruction
|
||||
//allow out of range address offsets here, so we have the option of replacing this instruction
|
||||
//with goto/16 or goto/32 later
|
||||
}
|
||||
|
||||
@ -56,34 +56,34 @@ public class Instruction20t extends Instruction implements OffsetInstruction {
|
||||
|
||||
assert buffer[bufferIndex] == opcode.value;
|
||||
|
||||
this.offset = NumberUtils.decodeShort(buffer, bufferIndex+2);
|
||||
assert offset != 0;
|
||||
this.targetAddressOffset = NumberUtils.decodeShort(buffer, bufferIndex+2);
|
||||
assert targetAddressOffset != 0;
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
if (offset == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead");
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
if (targetAddressOffset == 0) {
|
||||
throw new RuntimeException("The address offset cannot be 0. Use goto/32 instead");
|
||||
}
|
||||
|
||||
if (offset < -32768 || offset > 32767) {
|
||||
throw new RuntimeException("The offset is out of range. It must be in [-32768,-1] or [1, 32768]");
|
||||
if (targetAddressOffset < -32768 || targetAddressOffset > 32767) {
|
||||
throw new RuntimeException("The address offset is out of range. It must be in [-32768,-1] or [1, 32768]");
|
||||
}
|
||||
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(0x00);
|
||||
out.writeShort(offset);
|
||||
out.writeShort(targetAddressOffset);
|
||||
}
|
||||
|
||||
public void updateOffset(int offset) {
|
||||
this.offset = offset;
|
||||
public void updateTargetAddressOffset(int targetAddressOffset) {
|
||||
this.targetAddressOffset = targetAddressOffset;
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format20t;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
public int getTargetAddressOffset() {
|
||||
return targetAddressOffset;
|
||||
}
|
||||
|
||||
private static class Factory implements InstructionFactory {
|
||||
|
@ -68,7 +68,7 @@ public class Instruction21c extends InstructionWithReference implements SingleRe
|
||||
this.regA = buffer[bufferIndex + 1];
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
if(opcode == Opcode.CONST_STRING && getReferencedItem().getIndex() > 0xFFFF) {
|
||||
throw new RuntimeException("String offset is too large for const-string. Use string-const/jumbo instead.");
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public class Instruction21h extends Instruction implements SingleRegisterInstruc
|
||||
this.litB = NumberUtils.decodeShort(buffer, bufferIndex + 2);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(regA);
|
||||
out.writeShort(litB);
|
||||
|
@ -59,7 +59,7 @@ public class Instruction21s extends Instruction implements SingleRegisterInstruc
|
||||
this.litB = NumberUtils.decodeShort(buffer, bufferIndex + 2);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(regA);
|
||||
out.writeShort(litB);
|
||||
|
@ -36,7 +36,7 @@ import org.jf.dexlib.Util.AnnotatedOutput;
|
||||
public class Instruction21t extends Instruction implements OffsetInstruction, SingleRegisterInstruction {
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
private byte regA;
|
||||
private short offset;
|
||||
private short targetAddressOffset;
|
||||
|
||||
public Instruction21t(Opcode opcode, short regA, short offB) {
|
||||
super(opcode);
|
||||
@ -46,11 +46,11 @@ public class Instruction21t extends Instruction implements OffsetInstruction, Si
|
||||
}
|
||||
|
||||
if (offB == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0.");
|
||||
throw new RuntimeException("The address offset cannot be 0.");
|
||||
}
|
||||
|
||||
this.regA = (byte)regA;
|
||||
this.offset = offB;
|
||||
this.targetAddressOffset = offB;
|
||||
}
|
||||
|
||||
private Instruction21t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
@ -59,24 +59,25 @@ public class Instruction21t extends Instruction implements OffsetInstruction, Si
|
||||
assert buffer[bufferIndex] == opcode.value;
|
||||
|
||||
regA = buffer[bufferIndex + 1];
|
||||
offset = NumberUtils.decodeShort(buffer, bufferIndex + 2);
|
||||
assert offset != 0;
|
||||
targetAddressOffset = NumberUtils.decodeShort(buffer, bufferIndex + 2);
|
||||
assert targetAddressOffset != 0;
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(regA);
|
||||
out.writeShort(offset);
|
||||
out.writeShort(targetAddressOffset);
|
||||
}
|
||||
|
||||
public void updateOffset(int offset) {
|
||||
if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
|
||||
throw new RuntimeException("The offset " + offset + " is out of range. It must be in [-32768, 32767]");
|
||||
public void updateTargetAddressOffset(int targetAddressOffset) {
|
||||
if (targetAddressOffset < Short.MIN_VALUE || targetAddressOffset > Short.MAX_VALUE) {
|
||||
throw new RuntimeException("The address offset " + targetAddressOffset +
|
||||
" is out of range. It must be in [-32768, 32767]");
|
||||
}
|
||||
if (offset == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0");
|
||||
if (targetAddressOffset == 0) {
|
||||
throw new RuntimeException("The address offset cannot be 0");
|
||||
}
|
||||
this.offset = (short)offset;
|
||||
this.targetAddressOffset = (short) targetAddressOffset;
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
@ -87,8 +88,8 @@ public class Instruction21t extends Instruction implements OffsetInstruction, Si
|
||||
return regA & 0xFF;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
public int getTargetAddressOffset() {
|
||||
return targetAddressOffset;
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
|
@ -62,7 +62,7 @@ public class Instruction22b extends Instruction implements TwoRegisterInstructio
|
||||
this.litC = buffer[bufferIndex + 3];
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(regA);
|
||||
out.writeByte(regB);
|
||||
|
@ -61,7 +61,7 @@ public class Instruction22c extends InstructionWithReference implements TwoRegis
|
||||
this.regB = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte((regB << 4) | regA);
|
||||
out.writeShort(getReferencedItem().getIndex());
|
||||
|
@ -66,7 +66,7 @@ public class Instruction22cs extends Instruction implements TwoRegisterInstructi
|
||||
this.fieldOffset = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte((regB << 4) | regA);
|
||||
out.writeShort(fieldOffset);
|
||||
|
@ -43,7 +43,7 @@ public class Instruction22csf extends InstructionWithReference implements TwoReg
|
||||
this.unfixedInstruction = unfixedInstruction;
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
byte regA = (byte)getRegisterA();
|
||||
byte regB = (byte)getRegisterB();
|
||||
|
||||
|
@ -63,7 +63,7 @@ public class Instruction22s extends Instruction implements TwoRegisterInstructio
|
||||
this.litC = NumberUtils.decodeShort(buffer, bufferIndex + 2);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte((regB << 4) | regA);
|
||||
out.writeShort(litC);
|
||||
|
@ -40,7 +40,7 @@ public class Instruction22t extends Instruction implements OffsetInstruction, Tw
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
private byte regA;
|
||||
private byte regB;
|
||||
private short offset;
|
||||
private short targetAddressOffset;
|
||||
|
||||
public Instruction22t(Opcode opcode, byte regA, byte regB, short offC) {
|
||||
super(opcode);
|
||||
@ -51,12 +51,12 @@ public class Instruction22t extends Instruction implements OffsetInstruction, Tw
|
||||
}
|
||||
|
||||
if (offC == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0.");
|
||||
throw new RuntimeException("The address offset cannot be 0.");
|
||||
}
|
||||
|
||||
this.regA = regA;
|
||||
this.regB = regB;
|
||||
this.offset = offC;
|
||||
this.targetAddressOffset = offC;
|
||||
}
|
||||
|
||||
private Instruction22t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
@ -66,25 +66,26 @@ public class Instruction22t extends Instruction implements OffsetInstruction, Tw
|
||||
|
||||
regA = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
|
||||
regB = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
|
||||
offset = NumberUtils.decodeShort(buffer, bufferIndex + 2);
|
||||
targetAddressOffset = NumberUtils.decodeShort(buffer, bufferIndex + 2);
|
||||
|
||||
assert offset != 0;
|
||||
assert targetAddressOffset != 0;
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte((regB << 4) | regA);
|
||||
out.writeShort(offset);
|
||||
out.writeShort(targetAddressOffset);
|
||||
}
|
||||
|
||||
public void updateOffset(int offset) {
|
||||
if (offset < -32768 || offset > 32767) {
|
||||
throw new RuntimeException("The offset " + offset + " is out of range. It must be in [-32768, 32767]");
|
||||
public void updateTargetAddressOffset(int targetAddressOffset) {
|
||||
if (targetAddressOffset < -32768 || targetAddressOffset > 32767) {
|
||||
throw new RuntimeException("The address offset " + targetAddressOffset +
|
||||
" is out of range. It must be in [-32768, 32767]");
|
||||
}
|
||||
if (offset == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0");
|
||||
if (targetAddressOffset == 0) {
|
||||
throw new RuntimeException("The address offset cannot be 0");
|
||||
}
|
||||
this.offset = (short)offset;
|
||||
this.targetAddressOffset = (short)targetAddressOffset;
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
@ -99,8 +100,8 @@ public class Instruction22t extends Instruction implements OffsetInstruction, Tw
|
||||
return regB;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
public int getTargetAddressOffset() {
|
||||
return targetAddressOffset;
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
|
@ -62,7 +62,7 @@ public class Instruction22x extends Instruction implements TwoRegisterInstructio
|
||||
this.regB = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(regA);
|
||||
out.writeShort(regB);
|
||||
|
@ -62,7 +62,7 @@ public class Instruction23x extends Instruction implements ThreeRegisterInstruct
|
||||
this.regC = buffer[bufferIndex + 3];
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(regA);
|
||||
out.writeByte(regB);
|
||||
|
@ -37,11 +37,11 @@ import org.jf.dexlib.Util.NumberUtils;
|
||||
|
||||
public class Instruction30t extends Instruction implements OffsetInstruction {
|
||||
public static final InstructionFactory Factory = new Factory();
|
||||
private int offset;
|
||||
private int targetAddressOffset;
|
||||
|
||||
public Instruction30t(Opcode opcode, int offA) {
|
||||
super(opcode);
|
||||
this.offset = offA;
|
||||
this.targetAddressOffset = offA;
|
||||
}
|
||||
|
||||
private Instruction30t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
@ -49,25 +49,25 @@ public class Instruction30t extends Instruction implements OffsetInstruction {
|
||||
|
||||
assert buffer[bufferIndex] == opcode.value;
|
||||
|
||||
this.offset = NumberUtils.decodeInt(buffer, bufferIndex+2);
|
||||
this.targetAddressOffset = NumberUtils.decodeInt(buffer, bufferIndex+2);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(0x00);
|
||||
out.writeInt(offset);
|
||||
out.writeInt(targetAddressOffset);
|
||||
}
|
||||
|
||||
public void updateOffset(int offset) {
|
||||
this.offset = offset;
|
||||
public void updateTargetAddressOffset(int targetAddressOffset) {
|
||||
this.targetAddressOffset = targetAddressOffset;
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format30t;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
public int getTargetAddressOffset() {
|
||||
return targetAddressOffset;
|
||||
}
|
||||
|
||||
private static class Factory implements InstructionFactory {
|
||||
|
@ -57,7 +57,7 @@ public class Instruction31c extends InstructionWithReference implements SingleRe
|
||||
this.regA = buffer[bufferIndex + 1];
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(regA);
|
||||
out.writeInt(getReferencedItem().getIndex());
|
||||
|
@ -59,7 +59,7 @@ public class Instruction31i extends Instruction implements SingleRegisterInstruc
|
||||
this.litB = NumberUtils.decodeInt(buffer, bufferIndex + 2);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(regA);
|
||||
out.writeInt(litB);
|
||||
|
@ -39,7 +39,7 @@ import org.jf.dexlib.Util.AnnotatedOutput;
|
||||
public class Instruction31t extends Instruction implements OffsetInstruction, SingleRegisterInstruction {
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
private byte regA;
|
||||
private int offset;
|
||||
private int targetAddressOffset;
|
||||
|
||||
public Instruction31t(Opcode opcode, short regA, int offB) {
|
||||
super(opcode);
|
||||
@ -49,24 +49,25 @@ public class Instruction31t extends Instruction implements OffsetInstruction, Si
|
||||
}
|
||||
|
||||
this.regA = (byte)regA;
|
||||
this.offset = offB;
|
||||
this.targetAddressOffset = offB;
|
||||
}
|
||||
|
||||
private Instruction31t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
super(opcode);
|
||||
|
||||
this.regA = buffer[bufferIndex + 1];
|
||||
this.offset = NumberUtils.decodeInt(buffer, bufferIndex + 2);
|
||||
this.targetAddressOffset = NumberUtils.decodeInt(buffer, bufferIndex + 2);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(regA);
|
||||
out.writeInt(offset + (((currentCodeOffset/2) + offset) % 2));
|
||||
//align the address offset so that the absolute address is aligned on a 4-byte boundary (2 code block boundary)
|
||||
out.writeInt(targetAddressOffset + ((currentCodeAddress + targetAddressOffset) % 2));
|
||||
}
|
||||
|
||||
public void updateOffset(int offset) {
|
||||
this.offset = offset;
|
||||
public void updateTargetAddressOffset(int targetAddressOffset) {
|
||||
this.targetAddressOffset = targetAddressOffset;
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
@ -77,8 +78,8 @@ public class Instruction31t extends Instruction implements OffsetInstruction, Si
|
||||
return regA & 0xFF;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
public int getTargetAddressOffset() {
|
||||
return targetAddressOffset;
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
|
@ -59,7 +59,7 @@ public class Instruction32x extends Instruction implements TwoRegisterInstructio
|
||||
this.regB = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(0);
|
||||
out.writeShort(regA);
|
||||
|
@ -92,7 +92,7 @@ public class Instruction35c extends InstructionWithReference implements FiveRegi
|
||||
checkItem(opcode, getReferencedItem(), getRegCount());
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte((regCount << 4) | regA);
|
||||
out.writeShort(getReferencedItem().getIndex());
|
||||
|
@ -86,7 +86,7 @@ public class Instruction35ms extends Instruction implements FiveRegisterInstruct
|
||||
this.methodIndex = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte((regCount << 4) | regA);
|
||||
out.writeShort(methodIndex);
|
||||
|
@ -43,7 +43,7 @@ public class Instruction35msf extends InstructionWithReference implements FiveRe
|
||||
this.unfixedInstruction = unfixedInstruction;
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
byte regA = getRegisterA();
|
||||
byte regCount = getRegCount();
|
||||
byte regD = getRegisterD();
|
||||
|
@ -92,7 +92,7 @@ public class Instruction35s extends InstructionWithReference implements FiveRegi
|
||||
this.regG = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 5]);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte((regCount << 4) | regA);
|
||||
out.writeShort(getReferencedItem().getIndex());
|
||||
|
@ -41,7 +41,7 @@ public class Instruction35sf extends InstructionWithReference implements FiveReg
|
||||
this.unfixedInstruction = unfixedInstruction;
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
byte regA = getRegisterA();
|
||||
byte regCount = getRegCount();
|
||||
byte regD = getRegisterD();
|
||||
|
@ -78,7 +78,7 @@ public class Instruction3rc extends InstructionWithReference implements Register
|
||||
checkItem(opcode, getReferencedItem(), getRegCount());
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(regCount);
|
||||
out.writeShort(this.getReferencedItem().getIndex());
|
||||
|
@ -75,7 +75,7 @@ public class Instruction3rms extends Instruction implements RegisterRangeInstruc
|
||||
this.startReg = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(regCount);
|
||||
out.writeShort(methodIndex);
|
||||
|
@ -43,7 +43,7 @@ public class Instruction3rmsf extends InstructionWithReference implements Regist
|
||||
this.unfixedInstruction = unfixedInstruction;
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
short regCount = getRegCount();
|
||||
int startReg = getStartRegister();
|
||||
|
||||
|
@ -59,7 +59,7 @@ public class Instruction51l extends Instruction implements SingleRegisterInstruc
|
||||
litB = NumberUtils.decodeLong(buffer, bufferIndex + 2);
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(regA);
|
||||
out.writeLong(litB);
|
||||
|
@ -43,9 +43,8 @@ public class PackedSwitchDataPseudoInstruction extends Instruction implements Mu
|
||||
private int[] targets;
|
||||
|
||||
@Override
|
||||
public int getSize(int offset) {
|
||||
assert offset % 2 == 0;
|
||||
return getTargetCount() * 4 + 8 + (offset % 4);
|
||||
public int getSize(int codeAddress) {
|
||||
return getTargetCount() * 2 + 4 + (codeAddress % 2);
|
||||
}
|
||||
|
||||
public PackedSwitchDataPseudoInstruction(int firstKey, int[] targets) {
|
||||
@ -81,11 +80,8 @@ public class PackedSwitchDataPseudoInstruction extends Instruction implements Mu
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
//write out padding, if necessary
|
||||
if (currentCodeOffset % 4 != 0) {
|
||||
out.writeShort(0);
|
||||
}
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.alignTo(4);
|
||||
|
||||
out.writeByte(0x00);
|
||||
out.writeByte(0x01);
|
||||
@ -97,13 +93,13 @@ public class PackedSwitchDataPseudoInstruction extends Instruction implements Mu
|
||||
}
|
||||
}
|
||||
|
||||
protected void annotateInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
out.annotate(getSize(currentCodeOffset), "[0x" + Integer.toHexString(currentCodeOffset/2) + "] " +
|
||||
protected void annotateInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.annotate(getSize(currentCodeAddress)*2, "[0x" + Integer.toHexString(currentCodeAddress) + "] " +
|
||||
"packed-switch-data instruction");
|
||||
}
|
||||
|
||||
public void updateTarget(int targetIndex, int targetOffset) {
|
||||
targets[targetIndex] = targetOffset;
|
||||
public void updateTarget(int targetIndex, int targetAddressOffset) {
|
||||
targets[targetIndex] = targetAddressOffset;
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
@ -124,7 +120,7 @@ public class PackedSwitchDataPseudoInstruction extends Instruction implements Mu
|
||||
|
||||
public static class PackedSwitchTarget {
|
||||
public int value;
|
||||
public int target;
|
||||
public int targetAddressOffset;
|
||||
}
|
||||
|
||||
public Iterator<PackedSwitchTarget> iterateKeysAndTargets() {
|
||||
@ -141,7 +137,7 @@ public class PackedSwitchDataPseudoInstruction extends Instruction implements Mu
|
||||
|
||||
public PackedSwitchTarget next() {
|
||||
packedSwitchTarget.value = value++;
|
||||
packedSwitchTarget.target = targets[i];
|
||||
packedSwitchTarget.targetAddressOffset = targets[i];
|
||||
i++;
|
||||
return packedSwitchTarget;
|
||||
}
|
||||
@ -151,14 +147,10 @@ public class PackedSwitchDataPseudoInstruction extends Instruction implements Mu
|
||||
};
|
||||
}
|
||||
|
||||
public static interface PackedSwitchTargetIteratorDelegate {
|
||||
void ProcessPackedSwitchTarget(int value, int target);
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
if (opcode != Opcode.NOP) {
|
||||
throw new RuntimeException("The opcode for a PackedSwitchDataPseudoInstruction must by NOP");
|
||||
throw new RuntimeException("The opcode for a PackedSwitchDataPseudoInstruction must be NOP");
|
||||
}
|
||||
return new PackedSwitchDataPseudoInstruction(buffer, bufferIndex);
|
||||
}
|
||||
|
@ -43,16 +43,15 @@ public class SparseSwitchDataPseudoInstruction extends Instruction implements Mu
|
||||
private int[] targets;
|
||||
|
||||
@Override
|
||||
public int getSize(int offset) {
|
||||
assert offset % 2 == 0;
|
||||
return getTargetCount() * 8 + 4 + (offset % 4);
|
||||
public int getSize(int codeAddress) {
|
||||
return getTargetCount() * 4 + 2 + (codeAddress % 2);
|
||||
}
|
||||
|
||||
public SparseSwitchDataPseudoInstruction(int[] keys, int[] targets) {
|
||||
super(Opcode.NOP);
|
||||
|
||||
if (keys.length != targets.length) {
|
||||
throw new RuntimeException("The number of keys and offsets don't match");
|
||||
throw new RuntimeException("The number of keys and targets don't match");
|
||||
}
|
||||
|
||||
if (targets.length == 0) {
|
||||
@ -90,11 +89,8 @@ public class SparseSwitchDataPseudoInstruction extends Instruction implements Mu
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
//write out padding, if necessary
|
||||
if (currentCodeOffset % 4 != 0) {
|
||||
out.writeShort(0);
|
||||
}
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.alignTo(4);
|
||||
|
||||
out.writeByte(0x00);
|
||||
out.writeByte(0x02);
|
||||
@ -117,13 +113,13 @@ public class SparseSwitchDataPseudoInstruction extends Instruction implements Mu
|
||||
}
|
||||
}
|
||||
|
||||
protected void annotateInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
out.annotate(getSize(currentCodeOffset), "[0x" + Integer.toHexString(currentCodeOffset/2) + "] " +
|
||||
protected void annotateInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.annotate(getSize(currentCodeAddress)*2, "[0x" + Integer.toHexString(currentCodeAddress) + "] " +
|
||||
"sparse-switch-data instruction");
|
||||
}
|
||||
|
||||
public void updateTarget(int targetIndex, int targetOffset) {
|
||||
targets[targetIndex] = targetOffset;
|
||||
public void updateTarget(int targetIndex, int targetAddressOffset) {
|
||||
targets[targetIndex] = targetAddressOffset;
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
@ -144,7 +140,7 @@ public class SparseSwitchDataPseudoInstruction extends Instruction implements Mu
|
||||
|
||||
public static class SparseSwitchTarget {
|
||||
public int key;
|
||||
public int target;
|
||||
public int targetAddressOffset;
|
||||
}
|
||||
|
||||
public Iterator<SparseSwitchTarget> iterateKeysAndTargets() {
|
||||
@ -160,7 +156,7 @@ public class SparseSwitchDataPseudoInstruction extends Instruction implements Mu
|
||||
|
||||
public SparseSwitchTarget next() {
|
||||
sparseSwitchTarget.key = keys[i];
|
||||
sparseSwitchTarget.target = targets[i];
|
||||
sparseSwitchTarget.targetAddressOffset = targets[i];
|
||||
i++;
|
||||
return sparseSwitchTarget;
|
||||
}
|
||||
@ -173,7 +169,7 @@ public class SparseSwitchDataPseudoInstruction extends Instruction implements Mu
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
if (opcode != Opcode.NOP) {
|
||||
throw new RuntimeException("The opcode for a SparseSwitchDataPseudoInstruction must by NOP");
|
||||
throw new RuntimeException("The opcode for a SparseSwitchDataPseudoInstruction must be NOP");
|
||||
}
|
||||
return new SparseSwitchDataPseudoInstruction(buffer, bufferIndex);
|
||||
}
|
||||
|
@ -47,13 +47,13 @@ public class UnresolvedNullReference extends Instruction {
|
||||
this.ObjectRegisterNum = objectRegisterNumber;
|
||||
}
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
throw new RuntimeException("Cannot rewrite an instruction that couldn't be deodexed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize(int offset) {
|
||||
return OriginalInstruction.getSize(offset);
|
||||
public int getSize(int codeAddress) {
|
||||
return OriginalInstruction.getSize(codeAddress);
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
|
@ -29,15 +29,19 @@
|
||||
package org.jf.dexlib.Code;
|
||||
|
||||
import org.jf.dexlib.*;
|
||||
import org.jf.dexlib.Util.ByteArrayInput;
|
||||
import org.jf.dexlib.Util.AnnotatedOutput;
|
||||
import org.jf.dexlib.Code.Format.Format;
|
||||
|
||||
public abstract class Instruction {
|
||||
public final Opcode opcode;
|
||||
|
||||
public int getSize(int offset) {
|
||||
return opcode.format.size;
|
||||
/**
|
||||
* Returns the size of this instruction in code blocks, assuming the instruction is located at the given address
|
||||
* @param codeAddress the code address where the instruction is located
|
||||
* @return The size of this instruction in code blocks
|
||||
**/
|
||||
public int getSize(int codeAddress) {
|
||||
return opcode.format.size/2;
|
||||
}
|
||||
|
||||
protected Instruction(Opcode opcode) {
|
||||
@ -46,20 +50,20 @@ public abstract class Instruction {
|
||||
|
||||
public abstract Format getFormat();
|
||||
|
||||
public int write(AnnotatedOutput out, int currentCodeOffset) {
|
||||
public int write(AnnotatedOutput out, int currentCodeAddress) {
|
||||
if (out.annotates()) {
|
||||
annotateInstruction(out, currentCodeOffset);
|
||||
annotateInstruction(out, currentCodeAddress);
|
||||
}
|
||||
writeInstruction(out, currentCodeOffset);
|
||||
return currentCodeOffset + getSize(currentCodeOffset);
|
||||
writeInstruction(out, currentCodeAddress);
|
||||
return currentCodeAddress + getSize(currentCodeAddress);
|
||||
}
|
||||
|
||||
protected void annotateInstruction(AnnotatedOutput out, int currentCodeOffset) {
|
||||
out.annotate(getSize(currentCodeOffset), "[0x" + Integer.toHexString(currentCodeOffset/2) + "] " +
|
||||
protected void annotateInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
out.annotate(getSize(currentCodeAddress)*2, "[0x" + Integer.toHexString(currentCodeAddress) + "] " +
|
||||
opcode.name + " instruction");
|
||||
}
|
||||
|
||||
protected abstract void writeInstruction(AnnotatedOutput out, int currentCodeOffset);
|
||||
protected abstract void writeInstruction(AnnotatedOutput out, int currentCodeAddress);
|
||||
|
||||
public static interface InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex);
|
||||
|
@ -28,177 +28,65 @@
|
||||
|
||||
package org.jf.dexlib.Code;
|
||||
|
||||
import org.jf.dexlib.Util.ExceptionWithContext;
|
||||
import org.jf.dexlib.Util.Hex;
|
||||
import org.jf.dexlib.Util.NumberUtils;
|
||||
import org.jf.dexlib.Code.Format.*;
|
||||
import org.jf.dexlib.DexFile;
|
||||
|
||||
public class InstructionIterator {
|
||||
/**
|
||||
* This method partially decodes the instructions in the given byte array and iterates over them, calling
|
||||
* the appropriate ProcessRawInstructionDelegate method for each instruction
|
||||
* @param insns a byte array containing the instructions
|
||||
* @param processRawInstruction a <code>ProcessInstructionDelegate</code> object containing the methods
|
||||
* that get called for each instruction that is encountered
|
||||
*/
|
||||
public static void IterateInstructions(byte[] insns, ProcessRawInstructionDelegate processRawInstruction) {
|
||||
public static void IterateInstructions(DexFile dexFile, byte[] insns, ProcessInstructionDelegate delegate) {
|
||||
int insnsPosition = 0;
|
||||
|
||||
while (insnsPosition < insns.length) {
|
||||
try
|
||||
{
|
||||
Opcode opcode = Opcode.getOpcodeByValue(insns[insnsPosition]);
|
||||
|
||||
Instruction instruction = null;
|
||||
|
||||
if (opcode == null) {
|
||||
throw new RuntimeException("Unknown opcode: " + Hex.u1(insns[insnsPosition]));
|
||||
}
|
||||
|
||||
if (opcode.referenceType == ReferenceType.none) {
|
||||
byte secondByte = insns[insnsPosition+1];
|
||||
//if this is one of the "special" opcodes
|
||||
if (opcode == Opcode.NOP && secondByte > 0) {
|
||||
switch (secondByte) {
|
||||
case 1:
|
||||
{
|
||||
//packed-switch
|
||||
int size = NumberUtils.decodeUnsignedShort(insns[insnsPosition+2], insns[insnsPosition+3]);
|
||||
int end = insnsPosition + size * 4 + 8;
|
||||
processRawInstruction.ProcessPackedSwitchInstruction(insnsPosition, size, end-insnsPosition);
|
||||
insnsPosition = end;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
//sparse-switch
|
||||
int size = NumberUtils.decodeUnsignedShort(insns[insnsPosition+2], insns[insnsPosition+3]);
|
||||
int end = insnsPosition + size * 8 + 4;
|
||||
processRawInstruction.ProcessSparseSwitchInstruction(insnsPosition, size, end-insnsPosition);
|
||||
insnsPosition = end;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
//fill-array-data
|
||||
int elementWidth = NumberUtils.decodeUnsignedShort(insns[insnsPosition+2],
|
||||
insns[insnsPosition+3]);
|
||||
int size = NumberUtils.decodeInt(insns[insnsPosition+4], insns[insnsPosition+5],
|
||||
insns[insnsPosition+6], insns[insnsPosition+7]);
|
||||
int end = insnsPosition + (size * elementWidth) + 8;
|
||||
if (end % 2 == 1) {
|
||||
end++;
|
||||
}
|
||||
processRawInstruction.ProcessFillArrayDataInstruction(insnsPosition, elementWidth, size,
|
||||
end-insnsPosition);
|
||||
insnsPosition = end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
processRawInstruction.ProcessNormalInstruction(opcode, insnsPosition);
|
||||
insnsPosition += opcode.format.size;
|
||||
}
|
||||
} else {
|
||||
processRawInstruction.ProcessReferenceInstruction(opcode, insnsPosition);
|
||||
insnsPosition += opcode.format.size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void IterateInstructions(DexFile dexFile, byte[] insns, ProcessInstructionDelegate delegate) {
|
||||
int currentCodeOffset = 0;
|
||||
|
||||
while (currentCodeOffset < insns.length) {
|
||||
Opcode opcode = Opcode.getOpcodeByValue(insns[currentCodeOffset]);
|
||||
|
||||
Instruction instruction = null;
|
||||
|
||||
if (opcode == null) {
|
||||
throw new RuntimeException("Unknown opcode: " + Hex.u1(insns[currentCodeOffset]));
|
||||
}
|
||||
|
||||
if (opcode == Opcode.NOP) {
|
||||
byte secondByte = insns[currentCodeOffset+1];
|
||||
byte secondByte = insns[insnsPosition + 1];
|
||||
switch (secondByte) {
|
||||
case 0:
|
||||
{
|
||||
instruction = new Instruction10x(Opcode.NOP, insns, currentCodeOffset);
|
||||
instruction = new Instruction10x(Opcode.NOP, insns, insnsPosition);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
instruction = new PackedSwitchDataPseudoInstruction(insns, currentCodeOffset);
|
||||
instruction = new PackedSwitchDataPseudoInstruction(insns, insnsPosition);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
instruction = new SparseSwitchDataPseudoInstruction(insns, currentCodeOffset);
|
||||
instruction = new SparseSwitchDataPseudoInstruction(insns, insnsPosition);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
instruction = new ArrayDataPseudoInstruction(insns, currentCodeOffset);
|
||||
instruction = new ArrayDataPseudoInstruction(insns, insnsPosition);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
instruction = opcode.format.Factory.makeInstruction(dexFile, opcode, insns, currentCodeOffset);
|
||||
instruction = opcode.format.Factory.makeInstruction(dexFile, opcode, insns, insnsPosition);
|
||||
}
|
||||
|
||||
assert instruction != null;
|
||||
|
||||
delegate.ProcessInstruction(currentCodeOffset, instruction);
|
||||
currentCodeOffset += instruction.getSize(currentCodeOffset);
|
||||
delegate.ProcessInstruction(insnsPosition/2, instruction);
|
||||
insnsPosition += instruction.getSize(insnsPosition/2)*2;
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error occured at code address " + insnsPosition * 2);
|
||||
}
|
||||
}
|
||||
|
||||
public static interface ProcessRawInstructionDelegate {
|
||||
/**
|
||||
* The <code>InstructionIterator</code> calls this method when a "normal" instruction is encountered. I.e.
|
||||
* not a special or reference instruction
|
||||
* @param opcode the opcode of the instruction that was encountered
|
||||
* @param index the start index of the instruction in the byte array that the
|
||||
* <code>InstructionIterator</code> is iterating
|
||||
*/
|
||||
public void ProcessNormalInstruction(Opcode opcode, int index);
|
||||
|
||||
/**
|
||||
* The <code>InstructionIterator</code> calls this method when a "reference" instruction is encountered.
|
||||
* I.e. an instruction that contains an index that is a reference to a string, method, type or field.
|
||||
* @param opcode the opcode of the instruction that was encountered
|
||||
* @param index the start index of the instruction in the byte array that the
|
||||
* <code>InstructionIterator</code> is iterating
|
||||
*/
|
||||
public void ProcessReferenceInstruction(Opcode opcode, int index);
|
||||
|
||||
/**
|
||||
* The <code>InstructionIterator</code> calls this method when a packed switch instruction is encountered.
|
||||
* @param index the start index of the instruction in the byte array that the
|
||||
* <code>InstructionIterator</code> is iterating
|
||||
* @param targetCount the number of targets that this packed switch structure contains
|
||||
* @param instructionLength the length of this instruction in bytes
|
||||
*/
|
||||
public void ProcessPackedSwitchInstruction(int index, int targetCount, int instructionLength);
|
||||
|
||||
/**
|
||||
* The <code>InstructionIterator</code> calls this method when a sparse switch instruction is encountered.
|
||||
* @param index the start index of the instruction in the byte array that the
|
||||
* <code>InstructionIterator</code> is iterating
|
||||
* @param targetCount the number of targets that this sparse switch structure contains
|
||||
* @param instructionLength the length of this instruction in bytes
|
||||
*/
|
||||
public void ProcessSparseSwitchInstruction(int index, int targetCount, int instructionLength);
|
||||
|
||||
/**
|
||||
* The <code>InstructionIterator</code> calls this method when a fill-array-data instruction is encountered.
|
||||
* @param index the start index of the instruction in the byte array that the
|
||||
* <code>InstructionIterator</code> is iterating
|
||||
* @param elementWidth the width of the elements contained in this fill-array-data structure
|
||||
* @param elementCount the number of elements contained in this fill-array-data structure
|
||||
* @param instructionLength the length of this instruction in bytes
|
||||
*/
|
||||
public void ProcessFillArrayDataInstruction(int index, int elementWidth, int elementCount,
|
||||
int instructionLength);
|
||||
}
|
||||
|
||||
public static interface ProcessInstructionDelegate {
|
||||
public void ProcessInstruction(int index, Instruction instruction);
|
||||
public void ProcessInstruction(int codeAddress, Instruction instruction);
|
||||
}
|
||||
}
|
||||
|
@ -30,5 +30,5 @@ package org.jf.dexlib.Code;
|
||||
|
||||
public interface MultiOffsetInstruction {
|
||||
public int[] getTargets();
|
||||
public void updateTarget(int targetIndex, int targetOffset);
|
||||
public void updateTarget(int targetIndex, int targetAddressOffset);
|
||||
}
|
||||
|
@ -29,6 +29,6 @@
|
||||
package org.jf.dexlib.Code;
|
||||
|
||||
public interface OffsetInstruction {
|
||||
public int getOffset();
|
||||
public void updateOffset(int offset);
|
||||
public int getTargetAddressOffset();
|
||||
public void updateTargetAddressOffset(int targetAddressOffset);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import org.jf.dexlib.Code.Format.Instruction20t;
|
||||
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.Debug.DebugOpcode;
|
||||
import org.jf.dexlib.Util.*;
|
||||
import org.jf.dexlib.Debug.DebugInstructionIterator;
|
||||
|
||||
@ -142,7 +143,7 @@ public class CodeItem extends Item<CodeItem> {
|
||||
this.inWords = in.readShort();
|
||||
this.outWords = in.readShort();
|
||||
int triesCount = in.readShort();
|
||||
this.debugInfo = (DebugInfoItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_DEBUG_INFO_ITEM,
|
||||
this.debugInfo = (DebugInfoItem)readContext.getOptionalOffsettedItemByOffset(ItemType.TYPE_DEBUG_INFO_ITEM,
|
||||
in.readInt());
|
||||
if (this.debugInfo != null) {
|
||||
this.debugInfo.setParent(this);
|
||||
@ -154,7 +155,7 @@ public class CodeItem extends Item<CodeItem> {
|
||||
byte[] encodedInstructions = in.readBytes(instructionCount * 2);
|
||||
InstructionIterator.IterateInstructions(dexFile, encodedInstructions,
|
||||
new InstructionIterator.ProcessInstructionDelegate() {
|
||||
public void ProcessInstruction(int index, Instruction instruction) {
|
||||
public void ProcessInstruction(int codeAddress, Instruction instruction) {
|
||||
instructionList.add(instruction);
|
||||
}
|
||||
});
|
||||
@ -175,9 +176,13 @@ public class CodeItem extends Item<CodeItem> {
|
||||
SparseArray<EncodedCatchHandler> handlerMap = new SparseArray<EncodedCatchHandler>(handlerCount);
|
||||
encodedCatchHandlers = new EncodedCatchHandler[handlerCount];
|
||||
for (int i=0; i<handlerCount; i++) {
|
||||
try {
|
||||
int position = in.getCursor() - encodedHandlerStart;
|
||||
encodedCatchHandlers[i] = new EncodedCatchHandler(dexFile, in);
|
||||
handlerMap.append(position, encodedCatchHandlers[i]);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error while reading EncodedCatchHandler at index " + i);
|
||||
}
|
||||
}
|
||||
int codeItemEnd = in.getCursor();
|
||||
|
||||
@ -185,7 +190,11 @@ public class CodeItem extends Item<CodeItem> {
|
||||
in.setCursor(triesOffset);
|
||||
tries = new TryItem[triesCount];
|
||||
for (int i=0; i<triesCount; i++) {
|
||||
try {
|
||||
tries[i] = new TryItem(in, handlerMap);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error while reading TryItem at index " + i);
|
||||
}
|
||||
}
|
||||
|
||||
//and now back to the end of the code item
|
||||
@ -195,12 +204,10 @@ public class CodeItem extends Item<CodeItem> {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected int placeItem(int offset) {
|
||||
offset += 16 + getInstructionsLength();
|
||||
offset += 16 + getInstructionsLength() * 2;
|
||||
|
||||
if (tries != null && tries.length > 0) {
|
||||
if (offset % 4 != 0) {
|
||||
offset+=2;
|
||||
}
|
||||
offset = AlignmentUtils.alignOffset(offset, 4);
|
||||
|
||||
offset += tries.length * 8;
|
||||
int encodedCatchHandlerBaseOffset = offset;
|
||||
@ -214,7 +221,7 @@ public class CodeItem extends Item<CodeItem> {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void writeItem(final AnnotatedOutput out) {
|
||||
int instructionsLength = getInstructionsLength()/2;
|
||||
int instructionsLength = getInstructionsLength();
|
||||
|
||||
if (out.annotates()) {
|
||||
out.annotate(0, parent.method.getMethodString());
|
||||
@ -246,21 +253,16 @@ public class CodeItem extends Item<CodeItem> {
|
||||
out.writeInt(debugInfo.getOffset());
|
||||
}
|
||||
|
||||
int currentCodeOffset = 0;
|
||||
for (Instruction instruction: instructions) {
|
||||
currentCodeOffset += instruction.getSize(currentCodeOffset);
|
||||
}
|
||||
|
||||
out.writeInt(instructionsLength);
|
||||
|
||||
currentCodeOffset = 0;
|
||||
int currentCodeAddress = 0;
|
||||
for (Instruction instruction: instructions) {
|
||||
currentCodeOffset = instruction.write(out, currentCodeOffset);
|
||||
currentCodeAddress = instruction.write(out, currentCodeAddress);
|
||||
}
|
||||
|
||||
if (tries != null && tries.length > 0) {
|
||||
if (out.annotates()) {
|
||||
if ((currentCodeOffset % 4) != 0) {
|
||||
if ((currentCodeAddress % 2) != 0) {
|
||||
out.annotate("padding");
|
||||
out.writeShort(0);
|
||||
}
|
||||
@ -285,7 +287,7 @@ public class CodeItem extends Item<CodeItem> {
|
||||
out.deindent();
|
||||
}
|
||||
} else {
|
||||
if ((currentCodeOffset % 4) != 0) {
|
||||
if ((currentCodeAddress % 2) != 0) {
|
||||
out.writeShort(0);
|
||||
}
|
||||
|
||||
@ -309,8 +311,11 @@ public class CodeItem extends Item<CodeItem> {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getConciseIdentity() {
|
||||
if (this.parent == null) {
|
||||
return "code_item @0x" + Integer.toHexString(getOffset());
|
||||
}
|
||||
return "code_item @0x" + Integer.toHexString(getOffset()) + " (" + parent.method.getMethodString() + ")";
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int compareTo(CodeItem other) {
|
||||
@ -385,12 +390,15 @@ public class CodeItem extends Item<CodeItem> {
|
||||
this.instructions = newInstructions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The length of the instructions in this CodeItem, in 2-byte code blocks
|
||||
*/
|
||||
private int getInstructionsLength() {
|
||||
int offset = 0;
|
||||
int currentCodeAddress = 0;
|
||||
for (Instruction instruction: instructions) {
|
||||
offset += instruction.getSize(offset);
|
||||
currentCodeAddress += instruction.getSize(currentCodeAddress);
|
||||
}
|
||||
return offset;
|
||||
return currentCodeAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -403,46 +411,52 @@ public class CodeItem extends Item<CodeItem> {
|
||||
* The above fixes are applied iteratively, until no more fixes have been performed
|
||||
*/
|
||||
public void fixInstructions(boolean fixStringConst, boolean fixGoto) {
|
||||
try {
|
||||
boolean didSomething = false;
|
||||
|
||||
do
|
||||
{
|
||||
didSomething = false;
|
||||
|
||||
int currentCodeOffset = 0;
|
||||
int currentCodeAddress = 0;
|
||||
for (int i=0; i<instructions.length; i++) {
|
||||
Instruction instruction = instructions[i];
|
||||
|
||||
try {
|
||||
if (fixGoto && instruction.opcode == Opcode.GOTO) {
|
||||
int offset = ((OffsetInstruction)instruction).getOffset();
|
||||
int codeAddress = ((OffsetInstruction)instruction).getTargetAddressOffset();
|
||||
|
||||
if (((byte)offset) != offset) {
|
||||
//the offset doesn't fit within a byte, we need to upgrade to a goto/16 or goto/32
|
||||
if (((byte) codeAddress) != codeAddress) {
|
||||
//the address doesn't fit within a byte, we need to upgrade to a goto/16 or goto/32
|
||||
|
||||
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));
|
||||
if ((short) codeAddress == codeAddress) {
|
||||
//the address fits in a short, so upgrade to a goto/16
|
||||
replaceInstructionAtAddress(currentCodeAddress,
|
||||
new Instruction20t(Opcode.GOTO_16, codeAddress));
|
||||
}
|
||||
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));
|
||||
//The address won't fit into a short, we have to upgrade to a goto/32
|
||||
replaceInstructionAtAddress(currentCodeAddress,
|
||||
new Instruction30t(Opcode.GOTO_32, codeAddress));
|
||||
}
|
||||
didSomething = true;
|
||||
break;
|
||||
}
|
||||
} else if (fixGoto && instruction.opcode == Opcode.GOTO_16) {
|
||||
int offset = ((OffsetInstruction)instruction).getOffset();
|
||||
int codeAddress = ((OffsetInstruction)instruction).getTargetAddressOffset();
|
||||
|
||||
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));
|
||||
if (((short) codeAddress) != codeAddress) {
|
||||
//the address doesn't fit within a short, we need to upgrade to a goto/32
|
||||
replaceInstructionAtAddress(currentCodeAddress,
|
||||
new Instruction30t(Opcode.GOTO_32, codeAddress));
|
||||
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,
|
||||
replaceInstructionAtAddress(currentCodeAddress,
|
||||
new Instruction31c(Opcode.CONST_STRING_JUMBO,
|
||||
(short)constStringInstruction.getRegisterA(),
|
||||
constStringInstruction.getReferencedItem()));
|
||||
didSomething = true;
|
||||
@ -450,24 +464,31 @@ public class CodeItem extends Item<CodeItem> {
|
||||
}
|
||||
}
|
||||
|
||||
currentCodeOffset += instruction.getSize(currentCodeOffset);
|
||||
currentCodeAddress += instruction.getSize(currentCodeAddress);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error while attempting to fix " +
|
||||
instruction.opcode.name + " instruction at address " + currentCodeAddress);
|
||||
}
|
||||
}
|
||||
}while(didSomething);
|
||||
} catch (Exception ex) {
|
||||
throw this.addExceptionContext(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void replaceInstructionAtOffset(int offset, Instruction replacementInstruction) {
|
||||
private void replaceInstructionAtAddress(int codeAddress, Instruction replacementInstruction) {
|
||||
Instruction originalInstruction = null;
|
||||
|
||||
int[] originalInstructionOffsets = new int[instructions.length+1];
|
||||
SparseIntArray originalSwitchOffsetByOriginalSwitchDataOffset = new SparseIntArray();
|
||||
int[] originalInstructionCodeAddresses = new int[instructions.length+1];
|
||||
SparseIntArray originalSwitchAddressByOriginalSwitchDataAddress = new SparseIntArray();
|
||||
|
||||
int currentCodeOffset = 0;
|
||||
int currentCodeAddress = 0;
|
||||
int instructionIndex = 0;
|
||||
int i;
|
||||
for (i=0; i<instructions.length; i++) {
|
||||
Instruction instruction = instructions[i];
|
||||
|
||||
if (currentCodeOffset == offset) {
|
||||
if (currentCodeAddress == codeAddress) {
|
||||
originalInstruction = instruction;
|
||||
instructionIndex = i;
|
||||
}
|
||||
@ -475,97 +496,100 @@ public class CodeItem extends Item<CodeItem> {
|
||||
if (instruction.opcode == Opcode.PACKED_SWITCH || instruction.opcode == Opcode.SPARSE_SWITCH) {
|
||||
OffsetInstruction offsetInstruction = (OffsetInstruction)instruction;
|
||||
|
||||
int switchDataOffset = currentCodeOffset + offsetInstruction.getOffset() * 2;
|
||||
if (originalSwitchOffsetByOriginalSwitchDataOffset.indexOfKey(switchDataOffset) < 0) {
|
||||
originalSwitchOffsetByOriginalSwitchDataOffset.put(switchDataOffset, currentCodeOffset);
|
||||
int switchDataAddress = currentCodeAddress + offsetInstruction.getTargetAddressOffset();
|
||||
if (originalSwitchAddressByOriginalSwitchDataAddress.indexOfKey(switchDataAddress) < 0) {
|
||||
originalSwitchAddressByOriginalSwitchDataAddress.put(switchDataAddress, currentCodeAddress);
|
||||
}
|
||||
}
|
||||
|
||||
originalInstructionOffsets[i] = currentCodeOffset;
|
||||
currentCodeOffset += instruction.getSize(currentCodeOffset);
|
||||
originalInstructionCodeAddresses[i] = currentCodeAddress;
|
||||
currentCodeAddress += instruction.getSize(currentCodeAddress);
|
||||
}
|
||||
//add the offset just past the end of the last instruction, to help when fixing up try blocks that end
|
||||
//add the address just past the end of the last instruction, to help when fixing up try blocks that end
|
||||
//at the end of the method
|
||||
originalInstructionOffsets[i] = currentCodeOffset;
|
||||
originalInstructionCodeAddresses[i] = currentCodeAddress;
|
||||
|
||||
if (originalInstruction == null) {
|
||||
throw new RuntimeException("There is no instruction at offset " + offset);
|
||||
throw new RuntimeException("There is no instruction at address " + codeAddress);
|
||||
}
|
||||
|
||||
instructions[instructionIndex] = replacementInstruction;
|
||||
|
||||
//if we're replacing the instruction with one of the same size, we don't have to worry about fixing
|
||||
//up any offsets
|
||||
if (originalInstruction.getSize(offset) == replacementInstruction.getSize(offset)) {
|
||||
//up any address
|
||||
if (originalInstruction.getSize(codeAddress) == replacementInstruction.getSize(codeAddress)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final SparseIntArray originalOffsetsByNewOffset = new SparseIntArray();
|
||||
final SparseIntArray newOffsetsByOriginalOffset = new SparseIntArray();
|
||||
final SparseIntArray originalAddressByNewAddress = new SparseIntArray();
|
||||
final SparseIntArray newAddressByOriginalAddress = new SparseIntArray();
|
||||
|
||||
currentCodeOffset = 0;
|
||||
currentCodeAddress = 0;
|
||||
for (i=0; i<instructions.length; i++) {
|
||||
Instruction instruction = instructions[i];
|
||||
|
||||
int originalOffset = originalInstructionOffsets[i];
|
||||
originalOffsetsByNewOffset.append(currentCodeOffset, originalOffset);
|
||||
newOffsetsByOriginalOffset.append(originalOffset, currentCodeOffset);
|
||||
int originalAddress = originalInstructionCodeAddresses[i];
|
||||
originalAddressByNewAddress.append(currentCodeAddress, originalAddress);
|
||||
newAddressByOriginalAddress.append(originalAddress, currentCodeAddress);
|
||||
|
||||
currentCodeOffset += instruction.getSize(currentCodeOffset);
|
||||
currentCodeAddress += instruction.getSize(currentCodeAddress);
|
||||
}
|
||||
|
||||
//add the offset just past the end of the last instruction, to help when fixing up try blocks that end
|
||||
//add the address just past the end of the last instruction, to help when fixing up try blocks that end
|
||||
//at the end of the method
|
||||
originalOffsetsByNewOffset.append(currentCodeOffset, originalInstructionOffsets[i]);
|
||||
newOffsetsByOriginalOffset.append(originalInstructionOffsets[i], currentCodeOffset);
|
||||
originalAddressByNewAddress.append(currentCodeAddress, originalInstructionCodeAddresses[i]);
|
||||
newAddressByOriginalAddress.append(originalInstructionCodeAddresses[i], currentCodeAddress);
|
||||
|
||||
//update any "offset" instructions, or switch data instructions
|
||||
currentCodeOffset = 0;
|
||||
currentCodeAddress = 0;
|
||||
for (i=0; i<instructions.length; i++) {
|
||||
Instruction instruction = instructions[i];
|
||||
|
||||
if (instruction instanceof OffsetInstruction) {
|
||||
OffsetInstruction offsetInstruction = (OffsetInstruction)instruction;
|
||||
|
||||
assert originalOffsetsByNewOffset.indexOfKey(currentCodeOffset) >= 0;
|
||||
int originalOffset = originalOffsetsByNewOffset.get(currentCodeOffset);
|
||||
assert originalAddressByNewAddress.indexOfKey(currentCodeAddress) >= 0;
|
||||
int originalAddress = originalAddressByNewAddress.get(currentCodeAddress);
|
||||
|
||||
int originalInstructionTarget = originalOffset + offsetInstruction.getOffset() * 2;
|
||||
int originalInstructionTarget = originalAddress + offsetInstruction.getTargetAddressOffset();
|
||||
|
||||
assert newOffsetsByOriginalOffset.indexOfKey(originalInstructionTarget) >= 0;
|
||||
int newInstructionTarget = newOffsetsByOriginalOffset.get(originalInstructionTarget);
|
||||
assert newAddressByOriginalAddress.indexOfKey(originalInstructionTarget) >= 0;
|
||||
int newInstructionTarget = newAddressByOriginalAddress.get(originalInstructionTarget);
|
||||
|
||||
int newOffset = (newInstructionTarget - currentCodeOffset) / 2;
|
||||
int newCodeAddress = (newInstructionTarget - currentCodeAddress);
|
||||
|
||||
if (newOffset != offsetInstruction.getOffset()) {
|
||||
offsetInstruction.updateOffset(newOffset);
|
||||
if (newCodeAddress != offsetInstruction.getTargetAddressOffset()) {
|
||||
offsetInstruction.updateTargetAddressOffset(newCodeAddress);
|
||||
}
|
||||
} else if (instruction instanceof MultiOffsetInstruction) {
|
||||
MultiOffsetInstruction multiOffsetInstruction = (MultiOffsetInstruction)instruction;
|
||||
|
||||
assert originalOffsetsByNewOffset.indexOfKey(currentCodeOffset) >= 0;
|
||||
int originalDataOffset = originalOffsetsByNewOffset.get(currentCodeOffset);
|
||||
assert originalAddressByNewAddress.indexOfKey(currentCodeAddress) >= 0;
|
||||
int originalDataAddress = originalAddressByNewAddress.get(currentCodeAddress);
|
||||
|
||||
int originalSwitchOffset = originalSwitchOffsetByOriginalSwitchDataOffset.get(originalDataOffset, -1);
|
||||
if (originalSwitchOffset == -1) {
|
||||
throw new RuntimeException("This method contains an unreferenced switch data block, and can't be automatically fixed.");
|
||||
int originalSwitchAddress =
|
||||
originalSwitchAddressByOriginalSwitchDataAddress.get(originalDataAddress, -1);
|
||||
if (originalSwitchAddress == -1) {
|
||||
//TODO: maybe we could just remove the unreferenced switch data?
|
||||
throw new RuntimeException("This method contains an unreferenced switch data block at address " +
|
||||
+ currentCodeAddress + " and can't be automatically fixed.");
|
||||
}
|
||||
|
||||
assert newOffsetsByOriginalOffset.indexOfKey(originalSwitchOffset) >= 0;
|
||||
int newSwitchOffset = newOffsetsByOriginalOffset.get(originalSwitchOffset);
|
||||
assert newAddressByOriginalAddress.indexOfKey(originalSwitchAddress) >= 0;
|
||||
int newSwitchAddress = newAddressByOriginalAddress.get(originalSwitchAddress);
|
||||
|
||||
int[] targets = multiOffsetInstruction.getTargets();
|
||||
for (int t=0; t<targets.length; t++) {
|
||||
int originalTargetOffset = originalSwitchOffset + targets[t]*2;
|
||||
assert newOffsetsByOriginalOffset.indexOfKey(originalTargetOffset) >= 0;
|
||||
int newTargetOffset = newOffsetsByOriginalOffset.get(originalTargetOffset);
|
||||
int newOffset = (newTargetOffset - newSwitchOffset)/2;
|
||||
if (newOffset != targets[t]) {
|
||||
multiOffsetInstruction.updateTarget(t, newOffset);
|
||||
int originalTargetCodeAddress = originalSwitchAddress + targets[t];
|
||||
assert newAddressByOriginalAddress.indexOfKey(originalTargetCodeAddress) >= 0;
|
||||
int newTargetCodeAddress = newAddressByOriginalAddress.get(originalTargetCodeAddress);
|
||||
int newCodeAddress = newTargetCodeAddress - newSwitchAddress;
|
||||
if (newCodeAddress != targets[t]) {
|
||||
multiOffsetInstruction.updateTarget(t, newCodeAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
currentCodeOffset += instruction.getSize(currentCodeOffset);
|
||||
currentCodeAddress += instruction.getSize(currentCodeAddress);
|
||||
}
|
||||
|
||||
if (debugInfo != null) {
|
||||
@ -574,7 +598,7 @@ public class CodeItem extends Item<CodeItem> {
|
||||
ByteArrayInput debugInput = new ByteArrayInput(encodedDebugInfo);
|
||||
|
||||
DebugInstructionFixer debugInstructionFixer = new DebugInstructionFixer(encodedDebugInfo,
|
||||
newOffsetsByOriginalOffset, originalOffsetsByNewOffset);
|
||||
newAddressByOriginalAddress);
|
||||
DebugInstructionIterator.IterateInstructions(debugInput, debugInstructionFixer);
|
||||
|
||||
if (debugInstructionFixer.result != null) {
|
||||
@ -585,122 +609,124 @@ public class CodeItem extends Item<CodeItem> {
|
||||
if (encodedCatchHandlers != null) {
|
||||
for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) {
|
||||
if (encodedCatchHandler.catchAllHandlerAddress != -1) {
|
||||
assert newOffsetsByOriginalOffset.indexOfKey(encodedCatchHandler.catchAllHandlerAddress*2) >= 0;
|
||||
assert newAddressByOriginalAddress.indexOfKey(encodedCatchHandler.catchAllHandlerAddress) >= 0;
|
||||
encodedCatchHandler.catchAllHandlerAddress =
|
||||
newOffsetsByOriginalOffset.get(encodedCatchHandler.catchAllHandlerAddress*2)/2;
|
||||
newAddressByOriginalAddress.get(encodedCatchHandler.catchAllHandlerAddress);
|
||||
}
|
||||
|
||||
for (EncodedTypeAddrPair handler: encodedCatchHandler.handlers) {
|
||||
assert newOffsetsByOriginalOffset.indexOfKey(handler.handlerAddress*2) >= 0;
|
||||
handler.handlerAddress = newOffsetsByOriginalOffset.get(handler.handlerAddress*2)/2;
|
||||
assert newAddressByOriginalAddress.indexOfKey(handler.handlerAddress) >= 0;
|
||||
handler.handlerAddress = newAddressByOriginalAddress.get(handler.handlerAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.tries != null) {
|
||||
for (TryItem tryItem: tries) {
|
||||
int startAddress = tryItem.startAddress;
|
||||
int endAddress = tryItem.startAddress + tryItem.instructionCount;
|
||||
int startAddress = tryItem.startCodeAddress;
|
||||
int endAddress = tryItem.startCodeAddress + tryItem.tryLength;
|
||||
|
||||
assert newOffsetsByOriginalOffset.indexOfKey(startAddress * 2) >= 0;
|
||||
tryItem.startAddress = newOffsetsByOriginalOffset.get(startAddress * 2)/2;
|
||||
assert newAddressByOriginalAddress.indexOfKey(startAddress) >= 0;
|
||||
tryItem.startCodeAddress = newAddressByOriginalAddress.get(startAddress);
|
||||
|
||||
assert newOffsetsByOriginalOffset.indexOfKey(endAddress * 2) >= 0;
|
||||
tryItem.instructionCount = newOffsetsByOriginalOffset.get(endAddress * 2)/2 - tryItem.startAddress;
|
||||
assert newAddressByOriginalAddress.indexOfKey(endAddress) >= 0;
|
||||
tryItem.tryLength = newAddressByOriginalAddress.get(endAddress) - tryItem.startCodeAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DebugInstructionFixer extends DebugInstructionIterator.ProcessRawDebugInstructionDelegate {
|
||||
private int address = 0;
|
||||
private SparseIntArray newOffsetsByOriginalOffset;
|
||||
private SparseIntArray originalOffsetsByNewOffset;
|
||||
private int currentCodeAddress = 0;
|
||||
private SparseIntArray newAddressByOriginalAddress;
|
||||
private final byte[] originalEncodedDebugInfo;
|
||||
public byte[] result = null;
|
||||
|
||||
public DebugInstructionFixer(byte[] originalEncodedDebugInfo, SparseIntArray newOffsetsByOriginalOffset,
|
||||
SparseIntArray originalOffsetsByNewOffset) {
|
||||
this.newOffsetsByOriginalOffset = newOffsetsByOriginalOffset;
|
||||
this.originalOffsetsByNewOffset = originalOffsetsByNewOffset;
|
||||
public DebugInstructionFixer(byte[] originalEncodedDebugInfo, SparseIntArray newAddressByOriginalAddress) {
|
||||
this.newAddressByOriginalAddress = newAddressByOriginalAddress;
|
||||
this.originalEncodedDebugInfo = originalEncodedDebugInfo;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void ProcessAdvancePC(int startOffset, int length, int addressDelta) {
|
||||
address += addressDelta;
|
||||
public void ProcessAdvancePC(int startDebugOffset, int debugInstructionLength, int codeAddressDelta) {
|
||||
currentCodeAddress += codeAddressDelta;
|
||||
|
||||
if (result != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int newOffset = newOffsetsByOriginalOffset.get(address*2, -1);
|
||||
int newCodeAddress = newAddressByOriginalAddress.get(currentCodeAddress, -1);
|
||||
|
||||
//The address might not point to an actual instruction in some cases, for example, if an AdvancePC
|
||||
//instruction was inserted just before a "special" instruction, to fix up the offsets for a previous
|
||||
//instruction was inserted just before a "special" instruction, to fix up the addresses for a previous
|
||||
//instruction replacement.
|
||||
//In this case, it should be safe to skip, because there will be another AdvancePC/SpecialOpcode that will
|
||||
//bump up the address to point to a valid instruction before anything (line/local/etc.) is emitted
|
||||
if (newOffset == -1) {
|
||||
if (newCodeAddress == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert newOffset != -1;
|
||||
newOffset = newOffset / 2;
|
||||
if (newCodeAddress != currentCodeAddress) {
|
||||
int newCodeAddressDelta = newCodeAddress - (currentCodeAddress - codeAddressDelta);
|
||||
assert newCodeAddressDelta > 0;
|
||||
int codeAddressDeltaLeb128Size = Leb128Utils.unsignedLeb128Size(newCodeAddressDelta);
|
||||
|
||||
if (newOffset != address) {
|
||||
int newAddressDelta = newOffset - (address - addressDelta);
|
||||
assert newAddressDelta > 0;
|
||||
int addressDiffSize = Leb128Utils.unsignedLeb128Size(newAddressDelta);
|
||||
//if the length of the new code address delta is the same, we can use the existing buffer
|
||||
if (codeAddressDeltaLeb128Size + 1 == debugInstructionLength) {
|
||||
result = originalEncodedDebugInfo;
|
||||
Leb128Utils.writeUnsignedLeb128(newCodeAddressDelta, result, startDebugOffset+1);
|
||||
} else {
|
||||
//The length of the new code address delta is different, so create a new buffer with enough
|
||||
//additional space to accomodate the new code address delta value.
|
||||
result = new byte[originalEncodedDebugInfo.length + codeAddressDeltaLeb128Size -
|
||||
(debugInstructionLength - 1)];
|
||||
|
||||
result = new byte[originalEncodedDebugInfo.length + addressDiffSize - (length - 1)];
|
||||
System.arraycopy(originalEncodedDebugInfo, 0, result, 0, startDebugOffset);
|
||||
|
||||
System.arraycopy(originalEncodedDebugInfo, 0, result, 0, startOffset);
|
||||
result[startDebugOffset] = DebugOpcode.DBG_ADVANCE_PC.value;
|
||||
Leb128Utils.writeUnsignedLeb128(newCodeAddressDelta, result, startDebugOffset+1);
|
||||
|
||||
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));
|
||||
System.arraycopy(originalEncodedDebugInfo, startDebugOffset + debugInstructionLength, result,
|
||||
startDebugOffset + codeAddressDeltaLeb128Size + 1,
|
||||
originalEncodedDebugInfo.length - (startDebugOffset + codeAddressDeltaLeb128Size + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessSpecialOpcode(int startOffset, int debugOpcode, int lineDelta,
|
||||
int addressDelta) {
|
||||
address += addressDelta;
|
||||
public void ProcessSpecialOpcode(int startDebugOffset, int debugOpcode, int lineDelta,
|
||||
int codeAddressDelta) {
|
||||
currentCodeAddress += codeAddressDelta;
|
||||
if (result != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int newOffset = newOffsetsByOriginalOffset.get(address*2, -1);
|
||||
assert newOffset != -1;
|
||||
newOffset = newOffset / 2;
|
||||
int newCodeAddress = newAddressByOriginalAddress.get(currentCodeAddress, -1);
|
||||
assert newCodeAddress != -1;
|
||||
|
||||
if (newOffset != address) {
|
||||
int newAddressDelta = newOffset - (address - addressDelta);
|
||||
assert newAddressDelta > 0;
|
||||
if (newCodeAddress != currentCodeAddress) {
|
||||
int newCodeAddressDelta = newCodeAddress - (currentCodeAddress - codeAddressDelta);
|
||||
assert newCodeAddressDelta > 0;
|
||||
|
||||
//if the new address delta won't fit in the special opcode, we need to insert
|
||||
//if the new code address delta won't fit in the special opcode, we need to insert
|
||||
//an additional DBG_ADVANCE_PC opcode
|
||||
if (lineDelta < 2 && newAddressDelta > 16 || lineDelta > 1 && newAddressDelta > 15) {
|
||||
int additionalAddressDelta = newOffset - address;
|
||||
int additionalAddressDeltaSize = Leb128Utils.signedLeb128Size(additionalAddressDelta);
|
||||
if (lineDelta < 2 && newCodeAddressDelta > 16 || lineDelta > 1 && newCodeAddressDelta > 15) {
|
||||
int additionalCodeAddressDelta = newCodeAddress - currentCodeAddress;
|
||||
int additionalCodeAddressDeltaLeb128Size = Leb128Utils.signedLeb128Size(additionalCodeAddressDelta);
|
||||
|
||||
result = new byte[originalEncodedDebugInfo.length + additionalAddressDeltaSize + 1];
|
||||
//create a new buffer with enough additional space for the new opcode
|
||||
result = new byte[originalEncodedDebugInfo.length + additionalCodeAddressDeltaLeb128Size + 1];
|
||||
|
||||
System.arraycopy(originalEncodedDebugInfo, 0, result, 0, startOffset);
|
||||
result[startOffset] = 0x01; //DBG_ADVANCE_PC
|
||||
Leb128Utils.writeUnsignedLeb128(additionalAddressDelta, result, startOffset+1);
|
||||
System.arraycopy(originalEncodedDebugInfo, startOffset, result,
|
||||
startOffset+additionalAddressDeltaSize+1,
|
||||
result.length - (startOffset+additionalAddressDeltaSize+1));
|
||||
System.arraycopy(originalEncodedDebugInfo, 0, result, 0, startDebugOffset);
|
||||
result[startDebugOffset] = 0x01; //DBG_ADVANCE_PC
|
||||
Leb128Utils.writeUnsignedLeb128(additionalCodeAddressDelta, result, startDebugOffset+1);
|
||||
System.arraycopy(originalEncodedDebugInfo, startDebugOffset, result,
|
||||
startDebugOffset+additionalCodeAddressDeltaLeb128Size+1,
|
||||
result.length - (startDebugOffset+additionalCodeAddressDeltaLeb128Size+1));
|
||||
} else {
|
||||
result = new byte[originalEncodedDebugInfo.length];
|
||||
System.arraycopy(originalEncodedDebugInfo, 0, result, 0, result.length);
|
||||
result[startOffset] = DebugInfoBuilder.calculateSpecialOpcode(lineDelta,
|
||||
newAddressDelta);
|
||||
result = originalEncodedDebugInfo;
|
||||
result[startDebugOffset] = DebugInfoBuilder.calculateSpecialOpcode(lineDelta,
|
||||
newCodeAddressDelta);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -710,12 +736,12 @@ public class CodeItem extends Item<CodeItem> {
|
||||
/**
|
||||
* The address (in 2-byte words) within the code where the try block starts
|
||||
*/
|
||||
private int startAddress;
|
||||
private int startCodeAddress;
|
||||
|
||||
/**
|
||||
* The number of 2-byte words that the try block covers
|
||||
*/
|
||||
private int instructionCount;
|
||||
private int tryLength;
|
||||
|
||||
/**
|
||||
* The associated exception handler
|
||||
@ -724,13 +750,13 @@ public class CodeItem extends Item<CodeItem> {
|
||||
|
||||
/**
|
||||
* Construct a new <code>TryItem</code> with the given values
|
||||
* @param startAddress the address (in 2-byte words) within the code where the try block starts
|
||||
* @param instructionCount the number of 2-byte words that the try block covers
|
||||
* @param startCodeAddress the code address within the code where the try block starts
|
||||
* @param tryLength the number of code blocks that the try block covers
|
||||
* @param encodedCatchHandler the associated exception handler
|
||||
*/
|
||||
public TryItem(int startAddress, int instructionCount, EncodedCatchHandler encodedCatchHandler) {
|
||||
this.startAddress = startAddress;
|
||||
this.instructionCount = instructionCount;
|
||||
public TryItem(int startCodeAddress, int tryLength, EncodedCatchHandler encodedCatchHandler) {
|
||||
this.startCodeAddress = startCodeAddress;
|
||||
this.tryLength = tryLength;
|
||||
this.encodedCatchHandler = encodedCatchHandler;
|
||||
}
|
||||
|
||||
@ -742,8 +768,8 @@ public class CodeItem extends Item<CodeItem> {
|
||||
* structure.
|
||||
*/
|
||||
private TryItem(Input in, SparseArray<EncodedCatchHandler> encodedCatchHandlers) {
|
||||
startAddress = in.readInt();
|
||||
instructionCount = in.readShort();
|
||||
startCodeAddress = in.readInt();
|
||||
tryLength = in.readShort();
|
||||
|
||||
encodedCatchHandler = encodedCatchHandlers.get(in.readShort());
|
||||
if (encodedCatchHandler == null) {
|
||||
@ -757,29 +783,29 @@ public class CodeItem extends Item<CodeItem> {
|
||||
*/
|
||||
private void writeTo(AnnotatedOutput out) {
|
||||
if (out.annotates()) {
|
||||
out.annotate(4, "start_addr: 0x" + Integer.toHexString(startAddress));
|
||||
out.annotate(2, "insn_count: 0x" + Integer.toHexString(instructionCount) + " (" + instructionCount +
|
||||
out.annotate(4, "start_addr: 0x" + Integer.toHexString(startCodeAddress));
|
||||
out.annotate(2, "try_length: 0x" + Integer.toHexString(tryLength) + " (" + tryLength +
|
||||
")");
|
||||
out.annotate(2, "handler_off: 0x" + Integer.toHexString(encodedCatchHandler.getOffsetInList()));
|
||||
}
|
||||
|
||||
out.writeInt(startAddress);
|
||||
out.writeShort(instructionCount);
|
||||
out.writeInt(startCodeAddress);
|
||||
out.writeShort(tryLength);
|
||||
out.writeShort(encodedCatchHandler.getOffsetInList());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The address (in 2-byte words) within the code where the try block starts
|
||||
*/
|
||||
public int getStartAddress() {
|
||||
return startAddress;
|
||||
public int getStartCodeAddress() {
|
||||
return startCodeAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of 2-byte words that the try block covers
|
||||
* @return The number of code blocks that the try block covers
|
||||
*/
|
||||
public int getInstructionCount() {
|
||||
return instructionCount;
|
||||
public int getTryLength() {
|
||||
return tryLength;
|
||||
}
|
||||
}
|
||||
|
||||
@ -825,7 +851,11 @@ public class CodeItem extends Item<CodeItem> {
|
||||
}
|
||||
|
||||
for (int i=0; i<handlers.length; i++) {
|
||||
try {
|
||||
handlers[i] = new EncodedTypeAddrPair(dexFile, in);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error while reading EncodedTypeAddrPair at index " + i);
|
||||
}
|
||||
}
|
||||
|
||||
if (handlerCount <= 0) {
|
||||
|
@ -44,29 +44,31 @@ public class DebugInstructionIterator {
|
||||
* for each instruction that is encountered
|
||||
*/
|
||||
public static void IterateInstructions(Input in, ProcessRawDebugInstructionDelegate processDebugInstruction) {
|
||||
int startOffset;
|
||||
int startDebugOffset;
|
||||
|
||||
while(true)
|
||||
{
|
||||
startOffset = in.getCursor();
|
||||
startDebugOffset = in.getCursor();
|
||||
byte debugOpcode = in.readByte();
|
||||
|
||||
switch (debugOpcode) {
|
||||
case 0x00:
|
||||
{
|
||||
processDebugInstruction.ProcessEndSequence(startOffset);
|
||||
processDebugInstruction.ProcessEndSequence(startDebugOffset);
|
||||
return;
|
||||
}
|
||||
case 0x01:
|
||||
{
|
||||
int addressDiff = in.readUnsignedLeb128();
|
||||
processDebugInstruction.ProcessAdvancePC(startOffset, in.getCursor() - startOffset, addressDiff);
|
||||
int codeAddressDiff = in.readUnsignedLeb128();
|
||||
processDebugInstruction.ProcessAdvancePC(startDebugOffset, in.getCursor() - startDebugOffset,
|
||||
codeAddressDiff);
|
||||
break;
|
||||
}
|
||||
case 0x02:
|
||||
{
|
||||
int lineDiff = in.readSignedLeb128();
|
||||
processDebugInstruction.ProcessAdvanceLine(startOffset, in.getCursor() - startOffset, lineDiff);
|
||||
processDebugInstruction.ProcessAdvanceLine(startDebugOffset, in.getCursor() - startDebugOffset,
|
||||
lineDiff);
|
||||
break;
|
||||
}
|
||||
case 0x03:
|
||||
@ -79,8 +81,8 @@ public class DebugInstructionIterator {
|
||||
}
|
||||
int nameIndex = in.readUnsignedLeb128() - 1;
|
||||
int typeIndex = in.readUnsignedLeb128() - 1;
|
||||
processDebugInstruction.ProcessStartLocal(startOffset, in.getCursor() - startOffset, registerNum,
|
||||
nameIndex, typeIndex, isSignedRegister);
|
||||
processDebugInstruction.ProcessStartLocal(startDebugOffset, in.getCursor() - startDebugOffset,
|
||||
registerNum, nameIndex, typeIndex, isSignedRegister);
|
||||
break;
|
||||
}
|
||||
case 0x04:
|
||||
@ -94,8 +96,9 @@ public class DebugInstructionIterator {
|
||||
int nameIndex = in.readUnsignedLeb128() - 1;
|
||||
int typeIndex = in.readUnsignedLeb128() - 1;
|
||||
int signatureIndex = in.readUnsignedLeb128() - 1;
|
||||
processDebugInstruction.ProcessStartLocalExtended(startOffset, in.getCursor() - startOffset,
|
||||
registerNum, nameIndex, typeIndex, signatureIndex, isSignedRegister);
|
||||
processDebugInstruction.ProcessStartLocalExtended(startDebugOffset,
|
||||
in.getCursor() - startDebugOffset, registerNum, nameIndex, typeIndex, signatureIndex,
|
||||
isSignedRegister);
|
||||
break;
|
||||
}
|
||||
case 0x05:
|
||||
@ -106,8 +109,8 @@ public class DebugInstructionIterator {
|
||||
isSignedRegister = true;
|
||||
registerNum = ~registerNum;
|
||||
}
|
||||
processDebugInstruction.ProcessEndLocal(startOffset, in.getCursor() - startOffset, registerNum,
|
||||
isSignedRegister);
|
||||
processDebugInstruction.ProcessEndLocal(startDebugOffset, in.getCursor() - startDebugOffset,
|
||||
registerNum, isSignedRegister);
|
||||
break;
|
||||
}
|
||||
case 0x06:
|
||||
@ -118,30 +121,31 @@ public class DebugInstructionIterator {
|
||||
isSignedRegister = true;
|
||||
registerNum = ~registerNum;
|
||||
}
|
||||
processDebugInstruction.ProcessRestartLocal(startOffset, in.getCursor() - startOffset, registerNum,
|
||||
isSignedRegister);
|
||||
processDebugInstruction.ProcessRestartLocal(startDebugOffset, in.getCursor() - startDebugOffset,
|
||||
registerNum, isSignedRegister);
|
||||
break;
|
||||
}
|
||||
case 0x07:
|
||||
{
|
||||
processDebugInstruction.ProcessSetPrologueEnd(startOffset);
|
||||
processDebugInstruction.ProcessSetPrologueEnd(startDebugOffset);
|
||||
break;
|
||||
}
|
||||
case 0x08:
|
||||
{
|
||||
processDebugInstruction.ProcessSetEpilogueBegin(startOffset);
|
||||
processDebugInstruction.ProcessSetEpilogueBegin(startDebugOffset);
|
||||
break;
|
||||
}
|
||||
case 0x09:
|
||||
{
|
||||
int nameIndex = in.readUnsignedLeb128();
|
||||
processDebugInstruction.ProcessSetFile(startOffset, in.getCursor() - startOffset, nameIndex);
|
||||
processDebugInstruction.ProcessSetFile(startDebugOffset, in.getCursor() - startDebugOffset,
|
||||
nameIndex);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
int base = ((debugOpcode & 0xFF) - 0x0A);
|
||||
processDebugInstruction.ProcessSpecialOpcode(startOffset, debugOpcode, (base % 15) - 4, base / 15);
|
||||
processDebugInstruction.ProcessSpecialOpcode(startDebugOffset, debugOpcode, (base % 15) - 4, base / 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -157,8 +161,8 @@ public class DebugInstructionIterator {
|
||||
*/
|
||||
public static void DecodeInstructions(DebugInfoItem debugInfoItem, int registerCount,
|
||||
ProcessDecodedDebugInstructionDelegate processDecodedDebugInstruction) {
|
||||
int startOffset;
|
||||
int address = 0;
|
||||
int startDebugOffset;
|
||||
int currentCodeAddress = 0;
|
||||
int line = debugInfoItem.getLineStart();
|
||||
Input in = new ByteArrayInput(debugInfoItem.getEncodedDebugInfo());
|
||||
DexFile dexFile = debugInfoItem.getDexFile();
|
||||
@ -167,96 +171,97 @@ public class DebugInstructionIterator {
|
||||
|
||||
while(true)
|
||||
{
|
||||
startOffset = in.getCursor();
|
||||
startDebugOffset = in.getCursor();
|
||||
byte debugOpcode = in.readByte();
|
||||
|
||||
switch (debugOpcode) {
|
||||
case 0x00:
|
||||
switch (DebugOpcode.getDebugOpcodeByValue(debugOpcode)) {
|
||||
case DBG_END_SEQUENCE:
|
||||
{
|
||||
return;
|
||||
}
|
||||
case 0x01:
|
||||
case DBG_ADVANCE_PC:
|
||||
{
|
||||
int addressDiff = in.readUnsignedLeb128();
|
||||
address += addressDiff;
|
||||
int codeAddressDiff = in.readUnsignedLeb128();
|
||||
currentCodeAddress += codeAddressDiff;
|
||||
break;
|
||||
}
|
||||
case 0x02:
|
||||
case DBG_ADVANCE_LINE:
|
||||
{
|
||||
int lineDiff = in.readSignedLeb128();
|
||||
line += lineDiff;
|
||||
break;
|
||||
}
|
||||
case 0x03:
|
||||
case DBG_START_LOCAL:
|
||||
{
|
||||
int registerNum = in.readUnsignedLeb128();
|
||||
StringIdItem name = dexFile.StringIdsSection.getItemByIndex(in.readUnsignedLeb128() - 1);
|
||||
TypeIdItem type = dexFile.TypeIdsSection.getItemByIndex(in.readUnsignedLeb128() - 1);
|
||||
StringIdItem name = dexFile.StringIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
|
||||
TypeIdItem type = dexFile.TypeIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
|
||||
locals[registerNum] = new Local(registerNum, name, type, null);
|
||||
processDecodedDebugInstruction.ProcessStartLocal(address, in.getCursor() - startOffset, registerNum,
|
||||
name, type);
|
||||
processDecodedDebugInstruction.ProcessStartLocal(currentCodeAddress,
|
||||
in.getCursor() - startDebugOffset, registerNum, name, type);
|
||||
break;
|
||||
}
|
||||
case 0x04:
|
||||
case DBG_START_LOCAL_EXTENDED:
|
||||
{
|
||||
int registerNum = in.readUnsignedLeb128();
|
||||
StringIdItem name = dexFile.StringIdsSection.getItemByIndex(in.readUnsignedLeb128() - 1);
|
||||
TypeIdItem type = dexFile.TypeIdsSection.getItemByIndex(in.readUnsignedLeb128() - 1);
|
||||
StringIdItem signature = dexFile.StringIdsSection.getItemByIndex(in.readUnsignedLeb128() - 1);
|
||||
StringIdItem name = dexFile.StringIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
|
||||
TypeIdItem type = dexFile.TypeIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
|
||||
StringIdItem signature =
|
||||
dexFile.StringIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
|
||||
locals[registerNum] = new Local(registerNum, name, type, signature);
|
||||
processDecodedDebugInstruction.ProcessStartLocalExtended(address, in.getCursor() - startOffset,
|
||||
registerNum, name, type, signature);
|
||||
processDecodedDebugInstruction.ProcessStartLocalExtended(currentCodeAddress,
|
||||
in.getCursor() - startDebugOffset, registerNum, name, type, signature);
|
||||
break;
|
||||
}
|
||||
case 0x05:
|
||||
case DBG_END_LOCAL:
|
||||
{
|
||||
int registerNum = in.readUnsignedLeb128();
|
||||
Local local = locals[registerNum];
|
||||
if (local == null) {
|
||||
processDecodedDebugInstruction.ProcessEndLocal(address, in.getCursor() - startOffset, registerNum,
|
||||
processDecodedDebugInstruction.ProcessEndLocal(currentCodeAddress, in.getCursor() - startDebugOffset, registerNum,
|
||||
null, null, null);
|
||||
} else {
|
||||
processDecodedDebugInstruction.ProcessEndLocal(address, in.getCursor() - startOffset, registerNum,
|
||||
processDecodedDebugInstruction.ProcessEndLocal(currentCodeAddress, in.getCursor() - startDebugOffset, registerNum,
|
||||
local.name, local.type, local.signature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x06:
|
||||
case DBG_RESTART_LOCAL:
|
||||
{
|
||||
int registerNum = in.readUnsignedLeb128();
|
||||
Local local = locals[registerNum];
|
||||
if (local == null) {
|
||||
processDecodedDebugInstruction.ProcessRestartLocal(address, in.getCursor() - startOffset,
|
||||
processDecodedDebugInstruction.ProcessRestartLocal(currentCodeAddress, in.getCursor() - startDebugOffset,
|
||||
registerNum, null, null, null);
|
||||
} else {
|
||||
processDecodedDebugInstruction.ProcessRestartLocal(address, in.getCursor() - startOffset,
|
||||
processDecodedDebugInstruction.ProcessRestartLocal(currentCodeAddress, in.getCursor() - startDebugOffset,
|
||||
registerNum, local.name, local.type, local.signature);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x07:
|
||||
case DBG_SET_PROLOGUE_END:
|
||||
{
|
||||
processDecodedDebugInstruction.ProcessSetPrologueEnd(address);
|
||||
processDecodedDebugInstruction.ProcessSetPrologueEnd(currentCodeAddress);
|
||||
break;
|
||||
}
|
||||
case 0x08:
|
||||
case DBG_SET_EPILOGUE_BEGIN:
|
||||
{
|
||||
processDecodedDebugInstruction.ProcessSetEpilogueBegin(address);
|
||||
processDecodedDebugInstruction.ProcessSetEpilogueBegin(currentCodeAddress);
|
||||
break;
|
||||
}
|
||||
case 0x09:
|
||||
case DBG_SET_FILE:
|
||||
{
|
||||
StringIdItem name = dexFile.StringIdsSection.getItemByIndex(in.readUnsignedLeb128() - 1);
|
||||
processDecodedDebugInstruction.ProcessSetFile(address, in.getCursor() - startOffset, name);
|
||||
StringIdItem name = dexFile.StringIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
|
||||
processDecodedDebugInstruction.ProcessSetFile(currentCodeAddress, in.getCursor() - startDebugOffset, name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
case DBG_SPECIAL_OPCODE:
|
||||
{
|
||||
int base = ((debugOpcode & 0xFF) - 0x0A);
|
||||
address += base / 15;
|
||||
currentCodeAddress += base / 15;
|
||||
line += (base % 15) - 4;
|
||||
processDecodedDebugInstruction.ProcessLineEmit(address, line);
|
||||
processDecodedDebugInstruction.ProcessLineEmit(currentCodeAddress, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -265,50 +270,50 @@ public class DebugInstructionIterator {
|
||||
public static class ProcessRawDebugInstructionDelegate
|
||||
{
|
||||
//TODO: add javadocs
|
||||
public void ProcessEndSequence(int startOffset) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_END_SEQUENCE, startOffset, 1);
|
||||
public void ProcessEndSequence(int startDebugOffset) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_END_SEQUENCE, startDebugOffset, 1);
|
||||
}
|
||||
|
||||
public void ProcessAdvancePC(int startOffset, int length, int addressDiff) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_ADVANCE_PC, startOffset, length);
|
||||
public void ProcessAdvancePC(int startDebugOffset, int length, int codeAddressDiff) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_ADVANCE_PC, startDebugOffset, length);
|
||||
}
|
||||
|
||||
public void ProcessAdvanceLine(int startOffset, int length, int lineDiff) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_ADVANCE_LINE, startOffset, length);
|
||||
public void ProcessAdvanceLine(int startDebugOffset, int length, int lineDiff) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_ADVANCE_LINE, startDebugOffset, length);
|
||||
}
|
||||
|
||||
public void ProcessStartLocal(int startOffset, int length, int registerNum, int nameIndex, int typeIndex,
|
||||
public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex, int typeIndex,
|
||||
boolean registerIsSigned) {
|
||||
}
|
||||
|
||||
public void ProcessStartLocalExtended(int startOffset, int length, int registerNum, int nameIndex,
|
||||
public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNum, int nameIndex,
|
||||
int typeIndex,int signatureIndex, boolean registerIsSigned) {
|
||||
}
|
||||
|
||||
public void ProcessEndLocal(int startOffset, int length, int registerNum, boolean registerIsSigned) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_END_LOCAL, startOffset, length);
|
||||
public void ProcessEndLocal(int startDebugOffset, int length, int registerNum, boolean registerIsSigned) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_END_LOCAL, startDebugOffset, length);
|
||||
}
|
||||
|
||||
public void ProcessRestartLocal(int startOffset, int length, int registerNum, boolean registerIsSigned) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_RESTART_LOCAL, startOffset, length);
|
||||
public void ProcessRestartLocal(int startDebugOffset, int length, int registerNum, boolean registerIsSigned) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_RESTART_LOCAL, startDebugOffset, length);
|
||||
}
|
||||
|
||||
public void ProcessSetPrologueEnd(int startOffset) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_SET_PROLOGUE_END, startOffset, 1);
|
||||
public void ProcessSetPrologueEnd(int startDebugOffset) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_SET_PROLOGUE_END, startDebugOffset, 1);
|
||||
}
|
||||
|
||||
public void ProcessSetEpilogueBegin(int startOffset) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_SET_EPILOGUE_BEGIN, startOffset, 1);
|
||||
public void ProcessSetEpilogueBegin(int startDebugOffset) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_SET_EPILOGUE_BEGIN, startDebugOffset, 1);
|
||||
}
|
||||
|
||||
public void ProcessSetFile(int startOffset, int length, int nameIndex) {
|
||||
public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) {
|
||||
}
|
||||
|
||||
public void ProcessSpecialOpcode(int startOffset, int debugOpcode, int lineDiff, int addressDiff) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_SPECIAL_OPCODE, startOffset, 1);
|
||||
public void ProcessSpecialOpcode(int startDebugOffset, int debugOpcode, int lineDiff, int codeAddressDiff) {
|
||||
ProcessStaticOpcode(DebugOpcode.DBG_SPECIAL_OPCODE, startDebugOffset, 1);
|
||||
}
|
||||
|
||||
public void ProcessStaticOpcode(DebugOpcode debugOpcode, int startOffset, int length) {
|
||||
public void ProcessStaticOpcode(DebugOpcode debugOpcode, int startDebugOffset, int length) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ public enum DebugOpcode {
|
||||
}
|
||||
|
||||
public static DebugOpcode getDebugOpcodeByValue(byte debugOpcodeValue) {
|
||||
debugOpcodeValue = (byte)Math.min(debugOpcodeValue, 0x0A);
|
||||
debugOpcodeValue = (byte)Math.min(debugOpcodeValue & 0xFF, 0x0A);
|
||||
return opcodesByValue[debugOpcodeValue];
|
||||
}
|
||||
|
||||
|
@ -103,12 +103,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
parameterNames = new StringIdItem[in.readUnsignedLeb128()];
|
||||
IndexedSection<StringIdItem> stringIdSection = dexFile.StringIdsSection;
|
||||
for (int i=0; i<parameterNames.length; i++) {
|
||||
int index = in.readUnsignedLeb128() - 1;
|
||||
if (index < 0) {
|
||||
parameterNames[i] = null;
|
||||
} else {
|
||||
parameterNames[i] = stringIdSection.getItemByIndex(index);
|
||||
}
|
||||
parameterNames[i] = stringIdSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
|
||||
}
|
||||
|
||||
int start = in.getCursor();
|
||||
@ -116,7 +111,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
DebugInstructionIterator.IterateInstructions(in,
|
||||
new DebugInstructionIterator.ProcessRawDebugInstructionDelegate() {
|
||||
@Override
|
||||
public void ProcessStartLocal(int startOffset, int length, int registerNum, int nameIndex,
|
||||
public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex,
|
||||
int typeIndex, boolean registerIsSigned) {
|
||||
if (nameIndex != -1) {
|
||||
referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex));
|
||||
@ -127,8 +122,8 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessStartLocalExtended(int startOffset, int length, int registerNume, int nameIndex,
|
||||
int typeIndex, int signatureIndex,
|
||||
public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNume,
|
||||
int nameIndex, int typeIndex, int signatureIndex,
|
||||
boolean registerIsSigned) {
|
||||
if (nameIndex != -1) {
|
||||
referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex));
|
||||
@ -142,7 +137,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessSetFile(int startOffset, int length, int nameIndex) {
|
||||
public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) {
|
||||
if (nameIndex != -1) {
|
||||
referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex));
|
||||
}
|
||||
@ -187,12 +182,12 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
private int referencedItemsPosition = 0;
|
||||
|
||||
@Override
|
||||
public void ProcessStaticOpcode(DebugOpcode opcode, int startOffset, int length) {
|
||||
public void ProcessStaticOpcode(DebugOpcode opcode, int startDebugOffset, int length) {
|
||||
this.length+=length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessStartLocal(int startOffset, int length, int registerNum, int nameIndex,
|
||||
public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex,
|
||||
int typeIndex, boolean registerIsSigned) {
|
||||
this.length++;
|
||||
if (dexFile.getPreserveSignedRegisters() && registerIsSigned) {
|
||||
@ -216,7 +211,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessStartLocalExtended(int startOffset, int length, int registerNum, int nameIndex,
|
||||
public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNum, int nameIndex,
|
||||
int typeIndex, int signatureIndex,
|
||||
boolean registerIsSigned) {
|
||||
this.length++;
|
||||
@ -246,7 +241,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessSetFile(int startOffset, int length, int nameIndex) {
|
||||
public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) {
|
||||
this.length++;
|
||||
if (nameIndex != -1) {
|
||||
this.length+=
|
||||
@ -261,7 +256,6 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void writeItem(final AnnotatedOutput out) {
|
||||
|
||||
if (out.annotates()) {
|
||||
writeItemWithAnnotations(out);
|
||||
} else {
|
||||
@ -275,7 +269,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
* @param encodedDebugInfo the new encoded debug info
|
||||
*/
|
||||
protected void setEncodedDebugInfo(byte[] encodedDebugInfo) {
|
||||
//TODO: I would rather replace this method with some way of saying "The (code) instruction at offset changed from A bytes to B bytes. Fixup the debug info accordingly"
|
||||
//TODO: I would rather replace this method with some way of saying "The (code) instruction at address changed from A bytes to B bytes. Fixup the debug info accordingly"
|
||||
|
||||
this.encodedDebugInfo = encodedDebugInfo;
|
||||
}
|
||||
@ -302,12 +296,12 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
private int referencedItemsPosition = 0;
|
||||
|
||||
@Override
|
||||
public void ProcessStaticOpcode(DebugOpcode opcode, int startOffset, int length) {
|
||||
out.write(encodedDebugInfo, startOffset, length);
|
||||
public void ProcessStaticOpcode(DebugOpcode opcode, int startDebugOffset, int length) {
|
||||
out.write(encodedDebugInfo, startDebugOffset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessStartLocal(int startOffset, int length, int registerNum, int nameIndex,
|
||||
public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex,
|
||||
int typeIndex, boolean registerIsSigned) {
|
||||
out.writeByte(DebugOpcode.DBG_START_LOCAL.value);
|
||||
if (dexFile.getPreserveSignedRegisters() && registerIsSigned) {
|
||||
@ -328,7 +322,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessStartLocalExtended(int startOffset, int length, int registerNum, int nameIndex,
|
||||
public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNum, int nameIndex,
|
||||
int typeIndex, int signatureIndex,
|
||||
boolean registerIsSigned) {
|
||||
out.writeByte(DebugOpcode.DBG_START_LOCAL_EXTENDED.value);
|
||||
@ -355,7 +349,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessSetFile(int startOffset, int length, int nameIndex) {
|
||||
public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) {
|
||||
out.writeByte(DebugOpcode.DBG_SET_FILE.value);
|
||||
if (nameIndex != -1) {
|
||||
out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1);
|
||||
@ -395,13 +389,13 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
private int referencedItemsPosition = 0;
|
||||
|
||||
@Override
|
||||
public void ProcessEndSequence(int startOffset) {
|
||||
public void ProcessEndSequence(int startDebugOffset) {
|
||||
out.annotate("DBG_END_SEQUENCE");
|
||||
out.writeByte(DebugOpcode.DBG_END_SEQUENCE.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessAdvancePC(int startOffset, int length, int addressDiff) {
|
||||
public void ProcessAdvancePC(int startDebugOffset, int length, int addressDiff) {
|
||||
out.annotate("DBG_ADVANCE_PC");
|
||||
out.writeByte(DebugOpcode.DBG_ADVANCE_PC.value);
|
||||
out.indent();
|
||||
@ -411,7 +405,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessAdvanceLine(int startOffset, int length, int lineDiff) {
|
||||
public void ProcessAdvanceLine(int startDebugOffset, int length, int lineDiff) {
|
||||
out.annotate("DBG_ADVANCE_LINE");
|
||||
out.writeByte(DebugOpcode.DBG_ADVANCE_LINE.value);
|
||||
out.indent();
|
||||
@ -421,7 +415,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessStartLocal(int startOffset, int length, int registerNum, int nameIndex,
|
||||
public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex,
|
||||
int typeIndex, boolean registerIsSigned) {
|
||||
out.annotate("DBG_START_LOCAL");
|
||||
out.writeByte(DebugOpcode.DBG_START_LOCAL.value);
|
||||
@ -454,8 +448,8 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessStartLocalExtended(int startOffset, int length, int registerNum, int nameIndex,
|
||||
int typeIndex, int signatureIndex,
|
||||
public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNum,
|
||||
int nameIndex, int typeIndex, int signatureIndex,
|
||||
boolean registerIsSigned) {
|
||||
out.annotate("DBG_START_LOCAL_EXTENDED");
|
||||
out.writeByte(DebugOpcode.DBG_START_LOCAL_EXTENDED.value);
|
||||
@ -497,7 +491,8 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessEndLocal(int startOffset, int length, int registerNum, boolean registerIsSigned) {
|
||||
public void ProcessEndLocal(int startDebugOffset, int length, int registerNum,
|
||||
boolean registerIsSigned) {
|
||||
out.annotate("DBG_END_LOCAL");
|
||||
out.writeByte(DebugOpcode.DBG_END_LOCAL.value);
|
||||
out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")");
|
||||
@ -509,7 +504,8 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessRestartLocal(int startOffset, int length, int registerNum, boolean registerIsSigned) {
|
||||
public void ProcessRestartLocal(int startDebugOffset, int length, int registerNum,
|
||||
boolean registerIsSigned) {
|
||||
out.annotate("DBG_RESTART_LOCAL");
|
||||
out.writeByte(DebugOpcode.DBG_RESTART_LOCAL.value);
|
||||
out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")");
|
||||
@ -521,19 +517,19 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessSetPrologueEnd(int startOffset) {
|
||||
public void ProcessSetPrologueEnd(int startDebugOffset) {
|
||||
out.annotate("DBG_SET_PROLOGUE_END");
|
||||
out.writeByte(DebugOpcode.DBG_SET_PROLOGUE_END.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessSetEpilogueBegin(int startOffset) {
|
||||
public void ProcessSetEpilogueBegin(int startDebugOffset) {
|
||||
out.annotate("DBG_SET_EPILOGUE_BEGIN");
|
||||
out.writeByte(DebugOpcode.DBG_SET_EPILOGUE_BEGIN.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessSetFile(int startOffset, int length, int nameIndex) {
|
||||
public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) {
|
||||
out.annotate("DBG_SET_FILE");
|
||||
out.writeByte(DebugOpcode.DBG_SET_FILE.value);
|
||||
if (nameIndex != -1) {
|
||||
@ -548,7 +544,8 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessSpecialOpcode(int startOffset, int debugOpcode, int lineDiff, int addressDiff) {
|
||||
public void ProcessSpecialOpcode(int startDebugOffset, int debugOpcode, int lineDiff,
|
||||
int addressDiff) {
|
||||
out.annotate("DBG_SPECIAL_OPCODE: line_diff=0x" + Integer.toHexString(lineDiff) + "(" +
|
||||
lineDiff +"),addressDiff=0x" + Integer.toHexString(addressDiff) + "(" + addressDiff +
|
||||
")");
|
||||
|
@ -113,12 +113,7 @@ public class FieldIdItem extends Item<FieldIdItem> {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getConciseIdentity() {
|
||||
String parentClass = classType.getTypeDescriptor();
|
||||
//strip off the leading L and trailing ;
|
||||
parentClass = parentClass.substring(1, parentClass.length() - 1);
|
||||
|
||||
return parentClass + "/" + fieldName.getStringValue() +
|
||||
":" + fieldType.getTypeDescriptor();
|
||||
return getFieldString();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
package org.jf.dexlib;
|
||||
|
||||
import org.jf.dexlib.Util.ExceptionWithContext;
|
||||
import org.jf.dexlib.Util.Input;
|
||||
|
||||
public class IndexedSection<T extends Item> extends Section<T> {
|
||||
@ -51,17 +52,30 @@ public class IndexedSection<T extends Item> extends Section<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item at the specified index in this section
|
||||
* Gets the item at the specified index in this section, or null if the index is -1
|
||||
* @param index the index of the item to get
|
||||
* @return the item at the specified index in this section
|
||||
* @throws IndexOutOfBoundsException if index is outside the bounds of this section
|
||||
* @return the item at the specified index in this section, or null if the index is -1
|
||||
*/
|
||||
public T getItemByIndex(int index) {
|
||||
public T getOptionalItemByIndex(int index) {
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getItemByIndex(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item at the specified index in this section
|
||||
* @param index the index of the item to get
|
||||
* @return the item at the specified index in this section
|
||||
*/
|
||||
public T getItemByIndex(int index) {
|
||||
try {
|
||||
//if index is out of bounds, just let it throw an exception
|
||||
return items.get(index);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error occured while retrieving the " + this.ItemType.TypeName +
|
||||
" item at index " + index);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user