diff --git a/pom.xml b/pom.xml
new file mode 100644
index 00000000..b125bd7b
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+ smali
+ smali
+ 1.0
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.5
+ 1.5
+
+
+
+
+ org.antlr
+ antlr3-maven-plugin
+ 3.1.3-1
+
+
+ smali
+
+ antlr
+
+
+ org/JesusFreke/smali/smaliTreeWalker.g
+
+
+
+ smaliTreeWalker
+
+ antlr
+
+
+ org/JesusFreke/smali/smali.g
+
+
+
+
+
+
+
+
+
+
+ org.antlr
+ antlr-runtime
+ 3.1.3
+
+
+
\ No newline at end of file
diff --git a/src/main/antlr3/org/JesusFreke/smali/smali.g b/src/main/antlr3/org/JesusFreke/smali/smali.g
new file mode 100644
index 00000000..3f3937a2
--- /dev/null
+++ b/src/main/antlr3/org/JesusFreke/smali/smali.g
@@ -0,0 +1,594 @@
+/*
+ * The comment lexical rule, and the number, string and character constant
+ * lexical rules are derived from rules from the Java 1.6 grammar which can be
+ * found here: http://openjdk.java.net/projects/compiler-grammar/antlrworks/Java.g
+ *
+ * Specifically, these rules:
+ *
+ * COMMENT, LONG_LITERAL, INT_LITERAL, Integer_number, Hex_prefix, Hex_digit,
+ * Long_suffix, Non_integer_number_SIMPLE_NAME, Non_integer_number,
+ * Decimal_exponent, Hex_exponent, Float_suffix, Double_suffix,
+ * FLOAT_LITERAL_SIMPLE_NAME, FLOAT_LITERAL, DOUBLE_LITERAL_SIMPLE_NAME,
+ * DOUBLE_LITERAL, CHAR_LITERAL, STRING_LITERAL, EscapeSequence
+ *
+ * These rules were originally copyrighted by Terence Parr, and are used here in
+ * accordance with the following license
+ *
+ * [The "BSD licence"]
+ * Copyright (c) 2007-2008 Terence Parr
+ * 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.
+ *
+ *
+ * The remainder of this grammar is released by me (Ben Gruver) under the
+ * following license:
+ *
+ * [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.
+ */
+
+grammar smali;
+
+options {
+ output=AST;
+ ASTLabelType=CommonTree;
+}
+
+tokens {
+ //I_* tokens are imaginary tokens used as parent AST nodes
+ I_CLASS_DEF;
+ I_SUPER;
+ I_ACCESS_LIST;
+ I_METHODS;
+ I_FIELDS;
+ I_FIELD;
+ I_FIELD_TYPE;
+ I_FIELD_INITIAL_VALUE;
+ I_METHOD;
+ I_METHOD_PROTOTYPE;
+ I_METHOD_RETURN_TYPE;
+ I_REGISTERS;
+ I_STATEMENTS;
+ I_INVOKE_STATEMENT;
+ I_INVOKE_RANGE_STATEMENT;
+ I_BARE_STATEMENT;
+ I_STATIC_FIELD_STATEMENT;
+ I_INSTANCE_FIELD_STATEMENT;
+ I_CONST_STRING_STATEMENT;
+ I_NEW_INSTANCE_STATEMENT;
+ I_SINGLE_REGISTER_STATEMENT;
+ I_REGISTER_RANGE;
+ I_REGISTER_LIST;
+}
+
+@parser::header {
+package org.JesusFreke.smali;
+}
+
+@lexer::header {
+package org.JesusFreke.smali;
+
+import java.util.ArrayDeque;
+}
+
+@lexer::init {
+ state.token = Token.INVALID_TOKEN;
+}
+
+@lexer::members {
+ protected ArrayDeque tokens = new ArrayDeque();
+
+ public void reset() {
+ super.reset();
+ state.token = Token.INVALID_TOKEN;
+ tokens.clear();
+ }
+
+ public Token nextToken() {
+ while (true) {
+ if (tokens.size() > 0) {
+ Token token = tokens.poll();
+ if (token == Token.SKIP_TOKEN) {
+ continue;
+ }
+
+ return token;
+ }
+
+ state.channel = Token.DEFAULT_CHANNEL;
+ state.tokenStartCharIndex = input.index();
+ state.tokenStartCharPositionInLine = input.getCharPositionInLine();
+ state.tokenStartLine = input.getLine();
+ state.text = null;
+ if ( input.LA(1)==CharStream.EOF ) {
+ return Token.EOF_TOKEN;
+ }
+ try {
+ mTokens();
+
+ if (tokens.size() == 0) {
+ emit();
+ }
+ }
+ catch (NoViableAltException nva) {
+ reportError(nva);
+ recover(nva); // throw out current char and try again
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ // match() routine has already called recover()
+ }
+ }
+ }
+
+ public void skip() {
+ tokens.add(Token.SKIP_TOKEN);
+ }
+
+ public void emit(Token token) {
+ tokens.add(token);
+ }
+}
+
+
+smali_file: header methods_and_fields -> ^(I_CLASS_DEF header methods_and_fields);
+
+header : class_spec super_spec;
+
+class_spec
+ : '.class' access_list class_name -> class_name access_list;
+
+super_spec
+ : first_token='.super' class_name -> ^(I_SUPER[$first_token, "I_SUPER"] class_name);
+
+access_list
+ : first_token=ACCESS_SPEC ACCESS_SPEC* -> ^(I_ACCESS_LIST[$first_token,"I_ACCESS_LIST"] ACCESS_SPEC+);
+
+methods_and_fields
+ : (method | field)* -> ^(I_METHODS method*) ^(I_FIELDS field*);
+
+field : first_token='.field' access_list member_name field_type_descriptor ('=' literal)?
+ -> ^(I_FIELD[$first_token, "I_FIELD"] member_name access_list ^(I_FIELD_TYPE field_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)?);
+
+method : first_token='.method' access_list method_name_and_prototype locals_directive statements '.end method'
+ -> ^(I_METHOD[$first_token, "I_METHOD"] method_name_and_prototype access_list locals_directive statements);
+
+method_prototype
+ : first_token='(' field_type_list ')' type_descriptor
+ -> ^(I_METHOD_PROTOTYPE[$first_token, "I_METHOD_PROTOTYPE"] ^(I_METHOD_RETURN_TYPE type_descriptor) field_type_list?);
+
+method_name_and_prototype
+ : member_name method_prototype;
+
+field_type_list
+ : field_type_descriptor*;
+
+locals_directive
+ : first_token='.registers' INT_LITERAL
+ -> ^(I_REGISTERS[$first_token, "I_REGISTERS"] INT_LITERAL);
+
+
+full_method_name_and_prototype
+ : QUALIFIED_MEMBER__CLASS_NAME QUALIFIED_MEMBER__MEMBER_NAME method_prototype;
+
+full_field_name_and_type
+ : QUALIFIED_MEMBER__CLASS_NAME QUALIFIED_MEMBER__MEMBER_NAME field_type_descriptor;
+
+statements
+ : statement* -> ^(I_STATEMENTS statement*);
+
+statement
+ : instruction;
+
+instruction
+ //e.g. return
+ : BARE_INSTRUCTION_NAME
+ -> ^(I_BARE_STATEMENT[$start, "I_BARE_STATEMENT"] BARE_INSTRUCTION_NAME)
+ | //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V
+ INVOKE_INSTRUCTION_NAME '{' register_list '}' full_method_name_and_prototype
+ -> ^(I_INVOKE_STATEMENT[$start, "I_INVOKE_STATEMENT"] INVOKE_INSTRUCTION_NAME register_list full_method_name_and_prototype)
+ | //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+ INVOKE_RANGE_INSTRUCTION_NAME '{' register_range '}' full_method_name_and_prototype
+ -> ^(I_INVOKE_RANGE_STATEMENT[$start, "I_INVOKE_RANGE_STATEMENT"] INVOKE_RANGE_INSTRUCTION_NAME register_range full_method_name_and_prototype)
+ | //e.g. sget_object v0 java/lang/System/out LJava/io/PrintStream;
+ STATIC_FIELD_INSTRUCTION_NAME REGISTER full_field_name_and_type
+ -> ^(I_STATIC_FIELD_STATEMENT[$start, "I_STATIC_FIELD_STATEMENT"] STATIC_FIELD_INSTRUCTION_NAME REGISTER full_field_name_and_type)
+ | //e.g. iput-object v1 v0 org/JesusFreke/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String;
+ INSTANCE_FIELD_INSTRUCTION_NAME REGISTER REGISTER full_field_name_and_type
+ -> ^(I_INSTANCE_FIELD_STATEMENT[$start, "I_INSTANCE_FIELD_STATEMENT"] INSTANCE_FIELD_INSTRUCTION_NAME REGISTER REGISTER full_field_name_and_type)
+ | //e.g. const-string v1 "Hello World!"
+ CONST_STRING_INSTRUCTION_NAME REGISTER STRING_LITERAL
+ -> ^(I_CONST_STRING_STATEMENT[$start, "I_CONST_STRING_STATMENT"] CONST_STRING_INSTRUCTION_NAME REGISTER STRING_LITERAL)
+ | //e.g. new-instance v1 android/widget/TextView
+ NEW_INSTANCE_INSTRUCTION_NAME REGISTER class_name
+ -> ^(I_NEW_INSTANCE_STATEMENT[$start, "I_NEW_INSTANCE_STATEMENT"] NEW_INSTANCE_INSTRUCTION_NAME REGISTER class_name)
+ | //e.g. move-result-object v1
+ SINGLE_REGISTER_INSTRUCTION_NAME REGISTER
+ -> ^(I_SINGLE_REGISTER_STATEMENT[$start, "I_SINGLE_REGISTER_STATEMENT"] SINGLE_REGISTER_INSTRUCTION_NAME REGISTER)
+ ;
+
+
+register_list
+ : first_token=REGISTER? (',' REGISTER)* -> ^(I_REGISTER_LIST[$first_token, "I_REGISTER_LIST"] REGISTER*);
+
+register_range
+ : first_token=REGISTER ('..' REGISTER)? -> ^(I_REGISTER_RANGE[$first_token, "I_REGISTER_RANGE"] REGISTER REGISTER?);
+
+/*since there are no reserved words in the dex specification, there are a
+number of tokens that can be a valid simple_name, in addition to just
+SIMPLE_NAME. We need to match any token that could also be considered a valid
+SIMPLE_NAME. In the case of floating point literals, some could be considered
+a valid SIMPLE_NAME while others couldn't. The lexer will generate a separate
+FLOAT_LITERAL_SIMPLE_NAME OR DOUBLE_LITERAL_SIMPLE_NAME token for literals
+that can be considered a valid SIMPLE_NAME*/
+simple_name
+ : SIMPLE_NAME
+ | ACCESS_SPEC
+ | instruction_name
+ | INT_LITERAL
+ | LONG_LITERAL
+ | FLOAT_LITERAL_SIMPLE_NAME
+ | DOUBLE_LITERAL_SIMPLE_NAME
+ | BOOL_LITERAL
+ | PRIMITIVE_TYPE
+ ;
+
+instruction_name
+ : INVOKE_INSTRUCTION_NAME
+ | INVOKE_RANGE_INSTRUCTION_NAME
+ | STATIC_FIELD_INSTRUCTION_NAME
+ | INSTANCE_FIELD_INSTRUCTION_NAME
+ | BARE_INSTRUCTION_NAME
+ | CONST_STRING_INSTRUCTION_NAME
+ | NEW_INSTANCE_INSTRUCTION_NAME
+ | SINGLE_REGISTER_INSTRUCTION_NAME
+ ;
+
+member_name
+ : simple_name
+ | MEMBER_NAME
+ ;
+
+class_name
+ : SIMPLE_NAME | CLASS_WITH_PACKAGE_NAME;
+
+field_type_descriptor
+ : PRIMITIVE_TYPE
+ | CLASS_DESCRIPTOR
+ | ARRAY_TYPE
+ ;
+
+type_descriptor
+ : VOID_TYPE
+ | field_type_descriptor
+ ;
+
+literal : INT_LITERAL
+ | LONG_LITERAL
+ | float_literal
+ | double_literal
+ | CHAR_LITERAL
+ | STRING_LITERAL
+ | BOOL_LITERAL;
+
+float_literal
+ : FLOAT_LITERAL -> FLOAT_LITERAL
+ | FLOAT_LITERAL_SIMPLE_NAME -> FLOAT_LITERAL[$FLOAT_LITERAL_SIMPLE_NAME, $FLOAT_LITERAL_SIMPLE_NAME.text];
+
+double_literal
+ : DOUBLE_LITERAL -> DOUBLE_LITERAL
+ | DOUBLE_LITERAL_SIMPLE_NAME -> DOUBLE_LITERAL[$DOUBLE_LITERAL_SIMPLE_NAME, $DOUBLE_LITERAL_SIMPLE_NAME.text];
+
+ACCESS_SPEC
+ : 'public' | 'private' | 'static' | 'constructor' | 'final';
+
+INVOKE_INSTRUCTION_NAME
+ : 'invoke-virtual'
+ | 'invoke-super'
+ | 'invoke-direct'
+ | 'invoke-static'
+ | 'invoke-interface'
+ ;
+
+INVOKE_RANGE_INSTRUCTION_NAME
+ : 'invoke-virtual/range'
+ | 'invoke-super/range'
+ | 'invoke-direct/range'
+ | 'invoke-static/range'
+ | 'invoke-interface/range'
+ ;
+
+STATIC_FIELD_INSTRUCTION_NAME
+ : 'sget'
+ | 'sget-wide'
+ | 'sget-object'
+ | 'sget-boolean'
+ | 'sget-byte'
+ | 'sget-char'
+ | 'sget-short'
+ | 'sput'
+ | 'sput-wide'
+ | 'sput-object'
+ | 'sput-boolean'
+ | 'sput-byte'
+ | 'sput-char'
+ | 'sput-short'
+ ;
+
+INSTANCE_FIELD_INSTRUCTION_NAME
+ : 'iget'
+ | 'iget-wide'
+ | 'iget-object'
+ | 'iget-boolean'
+ | 'iget-byte'
+ | 'iget-char'
+ | 'iget-short'
+ | 'iput'
+ | 'iput-wide'
+ | 'iput-object'
+ | 'iput-boolean'
+ | 'iput-byte'
+ | 'iput-char'
+ | 'iput-short'
+ ;
+
+BARE_INSTRUCTION_NAME
+ : 'return-void'
+ | 'nop';
+
+
+CONST_STRING_INSTRUCTION_NAME
+ : 'const-string';
+
+NEW_INSTANCE_INSTRUCTION_NAME
+ : 'new-instance';
+
+SINGLE_REGISTER_INSTRUCTION_NAME
+ : 'move-result'
+ | 'move-result-wide'
+ | 'move-result-object'
+ | 'move-exception'
+ | 'return'
+ | 'return-wide'
+ | 'return-object'
+ | 'monitor-enter'
+ | 'monitor-exit'
+ | 'throw';
+
+
+/*since SIMPLE_NAME is so all-encompassing, it includes all integer literals
+and a subset of the possible floating point literals. For floating point
+literals, we need to generate a separate token depending on whether the token
+could also be considered a SIMPLE_NAME or not.
+
+The floating point related tokens with a _SIMPLE_NAME suffix could also be
+considered valid SIMPLE_NAME tokens, while the plain version of the token
+(without the suffix) could not be considered a valid SIMPLE_NAME token*/
+
+LONG_LITERAL
+ : Integer_number Long_suffix;
+
+INT_LITERAL
+ : Integer_number;
+
+fragment Integer_number
+ : '-'? '0'
+ | '-'? ('1'..'9') ('0'..'9')*
+ | '0' ('0'..'7')+
+ | Hex_prefix Hex_digit+
+ ;
+
+fragment Hex_prefix
+ : '0x'|'0X';
+
+fragment Hex_digit
+ : ('0'..'9'|'a'..'f'|'A'..'F');
+
+fragment Long_suffix
+ : 'l'|'L';
+
+fragment Non_integer_number_SIMPLE_NAME
+ : ('0'..'9')+ Decimal_exponent
+ | ('0'..'9')+
+ | Hex_prefix (Hex_digit)* Hex_exponent
+ ;
+
+
+fragment Non_integer_number
+ : ('0'..'9')+ '.' ('0'..'9')* Decimal_exponent?
+ | '.' ('0'..'9')+ Decimal_exponent?
+ | Hex_prefix (Hex_digit)* '.' (Hex_digit)* Hex_exponent
+ ;
+
+fragment Decimal_exponent
+ : ('e'|'E') '-'? ('0'..'9')+;
+
+fragment Hex_exponent
+ : ('p'|'P') '-'? ('0'..'9')+;
+
+fragment Float_suffix
+ : 'f'|'F';
+
+fragment Double_suffix
+ : 'd'|'D';
+
+FLOAT_LITERAL_SIMPLE_NAME
+ : Non_integer_number_SIMPLE_NAME Float_suffix;
+
+FLOAT_LITERAL
+ : Non_integer_number Float_suffix;
+
+DOUBLE_LITERAL_SIMPLE_NAME
+ : Non_integer_number_SIMPLE_NAME Double_suffix?;
+
+DOUBLE_LITERAL
+ : Non_integer_number Double_suffix?;
+
+CHAR_LITERAL
+
+ : '\'' {StringBuilder sb = new StringBuilder();}
+ ( Escape_sequence[sb] {setText(sb.toString());}
+ | ~( '\'' | '\\' | '\r' | '\n' )
+ )
+ '\''
+ ;
+
+STRING_LITERAL
+ : '"' {StringBuilder sb = new StringBuilder();}
+ ( Escape_sequence[sb]
+ | ~( '\\' | '"' | '\r' | '\n' ) {sb.append((char)input.LA(-1));}
+ )*
+ '"' {setText(sb.toString());}
+ ;
+
+
+Hex_digits
+ : Hex_digit Hex_digit Hex_digit Hex_digit;
+
+fragment
+Escape_sequence[StringBuilder sb]
+ : '\\'
+ (
+ 'b' {sb.append("\b");}
+ | 't' {sb.append("\t");}
+ | 'n' {sb.append("\n");}
+ | 'f' {sb.append("\f");}
+ | 'r' {sb.append("\r");}
+ | '\"' {sb.append("\"");}
+ | '\'' {sb.append("'");}
+ | '\\' {sb.append("\\");}
+ | 'u' Hex_digits {sb.append((char)Integer.parseInt($Hex_digits.text, 16));}
+/* | octdigits=(('0'..'3') ('0'..'7') ('0'..'7')) {$value = (char)Integer.parseInt("0" + $octdigits.text);}
+ | octdigits=(('0'..'7') ('0'..'7')) {$value = (char)Integer.parseInt("0" + $octdigits.text);}
+ | octdigits=(('0'..'7')) {$value = (char)Integer.parseInt("0" + $octdigits.text);}*/
+ );
+
+BOOL_LITERAL
+ : 'true'|'false';
+
+
+
+WHITESPACE
+ : (' '|'\t'|'\n'|'\r')+ {$channel = HIDDEN;};
+
+REGISTER: 'v' ('0'..'9')+;
+
+
+/*a token of type QUALIFIED_MEMBER is never generated. This rule emits 2 sub-tokens
+that represent the class name and the member name, so that they don't have to be
+parsed out later*/
+QUALIFIED_MEMBER
+ : class_name=QUALIFIED_MEMBER__CLASS_NAME '.' member_name=QUALIFIED_MEMBER__MEMBER_NAME
+ {
+ $class_name.setType(QUALIFIED_MEMBER__CLASS_NAME);
+ $member_name.setType(QUALIFIED_MEMBER__MEMBER_NAME);
+ emit($class_name);
+ emit($member_name);
+ };
+
+fragment QUALIFIED_MEMBER__CLASS_NAME
+ : (SIMPLE_NAME '/')* SIMPLE_NAME;
+
+fragment QUALIFIED_MEMBER__MEMBER_NAME
+ : MEMBER_NAME | SIMPLE_NAME;
+
+
+ARRAY_TYPE
+ :
+ ARRAY_CHAR_LIST[255] (PRIMITIVE_TYPE | CLASS_DESCRIPTOR);
+
+
+//match from 1 to maxCount '[' characters
+fragment
+ARRAY_CHAR_LIST[int maxCount]
+ : {$maxCount > 1}?=> '[' ARRAY_CHAR_LIST[$maxCount - 1]
+ | '['
+ ;
+
+MEMBER_NAME
+ : '<' SIMPLE_NAME '>';
+
+VOID_TYPE
+ : 'V';
+
+PRIMITIVE_TYPE
+ : 'Z'
+ | 'B'
+ | 'S'
+ | 'C'
+ | 'I'
+ | 'J'
+ | 'F'
+ | 'D'
+ ;
+
+CLASS_WITH_PACKAGE_NAME
+ : (SIMPLE_NAME '/')+ SIMPLE_NAME;
+
+CLASS_DESCRIPTOR
+ : 'L' (SIMPLE_NAME | CLASS_WITH_PACKAGE_NAME) ';';
+
+SIMPLE_NAME:
+ ( 'A'..'Z'
+ | 'a'..'z'
+ | '0'..'9'
+ | '$'
+ | '-'
+ | '_'
+ | '\u00a1'..'\u1fff'
+ | '\u2010'..'\u2027'
+ | '\u2030'..'\ud7ff'
+ | '\ue000'..'\uffef'
+ )+;
+
+COMMENT
+ : (';' ~('\n'|'\r')* ('\r\n' | '\r' | '\n')
+ | ';' ~('\n'|'\r')*)
+ {
+ $channel = HIDDEN;
+ }
+ ;
diff --git a/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g b/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g
new file mode 100644
index 00000000..c4806298
--- /dev/null
+++ b/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g
@@ -0,0 +1,437 @@
+/*
+ * [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.
+ */
+
+tree grammar smaliTreeWalker;
+
+options {
+ tokenVocab=smali;
+ ASTLabelType=CommonTree;
+}
+
+@header {
+package org.JesusFreke.smali;
+
+import org.JesusFreke.dexlib.*;
+import org.JesusFreke.dexlib.EncodedValue.*;
+import org.JesusFreke.dexlib.util.*;
+import org.JesusFreke.dexlib.code.*;
+import org.JesusFreke.dexlib.code.Format.*;
+}
+
+@members {
+ public DexFile dexFile;
+ public ClassDefItem classDefItem;
+ public ClassDataItem classDataItem;
+
+
+ private static byte parseRegister_nibble(String register) {
+ //register should be in the format "v12"
+ byte val = Byte.parseByte(register.substring(1));
+ if (val >= 2<<4) {
+ //TODO: throw correct exception type
+ throw new RuntimeException("The maximum allowed register in this context is list of registers is v15");
+ }
+ //the parser wouldn't accept a negative register, i.e. v-1, so we don't have to check for val<0;
+ return val;
+ }
+
+ //return a short, because java's byte is signed
+ private static short parseRegister_byte(String register) {
+ //register should be in the format "v123"
+ short val = Short.parseShort(register.substring(1));
+ if (val >= 2<<8) {
+ //TODO: throw correct exception type
+ throw new RuntimeException("The maximum allowed register in this context is v255");
+ }
+ return val;
+ }
+
+ //return an int because java's short is signed
+ private static int parseRegister_short(String register) {
+ //register should be in the format "v12345"
+ int val = Integer.parseInt(register.substring(1));
+ if (val >= 2<<16) {
+ //TODO: throw correct exception type
+ throw new RuntimeException("The maximum allowed register in this context is v65535");
+ }
+ //the parser wouldn't accept a negative register, i.e. v-1, so we don't have to check for val<0;
+ return val;
+ }
+}
+
+
+
+smali_file returns[ClassDefItem classDefItem]
+ : ^(I_CLASS_DEF header methods fields);
+
+header : class_spec super_spec
+ {
+ classDataItem = new ClassDataItem(dexFile, 0);
+ classDefItem = new ClassDefItem(dexFile, $class_spec.type, $class_spec.accessFlags, $super_spec.type, classDataItem);
+ };
+
+class_spec returns[TypeIdItem type, int accessFlags]
+ : class_name access_list
+ {
+ $type = $class_name.type;
+ $accessFlags = $access_list.value;
+ };
+
+super_spec returns[TypeIdItem type]
+ : ^(I_SUPER class_name)
+ {
+ $type = $class_name.type;
+ };
+
+access_list returns [int value]
+ @init
+ {
+ $value = 0;
+ }
+ : ^(I_ACCESS_LIST
+ (
+ ACCESS_SPEC
+ {
+ $value |= AccessFlags.getValueForAccessFlag($ACCESS_SPEC.getText());
+ }
+ )+);
+
+fields : ^(I_FIELDS
+ (field
+ {
+ classDefItem.addField($field.encodedField, $field.encodedValue);
+ })*);
+
+methods : ^(I_METHODS
+ (method
+ {
+ classDataItem.addMethod($method.encodedMethod);
+ })*);
+
+field returns[ClassDataItem.EncodedField encodedField, EncodedValue encodedValue]
+ :^(I_FIELD member_name access_list ^(I_FIELD_TYPE field_type_descriptor) field_initial_value)
+ {
+ TypeIdItem classType = classDefItem.getClassType();
+ StringIdItem memberName = new StringIdItem(dexFile, $member_name.memberName);
+ TypeIdItem fieldType = $field_type_descriptor.type;
+
+ FieldIdItem fieldIdItem = new FieldIdItem(dexFile, classType, memberName, fieldType);
+ $encodedField = new ClassDataItem.EncodedField(dexFile, fieldIdItem, $access_list.value);
+
+ if ($field_initial_value.encodedValue != null) {
+ if (($access_list.value & AccessFlags.STATIC) == 0) {
+ //TODO: change to an appropriate exception type?
+ throw new RuntimeException("Initial field values can only be specified for static fields.");
+ }
+
+ $encodedValue = $field_initial_value.encodedValue;
+ } else {
+ $encodedValue = null;
+ }
+ };
+
+field_initial_value returns[EncodedValue encodedValue]
+ : ^(I_FIELD_INITIAL_VALUE
+ ( int_literal { $encodedValue = new EncodedValue(dexFile, new IntEncodedValueSubField($int_literal.value)); }
+ | long_literal { $encodedValue = new EncodedValue(dexFile, new LongEncodedValueSubField($long_literal.value)); }
+ | float_literal { $encodedValue = new EncodedValue(dexFile, new FloatEncodedValueSubField($float_literal.value)); }
+ | double_literal { $encodedValue = new EncodedValue(dexFile, new DoubleEncodedValueSubField($double_literal.value)); }
+ | char_literal { $encodedValue = new EncodedValue(dexFile, new CharEncodedValueSubField($char_literal.value)); }
+ | string_literal { $encodedValue = new EncodedValue(dexFile, new EncodedIndexedItemReference(dexFile, new StringIdItem(dexFile, $string_literal.value))); }
+ | bool_literal { $encodedValue = new EncodedValue(dexFile, new BoolEncodedValueSubField($bool_literal.value)); }
+ ))
+ | ;
+
+
+method returns[ClassDataItem.EncodedMethod encodedMethod]
+ : ^(I_METHOD method_name_and_prototype access_list locals_directive statements)
+ {
+ MethodIdItem methodIdItem = $method_name_and_prototype.methodIdItem;
+ int registers = $locals_directive.registers;
+ int access = $access_list.value;
+ boolean isStatic = (access & AccessFlags.STATIC) != 0;
+ ArrayList instructions = $statements.instructions;
+
+ CodeItem codeItem = new CodeItem(dexFile, registers, methodIdItem.getParameterWordCount(isStatic), instructions);
+
+ $encodedMethod = new ClassDataItem.EncodedMethod(dexFile, methodIdItem, access, codeItem);
+ };
+
+method_prototype returns[ProtoIdItem protoIdItem]
+ : ^(I_METHOD_PROTOTYPE ^(I_METHOD_RETURN_TYPE type_descriptor) field_type_list)
+ {
+ TypeIdItem returnType = $type_descriptor.type;
+ ArrayList parameterTypes = $field_type_list.types;
+
+ $protoIdItem = new ProtoIdItem(dexFile, returnType, parameterTypes);
+ };
+
+method_name_and_prototype returns[MethodIdItem methodIdItem]
+ : member_name method_prototype
+ {
+ TypeIdItem classType = classDefItem.getClassType();
+ String methodNameString = $member_name.memberName;
+ StringIdItem methodName = new StringIdItem(dexFile, methodNameString);
+ ProtoIdItem protoIdItem = $method_prototype.protoIdItem;
+
+ $methodIdItem = new MethodIdItem(dexFile, classType, methodName, protoIdItem);
+ };
+
+field_type_list returns[ArrayList types]
+ @init
+ {
+ $types = new ArrayList();
+ }
+ : (
+ field_type_descriptor
+ {
+ $types.add($field_type_descriptor.type);
+ }
+ )*;
+
+locals_directive returns[int registers]
+ : ^(I_REGISTERS INT_LITERAL) {$registers = Integer.parseInt($INT_LITERAL.text);};
+
+full_method_name_and_prototype returns[MethodIdItem methodIdItem]
+ : QUALIFIED_MEMBER__CLASS_NAME QUALIFIED_MEMBER__MEMBER_NAME method_prototype
+ {
+ TypeIdItem classType = new TypeIdItem(dexFile, "L" + $QUALIFIED_MEMBER__CLASS_NAME.text + ";");
+ StringIdItem methodName = new StringIdItem(dexFile, $QUALIFIED_MEMBER__MEMBER_NAME.text);
+ ProtoIdItem prototype = $method_prototype.protoIdItem;
+ $methodIdItem = new MethodIdItem(dexFile, classType, methodName, prototype);
+ };
+
+full_field_name_and_type returns[FieldIdItem fieldIdItem]
+ : QUALIFIED_MEMBER__CLASS_NAME QUALIFIED_MEMBER__MEMBER_NAME field_type_descriptor
+ {
+ TypeIdItem classType = new TypeIdItem(dexFile, "L" + $QUALIFIED_MEMBER__CLASS_NAME.text + ";");
+ StringIdItem fieldName = new StringIdItem(dexFile, $QUALIFIED_MEMBER__MEMBER_NAME.text);
+ TypeIdItem fieldType = $field_type_descriptor.type;
+ $fieldIdItem = new FieldIdItem(dexFile, classType, fieldName, fieldType);
+ };
+
+statements returns[ArrayList instructions]
+ @init
+ {
+ $instructions = new ArrayList();
+ }
+ : ^(I_STATEMENTS
+ (instruction
+ {
+ $instructions.add($instruction.instruction);
+ })*);
+
+
+instruction returns[Instruction instruction]
+ //e.g. return
+ : ^(I_BARE_STATEMENT BARE_INSTRUCTION_NAME)
+ {
+ Opcode opcode = Opcode.getOpcodeByName($BARE_INSTRUCTION_NAME.text);
+ $instruction = Format10x.Format.make(dexFile, opcode.value);
+ }
+ | //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V
+ ^(I_INVOKE_STATEMENT INVOKE_INSTRUCTION_NAME register_list full_method_name_and_prototype)
+ {
+ Opcode opcode = Opcode.getOpcodeByName($INVOKE_INSTRUCTION_NAME.text);
+
+ //this depends on the fact that register_list returns a byte[5]
+ byte[] registers = $register_list.registers;
+ byte registerCount = $register_list.registerCount;
+
+ MethodIdItem methodIdItem = $full_method_name_and_prototype.methodIdItem;
+
+ $instruction = Format35c.Format.make(dexFile, opcode.value, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], methodIdItem);
+ }
+ | //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+ ^(I_INVOKE_RANGE_STATEMENT INVOKE_RANGE_INSTRUCTION_NAME register_range full_method_name_and_prototype)
+ {
+ Opcode opcode = Opcode.getOpcodeByName($INVOKE_RANGE_INSTRUCTION_NAME.text);
+ int startRegister = $register_range.startRegister;
+ int endRegister = $register_range.endRegister;
+
+ int registerCount = endRegister-startRegister+1;
+ if (registerCount > 256) {
+ //TODO: throw appropriate exception type
+ throw new RuntimeException("A register range can span a maximum of 256 registers");
+ }
+ if (registerCount < 1) {
+ //TODO: throw appropriate exception type
+ throw new RuntimeException("A register range must have the lower register listed first");
+ }
+
+ MethodIdItem methodIdItem = $full_method_name_and_prototype.methodIdItem;
+
+ //not supported yet
+ $instruction = Format3rc.Format.make(dexFile, opcode.value, (short)registerCount, startRegister, methodIdItem);
+ }
+ | //e.g. sget_object v0 java/lang/System/out LJava/io/PrintStream;
+ ^(I_STATIC_FIELD_STATEMENT STATIC_FIELD_INSTRUCTION_NAME REGISTER full_field_name_and_type)
+ {
+ Opcode opcode = Opcode.getOpcodeByName($STATIC_FIELD_INSTRUCTION_NAME.text);
+ short regA = parseRegister_byte($REGISTER.text);
+
+ FieldIdItem fieldIdItem = $full_field_name_and_type.fieldIdItem;
+
+ $instruction = Format21c.Format.make(dexFile, opcode.value, regA, fieldIdItem);
+ }
+ | //e.g. iput-object v1 v0 org/JesusFreke/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String;
+ ^(I_INSTANCE_FIELD_STATEMENT INSTANCE_FIELD_INSTRUCTION_NAME registerA=REGISTER registerB=REGISTER full_field_name_and_type)
+ {
+ Opcode opcode = Opcode.getOpcodeByName($INSTANCE_FIELD_INSTRUCTION_NAME.text);
+ byte regA = parseRegister_nibble($registerA.text);
+ byte regB = parseRegister_nibble($registerB.text);
+
+ FieldIdItem fieldIdItem = $full_field_name_and_type.fieldIdItem;
+
+ $instruction = Format22c.Format.make(dexFile, opcode.value, regA, regB, fieldIdItem);
+ }
+ | //e.g. const-string v1 "Hello World!"
+ ^(I_CONST_STRING_STATEMENT CONST_STRING_INSTRUCTION_NAME REGISTER string_literal)
+ {
+ Opcode opcode = Opcode.getOpcodeByName($CONST_STRING_INSTRUCTION_NAME.text);
+ short regA = parseRegister_byte($REGISTER.text);
+
+ StringIdItem stringIdItem = new StringIdItem(dexFile, $string_literal.value);
+
+ $instruction = Format21c.Format.make(dexFile, opcode.value, regA, stringIdItem);
+ }
+ | //e.g. new-instance v1 android/widget/TextView
+ ^(I_NEW_INSTANCE_STATEMENT NEW_INSTANCE_INSTRUCTION_NAME REGISTER class_name)
+ {
+ Opcode opcode = Opcode.getOpcodeByName($NEW_INSTANCE_INSTRUCTION_NAME.text);
+ short regA = parseRegister_byte($REGISTER.text);
+
+ TypeIdItem typeIdItem = $class_name.type;
+
+ $instruction = Format21c.Format.make(dexFile, opcode.value, regA, typeIdItem);
+ }
+ | //e.g. move-result-object v1
+ ^(I_SINGLE_REGISTER_STATEMENT SINGLE_REGISTER_INSTRUCTION_NAME REGISTER)
+ {
+ Opcode opcode = Opcode.getOpcodeByName($SINGLE_REGISTER_INSTRUCTION_NAME.text);
+ short regA = parseRegister_byte($REGISTER.text);
+
+ $instruction = Format11x.Format.make(dexFile, opcode.value, regA);
+ }
+ ;
+
+
+register_list returns[byte[\] registers, byte registerCount]
+ @init
+ {
+ $registers = new byte[5];
+ $registerCount = 0;
+ }
+ : ^(I_REGISTER_LIST
+ (REGISTER
+ {
+ if ($registerCount == 5) {
+ //TODO: throw the correct type of exception
+ throw new RuntimeException("A list of registers can only have a maximum of 5 registers. Use the /range alternate opcode instead.");
+ }
+ $registers[$registerCount++] = parseRegister_nibble($REGISTER.text);
+ })*);
+
+register_range returns[int startRegister, int endRegister]
+ : ^(I_REGISTER_RANGE startReg=REGISTER endReg=REGISTER?)
+ {
+ $startRegister = parseRegister_short($startReg.text);
+ if ($endReg == null) {
+ $endRegister = $startRegister;
+ } else {
+ $endRegister = parseRegister_short($endReg.text);
+ }
+ }
+ ;
+
+simple_name
+ : SIMPLE_NAME
+ | ACCESS_SPEC
+ | INT_LITERAL
+ | LONG_LITERAL
+ | FLOAT_LITERAL_SIMPLE_NAME
+ | DOUBLE_LITERAL_SIMPLE_NAME
+ | BOOL_LITERAL
+ | PRIMITIVE_TYPE
+ | instruction_name
+ ;
+
+instruction_name returns[String value]
+ : INVOKE_INSTRUCTION_NAME
+ | INVOKE_RANGE_INSTRUCTION_NAME
+ | STATIC_FIELD_INSTRUCTION_NAME
+ | INSTANCE_FIELD_INSTRUCTION_NAME
+ | BARE_INSTRUCTION_NAME
+ | CONST_STRING_INSTRUCTION_NAME
+ | NEW_INSTANCE_INSTRUCTION_NAME
+ ;
+
+member_name returns[String memberName]
+ : (simple_name
+ | MEMBER_NAME) {$memberName = $start.getText();}
+ ;
+
+class_name returns [TypeIdItem type]
+ : token=(SIMPLE_NAME | CLASS_WITH_PACKAGE_NAME)
+ {
+ $type = new TypeIdItem(dexFile, 'L'+$token.text+';');
+ };
+
+field_type_descriptor returns [TypeIdItem type]
+ : token=(PRIMITIVE_TYPE
+ | CLASS_DESCRIPTOR
+ | ARRAY_TYPE)
+ {
+ $type = new TypeIdItem(dexFile, $token.text);
+ };
+
+type_descriptor returns [TypeIdItem type]
+ : VOID_TYPE {$type = new TypeIdItem(dexFile, "V");}
+ | field_type_descriptor {$type = $field_type_descriptor.type;}
+ ;
+
+int_literal returns[int value]
+ : INT_LITERAL { $value = Integer.parseInt($INT_LITERAL.text); };
+
+long_literal returns[long value]
+ : LONG_LITERAL { $value = Long.parseLong($LONG_LITERAL.text); };
+
+float_literal returns[float value]
+ : FLOAT_LITERAL { $value = Float.parseFloat($FLOAT_LITERAL.text); };
+
+double_literal returns[double value]
+ : DOUBLE_LITERAL { $value = Double.parseDouble($DOUBLE_LITERAL.text); };
+
+char_literal returns[char value]
+ : CHAR_LITERAL { $value = $CHAR_LITERAL.text.charAt(0); };
+
+string_literal returns[String value]
+ : STRING_LITERAL { $value = $STRING_LITERAL.text; };
+
+bool_literal returns[boolean value]
+ : BOOL_LITERAL { $value = Boolean.parseBoolean($BOOL_LITERAL.text); };
diff --git a/src/main/java/org/JesusFreke/dexlib/AnnotationDirectoryItem.java b/src/main/java/org/JesusFreke/dexlib/AnnotationDirectoryItem.java
new file mode 100644
index 00000000..02145036
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/AnnotationDirectoryItem.java
@@ -0,0 +1,133 @@
+/*
+ * [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.JesusFreke.dexlib;
+
+import org.JesusFreke.dexlib.ItemType;
+
+import java.util.ArrayList;
+
+//TODO: fix field names in dex-format.html and submit
+public class AnnotationDirectoryItem extends OffsettedItem {
+ private final Field[] fields;
+
+ private final ArrayList fieldAnnotationList = new ArrayList();
+ private final ArrayList methodAnnotationList = new ArrayList();
+ private final ArrayList parameterAnnotationList = new ArrayList();
+
+ private final OffsettedItemReference classAnnotations;
+ private final ListSizeField annotatedFieldsCount;
+ private final ListSizeField annotatedMethodsCount;
+ private final ListSizeField annotatedParametersCount;
+ private final FieldListField fieldAnnotations;
+ private final FieldListField methodAnnotations;
+ private final FieldListField parameterAnnotations;
+
+ public AnnotationDirectoryItem(final DexFile dexFile, int offset) {
+ super(offset);
+
+ fields = new Field[] {
+ classAnnotations = new OffsettedItemReference(dexFile.AnnotationSetsSection, new IntegerField()),
+ annotatedFieldsCount = new ListSizeField(fieldAnnotationList, new IntegerField()),
+ annotatedMethodsCount = new ListSizeField(methodAnnotationList, new IntegerField()),
+ annotatedParametersCount = new ListSizeField(parameterAnnotationList, new IntegerField()),
+ fieldAnnotations = new FieldListField(fieldAnnotationList) {
+ protected FieldAnnotation make() {
+ return new FieldAnnotation(dexFile);
+ }
+ },
+ methodAnnotations = new FieldListField(methodAnnotationList) {
+ protected MethodAnnotation make() {
+ return new MethodAnnotation(dexFile);
+ }
+ },
+ parameterAnnotations = new FieldListField(parameterAnnotationList) {
+ protected ParameterAnnotation make() {
+ return new ParameterAnnotation(dexFile);
+ }
+ }
+ };
+ }
+
+ protected int getAlignment() {
+ return 4;
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public ItemType getItemType() {
+ return ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM;
+ }
+
+ public class FieldAnnotation extends CompositeField {
+ private final Field[] fields;
+
+ public FieldAnnotation(DexFile dexFile) {
+ fields = new Field[] {
+ new IndexedItemReference(dexFile.FieldIdsSection, new IntegerField()),
+ new OffsettedItemReference(dexFile.AnnotationSetsSection, new IntegerField())
+ };
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+ }
+
+ public class MethodAnnotation extends CompositeField {
+ private final Field[] fields;
+
+ public MethodAnnotation(DexFile dexFile) {
+ fields = new Field[] {
+ new IndexedItemReference(dexFile.MethodIdsSection, new IntegerField()),
+ new OffsettedItemReference(dexFile.AnnotationSetsSection, new IntegerField())
+ };
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+ }
+
+ public class ParameterAnnotation extends CompositeField {
+ private final Field[] fields;
+
+ public ParameterAnnotation(DexFile dexFile) {
+ fields = new Field[] {
+ new IndexedItemReference(dexFile.MethodIdsSection, new IntegerField()),
+ new OffsettedItemReference(dexFile.AnnotationSetsSection, new IntegerField())
+ };
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/AnnotationItem.java b/src/main/java/org/JesusFreke/dexlib/AnnotationItem.java
new file mode 100644
index 00000000..dc1a077d
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/AnnotationItem.java
@@ -0,0 +1,81 @@
+/*
+ * [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.JesusFreke.dexlib;
+
+import org.JesusFreke.dexlib.EncodedValue.AnnotationEncodedValueSubField;
+import org.JesusFreke.dexlib.ItemType;
+
+public class AnnotationItem extends OffsettedItem {
+ private final Field[] fields;
+
+ private final ByteField visibility;
+ private final AnnotationEncodedValueSubField annotation;
+
+ public AnnotationItem(DexFile dexFile, int offset) {
+ super(offset);
+
+ fields = new Field[] {
+ visibility = new ByteField(),
+ annotation = new AnnotationEncodedValueSubField(dexFile)
+ };
+ }
+
+ protected int getAlignment() {
+ return 1;
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public ItemType getItemType() {
+ return ItemType.TYPE_ANNOTATION_ITEM;
+ }
+
+ public void copyTo(DexFile dexFile, AnnotationItem copy) {
+ visibility.copyTo(dexFile, copy.visibility);
+ annotation.copyTo(dexFile, copy.annotation);
+ }
+
+ public int hashCode() {
+ return visibility.hashCode() * 31 + annotation.hashCode();
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof AnnotationItem)) {
+ return false;
+ }
+
+ AnnotationItem other = (AnnotationItem)o;
+
+ if (!visibility.equals(other.visibility))
+ return false;
+ return annotation.equals(other.annotation);
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/AnnotationSetItem.java b/src/main/java/org/JesusFreke/dexlib/AnnotationSetItem.java
new file mode 100644
index 00000000..5e528dbb
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/AnnotationSetItem.java
@@ -0,0 +1,68 @@
+/*
+ * [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.JesusFreke.dexlib;
+
+import org.JesusFreke.dexlib.ItemType;
+
+import java.util.ArrayList;
+
+public class AnnotationSetItem extends OffsettedItem {
+ private final Field[] fields;
+
+ private final ArrayList> annotationReferences =
+ new ArrayList>();
+
+ private final ListSizeField annotationCount;
+ private final FieldListField> annotations;
+
+ public AnnotationSetItem(final DexFile dexFile, int offset) {
+ super(offset);
+
+ fields = new Field[] {
+ annotationCount = new ListSizeField(annotationReferences, new IntegerField()),
+ annotations = new FieldListField>(annotationReferences) {
+ protected OffsettedItemReference make() {
+ return new OffsettedItemReference(dexFile.AnnotationsSection, new IntegerField());
+ }
+ }
+ };
+ }
+
+ protected int getAlignment() {
+ return 4;
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public ItemType getItemType() {
+ return ItemType.TYPE_ANNOTATION_SET_ITEM;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/AnnotationSetRefList.java b/src/main/java/org/JesusFreke/dexlib/AnnotationSetRefList.java
new file mode 100644
index 00000000..0bf905e6
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/AnnotationSetRefList.java
@@ -0,0 +1,68 @@
+/*
+ * [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.JesusFreke.dexlib;
+
+import org.JesusFreke.dexlib.ItemType;
+
+import java.util.ArrayList;
+
+public class AnnotationSetRefList extends OffsettedItem {
+ private final Field[] fields;
+
+ private final ArrayList> annotationSetReferences =
+ new ArrayList>();
+
+ private final ListSizeField annotationSetCount;
+ private final FieldListField> annotationSets;
+
+ public AnnotationSetRefList(final DexFile dexFile, int offset) {
+ super(offset);
+
+ fields = new Field[] {
+ annotationSetCount = new ListSizeField(annotationSetReferences, new IntegerField()),
+ annotationSets = new FieldListField>(annotationSetReferences) {
+ protected OffsettedItemReference make() {
+ return new OffsettedItemReference(dexFile.AnnotationSetsSection, new IntegerField());
+ }
+ }
+ };
+ }
+
+ protected int getAlignment() {
+ return 4;
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public ItemType getItemType() {
+ return ItemType.TYPE_ANNOTATION_SET_REF_LIST;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/ByteField.java b/src/main/java/org/JesusFreke/dexlib/ByteField.java
new file mode 100644
index 00000000..12e06874
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/ByteField.java
@@ -0,0 +1,63 @@
+/*
+ * [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.JesusFreke.dexlib;
+
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.Input;
+
+public class ByteField extends CachedIntegerValueField {
+ protected byte value;
+
+ public ByteField() {
+ }
+
+ public ByteField(byte value) {
+ this.value = value;
+ }
+
+ public void writeTo(Output out) {
+ out.writeByte(value);
+ }
+
+ public void readFrom(Input in) {
+ value = in.readByte();
+ }
+
+ public int place(int offset) {
+ return offset + 1;
+ }
+
+ public int getCachedValue() {
+ return value;
+ }
+
+ public void cacheValue(int value) {
+ this.value = (byte)value;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/CachedIntegerValueField.java b/src/main/java/org/JesusFreke/dexlib/CachedIntegerValueField.java
new file mode 100644
index 00000000..bcb75acb
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/CachedIntegerValueField.java
@@ -0,0 +1,52 @@
+/*
+ * [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.JesusFreke.dexlib;
+
+public abstract class CachedIntegerValueField implements Field {
+ public abstract int getCachedValue();
+ public abstract void cacheValue(int value);
+
+ public void copyTo(DexFile dexFile, CachedIntegerValueField copy) {
+ copy.cacheValue(getCachedValue());
+ }
+
+ public int hashCode() {
+ return ((Integer)getCachedValue()).hashCode();
+ }
+
+ public boolean equals(Object o) {
+ if (getClass() != o.getClass()) {
+ return false;
+ }
+
+ CachedIntegerValueField other = (CachedIntegerValueField)o;
+
+ return getCachedValue() == other.getCachedValue();
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/ClassDataItem.java b/src/main/java/org/JesusFreke/dexlib/ClassDataItem.java
new file mode 100644
index 00000000..688fcc35
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/ClassDataItem.java
@@ -0,0 +1,351 @@
+/*
+ * [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.JesusFreke.dexlib;
+
+import org.JesusFreke.dexlib.ItemType;
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.Input;
+import org.JesusFreke.dexlib.util.AccessFlags;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+public class ClassDataItem extends OffsettedItem {
+ private final Field[] fields;
+
+ private final ArrayList staticFieldList = new ArrayList();
+ private final ArrayList instanceFieldList = new ArrayList();
+ private final ArrayList directMethodList = new ArrayList();
+ private final ArrayList virtualMethodList = new ArrayList();
+
+ private final ListSizeField staticFieldsCount;
+ private final ListSizeField instanceFieldsCount;
+ private final ListSizeField directMethodsCount;
+ private final ListSizeField virtualMethodsCount;
+ private final EncodedMemberList staticFields;
+ private final EncodedMemberList instanceFields;
+ private final EncodedMemberList directMethods;
+ private final EncodedMemberList virtualMethods;
+
+
+ public ClassDataItem(final DexFile dexFile, int offset) {
+ super(offset);
+
+ fields = new Field[] {
+ staticFieldsCount = new ListSizeField(staticFieldList, new Leb128Field()),
+ instanceFieldsCount = new ListSizeField(instanceFieldList, new Leb128Field()),
+ directMethodsCount = new ListSizeField(directMethodList, new Leb128Field()),
+ virtualMethodsCount = new ListSizeField(virtualMethodList, new Leb128Field()),
+ staticFields = new EncodedMemberList(staticFieldList) {
+ protected EncodedField make(EncodedField previousField) {
+ return new EncodedField(dexFile, previousField);
+ }
+ },
+ instanceFields = new EncodedMemberList(instanceFieldList) {
+ protected EncodedField make(EncodedField previousField) {
+ return new EncodedField(dexFile, previousField);
+ }
+ },
+ directMethods = new EncodedMemberList(directMethodList) {
+ protected EncodedMethod make(EncodedMethod previousMethod) {
+ return new EncodedMethod(dexFile, previousMethod);
+ }
+ },
+ virtualMethods = new EncodedMemberList(virtualMethodList) {
+ protected EncodedMethod make(EncodedMethod previousMethod) {
+ return new EncodedMethod(dexFile, previousMethod);
+ }
+ }
+ };
+ }
+
+ public void addMethod(EncodedMethod encodedMethod) {
+ if (encodedMethod.isDirect()) {
+ directMethodList.add(encodedMethod);
+ } else {
+ virtualMethodList.add(encodedMethod);
+ }
+ }
+
+ public int addField(EncodedField encodedField) {
+ if (encodedField.isStatic()) {
+ staticFieldList.add(encodedField);
+ Collections.sort(staticFieldList);
+ return Collections.binarySearch(staticFieldList, encodedField);
+ } else {
+ instanceFieldList.add(encodedField);
+ Collections.sort(instanceFieldList);
+ return Collections.binarySearch(instanceFieldList, encodedField);
+ }
+ }
+
+ public EncodedField getStaticFieldAtIndex(int i)
+ {
+ return staticFieldList.get(i);
+ }
+
+ private static abstract class EncodedMember> extends CompositeField implements Field, Comparable
+ {
+ protected abstract void setPreviousMember(T previousMember);
+ }
+
+ private static abstract class EncodedMemberList> implements Field> {
+ private final ArrayList list;
+
+ public EncodedMemberList(ArrayList list) {
+ this.list = list;
+ }
+
+ public void writeTo(Output out) {
+ for (T field: list) {
+ field.writeTo(out);
+ }
+ }
+
+ protected abstract T make(T previousField);
+
+ public void readFrom(Input in) {
+ for (int i = 0; i < list.size(); i++) {
+ T previousField = null;
+ if (i > 0) {
+ previousField = list.get(i-1);
+ }
+ T field = make(previousField);
+ list.set(i, field);
+ field.readFrom(in);
+ }
+ }
+
+ public int place(int offset) {
+ Collections.sort(list);
+
+ T previousMember = null;
+ for (T encodedMember: list) {
+ encodedMember.setPreviousMember(previousMember);
+ offset = encodedMember.place(offset);
+ previousMember = encodedMember;
+ }
+ return offset;
+ }
+
+ public void copyTo(DexFile dexFile, EncodedMemberList copy) {
+ copy.list.clear();
+ copy.list.ensureCapacity(list.size());
+ for (int i = 0; i < list.size(); i++) {
+ T previousField = null;
+ if (i > 0) {
+ previousField = copy.list.get(i-1);
+ }
+ T fieldCopy = copy.make(previousField);
+ list.get(i).copyTo(dexFile, fieldCopy);
+ copy.list.add(fieldCopy);
+ }
+ }
+
+ public int hashCode() {
+ int h = 1;
+ for (int i = 0; i < list.size(); i++) {
+ h = h * 31 + list.get(i).hashCode();
+ }
+ return h;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof EncodedMemberList)) {
+ return false;
+ }
+
+ EncodedMemberList other = (EncodedMemberList)o;
+ if (list.size() != other.list.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < list.size(); i++) {
+ if (!list.get(i).equals(other.list.get(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ public static class EncodedField extends EncodedMember {
+ private final Field[] fields;
+
+ private final IndexedItemReference field;
+ private final Leb128DeltaField fieldIndexField;
+ private final Leb128Field accessFlags;
+
+ public EncodedField(DexFile dexFile, final EncodedField previousField) {
+ Leb128DeltaField previousIndexField = null;
+ if (previousField != null) {
+ previousIndexField = previousField.fieldIndexField;
+ }
+
+
+ fields = new Field[] {
+ field = new IndexedItemReference(dexFile.FieldIdsSection,
+ fieldIndexField = new Leb128DeltaField(previousIndexField)),
+ accessFlags = new Leb128Field()
+ };
+ }
+
+ public EncodedField(DexFile dexFile, FieldIdItem field, int accessFlags) {
+ fields = new Field[] {
+ this.field = new IndexedItemReference(dexFile, field,
+ fieldIndexField = new Leb128DeltaField(null)),
+ this.accessFlags = new Leb128Field(accessFlags)
+ };
+ }
+
+ protected void setPreviousMember(EncodedField previousField) {
+ if (previousField != null) {
+ fieldIndexField.setPreviousField(previousField.fieldIndexField);
+ } else {
+ fieldIndexField.setPreviousField(null);
+ }
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public int compareTo(EncodedField other)
+ {
+ return field.getReference().compareTo(other.field.getReference());
+ }
+
+ public boolean isStatic() {
+ return (accessFlags.getCachedValue() & AccessFlags.STATIC) != 0;
+ }
+
+ public FieldIdItem getField() {
+ return field.getReference();
+ }
+ }
+
+ public static class EncodedMethod extends EncodedMember {
+ private final Field[] fields;
+
+ private final IndexedItemReference method;
+ private final Leb128DeltaField methodIndexField;
+ private final Leb128Field accessFlags;
+ private final OffsettedItemReference codeItem;
+
+ public EncodedMethod(DexFile dexFile, final EncodedMethod previousMethod) {
+ Leb128DeltaField previousIndexField = null;
+ if (previousMethod != null) {
+ previousIndexField = previousMethod.methodIndexField;
+ }
+
+ fields = new Field[] {
+ method = new IndexedItemReference(dexFile.MethodIdsSection,
+ methodIndexField = new Leb128DeltaField(previousIndexField)),
+ accessFlags = new Leb128Field(),
+ codeItem = new OffsettedItemReference(dexFile.CodeItemsSection, new Leb128Field())
+ };
+ }
+
+ public EncodedMethod(DexFile dexFile, MethodIdItem methodIdItem, int accessFlags, CodeItem codeItem) {
+ fields = new Field[] {
+ this.method = new IndexedItemReference(dexFile, methodIdItem,
+ methodIndexField = new Leb128DeltaField(null)),
+ this.accessFlags = new Leb128Field(accessFlags),
+ this.codeItem = new OffsettedItemReference(dexFile, codeItem, new Leb128Field())
+ };
+ }
+
+ protected void setPreviousMember(EncodedMethod previousMethod) {
+ if (previousMethod != null) {
+ methodIndexField.setPreviousField(previousMethod.methodIndexField);
+ } else {
+ methodIndexField.setPreviousField(null);
+ }
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public int compareTo(EncodedMethod other)
+ {
+ return method.getReference().compareTo(other.method.getReference());
+ }
+
+ public boolean isDirect() {
+ return ((accessFlags.getCachedValue() & (AccessFlags.STATIC | AccessFlags.PRIVATE | AccessFlags.CONSTRUCTOR)) != 0);
+ }
+ }
+
+
+ /**
+ * An Leb128 integer that encodes its value as the difference between
+ * itself and the previous Leb128DeltaField in the list. The first
+ * item encodes the value as per normal
+ */
+ protected static class Leb128DeltaField extends Leb128Field {
+ private Leb128DeltaField previousField;
+
+ public Leb128DeltaField(Leb128DeltaField previousField) {
+ this.previousField = previousField;
+ }
+
+ public void setPreviousField(Leb128DeltaField previousField) {
+ this.previousField = previousField;
+ }
+
+ public int getCachedValue() {
+ if (previousField != null) {
+ return previousField.getCachedValue() + super.getCachedValue();
+ } else {
+ return super.getCachedValue();
+ }
+ }
+
+ public void cacheValue(int value) {
+ if (previousField != null) {
+ super.cacheValue(value - previousField.getCachedValue());
+ } else {
+ super.cacheValue(value);
+ }
+ }
+ }
+
+ protected int getAlignment() {
+ return 1;
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public ItemType getItemType() {
+ return ItemType.TYPE_CLASS_DATA_ITEM;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/ClassDefItem.java b/src/main/java/org/JesusFreke/dexlib/ClassDefItem.java
new file mode 100644
index 00000000..7bb5b2ec
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/ClassDefItem.java
@@ -0,0 +1,229 @@
+/*
+ * [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.JesusFreke.dexlib;
+
+import org.JesusFreke.dexlib.ItemType;
+import org.JesusFreke.dexlib.EncodedValue.EncodedValue;
+import org.JesusFreke.dexlib.EncodedValue.EncodedValueSubField;
+import org.JesusFreke.dexlib.util.TypeUtils;
+
+import java.util.HashMap;
+import java.util.ArrayList;
+
+public class ClassDefItem extends IndexedItem {
+ private final Field[] fields;
+
+ private final IndexedItemReference classType;
+ private final IntegerField accessFlags;
+ private final IndexedItemReference superclassType;
+ private final OffsettedItemReference classInterfacesList;
+ private final IndexedItemReference sourceFile;
+ private final OffsettedItemReference classAnnotations;
+ private final OffsettedItemReference classData;
+ private final OffsettedItemReference staticFieldInitialValues;
+
+ private ArrayList staticFieldInitialValuesList;
+
+ private final DexFile dexFile;
+
+ public ClassDefItem(DexFile dexFile, int index) {
+ super(index);
+
+ this.dexFile = dexFile;
+
+ fields = new Field[] {
+ classType = new IndexedItemReference(dexFile.TypeIdsSection, new IntegerField()),
+ accessFlags = new IntegerField(),
+ superclassType = new IndexedItemReference(dexFile.TypeIdsSection, new IntegerField()),
+ classInterfacesList = new OffsettedItemReference(dexFile.TypeListsSection, new IntegerField()),
+ sourceFile = new IndexedItemReference(dexFile.StringIdsSection, new IntegerField()),
+ classAnnotations = new OffsettedItemReference(dexFile.AnnotationDirectoriesSection, new IntegerField()),
+ classData = new OffsettedItemReference(dexFile.ClassDataSection, new IntegerField()),
+ staticFieldInitialValues = new OffsettedItemReference(dexFile.EncodedArraysSection, new IntegerField())
+ };
+ }
+
+ public ClassDefItem(DexFile dexFile, TypeIdItem classType, int accessFlags, TypeIdItem superType, ClassDataItem classDataItem) {
+ super(-1);
+
+ this.dexFile = dexFile;
+
+ fields = new Field[] {
+ this.classType = new IndexedItemReference(dexFile, classType, new IntegerField()),
+ this.accessFlags = new IntegerField(accessFlags),
+ superclassType = new IndexedItemReference(dexFile, superType, new IntegerField()),
+ classInterfacesList = new OffsettedItemReference(dexFile.TypeListsSection, new IntegerField()),
+ sourceFile = new IndexedItemReference(dexFile.StringIdsSection, new IntegerField()),
+ classAnnotations = new OffsettedItemReference(dexFile.AnnotationDirectoriesSection, new IntegerField()),
+ classData = new OffsettedItemReference(dexFile, classDataItem, new IntegerField()),
+ staticFieldInitialValues = new OffsettedItemReference(dexFile.EncodedArraysSection, new IntegerField())
+ };
+ }
+
+ public TypeIdItem getSuperclass() {
+ return superclassType.getReference();
+ }
+
+ public TypeIdItem getClassType() {
+ return classType.getReference();
+ }
+
+ protected int getAlignment() {
+ return 4;
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public ItemType getItemType() {
+ return ItemType.TYPE_CLASS_DEF_ITEM;
+ }
+
+ public String getClassName() {
+ return classType.getReference().toString();
+ }
+
+ public String toString() {
+ return getClassName();
+ }
+
+ public int hashCode() {
+ return classType.getReference().hashCode();
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof ClassDefItem)) {
+ return false;
+ }
+ ClassDefItem other = (ClassDefItem)o;
+ return classType.equals(other.classType);
+ }
+
+ public int compareTo(ClassDefItem o) {
+ //sorting is implemented in SortClassDefItemSection, so this class doesn't
+ //need an implementation of compareTo
+ return 0;
+ }
+
+ public void addMethod(ClassDataItem.EncodedMethod encodedMethod) {
+ }
+
+ public void addField(ClassDataItem.EncodedField encodedField, EncodedValue initialValue) {
+ if (!encodedField.isStatic() && initialValue != null) {
+ throw new RuntimeException("Initial values are only allowed for static fields.");
+ }
+
+ ClassDataItem classDataItem = this.classData.getReference();
+
+ int fieldIndex = classDataItem.addField(encodedField);
+ if (initialValue != null) {
+ if (staticFieldInitialValuesList == null) {
+ staticFieldInitialValuesList = new ArrayList();
+
+ EncodedArrayItem encodedArrayItem = new EncodedArrayItem(dexFile, staticFieldInitialValuesList);
+ staticFieldInitialValues.setReference(encodedArrayItem);
+ }
+
+ //All static fields before this one must have an initial value. Add any default values as needed
+ for (int i=staticFieldInitialValuesList.size(); i < fieldIndex; i++) {
+ ClassDataItem.EncodedField staticField = classDataItem.getStaticFieldAtIndex(i);
+ EncodedValueSubField subField = TypeUtils.makeDefaultValueForType(dexFile, staticField.getField().getFieldType().toString());
+ EncodedValue encodedValue = new EncodedValue(dexFile, subField);
+ staticFieldInitialValuesList.add(i, encodedValue);
+ }
+
+ staticFieldInitialValuesList.add(fieldIndex, initialValue);
+ }
+ }
+
+ public static int placeClassDefItems(IndexedSection section, int offset) {
+ ClassDefPlacer cdp = new ClassDefPlacer(section);
+ return cdp.placeSection(offset);
+ }
+
+ /**
+ * This class places the items within a ClassDefItem section, such that superclasses and interfaces are
+ * placed before sub/implementing classes
+ */
+ private static class ClassDefPlacer {
+ private final IndexedSection section;
+ private final HashMap classDefsByType = new HashMap();
+
+ private int currentIndex = 0;
+ private int currentOffset;
+
+ public ClassDefPlacer(IndexedSection section) {
+ this.section = section;
+
+ for (ClassDefItem classDefItem: section.items) {
+ TypeIdItem typeIdItem = classDefItem.classType.getReference();
+ classDefsByType.put(typeIdItem, classDefItem);
+ }
+ }
+
+ public int placeSection(int offset) {
+ currentOffset = offset;
+ for (ClassDefItem classDefItem: section.items) {
+ placeClass(classDefItem);
+ }
+
+ for (ClassDefItem classDefItem: classDefsByType.values()) {
+ section.items.set(classDefItem.getIndex(), classDefItem);
+ }
+
+ return currentOffset;
+ }
+
+ private void placeClass(ClassDefItem classDefItem) {
+ if (!classDefItem.isPlaced()) {
+ TypeIdItem superType = classDefItem.superclassType.getReference();
+ ClassDefItem superClassDefItem = classDefsByType.get(superType);
+
+ if (superClassDefItem != null) {
+ placeClass(superClassDefItem);
+ }
+
+ TypeListItem interfaces = classDefItem.classInterfacesList.getReference();
+
+ if (interfaces != null) {
+ for (TypeIdItem interfaceType: interfaces.getTypes()) {
+ ClassDefItem interfaceClass = classDefsByType.get(interfaceType);
+ if (interfaceClass != null) {
+ placeClass(interfaceClass);
+ }
+ }
+ }
+
+ currentOffset = classDefItem.place(currentIndex++, currentOffset);
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/CodeItem.java b/src/main/java/org/JesusFreke/dexlib/CodeItem.java
new file mode 100644
index 00000000..07c39b53
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/CodeItem.java
@@ -0,0 +1,384 @@
+/*
+ * [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.JesusFreke.dexlib;
+
+import org.JesusFreke.dexlib.code.Instruction;
+import org.JesusFreke.dexlib.code.Opcode;
+import org.JesusFreke.dexlib.ItemType;
+import org.JesusFreke.dexlib.util.Input;
+import org.JesusFreke.dexlib.util.Output;
+
+import java.util.ArrayList;
+
+public class CodeItem extends OffsettedItem {
+ private final Field[] fields;
+ private final ArrayList instructionList;
+ private final ArrayList tryItems = new ArrayList();
+ private final ArrayList catchHandlerList = new ArrayList();
+
+ private final ShortIntegerField registersCount;
+ private final ShortIntegerField inArgumentCount;
+ private final ShortIntegerField outArgumentCount;
+ private final ListSizeField triesCount;
+ private final OffsettedItemReference debugInfo;
+ private final IntegerField instructionsSize;
+ private final InstructionListField instructionListField;
+ private final PaddingField padding;
+ private final FieldListField tries;
+ private final EncodedCatchHandlerList catchHandlers;
+
+ public CodeItem(final DexFile dexFile, int offset) {
+ super(offset);
+
+ instructionList = new ArrayList();
+
+ fields = new Field[] {
+ registersCount = new ShortIntegerField(),
+ inArgumentCount = new ShortIntegerField(),
+ outArgumentCount = new ShortIntegerField(),
+ triesCount = new ListSizeField(tryItems, new ShortIntegerField()),
+ debugInfo = new OffsettedItemReference(dexFile.DebugInfoItemsSection, new IntegerField()),
+ instructionsSize = new IntegerField(),
+ instructionListField = new InstructionListField(dexFile),
+ padding = new PaddingField(),
+ tries = new FieldListField(tryItems) {
+ protected TryItem make() {
+ return new TryItem();
+ }
+ },
+
+ catchHandlers = new EncodedCatchHandlerList(dexFile)
+ };
+ }
+
+
+
+ public CodeItem(final DexFile dexFile, int registersCount, int inArguments, ArrayList instructions) {
+ super(-1);
+
+ this.instructionList = new ArrayList(instructions);
+ this.instructionListField = new InstructionListField(dexFile);
+
+ fields = new Field[] {
+ this.registersCount = new ShortIntegerField(registersCount),
+ this.inArgumentCount = new ShortIntegerField(inArguments),
+ this.outArgumentCount = new ShortIntegerField(instructionListField.getOutArguments()),
+ this.triesCount = new ListSizeField(tryItems, new ShortIntegerField(0)),
+ this.debugInfo = new OffsettedItemReference(dexFile, null, new IntegerField()),
+ this.instructionsSize = new IntegerField(instructionListField.getInstructionWordCount()),
+ instructionListField,
+ this.padding = new PaddingField(),
+ this.tries = new FieldListField(tryItems) {
+ protected TryItem make() {
+ return new TryItem();
+ }
+ },
+ this.catchHandlers = new EncodedCatchHandlerList(dexFile)
+ };
+ }
+
+ //TODO: take out
+ public void writeTo(Output out) {
+ super.writeTo(out);
+ }
+
+ protected int getAlignment() {
+ return 4;
+ }
+
+ public ItemType getItemType() {
+ return ItemType.TYPE_CODE_ITEM;
+ }
+
+ public Field[] getFields() {
+ return fields;
+ }
+
+ public class TryItem extends CompositeField {
+ private final Field[] fields;
+
+ public TryItem() {
+ fields = new Field[] {
+ new IntegerField(),
+ new ShortIntegerField(),
+ new ShortIntegerField()
+ };
+ }
+
+
+ protected Field[] getFields() {
+ return fields;
+ }
+ }
+
+ class EncodedCatchHandlerList extends CompositeField {
+ private boolean fieldPresent = false;
+
+ private final DexFile dexFile;
+
+ public EncodedCatchHandlerList(DexFile dexFile) {
+ this.dexFile = dexFile;
+ }
+
+ private final Field[] fields = new Field[] {
+ new ListSizeField(catchHandlerList, new Leb128Field()),
+ new FieldListField(catchHandlerList) {
+ protected EncodedCatchHandler make() {
+ return new EncodedCatchHandler(dexFile);
+ }
+ }
+ };
+
+ public void readFrom(Input in) {
+ if (tryItems.size() > 0) {
+ fieldPresent = true;
+ super.readFrom(in);
+ }
+ }
+
+ public void writeTo(Output out) {
+ if (fieldPresent) {
+ super.writeTo(out);
+ }
+ }
+
+ public int place(int offset) {
+ if (tryItems.size() > 0) {
+ fieldPresent = true;
+ return super.place(offset);
+ } else {
+ return offset;
+ }
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public void copyTo(DexFile dexFile, EncodedCatchHandlerList copy) {
+ super.copyTo(dexFile, copy);
+ copy.fieldPresent = fieldPresent;
+ }
+ }
+
+ public class EncodedCatchHandler extends CompositeField {
+ public final Field[] fields;
+ private ArrayList list = new ArrayList();
+ private boolean hasCatchAll = false;
+
+ public EncodedCatchHandler(final DexFile dexFile) {
+ fields = new Field[] {
+ new ListSizeField(list, new SignedLeb128Field() {
+ public void readFrom(Input in) {
+ super.readFrom(in);
+ hasCatchAll = (getCachedValue() <= 0);
+ }
+
+ public void cacheValue(int value) {
+ super.cacheValue(value * (hasCatchAll?-1:1));
+ }})
+ ,
+ new FieldListField(list) {
+ protected EncodedTypeAddrPair make() {
+ return new EncodedTypeAddrPair(dexFile);
+ }
+ },
+ new Leb128Field() {
+ public void readFrom(Input in) {
+ if (hasCatchAll) {
+ super.readFrom(in);
+ }
+ }
+
+ public void writeTo(Output out) {
+ if (hasCatchAll) {
+ super.writeTo(out);
+ }
+ }
+
+ public int place(int offset) {
+ if (hasCatchAll) {
+ return super.place(offset);
+ }
+ return offset;
+ }
+ }
+ };
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public void copyTo(DexFile dexFile, EncodedCatchHandler copy) {
+ super.copyTo(dexFile, copy);
+ copy.hasCatchAll = hasCatchAll;
+ }
+ }
+
+ public class EncodedTypeAddrPair extends CompositeField {
+ public final Field[] fields;
+
+ public EncodedTypeAddrPair(DexFile dexFile) {
+ fields = new Field[] {
+ new IndexedItemReference(dexFile.TypeIdsSection, new Leb128Field()),
+ new Leb128Field()
+ };
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+ }
+
+ private class InstructionListField implements Field {
+ private final DexFile dexFile;
+
+ public InstructionListField(DexFile dexFile) {
+ this.dexFile = dexFile;
+ }
+
+ public void writeTo(Output out) {
+ int startPosition = out.getCursor();
+ for (Instruction instruction: instructionList) {
+ instruction.writeTo(out);
+ }
+ if ((out.getCursor() - startPosition) != (instructionsSize.getCachedValue() * 2)) {
+ throw new RuntimeException("Did not write the expected amount of bytes");
+ }
+ }
+
+ public void readFrom(Input in) {
+ int numBytes = instructionsSize.getCachedValue() * 2;
+ int startPosition = in.getCursor();
+
+ do {
+ Instruction instruction = new Instruction(dexFile);
+ instruction.readFrom(in);
+ instructionList.add(instruction);
+ } while (in.getCursor() - startPosition < numBytes);
+
+ if (in.getCursor() - startPosition != numBytes) {
+ throw new RuntimeException("Read past the end of the code section");
+ }
+ }
+
+ public int place(int offset) {
+ return offset + (instructionsSize.getCachedValue() * 2);
+ }
+
+ public void copyTo(DexFile dexFile, InstructionListField copy) {
+ ArrayList copyInstructionList = copy.getInstructionList();
+ copyInstructionList.clear();
+ for (Instruction instruction: instructionList) {
+ Instruction instructionCopy = new Instruction(dexFile);
+ instruction.copyTo(dexFile, instructionCopy);
+ copyInstructionList.add(instructionCopy);
+ }
+ }
+
+ private ArrayList getInstructionList() {
+ return instructionList;
+ }
+
+ //return the word size of the instruction list
+ public int getInstructionWordCount() {
+ int bytes = 0;
+ //TODO: what about option padding before the special opcodes?
+ for (Instruction instruction: instructionList) {
+ bytes += instruction.getBytes().length;
+ }
+ return bytes/2;
+ }
+
+ //return the highest parameter word count of any method invokation
+ public int getOutArguments() {
+ int maxParamWordCount = 0;
+ for (Instruction instruction: instructionList) {
+ IndexedItem item = instruction.getReference();
+ if (item instanceof MethodIdItem) {
+ MethodIdItem methodIdItem = (MethodIdItem)item;
+ Opcode opcode = instruction.getOpcode();
+
+ boolean isStatic = false;
+ if (opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE) {
+ isStatic = true;
+ }
+ int paramWordCount = methodIdItem.getParameterWordCount(isStatic);
+
+ if (maxParamWordCount < paramWordCount) {
+ maxParamWordCount = paramWordCount;
+ }
+ }
+ }
+ return maxParamWordCount;
+ }
+ }
+
+ private class PaddingField implements Field {
+
+ public PaddingField() {
+ }
+
+ private boolean needsAlign() {
+ return (triesCount.getCachedValue() > 0) && (instructionsSize.getCachedValue() % 2 == 1);
+ }
+
+ public void writeTo(Output out) {
+ if (needsAlign()) {
+ out.writeShort(0);
+ }
+ }
+
+ public void readFrom(Input in) {
+ if (needsAlign()) {
+ in.skipBytes(2);
+ }
+ }
+
+ public int place(int offset) {
+ if (needsAlign()) {
+ return offset + 2;
+ } else {
+ return offset;
+ }
+ }
+
+ public int hashCode() {
+ return 0;
+ }
+
+ public boolean equals(Object o) {
+ return getClass() == o.getClass();
+ }
+
+ public void copyTo(DexFile dexFile, Field field) {
+ }
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/CompositeField.java b/src/main/java/org/JesusFreke/dexlib/CompositeField.java
new file mode 100644
index 00000000..e933ec2a
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/CompositeField.java
@@ -0,0 +1,102 @@
+/*
+ * [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.JesusFreke.dexlib;
+
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.Input;
+
+
+public abstract class CompositeField> implements Field {
+ /**
+ * Every instance of a specific subclass should return an array with the same structure,
+ * in other words have the same size, and the same type of field at each position.
+ * @return An array of fields that represents the sub-fields that make up this CompositeField
+ */
+ protected abstract Field[] getFields();
+
+ public void writeTo(Output out) {
+ for (Field field: getFields()) {
+ field.writeTo(out);
+ }
+ }
+
+ public void readFrom(Input in) {
+ for (Field field: getFields()) {
+ field.readFrom(in);
+ }
+ }
+
+ public int place(int offset) {
+ for (Field field: getFields()) {
+ offset = field.place(offset);
+ }
+ return offset;
+ }
+
+ public void copyTo(DexFile dexFile, T copy) {
+ Field[] fields = getFields();
+ Field[] copyFields = copy.getFields();
+ for (int i = 0; i < fields.length; i++) {
+ /**
+ * This assumes that the fields will be the same for every instance
+ * of a specific concrete subclass. By making this assumption, every subclass is
+ * prevented from having to implement copyTo
+ */
+ fields[i].copyTo(dexFile, copyFields[i]);
+ }
+ }
+
+ public int hashCode() {
+ int h = 1;
+ for (Field field: getFields()) {
+ h = h * 31 + field.hashCode();
+ }
+ return h;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof CompositeField)) {
+ return false;
+ }
+
+ CompositeField other = (CompositeField)o;
+ Field[] fields = getFields();
+ Field[] otherFields = other.getFields();
+ if (fields.length != otherFields.length) {
+ return false;
+ }
+ for (int i = 0; i < fields.length; i++) {
+ if (!fields[i].equals(otherFields[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/DebugInfoItem.java b/src/main/java/org/JesusFreke/dexlib/DebugInfoItem.java
new file mode 100644
index 00000000..e15c33f7
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/DebugInfoItem.java
@@ -0,0 +1,116 @@
+/*
+ * [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.JesusFreke.dexlib;
+
+import org.JesusFreke.dexlib.ItemType;
+import org.JesusFreke.dexlib.debug.DebugInstructionFactory;
+import org.JesusFreke.dexlib.debug.EndSequence;
+import org.JesusFreke.dexlib.debug.DebugInstruction;
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.Input;
+
+import java.util.ArrayList;
+
+public class DebugInfoItem extends OffsettedItem {
+ private final Field[] fields;
+
+ private final ArrayList> parameterNames =
+ new ArrayList>();
+
+ private ArrayList instructionFields = new ArrayList();
+
+ public DebugInfoItem(final DexFile dexFile, int offset) {
+ super(offset);
+
+ fields = new Field[] {
+ new Leb128Field(),
+ new ListSizeField(parameterNames, new Leb128Field()),
+ new FieldListField>(parameterNames) {
+ protected IndexedItemReference make() {
+ return new IndexedItemReference(dexFile.StringIdsSection, new Leb128p1Field());
+ }
+ },
+ new DebugInstructionList(dexFile)
+ };
+ }
+
+ protected int getAlignment() {
+ return 1;
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public ItemType getItemType() {
+ return ItemType.TYPE_DEBUG_INFO_ITEM;
+ }
+
+ private class DebugInstructionList implements Field {
+ private final DexFile dexFile;
+ private final ArrayList list;
+
+ public DebugInstructionList(DexFile dexFile) {
+ this.dexFile = dexFile;
+ list = instructionFields;
+ }
+
+ public void writeTo(Output out) {
+ for (DebugInstruction debugInstruction: list) {
+ debugInstruction.writeTo(out);
+ }
+ }
+
+ public void readFrom(Input in) {
+ DebugInstruction debugInstruction;
+ do {
+ debugInstruction = DebugInstructionFactory.readDebugInstruction(dexFile, in);
+ list.add(debugInstruction);
+ } while (!(debugInstruction instanceof EndSequence));
+ }
+
+ public int place(int offset) {
+ for (Field field: list) {
+ offset = field.place(offset);
+ }
+ return offset;
+ }
+
+ public void copyTo(DexFile dexFile, DebugInstructionList copy) {
+ copy.list.clear();
+ copy.list.ensureCapacity(list.size());
+ for (int i = 0; i < list.size(); i++) {
+ DebugInstruction debugInstruction = list.get(i);
+ DebugInstruction debugInstructionCopy = DebugInstructionFactory.makeDebugInstruction(dexFile, debugInstruction.getOpcode());
+ debugInstruction.copyTo(dexFile, debugInstructionCopy);
+ copy.list.add(debugInstructionCopy);
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/DexFile.java b/src/main/java/org/JesusFreke/dexlib/DexFile.java
new file mode 100644
index 00000000..7a77d4ad
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/DexFile.java
@@ -0,0 +1,390 @@
+/*
+ * [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.JesusFreke.dexlib;
+
+import org.JesusFreke.dexlib.util.Input;
+import org.JesusFreke.dexlib.util.ByteArrayInput;
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.FileUtils;
+
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.zip.Adler32;
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.DigestException;
+
+public class DexFile
+{
+ private final HashMap sectionsByType;
+ private final IndexedSection[] indexedSections;
+ private final OffsettedSection[] offsettedSections;
+ private int fileSize;
+ private int dataOffset;
+ private int dataSize;
+
+ private final DexFile dexFile = this;
+
+ private DexFile() {
+ sectionsByType = new HashMap(18);
+
+ sectionsByType.put(ItemType.TYPE_ANNOTATION_ITEM, AnnotationsSection);
+ sectionsByType.put(ItemType.TYPE_ANNOTATION_SET_ITEM, AnnotationSetsSection);
+ sectionsByType.put(ItemType.TYPE_ANNOTATION_SET_REF_LIST, AnnotationSetRefListsSection);
+ sectionsByType.put(ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM, AnnotationDirectoriesSection);
+ sectionsByType.put(ItemType.TYPE_CLASS_DATA_ITEM, ClassDataSection);
+ sectionsByType.put(ItemType.TYPE_CLASS_DEF_ITEM, ClassDefsSection);
+ sectionsByType.put(ItemType.TYPE_CODE_ITEM, CodeItemsSection);
+ sectionsByType.put(ItemType.TYPE_DEBUG_INFO_ITEM, DebugInfoItemsSection);
+ sectionsByType.put(ItemType.TYPE_ENCODED_ARRAY_ITEM, EncodedArraysSection);
+ sectionsByType.put(ItemType.TYPE_FIELD_ID_ITEM, FieldIdsSection);
+ sectionsByType.put(ItemType.TYPE_HEADER_ITEM, HeaderItemSection);
+ sectionsByType.put(ItemType.TYPE_MAP_LIST, MapSection);
+ sectionsByType.put(ItemType.TYPE_METHOD_ID_ITEM, MethodIdsSection);
+ sectionsByType.put(ItemType.TYPE_PROTO_ID_ITEM, ProtoIdsSection);
+ sectionsByType.put(ItemType.TYPE_STRING_DATA_ITEM, StringDataSection);
+ sectionsByType.put(ItemType.TYPE_STRING_ID_ITEM, StringIdsSection);
+ sectionsByType.put(ItemType.TYPE_TYPE_ID_ITEM, TypeIdsSection);
+ sectionsByType.put(ItemType.TYPE_TYPE_LIST, TypeListsSection);
+
+ indexedSections = new IndexedSection[] {
+ StringIdsSection,
+ TypeIdsSection,
+ ProtoIdsSection,
+ FieldIdsSection,
+ MethodIdsSection,
+ ClassDefsSection
+ };
+
+ offsettedSections = new OffsettedSection[] {
+ AnnotationSetsSection,
+ CodeItemsSection,
+ AnnotationDirectoriesSection,
+ TypeListsSection,
+ StringDataSection,
+ DebugInfoItemsSection,
+ AnnotationsSection,
+ EncodedArraysSection,
+ ClassDataSection,
+
+ AnnotationSetRefListsSection
+ };
+ }
+
+ public DexFile(File file) {
+ this();
+ Input in = new ByteArrayInput(FileUtils.readFile(file));
+
+ HeaderItemSection.readFrom(1, in);
+ HeaderItem headerItem = HeaderItemSection.items.get(0);
+
+ in.setCursor(headerItem.getMapOffset());
+
+ MapSection.readFrom(1, in);
+
+ for (MapField mapField: MapSection.items.get(0).getMapEntries()) {
+ Section section = sectionsByType.get(mapField.getSectionItemType());
+ if (section != null) {
+ in.setCursor(mapField.getSectionOffset());
+ section.readFrom(mapField.getSectionSize(), in);
+ }
+ }
+ }
+
+ public static DexFile makeBlankDexFile() {
+ DexFile dexFile = new DexFile();
+ try
+ {
+ dexFile.HeaderItemSection.intern(dexFile, new HeaderItem(dexFile, 0));
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ dexFile.MapSection.intern(dexFile, MapItem.makeBlankMapItem(dexFile));
+ return dexFile;
+ }
+
+
+ public Section getSectionForItem(T item) {
+ return sectionsByType.get(item.getItemType());
+ }
+
+ public Section getSectionForType(ItemType itemType) {
+ return sectionsByType.get(itemType);
+ }
+
+ public int getFileSize() {
+ return fileSize;
+ }
+
+ public int getDataOffset() {
+ return dataOffset;
+ }
+
+ public int getDataSize() {
+ return dataSize;
+ }
+
+ public void place() {
+ int offset = 0;
+
+ offset = HeaderItemSection.place(offset);
+ for (IndexedSection indexedSection: indexedSections) {
+ indexedSection.unplace();
+ offset = indexedSection.place(offset);
+ }
+
+ dataOffset = offset;
+
+ for (OffsettedSection offsettedSection: offsettedSections) {
+ offsettedSection.unplace();
+
+ offset = offsettedSection.place(offset);
+ }
+
+ offset = MapSection.place(offset);
+
+ dataSize = offset - dataOffset;
+ fileSize = offset;
+ }
+
+ public void writeTo(Output out) {
+ HeaderItemSection.writeTo(out);
+ for (IndexedSection indexedSection: indexedSections) {
+ indexedSection.writeTo(out);
+ }
+
+ for (OffsettedSection offsettedSection: offsettedSections) {
+ offsettedSection.writeTo(out);
+ }
+
+ MapSection.writeTo(out);
+ }
+
+ public ClassDefItem getClassByName(String className) {
+ for (ClassDefItem classDefItem: ClassDefsSection.items) {
+ if (classDefItem.getClassName().equals(className)) {
+ return classDefItem;
+ }
+ }
+ throw new RuntimeException("class not found");
+ }
+
+ public MethodIdItem[] getMethodsByClass(TypeIdItem classType) {
+ ArrayList methods = new ArrayList();
+
+ for (MethodIdItem methodIdItem: MethodIdsSection.items) {
+ if (methodIdItem.getClassType() == classType) {
+ methods.add(methodIdItem);
+ }
+ }
+
+ return methods.toArray(new MethodIdItem[0]);
+ }
+
+
+
+ public final IndexedSection HeaderItemSection = new IndexedSection() {
+ protected HeaderItem make(int index) {
+ try {
+ return new HeaderItem(dexFile, index);
+ } catch (UnsupportedEncodingException ex) {
+ //TODO: handle this
+ throw new RuntimeException(ex);
+ }
+ }
+ };
+
+ public final IndexedSection StringIdsSection = new IndexedSection() {
+ protected StringIdItem make(int index) {
+ return new StringIdItem(dexFile, index);
+ }
+ };
+
+ public final IndexedSection TypeIdsSection = new IndexedSection() {
+ protected TypeIdItem make(int index) {
+ return new TypeIdItem(dexFile, index);
+ }
+ };
+
+ public final IndexedSection ProtoIdsSection = new IndexedSection() {
+ protected ProtoIdItem make(int index) {
+ return new ProtoIdItem(dexFile, index);
+ }
+ };
+
+ public final IndexedSection FieldIdsSection = new IndexedSection() {
+ protected FieldIdItem make(int index) {
+ return new FieldIdItem(dexFile, index);
+ }
+ };
+
+ public final IndexedSection MethodIdsSection = new IndexedSection() {
+ protected MethodIdItem make(int index) {
+ return new MethodIdItem(dexFile, index);
+ }
+ };
+
+ public final IndexedSection ClassDefsSection = new IndexedSection() {
+ protected ClassDefItem make(int index) {
+ return new ClassDefItem(dexFile, index);
+ }
+
+ public int place(int offset) {
+ int ret = ClassDefItem.placeClassDefItems(this, offset);
+
+ this.offset = items.get(0).getOffset();
+ return ret;
+ }
+ };
+
+ public final IndexedSection MapSection = new IndexedSection() {
+ protected MapItem make(int index) {
+ return new MapItem(dexFile, index);
+ }
+
+ public MapItem intern(DexFile dexFile, MapItem item) {
+ this.items.add(item);
+ return item;
+ }
+ };
+
+ public final OffsettedSection TypeListsSection = new OffsettedSection() {
+ protected TypeListItem make(int offset) {
+ return new TypeListItem(dexFile, offset);
+ }
+ };
+
+ public final OffsettedSection AnnotationSetRefListsSection =
+ new OffsettedSection() {
+ protected AnnotationSetRefList make(int offset) {
+ return new AnnotationSetRefList(dexFile, offset);
+ }
+ };
+
+ public final OffsettedSection AnnotationSetsSection =
+ new OffsettedSection() {
+ protected AnnotationSetItem make(int offset) {
+ return new AnnotationSetItem(dexFile, offset);
+ }
+ };
+
+ public final OffsettedSection ClassDataSection = new OffsettedSection() {
+ protected ClassDataItem make(int offset) {
+ return new ClassDataItem(dexFile, offset);
+ }
+ };
+
+ public final OffsettedSection CodeItemsSection = new OffsettedSection() {
+ protected CodeItem make(int offset) {
+ return new CodeItem(dexFile, offset);
+ }
+ };
+
+ public final OffsettedSection StringDataSection = new OffsettedSection() {
+ protected StringDataItem make(int offset) {
+ return new StringDataItem(offset);
+ }
+ };
+
+ public final OffsettedSection DebugInfoItemsSection = new OffsettedSection() {
+ protected DebugInfoItem make(int offset) {
+ return new DebugInfoItem(dexFile, offset);
+ }
+ };
+
+ public final OffsettedSection AnnotationsSection = new OffsettedSection() {
+ protected AnnotationItem make(int offset) {
+ return new AnnotationItem(dexFile, offset);
+ }
+ };
+
+ public final OffsettedSection EncodedArraysSection = new OffsettedSection() {
+ protected EncodedArrayItem make(int offset) {
+ return new EncodedArrayItem(dexFile, offset);
+ }
+ };
+
+ public final OffsettedSection AnnotationDirectoriesSection =
+ new OffsettedSection() {
+ protected AnnotationDirectoryItem make(int offset) {
+ return new AnnotationDirectoryItem(dexFile, offset);
+ }
+ };
+
+
+ /**
+ * Calculates the signature for the .dex file in the
+ * given array, and modify the array to contain it.
+ *
+ * @param bytes non-null; the bytes of the file
+ */
+ public static void calcSignature(byte[] bytes) {
+ MessageDigest md;
+
+ try {
+ md = MessageDigest.getInstance("SHA-1");
+ } catch (NoSuchAlgorithmException ex) {
+ throw new RuntimeException(ex);
+ }
+
+ md.update(bytes, 32, bytes.length - 32);
+
+ try {
+ int amt = md.digest(bytes, 12, 20);
+ if (amt != 20) {
+ throw new RuntimeException("unexpected digest write: " + amt +
+ " bytes");
+ }
+ } catch (DigestException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * Calculates the checksum for the .dex file in the
+ * given array, and modify the array to contain it.
+ *
+ * @param bytes non-null; the bytes of the file
+ */
+ public static void calcChecksum(byte[] bytes) {
+ Adler32 a32 = new Adler32();
+
+ a32.update(bytes, 12, bytes.length - 12);
+
+ int sum = (int) a32.getValue();
+
+ bytes[8] = (byte) sum;
+ bytes[9] = (byte) (sum >> 8);
+ bytes[10] = (byte) (sum >> 16);
+ bytes[11] = (byte) (sum >> 24);
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedArrayItem.java b/src/main/java/org/JesusFreke/dexlib/EncodedArrayItem.java
new file mode 100644
index 00000000..032f2b9b
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedArrayItem.java
@@ -0,0 +1,91 @@
+/*
+ * [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.JesusFreke.dexlib;
+
+import org.JesusFreke.dexlib.ItemType;
+import org.JesusFreke.dexlib.EncodedValue.ArrayEncodedValueSubField;
+import org.JesusFreke.dexlib.EncodedValue.EncodedValue;
+import org.JesusFreke.dexlib.util.Input;
+import org.JesusFreke.dexlib.util.Output;
+
+import java.util.ArrayList;
+
+public class EncodedArrayItem extends OffsettedItem {
+ private final Field[] fields;
+
+ private final ArrayEncodedValueSubField encodedArray;
+
+ public EncodedArrayItem(DexFile dexFile, int offset) {
+ super(offset);
+
+ fields = new Field[] {
+ encodedArray = new ArrayEncodedValueSubField(dexFile)
+ };
+ }
+
+ public EncodedArrayItem(DexFile dexFile, ArrayList encodedValues) {
+ super(-1);
+
+ fields = new Field[] {
+ encodedArray = new ArrayEncodedValueSubField(dexFile, encodedValues)
+ };
+ }
+
+ public void readFrom(Input in) {
+ super.readFrom(in);
+ }
+
+ public int place(int index, int offset) {
+ return super.place(index, offset);
+ }
+
+ public void writeTo(Output out) {
+ super.writeTo(out);
+ }
+
+ protected int getAlignment() {
+ return 1;
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public int getOffset() {
+ return super.getOffset();
+ }
+
+ public void add(int index, EncodedValue value) {
+ encodedArray.add(index, value);
+ }
+
+ public ItemType getItemType() {
+ return ItemType.TYPE_ENCODED_ARRAY_ITEM;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/AnnotationElement.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/AnnotationElement.java
new file mode 100644
index 00000000..2bbbbc9d
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/AnnotationElement.java
@@ -0,0 +1,49 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.*;
+
+public class AnnotationElement extends CompositeField {
+ private Field[] fields;
+
+ private final IndexedItemReference elementName;
+ private final EncodedValue encodedValue;
+
+ public AnnotationElement(final DexFile dexFile) {
+ fields = new Field[] {
+ elementName = new IndexedItemReference(dexFile.StringIdsSection, new Leb128Field()),
+ encodedValue = new EncodedValue(dexFile)
+ };
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/AnnotationEncodedValueSubField.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/AnnotationEncodedValueSubField.java
new file mode 100644
index 00000000..91477717
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/AnnotationEncodedValueSubField.java
@@ -0,0 +1,72 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.*;
+
+import java.util.ArrayList;
+
+public class AnnotationEncodedValueSubField extends CompositeField
+ implements EncodedValueSubField {
+
+ private final Field[] fields;
+ private final ArrayList annotationElementList = new ArrayList();
+
+ private final IndexedItemReference annotationType;
+ private final ListSizeField annotationCount;
+ private final FieldListField annotationElements;
+
+ public AnnotationEncodedValueSubField(final DexFile dexFile) {
+ fields = new Field[] {
+ annotationType = new IndexedItemReference(dexFile.TypeIdsSection, new Leb128Field()),
+ annotationCount = new ListSizeField(annotationElementList, new Leb128Field()),
+ annotationElements = new FieldListField(annotationElementList) {
+ protected AnnotationElement make() {
+ return new AnnotationElement(dexFile);
+ }
+ }
+ };
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public void setInitialValueArg(byte valueArg) {
+ //valueArg is ignored for annotations
+ }
+
+ public byte getValueArg() {
+ return 0;
+ }
+
+ public ValueType getValueType() {
+ return ValueType.VALUE_ANNOTATION;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/ArrayEncodedValueSubField.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/ArrayEncodedValueSubField.java
new file mode 100644
index 00000000..67218955
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/ArrayEncodedValueSubField.java
@@ -0,0 +1,86 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.*;
+
+import java.util.ArrayList;
+
+public class ArrayEncodedValueSubField extends CompositeField
+ implements EncodedValueSubField
+{
+
+ private final Field[] fields;
+ private final ArrayList encodedValues;
+
+ public ArrayEncodedValueSubField(final DexFile dexFile) {
+ encodedValues = new ArrayList();
+ fields = new Field[] {
+ new ListSizeField(encodedValues, new Leb128Field()),
+ new FieldListField(encodedValues) {
+ protected EncodedValue make() {
+ return new EncodedValue(dexFile);
+ }
+ }
+ };
+ }
+
+ public ArrayEncodedValueSubField(final DexFile dexFile, ArrayList encodedValues) {
+ this.encodedValues = encodedValues;
+
+ fields = new Field[] {
+ new ListSizeField(this.encodedValues, new Leb128Field()),
+ new FieldListField(encodedValues) {
+ protected EncodedValue make() {
+ return new EncodedValue(dexFile);
+ }
+ }
+ };
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+
+ public void setInitialValueArg(byte valueArg) {
+ //valueArg is ignored for arrays
+ }
+
+ public byte getValueArg() {
+ return 0;
+ }
+
+ public ValueType getValueType() {
+ return ValueType.VALUE_ARRAY;
+ }
+
+ public void add(int index, EncodedValue encodedValue) {
+ encodedValues.add(index, encodedValue);
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/BoolEncodedValueSubField.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/BoolEncodedValueSubField.java
new file mode 100644
index 00000000..f6078e4e
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/BoolEncodedValueSubField.java
@@ -0,0 +1,62 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.Input;
+
+public class BoolEncodedValueSubField
+ extends SimpleEncodedValueSubField
+{
+ public BoolEncodedValueSubField() {
+ }
+
+ public BoolEncodedValueSubField(boolean value) {
+ this.value = value;
+ }
+
+ public void writeTo(Output out) {
+ }
+
+ public void readFrom(Input in) {
+ value = (valueArg != 0);
+ }
+
+ public int place(int offset) {
+ return offset;
+ }
+
+ public byte getValueArg() {
+ return (byte)(value?1:0);
+ }
+
+ public ValueType getValueType() {
+ return ValueType.VALUE_BOOLEAN;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/ByteEncodedValueSubField.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/ByteEncodedValueSubField.java
new file mode 100644
index 00000000..a59e9441
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/ByteEncodedValueSubField.java
@@ -0,0 +1,63 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.Input;
+
+public class ByteEncodedValueSubField
+ extends SimpleEncodedValueSubField
+{
+ public ByteEncodedValueSubField() {
+ }
+
+ public ByteEncodedValueSubField(byte value) {
+ this.value = value;
+ }
+
+ public void writeTo(Output out) {
+ out.writeByte(value);
+ }
+
+ public void readFrom(Input in) {
+ value = in.readByte();
+ }
+
+ public int place(int offset) {
+ return offset + 1;
+ }
+
+ public byte getValueArg() {
+ return 0;
+ }
+
+ public ValueType getValueType() {
+ return ValueType.VALUE_BYTE;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/CharEncodedValueSubField.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/CharEncodedValueSubField.java
new file mode 100644
index 00000000..ae70b879
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/CharEncodedValueSubField.java
@@ -0,0 +1,65 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.EncodedValueUtils;
+import org.JesusFreke.dexlib.util.Input;
+
+public class CharEncodedValueSubField
+ extends SimpleEncodedValueSubField
+{
+ public CharEncodedValueSubField() {
+ }
+
+ public CharEncodedValueSubField(char value) {
+ this.value = value;
+ }
+
+ public void writeTo(Output out) {
+ out.write(EncodedValueUtils.encodeUnsignedIntegralValue(value));
+ }
+
+ public void readFrom(Input in) {
+ value = (char)EncodedValueUtils.decodeUnsignedIntegralValue(
+ in.readBytes(valueArg + 1));
+ }
+
+ public int place(int offset) {
+ return offset + EncodedValueUtils.getRequiredBytesForUnsignedIntegralValue(value);
+ }
+
+ public byte getValueArg() {
+ return EncodedValueUtils.getRequiredBytesForUnsignedIntegralValue(value);
+ }
+
+ public ValueType getValueType() {
+ return ValueType.VALUE_CHAR;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/DoubleEncodedValueSubField.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/DoubleEncodedValueSubField.java
new file mode 100644
index 00000000..49e26db3
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/DoubleEncodedValueSubField.java
@@ -0,0 +1,68 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.EncodedValueUtils;
+import org.JesusFreke.dexlib.util.Input;
+
+public class DoubleEncodedValueSubField
+ extends SimpleEncodedValueSubField
+{
+ public DoubleEncodedValueSubField() {
+ }
+
+ public DoubleEncodedValueSubField(double value) {
+ this.value = value;
+ }
+
+ public void writeTo(Output out) {
+ out.write(EncodedValueUtils.encodeRightZeroExtendedValue(
+ Double.doubleToLongBits(value)));
+ }
+
+ public void readFrom(Input in) {
+ value = Double.longBitsToDouble(EncodedValueUtils.decodeRightZeroExtendedValue(
+ in.readBytes(valueArg + 1)));
+ }
+
+ public int place(int offset) {
+ return offset + EncodedValueUtils.getRequiredBytesForRightZeroExtendedValue(
+ Double.doubleToLongBits(value));
+ }
+
+ public byte getValueArg() {
+ return (byte)(EncodedValueUtils.getRequiredBytesForRightZeroExtendedValue(
+ Double.doubleToLongBits(value)) - 1);
+ }
+
+ public ValueType getValueType() {
+ return ValueType.VALUE_DOUBLE;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedIndexedItemReference.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedIndexedItemReference.java
new file mode 100644
index 00000000..c3a32a52
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedIndexedItemReference.java
@@ -0,0 +1,100 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.*;
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.Input;
+import org.JesusFreke.dexlib.util.EncodedValueUtils;
+
+/** TODO: it should be possible to somehow use the IndexedItemReference class */
+public class EncodedIndexedItemReference>
+ extends ItemReference>
+ implements EncodedValueSubField> {
+ private int initialValueArg;
+ private ValueType valueType;
+
+ public EncodedIndexedItemReference(IndexedSection section, ValueType valueType) {
+ super(section);
+ this.valueType = valueType;
+ }
+
+ //TODO: implement support for enum values
+ public EncodedIndexedItemReference(DexFile dexFile, T item) {
+ super(dexFile, item);
+ if (item.getClass() == StringIdItem.class) {
+ valueType = ValueType.VALUE_STRING;
+ } else if (item.getClass() == TypeIdItem.class) {
+ valueType = ValueType.VALUE_TYPE;
+ } else if (item.getClass() == FieldIdItem.class) {
+ valueType = ValueType.VALUE_FIELD;
+ } else if (item.getClass() == MethodIdItem.class) {
+ valueType = ValueType.VALUE_METHOD;
+ }
+ }
+
+ public void writeTo(Output out) {
+ T item = getReference();
+ if (!item.isPlaced()) {
+ throw new RuntimeException("Trying to write a reference to an item that hasn't been placed.");
+ }
+ out.write(EncodedValueUtils.encodeUnsignedIntegralValue(item.getIndex()));
+ }
+
+ public void readFrom(Input in) {
+ setReference(((IndexedSection)getSection()).getByIndex(
+ (int)EncodedValueUtils.decodeUnsignedIntegralValue(in.readBytes(initialValueArg))));
+ }
+
+ public int place(int offset) {
+ T item = getReference();
+ if (!item.isPlaced()) {
+ throw new RuntimeException("Trying to place a reference to an item that hasn't been placed.");
+ }
+ return offset + EncodedValueUtils.getRequiredBytesForUnsignedIntegralValue(item.getIndex());
+ }
+
+ public T getValue() {
+ return getReference();
+ }
+
+ public void setInitialValueArg(byte valueArg)
+ {
+ initialValueArg = valueArg;
+ }
+
+ public byte getValueArg() {
+ return EncodedValueUtils.getRequiredBytesForUnsignedIntegralValue(getReference().getIndex());
+ }
+
+ public ValueType getValueType() {
+ return valueType;
+ }
+
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedValue.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedValue.java
new file mode 100644
index 00000000..14d1e773
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedValue.java
@@ -0,0 +1,188 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.Input;
+import org.JesusFreke.dexlib.*;
+
+public class EncodedValue extends CompositeField {
+ private final Field[] fields;
+
+ private class ValueTypeArgField implements Field {
+ private ValueType valueType;
+ private byte valueArg;
+
+ public ValueTypeArgField() {
+ }
+
+ public ValueTypeArgField(ValueType valueType) {
+ this.valueType = valueType;
+ }
+
+ public void writeTo(Output out) {
+
+ byte value = (byte)(valueType.getMapValue() | (valueArg << 5));
+ out.writeByte(value);
+ }
+
+ public void readFrom(Input in) {
+ byte value = in.readByte();
+ valueType = ValueType.fromByte((byte)(value & 0x1F));
+ valueArg = (byte)((value & 0xFF) >>> 5);
+ }
+
+ public int place(int offset) {
+ return offset + 1;
+ }
+
+ public ValueType getValueType() {
+ return valueType;
+ }
+
+ public byte getValueArg() {
+ return valueArg;
+ }
+
+ public void copyTo(DexFile dexFile, ValueTypeArgField copy) {
+ copy.valueType = valueType;
+ copy.valueArg = valueArg;
+ }
+
+ public int hashCode() {
+ return valueType.hashCode() * 31 + ((Byte)valueArg).hashCode();
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof ValueTypeArgField)) {
+ return false;
+ }
+
+ ValueTypeArgField other = (ValueTypeArgField)o;
+ return valueType.equals(other.valueType) && (valueArg == other.valueArg);
+ }
+ }
+
+ private class EncodedValueSubFieldWrapper implements Field {
+ private final DexFile dexFile;
+ private EncodedValueSubField subField;
+
+ public EncodedValueSubFieldWrapper(DexFile dexFile) {
+ this.dexFile = dexFile;
+ }
+
+ public EncodedValueSubFieldWrapper(DexFile dexFile, EncodedValueSubField subField) {
+ this.dexFile = dexFile;
+ this.subField = subField;
+ }
+
+ public void writeTo(Output out) {
+ subField.writeTo(out);
+ }
+
+ public void readFrom(Input in) {
+ subField = EncodedValueSubFieldFactory.makeEncodedValueField(dexFile, getValueType());
+ subField.readFrom(in);
+ }
+
+ public int place(int offset) {
+ return subField.place(offset);
+ }
+
+ public EncodedValueSubField getEncodedValueSubField() {
+ return subField;
+ }
+
+ public void copyTo(DexFile dexFile, EncodedValueSubFieldWrapper copy) {
+ EncodedValueSubField fieldCopy = EncodedValueSubFieldFactory.makeEncodedValueField(dexFile, getValueType());
+ copy.subField = fieldCopy;
+
+ //both fields should be the same type because they were both made with the a call to
+ //EncodedValueSubFieldFactory.makeEncodedValueField using the same value type.
+ subField.copyTo(dexFile, fieldCopy);
+ }
+
+ public int hashCode() {
+ return subField.hashCode();
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof EncodedValueSubFieldWrapper)) {
+ return false;
+ }
+
+ EncodedValueSubFieldWrapper other = (EncodedValueSubFieldWrapper)o;
+ return subField.equals(other.subField);
+ }
+ }
+
+ private final ValueTypeArgField valueTypeArg;
+ private final EncodedValueSubFieldWrapper encodedValue;
+
+ public EncodedValue(final DexFile dexFile) {
+ fields = new Field[] {
+ valueTypeArg = new ValueTypeArgField(),
+ encodedValue = new EncodedValueSubFieldWrapper(dexFile)
+ };
+ }
+
+ public EncodedValue(final DexFile dexFile, EncodedValueSubField subField) {
+ fields = new Field[] {
+ valueTypeArg = new ValueTypeArgField(subField.getValueType()),
+ encodedValue = new EncodedValueSubFieldWrapper(dexFile, subField)
+ };
+ }
+
+ public int place(int offset) {
+ offset = valueTypeArg.place(offset);
+ int encodedValueStartOffset = offset;
+ int ret = encodedValue.place(offset);
+
+ int encodedValueLength = ret - encodedValueStartOffset;
+ if (encodedValueLength < 2 || valueTypeArg.valueType == ValueType.VALUE_ARRAY ||
+ valueTypeArg.valueType == ValueType.VALUE_ANNOTATION) {
+ valueTypeArg.valueArg = 0;
+ } else {
+ valueTypeArg.valueArg = (byte)(encodedValueLength - 1);
+ }
+ return ret;
+ }
+
+ public ValueType getValueType() {
+ return valueTypeArg.getValueType();
+ }
+
+ public byte getValueArg() {
+ return valueTypeArg.getValueArg();
+ }
+
+ protected Field[] getFields() {
+ return fields;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedValueSubField.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedValueSubField.java
new file mode 100644
index 00000000..9ab1b126
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedValueSubField.java
@@ -0,0 +1,38 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.Field;
+
+public interface EncodedValueSubField extends Field
+{
+ public void setInitialValueArg(byte valueArg);
+ public byte getValueArg();
+ public ValueType getValueType();
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedValueSubFieldFactory.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedValueSubFieldFactory.java
new file mode 100644
index 00000000..9ae0f401
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedValueSubFieldFactory.java
@@ -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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.*;
+
+
+public abstract class EncodedValueSubFieldFactory
+{
+ public static EncodedValueSubField makeEncodedValueField(DexFile dexFile, ValueType valueType) {
+ switch (valueType) {
+ case VALUE_NULL:
+ return new NullEncodedValueSubField();
+ case VALUE_BOOLEAN:
+ return new BoolEncodedValueSubField();
+ case VALUE_BYTE:
+ return new ByteEncodedValueSubField();
+ case VALUE_CHAR:
+ return new CharEncodedValueSubField();
+ case VALUE_SHORT:
+ return new ShortEncodedValueSubField();
+ case VALUE_INT:
+ return new IntEncodedValueSubField();
+ case VALUE_LONG:
+ return new LongEncodedValueSubField();
+ case VALUE_FLOAT:
+ return new FloatEncodedValueSubField();
+ case VALUE_DOUBLE:
+ return new DoubleEncodedValueSubField();
+ case VALUE_STRING:
+ return new EncodedIndexedItemReference(dexFile.StringIdsSection, valueType);
+ case VALUE_TYPE:
+ return new EncodedIndexedItemReference(dexFile.TypeIdsSection, valueType);
+ case VALUE_FIELD:
+ return new EncodedIndexedItemReference(dexFile.FieldIdsSection, valueType);
+ case VALUE_ENUM:
+ return new EncodedIndexedItemReference(dexFile.FieldIdsSection, valueType);
+ case VALUE_METHOD:
+ return new EncodedIndexedItemReference(dexFile.MethodIdsSection, valueType);
+ case VALUE_ARRAY:
+ return new ArrayEncodedValueSubField(dexFile);
+ case VALUE_ANNOTATION:
+ return new AnnotationEncodedValueSubField(dexFile);
+ default:
+ throw new RuntimeException("Invalid ValueType");
+ }
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/FloatEncodedValueSubField.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/FloatEncodedValueSubField.java
new file mode 100644
index 00000000..f58d2624
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/FloatEncodedValueSubField.java
@@ -0,0 +1,67 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.EncodedValueUtils;
+import org.JesusFreke.dexlib.util.Input;
+
+public class FloatEncodedValueSubField
+ extends SimpleEncodedValueSubField
+{
+ public FloatEncodedValueSubField() {
+ }
+
+ public FloatEncodedValueSubField(float value) {
+ this.value = value;
+ }
+ public void writeTo(Output out) {
+ out.write(EncodedValueUtils.encodeRightZeroExtendedValue(
+ ((long)Float.floatToIntBits(value)) << 32));
+ }
+
+ public void readFrom(Input in) {
+ long longValue = EncodedValueUtils.decodeRightZeroExtendedValue(in.readBytes(valueArg + 1));
+ value = Float.intBitsToFloat((int)((longValue >> 32) & 0xFFFFFFFF));
+ }
+
+ public int place(int offset) {
+ return offset + EncodedValueUtils.getRequiredBytesForRightZeroExtendedValue(
+ ((long)Float.floatToRawIntBits(value)) << 32);
+ }
+
+ public byte getValueArg() {
+ return (byte)(EncodedValueUtils.getRequiredBytesForRightZeroExtendedValue(
+ Float.floatToIntBits(value)) - 1);
+ }
+
+ public ValueType getValueType() {
+ return ValueType.VALUE_LONG;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/IntEncodedValueSubField.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/IntEncodedValueSubField.java
new file mode 100644
index 00000000..418fa492
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/IntEncodedValueSubField.java
@@ -0,0 +1,64 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.EncodedValueUtils;
+import org.JesusFreke.dexlib.util.Input;
+
+public class IntEncodedValueSubField
+ extends SimpleEncodedValueSubField
+{
+ public IntEncodedValueSubField() {
+ }
+
+ public IntEncodedValueSubField(int value) {
+ this.value = value;
+ }
+
+ public void writeTo(Output out) {
+ out.write(EncodedValueUtils.encodeSignedIntegralValue(value));
+ }
+
+ public void readFrom(Input in) {
+ value = (int)EncodedValueUtils.decodeSignedIntegralValue(in.readBytes(valueArg+1));
+ }
+
+ public int place(int offset) {
+ return offset + EncodedValueUtils.getRequiredBytesForSignedIntegralValue(value);
+ }
+
+ public byte getValueArg() {
+ return (byte)(EncodedValueUtils.getRequiredBytesForSignedIntegralValue(value) - 1);
+ }
+
+ public ValueType getValueType() {
+ return ValueType.VALUE_INT;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/LongEncodedValueSubField.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/LongEncodedValueSubField.java
new file mode 100644
index 00000000..9f4f95ac
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/LongEncodedValueSubField.java
@@ -0,0 +1,64 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.EncodedValueUtils;
+import org.JesusFreke.dexlib.util.Input;
+
+public class LongEncodedValueSubField
+ extends SimpleEncodedValueSubField
+{
+ public LongEncodedValueSubField() {
+ }
+
+ public LongEncodedValueSubField(long value) {
+ this.value = value;
+ }
+
+ public void writeTo(Output out) {
+ out.write(EncodedValueUtils.encodeSignedIntegralValue(value));
+ }
+
+ public void readFrom(Input in) {
+ value = EncodedValueUtils.decodeSignedIntegralValue(in.readBytes(valueArg+1));
+ }
+
+ public int place(int offset) {
+ return offset + EncodedValueUtils.getRequiredBytesForSignedIntegralValue(value);
+ }
+
+ public byte getValueArg() {
+ return (byte)(EncodedValueUtils.getRequiredBytesForSignedIntegralValue(value) - 1);
+ }
+
+ public ValueType getValueType() {
+ return ValueType.VALUE_LONG;
+ }
+}
diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/NullEncodedValueSubField.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/NullEncodedValueSubField.java
new file mode 100644
index 00000000..0b899835
--- /dev/null
+++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/NullEncodedValueSubField.java
@@ -0,0 +1,58 @@
+/*
+ * [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.JesusFreke.dexlib.EncodedValue;
+
+import org.JesusFreke.dexlib.util.Output;
+import org.JesusFreke.dexlib.util.Input;
+
+public class NullEncodedValueSubField
+ extends SimpleEncodedValueSubField