mirror of
https://github.com/revanced/smali.git
synced 2025-05-22 19:08:52 +02:00
Refactor dexlib so that the output is generated directly, instead of using the StringTemplate library
git-svn-id: https://smali.googlecode.com/svn/trunk@681 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
a7139f6586
commit
6eae34831f
@ -73,18 +73,9 @@
|
||||
<directory>src/main/resources/properties</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources/templates</directory>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.antlr</groupId>
|
||||
<artifactId>stringtemplate</artifactId>
|
||||
<version>3.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jf</groupId>
|
||||
<artifactId>dexlib</artifactId>
|
||||
|
@ -28,21 +28,37 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.dexlib.AnnotationItem;
|
||||
import org.jf.baksmali.Adaptors.EncodedValue.AnnotationEncodedValueAdaptor;
|
||||
import org.jf.baksmali.Adaptors.Reference.TypeReference;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.jf.dexlib.AnnotationSetItem;
|
||||
|
||||
import java.util.List;
|
||||
import java.io.IOException;
|
||||
|
||||
public class AnnotationAdaptor {
|
||||
public static StringTemplate createTemplate(StringTemplateGroup stg, AnnotationItem annotationItem) {
|
||||
StringTemplate template = stg.getInstanceOf("annotation");
|
||||
|
||||
template.setAttribute("Visibility", annotationItem.getVisibility().name().toLowerCase());
|
||||
AnnotationEncodedValueAdaptor.setAttributesForAnnotation(template, annotationItem.getEncodedAnnotation());
|
||||
public class AnnotationFormatter {
|
||||
|
||||
return template;
|
||||
public static void writeTo(IndentingPrintWriter writer, AnnotationSetItem annotationSet) throws IOException {
|
||||
boolean first = true;
|
||||
for (AnnotationItem annotationItem: annotationSet.getAnnotations()) {
|
||||
if (!first) {
|
||||
writer.println();
|
||||
}
|
||||
first = false;
|
||||
|
||||
writeTo(writer, annotationItem);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeTo(IndentingPrintWriter writer, AnnotationItem annotationItem) throws IOException {
|
||||
writer.write(".annotation ");
|
||||
writer.write(annotationItem.getVisibility().visibility);
|
||||
writer.write(' ');
|
||||
ReferenceFormatter.writeTypeReference(writer, annotationItem.getEncodedAnnotation().annotationType);
|
||||
writer.println();
|
||||
|
||||
AnnotationEncodedValueAdaptor.writeElementsTo(writer, annotationItem.getEncodedAnnotation());
|
||||
|
||||
writer.println(".end annotation");
|
||||
}
|
||||
}
|
@ -28,26 +28,21 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
|
||||
//a "spacer" between instructions
|
||||
public class BlankMethodItem extends MethodItem {
|
||||
private static StringTemplate template;
|
||||
|
||||
public BlankMethodItem(StringTemplateGroup stg, int codeAddress) {
|
||||
public BlankMethodItem(int codeAddress) {
|
||||
super(codeAddress);
|
||||
if (template == null) {
|
||||
template = stg.getInstanceOf("Blank");
|
||||
}
|
||||
}
|
||||
|
||||
public double getSortOrder() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return template.toString();
|
||||
public boolean writeTo(IndentingPrintWriter writer) {
|
||||
//we didn't technically print something, but returning true indicates that a newline should be printed
|
||||
//after this method item, which is the intended functionality
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -28,36 +28,32 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.dexlib.TypeIdItem;
|
||||
import org.jf.baksmali.Adaptors.Reference.TypeReference;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
public class CatchMethodItem extends MethodItem {
|
||||
private final StringTemplateGroup stg;
|
||||
private final TypeIdItem exceptionType;
|
||||
|
||||
private final LabelMethodItem tryStartLabel;
|
||||
private final LabelMethodItem tryEndLabel;
|
||||
private final LabelMethodItem handlerLabel;
|
||||
|
||||
public CatchMethodItem(MethodDefinition.LabelCache labelCache, int codeAddress, StringTemplateGroup stg,
|
||||
TypeIdItem exceptionType, int startAddress, int endAddress, int handlerAddress) {
|
||||
public CatchMethodItem(MethodDefinition.LabelCache labelCache, int codeAddress, TypeIdItem exceptionType,
|
||||
int startAddress, int endAddress, int handlerAddress) {
|
||||
super(codeAddress);
|
||||
this.stg = stg;
|
||||
this.exceptionType = exceptionType;
|
||||
|
||||
tryStartLabel = labelCache.internLabel(new LabelMethodItem(startAddress, stg, "try_start_"));
|
||||
tryStartLabel = labelCache.internLabel(new LabelMethodItem(startAddress, "try_start_"));
|
||||
tryStartLabel.setUncommented();
|
||||
//use the address from the last covered instruction, but make the label
|
||||
//name refer to the address of the next instruction
|
||||
tryEndLabel = labelCache.internLabel(new EndTryLabelMethodItem(codeAddress, stg, endAddress));
|
||||
tryEndLabel = labelCache.internLabel(new EndTryLabelMethodItem(codeAddress, endAddress));
|
||||
tryEndLabel.setUncommented();
|
||||
|
||||
if (exceptionType == null) {
|
||||
handlerLabel = labelCache.internLabel(new LabelMethodItem(handlerAddress, stg, "catchall_"));
|
||||
handlerLabel = labelCache.internLabel(new LabelMethodItem(handlerAddress, "catchall_"));
|
||||
} else {
|
||||
handlerLabel = labelCache.internLabel(new LabelMethodItem(handlerAddress, stg, "catch_"));
|
||||
handlerLabel = labelCache.internLabel(new LabelMethodItem(handlerAddress, "catch_"));
|
||||
}
|
||||
handlerLabel.setUncommented();
|
||||
}
|
||||
@ -79,19 +75,20 @@ public class CatchMethodItem extends MethodItem {
|
||||
return 102;
|
||||
}
|
||||
|
||||
protected String getTemplateName() {
|
||||
return "Catch";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringTemplate template = stg.getInstanceOf(getTemplateName());
|
||||
if (exceptionType != null) {
|
||||
template.setAttribute("ExceptionType", TypeReference.createTemplate(stg, exceptionType));
|
||||
public boolean writeTo(IndentingPrintWriter writer) {
|
||||
if (exceptionType == null) {
|
||||
writer.write(".catchall");
|
||||
} else {
|
||||
writer.write(".catch ");
|
||||
ReferenceFormatter.writeTypeReference(writer, exceptionType);
|
||||
}
|
||||
template.setAttribute("StartLabel", tryStartLabel);
|
||||
template.setAttribute("EndLabel", tryEndLabel);
|
||||
template.setAttribute("HandlerLabel", handlerLabel);
|
||||
return template.toString();
|
||||
writer.write(" {");
|
||||
tryStartLabel.writeTo(writer);
|
||||
writer.write(" .. ");
|
||||
tryEndLabel.writeTo(writer);
|
||||
writer.write("} ");
|
||||
handlerLabel.writeTo(writer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.dexlib.Code.Analysis.ValidationException;
|
||||
import org.jf.dexlib.EncodedValue.EncodedValue;
|
||||
import org.jf.dexlib.*;
|
||||
@ -35,13 +36,11 @@ import org.jf.dexlib.Code.Instruction;
|
||||
import org.jf.dexlib.Code.Format.Instruction21c;
|
||||
import org.jf.dexlib.Util.AccessFlags;
|
||||
import org.jf.dexlib.Util.SparseArray;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class ClassDefinition {
|
||||
private StringTemplateGroup stg;
|
||||
private ClassDefItem classDefItem;
|
||||
private ClassDataItem classDataItem;
|
||||
|
||||
@ -53,31 +52,13 @@ public class ClassDefinition {
|
||||
|
||||
protected boolean validationErrors;
|
||||
|
||||
public ClassDefinition(StringTemplateGroup stg, ClassDefItem classDefItem) {
|
||||
this.stg = stg;
|
||||
public ClassDefinition(ClassDefItem classDefItem) {
|
||||
this.classDefItem = classDefItem;
|
||||
this.classDataItem = classDefItem.getClassData();
|
||||
buildAnnotationMaps();
|
||||
findFieldsSetInStaticConstructor();
|
||||
}
|
||||
|
||||
public StringTemplate createTemplate() {
|
||||
StringTemplate template = stg.getInstanceOf("smaliFile");
|
||||
|
||||
template.setAttribute("AccessFlags", getAccessFlags());
|
||||
template.setAttribute("ClassType", classDefItem.getClassType().getTypeDescriptor());
|
||||
template.setAttribute("SuperType", getSuperType());
|
||||
template.setAttribute("SourceFile", getSourceFile());
|
||||
template.setAttribute("Interfaces", getInterfaces());
|
||||
template.setAttribute("Annotations", getAnnotations());
|
||||
template.setAttribute("StaticFields", getStaticFields());
|
||||
template.setAttribute("InstanceFields", getInstanceFields());
|
||||
template.setAttribute("DirectMethods", getDirectMethods());
|
||||
template.setAttribute("VirtualMethods", getVirtualMethods());
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
public boolean hadValidationErrors() {
|
||||
return validationErrors;
|
||||
}
|
||||
@ -143,149 +124,212 @@ public class ClassDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getAccessFlags() {
|
||||
List<String> accessFlags = new ArrayList<String>();
|
||||
|
||||
for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForClass(classDefItem.getAccessFlags())) {
|
||||
accessFlags.add(accessFlag.toString());
|
||||
}
|
||||
|
||||
return accessFlags;
|
||||
public void writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
writeClass(writer);
|
||||
writeSuper(writer);
|
||||
writeSourceFile(writer);
|
||||
writeInterfaces(writer);
|
||||
writeAnnotations(writer);
|
||||
writeStaticFields(writer);
|
||||
writeInstanceFields(writer);
|
||||
writeDirectMethods(writer);
|
||||
writeVirtualMethods(writer);
|
||||
return ;
|
||||
}
|
||||
|
||||
private void writeClass(IndentingPrintWriter writer) {
|
||||
writer.write(".class ");
|
||||
writeAccessFlags(writer);
|
||||
writer.println(classDefItem.getClassType().getTypeDescriptor());
|
||||
}
|
||||
|
||||
private String getSuperType() {
|
||||
private void writeAccessFlags(IndentingPrintWriter writer) {
|
||||
for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForClass(classDefItem.getAccessFlags())) {
|
||||
writer.write(accessFlag.toString());
|
||||
writer.write(' ');
|
||||
}
|
||||
}
|
||||
|
||||
private void writeSuper(IndentingPrintWriter writer) {
|
||||
TypeIdItem superClass = classDefItem.getSuperclass();
|
||||
if (superClass != null) {
|
||||
return superClass.getTypeDescriptor();
|
||||
writer.write(".super ");
|
||||
writer.println(superClass.getTypeDescriptor());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getSourceFile() {
|
||||
private void writeSourceFile(IndentingPrintWriter writer) {
|
||||
StringIdItem sourceFile = classDefItem.getSourceFile();
|
||||
|
||||
if (sourceFile == null) {
|
||||
return null;
|
||||
if (sourceFile != null) {
|
||||
writer.write(".source \"");
|
||||
writer.print(sourceFile.getStringValue());
|
||||
writer.println('"');
|
||||
}
|
||||
return classDefItem.getSourceFile().getStringValue();
|
||||
}
|
||||
|
||||
private List<String> getInterfaces() {
|
||||
List<String> interfaces = new ArrayList<String>();
|
||||
|
||||
private void writeInterfaces(IndentingPrintWriter writer) {
|
||||
TypeListItem interfaceList = classDefItem.getInterfaces();
|
||||
|
||||
if (interfaceList != null) {
|
||||
for (TypeIdItem typeIdItem: interfaceList.getTypes()) {
|
||||
interfaces.add(typeIdItem.getTypeDescriptor());
|
||||
}
|
||||
if (interfaceList == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
return interfaces;
|
||||
List<TypeIdItem> interfaces = interfaceList.getTypes();
|
||||
if (interfaces == null || interfaces.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
writer.println();
|
||||
writer.println("# interfaces");
|
||||
for (TypeIdItem typeIdItem: interfaceList.getTypes()) {
|
||||
writer.write(".implements ");
|
||||
writer.println(typeIdItem.getTypeDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
private List<StringTemplate> getAnnotations() {
|
||||
private void writeAnnotations(IndentingPrintWriter writer) throws IOException {
|
||||
AnnotationDirectoryItem annotationDirectory = classDefItem.getAnnotations();
|
||||
if (annotationDirectory == null) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
AnnotationSetItem annotationSet = annotationDirectory.getClassAnnotations();
|
||||
if (annotationSet == null) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
List<StringTemplate> annotations = new ArrayList<StringTemplate>();
|
||||
|
||||
for (AnnotationItem annotationItem: annotationSet.getAnnotations()) {
|
||||
annotations.add(AnnotationAdaptor.createTemplate(stg, annotationItem));
|
||||
}
|
||||
return annotations;
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.println("# annotations");
|
||||
AnnotationFormatter.writeTo(writer, annotationSet);
|
||||
}
|
||||
|
||||
private List<StringTemplate> getStaticFields() {
|
||||
List<StringTemplate> staticFields = new ArrayList<StringTemplate>();
|
||||
|
||||
if (classDataItem != null) {
|
||||
//if classDataItem is not null, then classDefItem won't be null either
|
||||
assert(classDefItem != null);
|
||||
EncodedArrayItem encodedStaticInitializers = classDefItem.getStaticFieldInitializers();
|
||||
|
||||
EncodedValue[] staticInitializers;
|
||||
if (encodedStaticInitializers != null) {
|
||||
staticInitializers = encodedStaticInitializers.getEncodedArray().values;
|
||||
} else {
|
||||
staticInitializers = new EncodedValue[0];
|
||||
}
|
||||
|
||||
int i=0;
|
||||
for (ClassDataItem.EncodedField field: classDataItem.getStaticFields()) {
|
||||
EncodedValue encodedValue = null;
|
||||
if (i < staticInitializers.length) {
|
||||
encodedValue = staticInitializers[i];
|
||||
}
|
||||
AnnotationSetItem annotationSet = fieldAnnotationsMap.get(field.field.getIndex());
|
||||
|
||||
boolean setInStaticConstructor =
|
||||
fieldsSetInStaticConstructor.get(field.field.getIndex()) != null;
|
||||
|
||||
staticFields.add(FieldDefinition.createTemplate(stg, field, encodedValue, annotationSet,
|
||||
setInStaticConstructor));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return staticFields;
|
||||
}
|
||||
|
||||
private List<StringTemplate> getInstanceFields() {
|
||||
List<StringTemplate> instanceFields = new ArrayList<StringTemplate>();
|
||||
|
||||
if (classDataItem != null) {
|
||||
for (ClassDataItem.EncodedField field: classDataItem.getInstanceFields()) {
|
||||
AnnotationSetItem annotationSet = fieldAnnotationsMap.get(field.field.getIndex());
|
||||
instanceFields.add(FieldDefinition.createTemplate(stg, field, annotationSet));
|
||||
}
|
||||
}
|
||||
|
||||
return instanceFields;
|
||||
}
|
||||
|
||||
private List<StringTemplate> getDirectMethods() {
|
||||
private void writeStaticFields(IndentingPrintWriter writer) throws IOException {
|
||||
if (classDataItem == null) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
//if classDataItem is not null, then classDefItem won't be null either
|
||||
assert(classDefItem != null);
|
||||
|
||||
EncodedArrayItem encodedStaticInitializers = classDefItem.getStaticFieldInitializers();
|
||||
|
||||
EncodedValue[] staticInitializers;
|
||||
if (encodedStaticInitializers != null) {
|
||||
staticInitializers = encodedStaticInitializers.getEncodedArray().values;
|
||||
} else {
|
||||
staticInitializers = new EncodedValue[0];
|
||||
}
|
||||
|
||||
return getTemplatesForMethods(classDataItem.getDirectMethods());
|
||||
ClassDataItem.EncodedField[] encodedFields = classDataItem.getStaticFields();
|
||||
if (encodedFields == null || encodedFields.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.println("# static fields");
|
||||
|
||||
boolean first = true;
|
||||
for (int i=0; i<encodedFields.length; i++) {
|
||||
if (!first) {
|
||||
writer.println();
|
||||
}
|
||||
first = false;
|
||||
|
||||
ClassDataItem.EncodedField field = encodedFields[i];
|
||||
EncodedValue encodedValue = null;
|
||||
if (i < staticInitializers.length) {
|
||||
encodedValue = staticInitializers[i];
|
||||
}
|
||||
AnnotationSetItem annotationSet = fieldAnnotationsMap.get(field.field.getIndex());
|
||||
|
||||
boolean setInStaticConstructor =
|
||||
fieldsSetInStaticConstructor.get(field.field.getIndex()) != null;
|
||||
|
||||
FieldDefinition.writeTo(writer, field, encodedValue, annotationSet, setInStaticConstructor);
|
||||
}
|
||||
}
|
||||
|
||||
private List<StringTemplate> getVirtualMethods() {
|
||||
private void writeInstanceFields(IndentingPrintWriter writer) throws IOException {
|
||||
if (classDataItem == null) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
return getTemplatesForMethods(classDataItem.getVirtualMethods());
|
||||
ClassDataItem.EncodedField[] encodedFields = classDataItem.getInstanceFields();
|
||||
if (encodedFields == null || encodedFields.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.println("# instance fields");
|
||||
boolean first = true;
|
||||
for (ClassDataItem.EncodedField field: classDataItem.getInstanceFields()) {
|
||||
if (!first) {
|
||||
writer.println();
|
||||
}
|
||||
first = false;
|
||||
|
||||
AnnotationSetItem annotationSet = fieldAnnotationsMap.get(field.field.getIndex());
|
||||
|
||||
FieldDefinition.writeTo(writer, field, null, annotationSet, false);
|
||||
}
|
||||
}
|
||||
|
||||
private List<StringTemplate> getTemplatesForMethods(ClassDataItem.EncodedMethod[] methods) {
|
||||
List<StringTemplate> methodTemplates = new ArrayList<StringTemplate>();
|
||||
private void writeDirectMethods(IndentingPrintWriter writer) throws IOException {
|
||||
if (classDataItem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ClassDataItem.EncodedMethod[] directMethods = classDataItem.getDirectMethods();
|
||||
|
||||
if (directMethods == null || directMethods.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.println("# direct methods");
|
||||
writeMethods(writer, directMethods);
|
||||
}
|
||||
|
||||
private void writeVirtualMethods(IndentingPrintWriter writer) throws IOException {
|
||||
if (classDataItem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ClassDataItem.EncodedMethod[] virtualMethods = classDataItem.getVirtualMethods();
|
||||
|
||||
if (virtualMethods == null || virtualMethods.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.println("# virtual methods");
|
||||
writeMethods(writer, virtualMethods);
|
||||
}
|
||||
|
||||
private void writeMethods(IndentingPrintWriter writer, ClassDataItem.EncodedMethod[] methods) throws IOException {
|
||||
boolean first = true;
|
||||
for (ClassDataItem.EncodedMethod method: methods) {
|
||||
if (!first) {
|
||||
writer.println();
|
||||
}
|
||||
first = false;
|
||||
|
||||
AnnotationSetItem annotationSet = methodAnnotationsMap.get(method.method.getIndex());
|
||||
AnnotationSetRefList parameterAnnotationList = parameterAnnotationsMap.get(method.method.getIndex());
|
||||
|
||||
MethodDefinition methodDefinition = new MethodDefinition(stg, method);
|
||||
MethodDefinition methodDefinition = new MethodDefinition(method);
|
||||
methodDefinition.writeTo(writer, annotationSet, parameterAnnotationList);
|
||||
|
||||
|
||||
methodTemplates.add(methodDefinition.createTemplate(annotationSet, parameterAnnotationList));
|
||||
|
||||
ValidationException validationException = methodDefinition.getValidationException();
|
||||
if (validationException != null) {
|
||||
//System.err.println(validationException.toString());
|
||||
validationException.printStackTrace(System.err);
|
||||
this.validationErrors = true;
|
||||
}
|
||||
}
|
||||
|
||||
return methodTemplates;
|
||||
}
|
||||
}
|
||||
|
@ -28,17 +28,16 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
|
||||
public class CommentMethodItem extends MethodItem {
|
||||
private final StringTemplate template;
|
||||
//private final StringTemplate template;
|
||||
private final String comment;
|
||||
private final double sortOrder;
|
||||
|
||||
public CommentMethodItem(StringTemplateGroup stg, String comment, int codeAddress, double sortOrder) {
|
||||
public CommentMethodItem(String comment, int codeAddress, double sortOrder) {
|
||||
super(codeAddress);
|
||||
template = stg.getInstanceOf("Comment");
|
||||
template.setAttribute("Comment", comment);
|
||||
this.comment = comment;
|
||||
this.sortOrder = sortOrder;
|
||||
}
|
||||
|
||||
@ -46,8 +45,9 @@ public class CommentMethodItem extends MethodItem {
|
||||
return sortOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return template.toString();
|
||||
public boolean writeTo(IndentingPrintWriter writer) {
|
||||
writer.write('#');
|
||||
writer.write(comment);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -28,16 +28,15 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class CommentedOutMethodItem extends MethodItem {
|
||||
private final StringTemplateGroup stg;
|
||||
private final MethodItem commentedOutMethodItem;
|
||||
|
||||
public CommentedOutMethodItem(StringTemplateGroup stg, MethodItem commentedOutMethodItem) {
|
||||
public CommentedOutMethodItem(MethodItem commentedOutMethodItem) {
|
||||
super(commentedOutMethodItem.getCodeAddress());
|
||||
this.stg = stg;
|
||||
this.commentedOutMethodItem = commentedOutMethodItem;
|
||||
}
|
||||
|
||||
@ -45,10 +44,9 @@ public class CommentedOutMethodItem extends MethodItem {
|
||||
return commentedOutMethodItem.getSortOrder() + .001;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringTemplate template = stg.getInstanceOf("CommentedOutMethodItem");
|
||||
template.setAttribute("MethodItem", commentedOutMethodItem);
|
||||
return template.toString();
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
writer.write('#');
|
||||
commentedOutMethodItem.writeTo(writer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -28,18 +28,16 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
import org.jf.dexlib.StringIdItem;
|
||||
import org.jf.dexlib.TypeIdItem;
|
||||
|
||||
public class DebugMethodItem extends MethodItem {
|
||||
private final StringTemplateGroup stg;
|
||||
private final String templateName;
|
||||
public abstract class DebugMethodItem extends MethodItem {
|
||||
private final double sortOrder;
|
||||
|
||||
public DebugMethodItem(int codeAddress, StringTemplateGroup stg, String templateName, double sortOrder) {
|
||||
public DebugMethodItem(int codeAddress, double sortOrder) {
|
||||
super(codeAddress);
|
||||
this.stg = stg;
|
||||
this.templateName = templateName;
|
||||
this.sortOrder = sortOrder;
|
||||
}
|
||||
|
||||
@ -47,14 +45,74 @@ public class DebugMethodItem extends MethodItem {
|
||||
return sortOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringTemplate template = stg.getInstanceOf(templateName);
|
||||
setAttributes(template);
|
||||
return template.toString();
|
||||
protected static void writeLine(IndentingPrintWriter writer, int line) {
|
||||
writer.write(".line ");
|
||||
writer.print(line);
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template)
|
||||
{
|
||||
protected static void writeEndPrologue(IndentingPrintWriter writer) {
|
||||
writer.write(".prologue");
|
||||
}
|
||||
|
||||
protected static void writeBeginEpilogue(IndentingPrintWriter writer) {
|
||||
writer.write(".epilogue");
|
||||
}
|
||||
|
||||
protected static void writeStartLocal(IndentingPrintWriter writer, CodeItem codeItem, int register,
|
||||
StringIdItem name, TypeIdItem type, StringIdItem signature) {
|
||||
writer.write(".local ");
|
||||
RegisterFormatter.writeTo(writer, codeItem, register);
|
||||
writer.write(", ");
|
||||
writer.write(name.getStringValue());
|
||||
writer.write(':');
|
||||
writer.write(type.getTypeDescriptor());
|
||||
if (signature != null) {
|
||||
writer.write(",\"");
|
||||
writer.write(signature.getStringValue());
|
||||
writer.write('"');
|
||||
}
|
||||
}
|
||||
|
||||
protected static void writeEndLocal(IndentingPrintWriter writer, CodeItem codeItem, int register, StringIdItem name,
|
||||
TypeIdItem type, StringIdItem signature) {
|
||||
writer.write(".end local ");
|
||||
RegisterFormatter.writeTo(writer, codeItem, register);
|
||||
|
||||
if (name != null) {
|
||||
writer.write(" #");
|
||||
writer.write(name.getStringValue());
|
||||
writer.write(':');
|
||||
writer.write(type.getTypeDescriptor());
|
||||
if (signature != null) {
|
||||
writer.write(",\"");
|
||||
writer.write(signature.getStringValue());
|
||||
writer.write('"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected static void writeRestartLocal(IndentingPrintWriter writer, CodeItem codeItem, int register,
|
||||
StringIdItem name, TypeIdItem type, StringIdItem signature) {
|
||||
writer.write(".restart local ");
|
||||
RegisterFormatter.writeTo(writer, codeItem, register);
|
||||
|
||||
if (name != null) {
|
||||
writer.write(" #");
|
||||
writer.write(name.getStringValue());
|
||||
writer.write(':');
|
||||
writer.write(type.getTypeDescriptor());
|
||||
if (signature != null) {
|
||||
writer.write(",\"");
|
||||
writer.write(signature.getStringValue());
|
||||
writer.write('"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static void writeSetFile(IndentingPrintWriter writer, String fileName) {
|
||||
writer.write(".source \"");
|
||||
writer.write(fileName);
|
||||
writer.write('"');
|
||||
}
|
||||
}
|
||||
|
@ -28,50 +28,34 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors.EncodedValue;
|
||||
|
||||
import org.jf.dexlib.EncodedValue.EncodedValue;
|
||||
import org.jf.baksmali.Adaptors.ReferenceFormatter;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.dexlib.EncodedValue.AnnotationEncodedSubValue;
|
||||
import org.jf.dexlib.StringIdItem;
|
||||
import org.jf.baksmali.Adaptors.Reference.TypeReference;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class AnnotationEncodedValueAdaptor {
|
||||
|
||||
public static StringTemplate createTemplate(StringTemplateGroup stg, AnnotationEncodedSubValue encodedAnnotation) {
|
||||
StringTemplate template = stg.getInstanceOf("AnnotationEncodedValue");
|
||||
template.setAttribute("AnnotationType", TypeReference.createTemplate(stg, encodedAnnotation.annotationType));
|
||||
template.setAttribute("Elements", getElements(stg, encodedAnnotation));
|
||||
return template;
|
||||
public static void writeTo(IndentingPrintWriter writer, AnnotationEncodedSubValue encodedAnnotation)
|
||||
throws IOException {
|
||||
writer.write(".subannotation ");
|
||||
ReferenceFormatter.writeTypeReference(writer, encodedAnnotation.annotationType);
|
||||
writer.println();
|
||||
|
||||
writeElementsTo(writer, encodedAnnotation);
|
||||
writer.write(".end subannotation");
|
||||
}
|
||||
|
||||
public static void setAttributesForAnnotation(StringTemplate template,
|
||||
AnnotationEncodedSubValue encodedAnnotation) {
|
||||
template.setAttribute("AnnotationType", TypeReference.createTemplate(template.getGroup(),
|
||||
encodedAnnotation.annotationType));
|
||||
template.setAttribute("Elements", getElements(template.getGroup(), encodedAnnotation));
|
||||
}
|
||||
|
||||
private static List<String> getElements(StringTemplateGroup stg,
|
||||
AnnotationEncodedSubValue encodedAnnotation) {
|
||||
List<String> elements = new ArrayList<String>();
|
||||
|
||||
public static void writeElementsTo(IndentingPrintWriter writer, AnnotationEncodedSubValue encodedAnnotation)
|
||||
throws IOException {
|
||||
writer.indent(4);
|
||||
for (int i=0; i<encodedAnnotation.names.length; i++) {
|
||||
elements.add(AnnotationElementAdaptor.toString(stg, encodedAnnotation.names[i], encodedAnnotation.values[i]));
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
|
||||
private static class AnnotationElementAdaptor {
|
||||
public static String toString(StringTemplateGroup stg, StringIdItem name, EncodedValue value) {
|
||||
StringTemplate template = stg.getInstanceOf("AnnotationElement");
|
||||
template.setAttribute("Name", name);
|
||||
template.setAttribute("Value", EncodedValueAdaptor.create(stg, value));
|
||||
return template.toString();
|
||||
writer.write(encodedAnnotation.names[i].getStringValue());
|
||||
writer.write(" = ");
|
||||
|
||||
EncodedValueAdaptor.writeTo(writer, encodedAnnotation.values[i]);
|
||||
writer.println();
|
||||
}
|
||||
writer.deindent(4);
|
||||
}
|
||||
}
|
||||
|
@ -28,27 +28,34 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors.EncodedValue;
|
||||
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.dexlib.EncodedValue.EncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.ArrayEncodedValue;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ArrayEncodedValueAdaptor {
|
||||
public static StringTemplate createTemplate(StringTemplateGroup stg, ArrayEncodedValue encodedArray) {
|
||||
StringTemplate template = stg.getInstanceOf("ArrayEncodedValue");
|
||||
template.setAttribute("Value", getValue(stg, encodedArray));
|
||||
return template;
|
||||
}
|
||||
|
||||
private static List<StringTemplate> getValue(StringTemplateGroup stg, ArrayEncodedValue encodedArray) {
|
||||
List<StringTemplate> encodedValues = new ArrayList<StringTemplate>();
|
||||
|
||||
for (EncodedValue encodedValue: encodedArray.values) {
|
||||
encodedValues.add(EncodedValueAdaptor.create(stg, encodedValue));
|
||||
public static void writeTo(IndentingPrintWriter writer, ArrayEncodedValue encodedArray) throws IOException {
|
||||
writer.print('{');
|
||||
EncodedValue[] values = encodedArray.values;
|
||||
if (values == null || values.length == 0) {
|
||||
writer.print('}');
|
||||
return;
|
||||
}
|
||||
return encodedValues;
|
||||
|
||||
writer.println();
|
||||
writer.indent(4);
|
||||
boolean first = true;
|
||||
for (EncodedValue encodedValue: encodedArray.values) {
|
||||
if (!first) {
|
||||
writer.println(',');
|
||||
}
|
||||
first = false;
|
||||
|
||||
EncodedValueAdaptor.writeTo(writer, encodedValue);
|
||||
}
|
||||
writer.deindent(4);
|
||||
writer.println();
|
||||
writer.print('}');
|
||||
}
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* 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.EncodedValue;
|
||||
|
||||
import org.jf.baksmali.Adaptors.Reference.Reference;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
|
||||
public class EncodedIndexedItemAdaptor {
|
||||
public static StringTemplate createTemplate(StringTemplateGroup stg, StringTemplate reference) {
|
||||
StringTemplate template = stg.getInstanceOf("EncodedIndexedItemReference");
|
||||
template.setAttribute("Value", reference);
|
||||
return template;
|
||||
}
|
||||
}
|
@ -28,52 +28,63 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors.EncodedValue;
|
||||
|
||||
import org.jf.baksmali.Adaptors.ReferenceFormatter;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.baksmali.Renderers.*;
|
||||
import org.jf.dexlib.EncodedValue.*;
|
||||
import org.jf.baksmali.Adaptors.Reference.*;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class EncodedValueAdaptor {
|
||||
public static StringTemplate create(StringTemplateGroup stg, EncodedValue encodedValue) {
|
||||
public static void writeTo(IndentingPrintWriter writer, EncodedValue encodedValue) throws IOException {
|
||||
switch (encodedValue.getValueType()) {
|
||||
case VALUE_ANNOTATION:
|
||||
return AnnotationEncodedValueAdaptor.createTemplate(stg, (AnnotationEncodedValue)encodedValue);
|
||||
AnnotationEncodedValueAdaptor.writeTo(writer, (AnnotationEncodedValue)encodedValue);
|
||||
return;
|
||||
case VALUE_ARRAY:
|
||||
return ArrayEncodedValueAdaptor.createTemplate(stg, (ArrayEncodedValue)encodedValue);
|
||||
ArrayEncodedValueAdaptor.writeTo(writer, (ArrayEncodedValue)encodedValue);
|
||||
return;
|
||||
case VALUE_BOOLEAN:
|
||||
return SimpleEncodedValueAdaptor.createTemplate(stg, ((BooleanEncodedValue)encodedValue).value);
|
||||
BooleanRenderer.writeTo(writer, ((BooleanEncodedValue)encodedValue).value);
|
||||
return;
|
||||
case VALUE_BYTE:
|
||||
return SimpleEncodedValueAdaptor.createTemplate(stg, ((ByteEncodedValue)encodedValue).value);
|
||||
ByteRenderer.writeTo(writer, ((ByteEncodedValue)encodedValue).value);
|
||||
return;
|
||||
case VALUE_CHAR:
|
||||
return SimpleEncodedValueAdaptor.createTemplate(stg, ((CharEncodedValue)encodedValue).value);
|
||||
CharRenderer.writeTo(writer, ((CharEncodedValue)encodedValue).value);
|
||||
return;
|
||||
case VALUE_DOUBLE:
|
||||
return SimpleEncodedValueAdaptor.createTemplate(stg, ((DoubleEncodedValue)encodedValue).value);
|
||||
DoubleRenderer.writeTo(writer, ((DoubleEncodedValue)encodedValue).value);
|
||||
return;
|
||||
case VALUE_ENUM:
|
||||
return EnumEncodedValueAdaptor.createTemplate(stg,
|
||||
FieldReference.createTemplate(stg, ((EnumEncodedValue)encodedValue).value));
|
||||
EnumEncodedValueAdaptor.writeTo(writer, ((EnumEncodedValue)encodedValue).value);
|
||||
return;
|
||||
case VALUE_FIELD:
|
||||
return EncodedIndexedItemAdaptor.createTemplate(stg, FieldReference.createTemplate(stg,
|
||||
((FieldEncodedValue)encodedValue).value));
|
||||
ReferenceFormatter.writeFieldReference(writer, ((FieldEncodedValue)encodedValue).value);
|
||||
return;
|
||||
case VALUE_FLOAT:
|
||||
return SimpleEncodedValueAdaptor.createTemplate(stg, ((FloatEncodedValue)encodedValue).value);
|
||||
FloatRenderer.writeTo(writer, ((FloatEncodedValue)encodedValue).value);
|
||||
return;
|
||||
case VALUE_INT:
|
||||
return SimpleEncodedValueAdaptor.createTemplate(stg, ((IntEncodedValue)encodedValue).value);
|
||||
IntegerRenderer.writeTo(writer, ((IntEncodedValue)encodedValue).value);
|
||||
return;
|
||||
case VALUE_LONG:
|
||||
return SimpleEncodedValueAdaptor.createTemplate(stg, ((LongEncodedValue)encodedValue).value);
|
||||
LongRenderer.writeTo(writer, ((LongEncodedValue)encodedValue).value);
|
||||
return;
|
||||
case VALUE_METHOD:
|
||||
return EncodedIndexedItemAdaptor.createTemplate(stg, MethodReference.createTemplate(stg,
|
||||
((MethodEncodedValue)encodedValue).value));
|
||||
ReferenceFormatter.writeMethodReference(writer, ((MethodEncodedValue)encodedValue).value);
|
||||
return;
|
||||
case VALUE_NULL:
|
||||
return SimpleEncodedValueAdaptor.createTemplate(stg, "null");
|
||||
writer.write("null");
|
||||
return;
|
||||
case VALUE_SHORT:
|
||||
return SimpleEncodedValueAdaptor.createTemplate(stg, ((ShortEncodedValue)encodedValue).value);
|
||||
ShortRenderer.writeTo(writer, ((ShortEncodedValue)encodedValue).value);
|
||||
return;
|
||||
case VALUE_STRING:
|
||||
return EncodedIndexedItemAdaptor.createTemplate(stg, StringReference.createTemplate(stg,
|
||||
((StringEncodedValue)encodedValue).value));
|
||||
ReferenceFormatter.writeStringReference(writer, ((StringEncodedValue)encodedValue).value);
|
||||
return;
|
||||
case VALUE_TYPE:
|
||||
return EncodedIndexedItemAdaptor.createTemplate(stg, TypeReference.createTemplate(stg,
|
||||
((TypeEncodedValue)encodedValue).value));
|
||||
ReferenceFormatter.writeTypeReference(writer, ((TypeEncodedValue)encodedValue).value);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -28,14 +28,15 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors.EncodedValue;
|
||||
|
||||
import org.jf.baksmali.Adaptors.Reference.FieldReference;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.jf.baksmali.Adaptors.ReferenceFormatter;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.dexlib.FieldIdItem;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class EnumEncodedValueAdaptor {
|
||||
public static StringTemplate createTemplate(StringTemplateGroup stg, StringTemplate fieldReference) {
|
||||
StringTemplate template = stg.getInstanceOf("EnumEncodedValue");
|
||||
template.setAttribute("Value", fieldReference);
|
||||
return template;
|
||||
public static void writeTo(IndentingPrintWriter writer, FieldIdItem item) throws IOException {
|
||||
writer.write(".enum ");
|
||||
ReferenceFormatter.writeFieldReference(writer, item);
|
||||
}
|
||||
}
|
||||
|
@ -28,13 +28,11 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
|
||||
public class EndTryLabelMethodItem extends LabelMethodItem {
|
||||
private int endTryAddress;
|
||||
|
||||
public EndTryLabelMethodItem(int codeAddress, StringTemplateGroup stg, int endTryAddress) {
|
||||
super(codeAddress, stg, "try_end_");
|
||||
public EndTryLabelMethodItem(int codeAddress, int endTryAddress) {
|
||||
super(codeAddress, "try_end_");
|
||||
this.endTryAddress = endTryAddress;
|
||||
}
|
||||
|
||||
@ -43,7 +41,7 @@ public class EndTryLabelMethodItem extends LabelMethodItem {
|
||||
return 101;
|
||||
}
|
||||
|
||||
public String getLabelAddress() {
|
||||
return Integer.toHexString(endTryAddress);
|
||||
public int getLabelAddress() {
|
||||
return endTryAddress;
|
||||
}
|
||||
}
|
||||
|
@ -29,31 +29,22 @@
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.Adaptors.EncodedValue.EncodedValueAdaptor;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.dexlib.ClassDataItem;
|
||||
import org.jf.dexlib.EncodedValue.EncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.NullEncodedValue;
|
||||
import org.jf.dexlib.AnnotationSetItem;
|
||||
import org.jf.dexlib.AnnotationItem;
|
||||
import org.jf.dexlib.Util.AccessFlags;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.io.IOException;
|
||||
|
||||
public class FieldDefinition {
|
||||
public static StringTemplate createTemplate(StringTemplateGroup stg, ClassDataItem.EncodedField encodedField,
|
||||
public static void writeTo(IndentingPrintWriter writer, ClassDataItem.EncodedField encodedField,
|
||||
EncodedValue initialValue, AnnotationSetItem annotationSet,
|
||||
boolean setInStaticConstructor) {
|
||||
StringTemplate template = stg.getInstanceOf("field");
|
||||
boolean setInStaticConstructor) throws IOException {
|
||||
|
||||
String fieldTypeDescriptor = encodedField.field.getFieldType().getTypeDescriptor();
|
||||
|
||||
template.setAttribute("AccessFlags", getAccessFlags(encodedField));
|
||||
template.setAttribute("FieldName", encodedField.field.getFieldName().getStringValue());
|
||||
template.setAttribute("FieldType", encodedField.field.getFieldType().getTypeDescriptor());
|
||||
template.setAttribute("Annotations", getAnnotations(stg, annotationSet));
|
||||
|
||||
if (setInStaticConstructor &&
|
||||
encodedField.isStatic() &&
|
||||
(encodedField.accessFlags & AccessFlags.FINAL.getValue()) != 0 &&
|
||||
@ -64,44 +55,33 @@ public class FieldDefinition {
|
||||
initialValue != NullEncodedValue.NullValue
|
||||
)) {
|
||||
|
||||
template.setAttribute("Comments",
|
||||
new String[]{"the value of this static final field might be set in the static constructor"});
|
||||
} else {
|
||||
template.setAttribute("Comments", null);
|
||||
writer.println("#the value of this static final field might be set in the static constructor");
|
||||
}
|
||||
|
||||
writer.write(".field ");
|
||||
writeAccessFlags(writer, encodedField);
|
||||
writer.write(encodedField.field.getFieldName().getStringValue());
|
||||
writer.write(':');
|
||||
writer.write(encodedField.field.getFieldType().getTypeDescriptor());
|
||||
if (initialValue != null) {
|
||||
template.setAttribute("InitialValue", EncodedValueAdaptor.create(stg, initialValue));
|
||||
writer.write(" = ");
|
||||
EncodedValueAdaptor.writeTo(writer, initialValue);
|
||||
}
|
||||
|
||||
return template;
|
||||
writer.println();
|
||||
|
||||
if (annotationSet != null) {
|
||||
writer.indent(4);
|
||||
AnnotationFormatter.writeTo(writer, annotationSet);
|
||||
writer.deindent(4);
|
||||
writer.println(".end field");
|
||||
}
|
||||
}
|
||||
|
||||
public static StringTemplate createTemplate(StringTemplateGroup stg, ClassDataItem.EncodedField encodedField,
|
||||
AnnotationSetItem annotationSet) {
|
||||
return createTemplate(stg, encodedField, null, annotationSet, false);
|
||||
}
|
||||
|
||||
private static List<String> getAccessFlags(ClassDataItem.EncodedField encodedField) {
|
||||
List<String> accessFlags = new ArrayList<String>();
|
||||
|
||||
private static void writeAccessFlags(IndentingPrintWriter writer, ClassDataItem.EncodedField encodedField) {
|
||||
for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForField(encodedField.accessFlags)) {
|
||||
accessFlags.add(accessFlag.toString());
|
||||
writer.write(accessFlag.toString());
|
||||
writer.write(' ');
|
||||
}
|
||||
|
||||
return accessFlags;
|
||||
}
|
||||
|
||||
private static List<StringTemplate> getAnnotations(StringTemplateGroup stg, AnnotationSetItem annotationSet) {
|
||||
if (annotationSet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<StringTemplate> annotationAdaptors = new ArrayList<StringTemplate>();
|
||||
|
||||
for (AnnotationItem annotationItem: annotationSet.getAnnotations()) {
|
||||
annotationAdaptors.add(AnnotationAdaptor.createTemplate(stg, annotationItem));
|
||||
}
|
||||
return annotationAdaptors;
|
||||
}
|
||||
}
|
||||
|
@ -28,40 +28,64 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.baksmali.Renderers.ByteRenderer;
|
||||
import org.jf.dexlib.Code.Format.ArrayDataPseudoInstruction;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class ArrayDataMethodItem extends InstructionMethodItem<ArrayDataPseudoInstruction> {
|
||||
private final boolean dead;
|
||||
|
||||
public ArrayDataMethodItem(CodeItem codeItem, int codeAddress, boolean dead, StringTemplateGroup stg,
|
||||
public ArrayDataMethodItem(CodeItem codeItem, int codeAddress, boolean dead,
|
||||
ArrayDataPseudoInstruction instruction) {
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
super(codeItem, codeAddress, instruction);
|
||||
this.dead = dead;
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
template.setAttribute("ElementWidth", instruction.getElementWidth());
|
||||
template.setAttribute("Dead", dead);
|
||||
setValuesAttribute(template);
|
||||
}
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
if (dead) {
|
||||
writer.print("#.array-data 0x");
|
||||
writer.printLongAsHex(instruction.getElementWidth());
|
||||
writer.println();
|
||||
|
||||
private void setValuesAttribute(StringTemplate parentTemplate) {
|
||||
Iterator<ArrayDataPseudoInstruction.ArrayElement> iterator = instruction.getElements();
|
||||
while (iterator.hasNext()) {
|
||||
ArrayDataPseudoInstruction.ArrayElement element = iterator.next();
|
||||
Iterator<ArrayDataPseudoInstruction.ArrayElement> iterator = instruction.getElements();
|
||||
while (iterator.hasNext()) {
|
||||
ArrayDataPseudoInstruction.ArrayElement element = iterator.next();
|
||||
|
||||
StringTemplate template = parentTemplate.getGroup().getInstanceOf("ArrayElement");
|
||||
|
||||
for (int i = element.bufferIndex; i < element.bufferIndex + element.elementWidth; i++) {
|
||||
template.setAttribute("Bytes", (Byte)element.buffer[i]);
|
||||
writer.write("# ");
|
||||
for (int i=0; i<element.elementWidth; i++) {
|
||||
if (i!=0) {
|
||||
writer.write(' ');
|
||||
}
|
||||
ByteRenderer.writeUnsignedTo(writer, element.buffer[element.bufferIndex+i]);
|
||||
}
|
||||
writer.println();
|
||||
}
|
||||
writer.print("#.end array-data");
|
||||
} else {
|
||||
writer.print(".array-data 0x");
|
||||
writer.printLongAsHex(instruction.getElementWidth());
|
||||
writer.println();
|
||||
|
||||
parentTemplate.setAttribute("Values", template);
|
||||
writer.indent(4);
|
||||
Iterator<ArrayDataPseudoInstruction.ArrayElement> iterator = instruction.getElements();
|
||||
while (iterator.hasNext()) {
|
||||
ArrayDataPseudoInstruction.ArrayElement element = iterator.next();
|
||||
|
||||
for (int i=0; i<element.elementWidth; i++) {
|
||||
if (i!=0) {
|
||||
writer.write(' ');
|
||||
}
|
||||
ByteRenderer.writeUnsignedTo(writer, element.buffer[element.bufferIndex+i]);
|
||||
}
|
||||
writer.println();
|
||||
}
|
||||
writer.deindent(4);
|
||||
writer.print(".end array-data");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -28,25 +28,23 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.jf.baksmali.Adaptors.MethodItem;
|
||||
import org.jf.baksmali.Adaptors.Reference.Reference;
|
||||
import org.jf.baksmali.Adaptors.ReferenceFormatter;
|
||||
import org.jf.baksmali.Adaptors.RegisterFormatter;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.baksmali.Renderers.LongRenderer;
|
||||
import org.jf.dexlib.*;
|
||||
import org.jf.dexlib.Code.*;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.io.IOException;
|
||||
|
||||
public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
||||
protected final CodeItem codeItem;
|
||||
protected final StringTemplateGroup stg;
|
||||
protected final T instruction;
|
||||
|
||||
public InstructionMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg, T instruction) {
|
||||
public InstructionMethodItem(CodeItem codeItem, int codeAddress, T instruction) {
|
||||
super(codeAddress);
|
||||
this.codeItem = codeItem;
|
||||
this.stg = stg;
|
||||
this.instruction = instruction;
|
||||
}
|
||||
|
||||
@ -55,125 +53,255 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
||||
return 100;
|
||||
}
|
||||
|
||||
protected String formatRegister(int register) {
|
||||
return RegisterFormatter.formatRegister(codeItem, register);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringTemplate template = stg.getInstanceOf(instruction.getFormat().name());
|
||||
template.setAttribute("Opcode", instruction.opcode.name);
|
||||
setAttributes(template);
|
||||
return template.toString();
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
switch (instruction.getFormat()) {
|
||||
case Format10t:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeTargetLabel(writer);
|
||||
return true;
|
||||
case Format10x:
|
||||
writeOpcode(writer);
|
||||
return true;
|
||||
case Format11n:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeLiteral(writer);
|
||||
return true;
|
||||
case Format11x:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
return true;
|
||||
case Format12x:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
return true;
|
||||
case Format20t:
|
||||
case Format30t:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeTargetLabel(writer);
|
||||
return true;
|
||||
case Format21c:
|
||||
case Format31c:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeReference(writer);
|
||||
return true;
|
||||
case Format21h:
|
||||
case Format21s:
|
||||
case Format31i:
|
||||
case Format51l:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeLiteral(writer);
|
||||
return true;
|
||||
case Format21t:
|
||||
case Format31t:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeTargetLabel(writer);
|
||||
return true;
|
||||
case Format22b:
|
||||
case Format22s:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
writer.write(", ");
|
||||
writeLiteral(writer);
|
||||
return true;
|
||||
case Format22c:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
writer.write(", ");
|
||||
writeReference(writer);
|
||||
return true;
|
||||
case Format22cs:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
writer.write(", ");
|
||||
writeFieldOffset(writer);
|
||||
return true;
|
||||
case Format22t:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
writer.write(", ");
|
||||
writeTargetLabel(writer);
|
||||
return true;
|
||||
case Format22x:
|
||||
case Format32x:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
return true;
|
||||
case Format23x:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
writer.write(", ");
|
||||
writeThirdRegister(writer);
|
||||
return true;
|
||||
case Format35c:
|
||||
case Format35s:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeInvokeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writeReference(writer);
|
||||
return true;
|
||||
case Format35ms:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeInvokeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writeVtableIndex(writer);
|
||||
return true;
|
||||
case Format3rc:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeInvokeRangeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writeReference(writer);
|
||||
return true;
|
||||
case Format3rms:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeInvokeRangeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writeVtableIndex(writer);
|
||||
return true;
|
||||
}
|
||||
assert false;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
if (instruction instanceof LiteralInstruction) {
|
||||
setLiteralAttributes((LiteralInstruction)instruction, template);
|
||||
}
|
||||
|
||||
if (instruction instanceof SingleRegisterInstruction) {
|
||||
setSingleRegisterAttributes((SingleRegisterInstruction)instruction, template);
|
||||
}
|
||||
|
||||
if (instruction instanceof FiveRegisterInstruction) {
|
||||
setFiveRegisterAttributes((FiveRegisterInstruction)instruction, template);
|
||||
}
|
||||
|
||||
if (instruction instanceof RegisterRangeInstruction) {
|
||||
setRegisterRangeAttributes((RegisterRangeInstruction)instruction, template);
|
||||
}
|
||||
|
||||
if (instruction instanceof InstructionWithReference) {
|
||||
setInstructionWithReferenceAttributes((InstructionWithReference)instruction, template);
|
||||
}
|
||||
|
||||
if (instruction instanceof OdexedInvokeVirtual) {
|
||||
setOdexedInvokeVirtualAttributes((OdexedInvokeVirtual)instruction, template);
|
||||
}
|
||||
|
||||
if (instruction instanceof OdexedFieldAccess) {
|
||||
setOdexedFieldAccessAttributes((OdexedFieldAccess)instruction, template);
|
||||
}
|
||||
protected void writeOpcode(IndentingPrintWriter writer) throws IOException {
|
||||
writer.write(instruction.opcode.name);
|
||||
}
|
||||
|
||||
private void setLiteralAttributes(LiteralInstruction instruction, StringTemplate template) {
|
||||
long literal = instruction.getLiteral();
|
||||
//TODO: do we really need to check and cast it to an int?
|
||||
if (literal <= Integer.MAX_VALUE && literal >= Integer.MIN_VALUE) {
|
||||
template.setAttribute("Literal", (int)literal);
|
||||
} else {
|
||||
template.setAttribute("Literal", literal);
|
||||
}
|
||||
protected void writeTargetLabel(IndentingPrintWriter writer) throws IOException {
|
||||
//this method is overrided by OffsetInstructionMethodItem, and should only be called for the formats that
|
||||
//have a target
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
private void setSingleRegisterAttributes(SingleRegisterInstruction instruction, StringTemplate template) {
|
||||
template.setAttribute("RegisterA", formatRegister(instruction.getRegisterA()));
|
||||
|
||||
if (instruction instanceof TwoRegisterInstruction) {
|
||||
setTwoRegisterAttributes((TwoRegisterInstruction)instruction, template);
|
||||
}
|
||||
protected void writeRegister(IndentingPrintWriter writer, int registerNumber) throws IOException {
|
||||
RegisterFormatter.writeTo(writer, codeItem, registerNumber);
|
||||
}
|
||||
|
||||
private void setTwoRegisterAttributes(TwoRegisterInstruction instruction, StringTemplate template) {
|
||||
template.setAttribute("RegisterB", formatRegister(instruction.getRegisterB()));
|
||||
|
||||
if (instruction instanceof ThreeRegisterInstruction) {
|
||||
setThreeRegisterAttributes((ThreeRegisterInstruction)instruction, template);
|
||||
}
|
||||
protected void writeFirstRegister(IndentingPrintWriter writer) throws IOException {
|
||||
writeRegister(writer, ((SingleRegisterInstruction)instruction).getRegisterA());
|
||||
}
|
||||
|
||||
private void setThreeRegisterAttributes(ThreeRegisterInstruction instruction, StringTemplate template) {
|
||||
template.setAttribute("RegisterC", formatRegister(instruction.getRegisterC()));
|
||||
protected void writeSecondRegister(IndentingPrintWriter writer) throws IOException {
|
||||
writeRegister(writer, ((TwoRegisterInstruction)instruction).getRegisterB());
|
||||
}
|
||||
|
||||
private void setFiveRegisterAttributes(FiveRegisterInstruction instruction, StringTemplate template) {
|
||||
switch (instruction.getRegCount()) {
|
||||
protected void writeThirdRegister(IndentingPrintWriter writer) throws IOException {
|
||||
writeRegister(writer, ((ThreeRegisterInstruction)instruction).getRegisterC());
|
||||
}
|
||||
|
||||
protected void writeInvokeRegisters(IndentingPrintWriter writer) throws IOException {
|
||||
FiveRegisterInstruction instruction = (FiveRegisterInstruction)this.instruction;
|
||||
final int regCount = instruction.getRegCount();
|
||||
|
||||
writer.write('{');
|
||||
switch (regCount) {
|
||||
case 1:
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
|
||||
return;
|
||||
writeRegister(writer, instruction.getRegisterD());
|
||||
break;
|
||||
case 2:
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterE()));
|
||||
return;
|
||||
writeRegister(writer, instruction.getRegisterD());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterE());
|
||||
break;
|
||||
case 3:
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterE()));
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterF()));
|
||||
return;
|
||||
writeRegister(writer, instruction.getRegisterD());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterE());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterF());
|
||||
break;
|
||||
case 4:
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterE()));
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterF()));
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterG()));
|
||||
return;
|
||||
writeRegister(writer, instruction.getRegisterD());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterE());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterF());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterG());
|
||||
break;
|
||||
case 5:
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterD()));
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterE()));
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterF()));
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterG()));
|
||||
template.setAttribute("Registers", formatRegister(instruction.getRegisterA()));
|
||||
writeRegister(writer, instruction.getRegisterD());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterE());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterF());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterG());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterA());
|
||||
break;
|
||||
}
|
||||
writer.write('}');
|
||||
}
|
||||
|
||||
protected void writeInvokeRangeRegisters(IndentingPrintWriter writer) throws IOException {
|
||||
RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction;
|
||||
|
||||
int regCount = instruction.getRegCount();
|
||||
if (regCount == 0) {
|
||||
writer.write("{}");
|
||||
} else {
|
||||
int startRegister = instruction.getStartRegister();
|
||||
RegisterFormatter.writeRegisterRange(writer, codeItem, startRegister, startRegister+regCount-1);
|
||||
}
|
||||
}
|
||||
|
||||
private void setRegisterRangeAttributes(RegisterRangeInstruction instruction, StringTemplate template) {
|
||||
String[] registers = RegisterFormatter.formatFormat3rcRegisters(codeItem, instruction.getStartRegister(),
|
||||
instruction.getStartRegister() + instruction.getRegCount() - 1);
|
||||
|
||||
template.setAttribute("StartRegister", registers[0]);
|
||||
template.setAttribute("LastRegister", registers[1]);
|
||||
protected void writeLiteral(IndentingPrintWriter writer) throws IOException {
|
||||
LongRenderer.writeSignedIntOrLongTo(writer, ((LiteralInstruction)instruction).getLiteral());
|
||||
}
|
||||
|
||||
private void setInstructionWithReferenceAttributes(InstructionWithReference instruction, StringTemplate template) {
|
||||
template.setAttribute("Reference", Reference.createReference(template.getGroup(),
|
||||
instruction.getReferencedItem()));
|
||||
protected void writeFieldOffset(IndentingPrintWriter writer) throws IOException {
|
||||
writer.write("field@0x");
|
||||
writer.printLongAsHex(((OdexedFieldAccess)instruction).getFieldOffset());
|
||||
}
|
||||
|
||||
private void setOdexedInvokeVirtualAttributes(OdexedInvokeVirtual instruction, StringTemplate template) {
|
||||
template.setAttribute("MethodIndex", instruction.getMethodIndex());
|
||||
protected void writeVtableIndex(IndentingPrintWriter writer) throws IOException {
|
||||
writer.write("vtable@0x");
|
||||
writer.printLongAsHex(((OdexedInvokeVirtual)instruction).getMethodIndex());
|
||||
}
|
||||
|
||||
private void setOdexedFieldAccessAttributes(OdexedFieldAccess instruction, StringTemplate template) {
|
||||
template.setAttribute("FieldOffset", instruction.getFieldOffset());
|
||||
protected void writeReference(IndentingPrintWriter writer) throws IOException {
|
||||
Item item = ((InstructionWithReference)instruction).getReferencedItem();
|
||||
ReferenceFormatter.writeReference(writer, item);
|
||||
}
|
||||
}
|
||||
|
@ -28,9 +28,7 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
import org.jf.dexlib.Code.Analysis.AnalyzedInstruction;
|
||||
import org.jf.dexlib.Code.Format.*;
|
||||
import org.jf.dexlib.Code.Instruction;
|
||||
import org.jf.dexlib.Code.OffsetInstruction;
|
||||
@ -43,29 +41,28 @@ public class InstructionMethodItemFactory {
|
||||
public static InstructionMethodItem makeInstructionFormatMethodItem(MethodDefinition methodDefinition,
|
||||
CodeItem codeItem,
|
||||
int codeAddress, boolean dead,
|
||||
StringTemplateGroup stg,
|
||||
Instruction instruction,
|
||||
boolean isLastInstruction) {
|
||||
if (instruction instanceof OffsetInstruction) {
|
||||
return new OffsetInstructionFormatMethodItem(methodDefinition.getLabelCache(), codeItem, codeAddress, stg,
|
||||
return new OffsetInstructionFormatMethodItem(methodDefinition.getLabelCache(), codeItem, codeAddress,
|
||||
instruction);
|
||||
}
|
||||
|
||||
switch (instruction.getFormat()) {
|
||||
case ArrayData:
|
||||
return new ArrayDataMethodItem(codeItem, codeAddress, dead, stg,
|
||||
return new ArrayDataMethodItem(codeItem, codeAddress, dead,
|
||||
(ArrayDataPseudoInstruction)instruction);
|
||||
case PackedSwitchData:
|
||||
return new PackedSwitchMethodItem(methodDefinition, codeItem, codeAddress, dead, stg,
|
||||
return new PackedSwitchMethodItem(methodDefinition, codeItem, codeAddress, dead,
|
||||
(PackedSwitchDataPseudoInstruction)instruction);
|
||||
case SparseSwitchData:
|
||||
return new SparseSwitchMethodItem(methodDefinition, codeItem, codeAddress, dead, stg,
|
||||
return new SparseSwitchMethodItem(methodDefinition, codeItem, codeAddress, dead,
|
||||
(SparseSwitchDataPseudoInstruction)instruction);
|
||||
case UnresolvedNullReference:
|
||||
return new UnresolvedNullReferenceMethodItem(codeItem, codeAddress, stg,
|
||||
return new UnresolvedNullReferenceMethodItem(codeItem, codeAddress,
|
||||
(UnresolvedNullReference)instruction, isLastInstruction);
|
||||
default:
|
||||
return new InstructionMethodItem(codeItem, codeAddress, stg, instruction);
|
||||
return new InstructionMethodItem(codeItem, codeAddress, instruction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,31 +28,32 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.dexlib.Code.Opcode;
|
||||
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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class OffsetInstructionFormatMethodItem<T extends Instruction & OffsetInstruction>
|
||||
extends InstructionMethodItem<T> {
|
||||
protected LabelMethodItem label;
|
||||
|
||||
public OffsetInstructionFormatMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int codeAddress,
|
||||
StringTemplateGroup stg, T instruction) {
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
T instruction) {
|
||||
super(codeItem, codeAddress, instruction);
|
||||
|
||||
label = new LabelMethodItem(codeAddress + instruction.getTargetAddressOffset(), stg, getLabelPrefix());
|
||||
label = new LabelMethodItem(codeAddress + instruction.getTargetAddressOffset(), getLabelPrefix());
|
||||
label = labelCache.internLabel(label);
|
||||
label.setUncommented();
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
template.setAttribute("TargetLabel", label);
|
||||
super.setAttributes(template);
|
||||
@Override
|
||||
protected void writeTargetLabel(IndentingPrintWriter writer) throws IOException {
|
||||
label.writeTo(writer);
|
||||
}
|
||||
|
||||
public LabelMethodItem getLabel() {
|
||||
|
@ -28,13 +28,14 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.baksmali.Renderers.IntegerRenderer;
|
||||
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.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -45,8 +46,8 @@ public class PackedSwitchMethodItem extends InstructionMethodItem<PackedSwitchDa
|
||||
private final boolean dead;
|
||||
|
||||
public PackedSwitchMethodItem(MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress, boolean dead,
|
||||
StringTemplateGroup stg, PackedSwitchDataPseudoInstruction instruction) {
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
PackedSwitchDataPseudoInstruction instruction) {
|
||||
super(codeItem, codeAddress, instruction);
|
||||
|
||||
int baseCodeAddress = methodDefinition.getPackedSwitchBaseAddress(codeAddress);
|
||||
|
||||
@ -54,7 +55,7 @@ public class PackedSwitchMethodItem extends InstructionMethodItem<PackedSwitchDa
|
||||
Iterator<PackedSwitchDataPseudoInstruction.PackedSwitchTarget> iterator = instruction.iterateKeysAndTargets();
|
||||
while (iterator.hasNext()) {
|
||||
PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next();
|
||||
LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, stg, "pswitch_");
|
||||
LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "pswitch_");
|
||||
label = methodDefinition.getLabelCache().internLabel(label);
|
||||
labels.add(label);
|
||||
label.setUncommented();
|
||||
@ -63,10 +64,31 @@ public class PackedSwitchMethodItem extends InstructionMethodItem<PackedSwitchDa
|
||||
this.dead = dead;
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
template.setAttribute("FirstKey", instruction.getFirstKey());
|
||||
template.setAttribute("Targets", labels);
|
||||
template.setAttribute("Dead", dead);
|
||||
@Override
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
if (dead) {
|
||||
writer.write("'#.packed-switch ");
|
||||
IntegerRenderer.writeTo(writer, instruction.getFirstKey());
|
||||
writer.println();
|
||||
for (LabelMethodItem label: labels) {
|
||||
writer.write("# ");
|
||||
label.writeTo(writer);
|
||||
writer.println();
|
||||
}
|
||||
writer.write("#.end packed-switch");
|
||||
} else {
|
||||
writer.write(".packed-switch ");
|
||||
IntegerRenderer.writeTo(writer, instruction.getFirstKey());
|
||||
writer.indent(4);
|
||||
writer.println();
|
||||
for (LabelMethodItem label: labels) {
|
||||
label.writeTo(writer);
|
||||
writer.println();
|
||||
}
|
||||
writer.deindent(4);
|
||||
writer.write(".end packed-switch");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Iterator<LabelMethodItem> iterator() {
|
||||
|
@ -28,13 +28,14 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.baksmali.Renderers.IntegerRenderer;
|
||||
import org.jf.dexlib.Code.Format.SparseSwitchDataPseudoInstruction;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
import org.jf.baksmali.Adaptors.LabelMethodItem;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -45,8 +46,8 @@ public class SparseSwitchMethodItem extends InstructionMethodItem<SparseSwitchDa
|
||||
private final boolean dead;
|
||||
|
||||
public SparseSwitchMethodItem(MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress, boolean dead,
|
||||
StringTemplateGroup stg, SparseSwitchDataPseudoInstruction instruction) {
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
SparseSwitchDataPseudoInstruction instruction) {
|
||||
super(codeItem, codeAddress, instruction);
|
||||
|
||||
int baseCodeAddress = methodDefinition.getSparseSwitchBaseAddress(codeAddress);
|
||||
|
||||
@ -57,7 +58,7 @@ public class SparseSwitchMethodItem extends InstructionMethodItem<SparseSwitchDa
|
||||
SparseSwitchTarget sparseSwitchTarget = new SparseSwitchTarget();
|
||||
sparseSwitchTarget.Key = target.key;
|
||||
|
||||
LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, stg, "sswitch_");
|
||||
LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "sswitch_");
|
||||
label = methodDefinition.getLabelCache().internLabel(label);
|
||||
sparseSwitchTarget.Target = label;
|
||||
label.setUncommented();
|
||||
@ -68,9 +69,30 @@ public class SparseSwitchMethodItem extends InstructionMethodItem<SparseSwitchDa
|
||||
this.dead = dead;
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
template.setAttribute("Targets", targets);
|
||||
template.setAttribute("Dead", dead);
|
||||
@Override
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
if (dead) {
|
||||
writer.println("#.sparse-switch");
|
||||
for (SparseSwitchTarget target: targets) {
|
||||
IntegerRenderer.writeTo(writer, target.Key);
|
||||
writer.write(" -> ");
|
||||
target.Target.writeTo(writer);
|
||||
writer.println();
|
||||
}
|
||||
writer.write("#.end sparse-switch");
|
||||
} else {
|
||||
writer.println(".sparse-switch");
|
||||
writer.indent(4);
|
||||
for (SparseSwitchTarget target: targets) {
|
||||
IntegerRenderer.writeTo(writer, target.Key);
|
||||
writer.write(" -> ");
|
||||
target.Target.writeTo(writer);
|
||||
writer.println();
|
||||
}
|
||||
writer.deindent(4);
|
||||
writer.write(".end sparse-switch");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Iterator<LabelMethodItem> iterator() {
|
||||
|
@ -28,31 +28,51 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.dexlib.Code.Format.UnresolvedNullReference;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class UnresolvedNullReferenceMethodItem extends InstructionMethodItem<UnresolvedNullReference> {
|
||||
public final boolean isLastInstruction;
|
||||
|
||||
public UnresolvedNullReferenceMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg,
|
||||
UnresolvedNullReference instruction, boolean isLastInstruction) {
|
||||
super(codeItem, codeAddress, stg, instruction);
|
||||
public UnresolvedNullReferenceMethodItem(CodeItem codeItem, int codeAddress, UnresolvedNullReference instruction,
|
||||
boolean isLastInstruction) {
|
||||
super(codeItem, codeAddress, instruction);
|
||||
this.isLastInstruction = isLastInstruction;
|
||||
}
|
||||
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
template.setAttribute("Register", formatRegister(instruction.ObjectRegisterNum));
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
switch (instruction.OriginalInstruction.opcode)
|
||||
{
|
||||
case INVOKE_VIRTUAL_QUICK_RANGE:
|
||||
case INVOKE_SUPER_QUICK_RANGE:
|
||||
template.setAttribute("UseInvokeRange", 1);
|
||||
if (isLastInstruction) {
|
||||
template.setAttribute("AddGoto", 1);
|
||||
}
|
||||
writeInvokeRangeTo(writer);
|
||||
return true;
|
||||
default:
|
||||
writeThrowTo(writer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeInvokeRangeTo(IndentingPrintWriter writer) throws IOException {
|
||||
writer.println("#Replaced unresolvable optimized invoke-*-range-quick instruction");
|
||||
writer.println("#with a generic method call that will throw a NullPointerException");
|
||||
writer.write("invoke-virtual/range {");
|
||||
writeRegister(writer, instruction.ObjectRegisterNum);
|
||||
writer.write(" .. ");
|
||||
writeRegister(writer, instruction.ObjectRegisterNum);
|
||||
writer.write("}, Ljava/lang/Object;->hashCode()I");
|
||||
if (isLastInstruction) {
|
||||
writer.println();
|
||||
writer.write("goto/32 0");
|
||||
}
|
||||
}
|
||||
|
||||
private void writeThrowTo(IndentingPrintWriter writer) throws IOException {
|
||||
writer.println("#Replaced unresolvable optimized instruction with a throw");
|
||||
writer.write("throw ");
|
||||
writeRegister(writer, instruction.ObjectRegisterNum);
|
||||
}
|
||||
}
|
||||
|
@ -28,19 +28,16 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.baksmali.baksmali;
|
||||
|
||||
public class LabelMethodItem extends MethodItem {
|
||||
private final StringTemplateGroup stg;
|
||||
private final String labelPrefix;
|
||||
private int labelSequence;
|
||||
private boolean isCommentedOut = true;
|
||||
|
||||
public LabelMethodItem(int codeAddress, StringTemplateGroup stg, String labelPrefix) {
|
||||
public LabelMethodItem(int codeAddress, String labelPrefix) {
|
||||
super(codeAddress);
|
||||
this.stg = stg;
|
||||
this.labelPrefix = labelPrefix;
|
||||
}
|
||||
|
||||
@ -79,24 +76,24 @@ public class LabelMethodItem extends MethodItem {
|
||||
return this.compareTo((MethodItem)o) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringTemplate template = stg.getInstanceOf("Label");
|
||||
template.setAttribute("Prefix", labelPrefix);
|
||||
|
||||
public boolean writeTo(IndentingPrintWriter writer) {
|
||||
writer.write(':');
|
||||
writer.write(labelPrefix);
|
||||
if (baksmali.useSequentialLabels) {
|
||||
template.setAttribute("Suffix", Integer.toHexString(labelSequence));
|
||||
writer.printLongAsHex(labelSequence);
|
||||
} else {
|
||||
template.setAttribute("Suffix", getLabelAddress());
|
||||
writer.printLongAsHex(this.getLabelAddress());
|
||||
}
|
||||
return template.toString();
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getLabelPrefix() {
|
||||
return labelPrefix;
|
||||
}
|
||||
|
||||
public String getLabelAddress() {
|
||||
return Integer.toHexString(this.getCodeAddress());
|
||||
public int getLabelAddress() {
|
||||
return this.getCodeAddress();
|
||||
}
|
||||
|
||||
public int getLabelSequence() {
|
||||
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* 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;
|
||||
|
||||
import org.jf.dexlib.TypeIdItem;
|
||||
import org.jf.dexlib.StringIdItem;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
public class LocalDebugMethodItem extends DebugMethodItem {
|
||||
private final String register;
|
||||
private final String name;
|
||||
private final String type;
|
||||
private final String signature;
|
||||
|
||||
public LocalDebugMethodItem(CodeItem codeItem, int codeAddress, StringTemplateGroup stg, String templateName,
|
||||
double sortOrder, int register, StringIdItem name, TypeIdItem type,
|
||||
StringIdItem signature) {
|
||||
super(codeAddress, stg, templateName, sortOrder);
|
||||
this.register = RegisterFormatter.formatRegister(codeItem, register);
|
||||
this.name = name==null?null:name.getStringValue();
|
||||
this.type = type==null?null:type.getTypeDescriptor();
|
||||
this.signature = signature==null?null:signature.getStringValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
template.setAttribute("Register", register);
|
||||
template.setAttribute("Name", name);
|
||||
template.setAttribute("Type", type);
|
||||
template.setAttribute("Signature", signature);
|
||||
}
|
||||
}
|
@ -29,27 +29,24 @@
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.Adaptors.Format.*;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.baksmali.Renderers.IntegerRenderer;
|
||||
import org.jf.baksmali.baksmali;
|
||||
import org.jf.baksmali.main;
|
||||
import org.jf.dexlib.*;
|
||||
import org.jf.dexlib.Code.*;
|
||||
import org.jf.dexlib.Code.Analysis.AnalyzedInstruction;
|
||||
import org.jf.dexlib.Code.Analysis.MethodAnalyzer;
|
||||
import org.jf.dexlib.Code.Analysis.RegisterType;
|
||||
import org.jf.dexlib.Code.Analysis.ValidationException;
|
||||
import org.jf.dexlib.Code.Format.Format;
|
||||
import org.jf.dexlib.Debug.DebugInstructionIterator;
|
||||
import org.jf.dexlib.Util.AccessFlags;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.jf.dexlib.Util.ExceptionWithContext;
|
||||
import org.jf.dexlib.Util.Hex;
|
||||
import org.jf.dexlib.Util.SparseIntArray;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
git
|
||||
public class MethodDefinition {
|
||||
private final StringTemplateGroup stg;
|
||||
private final ClassDataItem.EncodedMethod encodedMethod;
|
||||
private final MethodAnalyzer methodAnalyzer;
|
||||
|
||||
@ -59,13 +56,10 @@ public class MethodDefinition {
|
||||
private final SparseIntArray sparseSwitchMap;
|
||||
private final SparseIntArray instructionMap;
|
||||
|
||||
private final int registerCount;
|
||||
|
||||
public MethodDefinition(StringTemplateGroup stg, ClassDataItem.EncodedMethod encodedMethod) {
|
||||
public MethodDefinition(ClassDataItem.EncodedMethod encodedMethod) {
|
||||
|
||||
|
||||
try {
|
||||
this.stg = stg;
|
||||
this.encodedMethod = encodedMethod;
|
||||
|
||||
//TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh.
|
||||
@ -78,8 +72,6 @@ public class MethodDefinition {
|
||||
sparseSwitchMap = new SparseIntArray(1);
|
||||
instructionMap = new SparseIntArray(instructions.size());
|
||||
|
||||
registerCount = encodedMethod.codeItem.getRegisterCount();
|
||||
|
||||
int currentCodeAddress = 0;
|
||||
for (int i=0; i<instructions.size(); i++) {
|
||||
AnalyzedInstruction instruction = instructions.get(i);
|
||||
@ -100,7 +92,6 @@ public class MethodDefinition {
|
||||
sparseSwitchMap = null;
|
||||
instructionMap = null;
|
||||
methodAnalyzer = null;
|
||||
registerCount = 0;
|
||||
}
|
||||
}catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, String.format("Error while processing method %s",
|
||||
@ -108,24 +99,42 @@ public class MethodDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
public StringTemplate createTemplate(AnnotationSetItem annotationSet,
|
||||
AnnotationSetRefList parameterAnnotations) {
|
||||
public void writeTo(IndentingPrintWriter writer, AnnotationSetItem annotationSet,
|
||||
AnnotationSetRefList parameterAnnotations) throws IOException {
|
||||
final CodeItem codeItem = encodedMethod.codeItem;
|
||||
|
||||
CodeItem codeItem = encodedMethod.codeItem;
|
||||
writer.write(".method ");
|
||||
writeAccessFlags(writer, encodedMethod);
|
||||
writer.write(encodedMethod.method.getMethodName().getStringValue());
|
||||
writer.println(encodedMethod.method.getPrototype().getPrototypeString());
|
||||
|
||||
StringTemplate template = stg.getInstanceOf("method");
|
||||
writer.indent(4);
|
||||
if (codeItem != null) {
|
||||
if (baksmali.useLocalsDirective) {
|
||||
writer.write(".locals ");
|
||||
} else {
|
||||
writer.write(".registers ");
|
||||
}
|
||||
writer.println(getRegisterCount(encodedMethod));
|
||||
writeParameters(writer, codeItem, parameterAnnotations);
|
||||
if (annotationSet != null) {
|
||||
AnnotationFormatter.writeTo(writer, annotationSet);
|
||||
}
|
||||
|
||||
template.setAttribute("AccessFlags", getAccessFlags(encodedMethod));
|
||||
template.setAttribute("MethodName", encodedMethod.method.getMethodName().getStringValue());
|
||||
template.setAttribute("Prototype", encodedMethod.method.getPrototype().getPrototypeString());
|
||||
template.setAttribute("HasCode", codeItem != null);
|
||||
template.setAttribute("RegistersDirective", baksmali.useLocalsDirective?".locals":".registers");
|
||||
template.setAttribute("RegisterCount", codeItem==null?"0":Integer.toString(getRegisterCount(encodedMethod)));
|
||||
template.setAttribute("Parameters", getParameters(stg, codeItem, parameterAnnotations));
|
||||
template.setAttribute("Annotations", getAnnotations(stg, annotationSet));
|
||||
template.setAttribute("MethodItems", getMethodItems());
|
||||
writer.println();
|
||||
|
||||
return template;
|
||||
for (MethodItem methodItem: getMethodItems()) {
|
||||
if (methodItem.writeTo(writer)) {
|
||||
writer.write('\n');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (annotationSet != null) {
|
||||
AnnotationFormatter.writeTo(writer, annotationSet);
|
||||
}
|
||||
}
|
||||
writer.deindent(4);
|
||||
writer.println(".end method");
|
||||
}
|
||||
|
||||
private static int getRegisterCount(ClassDataItem.EncodedMethod encodedMethod)
|
||||
@ -141,65 +150,70 @@ public class MethodDefinition {
|
||||
return totalRegisters;
|
||||
}
|
||||
|
||||
private static List<String> getAccessFlags(ClassDataItem.EncodedMethod encodedMethod) {
|
||||
List<String> accessFlags = new ArrayList<String>();
|
||||
|
||||
private static void writeAccessFlags(IndentingPrintWriter writer, ClassDataItem.EncodedMethod encodedMethod) {
|
||||
for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(encodedMethod.accessFlags)) {
|
||||
accessFlags.add(accessFlag.toString());
|
||||
writer.write(accessFlag.toString());
|
||||
writer.write(' ');
|
||||
}
|
||||
|
||||
return accessFlags;
|
||||
}
|
||||
|
||||
private static List<StringTemplate> getParameters(StringTemplateGroup stg, CodeItem codeItem,
|
||||
AnnotationSetRefList parameterAnnotations) {
|
||||
private static void writeParameters(IndentingPrintWriter writer, CodeItem codeItem,
|
||||
AnnotationSetRefList parameterAnnotations) throws IOException {
|
||||
DebugInfoItem debugInfoItem = null;
|
||||
if (baksmali.outputDebugInfo && codeItem != null) {
|
||||
debugInfoItem = codeItem.getDebugInfo();
|
||||
}
|
||||
|
||||
int parameterCount = 0;
|
||||
AnnotationSetItem[] annotations;
|
||||
StringIdItem[] parameterNames = null;
|
||||
|
||||
List<AnnotationSetItem> annotations = new ArrayList<AnnotationSetItem>();
|
||||
if (parameterAnnotations != null) {
|
||||
AnnotationSetItem[] _annotations = parameterAnnotations.getAnnotationSets();
|
||||
if (_annotations != null) {
|
||||
annotations.addAll(Arrays.asList(_annotations));
|
||||
}
|
||||
|
||||
parameterCount = annotations.size();
|
||||
annotations = parameterAnnotations.getAnnotationSets();
|
||||
parameterCount = annotations.length;
|
||||
} else {
|
||||
annotations = new AnnotationSetItem[0];
|
||||
}
|
||||
|
||||
List<String> parameterNames = new ArrayList<String>();
|
||||
if (debugInfoItem != null) {
|
||||
StringIdItem[] _parameterNames = debugInfoItem.getParameterNames();
|
||||
if (_parameterNames != null) {
|
||||
for (StringIdItem parameterName: _parameterNames) {
|
||||
parameterNames.add(parameterName==null?null:parameterName.getStringValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (parameterCount < parameterNames.size()) {
|
||||
parameterCount = parameterNames.size();
|
||||
}
|
||||
parameterNames = debugInfoItem.getParameterNames();
|
||||
}
|
||||
if (parameterNames == null) {
|
||||
parameterNames = new StringIdItem[0];
|
||||
}
|
||||
|
||||
if (parameterCount < parameterNames.length) {
|
||||
parameterCount = parameterNames.length;
|
||||
}
|
||||
|
||||
List<StringTemplate> parameters = new ArrayList<StringTemplate>();
|
||||
for (int i=0; i<parameterCount; i++) {
|
||||
AnnotationSetItem annotationSet = null;
|
||||
if (i < annotations.size()) {
|
||||
annotationSet = annotations.get(i);
|
||||
if (i < annotations.length) {
|
||||
annotationSet = annotations[i];
|
||||
}
|
||||
|
||||
String parameterName = null;
|
||||
if (i < parameterNames.size()) {
|
||||
parameterName = parameterNames.get(i);
|
||||
StringIdItem parameterName = null;
|
||||
if (i < parameterNames.length) {
|
||||
parameterName = parameterNames[i];
|
||||
}
|
||||
|
||||
parameters.add(ParameterAdaptor.createTemplate(stg, parameterName, annotationSet));
|
||||
writer.write(".parameter");
|
||||
|
||||
if (parameterName != null) {
|
||||
writer.write('"');
|
||||
writer.write(parameterName.getStringValue());
|
||||
writer.write('"');
|
||||
}
|
||||
|
||||
writer.println();
|
||||
if (annotationSet != null) {
|
||||
writer.indent(4);
|
||||
AnnotationFormatter.writeTo(writer, annotationSet);
|
||||
writer.deindent(4);
|
||||
|
||||
writer.println(".end parameter");
|
||||
}
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public LabelCache getLabelCache() {
|
||||
@ -236,19 +250,6 @@ public class MethodDefinition {
|
||||
return sparseSwitchBaseAddress;
|
||||
}
|
||||
|
||||
private static List<StringTemplate> getAnnotations(StringTemplateGroup stg, AnnotationSetItem annotationSet) {
|
||||
if (annotationSet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<StringTemplate> annotationAdaptors = new ArrayList<StringTemplate>();
|
||||
|
||||
for (AnnotationItem annotationItem: annotationSet.getAnnotations()) {
|
||||
annotationAdaptors.add(AnnotationAdaptor.createTemplate(stg, annotationItem));
|
||||
}
|
||||
return annotationAdaptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param instructions The instructions array for this method
|
||||
* @param instruction The instruction
|
||||
@ -285,7 +286,7 @@ public class MethodDefinition {
|
||||
|
||||
ValidationException validationException = methodAnalyzer.getValidationException();
|
||||
if (validationException != null) {
|
||||
methodItems.add(new CommentMethodItem(stg,
|
||||
methodItems.add(new CommentMethodItem(
|
||||
String.format("ValidationException: %s" ,validationException.getMessage()),
|
||||
validationException.getCodeAddress(), Integer.MIN_VALUE));
|
||||
} else if (baksmali.verify) {
|
||||
@ -293,7 +294,7 @@ public class MethodDefinition {
|
||||
|
||||
validationException = methodAnalyzer.getValidationException();
|
||||
if (validationException != null) {
|
||||
methodItems.add(new CommentMethodItem(stg,
|
||||
methodItems.add(new CommentMethodItem(
|
||||
String.format("ValidationException: %s" ,validationException.getMessage()),
|
||||
validationException.getCodeAddress(), Integer.MIN_VALUE));
|
||||
}
|
||||
@ -312,9 +313,6 @@ public class MethodDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
BitSet printPreRegister = new BitSet(registerCount);
|
||||
BitSet printPostRegister = new BitSet(registerCount);
|
||||
|
||||
boolean lastIsUnreachable = false;
|
||||
|
||||
int currentCodeAddress = 0;
|
||||
@ -322,24 +320,22 @@ public class MethodDefinition {
|
||||
AnalyzedInstruction instruction = instructions.get(i);
|
||||
|
||||
MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this,
|
||||
encodedMethod.codeItem, currentCodeAddress, instruction.isDead(), stg, instruction.getInstruction(),
|
||||
encodedMethod.codeItem, currentCodeAddress, instruction.isDead(), instruction.getInstruction(),
|
||||
instruction == lastInstruction);
|
||||
|
||||
boolean addedInstruction = false;
|
||||
if (instruction.isDead() && !instruction.getInstruction().getFormat().variableSizeFormat) {
|
||||
methodItems.add(new CommentedOutMethodItem(stg, methodItem));
|
||||
methodItems.add(new CommentedOutMethodItem(methodItem));
|
||||
lastIsUnreachable = false;
|
||||
addedInstruction = true;
|
||||
} else if ( instruction.getPredecessorCount() == 0 &&
|
||||
!instruction.getInstruction().getFormat().variableSizeFormat &&
|
||||
!isInstructionPaddingNop(instructions, instruction)) {
|
||||
|
||||
if (!lastIsUnreachable) {
|
||||
methodItems.add(
|
||||
new CommentMethodItem(stg, "Unreachable code", currentCodeAddress, Double.MIN_VALUE));
|
||||
new CommentMethodItem("Unreachable code", currentCodeAddress, Double.MIN_VALUE));
|
||||
}
|
||||
|
||||
methodItems.add(new CommentedOutMethodItem(stg, methodItem));
|
||||
methodItems.add(new CommentedOutMethodItem(methodItem));
|
||||
lastIsUnreachable = true;
|
||||
} else {
|
||||
methodItems.add(methodItem);
|
||||
@ -347,67 +343,39 @@ public class MethodDefinition {
|
||||
}
|
||||
|
||||
if (instruction.getInstruction().getFormat() == Format.UnresolvedNullReference) {
|
||||
methodItems.add(new CommentedOutMethodItem(stg,
|
||||
methodItems.add(new CommentedOutMethodItem(
|
||||
InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, encodedMethod.codeItem,
|
||||
currentCodeAddress, instruction.isDead(), stg, instruction.getOriginalInstruction(),
|
||||
currentCodeAddress, instruction.isDead(), instruction.getOriginalInstruction(),
|
||||
false)));
|
||||
}
|
||||
|
||||
if (i != instructions.size() - 1) {
|
||||
methodItems.add(new BlankMethodItem(stg, currentCodeAddress));
|
||||
methodItems.add(new BlankMethodItem(currentCodeAddress));
|
||||
}
|
||||
|
||||
if (baksmali.addCodeOffsets) {
|
||||
methodItems.add(new CommentMethodItem(stg, String.format("@%x", currentCodeAddress),
|
||||
currentCodeAddress, -1000));
|
||||
methodItems.add(new MethodItem(currentCodeAddress) {
|
||||
|
||||
@Override
|
||||
public double getSortOrder() {
|
||||
return -1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
writer.write("#@");
|
||||
IntegerRenderer.writeUnsignedTo(writer, codeAddress);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (baksmali.registerInfo != 0 && !instruction.getInstruction().getFormat().variableSizeFormat) {
|
||||
printPreRegister.clear();
|
||||
printPostRegister.clear();
|
||||
methodItems.add(
|
||||
new PreInstructionRegisterInfoMethodItem(instruction, methodAnalyzer, currentCodeAddress));
|
||||
|
||||
if ((baksmali.registerInfo & main.ALL) != 0) {
|
||||
printPreRegister.set(0, registerCount);
|
||||
printPostRegister.set(0, registerCount);
|
||||
} else {
|
||||
if ((baksmali.registerInfo & main.ALLPRE) != 0) {
|
||||
printPreRegister.set(0, registerCount);
|
||||
} else {
|
||||
if ((baksmali.registerInfo & main.ARGS) != 0) {
|
||||
addArgsRegs(printPreRegister, instruction);
|
||||
}
|
||||
if ((baksmali.registerInfo & main.MERGE) != 0) {
|
||||
addMergeRegs(printPreRegister, instruction);
|
||||
} else if ((baksmali.registerInfo & main.FULLMERGE) != 0 &&
|
||||
(i == 0 || instruction.isBeginningInstruction())) {
|
||||
addParamRegs(printPreRegister);
|
||||
}
|
||||
}
|
||||
|
||||
if ((baksmali.registerInfo & main.ALLPOST) != 0) {
|
||||
printPostRegister.set(0, registerCount);
|
||||
} else if ((baksmali.registerInfo & main.DEST) != 0) {
|
||||
addDestRegs(printPostRegister, instruction);
|
||||
}
|
||||
}
|
||||
|
||||
if ((baksmali.registerInfo & main.FULLMERGE) != 0) {
|
||||
addFullMergeRegs(printPreRegister, methodItems, methodAnalyzer, instruction, currentCodeAddress);
|
||||
}
|
||||
|
||||
if (!printPreRegister.isEmpty()) {
|
||||
String comment = getPreInstructionRegisterString(instruction, printPreRegister);
|
||||
if (comment != null && comment.length() > 0) {
|
||||
methodItems.add(new CommentMethodItem(stg, comment, currentCodeAddress, 99.9));
|
||||
}
|
||||
}
|
||||
|
||||
if (!printPostRegister.isEmpty()) {
|
||||
String comment = getPostInstructionRegisterString(instruction, printPostRegister);
|
||||
if (comment != null && comment.length() > 0) {
|
||||
methodItems.add(new CommentMethodItem(stg, comment, currentCodeAddress, 100.1));
|
||||
}
|
||||
}
|
||||
methodItems.add(
|
||||
new PostInstructionRegisterInfoMethodItem(instruction, methodAnalyzer, currentCodeAddress));
|
||||
}
|
||||
|
||||
currentCodeAddress += instruction.getInstruction().getSize(currentCodeAddress);
|
||||
@ -423,7 +391,7 @@ public class MethodDefinition {
|
||||
|
||||
for (LabelMethodItem labelMethodItem: labelCache.getLabels()) {
|
||||
if (labelMethodItem.isCommentedOut()) {
|
||||
methodItems.add(new CommentedOutMethodItem(stg, labelMethodItem));
|
||||
methodItems.add(new CommentedOutMethodItem(labelMethodItem));
|
||||
} else {
|
||||
methodItems.add(labelMethodItem);
|
||||
}
|
||||
@ -434,188 +402,6 @@ public class MethodDefinition {
|
||||
return methodItems;
|
||||
}
|
||||
|
||||
private void addArgsRegs(BitSet printPreRegister, AnalyzedInstruction analyzedInstruction) {
|
||||
if (analyzedInstruction.getInstruction() instanceof RegisterRangeInstruction) {
|
||||
RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.getInstruction();
|
||||
|
||||
printPreRegister.set(instruction.getStartRegister(),
|
||||
instruction.getStartRegister() + instruction.getRegCount());
|
||||
} else if (analyzedInstruction.getInstruction() instanceof FiveRegisterInstruction) {
|
||||
FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
int regCount = instruction.getRegCount();
|
||||
switch (regCount) {
|
||||
case 5:
|
||||
printPreRegister.set(instruction.getRegisterA());
|
||||
//fall through
|
||||
case 4:
|
||||
printPreRegister.set(instruction.getRegisterG());
|
||||
//fall through
|
||||
case 3:
|
||||
printPreRegister.set(instruction.getRegisterF());
|
||||
//fall through
|
||||
case 2:
|
||||
printPreRegister.set(instruction.getRegisterE());
|
||||
//fall through
|
||||
case 1:
|
||||
printPreRegister.set(instruction.getRegisterD());
|
||||
}
|
||||
} else if (analyzedInstruction.getInstruction() instanceof ThreeRegisterInstruction) {
|
||||
ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
printPreRegister.set(instruction.getRegisterA());
|
||||
printPreRegister.set(instruction.getRegisterB());
|
||||
printPreRegister.set(instruction.getRegisterC());
|
||||
} else if (analyzedInstruction.getInstruction() instanceof TwoRegisterInstruction) {
|
||||
TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
printPreRegister.set(instruction.getRegisterA());
|
||||
printPreRegister.set(instruction.getRegisterB());
|
||||
} else if (analyzedInstruction.getInstruction() instanceof SingleRegisterInstruction) {
|
||||
SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
printPreRegister.set(instruction.getRegisterA());
|
||||
}
|
||||
}
|
||||
|
||||
private void addFullMergeRegs(BitSet printPreRegister, List<MethodItem> methodItems, MethodAnalyzer methodAnalyzer,
|
||||
AnalyzedInstruction instruction, int currentCodeAddress) {
|
||||
if (instruction.getPredecessorCount() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
for (int registerNum=0; registerNum<registerCount; registerNum++) {
|
||||
sb.setLength(0);
|
||||
sb.append(RegisterFormatter.formatRegister(encodedMethod.codeItem, registerNum));
|
||||
sb.append('=');
|
||||
sb.append(instruction.getPreInstructionRegisterType(registerNum));
|
||||
sb.append(":merge{");
|
||||
|
||||
RegisterType mergedRegisterType = null;
|
||||
boolean addRegister = false;
|
||||
|
||||
boolean first = true;
|
||||
for (AnalyzedInstruction predecessor: instruction.getPredecessors()) {
|
||||
RegisterType predecessorRegisterType = predecessor.getPostInstructionRegisterType(registerNum);
|
||||
|
||||
if (!first) {
|
||||
if (!addRegister) {
|
||||
sb.append(',');
|
||||
if (mergedRegisterType != predecessorRegisterType) {
|
||||
addRegister = true;
|
||||
}
|
||||
mergedRegisterType = mergedRegisterType.merge(predecessorRegisterType);
|
||||
}
|
||||
} else {
|
||||
mergedRegisterType = predecessorRegisterType;
|
||||
}
|
||||
|
||||
if (predecessor.getInstructionIndex() == -1) {
|
||||
//the fake "StartOfMethod" instruction
|
||||
sb.append("Start:");
|
||||
} else {
|
||||
sb.append("0x");
|
||||
sb.append(Integer.toHexString(methodAnalyzer.getInstructionAddress(predecessor)));
|
||||
sb.append(':');
|
||||
}
|
||||
sb.append(predecessorRegisterType.toString());
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (!addRegister) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sb.append("}");
|
||||
|
||||
methodItems.add(new CommentMethodItem(stg, sb.toString(), currentCodeAddress, 99.8));
|
||||
printPreRegister.clear(registerNum);
|
||||
}
|
||||
}
|
||||
|
||||
private void addMergeRegs(BitSet printPreRegister, AnalyzedInstruction instruction) {
|
||||
if (instruction.isBeginningInstruction()) {
|
||||
addParamRegs(printPreRegister);
|
||||
}
|
||||
|
||||
if (instruction.getPredecessorCount() <= 1) {
|
||||
//in the common case of an instruction that only has a single predecessor which is the previous
|
||||
//instruction, the pre-instruction registers will always match the previous instruction's
|
||||
//post-instruction registers
|
||||
return;
|
||||
}
|
||||
|
||||
for (int registerNum=0; registerNum<registerCount; registerNum++) {
|
||||
RegisterType mergedRegisterType = instruction.getPreInstructionRegisterType(registerNum);
|
||||
|
||||
for (AnalyzedInstruction predecessor: instruction.getPredecessors()) {
|
||||
if (predecessor.getPostInstructionRegisterType(registerNum) != mergedRegisterType) {
|
||||
printPreRegister.set(registerNum);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addParamRegs(BitSet printPreRegister) {
|
||||
int registerCount = encodedMethod.codeItem.getRegisterCount();
|
||||
|
||||
int parameterRegisterCount = encodedMethod.method.getPrototype().getParameterRegisterCount();
|
||||
if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) {
|
||||
parameterRegisterCount++;
|
||||
}
|
||||
|
||||
printPreRegister.set(registerCount-parameterRegisterCount, registerCount);
|
||||
}
|
||||
|
||||
private void addDestRegs(BitSet printPostRegister, AnalyzedInstruction analyzedInstruction) {
|
||||
for (int registerNum=0; registerNum<registerCount; registerNum++) {
|
||||
if (analyzedInstruction.getPreInstructionRegisterType(registerNum) !=
|
||||
analyzedInstruction.getPostInstructionRegisterType(registerNum)) {
|
||||
printPostRegister.set(registerNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String getPreInstructionRegisterString(AnalyzedInstruction instruction, BitSet registers) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int registerNum = registers.nextSetBit(0); registerNum >= 0;
|
||||
registerNum = registers.nextSetBit(registerNum + 1)) {
|
||||
|
||||
RegisterType registerType = instruction.getPreInstructionRegisterType(registerNum);
|
||||
sb.append(RegisterFormatter.formatRegister(encodedMethod.codeItem,registerNum));
|
||||
sb.append("=");
|
||||
if (registerType == null) {
|
||||
sb.append("null");
|
||||
} else {
|
||||
sb.append(registerType.toString());
|
||||
}
|
||||
sb.append(";");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getPostInstructionRegisterString(AnalyzedInstruction instruction, BitSet registers) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int registerNum = registers.nextSetBit(0); registerNum >= 0;
|
||||
registerNum = registers.nextSetBit(registerNum + 1)) {
|
||||
|
||||
RegisterType registerType = instruction.getPostInstructionRegisterType(registerNum);
|
||||
sb.append(RegisterFormatter.formatRegister(encodedMethod.codeItem,registerNum));
|
||||
sb.append("=");
|
||||
if (registerType == null) {
|
||||
sb.append("null");
|
||||
} else {
|
||||
sb.append(registerType.toString());
|
||||
}
|
||||
sb.append(";");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void addTries(List<MethodItem> methodItems) {
|
||||
if (encodedMethod.codeItem == null || encodedMethod.codeItem.getTries() == null) {
|
||||
return;
|
||||
@ -667,7 +453,7 @@ public class MethodDefinition {
|
||||
//add the catch all handler if it exists
|
||||
int catchAllAddress = tryItem.encodedCatchHandler.getCatchAllHandlerAddress();
|
||||
if (catchAllAddress != -1) {
|
||||
CatchMethodItem catchAllMethodItem = new CatchMethodItem(labelCache, lastInstructionAddress, stg, null,
|
||||
CatchMethodItem catchAllMethodItem = new CatchMethodItem(labelCache, lastInstructionAddress, null,
|
||||
startAddress, endAddress, catchAllAddress);
|
||||
methodItems.add(catchAllMethodItem);
|
||||
}
|
||||
@ -675,7 +461,7 @@ public class MethodDefinition {
|
||||
//add the rest of the handlers
|
||||
for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) {
|
||||
//use the address from the last covered instruction
|
||||
CatchMethodItem catchMethodItem = new CatchMethodItem(labelCache, lastInstructionAddress, stg,
|
||||
CatchMethodItem catchMethodItem = new CatchMethodItem(labelCache, lastInstructionAddress,
|
||||
handler.exceptionType, startAddress, endAddress, handler.getHandlerAddress());
|
||||
methodItems.add(catchMethodItem);
|
||||
}
|
||||
@ -693,61 +479,97 @@ public class MethodDefinition {
|
||||
DebugInstructionIterator.DecodeInstructions(debugInfoItem, codeItem.getRegisterCount(),
|
||||
new DebugInstructionIterator.ProcessDecodedDebugInstructionDelegate() {
|
||||
@Override
|
||||
public void ProcessStartLocal(int codeAddress, int length, int registerNum, StringIdItem name,
|
||||
TypeIdItem type) {
|
||||
methodItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "StartLocal",
|
||||
-1, registerNum, name, type, null));
|
||||
public void ProcessStartLocal(final int codeAddress, final int length, final int registerNum,
|
||||
final StringIdItem name, final TypeIdItem type) {
|
||||
methodItems.add(new DebugMethodItem(codeAddress, -1) {
|
||||
@Override
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
writeStartLocal(writer, codeItem, registerNum, name, type, null);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessStartLocalExtended(int codeAddress, int length, int registerNum,
|
||||
StringIdItem name, TypeIdItem type,
|
||||
StringIdItem signature) {
|
||||
methodItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "StartLocal",
|
||||
-1, registerNum, name, type, signature));
|
||||
public void ProcessStartLocalExtended(final int codeAddress, final int length,
|
||||
final int registerNum, final StringIdItem name,
|
||||
final TypeIdItem type, final StringIdItem signature) {
|
||||
methodItems.add(new DebugMethodItem(codeAddress, -1) {
|
||||
@Override
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
writeStartLocal(writer, codeItem, registerNum, name, type, signature);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessEndLocal(int codeAddress, int length, int registerNum, StringIdItem name,
|
||||
TypeIdItem type, StringIdItem signature) {
|
||||
methodItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "EndLocal", -1,
|
||||
registerNum, name, type, signature));
|
||||
public void ProcessEndLocal(final int codeAddress, final int length, final int registerNum,
|
||||
final StringIdItem name, final TypeIdItem type,
|
||||
final StringIdItem signature) {
|
||||
methodItems.add(new DebugMethodItem(codeAddress, -1) {
|
||||
@Override
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
writeEndLocal(writer, codeItem, registerNum, name, type, signature);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessRestartLocal(int codeAddress, int length, int registerNum, StringIdItem name,
|
||||
TypeIdItem type, StringIdItem signature) {
|
||||
methodItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "RestartLocal", -1,
|
||||
registerNum, name, type, signature));
|
||||
public void ProcessRestartLocal(final int codeAddress, final int length, final int registerNum,
|
||||
final StringIdItem name, final TypeIdItem type,
|
||||
final StringIdItem signature) {
|
||||
methodItems.add(new DebugMethodItem(codeAddress, -1) {
|
||||
@Override
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
writeRestartLocal(writer, codeItem, registerNum, name, type, signature);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessSetPrologueEnd(int codeAddress) {
|
||||
methodItems.add(new DebugMethodItem(codeAddress, stg, "EndPrologue", -4));
|
||||
methodItems.add(new DebugMethodItem(codeAddress, -4) {
|
||||
@Override
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
writeEndPrologue(writer);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessSetEpilogueBegin(int codeAddress) {
|
||||
methodItems.add(new DebugMethodItem(codeAddress, stg, "StartEpilogue", -4));
|
||||
methodItems.add(new DebugMethodItem(codeAddress, -4) {
|
||||
@Override
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
writeBeginEpilogue(writer);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessSetFile(int codeAddress, int length, final StringIdItem name) {
|
||||
methodItems.add(new DebugMethodItem(codeAddress, stg, "SetFile", -3) {
|
||||
methodItems.add(new DebugMethodItem(codeAddress, -3) {
|
||||
@Override
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
template.setAttribute("FileName", name.getStringValue());
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
writeSetFile(writer, name.getStringValue());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ProcessLineEmit(int codeAddress, final int line) {
|
||||
methodItems.add(new DebugMethodItem(codeAddress, stg, "Line", -2) {
|
||||
@Override
|
||||
protected void setAttributes(StringTemplate template) {
|
||||
template.setAttribute("Line", line);
|
||||
}
|
||||
methodItems.add(new DebugMethodItem(codeAddress, -2) {
|
||||
@Override
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
writeLine(writer, line);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -28,6 +28,10 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class MethodItem implements Comparable<MethodItem> {
|
||||
protected final int codeAddress;
|
||||
|
||||
@ -50,4 +54,6 @@ public abstract class MethodItem implements Comparable<MethodItem> {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public abstract boolean writeTo(IndentingPrintWriter writer) throws IOException;
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* 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;
|
||||
|
||||
import org.jf.dexlib.AnnotationSetItem;
|
||||
import org.jf.dexlib.AnnotationItem;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ParameterAdaptor {
|
||||
public static StringTemplate createTemplate(StringTemplateGroup stg, String parameterName,
|
||||
AnnotationSetItem parameterAnnotations) {
|
||||
StringTemplate template = stg.getInstanceOf("Parameter");
|
||||
|
||||
template.setAttribute("ParameterName", parameterName);
|
||||
template.setAttribute("Annotations", getAnnotations(stg, parameterAnnotations));
|
||||
return template;
|
||||
}
|
||||
|
||||
private static List<StringTemplate> getAnnotations(StringTemplateGroup stg,
|
||||
AnnotationSetItem parameterAnnotations) {
|
||||
if (parameterAnnotations == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<StringTemplate> annotations = new ArrayList<StringTemplate>();
|
||||
for (AnnotationItem annotationItem: parameterAnnotations.getAnnotations()) {
|
||||
annotations.add(AnnotationAdaptor.createTemplate(stg, annotationItem));
|
||||
}
|
||||
return annotations;
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 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;
|
||||
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.baksmali.baksmali;
|
||||
import org.jf.baksmali.main;
|
||||
import org.jf.dexlib.ClassDataItem;
|
||||
import org.jf.dexlib.Code.Analysis.AnalyzedInstruction;
|
||||
import org.jf.dexlib.Code.Analysis.MethodAnalyzer;
|
||||
import org.jf.dexlib.Code.Analysis.RegisterType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.BitSet;
|
||||
|
||||
public class PostInstructionRegisterInfoMethodItem extends MethodItem {
|
||||
private final AnalyzedInstruction analyzedInstruction;
|
||||
private final MethodAnalyzer methodAnalyzer;
|
||||
|
||||
public PostInstructionRegisterInfoMethodItem(AnalyzedInstruction analyzedInstruction, MethodAnalyzer methodAnalyzer,
|
||||
int codeAddress) {
|
||||
super(codeAddress);
|
||||
this.analyzedInstruction = analyzedInstruction;
|
||||
this.methodAnalyzer = methodAnalyzer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getSortOrder() {
|
||||
return 100.1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
int registerInfo = baksmali.registerInfo;
|
||||
int registerCount = analyzedInstruction.getRegisterCount();
|
||||
BitSet registers = new BitSet(registerCount);
|
||||
|
||||
if ((registerInfo & main.ALL) != 0) {
|
||||
registers.set(0, registerCount);
|
||||
} else {
|
||||
if ((registerInfo & main.ALLPOST) != 0) {
|
||||
registers.set(0, registerCount);
|
||||
} else if ((registerInfo & main.DEST) != 0) {
|
||||
addDestRegs(registers, registerCount);
|
||||
}
|
||||
}
|
||||
|
||||
return writeRegisterInfo(writer, registers);
|
||||
}
|
||||
|
||||
private void addDestRegs(BitSet printPostRegister, int registerCount) {
|
||||
for (int registerNum=0; registerNum<registerCount; registerNum++) {
|
||||
if (analyzedInstruction.getPreInstructionRegisterType(registerNum) !=
|
||||
analyzedInstruction.getPostInstructionRegisterType(registerNum)) {
|
||||
printPostRegister.set(registerNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean writeRegisterInfo(IndentingPrintWriter writer, BitSet registers) throws IOException {
|
||||
ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod();
|
||||
|
||||
int registerNum = registers.nextSetBit(0);
|
||||
if (registerNum < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
writer.write('#');
|
||||
for (; registerNum >= 0; registerNum = registers.nextSetBit(registerNum + 1)) {
|
||||
|
||||
RegisterType registerType = analyzedInstruction.getPostInstructionRegisterType(registerNum);
|
||||
|
||||
RegisterFormatter.writeTo(writer, encodedMethod.codeItem, registerNum);
|
||||
writer.write('=');
|
||||
|
||||
if (registerType == null) {
|
||||
writer.write("null");
|
||||
} else {
|
||||
registerType.writeTo(writer);
|
||||
}
|
||||
writer.write(';');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 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;
|
||||
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.baksmali.baksmali;
|
||||
import org.jf.baksmali.main;
|
||||
import org.jf.dexlib.ClassDataItem;
|
||||
import org.jf.dexlib.Code.*;
|
||||
import org.jf.dexlib.Code.Analysis.AnalyzedInstruction;
|
||||
import org.jf.dexlib.Code.Analysis.MethodAnalyzer;
|
||||
import org.jf.dexlib.Code.Analysis.RegisterType;
|
||||
import org.jf.dexlib.Util.AccessFlags;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.BitSet;
|
||||
|
||||
public class PreInstructionRegisterInfoMethodItem extends MethodItem {
|
||||
private final AnalyzedInstruction analyzedInstruction;
|
||||
private final MethodAnalyzer methodAnalyzer;
|
||||
|
||||
public PreInstructionRegisterInfoMethodItem(AnalyzedInstruction analyzedInstruction, MethodAnalyzer methodAnalyzer,
|
||||
int codeAddress) {
|
||||
super(codeAddress);
|
||||
this.analyzedInstruction = analyzedInstruction;
|
||||
this.methodAnalyzer = methodAnalyzer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getSortOrder() {
|
||||
return 99.9;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingPrintWriter writer) throws IOException {
|
||||
int registerInfo = baksmali.registerInfo;
|
||||
int registerCount = analyzedInstruction.getRegisterCount();
|
||||
BitSet registers = new BitSet(registerCount);
|
||||
|
||||
if ((registerInfo & main.ALL) != 0) {
|
||||
registers.set(0, registerCount);
|
||||
} else {
|
||||
if ((registerInfo & main.ALLPRE) != 0) {
|
||||
registers.set(0, registerCount);
|
||||
} else {
|
||||
if ((registerInfo & main.ARGS) != 0) {
|
||||
addArgsRegs(registers);
|
||||
}
|
||||
if ((registerInfo & main.MERGE) != 0) {
|
||||
addMergeRegs(registers, registerCount);
|
||||
} else if ((registerInfo & main.FULLMERGE) != 0 &&
|
||||
(analyzedInstruction.isBeginningInstruction())) {
|
||||
addParamRegs(registers, registerCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean printedSomething = false;
|
||||
if ((registerInfo & main.FULLMERGE) != 0) {
|
||||
printedSomething = writeFullMergeRegs(writer, registers, registerCount);
|
||||
}
|
||||
|
||||
printedSomething |= writeRegisterInfo(writer, registers, printedSomething);
|
||||
|
||||
return printedSomething;
|
||||
}
|
||||
|
||||
private void addArgsRegs(BitSet registers) {
|
||||
if (analyzedInstruction.getInstruction() instanceof RegisterRangeInstruction) {
|
||||
RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.getInstruction();
|
||||
|
||||
registers.set(instruction.getStartRegister(),
|
||||
instruction.getStartRegister() + instruction.getRegCount());
|
||||
} else if (analyzedInstruction.getInstruction() instanceof FiveRegisterInstruction) {
|
||||
FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
int regCount = instruction.getRegCount();
|
||||
switch (regCount) {
|
||||
case 5:
|
||||
registers.set(instruction.getRegisterA());
|
||||
//fall through
|
||||
case 4:
|
||||
registers.set(instruction.getRegisterG());
|
||||
//fall through
|
||||
case 3:
|
||||
registers.set(instruction.getRegisterF());
|
||||
//fall through
|
||||
case 2:
|
||||
registers.set(instruction.getRegisterE());
|
||||
//fall through
|
||||
case 1:
|
||||
registers.set(instruction.getRegisterD());
|
||||
}
|
||||
} else if (analyzedInstruction.getInstruction() instanceof ThreeRegisterInstruction) {
|
||||
ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
registers.set(instruction.getRegisterA());
|
||||
registers.set(instruction.getRegisterB());
|
||||
registers.set(instruction.getRegisterC());
|
||||
} else if (analyzedInstruction.getInstruction() instanceof TwoRegisterInstruction) {
|
||||
TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
registers.set(instruction.getRegisterA());
|
||||
registers.set(instruction.getRegisterB());
|
||||
} else if (analyzedInstruction.getInstruction() instanceof SingleRegisterInstruction) {
|
||||
SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
registers.set(instruction.getRegisterA());
|
||||
}
|
||||
}
|
||||
|
||||
private void addMergeRegs(BitSet registers, int registerCount) {
|
||||
if (analyzedInstruction.isBeginningInstruction()) {
|
||||
addParamRegs(registers, registerCount);
|
||||
}
|
||||
|
||||
if (analyzedInstruction.getPredecessorCount() <= 1) {
|
||||
//in the common case of an instruction that only has a single predecessor which is the previous
|
||||
//instruction, the pre-instruction registers will always match the previous instruction's
|
||||
//post-instruction registers
|
||||
return;
|
||||
}
|
||||
|
||||
for (int registerNum=0; registerNum<registerCount; registerNum++) {
|
||||
RegisterType mergedRegisterType = analyzedInstruction.getPreInstructionRegisterType(registerNum);
|
||||
|
||||
for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) {
|
||||
if (predecessor.getPostInstructionRegisterType(registerNum) != mergedRegisterType) {
|
||||
registers.set(registerNum);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addParamRegs(BitSet registers, int registerCount) {
|
||||
ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod();
|
||||
int parameterRegisterCount = encodedMethod.method.getPrototype().getParameterRegisterCount();
|
||||
if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) {
|
||||
parameterRegisterCount++;
|
||||
}
|
||||
|
||||
registers.set(registerCount-parameterRegisterCount, registerCount);
|
||||
}
|
||||
|
||||
private boolean writeFullMergeRegs(IndentingPrintWriter writer, BitSet registers, int registerCount)
|
||||
throws IOException {
|
||||
if (analyzedInstruction.getPredecessorCount() <= 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod();
|
||||
|
||||
boolean firstRegister = true;
|
||||
|
||||
for (int registerNum=0; registerNum<registerCount; registerNum++) {
|
||||
RegisterType mergedRegisterType = analyzedInstruction.getPreInstructionRegisterType(registerNum);
|
||||
boolean addRegister = false;
|
||||
|
||||
for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) {
|
||||
RegisterType predecessorRegisterType = predecessor.getPostInstructionRegisterType(registerNum);
|
||||
if (predecessorRegisterType.category != RegisterType.Category.Unknown &&
|
||||
predecessorRegisterType != mergedRegisterType) {
|
||||
|
||||
addRegister = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!addRegister) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (firstRegister) {
|
||||
firstRegister = false;
|
||||
} else {
|
||||
writer.println();
|
||||
}
|
||||
|
||||
writer.write('#');
|
||||
RegisterFormatter.writeTo(writer, encodedMethod.codeItem, registerNum);
|
||||
writer.write('=');
|
||||
analyzedInstruction.getPreInstructionRegisterType(registerNum).writeTo(writer);
|
||||
writer.write(":merge{");
|
||||
|
||||
boolean first = true;
|
||||
|
||||
for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) {
|
||||
RegisterType predecessorRegisterType = predecessor.getPostInstructionRegisterType(registerNum);
|
||||
|
||||
if (!first) {
|
||||
writer.write(',');
|
||||
}
|
||||
|
||||
if (predecessor.getInstructionIndex() == -1) {
|
||||
//the fake "StartOfMethod" instruction
|
||||
writer.write("Start:");
|
||||
} else {
|
||||
writer.write("0x");
|
||||
writer.printLongAsHex(methodAnalyzer.getInstructionAddress(predecessor));
|
||||
writer.write(':');
|
||||
}
|
||||
predecessorRegisterType.writeTo(writer);
|
||||
|
||||
first = false;
|
||||
}
|
||||
writer.write('}');
|
||||
|
||||
registers.clear(registerNum);
|
||||
}
|
||||
return !firstRegister;
|
||||
}
|
||||
|
||||
private boolean writeRegisterInfo(IndentingPrintWriter writer, BitSet registers,
|
||||
boolean addNewline) throws IOException {
|
||||
ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod();
|
||||
|
||||
int registerNum = registers.nextSetBit(0);
|
||||
if (registerNum < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (addNewline) {
|
||||
writer.println();
|
||||
}
|
||||
writer.write('#');
|
||||
for (; registerNum >= 0; registerNum = registers.nextSetBit(registerNum + 1)) {
|
||||
|
||||
RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(registerNum);
|
||||
|
||||
RegisterFormatter.writeTo(writer, encodedMethod.codeItem, registerNum);
|
||||
writer.write('=');
|
||||
|
||||
if (registerType == null) {
|
||||
writer.write("null");
|
||||
} else {
|
||||
registerType.writeTo(writer);
|
||||
}
|
||||
writer.write(';');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* 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.Reference;
|
||||
|
||||
import org.jf.dexlib.MethodIdItem;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
|
||||
public class MethodReference {
|
||||
public static StringTemplate createTemplate(StringTemplateGroup stg, MethodIdItem item) {
|
||||
StringTemplate template = stg.getInstanceOf("MethodReference");
|
||||
template.setAttribute("ContainingClass", item.getContainingClass().getTypeDescriptor());
|
||||
template.setAttribute("MethodName", item.getMethodName().getStringValue());
|
||||
template.setAttribute("Prototype", item.getPrototype().getPrototypeString());
|
||||
return template;
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* 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.Reference;
|
||||
|
||||
import org.jf.dexlib.*;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
public abstract class Reference {
|
||||
public static StringTemplate createReference(StringTemplateGroup stg, Item item) {
|
||||
switch (item.getItemType()) {
|
||||
case TYPE_METHOD_ID_ITEM:
|
||||
return MethodReference.createTemplate(stg, (MethodIdItem)item);
|
||||
case TYPE_FIELD_ID_ITEM:
|
||||
return FieldReference.createTemplate(stg, (FieldIdItem)item);
|
||||
case TYPE_STRING_ID_ITEM:
|
||||
return StringReference.createTemplate(stg, (StringIdItem)item);
|
||||
case TYPE_TYPE_ID_ITEM:
|
||||
return TypeReference.createTemplate(stg, (TypeIdItem)item);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* 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.Reference;
|
||||
|
||||
import org.jf.dexlib.StringIdItem;
|
||||
import org.jf.dexlib.Util.Utf8Utils;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
public class StringReference {
|
||||
public static StringTemplate createTemplate(StringTemplateGroup stg, StringIdItem item) {
|
||||
StringTemplate template = stg.getInstanceOf("StringReference");
|
||||
template.setAttribute("EscapedValue", Utf8Utils.escapeString(item.getStringValue()));
|
||||
return template;
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* 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.Reference;
|
||||
|
||||
import org.jf.dexlib.TypeIdItem;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
|
||||
public class TypeReference {
|
||||
public static StringTemplate createTemplate(StringTemplateGroup stg, TypeIdItem item) {
|
||||
StringTemplate template = stg.getInstanceOf("TypeReference");
|
||||
template.setAttribute("TypeDescriptor", item.getTypeDescriptor());
|
||||
return template;
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 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;
|
||||
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.dexlib.*;
|
||||
import org.jf.dexlib.Util.Utf8Utils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ReferenceFormatter {
|
||||
public static void writeReference(IndentingPrintWriter writer, Item item) throws IOException {
|
||||
switch (item.getItemType()) {
|
||||
case TYPE_METHOD_ID_ITEM:
|
||||
writeMethodReference(writer, (MethodIdItem)item);
|
||||
return;
|
||||
case TYPE_FIELD_ID_ITEM:
|
||||
writeFieldReference(writer, (FieldIdItem)item);
|
||||
return;
|
||||
case TYPE_STRING_ID_ITEM:
|
||||
writeStringReference(writer, (StringIdItem)item);
|
||||
return;
|
||||
case TYPE_TYPE_ID_ITEM:
|
||||
writeTypeReference(writer, (TypeIdItem)item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeMethodReference(IndentingPrintWriter writer, MethodIdItem item) {
|
||||
writer.write(item.getContainingClass().getTypeDescriptor());
|
||||
writer.write("->");
|
||||
writer.write(item.getMethodName().getStringValue());
|
||||
writer.write(item.getPrototype().getPrototypeString());
|
||||
}
|
||||
|
||||
public static void writeFieldReference(IndentingPrintWriter writer, FieldIdItem item) {
|
||||
writer.write(item.getContainingClass().getTypeDescriptor());
|
||||
writer.write("->");
|
||||
writer.write(item.getFieldName().getStringValue());
|
||||
writer.write(':');
|
||||
writer.write(item.getFieldType().getTypeDescriptor());
|
||||
}
|
||||
|
||||
public static void writeStringReference(IndentingPrintWriter writer, StringIdItem item) throws IOException {
|
||||
writer.write('"');
|
||||
Utf8Utils.writeEscapedString(writer, item.getStringValue());
|
||||
writer.write('"');
|
||||
}
|
||||
|
||||
public static void writeTypeReference(IndentingPrintWriter writer, TypeIdItem item) {
|
||||
writer.write(item.getTypeDescriptor());
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
import org.jf.dexlib.Util.AccessFlags;
|
||||
import org.jf.baksmali.baksmali;
|
||||
@ -38,15 +39,19 @@ import org.jf.baksmali.baksmali;
|
||||
public class RegisterFormatter {
|
||||
|
||||
/**
|
||||
* This method is used (only) by format 3rc (the format that uses a range of regsiters like {v1 .. v10}) to format
|
||||
* it's registers. If both registers are parameter registers, they will be formatted as such, otherwise they will
|
||||
* both be formatted as normal registers
|
||||
* @param codeItem
|
||||
* @param startRegister
|
||||
* @param lastRegister
|
||||
* @return an array of 2 strings containing the formatted registers
|
||||
* Write out the register range value used by Format3rc. If baksmali.noParameterRegisters is true, it will always
|
||||
* output the registers in the v<n> format. But if false, then it will check if *both* registers are parameter
|
||||
* registers, and if so, use the p<n> format for both. If only the last register is a parameter register, it will
|
||||
* use the v<n> format for both, otherwise it would be confusing to have something like {v20 .. p1}
|
||||
* @param writer the <code>IndentingPrintWriter</code> to write to
|
||||
* @param codeItem the <code>CodeItem</code> that the register is from
|
||||
* @param startRegister the first register in the range
|
||||
* @param lastRegister the last register in the range
|
||||
*/
|
||||
public static String[] formatFormat3rcRegisters(CodeItem codeItem, int startRegister, int lastRegister) {
|
||||
public static void writeRegisterRange(IndentingPrintWriter writer, CodeItem codeItem, int startRegister,
|
||||
int lastRegister) {
|
||||
assert lastRegister >= startRegister;
|
||||
|
||||
if (!baksmali.noParameterRegisters) {
|
||||
int parameterRegisterCount = codeItem.getParent().method.getPrototype().getParameterRegisterCount()
|
||||
+ (((codeItem.getParent().accessFlags & AccessFlags.STATIC.getValue())==0)?1:0);
|
||||
@ -55,32 +60,42 @@ public class RegisterFormatter {
|
||||
assert startRegister <= lastRegister;
|
||||
|
||||
if (startRegister >= registerCount - parameterRegisterCount) {
|
||||
return new String[] {"p" + (startRegister - (registerCount - parameterRegisterCount)),
|
||||
"p" + (lastRegister - (registerCount - parameterRegisterCount))};
|
||||
writer.write("{p");
|
||||
writer.print(startRegister - (registerCount - parameterRegisterCount));
|
||||
writer.write(" .. p");
|
||||
writer.print(lastRegister - (registerCount - parameterRegisterCount));
|
||||
writer.write('}');
|
||||
return;
|
||||
}
|
||||
}
|
||||
return new String[] {"v" + startRegister,
|
||||
"v" + lastRegister};
|
||||
writer.write("{v");
|
||||
writer.print(startRegister);
|
||||
writer.write(" .. v");
|
||||
writer.print(lastRegister);
|
||||
writer.write('}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a register with the appropriate format - with either the normal v<n> format or the p<n> parameter format.
|
||||
* Writes a register with the appropriate format. If baksmali.noParameterRegisters is true, then it will always
|
||||
* output a register in the v<n> format. If false, then it determines if the register is a parameter register,
|
||||
* and if so, formats it in the p<n> format instead.
|
||||
*
|
||||
* It uses the register and parameter information from the give <code>CodeItem</code> to determine if the given
|
||||
* register is a normal or parameter register.
|
||||
* @param codeItem
|
||||
* @param register
|
||||
* @return The formatted register
|
||||
* @param writer the <code>IndentingPrintWriter</code> to write to
|
||||
* @param codeItem the <code>CodeItem</code> that the register is from
|
||||
* @param register the register number
|
||||
*/
|
||||
public static String formatRegister(CodeItem codeItem, int register) {
|
||||
public static void writeTo(IndentingPrintWriter writer, CodeItem codeItem, int register) {
|
||||
if (!baksmali.noParameterRegisters) {
|
||||
int parameterRegisterCount = codeItem.getParent().method.getPrototype().getParameterRegisterCount()
|
||||
+ (((codeItem.getParent().accessFlags & AccessFlags.STATIC.getValue())==0)?1:0);
|
||||
+ (((codeItem.getParent().accessFlags & AccessFlags.STATIC.getValue())==0)?1:0);
|
||||
int registerCount = codeItem.getRegisterCount();
|
||||
if (register >= registerCount - parameterRegisterCount) {
|
||||
return "p" + (register - (registerCount - parameterRegisterCount));
|
||||
writer.write('p');
|
||||
writer.print((register - (registerCount - parameterRegisterCount)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
return "v" + register;
|
||||
writer.write('v');
|
||||
writer.print(register);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* Copyright (c) 2010 Ben Gruver
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,18 +26,48 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Reference;
|
||||
package org.jf.baksmali;
|
||||
|
||||
import org.jf.dexlib.FieldIdItem;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
public class FieldReference {
|
||||
public static StringTemplate createTemplate(StringTemplateGroup stg, FieldIdItem item) {
|
||||
StringTemplate template = stg.getInstanceOf("FieldReference");
|
||||
template.setAttribute("ContainingClass", item.getContainingClass().getTypeDescriptor());
|
||||
template.setAttribute("FieldName", item.getFieldName().getStringValue());
|
||||
template.setAttribute("FieldType", item.getFieldType().getTypeDescriptor());
|
||||
return template;
|
||||
public class IndentingPrintWriter extends PrintWriter {
|
||||
private IndentingWriter writer;
|
||||
private final char[] buffer = new char[16];
|
||||
|
||||
public IndentingPrintWriter(IndentingWriter writer) {
|
||||
super(writer);
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
public IndentingPrintWriter(IndentingWriter writer, boolean autoFlush) {
|
||||
super(writer, autoFlush);
|
||||
}
|
||||
|
||||
public void indent(int indentAmount) {
|
||||
writer.indent(indentAmount);
|
||||
}
|
||||
|
||||
public void deindent(int indentAmount) {
|
||||
writer.deindent(indentAmount);
|
||||
}
|
||||
|
||||
public void printLongAsHex(long l) {
|
||||
//synchronized(lock) {
|
||||
int i=0;
|
||||
do {
|
||||
int digit = (int)(l & 15);
|
||||
if (digit < 10) {
|
||||
buffer[i++] = (char)(digit + '0');
|
||||
} else {
|
||||
buffer[i++] = (char)((digit - 10) + 'a');
|
||||
}
|
||||
|
||||
l >>>= 4;
|
||||
} while (l != 0);
|
||||
|
||||
while (i>0) {
|
||||
write(buffer[--i]);
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
148
baksmali/src/main/java/org/jf/baksmali/IndentingWriter.java
Normal file
148
baksmali/src/main/java/org/jf/baksmali/IndentingWriter.java
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
public class IndentingWriter extends Writer {
|
||||
private final Writer writer;
|
||||
private int indentLevel = 0;
|
||||
private boolean beginningOfLine;
|
||||
|
||||
protected IndentingWriter(Writer writer) {
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int chr) throws IOException {
|
||||
//synchronized(lock) {
|
||||
if (chr == '\n') {
|
||||
writer.write(chr);
|
||||
beginningOfLine = true;
|
||||
} else {
|
||||
if (beginningOfLine) {
|
||||
for (int i=0; i<indentLevel; i++) {
|
||||
writer.write(' ');
|
||||
}
|
||||
}
|
||||
beginningOfLine = false;
|
||||
writer.write(chr);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(char[] chars) throws IOException {
|
||||
//synchronized(lock) {
|
||||
for (char chr: chars) {
|
||||
write(chr);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(char[] chars, int start, int len) throws IOException {
|
||||
//synchronized(lock) {
|
||||
len = start+len;
|
||||
while (start < len) {
|
||||
write(chars[start++]);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String s) throws IOException {
|
||||
//synchronized (lock) {
|
||||
for (int i=0; i<s.length(); i++) {
|
||||
write(s.charAt(i));
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String str, int start, int len) throws IOException {
|
||||
//synchronized(lock) {
|
||||
len = start+len;
|
||||
while (start < len) {
|
||||
write(str.charAt(start++));
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer append(CharSequence charSequence) throws IOException {
|
||||
write(charSequence.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer append(CharSequence charSequence, int start, int len) throws IOException {
|
||||
write(charSequence.subSequence(start, len).toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer append(char c) throws IOException {
|
||||
write(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
//synchronized(lock) {
|
||||
writer.flush();
|
||||
//}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
//synchronized(lock) {
|
||||
writer.close();
|
||||
//}
|
||||
}
|
||||
|
||||
public void indent(int indentAmount) {
|
||||
//synchronized(lock) {
|
||||
this.indentLevel += indentAmount;
|
||||
if (indentLevel < 0) {
|
||||
indentLevel = 0;
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
public void deindent(int indentAmount) {
|
||||
//synchronized(lock) {
|
||||
this.indentLevel -= indentAmount;
|
||||
if (indentLevel < 0) {
|
||||
indentLevel = 0;
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* Copyright (c) 2010 Ben Gruver
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -28,15 +28,14 @@
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.antlr.stringtemplate.AttributeRenderer;
|
||||
import org.jf.dexlib.StringIdItem;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
|
||||
public class StringIdItemRenderer implements AttributeRenderer {
|
||||
public String toString(Object o) {
|
||||
return ((StringIdItem)o).getStringValue();
|
||||
}
|
||||
|
||||
public String toString(Object o, String s) {
|
||||
return toString(o);
|
||||
public class BooleanRenderer {
|
||||
public static void writeTo(IndentingPrintWriter writer, boolean val) {
|
||||
if (val) {
|
||||
writer.write("true");
|
||||
} else {
|
||||
writer.write("false");
|
||||
}
|
||||
}
|
||||
}
|
@ -28,22 +28,24 @@
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.antlr.stringtemplate.AttributeRenderer;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
|
||||
public class ByteRenderer implements AttributeRenderer {
|
||||
public String toString(Object o) {
|
||||
Byte b = (Byte)o;
|
||||
if (b < 0) {
|
||||
return "-0x" + Integer.toHexString(-1 * b) + "t";
|
||||
public class ByteRenderer {
|
||||
public static void writeTo(IndentingPrintWriter writer, byte val) {
|
||||
if (val<0) {
|
||||
writer.write("-0x");
|
||||
writer.printLongAsHex(-val);
|
||||
writer.write('t');
|
||||
} else {
|
||||
writer.write("0x");
|
||||
writer.printLongAsHex(val);
|
||||
writer.write('t');
|
||||
}
|
||||
return "0x" + Integer.toHexString(b) + "t";
|
||||
}
|
||||
|
||||
public String toString(Object o, String s) {
|
||||
if (s.equals("unsigned")) {
|
||||
Byte b = (Byte)o;
|
||||
return "0x" + Integer.toHexString(b & 0xFF) + "t";
|
||||
}
|
||||
return toString(o);
|
||||
public static void writeUnsignedTo(IndentingPrintWriter writer, byte val) {
|
||||
writer.write("0x");
|
||||
writer.printLongAsHex(val & 0xFF);
|
||||
writer.write('t');
|
||||
}
|
||||
}
|
||||
|
@ -28,15 +28,15 @@
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.antlr.stringtemplate.AttributeRenderer;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
import org.jf.dexlib.Util.Utf8Utils;
|
||||
|
||||
public class CharRenderer implements AttributeRenderer {
|
||||
public String toString(Object o) {
|
||||
return "'" + Utf8Utils.escapeString(o.toString()) + "'";
|
||||
}
|
||||
import java.io.IOException;
|
||||
|
||||
public String toString(Object o, String s) {
|
||||
return toString(o);
|
||||
public class CharRenderer {
|
||||
public static void writeTo(IndentingPrintWriter writer, char val) throws IOException {
|
||||
writer.write('\'');
|
||||
Utf8Utils.writeEscapedChar(writer, val);
|
||||
writer.write('\'');
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* Copyright (c) 2010 Ben Gruver
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,15 +26,12 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.EncodedValue;
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
|
||||
public class SimpleEncodedValueAdaptor {
|
||||
public static StringTemplate createTemplate(StringTemplateGroup stg, Object value) {
|
||||
StringTemplate template = stg.getInstanceOf("SimpleEncodedValue");
|
||||
template.setAttribute("Value", value);
|
||||
return template;
|
||||
public class DoubleRenderer {
|
||||
public static void writeTo(IndentingPrintWriter writer, double val) {
|
||||
writer.print(val);
|
||||
}
|
||||
}
|
@ -28,14 +28,11 @@
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.antlr.stringtemplate.AttributeRenderer;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
|
||||
public class FloatRenderer implements AttributeRenderer {
|
||||
public String toString(Object o) {
|
||||
return Float.toString((Float)o) + "f";
|
||||
}
|
||||
|
||||
public String toString(Object o, String s) {
|
||||
return toString(o);
|
||||
public class FloatRenderer {
|
||||
public static void writeTo(IndentingPrintWriter writer, float val) {
|
||||
writer.print(val);
|
||||
writer.write('f');
|
||||
}
|
||||
}
|
||||
|
@ -28,23 +28,21 @@
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.antlr.stringtemplate.AttributeRenderer;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
|
||||
public class IntegerRenderer implements AttributeRenderer {
|
||||
public String toString(Object o) {
|
||||
Integer i = (Integer)o;
|
||||
if (i < 0) {
|
||||
return "-0x" + Integer.toHexString(-1 * i);
|
||||
public class IntegerRenderer {
|
||||
public static void writeTo(IndentingPrintWriter writer, int val) {
|
||||
if (val<0) {
|
||||
writer.write("-0x");
|
||||
writer.printLongAsHex(-((long)val));
|
||||
} else {
|
||||
writer.write("0x");
|
||||
writer.printLongAsHex(val);
|
||||
}
|
||||
return "0x" + Integer.toHexString((Integer)o);
|
||||
}
|
||||
|
||||
public String toString(Object o, String s) {
|
||||
if (s.equals("decimal")) {
|
||||
return Integer.toString((Integer)o);
|
||||
} else if (s.equals("barehex")) {
|
||||
return Integer.toHexString((Integer)o);
|
||||
}
|
||||
return toString(o);
|
||||
public static void writeUnsignedTo(IndentingPrintWriter writer, int val) {
|
||||
writer.write("0x");
|
||||
writer.printLongAsHex(val & 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
|
@ -28,18 +28,34 @@
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.antlr.stringtemplate.AttributeRenderer;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
|
||||
public class LongRenderer implements AttributeRenderer {
|
||||
public String toString(Object o) {
|
||||
Long l = (Long)o;
|
||||
if (l < 0) {
|
||||
return "-0x" + Long.toHexString(-1 * l) + "L";
|
||||
public class LongRenderer {
|
||||
public static void writeTo(IndentingPrintWriter writer, long val) {
|
||||
if (val<0) {
|
||||
writer.write("-0x");
|
||||
writer.printLongAsHex(-val);
|
||||
writer.write('L');
|
||||
} else {
|
||||
writer.write("0x");
|
||||
writer.printLongAsHex(val);
|
||||
writer.write('L');
|
||||
}
|
||||
return "0x" + Long.toHexString(l) + "L";
|
||||
}
|
||||
|
||||
public String toString(Object o, String s) {
|
||||
return toString(o);
|
||||
public static void writeSignedIntOrLongTo(IndentingPrintWriter writer, long val) {
|
||||
if (val<0) {
|
||||
writer.write("-0x");
|
||||
writer.printLongAsHex(-val);
|
||||
if (val < Integer.MIN_VALUE) {
|
||||
writer.write('L');
|
||||
}
|
||||
} else {
|
||||
writer.write("0x");
|
||||
writer.printLongAsHex(val);
|
||||
if (val > Integer.MAX_VALUE) {
|
||||
writer.write('L');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,18 +28,18 @@
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.antlr.stringtemplate.AttributeRenderer;
|
||||
import org.jf.baksmali.IndentingPrintWriter;
|
||||
|
||||
public class ShortRenderer implements AttributeRenderer {
|
||||
public String toString(Object o) {
|
||||
Short s = (Short)o;
|
||||
if (s < 0) {
|
||||
return "-0x" + Integer.toHexString(-1 * s) + "s";
|
||||
public class ShortRenderer {
|
||||
public static void writeTo(IndentingPrintWriter writer, short val) {
|
||||
if (val < 0) {
|
||||
writer.write("-0x");
|
||||
writer.printLongAsHex(-val);
|
||||
writer.write('s');
|
||||
} else {
|
||||
writer.write("0x");
|
||||
writer.printLongAsHex(val);
|
||||
writer.write('s');
|
||||
}
|
||||
return "0x" + Integer.toHexString(s) + "s";
|
||||
}
|
||||
|
||||
public String toString(Object o, String s) {
|
||||
return toString(o);
|
||||
}
|
||||
}
|
||||
|
@ -28,8 +28,6 @@
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import org.antlr.stringtemplate.StringTemplate;
|
||||
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||
import org.jf.baksmali.Adaptors.ClassDefinition;
|
||||
import org.jf.baksmali.Renderers.*;
|
||||
import org.jf.dexlib.Code.Analysis.ClassPath;
|
||||
@ -107,18 +105,6 @@ public class baksmali {
|
||||
}
|
||||
}
|
||||
|
||||
//load and initialize the templates
|
||||
InputStream templateStream = baksmali.class.getClassLoader().getResourceAsStream("templates/baksmali.stg");
|
||||
StringTemplateGroup templates = new StringTemplateGroup(new InputStreamReader(templateStream));
|
||||
templates.registerRenderer(Long.class, new LongRenderer());
|
||||
templates.registerRenderer(Integer.class, new IntegerRenderer());
|
||||
templates.registerRenderer(Short.class, new ShortRenderer());
|
||||
templates.registerRenderer(Byte.class, new ByteRenderer());
|
||||
templates.registerRenderer(Float.class, new FloatRenderer());
|
||||
templates.registerRenderer(Character.class, new CharRenderer());
|
||||
templates.registerRenderer(StringIdItem.class, new StringIdItemRenderer());
|
||||
|
||||
|
||||
for (ClassDefItem classDefItem: dexFile.ClassDefsSection.getItems()) {
|
||||
/**
|
||||
* The path for the disassembly file is based on the package name
|
||||
@ -154,15 +140,10 @@ public class baksmali {
|
||||
File smaliFile = new File(smaliPath.toString());
|
||||
|
||||
//create and initialize the top level string template
|
||||
ClassDefinition classDefinition = new ClassDefinition(templates, classDefItem);
|
||||
|
||||
StringTemplate smaliFileST = classDefinition.createTemplate();
|
||||
|
||||
//generate the disassembly
|
||||
String output = smaliFileST.toString();
|
||||
ClassDefinition classDefinition = new ClassDefinition(classDefItem);
|
||||
|
||||
//write the disassembly
|
||||
FileWriter writer = null;
|
||||
Writer writer = null;
|
||||
try
|
||||
{
|
||||
File smaliParent = smaliFile.getParentFile();
|
||||
@ -180,8 +161,10 @@ public class baksmali {
|
||||
}
|
||||
}
|
||||
|
||||
writer = new FileWriter(smaliFile);
|
||||
writer.write(output);
|
||||
BufferedWriter bufWriter = new BufferedWriter(new FileWriter(smaliFile));
|
||||
|
||||
writer = new IndentingPrintWriter(new IndentingWriter(bufWriter));
|
||||
classDefinition.writeTo((IndentingPrintWriter)writer);
|
||||
} catch (Exception ex) {
|
||||
System.err.println("\n\nError occured while disassembling class " + classDescriptor.replace('/', '.') + " - skipping class");
|
||||
ex.printStackTrace();
|
||||
|
@ -30,8 +30,6 @@ package org.jf.baksmali;
|
||||
|
||||
import org.apache.commons.cli.*;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.OdexDependencies;
|
||||
import org.jf.dexlib.Util.ExceptionWithContext;
|
||||
import org.jf.util.*;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -31,13 +31,15 @@ package org.jf.dexlib;
|
||||
import org.jf.dexlib.Util.ExceptionWithContext;
|
||||
|
||||
public enum AnnotationVisibility {
|
||||
BUILD((byte)0),
|
||||
RUNTIME((byte)1),
|
||||
SYSTEM((byte)2);
|
||||
BUILD((byte)0, "build"),
|
||||
RUNTIME((byte)1, "runtime"),
|
||||
SYSTEM((byte)2, "system");
|
||||
|
||||
public final byte value;
|
||||
private AnnotationVisibility(byte value) {
|
||||
public final String visibility;
|
||||
private AnnotationVisibility(byte value, String visibility) {
|
||||
this.value = value;
|
||||
this.visibility = visibility;
|
||||
}
|
||||
|
||||
public static AnnotationVisibility fromByte(byte value) {
|
||||
|
@ -354,6 +354,10 @@ public class MethodAnalyzer {
|
||||
return instructions.getValues();
|
||||
}
|
||||
|
||||
public ClassDataItem.EncodedMethod getMethod() {
|
||||
return this.encodedMethod;
|
||||
}
|
||||
|
||||
public ValidationException getValidationException() {
|
||||
return validationException;
|
||||
}
|
||||
|
@ -30,6 +30,9 @@ package org.jf.dexlib.Code.Analysis;
|
||||
|
||||
import org.jf.dexlib.TypeIdItem;
|
||||
import static org.jf.dexlib.Code.Analysis.ClassPath.ClassDef;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class RegisterType {
|
||||
@ -54,6 +57,16 @@ public class RegisterType {
|
||||
return "(" + category.name() + (type==null?"":("," + type.getClassType())) + ")";
|
||||
}
|
||||
|
||||
public void writeTo(Writer writer) throws IOException {
|
||||
writer.write('(');
|
||||
writer.write(category.name());
|
||||
if (type != null) {
|
||||
writer.write(',');
|
||||
writer.write(type.getClassType());
|
||||
}
|
||||
writer.write(')');
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
@ -16,6 +16,9 @@
|
||||
|
||||
package org.jf.dexlib.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* Constants of type <code>CONSTANT_Utf8_info</code>.
|
||||
*/
|
||||
@ -166,6 +169,55 @@ public final class Utf8Utils {
|
||||
" at offset " + Hex.u4(offset));
|
||||
}
|
||||
|
||||
public static void writeEscapedChar(Writer writer, char c) throws IOException {
|
||||
if ((c >= ' ') && (c < 0x7f)) {
|
||||
if ((c == '\'') || (c == '\"') || (c == '\\')) {
|
||||
writer.write('\\');
|
||||
}
|
||||
writer.write(c);
|
||||
return;
|
||||
} else if (c <= 0x7f) {
|
||||
switch (c) {
|
||||
case '\n': writer.write("\\n"); return;
|
||||
case '\r': writer.write("\\r"); return;
|
||||
case '\t': writer.write("\\t"); return;
|
||||
}
|
||||
}
|
||||
|
||||
writer.write("\\u");
|
||||
writer.write(Character.forDigit(c >> 12, 16));
|
||||
writer.write(Character.forDigit((c >> 8) & 0x0f, 16));
|
||||
writer.write(Character.forDigit((c >> 4) & 0x0f, 16));
|
||||
writer.write(Character.forDigit(c & 0x0f, 16));
|
||||
|
||||
}
|
||||
|
||||
public static void writeEscapedString(Writer writer, String value) throws IOException {
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
char c = value.charAt(i);
|
||||
|
||||
if ((c >= ' ') && (c < 0x7f)) {
|
||||
if ((c == '\'') || (c == '\"') || (c == '\\')) {
|
||||
writer.write('\\');
|
||||
}
|
||||
writer.write(c);
|
||||
continue;
|
||||
} else if (c <= 0x7f) {
|
||||
switch (c) {
|
||||
case '\n': writer.write("\\n"); continue;
|
||||
case '\r': writer.write("\\r"); continue;
|
||||
case '\t': writer.write("\\t"); continue;
|
||||
}
|
||||
}
|
||||
|
||||
writer.write("\\u");
|
||||
writer.write(Character.forDigit(c >> 12, 16));
|
||||
writer.write(Character.forDigit((c >> 8) & 0x0f, 16));
|
||||
writer.write(Character.forDigit((c >> 4) & 0x0f, 16));
|
||||
writer.write(Character.forDigit(c & 0x0f, 16));
|
||||
}
|
||||
}
|
||||
|
||||
public static String escapeString(String value) {
|
||||
int len = value.length();
|
||||
StringBuilder sb = new StringBuilder(len * 3 / 2);
|
||||
|
Loading…
x
Reference in New Issue
Block a user