- refactored/simplified the label code

- changed the handler_ label prefix to catch_ and catchall_
- added support for the new -i/--indexed-labels option, which numbers the labels incrementally for each method by type, rather than using the bytecode offset

git-svn-id: https://smali.googlecode.com/svn/trunk@493 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
JesusFreke@JesusFreke.com 2009-12-01 08:14:21 +00:00
parent 8555ce95d5
commit e2684fa219
16 changed files with 369 additions and 213 deletions

View File

@ -36,18 +36,42 @@ import org.antlr.stringtemplate.StringTemplate;
public class CatchMethodItem extends MethodItem { public class CatchMethodItem extends MethodItem {
private final StringTemplateGroup stg; private final StringTemplateGroup stg;
private final TypeIdItem exceptionType; private final TypeIdItem exceptionType;
private final int startAddress;
private final int endAddress;
private final int handlerAddress;
public CatchMethodItem(int offset, StringTemplateGroup stg, TypeIdItem exceptionType, int startAddress, private final LabelMethodItem tryStartLabel;
int endAddress, int handlerAddress) { private final LabelMethodItem tryEndLabel;
private final LabelMethodItem handlerLabel;
public CatchMethodItem(MethodDefinition.LabelCache labelCache, int offset, StringTemplateGroup stg,
TypeIdItem exceptionType, int startAddress, int endAddress, int handlerAddress) {
super(offset); super(offset);
this.stg = stg; this.stg = stg;
this.exceptionType = exceptionType; this.exceptionType = exceptionType;
this.startAddress = startAddress;
this.endAddress = endAddress; tryStartLabel = labelCache.internLabel(new LabelMethodItem(startAddress, stg, "try_start_"));
this.handlerAddress = handlerAddress; tryStartLabel.setUncommented();
//use the offset from the last covered instruction, but make the label
//name refer to the address of the next instruction
tryEndLabel = labelCache.internLabel(new EndTryLabelMethodItem(offset, stg, endAddress));
tryEndLabel.setUncommented();
if (exceptionType == null) {
handlerLabel = labelCache.internLabel(new LabelMethodItem(handlerAddress, stg, "catchall_"));
} else {
handlerLabel = labelCache.internLabel(new LabelMethodItem(handlerAddress, stg, "catch_"));
}
handlerLabel.setUncommented();
}
public LabelMethodItem getTryStartLabel() {
return tryStartLabel;
}
public LabelMethodItem getTryEndLabel() {
return tryEndLabel;
}
public LabelMethodItem getHandlerLabel() {
return handlerLabel;
} }
public int getSortOrder() { public int getSortOrder() {
@ -65,9 +89,9 @@ public class CatchMethodItem extends MethodItem {
if (exceptionType != null) { if (exceptionType != null) {
template.setAttribute("ExceptionType", TypeReference.makeTemplate(stg, exceptionType)); template.setAttribute("ExceptionType", TypeReference.makeTemplate(stg, exceptionType));
} }
template.setAttribute("StartAddress", Integer.toHexString(startAddress)); template.setAttribute("StartLabel", tryStartLabel);
template.setAttribute("EndAddress", Integer.toHexString(endAddress)); template.setAttribute("EndLabel", tryEndLabel);
template.setAttribute("HandlerAddress", Integer.toHexString(handlerAddress)); template.setAttribute("HandlerLabel", handlerLabel);
return template.toString(); return template.toString();
} }
} }

View File

@ -34,7 +34,7 @@ public class EndTryLabelMethodItem extends LabelMethodItem {
private int labelOffset; private int labelOffset;
public EndTryLabelMethodItem(int offset, StringTemplateGroup stg, int labelOffset) { public EndTryLabelMethodItem(int offset, StringTemplateGroup stg, int labelOffset) {
super(offset, stg, "try_end_", false); super(offset, stg, "try_end_");
this.labelOffset = labelOffset; this.labelOffset = labelOffset;
} }

View File

@ -28,18 +28,18 @@
package org.jf.baksmali.Adaptors.Format; package org.jf.baksmali.Adaptors.Format;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup; import org.antlr.stringtemplate.StringTemplateGroup;
import org.jf.dexlib.Code.Format.Instruction10t; import org.jf.dexlib.Code.Format.Instruction10t;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction10tMethodItem extends InstructionFormatMethodItem<Instruction10t> { public class Instruction10tMethodItem extends OffsetInstructionFormatMethodItem<Instruction10t> {
public Instruction10tMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction10tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
Instruction10t instruction) { StringTemplateGroup stg, Instruction10t instruction) {
super(codeItem, offset, stg, instruction); super(labelCache, codeItem, offset, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected String getLabelPrefix() {
template.setAttribute("Target", Integer.toHexString(getOffset() + instruction.getOffset())); return "goto_";
} }
} }

View File

@ -28,18 +28,18 @@
package org.jf.baksmali.Adaptors.Format; package org.jf.baksmali.Adaptors.Format;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup; import org.antlr.stringtemplate.StringTemplateGroup;
import org.jf.dexlib.Code.Format.Instruction20t; import org.jf.dexlib.Code.Format.Instruction20t;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction20tMethodItem extends InstructionFormatMethodItem<Instruction20t> { public class Instruction20tMethodItem extends OffsetInstructionFormatMethodItem<Instruction20t> {
public Instruction20tMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction20tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
Instruction20t instruction) { StringTemplateGroup stg, Instruction20t instruction) {
super(codeItem, offset, stg, instruction); super(labelCache, codeItem, offset, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected String getLabelPrefix() {
template.setAttribute("Target", Integer.toHexString(getOffset() + instruction.getOffset())); return "goto_";
} }
} }

View File

@ -32,15 +32,20 @@ import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup; import org.antlr.stringtemplate.StringTemplateGroup;
import org.jf.dexlib.Code.Format.Instruction21t; import org.jf.dexlib.Code.Format.Instruction21t;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction21tMethodItem extends InstructionFormatMethodItem<Instruction21t> { public class Instruction21tMethodItem extends OffsetInstructionFormatMethodItem<Instruction21t> {
public Instruction21tMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction21tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
Instruction21t instruction) { StringTemplateGroup stg, Instruction21t instruction) {
super(codeItem, offset, stg, instruction); super(labelCache, codeItem, offset, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {
super.setAttributes(template);
template.setAttribute("Register", formatRegister(instruction.getRegister())); template.setAttribute("Register", formatRegister(instruction.getRegister()));
template.setAttribute("Target", Integer.toHexString(getOffset() + instruction.getOffset())); }
protected String getLabelPrefix() {
return "cond_";
} }
} }

View File

@ -32,16 +32,21 @@ import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup; import org.antlr.stringtemplate.StringTemplateGroup;
import org.jf.dexlib.Code.Format.Instruction22t; import org.jf.dexlib.Code.Format.Instruction22t;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction22tMethodItem extends InstructionFormatMethodItem<Instruction22t> { public class Instruction22tMethodItem extends OffsetInstructionFormatMethodItem<Instruction22t> {
public Instruction22tMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction22tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
Instruction22t instruction) { StringTemplateGroup stg, Instruction22t instruction) {
super(codeItem, offset, stg, instruction); super(labelCache, codeItem, offset, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {
super.setAttributes(template);
template.setAttribute("RegisterA", formatRegister(instruction.getRegisterA())); template.setAttribute("RegisterA", formatRegister(instruction.getRegisterA()));
template.setAttribute("RegisterB", formatRegister(instruction.getRegisterB())); template.setAttribute("RegisterB", formatRegister(instruction.getRegisterB()));
template.setAttribute("Target", Integer.toHexString(getOffset() + instruction.getOffset())); }
protected String getLabelPrefix() {
return "cond_";
} }
} }

View File

@ -28,18 +28,18 @@
package org.jf.baksmali.Adaptors.Format; package org.jf.baksmali.Adaptors.Format;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup; import org.antlr.stringtemplate.StringTemplateGroup;
import org.jf.dexlib.Code.Format.Instruction30t; import org.jf.dexlib.Code.Format.Instruction30t;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction30tMethodItem extends InstructionFormatMethodItem<Instruction30t> { public class Instruction30tMethodItem extends OffsetInstructionFormatMethodItem<Instruction30t> {
public Instruction30tMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction30tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
Instruction30t instruction) { StringTemplateGroup stg, Instruction30t instruction) {
super(codeItem, offset, stg, instruction); super(labelCache, codeItem, offset, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected String getLabelPrefix() {
template.setAttribute("Target", Integer.toHexString(getOffset() + instruction.getOffset())); return "goto_";
} }
} }

View File

@ -31,16 +31,28 @@ package org.jf.baksmali.Adaptors.Format;
import org.antlr.stringtemplate.StringTemplate; import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup; import org.antlr.stringtemplate.StringTemplateGroup;
import org.jf.dexlib.Code.Format.Instruction31t; import org.jf.dexlib.Code.Format.Instruction31t;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction31tMethodItem extends InstructionFormatMethodItem<Instruction31t> { public class Instruction31tMethodItem extends OffsetInstructionFormatMethodItem<Instruction31t> {
public Instruction31tMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public Instruction31tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
Instruction31t instruction) { StringTemplateGroup stg, Instruction31t instruction) {
super(codeItem, offset, stg, instruction); super(labelCache, codeItem, offset, stg, instruction);
} }
protected void setAttributes(StringTemplate template) { protected void setAttributes(StringTemplate template) {
super.setAttributes(template);
template.setAttribute("Register", formatRegister(instruction.getRegister())); template.setAttribute("Register", formatRegister(instruction.getRegister()));
template.setAttribute("Target", Integer.toHexString(getOffset() + instruction.getOffset())); }
protected String getLabelPrefix() {
if (instruction.opcode == Opcode.FILL_ARRAY_DATA) {
return "array_";
}
if (instruction.opcode == Opcode.PACKED_SWITCH) {
return "pswitch_data_";
}
return "sswitch_data_";
} }
} }

View File

@ -0,0 +1,60 @@
/*
* [The "BSD licence"]
* Copyright (c) 2009 Ben Gruver
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.baksmali.Adaptors.Format;
import org.jf.dexlib.CodeItem;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.OffsetInstruction;
import org.jf.baksmali.Adaptors.LabelMethodItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplate;
public abstract class OffsetInstructionFormatMethodItem<T extends Instruction & OffsetInstruction>
extends InstructionFormatMethodItem<T> {
protected LabelMethodItem label;
public OffsetInstructionFormatMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
StringTemplateGroup stg, T instruction) {
super(codeItem, offset, stg, instruction);
label = new LabelMethodItem(offset + instruction.getOffset(), stg, getLabelPrefix());
label = labelCache.internLabel(label);
}
protected abstract String getLabelPrefix();
protected void setAttributes(StringTemplate template) {
template.setAttribute("TargetLabel", label);
}
public LabelMethodItem getLabel() {
return label;
}
}

View File

@ -32,34 +32,37 @@ import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup; import org.antlr.stringtemplate.StringTemplateGroup;
import org.jf.dexlib.Code.Format.PackedSwitchDataPseudoInstruction; import org.jf.dexlib.Code.Format.PackedSwitchDataPseudoInstruction;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.LabelMethodItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
public class PackedSwitchMethodItem extends InstructionFormatMethodItem<PackedSwitchDataPseudoInstruction> { public class PackedSwitchMethodItem extends InstructionFormatMethodItem<PackedSwitchDataPseudoInstruction>
private int baseAddress; implements Iterable<LabelMethodItem> {
private List<LabelMethodItem> labels = new ArrayList<LabelMethodItem>();
public PackedSwitchMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public PackedSwitchMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
PackedSwitchDataPseudoInstruction instruction, int baseAddress) { StringTemplateGroup stg, PackedSwitchDataPseudoInstruction instruction,
int baseAddress) {
super(codeItem, offset, stg, instruction); super(codeItem, offset, stg, instruction);
this.baseAddress = baseAddress;
}
protected void setAttributes(StringTemplate template) {
template.setAttribute("FirstKey", instruction.getFirstKey());
template.setAttribute("Targets", getTargets());
}
private List<String> getTargets() {
List<String> targets = new ArrayList<String>();
Iterator<PackedSwitchDataPseudoInstruction.PackedSwitchTarget> iterator = instruction.getTargets(); Iterator<PackedSwitchDataPseudoInstruction.PackedSwitchTarget> iterator = instruction.getTargets();
while (iterator.hasNext()) { while (iterator.hasNext()) {
PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next(); PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next();
targets.add(Integer.toHexString(target.target + baseAddress)); LabelMethodItem label = new LabelMethodItem(baseAddress + target.target, stg, "pswitch_");
label = labelCache.internLabel(label);
labels.add(label);
}
} }
return targets; protected void setAttributes(StringTemplate template) {
template.setAttribute("FirstKey", instruction.getFirstKey());
template.setAttribute("Targets", labels);
}
public Iterator<LabelMethodItem> iterator() {
return labels.iterator();
} }
} }

View File

@ -32,42 +32,60 @@ import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup; import org.antlr.stringtemplate.StringTemplateGroup;
import org.jf.dexlib.Code.Format.SparseSwitchDataPseudoInstruction; import org.jf.dexlib.Code.Format.SparseSwitchDataPseudoInstruction;
import org.jf.dexlib.CodeItem; import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.LabelMethodItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
public class SparseSwitchMethodItem extends InstructionFormatMethodItem<SparseSwitchDataPseudoInstruction> { public class SparseSwitchMethodItem extends InstructionFormatMethodItem<SparseSwitchDataPseudoInstruction>
private int baseAddress; implements Iterable<LabelMethodItem> {
private List<SparseSwitchTarget> targets = new ArrayList<SparseSwitchTarget>();
public SparseSwitchMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg, public SparseSwitchMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
SparseSwitchDataPseudoInstruction instruction, int baseAddress) { StringTemplateGroup stg, SparseSwitchDataPseudoInstruction instruction,
int baseAddress) {
super(codeItem, offset, stg, instruction); super(codeItem, offset, stg, instruction);
this.baseAddress = baseAddress;
}
protected void setAttributes(StringTemplate template) {
template.setAttribute("Targets", getTargets());
}
private static class SparseSwitchTarget {
public int Value;
public String Target;
}
private List<SparseSwitchTarget> getTargets() {
List<SparseSwitchTarget> targets = new ArrayList<SparseSwitchTarget>();
Iterator<SparseSwitchDataPseudoInstruction.SparseSwitchTarget> iterator = instruction.getTargets(); Iterator<SparseSwitchDataPseudoInstruction.SparseSwitchTarget> iterator = instruction.getTargets();
while (iterator.hasNext()) { while (iterator.hasNext()) {
SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next(); SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next();
SparseSwitchTarget sparseSwitchTarget = new SparseSwitchTarget(); SparseSwitchTarget sparseSwitchTarget = new SparseSwitchTarget();
sparseSwitchTarget.Value = target.value; sparseSwitchTarget.Value = target.value;
sparseSwitchTarget.Target = Integer.toHexString(target.target + baseAddress);
LabelMethodItem label = new LabelMethodItem(baseAddress + target.target, stg, "sswitch_");
label = labelCache.internLabel(label);
sparseSwitchTarget.Target = label;
targets.add(sparseSwitchTarget); targets.add(sparseSwitchTarget);
} }
}
return targets; protected void setAttributes(StringTemplate template) {
template.setAttribute("Targets", targets);
}
public Iterator<LabelMethodItem> iterator() {
return new Iterator<LabelMethodItem>() {
private Iterator<SparseSwitchTarget> iterator = targets.iterator();
public boolean hasNext() {
return iterator.hasNext();
}
public LabelMethodItem next() {
return iterator.next().Target;
}
public void remove() {
iterator.remove();
}
};
}
private static class SparseSwitchTarget {
public int Value;
public LabelMethodItem Target;
} }
} }

View File

@ -30,17 +30,18 @@ package org.jf.baksmali.Adaptors;
import org.antlr.stringtemplate.StringTemplateGroup; import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplate; import org.antlr.stringtemplate.StringTemplate;
import org.jf.baksmali.baksmali;
public class LabelMethodItem extends MethodItem { public class LabelMethodItem extends MethodItem {
private final StringTemplateGroup stg; private final StringTemplateGroup stg;
private final String labelPrefix; private final String labelPrefix;
private boolean isCommentedOut = false; private int labelIndex;
private boolean isCommentedOut = true;
public LabelMethodItem(int offset, StringTemplateGroup stg, String labelPrefix, boolean isCommentedOut) { public LabelMethodItem(int offset, StringTemplateGroup stg, String labelPrefix) {
super(offset); super(offset);
this.stg = stg; this.stg = stg;
this.labelPrefix = labelPrefix; this.labelPrefix = labelPrefix;
this.isCommentedOut = isCommentedOut;
} }
public int getSortOrder() { public int getSortOrder() {
@ -51,8 +52,8 @@ public class LabelMethodItem extends MethodItem {
return isCommentedOut; return isCommentedOut;
} }
public void setCommentedOut(boolean isCommentedOut) { public void setUncommented() {
this.isCommentedOut = isCommentedOut; this.isCommentedOut = false;
} }
public int compareTo(MethodItem methodItem) { public int compareTo(MethodItem methodItem) {
@ -81,13 +82,28 @@ public class LabelMethodItem extends MethodItem {
@Override @Override
public String toString() { public String toString() {
StringTemplate template = stg.getInstanceOf("Label"); StringTemplate template = stg.getInstanceOf("Label");
template.setAttribute("CommentedOut", this.isCommentedOut);
template.setAttribute("Prefix", labelPrefix); template.setAttribute("Prefix", labelPrefix);
template.setAttribute("HexOffset", getLabelOffset()); if (baksmali.useIndexedLabels) {
template.setAttribute("Suffix", Integer.toHexString(labelIndex));
} else {
template.setAttribute("Suffix", getLabelOffset());
}
return template.toString(); return template.toString();
} }
public String getLabelPrefix() {
return labelPrefix;
}
public String getLabelOffset() { public String getLabelOffset() {
return getHexOffset(); return getHexOffset();
} }
public int getLabelIndex() {
return labelIndex;
}
public void setLabelIndex(int labelIndex) {
this.labelIndex = labelIndex;
}
} }

View File

@ -36,6 +36,7 @@ import org.jf.dexlib.Code.Format.*;
import org.jf.dexlib.Code.Instruction; import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.Opcode; import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.InstructionIterator; import org.jf.dexlib.Code.InstructionIterator;
import org.jf.dexlib.Code.OffsetInstruction;
import org.jf.dexlib.Util.AccessFlags; import org.jf.dexlib.Util.AccessFlags;
import org.antlr.stringtemplate.StringTemplateGroup; import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplate; import org.antlr.stringtemplate.StringTemplate;
@ -159,7 +160,14 @@ public class MethodDefinition {
MethodItemList methodItemList = new MethodItemList(dexFile, stg, codeItem); MethodItemList methodItemList = new MethodItemList(dexFile, stg, codeItem);
methodItemList.generateMethodItemList(); methodItemList.generateMethodItemList();
methodItems.addAll(methodItemList.labels.values()); for (LabelMethodItem labelMethodItem: methodItemList.labels.getLabels()) {
if (labelMethodItem.isCommentedOut()) {
methodItems.add(new CommentedOutMethodItem(stg, labelMethodItem));
} else {
methodItems.add(labelMethodItem);
}
}
methodItems.addAll(methodItemList.instructions); methodItems.addAll(methodItemList.instructions);
methodItems.addAll(methodItemList.blanks); methodItems.addAll(methodItemList.blanks);
methodItems.addAll(methodItemList.catches); methodItems.addAll(methodItemList.catches);
@ -175,7 +183,8 @@ public class MethodDefinition {
private final StringTemplateGroup stg; private final StringTemplateGroup stg;
private final CodeItem codeItem; private final CodeItem codeItem;
public HashMap<LabelMethodItem, LabelMethodItem> labels = new HashMap<LabelMethodItem, LabelMethodItem>(); public LabelCache labels = new LabelCache();
public List<MethodItem> instructions = new ArrayList<MethodItem>(); public List<MethodItem> instructions = new ArrayList<MethodItem>();
public List<BlankMethodItem> blanks = new ArrayList<BlankMethodItem>(); public List<BlankMethodItem> blanks = new ArrayList<BlankMethodItem>();
public List<CatchMethodItem> catches = new ArrayList<CatchMethodItem>(); public List<CatchMethodItem> catches = new ArrayList<CatchMethodItem>();
@ -264,7 +273,23 @@ public class MethodDefinition {
addTries(); addTries();
addDebugInfo(); addDebugInfo();
if (baksmali.useIndexedLabels) {
setLabelIndexes();
} }
}
private void addOffsetInstructionMethodItem(OffsetInstructionFormatMethodItem methodItem, boolean commentedOut,
String comment) {
if (commentedOut) {
instructions.add(new CommentedOutMethodItem(stg, methodItem));
} else {
instructions.add(methodItem);
LabelMethodItem label = methodItem.getLabel();
label.setUncommented();
}
}
private void addInstructionMethodItem(InstructionFormatMethodItem methodItem, boolean commentedOut, private void addInstructionMethodItem(InstructionFormatMethodItem methodItem, boolean commentedOut,
String comment) { String comment) {
@ -275,26 +300,13 @@ public class MethodDefinition {
} }
} }
private void addLabelMethodItem(LabelMethodItem labelMethodItem) {
LabelMethodItem internedLabelMethodItem = labels.get(labelMethodItem);
if (internedLabelMethodItem != null) {
if (!labelMethodItem.isCommentedOut() && internedLabelMethodItem.isCommentedOut()) {
internedLabelMethodItem.setCommentedOut(false);
}
} else {
labels.put(labelMethodItem, labelMethodItem);
}
}
private void addMethodItemsForInstruction(int offset, Instruction instruction, boolean commentedOut, private void addMethodItemsForInstruction(int offset, Instruction instruction, boolean commentedOut,
String comment) { String comment) {
switch (instruction.getFormat()) { switch (instruction.getFormat()) {
case Format10t: case Format10t:
addInstructionMethodItem( addOffsetInstructionMethodItem(
new Instruction10tMethodItem(codeItem, offset, stg,(Instruction10t)instruction), new Instruction10tMethodItem(labels, codeItem, offset, stg,(Instruction10t)instruction),
commentedOut, comment); commentedOut, comment);
addLabelMethodItem(new LabelMethodItem(offset + ((Instruction10t)instruction).getOffset(), stg,
"goto_", commentedOut));
return; return;
case Format10x: case Format10x:
addInstructionMethodItem( addInstructionMethodItem(
@ -317,11 +329,9 @@ public class MethodDefinition {
commentedOut, comment); commentedOut, comment);
return; return;
case Format20t: case Format20t:
addInstructionMethodItem( addOffsetInstructionMethodItem(
new Instruction20tMethodItem(codeItem, offset, stg, (Instruction20t)instruction), new Instruction20tMethodItem(labels, codeItem, offset, stg, (Instruction20t)instruction),
commentedOut, comment); commentedOut, comment);
addLabelMethodItem(new LabelMethodItem(offset + ((Instruction20t)instruction).getOffset(), stg,
"goto_", commentedOut));
return; return;
case Format21c: case Format21c:
addInstructionMethodItem( addInstructionMethodItem(
@ -339,11 +349,9 @@ public class MethodDefinition {
commentedOut, comment); commentedOut, comment);
return; return;
case Format21t: case Format21t:
addInstructionMethodItem( addOffsetInstructionMethodItem(
new Instruction21tMethodItem(codeItem, offset, stg, (Instruction21t)instruction), new Instruction21tMethodItem(labels, codeItem, offset, stg, (Instruction21t)instruction),
commentedOut, comment); commentedOut, comment);
addLabelMethodItem(new LabelMethodItem(offset + ((Instruction21t)instruction).getOffset(), stg,
"cond_", commentedOut));
return; return;
case Format22b: case Format22b:
addInstructionMethodItem( addInstructionMethodItem(
@ -371,11 +379,9 @@ public class MethodDefinition {
commentedOut, comment); commentedOut, comment);
return; return;
case Format22t: case Format22t:
addInstructionMethodItem( addOffsetInstructionMethodItem(
new Instruction22tMethodItem(codeItem, offset, stg, (Instruction22t)instruction), new Instruction22tMethodItem(labels, codeItem, offset, stg, (Instruction22t)instruction),
commentedOut, comment); commentedOut, comment);
addLabelMethodItem(new LabelMethodItem(offset + ((Instruction22t)instruction).getOffset(), stg,
"cond_", commentedOut));
return; return;
case Format22x: case Format22x:
addInstructionMethodItem( addInstructionMethodItem(
@ -388,11 +394,9 @@ public class MethodDefinition {
commentedOut, comment); commentedOut, comment);
return; return;
case Format30t: case Format30t:
addInstructionMethodItem( addOffsetInstructionMethodItem(
new Instruction30tMethodItem(codeItem, offset, stg, (Instruction30t)instruction), new Instruction30tMethodItem(labels, codeItem, offset, stg, (Instruction30t)instruction),
commentedOut, comment); commentedOut, comment);
addLabelMethodItem(new LabelMethodItem(offset + ((Instruction30t)instruction).getOffset(), stg,
"goto_", commentedOut));
return; return;
case Format31c: case Format31c:
addInstructionMethodItem( addInstructionMethodItem(
@ -405,19 +409,9 @@ public class MethodDefinition {
commentedOut, comment); commentedOut, comment);
return; return;
case Format31t: case Format31t:
addInstructionMethodItem( addOffsetInstructionMethodItem(
new Instruction31tMethodItem(codeItem, offset, stg, (Instruction31t)instruction), new Instruction31tMethodItem(labels, codeItem, offset, stg, (Instruction31t)instruction),
commentedOut, comment); commentedOut, comment);
if (instruction.opcode == Opcode.FILL_ARRAY_DATA) {
addLabelMethodItem(new LabelMethodItem(offset + ((Instruction31t)instruction).getOffset(), stg,
"array_", commentedOut));
} else if (instruction.opcode == Opcode.PACKED_SWITCH) {
addLabelMethodItem(new LabelMethodItem(offset + ((Instruction31t)instruction).getOffset(), stg,
"pswitch_data_", commentedOut));
} else if (instruction.opcode == Opcode.SPARSE_SWITCH) {
addLabelMethodItem(new LabelMethodItem(offset + ((Instruction31t)instruction).getOffset(), stg,
"sswitch_data_", commentedOut));
}
return; return;
case Format32x: case Format32x:
addInstructionMethodItem( addInstructionMethodItem(
@ -482,16 +476,14 @@ public class MethodDefinition {
PackedSwitchDataPseudoInstruction packedSwitchInstruction = PackedSwitchDataPseudoInstruction packedSwitchInstruction =
(PackedSwitchDataPseudoInstruction)instruction; (PackedSwitchDataPseudoInstruction)instruction;
addInstructionMethodItem( PackedSwitchMethodItem packedSwitch = new PackedSwitchMethodItem(labels, codeItem, offset, stg,
new PackedSwitchMethodItem(codeItem, offset, stg, packedSwitchInstruction, baseAddress), packedSwitchInstruction, baseAddress);
commentedOut, comment); addInstructionMethodItem(packedSwitch, commentedOut, comment);
Iterator<PackedSwitchDataPseudoInstruction.PackedSwitchTarget> iterator = if (!commentedOut) {
packedSwitchInstruction.getTargets(); for (LabelMethodItem label: packedSwitch) {
while (iterator.hasNext()) { label.setUncommented();
PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next(); }
addLabelMethodItem(new LabelMethodItem(baseAddress + target.target, stg, "pswitch_",
commentedOut));
} }
} }
return; return;
@ -504,16 +496,14 @@ public class MethodDefinition {
SparseSwitchDataPseudoInstruction sparseSwitchInstruction = SparseSwitchDataPseudoInstruction sparseSwitchInstruction =
(SparseSwitchDataPseudoInstruction)instruction; (SparseSwitchDataPseudoInstruction)instruction;
addInstructionMethodItem( SparseSwitchMethodItem sparseSwitch = new SparseSwitchMethodItem(labels, codeItem, offset, stg,
new SparseSwitchMethodItem(codeItem, offset, stg, sparseSwitchInstruction, baseAddress), sparseSwitchInstruction, baseAddress);
commentedOut, comment); addInstructionMethodItem(sparseSwitch, commentedOut, comment);
Iterator<SparseSwitchDataPseudoInstruction.SparseSwitchTarget> iterator = if (!commentedOut) {
sparseSwitchInstruction.getTargets(); for (LabelMethodItem label: sparseSwitch) {
while (iterator.hasNext()) { label.setUncommented();
SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next(); }
addLabelMethodItem(new LabelMethodItem(baseAddress + target.target, stg, "sswitch_",
commentedOut));
} }
} }
return; return;
@ -575,35 +565,17 @@ public class MethodDefinition {
//add the catch all handler if it exists //add the catch all handler if it exists
int catchAllAddress = tryItem.encodedCatchHandler.catchAllHandlerAddress; int catchAllAddress = tryItem.encodedCatchHandler.catchAllHandlerAddress;
if (catchAllAddress != -1) { if (catchAllAddress != -1) {
CatchMethodItem catchMethodItem = new CatchMethodItem(lastInstructionOffset, stg, null, CatchMethodItem catchMethodItem = new CatchMethodItem(labels, lastInstructionOffset, stg, null,
startAddress, endAddress, catchAllAddress) { startAddress, endAddress, catchAllAddress);
public String getTemplateName() {
return "CatchAll";
}
};
catches.add(catchMethodItem); catches.add(catchMethodItem);
addLabelMethodItem(new LabelMethodItem(startAddress, stg, "try_start_", false));
//use the offset from the last covered instruction, but make the label
//name refer to the address of the next instruction
addLabelMethodItem(new EndTryLabelMethodItem(lastInstructionOffset, stg, endAddress));
addLabelMethodItem(new LabelMethodItem(catchAllAddress, stg, "handler_", false));
} }
//add the rest of the handlers //add the rest of the handlers
//TODO: find adjacent handlers for the same type and combine them
for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) { for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) {
//use the offset from the last covered instruction //use the offset from the last covered instruction
CatchMethodItem catchMethodItem = new CatchMethodItem(lastInstructionOffset, stg, CatchMethodItem catchMethodItem = new CatchMethodItem(labels, lastInstructionOffset, stg,
handler.exceptionType, startAddress, endAddress, handler.handlerAddress); handler.exceptionType, startAddress, endAddress, handler.handlerAddress);
catches.add(catchMethodItem); catches.add(catchMethodItem);
addLabelMethodItem(new LabelMethodItem(startAddress, stg, "try_start_", false));
//use the offset from the last covered instruction, but make the label
//name refer to the address of the next instruction
addLabelMethodItem(new EndTryLabelMethodItem(lastInstructionOffset, stg, endAddress));
addLabelMethodItem(new LabelMethodItem(handler.handlerAddress, stg, "handler_", false));
} }
} }
} }
@ -676,5 +648,46 @@ public class MethodDefinition {
} }
}); });
} }
private void setLabelIndexes() {
HashMap<String, Integer> nextLabelIndexByType = new HashMap<String, Integer>();
ArrayList<LabelMethodItem> sortedLabels = new ArrayList<LabelMethodItem>(labels.getLabels());
//sort the labels by their location in the method
Collections.sort(sortedLabels);
for (LabelMethodItem labelMethodItem: sortedLabels) {
Integer labelIndex = nextLabelIndexByType.get(labelMethodItem.getLabelPrefix());
if (labelIndex == null) {
labelIndex = 0;
}
labelMethodItem.setLabelIndex(labelIndex);
nextLabelIndexByType.put(labelMethodItem.getLabelPrefix(), labelIndex + 1);
}
}
}
public static class LabelCache {
protected HashMap<LabelMethodItem, LabelMethodItem> labels = new HashMap<LabelMethodItem, LabelMethodItem>();
public LabelCache() {
}
public LabelMethodItem internLabel(LabelMethodItem labelMethodItem) {
LabelMethodItem internedLabelMethodItem = labels.get(labelMethodItem);
if (internedLabelMethodItem != null) {
if (!labelMethodItem.isCommentedOut()) {
internedLabelMethodItem.setUncommented();
}
return internedLabelMethodItem;
}
labels.put(labelMethodItem, labelMethodItem);
return labelMethodItem;
}
public Collection<LabelMethodItem> getLabels() {
return labels.values();
}
} }
} }

View File

@ -43,13 +43,17 @@ import java.io.*;
public class baksmali { public class baksmali {
public static boolean noParameterRegisters = false; public static boolean noParameterRegisters = false;
public static boolean useLocalsDirective = false; public static boolean useLocalsDirective = false;
public static boolean useIndexedLabels = false;
public static DeodexUtil deodexUtil = null; public static DeodexUtil deodexUtil = null;
public static void disassembleDexFile(DexFile dexFile, Deodexerant deodexerant, String outputDirectory, public static void disassembleDexFile(DexFile dexFile, Deodexerant deodexerant, String outputDirectory,
boolean noParameterRegisters, boolean useLocalsDirective) boolean noParameterRegisters, boolean useLocalsDirective,
boolean useIndexedLabels)
{ {
baksmali.noParameterRegisters = noParameterRegisters; baksmali.noParameterRegisters = noParameterRegisters;
baksmali.useLocalsDirective = useLocalsDirective; baksmali.useLocalsDirective = useLocalsDirective;
baksmali.useIndexedLabels = useIndexedLabels;
if (deodexerant != null) { if (deodexerant != null) {
baksmali.deodexUtil = new DeodexUtil(deodexerant); baksmali.deodexUtil = new DeodexUtil(deodexerant);
} }

View File

@ -73,6 +73,7 @@ public class main {
boolean fixRegisters = false; boolean fixRegisters = false;
boolean noParameterRegisters = false; boolean noParameterRegisters = false;
boolean useLocalsDirective = false; boolean useLocalsDirective = false;
boolean useIndexedLabels = false;
String outputDirectory = "out"; String outputDirectory = "out";
@ -135,6 +136,10 @@ public class main {
useLocalsDirective = true; useLocalsDirective = true;
} }
if (commandLine.hasOption("i")) {
useIndexedLabels = true;
}
if (commandLine.hasOption("x")) { if (commandLine.hasOption("x")) {
String deodexerantAddress = commandLine.getOptionValue("x"); String deodexerantAddress = commandLine.getOptionValue("x");
String[] parts = deodexerantAddress.split(":"); String[] parts = deodexerantAddress.split(":");
@ -186,7 +191,7 @@ public class main {
if (disassemble) { if (disassemble) {
baksmali.disassembleDexFile(dexFile, deodexerant, outputDirectory, noParameterRegisters, baksmali.disassembleDexFile(dexFile, deodexerant, outputDirectory, noParameterRegisters,
useLocalsDirective); useLocalsDirective, useIndexedLabels);
} }
if ((doDump || write) && !dexFile.isOdex()) { if ((doDump || write) && !dexFile.isOdex()) {
@ -282,10 +287,15 @@ public class main {
.create("x"); .create("x");
Option useLocalsOption = OptionBuilder.withLongOpt("use-locals") Option useLocalsOption = OptionBuilder.withLongOpt("use-locals")
.withDescription("output the .locals directive with the number of non-parameter registers, instead of" + .withDescription("output the .locals directive with the number of non-parameter registers, rather" +
" the .register directive with the total number of register") " than the .register directive with the total number of register")
.create("l"); .create("l");
Option indexedLabelsOption = OptionBuilder.withLongOpt("indexed-labels")
.withDescription("create label names using a per-method/per-label-type auto-index as the suffix, " +
" rather than the bytecode offset")
.create("i");
OptionGroup dumpCommand = new OptionGroup(); OptionGroup dumpCommand = new OptionGroup();
options.addOption(versionOption); options.addOption(versionOption);
@ -299,5 +309,6 @@ public class main {
options.addOption(noParameterRegistersOption); options.addOption(noParameterRegistersOption);
options.addOption(deodexerantOption); options.addOption(deodexerantOption);
options.addOption(useLocalsOption); options.addOption(useLocalsOption);
options.addOption(indexedLabelsOption);
} }
} }

View File

@ -123,18 +123,9 @@ Parameter(ParameterName, Annotations) ::=
<endif> <endif>
>> >>
Format10t(Opcode, TargetLabel) ::=
Format31tLabelMap ::= [
"fill-array-data":"array_",
"packed-switch":"pswitch_data_",
"sparse-switch":"sswitch_data_"
]
Format10t(Opcode, Target) ::=
<< <<
<Opcode> :goto_<Target> <Opcode> <TargetLabel>
>> >>
Format10x(Opcode) ::= Format10x(Opcode) ::=
@ -157,9 +148,9 @@ Format12x(Opcode, RegisterA, RegisterB) ::=
<Opcode> <RegisterA>, <RegisterB> <Opcode> <RegisterA>, <RegisterB>
>> >>
Format20t(Opcode, Target) ::= Format20t(Opcode, TargetLabel) ::=
<< <<
<Opcode> :goto_<Target> <Opcode> <TargetLabel>
>> >>
Format21c(Opcode, Register, Reference) ::= Format21c(Opcode, Register, Reference) ::=
@ -177,9 +168,9 @@ Format21s(Opcode, Register, Literal) ::=
<Opcode> <Register>, <Literal> <Opcode> <Register>, <Literal>
>> >>
Format21t(Opcode, Register, Target) ::= Format21t(Opcode, Register, TargetLabel) ::=
<< <<
<Opcode> <Register>, :cond_<Target> <Opcode> <Register>, <TargetLabel>
>> >>
Format22b(Opcode, RegisterA, RegisterB, Literal) ::= Format22b(Opcode, RegisterA, RegisterB, Literal) ::=
@ -207,9 +198,9 @@ Format22s(Opcode, RegisterA, RegisterB, Literal) ::=
<Opcode> <RegisterA>, <RegisterB>, <Literal> <Opcode> <RegisterA>, <RegisterB>, <Literal>
>> >>
Format22t(Opcode, RegisterA, RegisterB, Target) ::= Format22t(Opcode, RegisterA, RegisterB, TargetLabel) ::=
<< <<
<Opcode> <RegisterA>, <RegisterB>, :cond_<Target> <Opcode> <RegisterA>, <RegisterB>, <TargetLabel>
>> >>
Format22x(Opcode, RegisterA, RegisterB) ::= Format22x(Opcode, RegisterA, RegisterB) ::=
@ -222,9 +213,9 @@ Format23x(Opcode, RegisterA, RegisterB, RegisterC) ::=
<Opcode> <RegisterA>, <RegisterB>, <RegisterC> <Opcode> <RegisterA>, <RegisterB>, <RegisterC>
>> >>
Format30t(Opcode, Target) ::= Format30t(Opcode, TargetLabel) ::=
<< <<
<Opcode> :goto_<Target> <Opcode> <TargetLabel>
>> >>
Format31c(Opcode, Register, Reference) ::= Format31c(Opcode, Register, Reference) ::=
@ -237,9 +228,9 @@ Format31i(Opcode, Register, Literal) ::=
<Opcode> <Register>, <Literal> <Opcode> <Register>, <Literal>
>> >>
Format31t(Opcode, Register, Target) ::= Format31t(Opcode, Register, TargetLabel) ::=
<< <<
<Opcode> <Register>, :<Format31tLabelMap.(Opcode)><Target> <Opcode> <Register>, <TargetLabel>
>> >>
Format32x(Opcode, RegisterA, RegisterB) ::= Format32x(Opcode, RegisterA, RegisterB) ::=
@ -322,21 +313,21 @@ ArrayElement(Bytes) ::=
PackedSwitchData(Opcode, FirstKey, Targets) ::= PackedSwitchData(Opcode, FirstKey, Targets) ::=
<< <<
.packed-switch <FirstKey> .packed-switch <FirstKey>
<Targets: {:pswitch_<it>}; separator="\n"> <Targets: {<it>}; separator="\n">
.end packed-switch .end packed-switch
>> >>
SparseSwitchData(Opcode, Targets) ::= SparseSwitchData(Opcode, Targets) ::=
<< <<
.sparse-switch .sparse-switch
<Targets:{<it.Value> -> :sswitch_<it.Target>}; separator="\n"> <Targets:{<it.Value> -> <it.Target>}; separator="\n">
.end sparse-switch .end sparse-switch
>> >>
Label(Prefix, HexOffset, CommentedOut) ::= Label(Prefix, Suffix) ::=
<< <<
<if(CommentedOut)>#<endif>:<Prefix><HexOffset> :<Prefix><Suffix>
>> >>
Line(Line) ::= Line(Line) ::=
@ -379,17 +370,11 @@ Blank(Blank) ::=
>> >>
Catch(ExceptionType, StartAddress, EndAddress, HandlerAddress) ::= Catch(ExceptionType, StartLabel, EndLabel, HandlerLabel) ::=
<< <<
.catch <ExceptionType> {:try_start_<StartAddress> .. :try_end_<EndAddress>} :handler_<HandlerAddress> <if(ExceptionType)>.catch <ExceptionType><else>.catchall<endif> {<StartLabel> .. <EndLabel>} <HandlerLabel>
>> >>
CatchAll(StartAddress, EndAddress, HandlerAddress) ::=
<<
.catchall {:try_start_<StartAddress> .. :try_end_<EndAddress>} :handler_<HandlerAddress>
>>
StringReference(EscapedValue) ::= StringReference(EscapedValue) ::=
<< <<