Adding initial sources for baksmali

git-svn-id: https://smali.googlecode.com/svn/trunk@143 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
JesusFreke@JesusFreke.com 2009-06-13 05:53:07 +00:00
parent d82bf813d7
commit 36836121d7
6 changed files with 546 additions and 0 deletions

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jf.baksmali;
/**
* Simple exception class used to communicate that the command-line tool
* should print the usage message.
*/
public class UsageException extends RuntimeException {
// This space intentionally left blank.
}

View File

@ -0,0 +1,56 @@
/*
* [The "BSD licence"]
* Copyright (c) 2009 Ben Gruver
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.baksmali;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.jf.dexlib.DexFile;
import org.jf.baksmali.wrappers.ClassDefinition;
import java.io.FileReader;
import java.io.File;
public class baksmali {
public static void main(String[] args) throws Exception
{
String dexFileName = args[0];
String outputDir = args[1];
DexFile dexFile = new DexFile(new File(dexFileName));
StringTemplateGroup templates = new StringTemplateGroup(
new FileReader("src/main/resources/templates/baksmali.stg"));
StringTemplate smaliFileST = templates.getInstanceOf("smaliFile");
smaliFileST.setAttribute("classDef", new ClassDefinition(dexFile.ClassDefsSection.getByIndex(0)));
System.out.println(smaliFileST.toString());
}
}

View File

@ -0,0 +1,131 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jf.baksmali;
import org.jf.baksmali.UsageException;
/**
* Main class for baksmali. It recognizes enough options to be able to dispatch
* to the right "actual" main.
*/
public class main {
public static final String VERSION = "0.9";
private static String USAGE_MESSAGE =
"usage:\n" +
" java -jar baksmali.jar --disassemble <.dex file> <output folder>\n" +
" disassembles the given dex file into a set of .smali files\n" +
" in the given folder\n" +
" java -jar baksmali.jar --version\n" +
" Print the version of this tool (" + VERSION +
").\n" +
" java -jar baksmali.jar --help\n" +
" Print this message.";
/**
* This class is uninstantiable.
*/
private main() {
// This space intentionally left blank.
}
/**
* Run!
*/
public static void main(String[] args) {
boolean gotCmd = false;
boolean showUsage = false;
try {
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.equals("--") || !arg.startsWith("--")) {
gotCmd = false;
showUsage = true;
break;
}
gotCmd = true;
if (arg.equals("--disassemble")) {
baksmali.main(without(args, i));
break;
} else if (arg.equals("--version")) {
version();
break;
} else if (arg.equals("--help")) {
showUsage = true;
break;
} else {
gotCmd = false;
}
}
} catch (UsageException ex) {
showUsage = true;
} catch (RuntimeException ex) {
System.err.println("\nUNEXPECTED TOP-LEVEL EXCEPTION:");
ex.printStackTrace();
System.exit(2);
} catch (Throwable ex) {
System.err.println("\nUNEXPECTED TOP-LEVEL ERROR:");
ex.printStackTrace();
System.exit(3);
}
if (!gotCmd) {
System.err.println("error: no command specified");
showUsage = true;
}
if (showUsage) {
usage();
System.exit(1);
}
}
/**
* Prints the version message.
*/
private static void version() {
System.err.println("baksmali version " + VERSION);
System.exit(0);
}
/**
* Prints the usage message.
*/
private static void usage() {
System.err.println(USAGE_MESSAGE);
}
/**
* Returns a copy of the given args array, but without the indicated
* element.
*
* @param orig non-null; original array
* @param n which element to omit
* @return non-null; new array
*/
private static String[] without(String[] orig, int n) {
int len = orig.length - 1;
String[] newa = new String[len];
System.arraycopy(orig, 0, newa, 0, n);
System.arraycopy(orig, n + 1, newa, n, len - n);
return newa;
}
}

View File

@ -0,0 +1,147 @@
/*
* [The "BSD licence"]
* Copyright (c) 2009 Ben Gruver
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.baksmali.wrappers;
import org.jf.dexlib.ClassDefItem;
import org.jf.dexlib.TypeIdItem;
import org.jf.dexlib.ClassDataItem;
import org.jf.dexlib.util.AccessFlags;
import java.util.List;
import java.util.ArrayList;
public class ClassDefinition {
private ClassDefItem classDefItem;
private ClassDataItem classDataItem;
public ClassDefinition(ClassDefItem classDefItem) {
this.classDefItem = classDefItem;
this.classDataItem = classDefItem.getClassData();
}
private List<String> accessFlags = null;
public List<String> getAccessFlags() {
if (accessFlags == null) {
accessFlags = new ArrayList<String>();
for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForClass(classDefItem.getAccessFlags())) {
accessFlags.add(accessFlag.toString());
}
}
return accessFlags;
}
private String classType = null;
public String getClassType() {
if (classType == null) {
classType = classDefItem.getClassType().getTypeDescriptor();
}
return classType;
}
private String superType = null;
public String getSuperType() {
if (superType == null) {
superType = classDefItem.getSuperclass().getTypeDescriptor();
}
return superType;
}
private List<String> interfaces = null;
public List<String> getInterfaces() {
if (interfaces == null) {
interfaces = new ArrayList<String>();
List<TypeIdItem> interfaceList = classDefItem.getInterfaces();
if (interfaceList != null) {
for (TypeIdItem typeIdItem: interfaceList) {
interfaces.add(typeIdItem.getTypeDescriptor());
}
}
}
return interfaces;
}
private List<FieldDefinition> staticFields = null;
public List<FieldDefinition> getStaticFields() {
if (staticFields == null) {
staticFields = new ArrayList<FieldDefinition>();
if (classDataItem != null) {
for (ClassDataItem.EncodedField field: classDataItem.getStaticFields()) {
staticFields.add(new FieldDefinition(field));
}
}
}
return staticFields;
}
private List<FieldDefinition> instanceFields = null;
public List<FieldDefinition> getInstanceFields() {
if (instanceFields == null) {
instanceFields = new ArrayList<FieldDefinition>();
if (classDataItem != null) {
for (ClassDataItem.EncodedField field: classDataItem.getInstanceFields()) {
instanceFields.add(new FieldDefinition(field));
}
}
}
return instanceFields;
}
private List<MethodDefinition> directMethods = null;
public List<MethodDefinition> getDirectMethods() {
if (directMethods == null) {
directMethods = new ArrayList<MethodDefinition>();
if (classDataItem != null) {
for (ClassDataItem.EncodedMethod method: classDataItem.getDirectMethods()) {
directMethods.add(new MethodDefinition(method));
}
}
}
return directMethods;
}
private List<MethodDefinition> virtualMethods = null;
public List<MethodDefinition> getVirtualMethods() {
if (virtualMethods == null) {
virtualMethods = new ArrayList<MethodDefinition>();
if (classDataItem != null) {
for (ClassDataItem.EncodedMethod method: classDataItem.getVirtualMethods()) {
virtualMethods.add(new MethodDefinition(method));
}
}
}
return virtualMethods;
}
}

View File

@ -0,0 +1,74 @@
/*
* [The "BSD licence"]
* Copyright (c) 2009 Ben Gruver
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.baksmali.wrappers;
import org.jf.dexlib.ClassDataItem;
import org.jf.dexlib.FieldIdItem;
import org.jf.dexlib.util.AccessFlags;
import java.util.List;
import java.util.ArrayList;
public class FieldDefinition {
private ClassDataItem.EncodedField encodedField;
private FieldIdItem fieldIdItem;
public FieldDefinition(ClassDataItem.EncodedField encodedField) {
this.encodedField = encodedField;
this.fieldIdItem = encodedField.getFieldReference();
}
private List<String> accessFlags = null;
public List<String> getAccessFlags() {
if (accessFlags == null) {
accessFlags = new ArrayList<String>();
for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForField(encodedField.getAccessFlags())) {
accessFlags.add(accessFlag.toString());
}
}
return accessFlags;
}
private String fieldName = null;
public String getFieldName() {
if (fieldName == null) {
fieldName = fieldIdItem.getFieldName().getStringValue();
}
return fieldName;
}
private String fieldType = null;
public String getFieldType() {
if (fieldType == null) {
fieldType = fieldIdItem.getFieldType().getTypeDescriptor();
}
return fieldType;
}
}

View File

@ -0,0 +1,113 @@
/*
* [The "BSD licence"]
* Copyright (c) 2009 Ben Gruver
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.baksmali.wrappers;
import org.jf.dexlib.ClassDataItem;
import org.jf.dexlib.CodeItem;
import org.jf.dexlib.MethodIdItem;
import org.jf.dexlib.code.Instruction;
import org.jf.dexlib.code.InstructionField;
import org.jf.dexlib.util.AccessFlags;
import java.util.List;
import java.util.ArrayList;
public class MethodDefinition {
private ClassDataItem.EncodedMethod encodedMethod;
private MethodIdItem methodIdItem;
private CodeItem codeItem;
public MethodDefinition(ClassDataItem.EncodedMethod encodedMethod) {
this.encodedMethod = encodedMethod;
this.methodIdItem = encodedMethod.getMethod();
this.codeItem = encodedMethod.getCodeItem();
}
private String methodName = null;
public String getMethodName() {
if (methodName == null) {
methodName = methodIdItem.getMethodName();
}
return methodName;
}
private List<String> accessFlags = null;
public List<String> getAccessFlags() {
if (accessFlags == null) {
accessFlags = new ArrayList<String>();
for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(encodedMethod.getAccessFlags())) {
accessFlags.add(accessFlag.toString());
}
}
return accessFlags;
}
private String prototype = null;
public String getPrototype() {
if (prototype == null) {
prototype = methodIdItem.getPrototype().getPrototypeString();
}
return prototype;
}
private Boolean hasCode = null;
public boolean getHasCode() {
if (hasCode == null) {
hasCode = (codeItem != null);
}
return hasCode;
}
private String registerCount = null;
public String getRegisterCount() {
if (registerCount == null) {
if (codeItem == null) {
registerCount = "0";
} else {
registerCount = Integer.toString(codeItem.getRegisterCount());
}
}
return registerCount;
}
//TODO: how best to abstract this? I don't like exposing dexlib's "Instruction" directly
private List<Instruction> instructions = null;
public List<Instruction> getInstructions() {
if (instructions == null) {
instructions = new ArrayList<Instruction>();
if (codeItem != null) {
for (InstructionField instruction: codeItem.getInstructions()) {
instructions.add(instruction.getInstruction());
}
}
}
return instructions;
}
}