mirror of
https://github.com/revanced/smali.git
synced 2025-05-05 17:14:25 +02:00
- 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:
parent
8555ce95d5
commit
e2684fa219
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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_";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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_";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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_";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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_";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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_";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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_";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,8 +273,24 @@ 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) {
|
||||||
if (commentedOut) {
|
if (commentedOut) {
|
||||||
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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) ::=
|
||||||
<<
|
<<
|
||||||
|
Loading…
x
Reference in New Issue
Block a user