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:
JesusFreke@JesusFreke.com 2010-01-12 07:56:16 +00:00
parent 3ae5a27b60
commit 16a911620c
106 changed files with 937 additions and 906 deletions

View File

@ -35,8 +35,8 @@ import org.antlr.stringtemplate.StringTemplate;
public class BlankMethodItem extends MethodItem { public class BlankMethodItem extends MethodItem {
private static StringTemplate template; private static StringTemplate template;
public BlankMethodItem(StringTemplateGroup stg, int offset) { public BlankMethodItem(StringTemplateGroup stg, int codeAddress) {
super(offset); super(codeAddress);
if (template == null) { if (template == null) {
template = stg.getInstanceOf("Blank"); template = stg.getInstanceOf("Blank");
} }

View File

@ -41,17 +41,17 @@ public class CatchMethodItem extends MethodItem {
private final LabelMethodItem tryEndLabel; private final LabelMethodItem tryEndLabel;
private final LabelMethodItem handlerLabel; 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) { TypeIdItem exceptionType, int startAddress, int endAddress, int handlerAddress) {
super(offset); super(codeAddress);
this.stg = stg; this.stg = stg;
this.exceptionType = exceptionType; this.exceptionType = exceptionType;
tryStartLabel = labelCache.internLabel(new LabelMethodItem(startAddress, stg, "try_start_")); tryStartLabel = labelCache.internLabel(new LabelMethodItem(startAddress, stg, "try_start_"));
tryStartLabel.setUncommented(); 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 //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(); tryEndLabel.setUncommented();
if (exceptionType == null) { if (exceptionType == null) {

View File

@ -36,7 +36,7 @@ public class CommentedOutMethodItem extends MethodItem {
private final MethodItem commentedOutMethodItem; private final MethodItem commentedOutMethodItem;
public CommentedOutMethodItem(StringTemplateGroup stg, MethodItem commentedOutMethodItem) { public CommentedOutMethodItem(StringTemplateGroup stg, MethodItem commentedOutMethodItem) {
super(commentedOutMethodItem.getOffset()); super(commentedOutMethodItem.getCodeAddress());
this.stg = stg; this.stg = stg;
this.commentedOutMethodItem = commentedOutMethodItem; this.commentedOutMethodItem = commentedOutMethodItem;
} }

View File

@ -36,8 +36,8 @@ public class DebugMethodItem extends MethodItem {
private final String templateName; private final String templateName;
private final int sortOrder; private final int sortOrder;
public DebugMethodItem(int offset, StringTemplateGroup stg, String templateName, int sortOrder) { public DebugMethodItem(int codeAddress, StringTemplateGroup stg, String templateName, int sortOrder) {
super(offset); super(codeAddress);
this.stg = stg; this.stg = stg;
this.templateName = templateName; this.templateName = templateName;
this.sortOrder = sortOrder; this.sortOrder = sortOrder;

View File

@ -31,11 +31,11 @@ package org.jf.baksmali.Adaptors;
import org.antlr.stringtemplate.StringTemplateGroup; import org.antlr.stringtemplate.StringTemplateGroup;
public class EndTryLabelMethodItem extends LabelMethodItem { public class EndTryLabelMethodItem extends LabelMethodItem {
private int labelOffset; private int endTryAddress;
public EndTryLabelMethodItem(int offset, StringTemplateGroup stg, int labelOffset) { public EndTryLabelMethodItem(int codeAddress, StringTemplateGroup stg, int endTryAddress) {
super(offset, stg, "try_end_"); super(codeAddress, stg, "try_end_");
this.labelOffset = labelOffset; this.endTryAddress = endTryAddress;
} }
public int getSortOrder() { public int getSortOrder() {
@ -43,7 +43,7 @@ public class EndTryLabelMethodItem extends LabelMethodItem {
return 101; return 101;
} }
public String getLabelOffset() { public String getLabelAddress() {
return Integer.toHexString(labelOffset); return Integer.toHexString(endTryAddress);
} }
} }

View File

@ -36,9 +36,9 @@ import org.jf.dexlib.CodeItem;
import java.util.Iterator; import java.util.Iterator;
public class ArrayDataMethodItem extends InstructionFormatMethodItem<ArrayDataPseudoInstruction> { public class ArrayDataMethodItem extends InstructionFormatMethodItem<ArrayDataPseudoInstruction> {
public ArrayDataMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public ArrayDataMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
ArrayDataPseudoInstruction instruction) { ArrayDataPseudoInstruction instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition; import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction10tMethodItem extends OffsetInstructionFormatMethodItem<Instruction10t> { 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) { StringTemplateGroup stg, Instruction10t instruction) {
super(labelCache, codeItem, offset, stg, instruction); super(labelCache, codeItem, codeAddress, stg, instruction);
} }
protected String getLabelPrefix() { protected String getLabelPrefix() {

View File

@ -34,8 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction10x;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction10xMethodItem extends InstructionFormatMethodItem<Instruction10x> { public class Instruction10xMethodItem extends InstructionFormatMethodItem<Instruction10x> {
public Instruction10xMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, Instruction10x instruction) { public Instruction10xMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
super(codeItem, offset, stg, instruction); Instruction10x instruction) {
super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction11n;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction11nMethodItem extends InstructionFormatMethodItem<Instruction11n> { public class Instruction11nMethodItem extends InstructionFormatMethodItem<Instruction11n> {
public Instruction11nMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction11nMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction11n instruction) { Instruction11n instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction11x;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction11xMethodItem extends InstructionFormatMethodItem<Instruction11x> { public class Instruction11xMethodItem extends InstructionFormatMethodItem<Instruction11x> {
public Instruction11xMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction11xMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction11x instruction) { Instruction11x instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction12x;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction12xMethodItem extends InstructionFormatMethodItem<Instruction12x> { public class Instruction12xMethodItem extends InstructionFormatMethodItem<Instruction12x> {
public Instruction12xMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction12xMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction12x instruction) { Instruction12x instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition; import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction20tMethodItem extends OffsetInstructionFormatMethodItem<Instruction20t> { 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) { StringTemplateGroup stg, Instruction20t instruction) {
super(labelCache, codeItem, offset, stg, instruction); super(labelCache, codeItem, codeAddress, stg, instruction);
} }
protected String getLabelPrefix() { protected String getLabelPrefix() {

View File

@ -35,9 +35,9 @@ import org.jf.dexlib.Code.Format.Instruction21c;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction21cMethodItem extends InstructionFormatMethodItem<Instruction21c> { public class Instruction21cMethodItem extends InstructionFormatMethodItem<Instruction21c> {
public Instruction21cMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction21cMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction21c instruction) { Instruction21c instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction21h;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction21hMethodItem extends InstructionFormatMethodItem<Instruction21h> { public class Instruction21hMethodItem extends InstructionFormatMethodItem<Instruction21h> {
public Instruction21hMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction21hMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction21h instruction) { Instruction21h instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction21s;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction21sMethodItem extends InstructionFormatMethodItem<Instruction21s> { public class Instruction21sMethodItem extends InstructionFormatMethodItem<Instruction21s> {
public Instruction21sMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction21sMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction21s instruction) { Instruction21s instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -35,9 +35,9 @@ import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition; import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction21tMethodItem extends OffsetInstructionFormatMethodItem<Instruction21t> { 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) { StringTemplateGroup stg, Instruction21t instruction) {
super(labelCache, codeItem, offset, stg, instruction); super(labelCache, codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction22b;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction22bMethodItem extends InstructionFormatMethodItem<Instruction22b> { public class Instruction22bMethodItem extends InstructionFormatMethodItem<Instruction22b> {
public Instruction22bMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction22bMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction22b instruction) { Instruction22b instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -35,9 +35,9 @@ import org.jf.dexlib.Code.Format.Instruction22c;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction22cMethodItem extends InstructionFormatMethodItem<Instruction22c> { public class Instruction22cMethodItem extends InstructionFormatMethodItem<Instruction22c> {
public Instruction22cMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction22cMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction22c instruction) { Instruction22c instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplate; import org.antlr.stringtemplate.StringTemplate;
public class Instruction22csMethodItem extends InstructionFormatMethodItem<Instruction22cs> { public class Instruction22csMethodItem extends InstructionFormatMethodItem<Instruction22cs> {
public Instruction22csMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction22csMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction22cs instruction) { Instruction22cs instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -35,9 +35,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplate; import org.antlr.stringtemplate.StringTemplate;
public class Instruction22csfMethodItem extends InstructionFormatMethodItem<Instruction22csf> { public class Instruction22csfMethodItem extends InstructionFormatMethodItem<Instruction22csf> {
public Instruction22csfMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction22csfMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction22csf instruction) { Instruction22csf instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction22s;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction22sMethodItem extends InstructionFormatMethodItem<Instruction22s> { public class Instruction22sMethodItem extends InstructionFormatMethodItem<Instruction22s> {
public Instruction22sMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction22sMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction22s instruction) { Instruction22s instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -35,9 +35,9 @@ import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition; import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction22tMethodItem extends OffsetInstructionFormatMethodItem<Instruction22t> { 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) { StringTemplateGroup stg, Instruction22t instruction) {
super(labelCache, codeItem, offset, stg, instruction); super(labelCache, codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction22x;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction22xMethodItem extends InstructionFormatMethodItem<Instruction22x> { public class Instruction22xMethodItem extends InstructionFormatMethodItem<Instruction22x> {
public Instruction22xMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction22xMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction22x instruction) { Instruction22x instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction23x;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction23xMethodItem extends InstructionFormatMethodItem<Instruction23x> { public class Instruction23xMethodItem extends InstructionFormatMethodItem<Instruction23x> {
public Instruction23xMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction23xMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction23x instruction) { Instruction23x instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition; import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction30tMethodItem extends OffsetInstructionFormatMethodItem<Instruction30t> { 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) { StringTemplateGroup stg, Instruction30t instruction) {
super(labelCache, codeItem, offset, stg, instruction); super(labelCache, codeItem, codeAddress, stg, instruction);
} }
protected String getLabelPrefix() { protected String getLabelPrefix() {

View File

@ -35,9 +35,9 @@ import org.jf.dexlib.Code.Format.Instruction31c;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction31cMethodItem extends InstructionFormatMethodItem<Instruction31c> { public class Instruction31cMethodItem extends InstructionFormatMethodItem<Instruction31c> {
public Instruction31cMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction31cMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction31c instruction) { Instruction31c instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction31i;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction31iMethodItem extends InstructionFormatMethodItem<Instruction31i> { public class Instruction31iMethodItem extends InstructionFormatMethodItem<Instruction31i> {
public Instruction31iMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction31iMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction31i instruction) { Instruction31i instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -36,9 +36,9 @@ import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition; import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction31tMethodItem extends OffsetInstructionFormatMethodItem<Instruction31t> { 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) { StringTemplateGroup stg, Instruction31t instruction) {
super(labelCache, codeItem, offset, stg, instruction); super(labelCache, codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction32x;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction32xMethodItem extends InstructionFormatMethodItem<Instruction32x> { public class Instruction32xMethodItem extends InstructionFormatMethodItem<Instruction32x> {
public Instruction32xMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction32xMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction32x instruction) { Instruction32x instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -35,9 +35,9 @@ import org.jf.dexlib.Code.Format.Instruction35c;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction35cMethodItem extends InstructionFormatMethodItem<Instruction35c> { public class Instruction35cMethodItem extends InstructionFormatMethodItem<Instruction35c> {
public Instruction35cMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction35cMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction35c instruction) { Instruction35c instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -36,9 +36,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplate; import org.antlr.stringtemplate.StringTemplate;
public class Instruction35msMethodItem extends InstructionFormatMethodItem<Instruction35ms> { public class Instruction35msMethodItem extends InstructionFormatMethodItem<Instruction35ms> {
public Instruction35msMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction35msMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction35ms instruction) { Instruction35ms instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -35,9 +35,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplate; import org.antlr.stringtemplate.StringTemplate;
public class Instruction35msfMethodItem extends InstructionFormatMethodItem<Instruction35msf> { public class Instruction35msfMethodItem extends InstructionFormatMethodItem<Instruction35msf> {
public Instruction35msfMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction35msfMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction35msf instruction) { Instruction35msf instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -35,9 +35,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplate; import org.antlr.stringtemplate.StringTemplate;
public class Instruction35sMethodItem extends InstructionFormatMethodItem<Instruction35s> { public class Instruction35sMethodItem extends InstructionFormatMethodItem<Instruction35s> {
public Instruction35sMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction35sMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction35s instruction) { Instruction35s instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -35,9 +35,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplate; import org.antlr.stringtemplate.StringTemplate;
public class Instruction35sfMethodItem extends InstructionFormatMethodItem<Instruction35sf> { public class Instruction35sfMethodItem extends InstructionFormatMethodItem<Instruction35sf> {
public Instruction35sfMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction35sfMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction35sf instruction) { Instruction35sf instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -36,9 +36,9 @@ import org.jf.dexlib.Code.Format.Instruction3rc;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction3rcMethodItem extends InstructionFormatMethodItem<Instruction3rc> { public class Instruction3rcMethodItem extends InstructionFormatMethodItem<Instruction3rc> {
public Instruction3rcMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction3rcMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction3rc instruction) { Instruction3rc instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -35,9 +35,9 @@ import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.RegisterFormatter; import org.jf.baksmali.Adaptors.RegisterFormatter;
public class Instruction3rmsMethodItem extends InstructionFormatMethodItem<Instruction3rms> { public class Instruction3rmsMethodItem extends InstructionFormatMethodItem<Instruction3rms> {
public Instruction3rmsMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction3rmsMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction3rms instruction) { Instruction3rms instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -36,9 +36,9 @@ import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplate; import org.antlr.stringtemplate.StringTemplate;
public class Instruction3rmsfMethodItem extends InstructionFormatMethodItem<Instruction3rmsf> { public class Instruction3rmsfMethodItem extends InstructionFormatMethodItem<Instruction3rmsf> {
public Instruction3rmsfMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction3rmsfMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction3rmsf instruction) { Instruction3rmsf instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -34,9 +34,9 @@ import org.jf.dexlib.Code.Format.Instruction51l;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
public class Instruction51lMethodItem extends InstructionFormatMethodItem<Instruction51l> { public class Instruction51lMethodItem extends InstructionFormatMethodItem<Instruction51l> {
public Instruction51lMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction51lMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
Instruction51l instruction) { Instruction51l instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -41,8 +41,8 @@ public abstract class InstructionFormatMethodItem<T extends Instruction> extends
protected final T instruction; protected final T instruction;
public InstructionFormatMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, T instruction) { public InstructionFormatMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg, T instruction) {
super(offset); super(codeAddress);
this.codeItem = codeItem; this.codeItem = codeItem;
this.stg = stg; this.stg = stg;
this.instruction = instruction; this.instruction = instruction;

View File

@ -40,11 +40,11 @@ public abstract class OffsetInstructionFormatMethodItem<T extends Instruction &
extends InstructionFormatMethodItem<T> { extends InstructionFormatMethodItem<T> {
protected LabelMethodItem label; 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) { 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); label = labelCache.internLabel(label);
} }

View File

@ -43,15 +43,15 @@ public class PackedSwitchMethodItem extends InstructionFormatMethodItem<PackedSw
implements Iterable<LabelMethodItem> { implements Iterable<LabelMethodItem> {
private List<LabelMethodItem> labels = new ArrayList<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, StringTemplateGroup stg, PackedSwitchDataPseudoInstruction instruction,
int baseAddress) { int baseCodeAddress) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
Iterator<PackedSwitchDataPseudoInstruction.PackedSwitchTarget> iterator = instruction.iterateKeysAndTargets(); Iterator<PackedSwitchDataPseudoInstruction.PackedSwitchTarget> iterator = instruction.iterateKeysAndTargets();
while (iterator.hasNext()) { while (iterator.hasNext()) {
PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next(); 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); label = labelCache.internLabel(label);
labels.add(label); labels.add(label);
} }

View File

@ -43,10 +43,10 @@ public class SparseSwitchMethodItem extends InstructionFormatMethodItem<SparseSw
implements Iterable<LabelMethodItem> { implements Iterable<LabelMethodItem> {
private List<SparseSwitchTarget> targets = new ArrayList<SparseSwitchTarget>(); 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, StringTemplateGroup stg, SparseSwitchDataPseudoInstruction instruction,
int baseAddress) { int baseAddress) {
super(codeItem, offset, stg, instruction); super(codeItem, targetAddressOffset, stg, instruction);
Iterator<SparseSwitchDataPseudoInstruction.SparseSwitchTarget> iterator = instruction.iterateKeysAndTargets(); Iterator<SparseSwitchDataPseudoInstruction.SparseSwitchTarget> iterator = instruction.iterateKeysAndTargets();
@ -55,7 +55,7 @@ public class SparseSwitchMethodItem extends InstructionFormatMethodItem<SparseSw
SparseSwitchTarget sparseSwitchTarget = new SparseSwitchTarget(); SparseSwitchTarget sparseSwitchTarget = new SparseSwitchTarget();
sparseSwitchTarget.Key = target.key; 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); label = labelCache.internLabel(label);
sparseSwitchTarget.Target = label; sparseSwitchTarget.Target = label;

View File

@ -44,9 +44,9 @@ public class UnresolvedNullReferenceMethodItem extends InstructionFormatMethodIt
this.isLastInstruction = isLastInstruction; this.isLastInstruction = isLastInstruction;
} }
public UnresolvedNullReferenceMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public UnresolvedNullReferenceMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
UnresolvedNullReference instruction) { UnresolvedNullReference instruction) {
super(codeItem, offset, stg, instruction); super(codeItem, codeAddress, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {

View File

@ -38,8 +38,8 @@ public class LabelMethodItem extends MethodItem {
private int labelSequence; private int labelSequence;
private boolean isCommentedOut = true; private boolean isCommentedOut = true;
public LabelMethodItem(int offset, StringTemplateGroup stg, String labelPrefix) { public LabelMethodItem(int codeAddress, StringTemplateGroup stg, String labelPrefix) {
super(offset); super(codeAddress);
this.stg = stg; this.stg = stg;
this.labelPrefix = labelPrefix; this.labelPrefix = labelPrefix;
} }
@ -69,7 +69,7 @@ public class LabelMethodItem extends MethodItem {
public int hashCode() { public int hashCode() {
//force it to call equals when two labels are at the same address //force it to call equals when two labels are at the same address
return getOffset(); return getCodeAddress();
} }
public boolean equals(Object o) { public boolean equals(Object o) {
@ -86,7 +86,7 @@ public class LabelMethodItem extends MethodItem {
if (baksmali.useSequentialLabels) { if (baksmali.useSequentialLabels) {
template.setAttribute("Suffix", Integer.toHexString(labelSequence)); template.setAttribute("Suffix", Integer.toHexString(labelSequence));
} else { } else {
template.setAttribute("Suffix", getLabelOffset()); template.setAttribute("Suffix", getLabelAddress());
} }
return template.toString(); return template.toString();
} }
@ -95,8 +95,8 @@ public class LabelMethodItem extends MethodItem {
return labelPrefix; return labelPrefix;
} }
public String getLabelOffset() { public String getLabelAddress() {
return getHexOffset(); return Integer.toHexString(this.getCodeAddress());
} }
public int getLabelSequence() { public int getLabelSequence() {

View File

@ -40,10 +40,10 @@ public class LocalDebugMethodItem extends DebugMethodItem {
private final String type; private final String type;
private final String signature; 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, int sortOrder, int register, StringIdItem name, TypeIdItem type,
StringIdItem signature) { StringIdItem signature) {
super(offset, stg, templateName, sortOrder); super(codeAddress, stg, templateName, sortOrder);
this.register = RegisterFormatter.formatRegister(codeItem, register); this.register = RegisterFormatter.formatRegister(codeItem, register);
this.name = name==null?null:name.getStringValue(); this.name = name==null?null:name.getStringValue();
this.type = type==null?null:type.getTypeDescriptor(); this.type = type==null?null:type.getTypeDescriptor();

View File

@ -206,25 +206,25 @@ public class MethodDefinition {
if (baksmali.deodexUtil != null && dexFile.isOdex()) { if (baksmali.deodexUtil != null && dexFile.isOdex()) {
List<Instruction> instructions = baksmali.deodexUtil.deodexerizeCode(codeItem); List<Instruction> instructions = baksmali.deodexUtil.deodexerizeCode(codeItem);
int offset = 0; int currentCodeAddress = 0;
for (Instruction instruction: instructions) { for (Instruction instruction: instructions) {
if (instruction.opcode == Opcode.PACKED_SWITCH) { if (instruction.opcode == Opcode.PACKED_SWITCH) {
Instruction31t ins = (Instruction31t)instruction; Instruction31t ins = (Instruction31t)instruction;
packedSwitchMap.put(offset + ins.getOffset(), offset); packedSwitchMap.put(currentCodeAddress + ins.getTargetAddressOffset(), currentCodeAddress);
} else if (instruction.opcode == Opcode.SPARSE_SWITCH) { } else if (instruction.opcode == Opcode.SPARSE_SWITCH) {
Instruction31t ins = (Instruction31t)instruction; 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) { for (Instruction instruction: instructions) {
addMethodItemsForInstruction(offset, instruction, false); addMethodItemsForInstruction(currentCodeAddress, instruction, false);
blanks.add(new BlankMethodItem(stg, offset)); blanks.add(new BlankMethodItem(stg, currentCodeAddress));
offset += instruction.getSize(offset*2)/2; currentCodeAddress += instruction.getSize(currentCodeAddress);
} }
/* /*
@ -244,25 +244,24 @@ public class MethodDefinition {
} }
} }
} else { } else {
int currentCodeOffset = 0; int currentCodeAddress = 0;
for (Instruction instruction: codeItem.getInstructions()) { for (Instruction instruction: codeItem.getInstructions()) {
if (instruction.opcode == Opcode.PACKED_SWITCH) { if (instruction.opcode == Opcode.PACKED_SWITCH) {
OffsetInstruction offsetInstruction = (OffsetInstruction)instruction; 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) { } else if (instruction.opcode == Opcode.SPARSE_SWITCH) {
OffsetInstruction offsetInstruction = (OffsetInstruction)instruction; 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()) { for (Instruction instruction: codeItem.getInstructions()) {
int offset = currentCodeOffset/2; addMethodItemsForInstruction(currentCodeAddress, instruction, false);
addMethodItemsForInstruction(offset, instruction, false); blanks.add(new BlankMethodItem(stg, currentCodeAddress));
blanks.add(new BlankMethodItem(stg, offset)); currentCodeAddress += instruction.getSize(currentCodeAddress);
currentCodeOffset += instruction.getSize(currentCodeOffset);
} }
} }
@ -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()) { switch (instruction.getFormat()) {
case Format10t: case Format10t:
addOffsetInstructionMethodItem( addOffsetInstructionMethodItem(
new Instruction10tMethodItem(labels, codeItem, offset, stg,(Instruction10t)instruction), new Instruction10tMethodItem(labels, codeItem, codeAddress, stg,(Instruction10t)instruction),
commentedOut); commentedOut);
return; return;
case Format10x: case Format10x:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction10xMethodItem(codeItem, offset, stg, (Instruction10x)instruction), new Instruction10xMethodItem(codeItem, codeAddress, stg, (Instruction10x)instruction),
commentedOut); commentedOut);
return; return;
case Format11n: case Format11n:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction11nMethodItem(codeItem, offset, stg, (Instruction11n)instruction), new Instruction11nMethodItem(codeItem, codeAddress, stg, (Instruction11n)instruction),
commentedOut); commentedOut);
return; return;
case Format11x: case Format11x:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction11xMethodItem(codeItem, offset, stg, (Instruction11x)instruction), new Instruction11xMethodItem(codeItem, codeAddress, stg, (Instruction11x)instruction),
commentedOut); commentedOut);
return; return;
case Format12x: case Format12x:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction12xMethodItem(codeItem, offset, stg, (Instruction12x)instruction), new Instruction12xMethodItem(codeItem, codeAddress, stg, (Instruction12x)instruction),
commentedOut); commentedOut);
return; return;
case Format20t: case Format20t:
addOffsetInstructionMethodItem( addOffsetInstructionMethodItem(
new Instruction20tMethodItem(labels, codeItem, offset, stg, (Instruction20t)instruction), new Instruction20tMethodItem(labels, codeItem, codeAddress, stg, (Instruction20t)instruction),
commentedOut); commentedOut);
return; return;
case Format21c: case Format21c:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction21cMethodItem(codeItem, offset, stg, (Instruction21c)instruction), new Instruction21cMethodItem(codeItem, codeAddress, stg, (Instruction21c)instruction),
commentedOut); commentedOut);
return; return;
case Format21h: case Format21h:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction21hMethodItem(codeItem, offset, stg, (Instruction21h)instruction), new Instruction21hMethodItem(codeItem, codeAddress, stg, (Instruction21h)instruction),
commentedOut); commentedOut);
return; return;
case Format21s: case Format21s:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction21sMethodItem(codeItem, offset, stg, (Instruction21s)instruction), new Instruction21sMethodItem(codeItem, codeAddress, stg, (Instruction21s)instruction),
commentedOut); commentedOut);
return; return;
case Format21t: case Format21t:
addOffsetInstructionMethodItem( addOffsetInstructionMethodItem(
new Instruction21tMethodItem(labels, codeItem, offset, stg, (Instruction21t)instruction), new Instruction21tMethodItem(labels, codeItem, codeAddress, stg, (Instruction21t)instruction),
commentedOut); commentedOut);
return; return;
case Format22b: case Format22b:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction22bMethodItem(codeItem, offset, stg, (Instruction22b)instruction), new Instruction22bMethodItem(codeItem, codeAddress, stg, (Instruction22b)instruction),
commentedOut); commentedOut);
return; return;
case Format22c: case Format22c:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction22cMethodItem(codeItem, offset, stg, (Instruction22c)instruction), new Instruction22cMethodItem(codeItem, codeAddress, stg, (Instruction22c)instruction),
commentedOut); commentedOut);
return; return;
case Format22cs: case Format22cs:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction22csMethodItem(codeItem, offset, stg, (Instruction22cs)instruction), new Instruction22csMethodItem(codeItem, codeAddress, stg, (Instruction22cs)instruction),
commentedOut); commentedOut);
return; return;
case Format22csf: case Format22csf:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction22csfMethodItem(codeItem, offset, stg, (Instruction22csf)instruction), new Instruction22csfMethodItem(codeItem, codeAddress, stg, (Instruction22csf)instruction),
commentedOut); commentedOut);
return; return;
case Format22s: case Format22s:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction22sMethodItem(codeItem, offset, stg, (Instruction22s)instruction), new Instruction22sMethodItem(codeItem, codeAddress, stg, (Instruction22s)instruction),
commentedOut); commentedOut);
return; return;
case Format22t: case Format22t:
addOffsetInstructionMethodItem( addOffsetInstructionMethodItem(
new Instruction22tMethodItem(labels, codeItem, offset, stg, (Instruction22t)instruction), new Instruction22tMethodItem(labels, codeItem, codeAddress, stg, (Instruction22t)instruction),
commentedOut); commentedOut);
return; return;
case Format22x: case Format22x:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction22xMethodItem(codeItem, offset, stg, (Instruction22x)instruction), new Instruction22xMethodItem(codeItem, codeAddress, stg, (Instruction22x)instruction),
commentedOut); commentedOut);
return; return;
case Format23x: case Format23x:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction23xMethodItem(codeItem, offset, stg, (Instruction23x)instruction), new Instruction23xMethodItem(codeItem, codeAddress, stg, (Instruction23x)instruction),
commentedOut); commentedOut);
return; return;
case Format30t: case Format30t:
addOffsetInstructionMethodItem( addOffsetInstructionMethodItem(
new Instruction30tMethodItem(labels, codeItem, offset, stg, (Instruction30t)instruction), new Instruction30tMethodItem(labels, codeItem, codeAddress, stg, (Instruction30t)instruction),
commentedOut); commentedOut);
return; return;
case Format31c: case Format31c:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction31cMethodItem(codeItem, offset, stg, (Instruction31c)instruction), new Instruction31cMethodItem(codeItem, codeAddress, stg, (Instruction31c)instruction),
commentedOut); commentedOut);
return; return;
case Format31i: case Format31i:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction31iMethodItem(codeItem, offset, stg, (Instruction31i)instruction), new Instruction31iMethodItem(codeItem, codeAddress, stg, (Instruction31i)instruction),
commentedOut); commentedOut);
return; return;
case Format31t: case Format31t:
addOffsetInstructionMethodItem( addOffsetInstructionMethodItem(
new Instruction31tMethodItem(labels, codeItem, offset, stg, (Instruction31t)instruction), new Instruction31tMethodItem(labels, codeItem, codeAddress, stg, (Instruction31t)instruction),
commentedOut); commentedOut);
return; return;
case Format32x: case Format32x:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction32xMethodItem(codeItem, offset, stg, (Instruction32x)instruction), new Instruction32xMethodItem(codeItem, codeAddress, stg, (Instruction32x)instruction),
commentedOut); commentedOut);
return; return;
case Format35c: case Format35c:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction35cMethodItem(codeItem, offset, stg, (Instruction35c)instruction), new Instruction35cMethodItem(codeItem, codeAddress, stg, (Instruction35c)instruction),
commentedOut); commentedOut);
return; return;
case Format35s: case Format35s:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction35sMethodItem(codeItem, offset, stg, (Instruction35s)instruction), new Instruction35sMethodItem(codeItem, codeAddress, stg, (Instruction35s)instruction),
commentedOut); commentedOut);
return; return;
case Format35sf: case Format35sf:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction35sfMethodItem(codeItem, offset, stg, (Instruction35sf)instruction), new Instruction35sfMethodItem(codeItem, codeAddress, stg, (Instruction35sf)instruction),
commentedOut); commentedOut);
return; return;
case Format35ms: case Format35ms:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction35msMethodItem(codeItem, offset, stg, (Instruction35ms)instruction), new Instruction35msMethodItem(codeItem, codeAddress, stg, (Instruction35ms)instruction),
commentedOut); commentedOut);
return; return;
case Format35msf: case Format35msf:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction35msfMethodItem(codeItem, offset, stg, (Instruction35msf)instruction), new Instruction35msfMethodItem(codeItem, codeAddress, stg, (Instruction35msf)instruction),
commentedOut); commentedOut);
return; return;
case Format3rc: case Format3rc:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction3rcMethodItem(codeItem, offset, stg, (Instruction3rc)instruction), new Instruction3rcMethodItem(codeItem, codeAddress, stg, (Instruction3rc)instruction),
commentedOut); commentedOut);
return; return;
case Format3rms: case Format3rms:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction3rmsMethodItem(codeItem, offset, stg, (Instruction3rms)instruction), new Instruction3rmsMethodItem(codeItem, codeAddress, stg, (Instruction3rms)instruction),
commentedOut); commentedOut);
return; return;
case Format3rmsf: case Format3rmsf:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction3rmsfMethodItem(codeItem, offset, stg, (Instruction3rmsf)instruction), new Instruction3rmsfMethodItem(codeItem, codeAddress, stg, (Instruction3rmsf)instruction),
commentedOut); commentedOut);
return; return;
case Format51l: case Format51l:
addInstructionMethodItem( addInstructionMethodItem(
new Instruction51lMethodItem(codeItem, offset, stg, (Instruction51l)instruction), new Instruction51lMethodItem(codeItem, codeAddress, stg, (Instruction51l)instruction),
commentedOut); commentedOut);
return; return;
case ArrayData: case ArrayData:
addInstructionMethodItem( addInstructionMethodItem(
new ArrayDataMethodItem(codeItem, offset, stg, (ArrayDataPseudoInstruction)instruction), new ArrayDataMethodItem(codeItem, codeAddress, stg, (ArrayDataPseudoInstruction)instruction),
commentedOut); commentedOut);
return; return;
case PackedSwitchData: case PackedSwitchData:
{ {
final Integer baseAddress = packedSwitchMap.get(offset); final Integer baseAddress = packedSwitchMap.get(codeAddress);
if (baseAddress != null) { if (baseAddress != null) {
PackedSwitchDataPseudoInstruction packedSwitchInstruction = PackedSwitchDataPseudoInstruction packedSwitchInstruction =
(PackedSwitchDataPseudoInstruction)instruction; (PackedSwitchDataPseudoInstruction)instruction;
PackedSwitchMethodItem packedSwitch = new PackedSwitchMethodItem(labels, codeItem, offset, stg, PackedSwitchMethodItem packedSwitch = new PackedSwitchMethodItem(labels, codeItem, codeAddress, stg,
packedSwitchInstruction, baseAddress); packedSwitchInstruction, baseAddress);
addInstructionMethodItem(packedSwitch, commentedOut); addInstructionMethodItem(packedSwitch, commentedOut);
@ -487,13 +486,13 @@ public class MethodDefinition {
} }
case SparseSwitchData: case SparseSwitchData:
{ {
final Integer baseAddress = sparseSwitchMap.get(offset); final Integer baseAddress = sparseSwitchMap.get(codeAddress);
if (baseAddress != null) { if (baseAddress != null) {
SparseSwitchDataPseudoInstruction sparseSwitchInstruction = SparseSwitchDataPseudoInstruction sparseSwitchInstruction =
(SparseSwitchDataPseudoInstruction)instruction; (SparseSwitchDataPseudoInstruction)instruction;
SparseSwitchMethodItem sparseSwitch = new SparseSwitchMethodItem(labels, codeItem, offset, stg, SparseSwitchMethodItem sparseSwitch = new SparseSwitchMethodItem(labels, codeItem, codeAddress, stg,
sparseSwitchInstruction, baseAddress); sparseSwitchInstruction, baseAddress);
addInstructionMethodItem(sparseSwitch, commentedOut); addInstructionMethodItem(sparseSwitch, commentedOut);
@ -507,16 +506,16 @@ public class MethodDefinition {
} }
case UnresolvedNullReference: case UnresolvedNullReference:
{ {
addInstructionMethodItem(new UnresolvedNullReferenceMethodItem(codeItem, offset, stg, addInstructionMethodItem(new UnresolvedNullReferenceMethodItem(codeItem, codeAddress, stg,
(UnresolvedNullReference)instruction), commentedOut); (UnresolvedNullReference)instruction), commentedOut);
addMethodItemsForInstruction(offset, ((UnresolvedNullReference)instruction).OriginalInstruction, addMethodItemsForInstruction(codeAddress, ((UnresolvedNullReference)instruction).OriginalInstruction,
true); true);
return; return;
} }
case DeadInstruction: case DeadInstruction:
{ {
//TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh. //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; return;
} }
} }
@ -527,14 +526,14 @@ public class MethodDefinition {
return; return;
} }
for (CodeItem.TryItem tryItem: codeItem.getTries()) { for (CodeItem.TryItem tryItem: codeItem.getTries()) {
int startAddress = tryItem.getStartAddress(); int startAddress = tryItem.getStartCodeAddress();
int endAddress = tryItem.getStartAddress() + tryItem.getInstructionCount(); int endAddress = tryItem.getStartCodeAddress() + tryItem.getTryLength();
/** /**
* The end address points to the address immediately after the end of the last * The end address points to the address immediately after the end of the last
* instruction that the try block covers. We want the .catch directive and end_try * 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 * 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)); int index = Collections.binarySearch(instructions, new BlankMethodItem(stg, endAddress));
if (index < 0) { if (index < 0) {
@ -546,7 +545,7 @@ public class MethodDefinition {
//this try item ends at the next to last instruction. //this try item ends at the next to last instruction.
//otherwise, if the end address is past the address of the last instruction, //otherwise, if the end address is past the address of the last instruction,
//thin this try item ends at 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 //get the address for the next to last instruction
index -= 2; index -= 2;
} else { } else {
@ -557,20 +556,20 @@ public class MethodDefinition {
index -= 2; index -= 2;
} }
int lastInstructionOffset = instructions.get(index).getOffset(); int lastInstructionAddress = instructions.get(index).getCodeAddress();
//add the catch all handler if it exists //add the catch all handler if it exists
int catchAllAddress = tryItem.encodedCatchHandler.getCatchAllHandlerAddress(); int catchAllAddress = tryItem.encodedCatchHandler.getCatchAllHandlerAddress();
if (catchAllAddress != -1) { if (catchAllAddress != -1) {
CatchMethodItem catchMethodItem = new CatchMethodItem(labels, lastInstructionOffset, stg, null, CatchMethodItem catchMethodItem = new CatchMethodItem(labels, lastInstructionAddress, stg, null,
startAddress, endAddress, catchAllAddress); startAddress, endAddress, catchAllAddress);
catches.add(catchMethodItem); catches.add(catchMethodItem);
} }
//add the rest of the handlers //add the rest of the handlers
for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) { for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) {
//use the offset from the last covered instruction //use the address from the last covered instruction
CatchMethodItem catchMethodItem = new CatchMethodItem(labels, lastInstructionOffset, stg, CatchMethodItem catchMethodItem = new CatchMethodItem(labels, lastInstructionAddress, stg,
handler.exceptionType, startAddress, endAddress, handler.getHandlerAddress()); handler.exceptionType, startAddress, endAddress, handler.getHandlerAddress());
catches.add(catchMethodItem); catches.add(catchMethodItem);
} }

View File

@ -29,26 +29,21 @@
package org.jf.baksmali.Adaptors; package org.jf.baksmali.Adaptors;
public abstract class MethodItem implements Comparable<MethodItem> { public abstract class MethodItem implements Comparable<MethodItem> {
private int offset; private int codeAddress;
protected MethodItem(int offset) { protected MethodItem(int codeAddress) {
this.offset = offset; this.codeAddress = codeAddress;
} }
public int getOffset() { public int getCodeAddress() {
return offset; return codeAddress;
} }
public String getHexOffset() { //return an arbitrary integer that determines how this item will be sorted with others at the same address
return Integer.toHexString(offset);
}
//return an arbitrary integer that determines how this item will be sorted with
//others at the same offset
public abstract int getSortOrder(); public abstract int getSortOrder();
public int compareTo(MethodItem methodItem) { public int compareTo(MethodItem methodItem) {
int result = ((Integer)offset).compareTo(methodItem.offset); int result = ((Integer) codeAddress).compareTo(methodItem.codeAddress);
if (result == 0){ if (result == 0){
return ((Integer)getSortOrder()).compareTo(methodItem.getSortOrder()); return ((Integer)getSortOrder()).compareTo(methodItem.getSortOrder());

View File

@ -303,7 +303,7 @@ public class main {
Option sequentialLabelsOption = OptionBuilder.withLongOpt("sequential-labels") Option sequentialLabelsOption = OptionBuilder.withLongOpt("sequential-labels")
.withDescription("create label names using a sequential numbering scheme per label type, rather than " + .withDescription("create label names using a sequential numbering scheme per label type, rather than " +
"using the bytecode offset") "using the bytecode address")
.create("q"); .create("q");
Option noDebugInfoOption = OptionBuilder.withLongOpt("no-debug-info") Option noDebugInfoOption = OptionBuilder.withLongOpt("no-debug-info")

View File

@ -28,6 +28,7 @@
package org.jf.dexlib; package org.jf.dexlib;
import org.jf.dexlib.Util.ExceptionWithContext;
import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.Input;
import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.AnnotatedOutput;
@ -166,8 +167,8 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
/** {@inheritDoc} */ /** {@inheritDoc} */
protected void readItem(Input in, ReadContext readContext) { protected void readItem(Input in, ReadContext readContext) {
classAnnotations = (AnnotationSetItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_ANNOTATION_SET_ITEM, classAnnotations = (AnnotationSetItem)readContext.getOptionalOffsettedItemByOffset(
in.readInt()); ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
fieldAnnotationFields = new FieldIdItem[in.readInt()]; fieldAnnotationFields = new FieldIdItem[in.readInt()];
fieldAnnotations = new AnnotationSetItem[fieldAnnotationFields.length]; fieldAnnotations = new AnnotationSetItem[fieldAnnotationFields.length];
@ -178,21 +179,36 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
parameterAnnotations = new AnnotationSetRefList[parameterAnnotationMethods.length]; parameterAnnotations = new AnnotationSetRefList[parameterAnnotationMethods.length];
for (int i=0; i<fieldAnnotations.length; i++) { for (int i=0; i<fieldAnnotations.length; i++) {
fieldAnnotationFields[i] = dexFile.FieldIdsSection.getItemByIndex(in.readInt()); try {
fieldAnnotations[i] = (AnnotationSetItem)readContext.getOffsettedItemByOffset( fieldAnnotationFields[i] = dexFile.FieldIdsSection.getItemByIndex(in.readInt());
ItemType.TYPE_ANNOTATION_SET_ITEM, 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++) { for (int i=0; i<methodAnnotations.length; i++) {
methodAnnotationMethods[i] = dexFile.MethodIdsSection.getItemByIndex(in.readInt()); try {
methodAnnotations[i] = (AnnotationSetItem)readContext.getOffsettedItemByOffset( methodAnnotationMethods[i] = dexFile.MethodIdsSection.getItemByIndex(in.readInt());
ItemType.TYPE_ANNOTATION_SET_ITEM, 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++) { for (int i=0; i<parameterAnnotations.length; i++) {
parameterAnnotationMethods[i] = dexFile.MethodIdsSection.getItemByIndex(in.readInt()); try {
parameterAnnotations[i] = (AnnotationSetRefList)readContext.getOffsettedItemByOffset( parameterAnnotationMethods[i] = dexFile.MethodIdsSection.getItemByIndex(in.readInt());
ItemType.TYPE_ANNOTATION_SET_REF_LIST, 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,13 +305,17 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
} }
} }
/** {@inheritDoc} */public ItemType getItemType() { /** {@inheritDoc} */
public ItemType getItemType() {
return ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM; return ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM;
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public String getConciseIdentity() { public String getConciseIdentity() {
return "annotation_directory_item @0x" + Integer.toHexString(getOffset()); if (parent == null) {
return "annotation_directory_item @0x" + Integer.toHexString(getOffset());
}
return "annotation_directory_item @0x" + Integer.toHexString(getOffset()) + " (" + parent.getClassType() + ")";
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@ -327,7 +347,13 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
*/ */
public void iterateFieldAnnotations(FieldAnnotationIteratorDelegate delegate) { public void iterateFieldAnnotations(FieldAnnotationIteratorDelegate delegate) {
for (int i=0; i<fieldAnnotationFields.length; i++) { for (int i=0; i<fieldAnnotationFields.length; i++) {
delegate.processFieldAnnotations(fieldAnnotationFields[i], fieldAnnotations[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) { public void iterateMethodAnnotations(MethodAnnotationIteratorDelegate delegate) {
for (int i=0; i<methodAnnotationMethods.length; i++) { for (int i=0; i<methodAnnotationMethods.length; i++) {
delegate.processMethodAnnotations(methodAnnotationMethods[i], methodAnnotations[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) { public void iterateParameterAnnotations(ParameterAnnotationIteratorDelegate delegate) {
for (int i=0; i<parameterAnnotationMethods.length; i++) { for (int i=0; i<parameterAnnotationMethods.length; i++) {
delegate.processParameterAnnotations(parameterAnnotationMethods[i], parameterAnnotations[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()));
}
} }
} }

View File

@ -76,7 +76,7 @@ public class AnnotationSetRefList extends Item<AnnotationSetRefList> {
annotationSets = new AnnotationSetItem[in.readInt()]; annotationSets = new AnnotationSetItem[in.readInt()];
for (int i=0; i<annotationSets.length; i++) { 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()); ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
} }
} }

View File

@ -28,6 +28,8 @@
package org.jf.dexlib; package org.jf.dexlib;
import org.jf.dexlib.Util.ExceptionWithContext;
public enum AnnotationVisibility { public enum AnnotationVisibility {
BUILD((byte)0), BUILD((byte)0),
RUNTIME((byte)1), RUNTIME((byte)1),
@ -47,7 +49,7 @@ public enum AnnotationVisibility {
case (byte)2: case (byte)2:
return SYSTEM; return SYSTEM;
default: default:
throw new RuntimeException("Invalid annotation visibility value " + value); throw new RuntimeException("Invalid annotation visibility value: " + value);
} }
} }
} }

View File

@ -122,24 +122,40 @@ public class ClassDataItem extends Item<ClassDataItem> {
EncodedField previousEncodedField = null; EncodedField previousEncodedField = null;
for (int i=0; i<staticFields.length; i++) { for (int i=0; i<staticFields.length; i++) {
staticFields[i] = previousEncodedField = new EncodedField(dexFile, in, previousEncodedField); 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; previousEncodedField = null;
for (int i=0; i<instanceFields.length; i++) { for (int i=0; i<instanceFields.length; i++) {
instanceFields[i] = previousEncodedField = new EncodedField(dexFile, in, previousEncodedField); 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; EncodedMethod previousEncodedMethod = null;
for (int i=0; i<directMethods.length; i++) { for (int i=0; i<directMethods.length; i++) {
directMethods[i] = previousEncodedMethod = new EncodedMethod(dexFile, readContext, in, try {
previousEncodedMethod); 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; previousEncodedMethod = null;
for (int i=0; i<virtualMethods.length; i++) { for (int i=0; i<virtualMethods.length; i++) {
virtualMethods[i] = previousEncodedMethod = new EncodedMethod(dexFile, readContext, in, try {
previousEncodedMethod); 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,7 +287,10 @@ public class ClassDataItem extends Item<ClassDataItem> {
/** {@inheritDoc} */ /** {@inheritDoc} */
public String getConciseIdentity() { public String getConciseIdentity() {
return "class_data_item @0x" + Integer.toHexString(getOffset()); if (parent == null) {
return "class_data_item @0x" + Integer.toHexString(getOffset());
}
return "class_data_item @0x" + Integer.toHexString(getOffset()) + " (" + parent.getClassType() +")";
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@ -459,7 +478,8 @@ public class ClassDataItem extends Item<ClassDataItem> {
int previousIndex = previousEncodedMethod==null?0:previousEncodedMethod.method.getIndex(); int previousIndex = previousEncodedMethod==null?0:previousEncodedMethod.method.getIndex();
method = dexFile.MethodIdsSection.getItemByIndex(in.readUnsignedLeb128() + previousIndex); method = dexFile.MethodIdsSection.getItemByIndex(in.readUnsignedLeb128() + previousIndex);
accessFlags = in.readUnsignedLeb128(); 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) { if (codeItem != null) {
codeItem.setParent(this); codeItem.setParent(this);
} }
@ -480,7 +500,7 @@ public class ClassDataItem extends Item<ClassDataItem> {
out.annotate("access_flags: " + AccessFlags.formatAccessFlagsForMethod(accessFlags)); out.annotate("access_flags: " + AccessFlags.formatAccessFlagsForMethod(accessFlags));
out.writeUnsignedLeb128(accessFlags); out.writeUnsignedLeb128(accessFlags);
if (codeItem != null) { if (codeItem != null) {
out.annotate("code_off: 0x" + codeItem.getOffset()); out.annotate("code_off: 0x" + Integer.toHexString(codeItem.getOffset()));
out.writeUnsignedLeb128(codeItem.getOffset()); out.writeUnsignedLeb128(codeItem.getOffset());
} else { } else {
out.annotate("code_off: 0x0"); out.annotate("code_off: 0x0");

View File

@ -76,6 +76,7 @@ public class ClassDefItem extends Item<ClassDefItem> {
AnnotationDirectoryItem annotations, ClassDataItem classData, AnnotationDirectoryItem annotations, ClassDataItem classData,
EncodedArrayItem staticFieldInitializers) { EncodedArrayItem staticFieldInitializers) {
super(dexFile); super(dexFile);
assert classType != null;
this.classType = classType; this.classType = classType;
this.accessFlags = accessFlags; this.accessFlags = accessFlags;
this.superType = superType; this.superType = superType;
@ -131,14 +132,14 @@ public class ClassDefItem extends Item<ClassDefItem> {
protected void readItem(Input in, ReadContext readContext) { protected void readItem(Input in, ReadContext readContext) {
classType = dexFile.TypeIdsSection.getItemByIndex(in.readInt()); classType = dexFile.TypeIdsSection.getItemByIndex(in.readInt());
accessFlags = in.readInt(); accessFlags = in.readInt();
superType = dexFile.TypeIdsSection.getItemByIndex(in.readInt()); superType = dexFile.TypeIdsSection.getOptionalItemByIndex(in.readInt());
implementedInterfaces = (TypeListItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_TYPE_LIST, implementedInterfaces = (TypeListItem)readContext.getOptionalOffsettedItemByOffset(ItemType.TYPE_TYPE_LIST,
in.readInt()); in.readInt());
sourceFile = dexFile.StringIdsSection.getItemByIndex(in.readInt()); sourceFile = dexFile.StringIdsSection.getOptionalItemByIndex(in.readInt());
annotations = (AnnotationDirectoryItem)readContext.getOffsettedItemByOffset( annotations = (AnnotationDirectoryItem)readContext.getOptionalOffsettedItemByOffset(
ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM, in.readInt()); ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM, in.readInt());
classData = (ClassDataItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_CLASS_DATA_ITEM, in.readInt()); classData = (ClassDataItem)readContext.getOptionalOffsettedItemByOffset(ItemType.TYPE_CLASS_DATA_ITEM, in.readInt());
staticFieldInitializers = (EncodedArrayItem)readContext.getOffsettedItemByOffset( staticFieldInitializers = (EncodedArrayItem)readContext.getOptionalOffsettedItemByOffset(
ItemType.TYPE_ENCODED_ARRAY_ITEM, in.readInt()); ItemType.TYPE_ENCODED_ARRAY_ITEM, in.readInt());
if (classData != null) { if (classData != null) {

View File

@ -41,10 +41,8 @@ public class ArrayDataPseudoInstruction extends Instruction {
private byte[] encodedValues; private byte[] encodedValues;
@Override @Override
public int getSize(int offset) { public int getSize(int codeAddress) {
assert offset % 2 == 0; return ((encodedValues.length + 1)/2) + 4 + (codeAddress % 2);
int size = getElementWidth() * getElementCount();
return size + (size & 0x01) + 8 + (offset % 4);
} }
public ArrayDataPseudoInstruction(int elementWidth, byte[] encodedValues) { public ArrayDataPseudoInstruction(int elementWidth, byte[] encodedValues) {
@ -77,11 +75,8 @@ public class ArrayDataPseudoInstruction extends Instruction {
System.arraycopy(buffer, bufferIndex+8, encodedValues, 0, elementCount * elementWidth); System.arraycopy(buffer, bufferIndex+8, encodedValues, 0, elementCount * elementWidth);
} }
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
//write out padding, if necessary out.alignTo(4);
if (out.getCursor() % 4 != 0) {
out.writeShort(0);
}
int elementCount = encodedValues.length / elementWidth; int elementCount = encodedValues.length / elementWidth;
@ -90,14 +85,13 @@ public class ArrayDataPseudoInstruction extends Instruction {
out.writeShort(elementWidth); out.writeShort(elementWidth);
out.writeInt(elementCount); out.writeInt(elementCount);
out.write(encodedValues); out.write(encodedValues);
if ((encodedValues.length % 2) != 0) {
//must write out an even number of bytes //make sure we're written out an even number of bytes
out.writeByte(0); out.alignTo(2);
}
} }
protected void annotateInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void annotateInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.annotate(getSize(currentCodeOffset), "[0x" + Integer.toHexString(currentCodeOffset/2) + "] " + out.annotate(getSize(currentCodeAddress)*2, "[0x" + Integer.toHexString(currentCodeAddress) + "] " +
"fill-array-data instruction"); "fill-array-data instruction");
} }
@ -149,7 +143,7 @@ public class ArrayDataPseudoInstruction extends Instruction {
private static class Factory implements Instruction.InstructionFactory { private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
if (opcode != Opcode.NOP) { 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); return new ArrayDataPseudoInstruction(buffer, bufferIndex);
} }

View File

@ -39,13 +39,13 @@ public class DeadInstruction extends Instruction {
this.OriginalInstruction = originalInstruction; this.OriginalInstruction = originalInstruction;
} }
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
//don't write anything //don't write anything
} }
@Override @Override
public int getSize(int offset) { public int getSize(int codeAddress) {
return OriginalInstruction.getSize(offset); return OriginalInstruction.getSize(codeAddress);
} }
public Format getFormat() { public Format getFormat() {

View File

@ -36,17 +36,17 @@ import org.jf.dexlib.Util.AnnotatedOutput;
public class Instruction10t extends Instruction implements OffsetInstruction { public class Instruction10t extends Instruction implements OffsetInstruction {
public static final InstructionFactory Factory = new Factory(); public static final InstructionFactory Factory = new Factory();
private int offset; private int targetAddressOffset;
public Instruction10t(Opcode opcode, int offA) { public Instruction10t(Opcode opcode, int offA) {
super(opcode); super(opcode);
this.offset = offA; this.targetAddressOffset = offA;
if (offset == 0) { if (targetAddressOffset == 0) {
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead."); 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 //with goto/16 or goto/32 later
} }
@ -55,33 +55,33 @@ public class Instruction10t extends Instruction implements OffsetInstruction {
assert buffer[bufferIndex] == opcode.value; assert buffer[bufferIndex] == opcode.value;
this.offset = buffer[bufferIndex + 1]; this.targetAddressOffset = buffer[bufferIndex + 1];
assert offset != 0; assert targetAddressOffset != 0;
} }
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
if (offset == 0) { if (targetAddressOffset == 0) {
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead"); throw new RuntimeException("The address offset cannot be 0. Use goto/32 instead");
} }
if (offset < -128 || offset > 127) { if (targetAddressOffset < -128 || targetAddressOffset > 127) {
throw new RuntimeException("The offset is out of range. It must be in [-128,-1] or [1, 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(opcode.value);
out.writeByte(offset); out.writeByte(targetAddressOffset);
} }
public void updateOffset(int offset) { public void updateTargetAddressOffset(int targetAddressOffset) {
this.offset = offset; this.targetAddressOffset = targetAddressOffset;
} }
public Format getFormat() { public Format getFormat() {
return Format.Format10t; return Format.Format10t;
} }
public int getOffset() { public int getTargetAddressOffset() {
return offset; return targetAddressOffset;
} }
private static class Factory implements InstructionFactory { private static class Factory implements InstructionFactory {

View File

@ -47,7 +47,7 @@ public class Instruction10x extends Instruction {
assert buffer[bufferIndex + 1] == 0x00; 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(opcode.value);
out.writeByte(0); out.writeByte(0);
} }

View File

@ -64,7 +64,7 @@ public class Instruction11n extends Instruction implements SingleRegisterInstruc
this.litB = NumberUtils.decodeHighSignedNibble(buffer[bufferIndex + 1]); 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(opcode.value);
out.writeByte((litB << 4) | regA); out.writeByte((litB << 4) | regA);
} }

View File

@ -55,7 +55,7 @@ public class Instruction11x extends Instruction implements SingleRegisterInstruc
this.regA = (byte)NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]); 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(opcode.value);
out.writeByte(regA); out.writeByte(regA);
} }

View File

@ -58,7 +58,7 @@ public class Instruction12x extends Instruction implements TwoRegisterInstructio
this.regB = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]); 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(opcode.value);
out.writeByte((regB << 4) | regA); out.writeByte((regB << 4) | regA);
} }

View File

@ -37,17 +37,17 @@ import org.jf.dexlib.Util.NumberUtils;
public class Instruction20t extends Instruction implements OffsetInstruction { public class Instruction20t extends Instruction implements OffsetInstruction {
public static final InstructionFactory Factory = new Factory(); public static final InstructionFactory Factory = new Factory();
private int offset; private int targetAddressOffset;
public Instruction20t(Opcode opcode, int offA) { public Instruction20t(Opcode opcode, int offA) {
super(opcode); super(opcode);
this.offset = offA; this.targetAddressOffset = offA;
if (offset == 0) { if (targetAddressOffset == 0) {
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead."); 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 //with goto/16 or goto/32 later
} }
@ -56,34 +56,34 @@ public class Instruction20t extends Instruction implements OffsetInstruction {
assert buffer[bufferIndex] == opcode.value; assert buffer[bufferIndex] == opcode.value;
this.offset = NumberUtils.decodeShort(buffer, bufferIndex+2); this.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) {
if (offset == 0) { if (targetAddressOffset == 0) {
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead"); throw new RuntimeException("The address offset cannot be 0. Use goto/32 instead");
} }
if (offset < -32768 || offset > 32767) { if (targetAddressOffset < -32768 || targetAddressOffset > 32767) {
throw new RuntimeException("The offset is out of range. It must be in [-32768,-1] or [1, 32768]"); 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(opcode.value);
out.writeByte(0x00); out.writeByte(0x00);
out.writeShort(offset); out.writeShort(targetAddressOffset);
} }
public void updateOffset(int offset) { public void updateTargetAddressOffset(int targetAddressOffset) {
this.offset = offset; this.targetAddressOffset = targetAddressOffset;
} }
public Format getFormat() { public Format getFormat() {
return Format.Format20t; return Format.Format20t;
} }
public int getOffset() { public int getTargetAddressOffset() {
return offset; return targetAddressOffset;
} }
private static class Factory implements InstructionFactory { private static class Factory implements InstructionFactory {

View File

@ -68,7 +68,7 @@ public class Instruction21c extends InstructionWithReference implements SingleRe
this.regA = buffer[bufferIndex + 1]; 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) { if(opcode == Opcode.CONST_STRING && getReferencedItem().getIndex() > 0xFFFF) {
throw new RuntimeException("String offset is too large for const-string. Use string-const/jumbo instead."); throw new RuntimeException("String offset is too large for const-string. Use string-const/jumbo instead.");
} }

View File

@ -59,7 +59,7 @@ public class Instruction21h extends Instruction implements SingleRegisterInstruc
this.litB = NumberUtils.decodeShort(buffer, bufferIndex + 2); 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(opcode.value);
out.writeByte(regA); out.writeByte(regA);
out.writeShort(litB); out.writeShort(litB);

View File

@ -59,7 +59,7 @@ public class Instruction21s extends Instruction implements SingleRegisterInstruc
this.litB = NumberUtils.decodeShort(buffer, bufferIndex + 2); 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(opcode.value);
out.writeByte(regA); out.writeByte(regA);
out.writeShort(litB); out.writeShort(litB);

View File

@ -36,7 +36,7 @@ import org.jf.dexlib.Util.AnnotatedOutput;
public class Instruction21t extends Instruction implements OffsetInstruction, SingleRegisterInstruction { public class Instruction21t extends Instruction implements OffsetInstruction, SingleRegisterInstruction {
public static final Instruction.InstructionFactory Factory = new Factory(); public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA; private byte regA;
private short offset; private short targetAddressOffset;
public Instruction21t(Opcode opcode, short regA, short offB) { public Instruction21t(Opcode opcode, short regA, short offB) {
super(opcode); super(opcode);
@ -46,11 +46,11 @@ public class Instruction21t extends Instruction implements OffsetInstruction, Si
} }
if (offB == 0) { 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.regA = (byte)regA;
this.offset = offB; this.targetAddressOffset = offB;
} }
private Instruction21t(Opcode opcode, byte[] buffer, int bufferIndex) { 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; assert buffer[bufferIndex] == opcode.value;
regA = buffer[bufferIndex + 1]; regA = 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(opcode.value);
out.writeByte(regA); out.writeByte(regA);
out.writeShort(offset); out.writeShort(targetAddressOffset);
} }
public void updateOffset(int offset) { public void updateTargetAddressOffset(int targetAddressOffset) {
if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) { if (targetAddressOffset < Short.MIN_VALUE || targetAddressOffset > Short.MAX_VALUE) {
throw new RuntimeException("The offset " + offset + " is out of range. It must be in [-32768, 32767]"); throw new RuntimeException("The address offset " + targetAddressOffset +
" is out of range. It must be in [-32768, 32767]");
} }
if (offset == 0) { if (targetAddressOffset == 0) {
throw new RuntimeException("The offset cannot be 0"); throw new RuntimeException("The address offset cannot be 0");
} }
this.offset = (short)offset; this.targetAddressOffset = (short) targetAddressOffset;
} }
public Format getFormat() { public Format getFormat() {
@ -87,8 +88,8 @@ public class Instruction21t extends Instruction implements OffsetInstruction, Si
return regA & 0xFF; return regA & 0xFF;
} }
public int getOffset() { public int getTargetAddressOffset() {
return offset; return targetAddressOffset;
} }
private static class Factory implements Instruction.InstructionFactory { private static class Factory implements Instruction.InstructionFactory {

View File

@ -62,7 +62,7 @@ public class Instruction22b extends Instruction implements TwoRegisterInstructio
this.litC = buffer[bufferIndex + 3]; 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(opcode.value);
out.writeByte(regA); out.writeByte(regA);
out.writeByte(regB); out.writeByte(regB);

View File

@ -61,7 +61,7 @@ public class Instruction22c extends InstructionWithReference implements TwoRegis
this.regB = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]); 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(opcode.value);
out.writeByte((regB << 4) | regA); out.writeByte((regB << 4) | regA);
out.writeShort(getReferencedItem().getIndex()); out.writeShort(getReferencedItem().getIndex());

View File

@ -66,7 +66,7 @@ public class Instruction22cs extends Instruction implements TwoRegisterInstructi
this.fieldOffset = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2); 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(opcode.value);
out.writeByte((regB << 4) | regA); out.writeByte((regB << 4) | regA);
out.writeShort(fieldOffset); out.writeShort(fieldOffset);

View File

@ -43,7 +43,7 @@ public class Instruction22csf extends InstructionWithReference implements TwoReg
this.unfixedInstruction = unfixedInstruction; this.unfixedInstruction = unfixedInstruction;
} }
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
byte regA = (byte)getRegisterA(); byte regA = (byte)getRegisterA();
byte regB = (byte)getRegisterB(); byte regB = (byte)getRegisterB();

View File

@ -63,7 +63,7 @@ public class Instruction22s extends Instruction implements TwoRegisterInstructio
this.litC = NumberUtils.decodeShort(buffer, bufferIndex + 2); 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(opcode.value);
out.writeByte((regB << 4) | regA); out.writeByte((regB << 4) | regA);
out.writeShort(litC); out.writeShort(litC);

View File

@ -40,7 +40,7 @@ public class Instruction22t extends Instruction implements OffsetInstruction, Tw
public static final Instruction.InstructionFactory Factory = new Factory(); public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA; private byte regA;
private byte regB; private byte regB;
private short offset; private short targetAddressOffset;
public Instruction22t(Opcode opcode, byte regA, byte regB, short offC) { public Instruction22t(Opcode opcode, byte regA, byte regB, short offC) {
super(opcode); super(opcode);
@ -51,12 +51,12 @@ public class Instruction22t extends Instruction implements OffsetInstruction, Tw
} }
if (offC == 0) { if (offC == 0) {
throw new RuntimeException("The offset cannot be 0."); throw new RuntimeException("The address offset cannot be 0.");
} }
this.regA = regA; this.regA = regA;
this.regB = regB; this.regB = regB;
this.offset = offC; this.targetAddressOffset = offC;
} }
private Instruction22t(Opcode opcode, byte[] buffer, int bufferIndex) { 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]); regA = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
regB = NumberUtils.decodeHighUnsignedNibble(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(opcode.value);
out.writeByte((regB << 4) | regA); out.writeByte((regB << 4) | regA);
out.writeShort(offset); out.writeShort(targetAddressOffset);
} }
public void updateOffset(int offset) { public void updateTargetAddressOffset(int targetAddressOffset) {
if (offset < -32768 || offset > 32767) { if (targetAddressOffset < -32768 || targetAddressOffset > 32767) {
throw new RuntimeException("The offset " + offset + " is out of range. It must be in [-32768, 32767]"); throw new RuntimeException("The address offset " + targetAddressOffset +
" is out of range. It must be in [-32768, 32767]");
} }
if (offset == 0) { if (targetAddressOffset == 0) {
throw new RuntimeException("The offset cannot be 0"); throw new RuntimeException("The address offset cannot be 0");
} }
this.offset = (short)offset; this.targetAddressOffset = (short)targetAddressOffset;
} }
public Format getFormat() { public Format getFormat() {
@ -99,8 +100,8 @@ public class Instruction22t extends Instruction implements OffsetInstruction, Tw
return regB; return regB;
} }
public int getOffset() { public int getTargetAddressOffset() {
return offset; return targetAddressOffset;
} }
private static class Factory implements Instruction.InstructionFactory { private static class Factory implements Instruction.InstructionFactory {

View File

@ -62,7 +62,7 @@ public class Instruction22x extends Instruction implements TwoRegisterInstructio
this.regB = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2); 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(opcode.value);
out.writeByte(regA); out.writeByte(regA);
out.writeShort(regB); out.writeShort(regB);

View File

@ -62,7 +62,7 @@ public class Instruction23x extends Instruction implements ThreeRegisterInstruct
this.regC = buffer[bufferIndex + 3]; 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(opcode.value);
out.writeByte(regA); out.writeByte(regA);
out.writeByte(regB); out.writeByte(regB);

View File

@ -37,11 +37,11 @@ import org.jf.dexlib.Util.NumberUtils;
public class Instruction30t extends Instruction implements OffsetInstruction { public class Instruction30t extends Instruction implements OffsetInstruction {
public static final InstructionFactory Factory = new Factory(); public static final InstructionFactory Factory = new Factory();
private int offset; private int targetAddressOffset;
public Instruction30t(Opcode opcode, int offA) { public Instruction30t(Opcode opcode, int offA) {
super(opcode); super(opcode);
this.offset = offA; this.targetAddressOffset = offA;
} }
private Instruction30t(Opcode opcode, byte[] buffer, int bufferIndex) { private Instruction30t(Opcode opcode, byte[] buffer, int bufferIndex) {
@ -49,25 +49,25 @@ public class Instruction30t extends Instruction implements OffsetInstruction {
assert buffer[bufferIndex] == opcode.value; 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(opcode.value);
out.writeByte(0x00); out.writeByte(0x00);
out.writeInt(offset); out.writeInt(targetAddressOffset);
} }
public void updateOffset(int offset) { public void updateTargetAddressOffset(int targetAddressOffset) {
this.offset = offset; this.targetAddressOffset = targetAddressOffset;
} }
public Format getFormat() { public Format getFormat() {
return Format.Format30t; return Format.Format30t;
} }
public int getOffset() { public int getTargetAddressOffset() {
return offset; return targetAddressOffset;
} }
private static class Factory implements InstructionFactory { private static class Factory implements InstructionFactory {

View File

@ -57,7 +57,7 @@ public class Instruction31c extends InstructionWithReference implements SingleRe
this.regA = buffer[bufferIndex + 1]; 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(opcode.value);
out.writeByte(regA); out.writeByte(regA);
out.writeInt(getReferencedItem().getIndex()); out.writeInt(getReferencedItem().getIndex());

View File

@ -59,7 +59,7 @@ public class Instruction31i extends Instruction implements SingleRegisterInstruc
this.litB = NumberUtils.decodeInt(buffer, bufferIndex + 2); 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(opcode.value);
out.writeByte(regA); out.writeByte(regA);
out.writeInt(litB); out.writeInt(litB);

View File

@ -39,7 +39,7 @@ import org.jf.dexlib.Util.AnnotatedOutput;
public class Instruction31t extends Instruction implements OffsetInstruction, SingleRegisterInstruction { public class Instruction31t extends Instruction implements OffsetInstruction, SingleRegisterInstruction {
public static final Instruction.InstructionFactory Factory = new Factory(); public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA; private byte regA;
private int offset; private int targetAddressOffset;
public Instruction31t(Opcode opcode, short regA, int offB) { public Instruction31t(Opcode opcode, short regA, int offB) {
super(opcode); super(opcode);
@ -49,24 +49,25 @@ public class Instruction31t extends Instruction implements OffsetInstruction, Si
} }
this.regA = (byte)regA; this.regA = (byte)regA;
this.offset = offB; this.targetAddressOffset = offB;
} }
private Instruction31t(Opcode opcode, byte[] buffer, int bufferIndex) { private Instruction31t(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode); super(opcode);
this.regA = buffer[bufferIndex + 1]; 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(opcode.value);
out.writeByte(regA); 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) { public void updateTargetAddressOffset(int targetAddressOffset) {
this.offset = offset; this.targetAddressOffset = targetAddressOffset;
} }
public Format getFormat() { public Format getFormat() {
@ -77,8 +78,8 @@ public class Instruction31t extends Instruction implements OffsetInstruction, Si
return regA & 0xFF; return regA & 0xFF;
} }
public int getOffset() { public int getTargetAddressOffset() {
return offset; return targetAddressOffset;
} }
private static class Factory implements Instruction.InstructionFactory { private static class Factory implements Instruction.InstructionFactory {

View File

@ -59,7 +59,7 @@ public class Instruction32x extends Instruction implements TwoRegisterInstructio
this.regB = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4); 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(opcode.value);
out.writeByte(0); out.writeByte(0);
out.writeShort(regA); out.writeShort(regA);

View File

@ -92,7 +92,7 @@ public class Instruction35c extends InstructionWithReference implements FiveRegi
checkItem(opcode, getReferencedItem(), getRegCount()); checkItem(opcode, getReferencedItem(), getRegCount());
} }
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value); out.writeByte(opcode.value);
out.writeByte((regCount << 4) | regA); out.writeByte((regCount << 4) | regA);
out.writeShort(getReferencedItem().getIndex()); out.writeShort(getReferencedItem().getIndex());

View File

@ -86,7 +86,7 @@ public class Instruction35ms extends Instruction implements FiveRegisterInstruct
this.methodIndex = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2); 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(opcode.value);
out.writeByte((regCount << 4) | regA); out.writeByte((regCount << 4) | regA);
out.writeShort(methodIndex); out.writeShort(methodIndex);

View File

@ -43,7 +43,7 @@ public class Instruction35msf extends InstructionWithReference implements FiveRe
this.unfixedInstruction = unfixedInstruction; this.unfixedInstruction = unfixedInstruction;
} }
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
byte regA = getRegisterA(); byte regA = getRegisterA();
byte regCount = getRegCount(); byte regCount = getRegCount();
byte regD = getRegisterD(); byte regD = getRegisterD();

View File

@ -92,7 +92,7 @@ public class Instruction35s extends InstructionWithReference implements FiveRegi
this.regG = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 5]); 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(opcode.value);
out.writeByte((regCount << 4) | regA); out.writeByte((regCount << 4) | regA);
out.writeShort(getReferencedItem().getIndex()); out.writeShort(getReferencedItem().getIndex());

View File

@ -41,7 +41,7 @@ public class Instruction35sf extends InstructionWithReference implements FiveReg
this.unfixedInstruction = unfixedInstruction; this.unfixedInstruction = unfixedInstruction;
} }
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
byte regA = getRegisterA(); byte regA = getRegisterA();
byte regCount = getRegCount(); byte regCount = getRegCount();
byte regD = getRegisterD(); byte regD = getRegisterD();

View File

@ -78,7 +78,7 @@ public class Instruction3rc extends InstructionWithReference implements Register
checkItem(opcode, getReferencedItem(), getRegCount()); checkItem(opcode, getReferencedItem(), getRegCount());
} }
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value); out.writeByte(opcode.value);
out.writeByte(regCount); out.writeByte(regCount);
out.writeShort(this.getReferencedItem().getIndex()); out.writeShort(this.getReferencedItem().getIndex());

View File

@ -75,7 +75,7 @@ public class Instruction3rms extends Instruction implements RegisterRangeInstruc
this.startReg = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4); 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(opcode.value);
out.writeByte(regCount); out.writeByte(regCount);
out.writeShort(methodIndex); out.writeShort(methodIndex);

View File

@ -43,7 +43,7 @@ public class Instruction3rmsf extends InstructionWithReference implements Regist
this.unfixedInstruction = unfixedInstruction; this.unfixedInstruction = unfixedInstruction;
} }
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
short regCount = getRegCount(); short regCount = getRegCount();
int startReg = getStartRegister(); int startReg = getStartRegister();

View File

@ -59,7 +59,7 @@ public class Instruction51l extends Instruction implements SingleRegisterInstruc
litB = NumberUtils.decodeLong(buffer, bufferIndex + 2); 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(opcode.value);
out.writeByte(regA); out.writeByte(regA);
out.writeLong(litB); out.writeLong(litB);

View File

@ -43,9 +43,8 @@ public class PackedSwitchDataPseudoInstruction extends Instruction implements Mu
private int[] targets; private int[] targets;
@Override @Override
public int getSize(int offset) { public int getSize(int codeAddress) {
assert offset % 2 == 0; return getTargetCount() * 2 + 4 + (codeAddress % 2);
return getTargetCount() * 4 + 8 + (offset % 4);
} }
public PackedSwitchDataPseudoInstruction(int firstKey, int[] targets) { public PackedSwitchDataPseudoInstruction(int firstKey, int[] targets) {
@ -81,11 +80,8 @@ public class PackedSwitchDataPseudoInstruction extends Instruction implements Mu
} }
} }
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
//write out padding, if necessary out.alignTo(4);
if (currentCodeOffset % 4 != 0) {
out.writeShort(0);
}
out.writeByte(0x00); out.writeByte(0x00);
out.writeByte(0x01); out.writeByte(0x01);
@ -97,13 +93,13 @@ public class PackedSwitchDataPseudoInstruction extends Instruction implements Mu
} }
} }
protected void annotateInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void annotateInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.annotate(getSize(currentCodeOffset), "[0x" + Integer.toHexString(currentCodeOffset/2) + "] " + out.annotate(getSize(currentCodeAddress)*2, "[0x" + Integer.toHexString(currentCodeAddress) + "] " +
"packed-switch-data instruction"); "packed-switch-data instruction");
} }
public void updateTarget(int targetIndex, int targetOffset) { public void updateTarget(int targetIndex, int targetAddressOffset) {
targets[targetIndex] = targetOffset; targets[targetIndex] = targetAddressOffset;
} }
public Format getFormat() { public Format getFormat() {
@ -124,7 +120,7 @@ public class PackedSwitchDataPseudoInstruction extends Instruction implements Mu
public static class PackedSwitchTarget { public static class PackedSwitchTarget {
public int value; public int value;
public int target; public int targetAddressOffset;
} }
public Iterator<PackedSwitchTarget> iterateKeysAndTargets() { public Iterator<PackedSwitchTarget> iterateKeysAndTargets() {
@ -141,7 +137,7 @@ public class PackedSwitchDataPseudoInstruction extends Instruction implements Mu
public PackedSwitchTarget next() { public PackedSwitchTarget next() {
packedSwitchTarget.value = value++; packedSwitchTarget.value = value++;
packedSwitchTarget.target = targets[i]; packedSwitchTarget.targetAddressOffset = targets[i];
i++; i++;
return packedSwitchTarget; 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 { private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
if (opcode != Opcode.NOP) { 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); return new PackedSwitchDataPseudoInstruction(buffer, bufferIndex);
} }

View File

@ -43,16 +43,15 @@ public class SparseSwitchDataPseudoInstruction extends Instruction implements Mu
private int[] targets; private int[] targets;
@Override @Override
public int getSize(int offset) { public int getSize(int codeAddress) {
assert offset % 2 == 0; return getTargetCount() * 4 + 2 + (codeAddress % 2);
return getTargetCount() * 8 + 4 + (offset % 4);
} }
public SparseSwitchDataPseudoInstruction(int[] keys, int[] targets) { public SparseSwitchDataPseudoInstruction(int[] keys, int[] targets) {
super(Opcode.NOP); super(Opcode.NOP);
if (keys.length != targets.length) { 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) { if (targets.length == 0) {
@ -90,11 +89,8 @@ public class SparseSwitchDataPseudoInstruction extends Instruction implements Mu
} }
} }
protected void writeInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
//write out padding, if necessary out.alignTo(4);
if (currentCodeOffset % 4 != 0) {
out.writeShort(0);
}
out.writeByte(0x00); out.writeByte(0x00);
out.writeByte(0x02); out.writeByte(0x02);
@ -117,13 +113,13 @@ public class SparseSwitchDataPseudoInstruction extends Instruction implements Mu
} }
} }
protected void annotateInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void annotateInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.annotate(getSize(currentCodeOffset), "[0x" + Integer.toHexString(currentCodeOffset/2) + "] " + out.annotate(getSize(currentCodeAddress)*2, "[0x" + Integer.toHexString(currentCodeAddress) + "] " +
"sparse-switch-data instruction"); "sparse-switch-data instruction");
} }
public void updateTarget(int targetIndex, int targetOffset) { public void updateTarget(int targetIndex, int targetAddressOffset) {
targets[targetIndex] = targetOffset; targets[targetIndex] = targetAddressOffset;
} }
public Format getFormat() { public Format getFormat() {
@ -144,7 +140,7 @@ public class SparseSwitchDataPseudoInstruction extends Instruction implements Mu
public static class SparseSwitchTarget { public static class SparseSwitchTarget {
public int key; public int key;
public int target; public int targetAddressOffset;
} }
public Iterator<SparseSwitchTarget> iterateKeysAndTargets() { public Iterator<SparseSwitchTarget> iterateKeysAndTargets() {
@ -160,7 +156,7 @@ public class SparseSwitchDataPseudoInstruction extends Instruction implements Mu
public SparseSwitchTarget next() { public SparseSwitchTarget next() {
sparseSwitchTarget.key = keys[i]; sparseSwitchTarget.key = keys[i];
sparseSwitchTarget.target = targets[i]; sparseSwitchTarget.targetAddressOffset = targets[i];
i++; i++;
return sparseSwitchTarget; return sparseSwitchTarget;
} }
@ -173,7 +169,7 @@ public class SparseSwitchDataPseudoInstruction extends Instruction implements Mu
private static class Factory implements Instruction.InstructionFactory { private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
if (opcode != Opcode.NOP) { 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); return new SparseSwitchDataPseudoInstruction(buffer, bufferIndex);
} }

View File

@ -47,13 +47,13 @@ public class UnresolvedNullReference extends Instruction {
this.ObjectRegisterNum = objectRegisterNumber; 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"); throw new RuntimeException("Cannot rewrite an instruction that couldn't be deodexed");
} }
@Override @Override
public int getSize(int offset) { public int getSize(int codeAddress) {
return OriginalInstruction.getSize(offset); return OriginalInstruction.getSize(codeAddress);
} }
public Format getFormat() { public Format getFormat() {

View File

@ -29,15 +29,19 @@
package org.jf.dexlib.Code; package org.jf.dexlib.Code;
import org.jf.dexlib.*; import org.jf.dexlib.*;
import org.jf.dexlib.Util.ByteArrayInput;
import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Code.Format.Format; import org.jf.dexlib.Code.Format.Format;
public abstract class Instruction { public abstract class Instruction {
public final Opcode opcode; 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) { protected Instruction(Opcode opcode) {
@ -46,20 +50,20 @@ public abstract class Instruction {
public abstract Format getFormat(); public abstract Format getFormat();
public int write(AnnotatedOutput out, int currentCodeOffset) { public int write(AnnotatedOutput out, int currentCodeAddress) {
if (out.annotates()) { if (out.annotates()) {
annotateInstruction(out, currentCodeOffset); annotateInstruction(out, currentCodeAddress);
} }
writeInstruction(out, currentCodeOffset); writeInstruction(out, currentCodeAddress);
return currentCodeOffset + getSize(currentCodeOffset); return currentCodeAddress + getSize(currentCodeAddress);
} }
protected void annotateInstruction(AnnotatedOutput out, int currentCodeOffset) { protected void annotateInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.annotate(getSize(currentCodeOffset), "[0x" + Integer.toHexString(currentCodeOffset/2) + "] " + out.annotate(getSize(currentCodeAddress)*2, "[0x" + Integer.toHexString(currentCodeAddress) + "] " +
opcode.name + " instruction"); opcode.name + " instruction");
} }
protected abstract void writeInstruction(AnnotatedOutput out, int currentCodeOffset); protected abstract void writeInstruction(AnnotatedOutput out, int currentCodeAddress);
public static interface InstructionFactory { public static interface InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex); public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex);

View File

@ -28,177 +28,65 @@
package org.jf.dexlib.Code; package org.jf.dexlib.Code;
import org.jf.dexlib.Util.ExceptionWithContext;
import org.jf.dexlib.Util.Hex; import org.jf.dexlib.Util.Hex;
import org.jf.dexlib.Util.NumberUtils;
import org.jf.dexlib.Code.Format.*; import org.jf.dexlib.Code.Format.*;
import org.jf.dexlib.DexFile; import org.jf.dexlib.DexFile;
public class InstructionIterator { public class InstructionIterator {
/** public static void IterateInstructions(DexFile dexFile, byte[] insns, ProcessInstructionDelegate delegate) {
* 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) {
int insnsPosition = 0; int insnsPosition = 0;
while (insnsPosition < insns.length) { while (insnsPosition < insns.length) {
Opcode opcode = Opcode.getOpcodeByValue(insns[insnsPosition]); try
{
Opcode opcode = Opcode.getOpcodeByValue(insns[insnsPosition]);
if (opcode == null) { Instruction instruction = null;
throw new RuntimeException("Unknown opcode: " + Hex.u1(insns[insnsPosition]));
}
if (opcode.referenceType == ReferenceType.none) { if (opcode == null) {
byte secondByte = insns[insnsPosition+1]; throw new RuntimeException("Unknown opcode: " + Hex.u1(insns[insnsPosition]));
//if this is one of the "special" opcodes }
if (opcode == Opcode.NOP && secondByte > 0) {
if (opcode == Opcode.NOP) {
byte secondByte = insns[insnsPosition + 1];
switch (secondByte) { switch (secondByte) {
case 0:
{
instruction = new Instruction10x(Opcode.NOP, insns, insnsPosition);
break;
}
case 1: case 1:
{ {
//packed-switch instruction = new PackedSwitchDataPseudoInstruction(insns, insnsPosition);
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; break;
} }
case 2: case 2:
{ {
//sparse-switch instruction = new SparseSwitchDataPseudoInstruction(insns, insnsPosition);
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; break;
} }
case 3: case 3:
{ {
//fill-array-data instruction = new ArrayDataPseudoInstruction(insns, insnsPosition);
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; break;
} }
} }
} else { } else {
processRawInstruction.ProcessNormalInstruction(opcode, insnsPosition); instruction = opcode.format.Factory.makeInstruction(dexFile, opcode, insns, insnsPosition);
insnsPosition += opcode.format.size;
} }
} else {
processRawInstruction.ProcessReferenceInstruction(opcode, insnsPosition); assert instruction != null;
insnsPosition += opcode.format.size;
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 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];
switch (secondByte) {
case 0:
{
instruction = new Instruction10x(Opcode.NOP, insns, currentCodeOffset);
break;
}
case 1:
{
instruction = new PackedSwitchDataPseudoInstruction(insns, currentCodeOffset);
break;
}
case 2:
{
instruction = new SparseSwitchDataPseudoInstruction(insns, currentCodeOffset);
break;
}
case 3:
{
instruction = new ArrayDataPseudoInstruction(insns, currentCodeOffset);
break;
}
}
} else {
instruction = opcode.format.Factory.makeInstruction(dexFile, opcode, insns, currentCodeOffset);
}
assert instruction != null;
delegate.ProcessInstruction(currentCodeOffset, instruction);
currentCodeOffset += instruction.getSize(currentCodeOffset);
}
}
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 static interface ProcessInstructionDelegate {
public void ProcessInstruction(int index, Instruction instruction); public void ProcessInstruction(int codeAddress, Instruction instruction);
} }
} }

View File

@ -30,5 +30,5 @@ package org.jf.dexlib.Code;
public interface MultiOffsetInstruction { public interface MultiOffsetInstruction {
public int[] getTargets(); public int[] getTargets();
public void updateTarget(int targetIndex, int targetOffset); public void updateTarget(int targetIndex, int targetAddressOffset);
} }

View File

@ -29,6 +29,6 @@
package org.jf.dexlib.Code; package org.jf.dexlib.Code;
public interface OffsetInstruction { public interface OffsetInstruction {
public int getOffset(); public int getTargetAddressOffset();
public void updateOffset(int offset); public void updateTargetAddressOffset(int targetAddressOffset);
} }

View File

@ -33,6 +33,7 @@ import org.jf.dexlib.Code.Format.Instruction20t;
import org.jf.dexlib.Code.Format.Instruction30t; import org.jf.dexlib.Code.Format.Instruction30t;
import org.jf.dexlib.Code.Format.Instruction21c; import org.jf.dexlib.Code.Format.Instruction21c;
import org.jf.dexlib.Code.Format.Instruction31c; import org.jf.dexlib.Code.Format.Instruction31c;
import org.jf.dexlib.Debug.DebugOpcode;
import org.jf.dexlib.Util.*; import org.jf.dexlib.Util.*;
import org.jf.dexlib.Debug.DebugInstructionIterator; import org.jf.dexlib.Debug.DebugInstructionIterator;
@ -142,7 +143,7 @@ public class CodeItem extends Item<CodeItem> {
this.inWords = in.readShort(); this.inWords = in.readShort();
this.outWords = in.readShort(); this.outWords = in.readShort();
int triesCount = 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()); in.readInt());
if (this.debugInfo != null) { if (this.debugInfo != null) {
this.debugInfo.setParent(this); this.debugInfo.setParent(this);
@ -154,7 +155,7 @@ public class CodeItem extends Item<CodeItem> {
byte[] encodedInstructions = in.readBytes(instructionCount * 2); byte[] encodedInstructions = in.readBytes(instructionCount * 2);
InstructionIterator.IterateInstructions(dexFile, encodedInstructions, InstructionIterator.IterateInstructions(dexFile, encodedInstructions,
new InstructionIterator.ProcessInstructionDelegate() { new InstructionIterator.ProcessInstructionDelegate() {
public void ProcessInstruction(int index, Instruction instruction) { public void ProcessInstruction(int codeAddress, Instruction instruction) {
instructionList.add(instruction); instructionList.add(instruction);
} }
}); });
@ -175,9 +176,13 @@ public class CodeItem extends Item<CodeItem> {
SparseArray<EncodedCatchHandler> handlerMap = new SparseArray<EncodedCatchHandler>(handlerCount); SparseArray<EncodedCatchHandler> handlerMap = new SparseArray<EncodedCatchHandler>(handlerCount);
encodedCatchHandlers = new EncodedCatchHandler[handlerCount]; encodedCatchHandlers = new EncodedCatchHandler[handlerCount];
for (int i=0; i<handlerCount; i++) { for (int i=0; i<handlerCount; i++) {
int position = in.getCursor() - encodedHandlerStart; try {
encodedCatchHandlers[i] = new EncodedCatchHandler(dexFile, in); int position = in.getCursor() - encodedHandlerStart;
handlerMap.append(position, encodedCatchHandlers[i]); 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(); int codeItemEnd = in.getCursor();
@ -185,7 +190,11 @@ public class CodeItem extends Item<CodeItem> {
in.setCursor(triesOffset); in.setCursor(triesOffset);
tries = new TryItem[triesCount]; tries = new TryItem[triesCount];
for (int i=0; i<triesCount; i++) { for (int i=0; i<triesCount; i++) {
tries[i] = new TryItem(in, handlerMap); 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 //and now back to the end of the code item
@ -195,12 +204,10 @@ public class CodeItem extends Item<CodeItem> {
/** {@inheritDoc} */ /** {@inheritDoc} */
protected int placeItem(int offset) { protected int placeItem(int offset) {
offset += 16 + getInstructionsLength(); offset += 16 + getInstructionsLength() * 2;
if (tries != null && tries.length > 0) { if (tries != null && tries.length > 0) {
if (offset % 4 != 0) { offset = AlignmentUtils.alignOffset(offset, 4);
offset+=2;
}
offset += tries.length * 8; offset += tries.length * 8;
int encodedCatchHandlerBaseOffset = offset; int encodedCatchHandlerBaseOffset = offset;
@ -214,7 +221,7 @@ public class CodeItem extends Item<CodeItem> {
/** {@inheritDoc} */ /** {@inheritDoc} */
protected void writeItem(final AnnotatedOutput out) { protected void writeItem(final AnnotatedOutput out) {
int instructionsLength = getInstructionsLength()/2; int instructionsLength = getInstructionsLength();
if (out.annotates()) { if (out.annotates()) {
out.annotate(0, parent.method.getMethodString()); out.annotate(0, parent.method.getMethodString());
@ -246,21 +253,16 @@ public class CodeItem extends Item<CodeItem> {
out.writeInt(debugInfo.getOffset()); out.writeInt(debugInfo.getOffset());
} }
int currentCodeOffset = 0;
for (Instruction instruction: instructions) {
currentCodeOffset += instruction.getSize(currentCodeOffset);
}
out.writeInt(instructionsLength); out.writeInt(instructionsLength);
currentCodeOffset = 0; int currentCodeAddress = 0;
for (Instruction instruction: instructions) { for (Instruction instruction: instructions) {
currentCodeOffset = instruction.write(out, currentCodeOffset); currentCodeAddress = instruction.write(out, currentCodeAddress);
} }
if (tries != null && tries.length > 0) { if (tries != null && tries.length > 0) {
if (out.annotates()) { if (out.annotates()) {
if ((currentCodeOffset % 4) != 0) { if ((currentCodeAddress % 2) != 0) {
out.annotate("padding"); out.annotate("padding");
out.writeShort(0); out.writeShort(0);
} }
@ -285,7 +287,7 @@ public class CodeItem extends Item<CodeItem> {
out.deindent(); out.deindent();
} }
} else { } else {
if ((currentCodeOffset % 4) != 0) { if ((currentCodeAddress % 2) != 0) {
out.writeShort(0); out.writeShort(0);
} }
@ -309,7 +311,10 @@ public class CodeItem extends Item<CodeItem> {
/** {@inheritDoc} */ /** {@inheritDoc} */
public String getConciseIdentity() { public String getConciseIdentity() {
return "code_item @0x" + Integer.toHexString(getOffset()); if (this.parent == null) {
return "code_item @0x" + Integer.toHexString(getOffset());
}
return "code_item @0x" + Integer.toHexString(getOffset()) + " (" + parent.method.getMethodString() + ")";
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@ -385,12 +390,15 @@ public class CodeItem extends Item<CodeItem> {
this.instructions = newInstructions; this.instructions = newInstructions;
} }
/**
* @return The length of the instructions in this CodeItem, in 2-byte code blocks
*/
private int getInstructionsLength() { private int getInstructionsLength() {
int offset = 0; int currentCodeAddress = 0;
for (Instruction instruction: instructions) { for (Instruction instruction: instructions) {
offset += instruction.getSize(offset); currentCodeAddress += instruction.getSize(currentCodeAddress);
} }
return offset; return currentCodeAddress;
} }
/** /**
@ -403,71 +411,84 @@ public class CodeItem extends Item<CodeItem> {
* The above fixes are applied iteratively, until no more fixes have been performed * The above fixes are applied iteratively, until no more fixes have been performed
*/ */
public void fixInstructions(boolean fixStringConst, boolean fixGoto) { public void fixInstructions(boolean fixStringConst, boolean fixGoto) {
boolean didSomething = false; try {
boolean didSomething = false;
do do
{ {
didSomething = false; didSomething = false;
int currentCodeOffset = 0; int currentCodeAddress = 0;
for (int i=0; i<instructions.length; i++) { for (int i=0; i<instructions.length; i++) {
Instruction instruction = instructions[i]; Instruction instruction = instructions[i];
if (fixGoto && instruction.opcode == Opcode.GOTO) { try {
int offset = ((OffsetInstruction)instruction).getOffset(); if (fixGoto && instruction.opcode == Opcode.GOTO) {
int codeAddress = ((OffsetInstruction)instruction).getTargetAddressOffset();
if (((byte)offset) != offset) { if (((byte) codeAddress) != codeAddress) {
//the offset doesn't fit within a byte, we need to upgrade to a goto/16 or goto/32 //the address doesn't fit within a byte, we need to upgrade to a goto/16 or goto/32
if ((short)offset == offset) { if ((short) codeAddress == codeAddress) {
//the offset fits in a short, so upgrade to a goto/16 h //the address fits in a short, so upgrade to a goto/16
replaceInstructionAtOffset(currentCodeOffset, new Instruction20t(Opcode.GOTO_16, offset)); replaceInstructionAtAddress(currentCodeAddress,
new Instruction20t(Opcode.GOTO_16, codeAddress));
}
else {
//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 codeAddress = ((OffsetInstruction)instruction).getTargetAddressOffset();
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) {
replaceInstructionAtAddress(currentCodeAddress,
new Instruction31c(Opcode.CONST_STRING_JUMBO,
(short)constStringInstruction.getRegisterA(),
constStringInstruction.getReferencedItem()));
didSomething = true;
break;
}
} }
else {
//The offset won't fit into a short, we have to upgrade to a goto/32
replaceInstructionAtOffset(currentCodeOffset, new Instruction30t(Opcode.GOTO_32, offset));
}
didSomething = true;
break;
}
} else if (fixGoto && instruction.opcode == Opcode.GOTO_16) {
int offset = ((OffsetInstruction)instruction).getOffset();
if (((short)offset) != offset) { currentCodeAddress += instruction.getSize(currentCodeAddress);
//the offset doesn't fit within a short, we need to upgrade to a goto/32 } catch (Exception ex) {
replaceInstructionAtOffset(currentCodeOffset, new Instruction30t(Opcode.GOTO_32, offset)); throw ExceptionWithContext.withContext(ex, "Error while attempting to fix " +
didSomething = true; instruction.opcode.name + " instruction at address " + currentCodeAddress);
break;
}
} else if (fixStringConst && instruction.opcode == Opcode.CONST_STRING) {
Instruction21c constStringInstruction = (Instruction21c)instruction;
if (constStringInstruction.getReferencedItem().getIndex() > 0xFFFF) {
replaceInstructionAtOffset(currentCodeOffset, new Instruction31c(Opcode.CONST_STRING_JUMBO,
(short)constStringInstruction.getRegisterA(),
constStringInstruction.getReferencedItem()));
didSomething = true;
break;
} }
} }
}while(didSomething);
currentCodeOffset += instruction.getSize(currentCodeOffset); } catch (Exception ex) {
} throw this.addExceptionContext(ex);
}while(didSomething); }
} }
private void replaceInstructionAtOffset(int offset, Instruction replacementInstruction) { private void replaceInstructionAtAddress(int codeAddress, Instruction replacementInstruction) {
Instruction originalInstruction = null; Instruction originalInstruction = null;
int[] originalInstructionOffsets = new int[instructions.length+1]; int[] originalInstructionCodeAddresses = new int[instructions.length+1];
SparseIntArray originalSwitchOffsetByOriginalSwitchDataOffset = new SparseIntArray(); SparseIntArray originalSwitchAddressByOriginalSwitchDataAddress = new SparseIntArray();
int currentCodeOffset = 0; int currentCodeAddress = 0;
int instructionIndex = 0; int instructionIndex = 0;
int i; int i;
for (i=0; i<instructions.length; i++) { for (i=0; i<instructions.length; i++) {
Instruction instruction = instructions[i]; Instruction instruction = instructions[i];
if (currentCodeOffset == offset) { if (currentCodeAddress == codeAddress) {
originalInstruction = instruction; originalInstruction = instruction;
instructionIndex = i; instructionIndex = i;
} }
@ -475,97 +496,100 @@ public class CodeItem extends Item<CodeItem> {
if (instruction.opcode == Opcode.PACKED_SWITCH || instruction.opcode == Opcode.SPARSE_SWITCH) { if (instruction.opcode == Opcode.PACKED_SWITCH || instruction.opcode == Opcode.SPARSE_SWITCH) {
OffsetInstruction offsetInstruction = (OffsetInstruction)instruction; OffsetInstruction offsetInstruction = (OffsetInstruction)instruction;
int switchDataOffset = currentCodeOffset + offsetInstruction.getOffset() * 2; int switchDataAddress = currentCodeAddress + offsetInstruction.getTargetAddressOffset();
if (originalSwitchOffsetByOriginalSwitchDataOffset.indexOfKey(switchDataOffset) < 0) { if (originalSwitchAddressByOriginalSwitchDataAddress.indexOfKey(switchDataAddress) < 0) {
originalSwitchOffsetByOriginalSwitchDataOffset.put(switchDataOffset, currentCodeOffset); originalSwitchAddressByOriginalSwitchDataAddress.put(switchDataAddress, currentCodeAddress);
} }
} }
originalInstructionOffsets[i] = currentCodeOffset; originalInstructionCodeAddresses[i] = 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 //at the end of the method
originalInstructionOffsets[i] = currentCodeOffset; originalInstructionCodeAddresses[i] = currentCodeAddress;
if (originalInstruction == null) { 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; instructions[instructionIndex] = replacementInstruction;
//if we're replacing the instruction with one of the same size, we don't have to worry about fixing //if we're replacing the instruction with one of the same size, we don't have to worry about fixing
//up any offsets //up any address
if (originalInstruction.getSize(offset) == replacementInstruction.getSize(offset)) { if (originalInstruction.getSize(codeAddress) == replacementInstruction.getSize(codeAddress)) {
return; return;
} }
final SparseIntArray originalOffsetsByNewOffset = new SparseIntArray(); final SparseIntArray originalAddressByNewAddress = new SparseIntArray();
final SparseIntArray newOffsetsByOriginalOffset = new SparseIntArray(); final SparseIntArray newAddressByOriginalAddress = new SparseIntArray();
currentCodeOffset = 0; currentCodeAddress = 0;
for (i=0; i<instructions.length; i++) { for (i=0; i<instructions.length; i++) {
Instruction instruction = instructions[i]; Instruction instruction = instructions[i];
int originalOffset = originalInstructionOffsets[i]; int originalAddress = originalInstructionCodeAddresses[i];
originalOffsetsByNewOffset.append(currentCodeOffset, originalOffset); originalAddressByNewAddress.append(currentCodeAddress, originalAddress);
newOffsetsByOriginalOffset.append(originalOffset, currentCodeOffset); 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 //at the end of the method
originalOffsetsByNewOffset.append(currentCodeOffset, originalInstructionOffsets[i]); originalAddressByNewAddress.append(currentCodeAddress, originalInstructionCodeAddresses[i]);
newOffsetsByOriginalOffset.append(originalInstructionOffsets[i], currentCodeOffset); newAddressByOriginalAddress.append(originalInstructionCodeAddresses[i], currentCodeAddress);
//update any "offset" instructions, or switch data instructions //update any "offset" instructions, or switch data instructions
currentCodeOffset = 0; currentCodeAddress = 0;
for (i=0; i<instructions.length; i++) { for (i=0; i<instructions.length; i++) {
Instruction instruction = instructions[i]; Instruction instruction = instructions[i];
if (instruction instanceof OffsetInstruction) { if (instruction instanceof OffsetInstruction) {
OffsetInstruction offsetInstruction = (OffsetInstruction)instruction; OffsetInstruction offsetInstruction = (OffsetInstruction)instruction;
assert originalOffsetsByNewOffset.indexOfKey(currentCodeOffset) >= 0; assert originalAddressByNewAddress.indexOfKey(currentCodeAddress) >= 0;
int originalOffset = originalOffsetsByNewOffset.get(currentCodeOffset); int originalAddress = originalAddressByNewAddress.get(currentCodeAddress);
int originalInstructionTarget = originalOffset + offsetInstruction.getOffset() * 2; int originalInstructionTarget = originalAddress + offsetInstruction.getTargetAddressOffset();
assert newOffsetsByOriginalOffset.indexOfKey(originalInstructionTarget) >= 0; assert newAddressByOriginalAddress.indexOfKey(originalInstructionTarget) >= 0;
int newInstructionTarget = newOffsetsByOriginalOffset.get(originalInstructionTarget); int newInstructionTarget = newAddressByOriginalAddress.get(originalInstructionTarget);
int newOffset = (newInstructionTarget - currentCodeOffset) / 2; int newCodeAddress = (newInstructionTarget - currentCodeAddress);
if (newOffset != offsetInstruction.getOffset()) { if (newCodeAddress != offsetInstruction.getTargetAddressOffset()) {
offsetInstruction.updateOffset(newOffset); offsetInstruction.updateTargetAddressOffset(newCodeAddress);
} }
} else if (instruction instanceof MultiOffsetInstruction) { } else if (instruction instanceof MultiOffsetInstruction) {
MultiOffsetInstruction multiOffsetInstruction = (MultiOffsetInstruction)instruction; MultiOffsetInstruction multiOffsetInstruction = (MultiOffsetInstruction)instruction;
assert originalOffsetsByNewOffset.indexOfKey(currentCodeOffset) >= 0; assert originalAddressByNewAddress.indexOfKey(currentCodeAddress) >= 0;
int originalDataOffset = originalOffsetsByNewOffset.get(currentCodeOffset); int originalDataAddress = originalAddressByNewAddress.get(currentCodeAddress);
int originalSwitchOffset = originalSwitchOffsetByOriginalSwitchDataOffset.get(originalDataOffset, -1); int originalSwitchAddress =
if (originalSwitchOffset == -1) { originalSwitchAddressByOriginalSwitchDataAddress.get(originalDataAddress, -1);
throw new RuntimeException("This method contains an unreferenced switch data block, and can't be automatically fixed."); 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; assert newAddressByOriginalAddress.indexOfKey(originalSwitchAddress) >= 0;
int newSwitchOffset = newOffsetsByOriginalOffset.get(originalSwitchOffset); int newSwitchAddress = newAddressByOriginalAddress.get(originalSwitchAddress);
int[] targets = multiOffsetInstruction.getTargets(); int[] targets = multiOffsetInstruction.getTargets();
for (int t=0; t<targets.length; t++) { for (int t=0; t<targets.length; t++) {
int originalTargetOffset = originalSwitchOffset + targets[t]*2; int originalTargetCodeAddress = originalSwitchAddress + targets[t];
assert newOffsetsByOriginalOffset.indexOfKey(originalTargetOffset) >= 0; assert newAddressByOriginalAddress.indexOfKey(originalTargetCodeAddress) >= 0;
int newTargetOffset = newOffsetsByOriginalOffset.get(originalTargetOffset); int newTargetCodeAddress = newAddressByOriginalAddress.get(originalTargetCodeAddress);
int newOffset = (newTargetOffset - newSwitchOffset)/2; int newCodeAddress = newTargetCodeAddress - newSwitchAddress;
if (newOffset != targets[t]) { if (newCodeAddress != targets[t]) {
multiOffsetInstruction.updateTarget(t, newOffset); multiOffsetInstruction.updateTarget(t, newCodeAddress);
} }
} }
} }
currentCodeOffset += instruction.getSize(currentCodeOffset); currentCodeAddress += instruction.getSize(currentCodeAddress);
} }
if (debugInfo != null) { if (debugInfo != null) {
@ -574,7 +598,7 @@ public class CodeItem extends Item<CodeItem> {
ByteArrayInput debugInput = new ByteArrayInput(encodedDebugInfo); ByteArrayInput debugInput = new ByteArrayInput(encodedDebugInfo);
DebugInstructionFixer debugInstructionFixer = new DebugInstructionFixer(encodedDebugInfo, DebugInstructionFixer debugInstructionFixer = new DebugInstructionFixer(encodedDebugInfo,
newOffsetsByOriginalOffset, originalOffsetsByNewOffset); newAddressByOriginalAddress);
DebugInstructionIterator.IterateInstructions(debugInput, debugInstructionFixer); DebugInstructionIterator.IterateInstructions(debugInput, debugInstructionFixer);
if (debugInstructionFixer.result != null) { if (debugInstructionFixer.result != null) {
@ -585,122 +609,124 @@ public class CodeItem extends Item<CodeItem> {
if (encodedCatchHandlers != null) { if (encodedCatchHandlers != null) {
for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) { for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) {
if (encodedCatchHandler.catchAllHandlerAddress != -1) { if (encodedCatchHandler.catchAllHandlerAddress != -1) {
assert newOffsetsByOriginalOffset.indexOfKey(encodedCatchHandler.catchAllHandlerAddress*2) >= 0; assert newAddressByOriginalAddress.indexOfKey(encodedCatchHandler.catchAllHandlerAddress) >= 0;
encodedCatchHandler.catchAllHandlerAddress = encodedCatchHandler.catchAllHandlerAddress =
newOffsetsByOriginalOffset.get(encodedCatchHandler.catchAllHandlerAddress*2)/2; newAddressByOriginalAddress.get(encodedCatchHandler.catchAllHandlerAddress);
} }
for (EncodedTypeAddrPair handler: encodedCatchHandler.handlers) { for (EncodedTypeAddrPair handler: encodedCatchHandler.handlers) {
assert newOffsetsByOriginalOffset.indexOfKey(handler.handlerAddress*2) >= 0; assert newAddressByOriginalAddress.indexOfKey(handler.handlerAddress) >= 0;
handler.handlerAddress = newOffsetsByOriginalOffset.get(handler.handlerAddress*2)/2; handler.handlerAddress = newAddressByOriginalAddress.get(handler.handlerAddress);
} }
} }
} }
if (this.tries != null) { if (this.tries != null) {
for (TryItem tryItem: tries) { for (TryItem tryItem: tries) {
int startAddress = tryItem.startAddress; int startAddress = tryItem.startCodeAddress;
int endAddress = tryItem.startAddress + tryItem.instructionCount; int endAddress = tryItem.startCodeAddress + tryItem.tryLength;
assert newOffsetsByOriginalOffset.indexOfKey(startAddress * 2) >= 0; assert newAddressByOriginalAddress.indexOfKey(startAddress) >= 0;
tryItem.startAddress = newOffsetsByOriginalOffset.get(startAddress * 2)/2; tryItem.startCodeAddress = newAddressByOriginalAddress.get(startAddress);
assert newOffsetsByOriginalOffset.indexOfKey(endAddress * 2) >= 0; assert newAddressByOriginalAddress.indexOfKey(endAddress) >= 0;
tryItem.instructionCount = newOffsetsByOriginalOffset.get(endAddress * 2)/2 - tryItem.startAddress; tryItem.tryLength = newAddressByOriginalAddress.get(endAddress) - tryItem.startCodeAddress;
} }
} }
} }
private class DebugInstructionFixer extends DebugInstructionIterator.ProcessRawDebugInstructionDelegate { private class DebugInstructionFixer extends DebugInstructionIterator.ProcessRawDebugInstructionDelegate {
private int address = 0; private int currentCodeAddress = 0;
private SparseIntArray newOffsetsByOriginalOffset; private SparseIntArray newAddressByOriginalAddress;
private SparseIntArray originalOffsetsByNewOffset;
private final byte[] originalEncodedDebugInfo; private final byte[] originalEncodedDebugInfo;
public byte[] result = null; public byte[] result = null;
public DebugInstructionFixer(byte[] originalEncodedDebugInfo, SparseIntArray newOffsetsByOriginalOffset, public DebugInstructionFixer(byte[] originalEncodedDebugInfo, SparseIntArray newAddressByOriginalAddress) {
SparseIntArray originalOffsetsByNewOffset) { this.newAddressByOriginalAddress = newAddressByOriginalAddress;
this.newOffsetsByOriginalOffset = newOffsetsByOriginalOffset;
this.originalOffsetsByNewOffset = originalOffsetsByNewOffset;
this.originalEncodedDebugInfo = originalEncodedDebugInfo; this.originalEncodedDebugInfo = originalEncodedDebugInfo;
} }
@Override @Override
public void ProcessAdvancePC(int startOffset, int length, int addressDelta) { public void ProcessAdvancePC(int startDebugOffset, int debugInstructionLength, int codeAddressDelta) {
address += addressDelta; currentCodeAddress += codeAddressDelta;
if (result != null) { if (result != null) {
return; 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 //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. //instruction replacement.
//In this case, it should be safe to skip, because there will be another AdvancePC/SpecialOpcode that will //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 //bump up the address to point to a valid instruction before anything (line/local/etc.) is emitted
if (newOffset == -1) { if (newCodeAddress == -1) {
return; return;
} }
assert newOffset != -1; if (newCodeAddress != currentCodeAddress) {
newOffset = newOffset / 2; int newCodeAddressDelta = newCodeAddress - (currentCodeAddress - codeAddressDelta);
assert newCodeAddressDelta > 0;
int codeAddressDeltaLeb128Size = Leb128Utils.unsignedLeb128Size(newCodeAddressDelta);
if (newOffset != address) { //if the length of the new code address delta is the same, we can use the existing buffer
int newAddressDelta = newOffset - (address - addressDelta); if (codeAddressDeltaLeb128Size + 1 == debugInstructionLength) {
assert newAddressDelta > 0; result = originalEncodedDebugInfo;
int addressDiffSize = Leb128Utils.unsignedLeb128Size(newAddressDelta); 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 System.arraycopy(originalEncodedDebugInfo, startDebugOffset + debugInstructionLength, result,
Leb128Utils.writeUnsignedLeb128(newAddressDelta, result, startOffset+1); startDebugOffset + codeAddressDeltaLeb128Size + 1,
originalEncodedDebugInfo.length - (startDebugOffset + codeAddressDeltaLeb128Size + 1));
System.arraycopy(originalEncodedDebugInfo, startOffset+length, result, }
startOffset + addressDiffSize + 1,
originalEncodedDebugInfo.length - (startOffset + addressDiffSize + 1));
} }
} }
@Override @Override
public void ProcessSpecialOpcode(int startOffset, int debugOpcode, int lineDelta, public void ProcessSpecialOpcode(int startDebugOffset, int debugOpcode, int lineDelta,
int addressDelta) { int codeAddressDelta) {
address += addressDelta; currentCodeAddress += codeAddressDelta;
if (result != null) { if (result != null) {
return; return;
} }
int newOffset = newOffsetsByOriginalOffset.get(address*2, -1); int newCodeAddress = newAddressByOriginalAddress.get(currentCodeAddress, -1);
assert newOffset != -1; assert newCodeAddress != -1;
newOffset = newOffset / 2;
if (newOffset != address) { if (newCodeAddress != currentCodeAddress) {
int newAddressDelta = newOffset - (address - addressDelta); int newCodeAddressDelta = newCodeAddress - (currentCodeAddress - codeAddressDelta);
assert newAddressDelta > 0; 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 //an additional DBG_ADVANCE_PC opcode
if (lineDelta < 2 && newAddressDelta > 16 || lineDelta > 1 && newAddressDelta > 15) { if (lineDelta < 2 && newCodeAddressDelta > 16 || lineDelta > 1 && newCodeAddressDelta > 15) {
int additionalAddressDelta = newOffset - address; int additionalCodeAddressDelta = newCodeAddress - currentCodeAddress;
int additionalAddressDeltaSize = Leb128Utils.signedLeb128Size(additionalAddressDelta); 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); System.arraycopy(originalEncodedDebugInfo, 0, result, 0, startDebugOffset);
result[startOffset] = 0x01; //DBG_ADVANCE_PC result[startDebugOffset] = 0x01; //DBG_ADVANCE_PC
Leb128Utils.writeUnsignedLeb128(additionalAddressDelta, result, startOffset+1); Leb128Utils.writeUnsignedLeb128(additionalCodeAddressDelta, result, startDebugOffset+1);
System.arraycopy(originalEncodedDebugInfo, startOffset, result, System.arraycopy(originalEncodedDebugInfo, startDebugOffset, result,
startOffset+additionalAddressDeltaSize+1, startDebugOffset+additionalCodeAddressDeltaLeb128Size+1,
result.length - (startOffset+additionalAddressDeltaSize+1)); result.length - (startDebugOffset+additionalCodeAddressDeltaLeb128Size+1));
} else { } else {
result = new byte[originalEncodedDebugInfo.length]; result = originalEncodedDebugInfo;
System.arraycopy(originalEncodedDebugInfo, 0, result, 0, result.length); result[startDebugOffset] = DebugInfoBuilder.calculateSpecialOpcode(lineDelta,
result[startOffset] = DebugInfoBuilder.calculateSpecialOpcode(lineDelta, newCodeAddressDelta);
newAddressDelta);
} }
} }
} }
@ -710,12 +736,12 @@ public class CodeItem extends Item<CodeItem> {
/** /**
* The address (in 2-byte words) within the code where the try block starts * The address (in 2-byte words) within the code where the try block starts
*/ */
private int startAddress; private int startCodeAddress;
/** /**
* The number of 2-byte words that the try block covers * The number of 2-byte words that the try block covers
*/ */
private int instructionCount; private int tryLength;
/** /**
* The associated exception handler * The associated exception handler
@ -724,13 +750,13 @@ public class CodeItem extends Item<CodeItem> {
/** /**
* Construct a new <code>TryItem</code> with the given values * 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 startCodeAddress the code address within the code where the try block starts
* @param instructionCount the number of 2-byte words that the try block covers * @param tryLength the number of code blocks that the try block covers
* @param encodedCatchHandler the associated exception handler * @param encodedCatchHandler the associated exception handler
*/ */
public TryItem(int startAddress, int instructionCount, EncodedCatchHandler encodedCatchHandler) { public TryItem(int startCodeAddress, int tryLength, EncodedCatchHandler encodedCatchHandler) {
this.startAddress = startAddress; this.startCodeAddress = startCodeAddress;
this.instructionCount = instructionCount; this.tryLength = tryLength;
this.encodedCatchHandler = encodedCatchHandler; this.encodedCatchHandler = encodedCatchHandler;
} }
@ -742,8 +768,8 @@ public class CodeItem extends Item<CodeItem> {
* structure. * structure.
*/ */
private TryItem(Input in, SparseArray<EncodedCatchHandler> encodedCatchHandlers) { private TryItem(Input in, SparseArray<EncodedCatchHandler> encodedCatchHandlers) {
startAddress = in.readInt(); startCodeAddress = in.readInt();
instructionCount = in.readShort(); tryLength = in.readShort();
encodedCatchHandler = encodedCatchHandlers.get(in.readShort()); encodedCatchHandler = encodedCatchHandlers.get(in.readShort());
if (encodedCatchHandler == null) { if (encodedCatchHandler == null) {
@ -757,29 +783,29 @@ public class CodeItem extends Item<CodeItem> {
*/ */
private void writeTo(AnnotatedOutput out) { private void writeTo(AnnotatedOutput out) {
if (out.annotates()) { if (out.annotates()) {
out.annotate(4, "start_addr: 0x" + Integer.toHexString(startAddress)); out.annotate(4, "start_addr: 0x" + Integer.toHexString(startCodeAddress));
out.annotate(2, "insn_count: 0x" + Integer.toHexString(instructionCount) + " (" + instructionCount + out.annotate(2, "try_length: 0x" + Integer.toHexString(tryLength) + " (" + tryLength +
")"); ")");
out.annotate(2, "handler_off: 0x" + Integer.toHexString(encodedCatchHandler.getOffsetInList())); out.annotate(2, "handler_off: 0x" + Integer.toHexString(encodedCatchHandler.getOffsetInList()));
} }
out.writeInt(startAddress); out.writeInt(startCodeAddress);
out.writeShort(instructionCount); out.writeShort(tryLength);
out.writeShort(encodedCatchHandler.getOffsetInList()); out.writeShort(encodedCatchHandler.getOffsetInList());
} }
/** /**
* @return The address (in 2-byte words) within the code where the try block starts * @return The address (in 2-byte words) within the code where the try block starts
*/ */
public int getStartAddress() { public int getStartCodeAddress() {
return startAddress; 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() { public int getTryLength() {
return instructionCount; return tryLength;
} }
} }
@ -825,7 +851,11 @@ public class CodeItem extends Item<CodeItem> {
} }
for (int i=0; i<handlers.length; i++) { for (int i=0; i<handlers.length; i++) {
handlers[i] = new EncodedTypeAddrPair(dexFile, in); try {
handlers[i] = new EncodedTypeAddrPair(dexFile, in);
} catch (Exception ex) {
throw ExceptionWithContext.withContext(ex, "Error while reading EncodedTypeAddrPair at index " + i);
}
} }
if (handlerCount <= 0) { if (handlerCount <= 0) {

View File

@ -44,29 +44,31 @@ public class DebugInstructionIterator {
* for each instruction that is encountered * for each instruction that is encountered
*/ */
public static void IterateInstructions(Input in, ProcessRawDebugInstructionDelegate processDebugInstruction) { public static void IterateInstructions(Input in, ProcessRawDebugInstructionDelegate processDebugInstruction) {
int startOffset; int startDebugOffset;
while(true) while(true)
{ {
startOffset = in.getCursor(); startDebugOffset = in.getCursor();
byte debugOpcode = in.readByte(); byte debugOpcode = in.readByte();
switch (debugOpcode) { switch (debugOpcode) {
case 0x00: case 0x00:
{ {
processDebugInstruction.ProcessEndSequence(startOffset); processDebugInstruction.ProcessEndSequence(startDebugOffset);
return; return;
} }
case 0x01: case 0x01:
{ {
int addressDiff = in.readUnsignedLeb128(); int codeAddressDiff = in.readUnsignedLeb128();
processDebugInstruction.ProcessAdvancePC(startOffset, in.getCursor() - startOffset, addressDiff); processDebugInstruction.ProcessAdvancePC(startDebugOffset, in.getCursor() - startDebugOffset,
codeAddressDiff);
break; break;
} }
case 0x02: case 0x02:
{ {
int lineDiff = in.readSignedLeb128(); int lineDiff = in.readSignedLeb128();
processDebugInstruction.ProcessAdvanceLine(startOffset, in.getCursor() - startOffset, lineDiff); processDebugInstruction.ProcessAdvanceLine(startDebugOffset, in.getCursor() - startDebugOffset,
lineDiff);
break; break;
} }
case 0x03: case 0x03:
@ -79,8 +81,8 @@ public class DebugInstructionIterator {
} }
int nameIndex = in.readUnsignedLeb128() - 1; int nameIndex = in.readUnsignedLeb128() - 1;
int typeIndex = in.readUnsignedLeb128() - 1; int typeIndex = in.readUnsignedLeb128() - 1;
processDebugInstruction.ProcessStartLocal(startOffset, in.getCursor() - startOffset, registerNum, processDebugInstruction.ProcessStartLocal(startDebugOffset, in.getCursor() - startDebugOffset,
nameIndex, typeIndex, isSignedRegister); registerNum, nameIndex, typeIndex, isSignedRegister);
break; break;
} }
case 0x04: case 0x04:
@ -94,8 +96,9 @@ public class DebugInstructionIterator {
int nameIndex = in.readUnsignedLeb128() - 1; int nameIndex = in.readUnsignedLeb128() - 1;
int typeIndex = in.readUnsignedLeb128() - 1; int typeIndex = in.readUnsignedLeb128() - 1;
int signatureIndex = in.readUnsignedLeb128() - 1; int signatureIndex = in.readUnsignedLeb128() - 1;
processDebugInstruction.ProcessStartLocalExtended(startOffset, in.getCursor() - startOffset, processDebugInstruction.ProcessStartLocalExtended(startDebugOffset,
registerNum, nameIndex, typeIndex, signatureIndex, isSignedRegister); in.getCursor() - startDebugOffset, registerNum, nameIndex, typeIndex, signatureIndex,
isSignedRegister);
break; break;
} }
case 0x05: case 0x05:
@ -106,8 +109,8 @@ public class DebugInstructionIterator {
isSignedRegister = true; isSignedRegister = true;
registerNum = ~registerNum; registerNum = ~registerNum;
} }
processDebugInstruction.ProcessEndLocal(startOffset, in.getCursor() - startOffset, registerNum, processDebugInstruction.ProcessEndLocal(startDebugOffset, in.getCursor() - startDebugOffset,
isSignedRegister); registerNum, isSignedRegister);
break; break;
} }
case 0x06: case 0x06:
@ -118,30 +121,31 @@ public class DebugInstructionIterator {
isSignedRegister = true; isSignedRegister = true;
registerNum = ~registerNum; registerNum = ~registerNum;
} }
processDebugInstruction.ProcessRestartLocal(startOffset, in.getCursor() - startOffset, registerNum, processDebugInstruction.ProcessRestartLocal(startDebugOffset, in.getCursor() - startDebugOffset,
isSignedRegister); registerNum, isSignedRegister);
break; break;
} }
case 0x07: case 0x07:
{ {
processDebugInstruction.ProcessSetPrologueEnd(startOffset); processDebugInstruction.ProcessSetPrologueEnd(startDebugOffset);
break; break;
} }
case 0x08: case 0x08:
{ {
processDebugInstruction.ProcessSetEpilogueBegin(startOffset); processDebugInstruction.ProcessSetEpilogueBegin(startDebugOffset);
break; break;
} }
case 0x09: case 0x09:
{ {
int nameIndex = in.readUnsignedLeb128(); int nameIndex = in.readUnsignedLeb128();
processDebugInstruction.ProcessSetFile(startOffset, in.getCursor() - startOffset, nameIndex); processDebugInstruction.ProcessSetFile(startDebugOffset, in.getCursor() - startDebugOffset,
nameIndex);
break; break;
} }
default: default:
{ {
int base = ((debugOpcode & 0xFF) - 0x0A); 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, public static void DecodeInstructions(DebugInfoItem debugInfoItem, int registerCount,
ProcessDecodedDebugInstructionDelegate processDecodedDebugInstruction) { ProcessDecodedDebugInstructionDelegate processDecodedDebugInstruction) {
int startOffset; int startDebugOffset;
int address = 0; int currentCodeAddress = 0;
int line = debugInfoItem.getLineStart(); int line = debugInfoItem.getLineStart();
Input in = new ByteArrayInput(debugInfoItem.getEncodedDebugInfo()); Input in = new ByteArrayInput(debugInfoItem.getEncodedDebugInfo());
DexFile dexFile = debugInfoItem.getDexFile(); DexFile dexFile = debugInfoItem.getDexFile();
@ -167,96 +171,97 @@ public class DebugInstructionIterator {
while(true) while(true)
{ {
startOffset = in.getCursor(); startDebugOffset = in.getCursor();
byte debugOpcode = in.readByte(); byte debugOpcode = in.readByte();
switch (debugOpcode) { switch (DebugOpcode.getDebugOpcodeByValue(debugOpcode)) {
case 0x00: case DBG_END_SEQUENCE:
{ {
return; return;
} }
case 0x01: case DBG_ADVANCE_PC:
{ {
int addressDiff = in.readUnsignedLeb128(); int codeAddressDiff = in.readUnsignedLeb128();
address += addressDiff; currentCodeAddress += codeAddressDiff;
break; break;
} }
case 0x02: case DBG_ADVANCE_LINE:
{ {
int lineDiff = in.readSignedLeb128(); int lineDiff = in.readSignedLeb128();
line += lineDiff; line += lineDiff;
break; break;
} }
case 0x03: case DBG_START_LOCAL:
{ {
int registerNum = in.readUnsignedLeb128(); int registerNum = in.readUnsignedLeb128();
StringIdItem name = dexFile.StringIdsSection.getItemByIndex(in.readUnsignedLeb128() - 1); StringIdItem name = dexFile.StringIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
TypeIdItem type = dexFile.TypeIdsSection.getItemByIndex(in.readUnsignedLeb128() - 1); TypeIdItem type = dexFile.TypeIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
locals[registerNum] = new Local(registerNum, name, type, null); locals[registerNum] = new Local(registerNum, name, type, null);
processDecodedDebugInstruction.ProcessStartLocal(address, in.getCursor() - startOffset, registerNum, processDecodedDebugInstruction.ProcessStartLocal(currentCodeAddress,
name, type); in.getCursor() - startDebugOffset, registerNum, name, type);
break; break;
} }
case 0x04: case DBG_START_LOCAL_EXTENDED:
{ {
int registerNum = in.readUnsignedLeb128(); int registerNum = in.readUnsignedLeb128();
StringIdItem name = dexFile.StringIdsSection.getItemByIndex(in.readUnsignedLeb128() - 1); StringIdItem name = dexFile.StringIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
TypeIdItem type = dexFile.TypeIdsSection.getItemByIndex(in.readUnsignedLeb128() - 1); TypeIdItem type = dexFile.TypeIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
StringIdItem signature = dexFile.StringIdsSection.getItemByIndex(in.readUnsignedLeb128() - 1); StringIdItem signature =
dexFile.StringIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
locals[registerNum] = new Local(registerNum, name, type, signature); locals[registerNum] = new Local(registerNum, name, type, signature);
processDecodedDebugInstruction.ProcessStartLocalExtended(address, in.getCursor() - startOffset, processDecodedDebugInstruction.ProcessStartLocalExtended(currentCodeAddress,
registerNum, name, type, signature); in.getCursor() - startDebugOffset, registerNum, name, type, signature);
break; break;
} }
case 0x05: case DBG_END_LOCAL:
{ {
int registerNum = in.readUnsignedLeb128(); int registerNum = in.readUnsignedLeb128();
Local local = locals[registerNum]; Local local = locals[registerNum];
if (local == null) { if (local == null) {
processDecodedDebugInstruction.ProcessEndLocal(address, in.getCursor() - startOffset, registerNum, processDecodedDebugInstruction.ProcessEndLocal(currentCodeAddress, in.getCursor() - startDebugOffset, registerNum,
null, null, null); null, null, null);
} else { } else {
processDecodedDebugInstruction.ProcessEndLocal(address, in.getCursor() - startOffset, registerNum, processDecodedDebugInstruction.ProcessEndLocal(currentCodeAddress, in.getCursor() - startDebugOffset, registerNum,
local.name, local.type, local.signature); local.name, local.type, local.signature);
} }
break; break;
} }
case 0x06: case DBG_RESTART_LOCAL:
{ {
int registerNum = in.readUnsignedLeb128(); int registerNum = in.readUnsignedLeb128();
Local local = locals[registerNum]; Local local = locals[registerNum];
if (local == null) { if (local == null) {
processDecodedDebugInstruction.ProcessRestartLocal(address, in.getCursor() - startOffset, processDecodedDebugInstruction.ProcessRestartLocal(currentCodeAddress, in.getCursor() - startDebugOffset,
registerNum, null, null, null); registerNum, null, null, null);
} else { } else {
processDecodedDebugInstruction.ProcessRestartLocal(address, in.getCursor() - startOffset, processDecodedDebugInstruction.ProcessRestartLocal(currentCodeAddress, in.getCursor() - startDebugOffset,
registerNum, local.name, local.type, local.signature); registerNum, local.name, local.type, local.signature);
} }
break; break;
} }
case 0x07: case DBG_SET_PROLOGUE_END:
{ {
processDecodedDebugInstruction.ProcessSetPrologueEnd(address); processDecodedDebugInstruction.ProcessSetPrologueEnd(currentCodeAddress);
break; break;
} }
case 0x08: case DBG_SET_EPILOGUE_BEGIN:
{ {
processDecodedDebugInstruction.ProcessSetEpilogueBegin(address); processDecodedDebugInstruction.ProcessSetEpilogueBegin(currentCodeAddress);
break; break;
} }
case 0x09: case DBG_SET_FILE:
{ {
StringIdItem name = dexFile.StringIdsSection.getItemByIndex(in.readUnsignedLeb128() - 1); StringIdItem name = dexFile.StringIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
processDecodedDebugInstruction.ProcessSetFile(address, in.getCursor() - startOffset, name); processDecodedDebugInstruction.ProcessSetFile(currentCodeAddress, in.getCursor() - startDebugOffset, name);
break; break;
} }
default: case DBG_SPECIAL_OPCODE:
{ {
int base = ((debugOpcode & 0xFF) - 0x0A); int base = ((debugOpcode & 0xFF) - 0x0A);
address += base / 15; currentCodeAddress += base / 15;
line += (base % 15) - 4; line += (base % 15) - 4;
processDecodedDebugInstruction.ProcessLineEmit(address, line); processDecodedDebugInstruction.ProcessLineEmit(currentCodeAddress, line);
} }
} }
} }
@ -265,50 +270,50 @@ public class DebugInstructionIterator {
public static class ProcessRawDebugInstructionDelegate public static class ProcessRawDebugInstructionDelegate
{ {
//TODO: add javadocs //TODO: add javadocs
public void ProcessEndSequence(int startOffset) { public void ProcessEndSequence(int startDebugOffset) {
ProcessStaticOpcode(DebugOpcode.DBG_END_SEQUENCE, startOffset, 1); ProcessStaticOpcode(DebugOpcode.DBG_END_SEQUENCE, startDebugOffset, 1);
} }
public void ProcessAdvancePC(int startOffset, int length, int addressDiff) { public void ProcessAdvancePC(int startDebugOffset, int length, int codeAddressDiff) {
ProcessStaticOpcode(DebugOpcode.DBG_ADVANCE_PC, startOffset, length); ProcessStaticOpcode(DebugOpcode.DBG_ADVANCE_PC, startDebugOffset, length);
} }
public void ProcessAdvanceLine(int startOffset, int length, int lineDiff) { public void ProcessAdvanceLine(int startDebugOffset, int length, int lineDiff) {
ProcessStaticOpcode(DebugOpcode.DBG_ADVANCE_LINE, startOffset, length); 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) { 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) { int typeIndex,int signatureIndex, boolean registerIsSigned) {
} }
public void ProcessEndLocal(int startOffset, int length, int registerNum, boolean registerIsSigned) { public void ProcessEndLocal(int startDebugOffset, int length, int registerNum, boolean registerIsSigned) {
ProcessStaticOpcode(DebugOpcode.DBG_END_LOCAL, startOffset, length); ProcessStaticOpcode(DebugOpcode.DBG_END_LOCAL, startDebugOffset, length);
} }
public void ProcessRestartLocal(int startOffset, int length, int registerNum, boolean registerIsSigned) { public void ProcessRestartLocal(int startDebugOffset, int length, int registerNum, boolean registerIsSigned) {
ProcessStaticOpcode(DebugOpcode.DBG_RESTART_LOCAL, startOffset, length); ProcessStaticOpcode(DebugOpcode.DBG_RESTART_LOCAL, startDebugOffset, length);
} }
public void ProcessSetPrologueEnd(int startOffset) { public void ProcessSetPrologueEnd(int startDebugOffset) {
ProcessStaticOpcode(DebugOpcode.DBG_SET_PROLOGUE_END, startOffset, 1); ProcessStaticOpcode(DebugOpcode.DBG_SET_PROLOGUE_END, startDebugOffset, 1);
} }
public void ProcessSetEpilogueBegin(int startOffset) { public void ProcessSetEpilogueBegin(int startDebugOffset) {
ProcessStaticOpcode(DebugOpcode.DBG_SET_EPILOGUE_BEGIN, startOffset, 1); 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) { public void ProcessSpecialOpcode(int startDebugOffset, int debugOpcode, int lineDiff, int codeAddressDiff) {
ProcessStaticOpcode(DebugOpcode.DBG_SPECIAL_OPCODE, startOffset, 1); 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) {
} }
} }

View File

@ -52,7 +52,7 @@ public enum DebugOpcode {
} }
public static DebugOpcode getDebugOpcodeByValue(byte debugOpcodeValue) { public static DebugOpcode getDebugOpcodeByValue(byte debugOpcodeValue) {
debugOpcodeValue = (byte)Math.min(debugOpcodeValue, 0x0A); debugOpcodeValue = (byte)Math.min(debugOpcodeValue & 0xFF, 0x0A);
return opcodesByValue[debugOpcodeValue]; return opcodesByValue[debugOpcodeValue];
} }

View File

@ -103,12 +103,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
parameterNames = new StringIdItem[in.readUnsignedLeb128()]; parameterNames = new StringIdItem[in.readUnsignedLeb128()];
IndexedSection<StringIdItem> stringIdSection = dexFile.StringIdsSection; IndexedSection<StringIdItem> stringIdSection = dexFile.StringIdsSection;
for (int i=0; i<parameterNames.length; i++) { for (int i=0; i<parameterNames.length; i++) {
int index = in.readUnsignedLeb128() - 1; parameterNames[i] = stringIdSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
if (index < 0) {
parameterNames[i] = null;
} else {
parameterNames[i] = stringIdSection.getItemByIndex(index);
}
} }
int start = in.getCursor(); int start = in.getCursor();
@ -116,7 +111,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
DebugInstructionIterator.IterateInstructions(in, DebugInstructionIterator.IterateInstructions(in,
new DebugInstructionIterator.ProcessRawDebugInstructionDelegate() { new DebugInstructionIterator.ProcessRawDebugInstructionDelegate() {
@Override @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) { int typeIndex, boolean registerIsSigned) {
if (nameIndex != -1) { if (nameIndex != -1) {
referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex)); referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex));
@ -127,8 +122,8 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
} }
@Override @Override
public void ProcessStartLocalExtended(int startOffset, int length, int registerNume, int nameIndex, public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNume,
int typeIndex, int signatureIndex, int nameIndex, int typeIndex, int signatureIndex,
boolean registerIsSigned) { boolean registerIsSigned) {
if (nameIndex != -1) { if (nameIndex != -1) {
referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex)); referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex));
@ -142,7 +137,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
} }
@Override @Override
public void ProcessSetFile(int startOffset, int length, int nameIndex) { public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) {
if (nameIndex != -1) { if (nameIndex != -1) {
referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex)); referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex));
} }
@ -187,12 +182,12 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
private int referencedItemsPosition = 0; private int referencedItemsPosition = 0;
@Override @Override
public void ProcessStaticOpcode(DebugOpcode opcode, int startOffset, int length) { public void ProcessStaticOpcode(DebugOpcode opcode, int startDebugOffset, int length) {
this.length+=length; this.length+=length;
} }
@Override @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) { int typeIndex, boolean registerIsSigned) {
this.length++; this.length++;
if (dexFile.getPreserveSignedRegisters() && registerIsSigned) { if (dexFile.getPreserveSignedRegisters() && registerIsSigned) {
@ -216,7 +211,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
} }
@Override @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, int typeIndex, int signatureIndex,
boolean registerIsSigned) { boolean registerIsSigned) {
this.length++; this.length++;
@ -246,7 +241,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
} }
@Override @Override
public void ProcessSetFile(int startOffset, int length, int nameIndex) { public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) {
this.length++; this.length++;
if (nameIndex != -1) { if (nameIndex != -1) {
this.length+= this.length+=
@ -261,7 +256,6 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
/** {@inheritDoc} */ /** {@inheritDoc} */
protected void writeItem(final AnnotatedOutput out) { protected void writeItem(final AnnotatedOutput out) {
if (out.annotates()) { if (out.annotates()) {
writeItemWithAnnotations(out); writeItemWithAnnotations(out);
} else { } else {
@ -275,7 +269,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
* @param encodedDebugInfo the new encoded debug info * @param encodedDebugInfo the new encoded debug info
*/ */
protected void setEncodedDebugInfo(byte[] encodedDebugInfo) { 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; this.encodedDebugInfo = encodedDebugInfo;
} }
@ -302,12 +296,12 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
private int referencedItemsPosition = 0; private int referencedItemsPosition = 0;
@Override @Override
public void ProcessStaticOpcode(DebugOpcode opcode, int startOffset, int length) { public void ProcessStaticOpcode(DebugOpcode opcode, int startDebugOffset, int length) {
out.write(encodedDebugInfo, startOffset, length); out.write(encodedDebugInfo, startDebugOffset, length);
} }
@Override @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) { int typeIndex, boolean registerIsSigned) {
out.writeByte(DebugOpcode.DBG_START_LOCAL.value); out.writeByte(DebugOpcode.DBG_START_LOCAL.value);
if (dexFile.getPreserveSignedRegisters() && registerIsSigned) { if (dexFile.getPreserveSignedRegisters() && registerIsSigned) {
@ -328,7 +322,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
} }
@Override @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, int typeIndex, int signatureIndex,
boolean registerIsSigned) { boolean registerIsSigned) {
out.writeByte(DebugOpcode.DBG_START_LOCAL_EXTENDED.value); out.writeByte(DebugOpcode.DBG_START_LOCAL_EXTENDED.value);
@ -355,7 +349,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
} }
@Override @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); out.writeByte(DebugOpcode.DBG_SET_FILE.value);
if (nameIndex != -1) { if (nameIndex != -1) {
out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1); out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1);
@ -395,13 +389,13 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
private int referencedItemsPosition = 0; private int referencedItemsPosition = 0;
@Override @Override
public void ProcessEndSequence(int startOffset) { public void ProcessEndSequence(int startDebugOffset) {
out.annotate("DBG_END_SEQUENCE"); out.annotate("DBG_END_SEQUENCE");
out.writeByte(DebugOpcode.DBG_END_SEQUENCE.value); out.writeByte(DebugOpcode.DBG_END_SEQUENCE.value);
} }
@Override @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.annotate("DBG_ADVANCE_PC");
out.writeByte(DebugOpcode.DBG_ADVANCE_PC.value); out.writeByte(DebugOpcode.DBG_ADVANCE_PC.value);
out.indent(); out.indent();
@ -411,7 +405,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
} }
@Override @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.annotate("DBG_ADVANCE_LINE");
out.writeByte(DebugOpcode.DBG_ADVANCE_LINE.value); out.writeByte(DebugOpcode.DBG_ADVANCE_LINE.value);
out.indent(); out.indent();
@ -421,7 +415,7 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
} }
@Override @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) { int typeIndex, boolean registerIsSigned) {
out.annotate("DBG_START_LOCAL"); out.annotate("DBG_START_LOCAL");
out.writeByte(DebugOpcode.DBG_START_LOCAL.value); out.writeByte(DebugOpcode.DBG_START_LOCAL.value);
@ -454,8 +448,8 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
} }
@Override @Override
public void ProcessStartLocalExtended(int startOffset, int length, int registerNum, int nameIndex, public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNum,
int typeIndex, int signatureIndex, int nameIndex, int typeIndex, int signatureIndex,
boolean registerIsSigned) { boolean registerIsSigned) {
out.annotate("DBG_START_LOCAL_EXTENDED"); out.annotate("DBG_START_LOCAL_EXTENDED");
out.writeByte(DebugOpcode.DBG_START_LOCAL_EXTENDED.value); out.writeByte(DebugOpcode.DBG_START_LOCAL_EXTENDED.value);
@ -497,7 +491,8 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
} }
@Override @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.annotate("DBG_END_LOCAL");
out.writeByte(DebugOpcode.DBG_END_LOCAL.value); out.writeByte(DebugOpcode.DBG_END_LOCAL.value);
out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")"); out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")");
@ -509,7 +504,8 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
} }
@Override @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.annotate("DBG_RESTART_LOCAL");
out.writeByte(DebugOpcode.DBG_RESTART_LOCAL.value); out.writeByte(DebugOpcode.DBG_RESTART_LOCAL.value);
out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")"); out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")");
@ -521,19 +517,19 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
} }
@Override @Override
public void ProcessSetPrologueEnd(int startOffset) { public void ProcessSetPrologueEnd(int startDebugOffset) {
out.annotate("DBG_SET_PROLOGUE_END"); out.annotate("DBG_SET_PROLOGUE_END");
out.writeByte(DebugOpcode.DBG_SET_PROLOGUE_END.value); out.writeByte(DebugOpcode.DBG_SET_PROLOGUE_END.value);
} }
@Override @Override
public void ProcessSetEpilogueBegin(int startOffset) { public void ProcessSetEpilogueBegin(int startDebugOffset) {
out.annotate("DBG_SET_EPILOGUE_BEGIN"); out.annotate("DBG_SET_EPILOGUE_BEGIN");
out.writeByte(DebugOpcode.DBG_SET_EPILOGUE_BEGIN.value); out.writeByte(DebugOpcode.DBG_SET_EPILOGUE_BEGIN.value);
} }
@Override @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.annotate("DBG_SET_FILE");
out.writeByte(DebugOpcode.DBG_SET_FILE.value); out.writeByte(DebugOpcode.DBG_SET_FILE.value);
if (nameIndex != -1) { if (nameIndex != -1) {
@ -548,7 +544,8 @@ public class DebugInfoItem extends Item<DebugInfoItem> {
} }
@Override @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) + "(" + out.annotate("DBG_SPECIAL_OPCODE: line_diff=0x" + Integer.toHexString(lineDiff) + "(" +
lineDiff +"),addressDiff=0x" + Integer.toHexString(addressDiff) + "(" + addressDiff + lineDiff +"),addressDiff=0x" + Integer.toHexString(addressDiff) + "(" + addressDiff +
")"); ")");

View File

@ -113,12 +113,7 @@ public class FieldIdItem extends Item<FieldIdItem> {
/** {@inheritDoc} */ /** {@inheritDoc} */
public String getConciseIdentity() { public String getConciseIdentity() {
String parentClass = classType.getTypeDescriptor(); return getFieldString();
//strip off the leading L and trailing ;
parentClass = parentClass.substring(1, parentClass.length() - 1);
return parentClass + "/" + fieldName.getStringValue() +
":" + fieldType.getTypeDescriptor();
} }
/** {@inheritDoc} */ /** {@inheritDoc} */

View File

@ -28,6 +28,7 @@
package org.jf.dexlib; package org.jf.dexlib;
import org.jf.dexlib.Util.ExceptionWithContext;
import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.Input;
public class IndexedSection<T extends Item> extends Section<T> { 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 * @param index the index of the item to get
* @return the item at the specified index in this section * @return the item at the specified index in this section, or null if the index is -1
* @throws IndexOutOfBoundsException if index is outside the bounds of this section
*/ */
public T getItemByIndex(int index) { public T getOptionalItemByIndex(int index) {
if (index == -1) { if (index == -1) {
return null; return null;
} }
//if index is out of bounds, just let it throw an exception return getItemByIndex(index);
return items.get(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