- 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 {
private final StringTemplateGroup stg;
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,
int endAddress, int handlerAddress) {
private final LabelMethodItem tryStartLabel;
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);
this.stg = stg;
this.exceptionType = exceptionType;
this.startAddress = startAddress;
this.endAddress = endAddress;
this.handlerAddress = handlerAddress;
tryStartLabel = labelCache.internLabel(new LabelMethodItem(startAddress, stg, "try_start_"));
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() {
@ -65,9 +89,9 @@ public class CatchMethodItem extends MethodItem {
if (exceptionType != null) {
template.setAttribute("ExceptionType", TypeReference.makeTemplate(stg, exceptionType));
}
template.setAttribute("StartAddress", Integer.toHexString(startAddress));
template.setAttribute("EndAddress", Integer.toHexString(endAddress));
template.setAttribute("HandlerAddress", Integer.toHexString(handlerAddress));
template.setAttribute("StartLabel", tryStartLabel);
template.setAttribute("EndLabel", tryEndLabel);
template.setAttribute("HandlerLabel", handlerLabel);
return template.toString();
}
}

View File

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

View File

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

View File

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

View File

@ -32,15 +32,20 @@ import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.jf.dexlib.Code.Format.Instruction21t;
import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction21tMethodItem extends InstructionFormatMethodItem<Instruction21t> {
public Instruction21tMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
Instruction21t instruction) {
super(codeItem, offset, stg, instruction);
public class Instruction21tMethodItem extends OffsetInstructionFormatMethodItem<Instruction21t> {
public Instruction21tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
StringTemplateGroup stg, Instruction21t instruction) {
super(labelCache, codeItem, offset, stg, instruction);
}
protected void setAttributes(StringTemplate template) {
super.setAttributes(template);
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.jf.dexlib.Code.Format.Instruction22t;
import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction22tMethodItem extends InstructionFormatMethodItem<Instruction22t> {
public Instruction22tMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
Instruction22t instruction) {
super(codeItem, offset, stg, instruction);
public class Instruction22tMethodItem extends OffsetInstructionFormatMethodItem<Instruction22t> {
public Instruction22tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
StringTemplateGroup stg, Instruction22t instruction) {
super(labelCache, codeItem, offset, stg, instruction);
}
protected void setAttributes(StringTemplate template) {
super.setAttributes(template);
template.setAttribute("RegisterA", formatRegister(instruction.getRegisterA()));
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;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.jf.dexlib.Code.Format.Instruction30t;
import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction30tMethodItem extends InstructionFormatMethodItem<Instruction30t> {
public Instruction30tMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
Instruction30t instruction) {
super(codeItem, offset, stg, instruction);
public class Instruction30tMethodItem extends OffsetInstructionFormatMethodItem<Instruction30t> {
public Instruction30tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
StringTemplateGroup stg, Instruction30t instruction) {
super(labelCache, codeItem, offset, stg, instruction);
}
protected void setAttributes(StringTemplate template) {
template.setAttribute("Target", Integer.toHexString(getOffset() + instruction.getOffset()));
protected String getLabelPrefix() {
return "goto_";
}
}

View File

@ -31,16 +31,28 @@ package org.jf.baksmali.Adaptors.Format;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.jf.dexlib.Code.Format.Instruction31t;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
public class Instruction31tMethodItem extends InstructionFormatMethodItem<Instruction31t> {
public Instruction31tMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
Instruction31t instruction) {
super(codeItem, offset, stg, instruction);
public class Instruction31tMethodItem extends OffsetInstructionFormatMethodItem<Instruction31t> {
public Instruction31tMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
StringTemplateGroup stg, Instruction31t instruction) {
super(labelCache, codeItem, offset, stg, instruction);
}
protected void setAttributes(StringTemplate template) {
super.setAttributes(template);
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.jf.dexlib.Code.Format.PackedSwitchDataPseudoInstruction;
import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.LabelMethodItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class PackedSwitchMethodItem extends InstructionFormatMethodItem<PackedSwitchDataPseudoInstruction> {
private int baseAddress;
public class PackedSwitchMethodItem extends InstructionFormatMethodItem<PackedSwitchDataPseudoInstruction>
implements Iterable<LabelMethodItem> {
private List<LabelMethodItem> labels = new ArrayList<LabelMethodItem>();
public PackedSwitchMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
PackedSwitchDataPseudoInstruction instruction, int baseAddress) {
public PackedSwitchMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
StringTemplateGroup stg, PackedSwitchDataPseudoInstruction instruction,
int baseAddress) {
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();
while (iterator.hasNext()) {
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.jf.dexlib.Code.Format.SparseSwitchDataPseudoInstruction;
import org.jf.dexlib.CodeItem;
import org.jf.baksmali.Adaptors.LabelMethodItem;
import org.jf.baksmali.Adaptors.MethodDefinition;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class SparseSwitchMethodItem extends InstructionFormatMethodItem<SparseSwitchDataPseudoInstruction> {
private int baseAddress;
public class SparseSwitchMethodItem extends InstructionFormatMethodItem<SparseSwitchDataPseudoInstruction>
implements Iterable<LabelMethodItem> {
private List<SparseSwitchTarget> targets = new ArrayList<SparseSwitchTarget>();
public SparseSwitchMethodItem(CodeItem codeItem, int offset, StringTemplateGroup stg,
SparseSwitchDataPseudoInstruction instruction, int baseAddress) {
public SparseSwitchMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int offset,
StringTemplateGroup stg, SparseSwitchDataPseudoInstruction instruction,
int baseAddress) {
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();
while (iterator.hasNext()) {
SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next();
SparseSwitchTarget sparseSwitchTarget = new SparseSwitchTarget();
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);
}
}
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.StringTemplate;
import org.jf.baksmali.baksmali;
public class LabelMethodItem extends MethodItem {
private final StringTemplateGroup stg;
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);
this.stg = stg;
this.labelPrefix = labelPrefix;
this.isCommentedOut = isCommentedOut;
}
public int getSortOrder() {
@ -51,8 +52,8 @@ public class LabelMethodItem extends MethodItem {
return isCommentedOut;
}
public void setCommentedOut(boolean isCommentedOut) {
this.isCommentedOut = isCommentedOut;
public void setUncommented() {
this.isCommentedOut = false;
}
public int compareTo(MethodItem methodItem) {
@ -81,13 +82,28 @@ public class LabelMethodItem extends MethodItem {
@Override
public String toString() {
StringTemplate template = stg.getInstanceOf("Label");
template.setAttribute("CommentedOut", this.isCommentedOut);
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();
}
public String getLabelPrefix() {
return labelPrefix;
}
public String getLabelOffset() {
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.Opcode;
import org.jf.dexlib.Code.InstructionIterator;
import org.jf.dexlib.Code.OffsetInstruction;
import org.jf.dexlib.Util.AccessFlags;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplate;
@ -159,7 +160,14 @@ public class MethodDefinition {
MethodItemList methodItemList = new MethodItemList(dexFile, stg, codeItem);
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.blanks);
methodItems.addAll(methodItemList.catches);
@ -175,7 +183,8 @@ public class MethodDefinition {
private final StringTemplateGroup stg;
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<BlankMethodItem> blanks = new ArrayList<BlankMethodItem>();
public List<CatchMethodItem> catches = new ArrayList<CatchMethodItem>();
@ -264,7 +273,23 @@ public class MethodDefinition {
addTries();
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,
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,
String comment) {
switch (instruction.getFormat()) {
case Format10t:
addInstructionMethodItem(
new Instruction10tMethodItem(codeItem, offset, stg,(Instruction10t)instruction),
addOffsetInstructionMethodItem(
new Instruction10tMethodItem(labels, codeItem, offset, stg,(Instruction10t)instruction),
commentedOut, comment);
addLabelMethodItem(new LabelMethodItem(offset + ((Instruction10t)instruction).getOffset(), stg,
"goto_", commentedOut));
return;
case Format10x:
addInstructionMethodItem(
@ -317,11 +329,9 @@ public class MethodDefinition {
commentedOut, comment);
return;
case Format20t:
addInstructionMethodItem(
new Instruction20tMethodItem(codeItem, offset, stg, (Instruction20t)instruction),
addOffsetInstructionMethodItem(
new Instruction20tMethodItem(labels, codeItem, offset, stg, (Instruction20t)instruction),
commentedOut, comment);
addLabelMethodItem(new LabelMethodItem(offset + ((Instruction20t)instruction).getOffset(), stg,
"goto_", commentedOut));
return;
case Format21c:
addInstructionMethodItem(
@ -339,11 +349,9 @@ public class MethodDefinition {
commentedOut, comment);
return;
case Format21t:
addInstructionMethodItem(
new Instruction21tMethodItem(codeItem, offset, stg, (Instruction21t)instruction),
addOffsetInstructionMethodItem(
new Instruction21tMethodItem(labels, codeItem, offset, stg, (Instruction21t)instruction),
commentedOut, comment);
addLabelMethodItem(new LabelMethodItem(offset + ((Instruction21t)instruction).getOffset(), stg,
"cond_", commentedOut));
return;
case Format22b:
addInstructionMethodItem(
@ -371,11 +379,9 @@ public class MethodDefinition {
commentedOut, comment);
return;
case Format22t:
addInstructionMethodItem(
new Instruction22tMethodItem(codeItem, offset, stg, (Instruction22t)instruction),
addOffsetInstructionMethodItem(
new Instruction22tMethodItem(labels, codeItem, offset, stg, (Instruction22t)instruction),
commentedOut, comment);
addLabelMethodItem(new LabelMethodItem(offset + ((Instruction22t)instruction).getOffset(), stg,
"cond_", commentedOut));
return;
case Format22x:
addInstructionMethodItem(
@ -388,11 +394,9 @@ public class MethodDefinition {
commentedOut, comment);
return;
case Format30t:
addInstructionMethodItem(
new Instruction30tMethodItem(codeItem, offset, stg, (Instruction30t)instruction),
addOffsetInstructionMethodItem(
new Instruction30tMethodItem(labels, codeItem, offset, stg, (Instruction30t)instruction),
commentedOut, comment);
addLabelMethodItem(new LabelMethodItem(offset + ((Instruction30t)instruction).getOffset(), stg,
"goto_", commentedOut));
return;
case Format31c:
addInstructionMethodItem(
@ -405,19 +409,9 @@ public class MethodDefinition {
commentedOut, comment);
return;
case Format31t:
addInstructionMethodItem(
new Instruction31tMethodItem(codeItem, offset, stg, (Instruction31t)instruction),
addOffsetInstructionMethodItem(
new Instruction31tMethodItem(labels, codeItem, offset, stg, (Instruction31t)instruction),
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;
case Format32x:
addInstructionMethodItem(
@ -482,16 +476,14 @@ public class MethodDefinition {
PackedSwitchDataPseudoInstruction packedSwitchInstruction =
(PackedSwitchDataPseudoInstruction)instruction;
addInstructionMethodItem(
new PackedSwitchMethodItem(codeItem, offset, stg, packedSwitchInstruction, baseAddress),
commentedOut, comment);
PackedSwitchMethodItem packedSwitch = new PackedSwitchMethodItem(labels, codeItem, offset, stg,
packedSwitchInstruction, baseAddress);
addInstructionMethodItem(packedSwitch, commentedOut, comment);
Iterator<PackedSwitchDataPseudoInstruction.PackedSwitchTarget> iterator =
packedSwitchInstruction.getTargets();
while (iterator.hasNext()) {
PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next();
addLabelMethodItem(new LabelMethodItem(baseAddress + target.target, stg, "pswitch_",
commentedOut));
if (!commentedOut) {
for (LabelMethodItem label: packedSwitch) {
label.setUncommented();
}
}
}
return;
@ -504,16 +496,14 @@ public class MethodDefinition {
SparseSwitchDataPseudoInstruction sparseSwitchInstruction =
(SparseSwitchDataPseudoInstruction)instruction;
addInstructionMethodItem(
new SparseSwitchMethodItem(codeItem, offset, stg, sparseSwitchInstruction, baseAddress),
commentedOut, comment);
SparseSwitchMethodItem sparseSwitch = new SparseSwitchMethodItem(labels, codeItem, offset, stg,
sparseSwitchInstruction, baseAddress);
addInstructionMethodItem(sparseSwitch, commentedOut, comment);
Iterator<SparseSwitchDataPseudoInstruction.SparseSwitchTarget> iterator =
sparseSwitchInstruction.getTargets();
while (iterator.hasNext()) {
SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next();
addLabelMethodItem(new LabelMethodItem(baseAddress + target.target, stg, "sswitch_",
commentedOut));
if (!commentedOut) {
for (LabelMethodItem label: sparseSwitch) {
label.setUncommented();
}
}
}
return;
@ -575,35 +565,17 @@ public class MethodDefinition {
//add the catch all handler if it exists
int catchAllAddress = tryItem.encodedCatchHandler.catchAllHandlerAddress;
if (catchAllAddress != -1) {
CatchMethodItem catchMethodItem = new CatchMethodItem(lastInstructionOffset, stg, null,
startAddress, endAddress, catchAllAddress) {
public String getTemplateName() {
return "CatchAll";
}
};
CatchMethodItem catchMethodItem = new CatchMethodItem(labels, lastInstructionOffset, stg, null,
startAddress, endAddress, catchAllAddress);
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
//TODO: find adjacent handlers for the same type and combine them
for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) {
//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);
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 static boolean noParameterRegisters = false;
public static boolean useLocalsDirective = false;
public static boolean useIndexedLabels = false;
public static DeodexUtil deodexUtil = null;
public static void disassembleDexFile(DexFile dexFile, Deodexerant deodexerant, String outputDirectory,
boolean noParameterRegisters, boolean useLocalsDirective)
boolean noParameterRegisters, boolean useLocalsDirective,
boolean useIndexedLabels)
{
baksmali.noParameterRegisters = noParameterRegisters;
baksmali.useLocalsDirective = useLocalsDirective;
baksmali.useIndexedLabels = useIndexedLabels;
if (deodexerant != null) {
baksmali.deodexUtil = new DeodexUtil(deodexerant);
}

View File

@ -73,6 +73,7 @@ public class main {
boolean fixRegisters = false;
boolean noParameterRegisters = false;
boolean useLocalsDirective = false;
boolean useIndexedLabels = false;
String outputDirectory = "out";
@ -135,6 +136,10 @@ public class main {
useLocalsDirective = true;
}
if (commandLine.hasOption("i")) {
useIndexedLabels = true;
}
if (commandLine.hasOption("x")) {
String deodexerantAddress = commandLine.getOptionValue("x");
String[] parts = deodexerantAddress.split(":");
@ -186,7 +191,7 @@ public class main {
if (disassemble) {
baksmali.disassembleDexFile(dexFile, deodexerant, outputDirectory, noParameterRegisters,
useLocalsDirective);
useLocalsDirective, useIndexedLabels);
}
if ((doDump || write) && !dexFile.isOdex()) {
@ -282,10 +287,15 @@ public class main {
.create("x");
Option useLocalsOption = OptionBuilder.withLongOpt("use-locals")
.withDescription("output the .locals directive with the number of non-parameter registers, instead of" +
" the .register directive with the total number of register")
.withDescription("output the .locals directive with the number of non-parameter registers, rather" +
" than the .register directive with the total number of register")
.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();
options.addOption(versionOption);
@ -299,5 +309,6 @@ public class main {
options.addOption(noParameterRegistersOption);
options.addOption(deodexerantOption);
options.addOption(useLocalsOption);
options.addOption(indexedLabelsOption);
}
}

View File

@ -123,18 +123,9 @@ Parameter(ParameterName, Annotations) ::=
<endif>
>>
Format31tLabelMap ::= [
"fill-array-data":"array_",
"packed-switch":"pswitch_data_",
"sparse-switch":"sswitch_data_"
]
Format10t(Opcode, Target) ::=
Format10t(Opcode, TargetLabel) ::=
<<
<Opcode> :goto_<Target>
<Opcode> <TargetLabel>
>>
Format10x(Opcode) ::=
@ -157,9 +148,9 @@ Format12x(Opcode, RegisterA, RegisterB) ::=
<Opcode> <RegisterA>, <RegisterB>
>>
Format20t(Opcode, Target) ::=
Format20t(Opcode, TargetLabel) ::=
<<
<Opcode> :goto_<Target>
<Opcode> <TargetLabel>
>>
Format21c(Opcode, Register, Reference) ::=
@ -177,9 +168,9 @@ Format21s(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) ::=
@ -207,9 +198,9 @@ Format22s(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) ::=
@ -222,9 +213,9 @@ Format23x(Opcode, RegisterA, RegisterB, RegisterC) ::=
<Opcode> <RegisterA>, <RegisterB>, <RegisterC>
>>
Format30t(Opcode, Target) ::=
Format30t(Opcode, TargetLabel) ::=
<<
<Opcode> :goto_<Target>
<Opcode> <TargetLabel>
>>
Format31c(Opcode, Register, Reference) ::=
@ -237,9 +228,9 @@ Format31i(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) ::=
@ -322,21 +313,21 @@ ArrayElement(Bytes) ::=
PackedSwitchData(Opcode, FirstKey, Targets) ::=
<<
.packed-switch <FirstKey>
<Targets: {:pswitch_<it>}; separator="\n">
<Targets: {<it>}; separator="\n">
.end packed-switch
>>
SparseSwitchData(Opcode, Targets) ::=
<<
.sparse-switch
<Targets:{<it.Value> -> :sswitch_<it.Target>}; separator="\n">
<Targets:{<it.Value> -> <it.Target>}; separator="\n">
.end sparse-switch
>>
Label(Prefix, HexOffset, CommentedOut) ::=
Label(Prefix, Suffix) ::=
<<
<if(CommentedOut)>#<endif>:<Prefix><HexOffset>
:<Prefix><Suffix>
>>
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) ::=
<<