Initial commit

git-svn-id: https://smali.googlecode.com/svn/trunk@2 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
JesusFreke@JesusFreke.com 2009-04-16 06:14:38 +00:00
parent 06a26914de
commit f10d1a3598
107 changed files with 12019 additions and 0 deletions

56
pom.xml Normal file
View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>smali</groupId>
<artifactId>smali</artifactId>
<version>1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr3-maven-plugin</artifactId>
<version>3.1.3-1</version>
<executions>
<execution>
<id>smali</id>
<goals>
<goal>antlr</goal>
</goals>
<configuration>
<excludes><exclude>org/JesusFreke/smali/smaliTreeWalker.g</exclude></excludes>
</configuration>
</execution>
<execution>
<id>smaliTreeWalker</id>
<goals>
<goal>antlr</goal>
</goals>
<configuration>
<excludes><exclude>org/JesusFreke/smali/smali.g</exclude></excludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr-runtime</artifactId>
<version>3.1.3</version>
</dependency>
</dependencies>
</project>

View File

@ -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<Token> tokens = new ArrayDeque<Token>();
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;
}
;

View File

@ -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<Instruction> 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<TypeIdItem> 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<TypeIdItem> types]
@init
{
$types = new ArrayList<TypeIdItem>();
}
: (
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<Instruction> instructions]
@init
{
$instructions = new ArrayList<Instruction>();
}
: ^(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 <op>/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); };

View File

@ -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<AnnotationDirectoryItem> {
private final Field[] fields;
private final ArrayList<FieldAnnotation> fieldAnnotationList = new ArrayList<FieldAnnotation>();
private final ArrayList<MethodAnnotation> methodAnnotationList = new ArrayList<MethodAnnotation>();
private final ArrayList<ParameterAnnotation> parameterAnnotationList = new ArrayList<ParameterAnnotation>();
private final OffsettedItemReference<AnnotationSetItem> classAnnotations;
private final ListSizeField annotatedFieldsCount;
private final ListSizeField annotatedMethodsCount;
private final ListSizeField annotatedParametersCount;
private final FieldListField<FieldAnnotation> fieldAnnotations;
private final FieldListField<MethodAnnotation> methodAnnotations;
private final FieldListField<ParameterAnnotation> parameterAnnotations;
public AnnotationDirectoryItem(final DexFile dexFile, int offset) {
super(offset);
fields = new Field[] {
classAnnotations = new OffsettedItemReference<AnnotationSetItem>(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<FieldAnnotation>(fieldAnnotationList) {
protected FieldAnnotation make() {
return new FieldAnnotation(dexFile);
}
},
methodAnnotations = new FieldListField<MethodAnnotation>(methodAnnotationList) {
protected MethodAnnotation make() {
return new MethodAnnotation(dexFile);
}
},
parameterAnnotations = new FieldListField<ParameterAnnotation>(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<FieldAnnotation> {
private final Field[] fields;
public FieldAnnotation(DexFile dexFile) {
fields = new Field[] {
new IndexedItemReference<FieldIdItem>(dexFile.FieldIdsSection, new IntegerField()),
new OffsettedItemReference<AnnotationSetItem>(dexFile.AnnotationSetsSection, new IntegerField())
};
}
protected Field[] getFields() {
return fields;
}
}
public class MethodAnnotation extends CompositeField<MethodAnnotation> {
private final Field[] fields;
public MethodAnnotation(DexFile dexFile) {
fields = new Field[] {
new IndexedItemReference<MethodIdItem>(dexFile.MethodIdsSection, new IntegerField()),
new OffsettedItemReference<AnnotationSetItem>(dexFile.AnnotationSetsSection, new IntegerField())
};
}
protected Field[] getFields() {
return fields;
}
}
public class ParameterAnnotation extends CompositeField<ParameterAnnotation> {
private final Field[] fields;
public ParameterAnnotation(DexFile dexFile) {
fields = new Field[] {
new IndexedItemReference<MethodIdItem>(dexFile.MethodIdsSection, new IntegerField()),
new OffsettedItemReference<AnnotationSetItem>(dexFile.AnnotationSetsSection, new IntegerField())
};
}
protected Field[] getFields() {
return fields;
}
}
}

View File

@ -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<AnnotationItem> {
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);
}
}

View File

@ -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<AnnotationSetItem> {
private final Field[] fields;
private final ArrayList<OffsettedItemReference<AnnotationItem>> annotationReferences =
new ArrayList<OffsettedItemReference<AnnotationItem>>();
private final ListSizeField annotationCount;
private final FieldListField<OffsettedItemReference<AnnotationItem>> annotations;
public AnnotationSetItem(final DexFile dexFile, int offset) {
super(offset);
fields = new Field[] {
annotationCount = new ListSizeField(annotationReferences, new IntegerField()),
annotations = new FieldListField<OffsettedItemReference<AnnotationItem>>(annotationReferences) {
protected OffsettedItemReference<AnnotationItem> make() {
return new OffsettedItemReference<AnnotationItem>(dexFile.AnnotationsSection, new IntegerField());
}
}
};
}
protected int getAlignment() {
return 4;
}
protected Field[] getFields() {
return fields;
}
public ItemType getItemType() {
return ItemType.TYPE_ANNOTATION_SET_ITEM;
}
}

View File

@ -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<AnnotationSetRefList> {
private final Field[] fields;
private final ArrayList<OffsettedItemReference<AnnotationSetItem>> annotationSetReferences =
new ArrayList<OffsettedItemReference<AnnotationSetItem>>();
private final ListSizeField annotationSetCount;
private final FieldListField<OffsettedItemReference<AnnotationSetItem>> annotationSets;
public AnnotationSetRefList(final DexFile dexFile, int offset) {
super(offset);
fields = new Field[] {
annotationSetCount = new ListSizeField(annotationSetReferences, new IntegerField()),
annotationSets = new FieldListField<OffsettedItemReference<AnnotationSetItem>>(annotationSetReferences) {
protected OffsettedItemReference<AnnotationSetItem> make() {
return new OffsettedItemReference<AnnotationSetItem>(dexFile.AnnotationSetsSection, new IntegerField());
}
}
};
}
protected int getAlignment() {
return 4;
}
protected Field[] getFields() {
return fields;
}
public ItemType getItemType() {
return ItemType.TYPE_ANNOTATION_SET_REF_LIST;
}
}

View File

@ -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;
}
}

View File

@ -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<CachedIntegerValueField> {
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();
}
}

View File

@ -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<ClassDataItem> {
private final Field[] fields;
private final ArrayList<EncodedField> staticFieldList = new ArrayList<EncodedField>();
private final ArrayList<EncodedField> instanceFieldList = new ArrayList<EncodedField>();
private final ArrayList<EncodedMethod> directMethodList = new ArrayList<EncodedMethod>();
private final ArrayList<EncodedMethod> virtualMethodList = new ArrayList<EncodedMethod>();
private final ListSizeField staticFieldsCount;
private final ListSizeField instanceFieldsCount;
private final ListSizeField directMethodsCount;
private final ListSizeField virtualMethodsCount;
private final EncodedMemberList<EncodedField> staticFields;
private final EncodedMemberList<EncodedField> instanceFields;
private final EncodedMemberList<EncodedMethod> directMethods;
private final EncodedMemberList<EncodedMethod> 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<EncodedField>(staticFieldList) {
protected EncodedField make(EncodedField previousField) {
return new EncodedField(dexFile, previousField);
}
},
instanceFields = new EncodedMemberList<EncodedField>(instanceFieldList) {
protected EncodedField make(EncodedField previousField) {
return new EncodedField(dexFile, previousField);
}
},
directMethods = new EncodedMemberList<EncodedMethod>(directMethodList) {
protected EncodedMethod make(EncodedMethod previousMethod) {
return new EncodedMethod(dexFile, previousMethod);
}
},
virtualMethods = new EncodedMemberList<EncodedMethod>(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<T extends EncodedMember<T>> extends CompositeField<T> implements Field<T>, Comparable<T>
{
protected abstract void setPreviousMember(T previousMember);
}
private static abstract class EncodedMemberList<T extends EncodedMember<T>> implements Field<EncodedMemberList<T>> {
private final ArrayList<T> list;
public EncodedMemberList(ArrayList<T> 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<T> 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<T> other = (EncodedMemberList<T>)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<EncodedField> {
private final Field[] fields;
private final IndexedItemReference<FieldIdItem> 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<FieldIdItem>(dexFile.FieldIdsSection,
fieldIndexField = new Leb128DeltaField(previousIndexField)),
accessFlags = new Leb128Field()
};
}
public EncodedField(DexFile dexFile, FieldIdItem field, int accessFlags) {
fields = new Field[] {
this.field = new IndexedItemReference<FieldIdItem>(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<EncodedMethod> {
private final Field[] fields;
private final IndexedItemReference<MethodIdItem> method;
private final Leb128DeltaField methodIndexField;
private final Leb128Field accessFlags;
private final OffsettedItemReference<CodeItem> codeItem;
public EncodedMethod(DexFile dexFile, final EncodedMethod previousMethod) {
Leb128DeltaField previousIndexField = null;
if (previousMethod != null) {
previousIndexField = previousMethod.methodIndexField;
}
fields = new Field[] {
method = new IndexedItemReference<MethodIdItem>(dexFile.MethodIdsSection,
methodIndexField = new Leb128DeltaField(previousIndexField)),
accessFlags = new Leb128Field(),
codeItem = new OffsettedItemReference<CodeItem>(dexFile.CodeItemsSection, new Leb128Field())
};
}
public EncodedMethod(DexFile dexFile, MethodIdItem methodIdItem, int accessFlags, CodeItem codeItem) {
fields = new Field[] {
this.method = new IndexedItemReference<MethodIdItem>(dexFile, methodIdItem,
methodIndexField = new Leb128DeltaField(null)),
this.accessFlags = new Leb128Field(accessFlags),
this.codeItem = new OffsettedItemReference<CodeItem>(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;
}
}

View File

@ -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<ClassDefItem> {
private final Field[] fields;
private final IndexedItemReference<TypeIdItem> classType;
private final IntegerField accessFlags;
private final IndexedItemReference<TypeIdItem> superclassType;
private final OffsettedItemReference<TypeListItem> classInterfacesList;
private final IndexedItemReference<StringIdItem> sourceFile;
private final OffsettedItemReference<AnnotationDirectoryItem> classAnnotations;
private final OffsettedItemReference<ClassDataItem> classData;
private final OffsettedItemReference<EncodedArrayItem> staticFieldInitialValues;
private ArrayList<EncodedValue> staticFieldInitialValuesList;
private final DexFile dexFile;
public ClassDefItem(DexFile dexFile, int index) {
super(index);
this.dexFile = dexFile;
fields = new Field[] {
classType = new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new IntegerField()),
accessFlags = new IntegerField(),
superclassType = new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new IntegerField()),
classInterfacesList = new OffsettedItemReference<TypeListItem>(dexFile.TypeListsSection, new IntegerField()),
sourceFile = new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new IntegerField()),
classAnnotations = new OffsettedItemReference<AnnotationDirectoryItem>(dexFile.AnnotationDirectoriesSection, new IntegerField()),
classData = new OffsettedItemReference<ClassDataItem>(dexFile.ClassDataSection, new IntegerField()),
staticFieldInitialValues = new OffsettedItemReference<EncodedArrayItem>(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<TypeIdItem>(dexFile, classType, new IntegerField()),
this.accessFlags = new IntegerField(accessFlags),
superclassType = new IndexedItemReference<TypeIdItem>(dexFile, superType, new IntegerField()),
classInterfacesList = new OffsettedItemReference<TypeListItem>(dexFile.TypeListsSection, new IntegerField()),
sourceFile = new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new IntegerField()),
classAnnotations = new OffsettedItemReference<AnnotationDirectoryItem>(dexFile.AnnotationDirectoriesSection, new IntegerField()),
classData = new OffsettedItemReference<ClassDataItem>(dexFile, classDataItem, new IntegerField()),
staticFieldInitialValues = new OffsettedItemReference<EncodedArrayItem>(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<EncodedValue>();
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<ClassDefItem> 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<ClassDefItem> section;
private final HashMap<TypeIdItem, ClassDefItem> classDefsByType = new HashMap<TypeIdItem, ClassDefItem>();
private int currentIndex = 0;
private int currentOffset;
public ClassDefPlacer(IndexedSection<ClassDefItem> 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);
}
}
}
}

View File

@ -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<CodeItem> {
private final Field[] fields;
private final ArrayList<Instruction> instructionList;
private final ArrayList<TryItem> tryItems = new ArrayList<TryItem>();
private final ArrayList<EncodedCatchHandler> catchHandlerList = new ArrayList<EncodedCatchHandler>();
private final ShortIntegerField registersCount;
private final ShortIntegerField inArgumentCount;
private final ShortIntegerField outArgumentCount;
private final ListSizeField triesCount;
private final OffsettedItemReference<DebugInfoItem> debugInfo;
private final IntegerField instructionsSize;
private final InstructionListField instructionListField;
private final PaddingField padding;
private final FieldListField<TryItem> tries;
private final EncodedCatchHandlerList catchHandlers;
public CodeItem(final DexFile dexFile, int offset) {
super(offset);
instructionList = new ArrayList<Instruction>();
fields = new Field[] {
registersCount = new ShortIntegerField(),
inArgumentCount = new ShortIntegerField(),
outArgumentCount = new ShortIntegerField(),
triesCount = new ListSizeField(tryItems, new ShortIntegerField()),
debugInfo = new OffsettedItemReference<DebugInfoItem>(dexFile.DebugInfoItemsSection, new IntegerField()),
instructionsSize = new IntegerField(),
instructionListField = new InstructionListField(dexFile),
padding = new PaddingField(),
tries = new FieldListField<TryItem>(tryItems) {
protected TryItem make() {
return new TryItem();
}
},
catchHandlers = new EncodedCatchHandlerList(dexFile)
};
}
public CodeItem(final DexFile dexFile, int registersCount, int inArguments, ArrayList<Instruction> instructions) {
super(-1);
this.instructionList = new ArrayList<Instruction>(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<DebugInfoItem>(dexFile, null, new IntegerField()),
this.instructionsSize = new IntegerField(instructionListField.getInstructionWordCount()),
instructionListField,
this.padding = new PaddingField(),
this.tries = new FieldListField<TryItem>(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<TryItem> {
private final Field[] fields;
public TryItem() {
fields = new Field[] {
new IntegerField(),
new ShortIntegerField(),
new ShortIntegerField()
};
}
protected Field[] getFields() {
return fields;
}
}
class EncodedCatchHandlerList extends CompositeField<EncodedCatchHandlerList> {
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<EncodedCatchHandler>(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<EncodedCatchHandler> {
public final Field[] fields;
private ArrayList<EncodedTypeAddrPair> list = new ArrayList<EncodedTypeAddrPair>();
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<EncodedTypeAddrPair>(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<EncodedTypeAddrPair> {
public final Field[] fields;
public EncodedTypeAddrPair(DexFile dexFile) {
fields = new Field[] {
new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new Leb128Field()),
new Leb128Field()
};
}
protected Field[] getFields() {
return fields;
}
}
private class InstructionListField implements Field<InstructionListField> {
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<Instruction> copyInstructionList = copy.getInstructionList();
copyInstructionList.clear();
for (Instruction instruction: instructionList) {
Instruction instructionCopy = new Instruction(dexFile);
instruction.copyTo(dexFile, instructionCopy);
copyInstructionList.add(instructionCopy);
}
}
private ArrayList<Instruction> 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) {
}
}
}

View File

@ -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<T extends CompositeField<T>> implements Field<T> {
/**
* 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;
}
}

View File

@ -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<DebugInfoItem> {
private final Field[] fields;
private final ArrayList<IndexedItemReference<StringIdItem>> parameterNames =
new ArrayList<IndexedItemReference<StringIdItem>>();
private ArrayList<DebugInstruction> instructionFields = new ArrayList<DebugInstruction>();
public DebugInfoItem(final DexFile dexFile, int offset) {
super(offset);
fields = new Field[] {
new Leb128Field(),
new ListSizeField(parameterNames, new Leb128Field()),
new FieldListField<IndexedItemReference<StringIdItem>>(parameterNames) {
protected IndexedItemReference<StringIdItem> make() {
return new IndexedItemReference<StringIdItem>(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<DebugInstructionList> {
private final DexFile dexFile;
private final ArrayList<DebugInstruction> 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);
}
}
}
}

View File

@ -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<ItemType, Section> 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<ItemType, Section>(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 <T extends Item> Section<T> 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<MethodIdItem> methods = new ArrayList<MethodIdItem>();
for (MethodIdItem methodIdItem: MethodIdsSection.items) {
if (methodIdItem.getClassType() == classType) {
methods.add(methodIdItem);
}
}
return methods.toArray(new MethodIdItem[0]);
}
public final IndexedSection<HeaderItem> HeaderItemSection = new IndexedSection<HeaderItem>() {
protected HeaderItem make(int index) {
try {
return new HeaderItem(dexFile, index);
} catch (UnsupportedEncodingException ex) {
//TODO: handle this
throw new RuntimeException(ex);
}
}
};
public final IndexedSection<StringIdItem> StringIdsSection = new IndexedSection<StringIdItem>() {
protected StringIdItem make(int index) {
return new StringIdItem(dexFile, index);
}
};
public final IndexedSection<TypeIdItem> TypeIdsSection = new IndexedSection<TypeIdItem>() {
protected TypeIdItem make(int index) {
return new TypeIdItem(dexFile, index);
}
};
public final IndexedSection<ProtoIdItem> ProtoIdsSection = new IndexedSection<ProtoIdItem>() {
protected ProtoIdItem make(int index) {
return new ProtoIdItem(dexFile, index);
}
};
public final IndexedSection<FieldIdItem> FieldIdsSection = new IndexedSection<FieldIdItem>() {
protected FieldIdItem make(int index) {
return new FieldIdItem(dexFile, index);
}
};
public final IndexedSection<MethodIdItem> MethodIdsSection = new IndexedSection<MethodIdItem>() {
protected MethodIdItem make(int index) {
return new MethodIdItem(dexFile, index);
}
};
public final IndexedSection<ClassDefItem> ClassDefsSection = new IndexedSection<ClassDefItem>() {
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<MapItem> MapSection = new IndexedSection<MapItem>() {
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<TypeListItem> TypeListsSection = new OffsettedSection<TypeListItem>() {
protected TypeListItem make(int offset) {
return new TypeListItem(dexFile, offset);
}
};
public final OffsettedSection<AnnotationSetRefList> AnnotationSetRefListsSection =
new OffsettedSection<AnnotationSetRefList>() {
protected AnnotationSetRefList make(int offset) {
return new AnnotationSetRefList(dexFile, offset);
}
};
public final OffsettedSection<AnnotationSetItem> AnnotationSetsSection =
new OffsettedSection<AnnotationSetItem>() {
protected AnnotationSetItem make(int offset) {
return new AnnotationSetItem(dexFile, offset);
}
};
public final OffsettedSection<ClassDataItem> ClassDataSection = new OffsettedSection<ClassDataItem>() {
protected ClassDataItem make(int offset) {
return new ClassDataItem(dexFile, offset);
}
};
public final OffsettedSection<CodeItem> CodeItemsSection = new OffsettedSection<CodeItem>() {
protected CodeItem make(int offset) {
return new CodeItem(dexFile, offset);
}
};
public final OffsettedSection<StringDataItem> StringDataSection = new OffsettedSection<StringDataItem>() {
protected StringDataItem make(int offset) {
return new StringDataItem(offset);
}
};
public final OffsettedSection<DebugInfoItem> DebugInfoItemsSection = new OffsettedSection<DebugInfoItem>() {
protected DebugInfoItem make(int offset) {
return new DebugInfoItem(dexFile, offset);
}
};
public final OffsettedSection<AnnotationItem> AnnotationsSection = new OffsettedSection<AnnotationItem>() {
protected AnnotationItem make(int offset) {
return new AnnotationItem(dexFile, offset);
}
};
public final OffsettedSection<EncodedArrayItem> EncodedArraysSection = new OffsettedSection<EncodedArrayItem>() {
protected EncodedArrayItem make(int offset) {
return new EncodedArrayItem(dexFile, offset);
}
};
public final OffsettedSection<AnnotationDirectoryItem> AnnotationDirectoriesSection =
new OffsettedSection<AnnotationDirectoryItem>() {
protected AnnotationDirectoryItem make(int offset) {
return new AnnotationDirectoryItem(dexFile, offset);
}
};
/**
* Calculates the signature for the <code>.dex</code> 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 <code>.dex</code> 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);
}
}

View File

@ -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<EncodedArrayItem> {
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<EncodedValue> 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;
}
}

View File

@ -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<AnnotationElement> {
private Field[] fields;
private final IndexedItemReference<StringIdItem> elementName;
private final EncodedValue encodedValue;
public AnnotationElement(final DexFile dexFile) {
fields = new Field[] {
elementName = new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new Leb128Field()),
encodedValue = new EncodedValue(dexFile)
};
}
protected Field[] getFields() {
return fields;
}
}

View File

@ -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<AnnotationEncodedValueSubField>
implements EncodedValueSubField<AnnotationEncodedValueSubField> {
private final Field[] fields;
private final ArrayList<AnnotationElement> annotationElementList = new ArrayList<AnnotationElement>();
private final IndexedItemReference<TypeIdItem> annotationType;
private final ListSizeField annotationCount;
private final FieldListField<AnnotationElement> annotationElements;
public AnnotationEncodedValueSubField(final DexFile dexFile) {
fields = new Field[] {
annotationType = new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new Leb128Field()),
annotationCount = new ListSizeField(annotationElementList, new Leb128Field()),
annotationElements = new FieldListField<AnnotationElement>(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;
}
}

View File

@ -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<ArrayEncodedValueSubField>
implements EncodedValueSubField<ArrayEncodedValueSubField>
{
private final Field[] fields;
private final ArrayList<EncodedValue> encodedValues;
public ArrayEncodedValueSubField(final DexFile dexFile) {
encodedValues = new ArrayList<EncodedValue>();
fields = new Field[] {
new ListSizeField(encodedValues, new Leb128Field()),
new FieldListField<EncodedValue>(encodedValues) {
protected EncodedValue make() {
return new EncodedValue(dexFile);
}
}
};
}
public ArrayEncodedValueSubField(final DexFile dexFile, ArrayList<EncodedValue> encodedValues) {
this.encodedValues = encodedValues;
fields = new Field[] {
new ListSizeField(this.encodedValues, new Leb128Field()),
new FieldListField<EncodedValue>(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);
}
}

View File

@ -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<Boolean, BoolEncodedValueSubField>
{
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;
}
}

View File

@ -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<Byte, ByteEncodedValueSubField>
{
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;
}
}

View File

@ -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<Character, CharEncodedValueSubField>
{
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;
}
}

View File

@ -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<Double, DoubleEncodedValueSubField>
{
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;
}
}

View File

@ -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<T extends IndexedItem<T>>
extends ItemReference<T, EncodedIndexedItemReference<T>>
implements EncodedValueSubField<EncodedIndexedItemReference<T>> {
private int initialValueArg;
private ValueType valueType;
public EncodedIndexedItemReference(IndexedSection<T> 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<T>)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;
}
}

View File

@ -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<EncodedValue> {
private final Field[] fields;
private class ValueTypeArgField implements Field<ValueTypeArgField> {
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<EncodedValueSubFieldWrapper> {
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;
}
}

View File

@ -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<T extends EncodedValueSubField> extends Field<T>
{
public void setInitialValueArg(byte valueArg);
public byte getValueArg();
public ValueType getValueType();
}

View File

@ -0,0 +1,74 @@
/*
* [The "BSD licence"]
* Copyright (c) 2009 Ben Gruver
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.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<StringIdItem>(dexFile.StringIdsSection, valueType);
case VALUE_TYPE:
return new EncodedIndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, valueType);
case VALUE_FIELD:
return new EncodedIndexedItemReference<FieldIdItem>(dexFile.FieldIdsSection, valueType);
case VALUE_ENUM:
return new EncodedIndexedItemReference<FieldIdItem>(dexFile.FieldIdsSection, valueType);
case VALUE_METHOD:
return new EncodedIndexedItemReference<MethodIdItem>(dexFile.MethodIdsSection, valueType);
case VALUE_ARRAY:
return new ArrayEncodedValueSubField(dexFile);
case VALUE_ANNOTATION:
return new AnnotationEncodedValueSubField(dexFile);
default:
throw new RuntimeException("Invalid ValueType");
}
}
}

View File

@ -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<Float, FloatEncodedValueSubField>
{
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;
}
}

View File

@ -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<Integer, IntEncodedValueSubField>
{
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;
}
}

View File

@ -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<Long, LongEncodedValueSubField>
{
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;
}
}

View File

@ -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<Object, NullEncodedValueSubField>
{
public NullEncodedValueSubField() {
}
public void writeTo(Output out) {
}
public void readFrom(Input in) {
value = null;
}
public int place(int offset) {
return offset;
}
public byte getValueArg() {
return 0;
}
public ValueType getValueType() {
return ValueType.VALUE_NULL;
}
}

View File

@ -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 ShortEncodedValueSubField
extends SimpleEncodedValueSubField<Short, ShortEncodedValueSubField>
{
public ShortEncodedValueSubField() {
}
public ShortEncodedValueSubField(short value) {
this.value = value;
}
public void writeTo(Output out) {
out.write(EncodedValueUtils.encodeSignedIntegralValue(value));
}
public void readFrom(Input in) {
value = (short)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_SHORT;
}
}

View File

@ -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.DexFile;
public abstract class SimpleEncodedValueSubField<V, T extends SimpleEncodedValueSubField<V,T>> implements EncodedValueSubField<T>
{
protected V value;
protected byte valueArg = 0;
public V getValue() {
return value;
}
public void setInitialValueArg(byte valueArg) {
this.valueArg = valueArg;
}
public void copyTo(DexFile dexFile, T copy) {
copy.value = value;
}
public int hashCode() {
if (value == null) {
return 0;
}
return value.hashCode();
}
public boolean equals(Object o) {
if (!(o instanceof SimpleEncodedValueSubField)) {
return false;
}
SimpleEncodedValueSubField other = (SimpleEncodedValueSubField)o;
if (value == null) {
return other.value == null;
}
return value.equals(other.value);
}
}

View File

@ -0,0 +1,87 @@
/*
* [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 java.util.TreeMap;
public enum ValueType {
VALUE_BYTE((byte) 0x00),
VALUE_SHORT((byte) 0x02),
VALUE_CHAR((byte) 0x03),
VALUE_INT((byte) 0x04),
VALUE_LONG((byte) 0x06),
VALUE_FLOAT((byte) 0x10),
VALUE_DOUBLE((byte) 0x11),
VALUE_STRING((byte) 0x17),
VALUE_TYPE((byte) 0x18),
VALUE_FIELD((byte) 0x19),
VALUE_METHOD((byte) 0x1a),
VALUE_ENUM((byte) 0x1b),
VALUE_ARRAY((byte) 0x1c),
VALUE_ANNOTATION((byte) 0x1d),
VALUE_NULL((byte) 0x1e),
VALUE_BOOLEAN((byte) 0x1f);
/**
* A map to facilitate looking up an <code>ItemType</code> by ordinal
*/
private final static TreeMap<Byte, ValueType> valueTypeIntegerMap;
/** builds the <code>itemTypeIntegerMap</code> object */
static {
valueTypeIntegerMap = new TreeMap<Byte, ValueType>();
for (ValueType valueType : ValueType.values()) {
valueTypeIntegerMap.put(valueType.getMapValue(), valueType);
}
}
private final byte mapValue;
private ValueType(byte mapValue) {
this.mapValue = mapValue;
}
public byte getMapValue() {
return mapValue;
}
/**
* Converts a byte value to the corresponding ValueType enum value,
* or null if the value isn't a valid ValueType value
*
* @param valueType the int value to convert to a ValueType
* @return the ValueType enum value corresponding to valueType, or null
* if not a valid ValueType value
*/
public static ValueType fromByte(byte valueType) {
return valueTypeIntegerMap.get(valueType);
}
}

View File

@ -0,0 +1,39 @@
/*
* [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 interface Field<T extends Field> {
public void writeTo(Output out);
public void readFrom(Input in);
public int place(int offset);
public void copyTo(DexFile dexFile, T copy);
}

View File

@ -0,0 +1,96 @@
/*
* [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;
public class FieldIdItem extends IndexedItem<FieldIdItem> {
private final Field[] fields;
private final IndexedItemReference<TypeIdItem> classType;
private final IndexedItemReference<TypeIdItem> fieldType;
private final IndexedItemReference<StringIdItem> fieldName;
public FieldIdItem(DexFile dexFile, int index) {
super(index);
fields = new Field[] {
classType = new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new ShortIntegerField()),
fieldType = new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new ShortIntegerField()),
fieldName = new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new IntegerField())
};
}
public FieldIdItem(DexFile dexFile, TypeIdItem classType, StringIdItem fieldName, TypeIdItem fieldType) {
super(-1);
fields = new Field[] {
this.classType = new IndexedItemReference<TypeIdItem>(dexFile, classType, new ShortIntegerField()),
this.fieldType = new IndexedItemReference<TypeIdItem>(dexFile, fieldType, new ShortIntegerField()),
this.fieldName = new IndexedItemReference<StringIdItem>(dexFile, fieldName, new IntegerField())
};
}
public FieldIdItem(DexFile dexFile, TypeIdItem classType, String fieldName, TypeIdItem fieldType) {
this(dexFile, classType, new StringIdItem(dexFile, fieldName), fieldType);
}
protected int getAlignment() {
return 4;
}
protected Field[] getFields() {
return fields;
}
public ItemType getItemType() {
return ItemType.TYPE_FIELD_ID_ITEM;
}
public String toString() {
return classType.toString() + " - " + fieldName.toString();
}
public int compareTo(FieldIdItem o) {
int result = classType.compareTo(o.classType);
if (result != 0) {
return result;
}
result = fieldName.compareTo(o.fieldName);
if (result != 0) {
return result;
}
return fieldType.compareTo(o.fieldType);
}
public TypeIdItem getFieldType() {
return fieldType.getReference();
}
}

View File

@ -0,0 +1,105 @@
/*
* [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;
import java.util.ArrayList;
public abstract class FieldListField<T extends Field> implements Field<FieldListField<T>> {
private final ArrayList<T> list;
public FieldListField(ArrayList<T> list) {
this.list = list;
}
public void writeTo(Output out) {
for (Field field: list) {
field.writeTo(out);
}
}
public void readFrom(Input in) {
for (int i = 0; i < list.size(); i++) {
T field = list.get(i);
if (field == null) {
field = make();
list.set(i, field);
}
field.readFrom(in);
}
}
protected abstract T make();
public int place(int offset) {
for (Field field: list) {
offset = field.place(offset);
}
return offset;
}
public void copyTo(DexFile dexFile, FieldListField<T> copy) {
copy.list.clear();
copy.list.ensureCapacity(list.size());
for (int i = 0; i < list.size(); i++) {
T fieldCopy = copy.make();
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 FieldListField)) {
return false;
}
FieldListField other = (FieldListField)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;
}
}

View File

@ -0,0 +1,66 @@
/*
* [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;
import org.JesusFreke.dexlib.util.ByteArray;
public class FixedByteArrayField implements Field<FixedByteArrayField> {
protected byte[] value;
public FixedByteArrayField(int size) {
value = new byte[size];
}
public FixedByteArrayField(byte[] bytes) {
this.value = bytes.clone();
}
public FixedByteArrayField(ByteArray byteArray) {
value = new byte[byteArray.size()];
byteArray.getBytes(value, 0);
}
public void writeTo(Output out) {
out.write(value);
}
public void readFrom(Input in) {
in.read(value);
}
public int place(int offset) {
return offset + value.length;
}
public void copyTo(DexFile dexFile, FixedByteArrayField copy) {
copy.value = value.clone();
}
}

View File

@ -0,0 +1,169 @@
/*
* [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 java.io.UnsupportedEncodingException;
public class HeaderItem extends IndexedItem<HeaderItem> {
/**
* non-null; the file format magic number, represented as the
* low-order bytes of a string
*/
private static final String MAGIC = "dex\n035" + '\0';
/** size of this section, in bytes */
private static final int HEADER_SIZE = 0x70;
/** the endianness tag */
private static final int ENDIAN_TAG = 0x12345678;
private final Field[] fields;
protected Field[] getFields() {
return fields;
}
private final FixedByteArrayField magic;
private final IntegerField checksum;
private final FixedByteArrayField signature;
private final IntegerField fileSize;
private final IntegerField headerSize;
private final IntegerField endianTag;
private final IntegerField linkSize;
private final IntegerField linkOff;
private final IntegerField mapOff;
private final SectionHeaderInfo StringIdsInfo;
private final SectionHeaderInfo TypeIdsInfo;
private final SectionHeaderInfo ProtoIdsInfo;
private final SectionHeaderInfo FieldIdsInfo;
private final SectionHeaderInfo MethodIdsInfo;
private final SectionHeaderInfo ClassDefsInfo;
private final IntegerField dataSize;
private final IntegerField dataOff;
public HeaderItem(final DexFile file, int index) throws UnsupportedEncodingException {
super(index);
fields = new Field[] {
magic = new FixedByteArrayField(MAGIC.getBytes("US-ASCII")),
checksum = new IntegerField() {
public void writeTo(Output out) {
cacheValue(0);
super.writeTo(out);
}
},
signature = new FixedByteArrayField(20) {
public void writeTo(Output out) {
for (int i = 0; i < value.length; i++) {
value[i] = 0;
}
super.writeTo(out);
}
},
fileSize = new IntegerField() {
public void writeTo(Output out) {
cacheValue(file.getFileSize());
super.writeTo(out);
}
},
headerSize = new IntegerField(HEADER_SIZE),
endianTag = new IntegerField(ENDIAN_TAG),
linkSize = new IntegerField(0),
linkOff = new IntegerField(0),
mapOff = new IntegerField() {
public void writeTo(Output out) {
cacheValue(file.MapSection.getOffset());
super.writeTo(out);
}
},
StringIdsInfo = new SectionHeaderInfo() {
protected Section getSection() {
return file.StringIdsSection;
}
},
TypeIdsInfo = new SectionHeaderInfo() {
protected Section getSection() {
return file.TypeIdsSection;
}
},
ProtoIdsInfo = new SectionHeaderInfo() {
protected Section getSection() {
return file.ProtoIdsSection;
}
},
FieldIdsInfo = new SectionHeaderInfo() {
protected Section getSection() {
return file.FieldIdsSection;
}
},
MethodIdsInfo = new SectionHeaderInfo() {
protected Section getSection() {
return file.MethodIdsSection;
}
},
ClassDefsInfo = new SectionHeaderInfo() {
protected Section getSection() {
return file.ClassDefsSection;
}
},
dataSize = new IntegerField() {
public void writeTo(Output out) {
cacheValue(file.getDataSize());
super.writeTo(out);
}
},
dataOff = new IntegerField() {
public void writeTo(Output out) {
cacheValue(file.getDataOffset());
super.writeTo(out);
}
}
};
}
public int getMapOffset() {
return mapOff.getCachedValue();
}
protected int getAlignment() {
return 4;
}
public ItemType getItemType() {
return ItemType.TYPE_HEADER_ITEM;
}
public int compareTo(HeaderItem o) {
//there is only 1 header item
return 0;
}
}

View File

@ -0,0 +1,46 @@
/*
* [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 IndexedItem<T extends IndexedItem> extends Item<T> implements Comparable<T> {
private int index;
protected IndexedItem(int index) {
this.index = index;
}
public int place(int index, int offset) {
this.index = index;
return super.place(index, offset);
}
public int getIndex() {
return index;
}
}

View File

@ -0,0 +1,79 @@
/*
* [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 IndexedItemReference<T extends IndexedItem<T>> extends
ItemReference<T,IndexedItemReference<T>> implements Comparable<IndexedItemReference<T>> {
private final CachedIntegerValueField underlyingField;
public IndexedItemReference(IndexedSection<T> section, CachedIntegerValueField underlyingField) {
super(section);
this.underlyingField = underlyingField;
}
public IndexedItemReference(DexFile dexFile, T item, CachedIntegerValueField underlyingField) {
super(dexFile, item);
this.underlyingField = underlyingField;
}
public void writeTo(Output out) {
T item = getReference();
if (item != null && !item.isPlaced()) {
throw new RuntimeException("Trying to write a reference to an item that hasn't been placed.");
}
underlyingField.writeTo(out);
}
public void readFrom(Input in) {
underlyingField.readFrom(in);
if (underlyingField.getCachedValue() != -1) {
setReference(getSection().getByIndex(underlyingField.getCachedValue()));
}
}
public IndexedSection<T> getSection() {
return (IndexedSection<T>)super.getSection();
}
public int place(int offset) {
if (getReference() != null) {
underlyingField.cacheValue(getReference().getIndex());
} else {
underlyingField.cacheValue(-1);
}
return underlyingField.place(offset);
}
public int compareTo(IndexedItemReference<T> o) {
return getReference().compareTo(o.getReference());
}
}

View File

@ -0,0 +1,88 @@
/*
* [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 java.util.Collections;
public abstract class IndexedSection<T extends IndexedItem<T>> extends Section<T> {
public IndexedSection() {
}
public T getByIndex(int index) {
for (int i = items.size(); i <= index; i++) {
items.add(null);
}
T item = items.get(index);
if (item == null) {
item = make(index);
items.set(index, item);
}
return item;
}
public void readFrom(int size, Input in) {
super.setSize(size);
for (int i = 0; i < size(); i++) {
T item = getByIndex(i);
item.readFrom(in);
in.alignTo(item.getAlignment());
}
}
protected abstract T make(int index);
public T intern(DexFile dexFile, T item) {
T itemToReturn = getInternedItem(item);
if (itemToReturn == null) {
/**
* Make a new item at the end of this section, and copy the fields
* to the new item
*/
itemToReturn = getByIndex(size());
item.copyTo(dexFile, itemToReturn);
uniqueItems.put(itemToReturn, itemToReturn);
}
return itemToReturn;
}
protected void sortSection() {
Collections.sort(items);
}
public int place(int offset) {
sortSection();
return super.place(offset);
}
}

View File

@ -0,0 +1,70 @@
/*
* [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 IntegerField extends CachedIntegerValueField {
protected int value = 0;
public IntegerField() {
}
public IntegerField(int value) {
this.value = value;
}
public void writeTo(Output out) {
out.writeInt(value);
}
public void readFrom(Input in) {
value = in.readInt();
}
public int place(int offset) {
return offset + 4;
}
/**
* This method returns the integer value that has been cached. This
* value is either the value that the field was constructed with, the
* value that was read via <code>readFrom</code>, or the value that was
* cached when <code>place</code> was called
* @return the cached value
*/
public int getCachedValue() {
return value;
}
public void cacheValue(int value) {
this.value = value;
}
}

View File

@ -0,0 +1,142 @@
/*
* [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.Output;
import org.JesusFreke.dexlib.ItemType;
public abstract class Item<T extends Item> {
private int offset = -1;
protected Item() {
}
protected Item(int offset) {
this.offset = offset;
}
public boolean isPlaced() {
return offset > -1;
}
public void unplace() {
offset = -1;
}
public int place(int index, int offset) {
offset = alignOffset(offset);
//TODO: take out
System.out.println("Placing item type " + getItemType().getTypeName() + " at offset " + ((Integer)offset).toString());
this.offset = offset;
Field[] fields = getFields();
for (Field field: fields) {
offset = field.place(offset);
}
return offset;
}
public void readFrom(Input in) {
for (Field field: getFields()) {
field.readFrom(in);
}
}
public void writeTo(Output out) {
out.alignTo(getAlignment());
//TODO: take out
System.out.println("Writing item type " + getItemType().getTypeName() + " at offset " + ((Integer)out.getCursor()).toString());
if (out.getCursor() != offset) {
throw new RuntimeException("Item is being written somewhere other than where it was placed");
}
for (Field field: getFields()) {
field.writeTo(out);
}
}
protected abstract int getAlignment();
protected int alignOffset(int offset) {
int mask = getAlignment() - 1;
return (offset + mask) & ~mask;
}
protected int getOffset() {
return offset;
}
protected abstract Field[] getFields();
public abstract ItemType getItemType();
public void copyTo(DexFile dexFile, T copy) {
Field[] fields = getFields();
Field[] fieldsCopy = copy.getFields();
for (int i = 0; i < fields.length; i++) {
fields[i].copyTo(dexFile, fieldsCopy[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 Item)) {
return false;
}
Item other = (Item)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;
}
}

View File

@ -0,0 +1,87 @@
/*
* [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 ItemReference<T extends Item<T>, S extends ItemReference<T,S>> implements Field<S> {
private T item = null;
private Section<T> section;
public ItemReference(Section<T> section) {
this.section = section;
}
public ItemReference(DexFile dexFile, T item) {
if (item != null) {
section = dexFile.getSectionForItem(item);
this.item = item;
}
}
public T getReference() {
return item;
}
protected void setReference(T item) {
this.item = item;
}
public Section<T> getSection() {
return section;
}
public void copyTo(DexFile dexFile, S copy) {
T referencedItem = getReference();
if (referencedItem == null) {
return;
}
Section<T> section = copy.getSection();
T copiedItem = section.intern(dexFile, referencedItem);
copy.setReference(copiedItem);
}
public int hashCode() {
if (item == null) {
return 0;
}
return item.hashCode();
}
public boolean equals(Object o) {
if (!(o instanceof ItemReference)) {
return false;
}
ItemReference other = (ItemReference)o;
if (item != null) {
return item.equals(other.item);
} else {
return other.item == null;
}
}
}

View File

@ -0,0 +1,106 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.JesusFreke.dexlib;
import java.util.TreeMap;
/**
* Enumeration of all the top-level item types.
*/
public enum ItemType {
TYPE_HEADER_ITEM( 0x0000, "header_item"),
TYPE_STRING_ID_ITEM( 0x0001, "string_id_item"),
TYPE_TYPE_ID_ITEM( 0x0002, "type_id_item"),
TYPE_PROTO_ID_ITEM( 0x0003, "proto_id_item"),
TYPE_FIELD_ID_ITEM( 0x0004, "field_id_item"),
TYPE_METHOD_ID_ITEM( 0x0005, "method_id_item"),
TYPE_CLASS_DEF_ITEM( 0x0006, "class_def_item"),
TYPE_MAP_LIST( 0x1000, "map_list"),
TYPE_TYPE_LIST( 0x1001, "type_list"),
TYPE_ANNOTATION_SET_REF_LIST( 0x1002, "annotation_set_ref_list"),
TYPE_ANNOTATION_SET_ITEM( 0x1003, "annotation_set_item"),
TYPE_CLASS_DATA_ITEM( 0x2000, "class_data_item"),
TYPE_CODE_ITEM( 0x2001, "code_item"),
TYPE_STRING_DATA_ITEM( 0x2002, "string_data_item"),
TYPE_DEBUG_INFO_ITEM( 0x2003, "debug_info_item"),
TYPE_ANNOTATION_ITEM( 0x2004, "annotation_item"),
TYPE_ENCODED_ARRAY_ITEM( 0x2005, "encoded_array_item"),
TYPE_ANNOTATIONS_DIRECTORY_ITEM(0x2006, "annotations_directory_item"),
TYPE_MAP_ITEM( -1, "map_item"),
TYPE_TYPE_ITEM( -1, "type_item"),
TYPE_EXCEPTION_HANDLER_ITEM( -1, "exception_handler_item"),
TYPE_ANNOTATION_SET_REF_ITEM( -1, "annotation_set_ref_item");
/** A map to facilitate looking up an <code>ItemType</code> by ordinal */
private final static TreeMap<Integer, ItemType> itemTypeIntegerMap;
/** builds the <code>itemTypeIntegerMap</code> object */
static {
itemTypeIntegerMap = new TreeMap<Integer, ItemType>();
for (ItemType itemType: ItemType.values()) {
itemTypeIntegerMap.put(itemType.getMapValue(), itemType);
}
}
/** value when represented in a MapItem */
private final int mapValue;
/** non-null; name of the type */
private final String typeName;
/**
* Constructs an instance.
*
* @param mapValue value when represented in a MapItem
* @param typeName non-null; name of the type
*/
private ItemType(int mapValue, String typeName) {
this.mapValue = mapValue;
this.typeName = typeName;
}
/**
* Gets the map value.
*
* @return the map value
*/
public int getMapValue() {
return mapValue;
}
/**
* Gets the type name.
*
* @return non-null; the type name
*/
public String getTypeName() {
return typeName;
}
/**
* Converts an int value to the corresponding ItemType enum value,
* or null if the value isn't a valid ItemType value
*
* @param itemType the int value to convert to an ItemType
* @return the ItemType enum value corresponding to itemType, or null
* if not a valid ItemType value
*/
public static ItemType fromInt(int itemType) {
return itemTypeIntegerMap.get(itemType);
}
}

View File

@ -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;
import org.JesusFreke.dexlib.util.Output;
import org.JesusFreke.dexlib.util.Input;
import org.JesusFreke.dexlib.util.Leb128Utils;
public class Leb128Field extends CachedIntegerValueField {
protected int value;
public Leb128Field() {
}
public Leb128Field(int value) {
this.value = value;
}
public void writeTo(Output out) {
out.writeUnsignedLeb128(value);
}
public void readFrom(Input in) {
value = in.readUnsignedLeb128();
}
public int place(int offset) {
return offset + Leb128Utils.unsignedLeb128Size(value);
}
public int getCachedValue() {
return value;
}
public void cacheValue(int value) {
this.value = value;
}
}

View File

@ -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;
import org.JesusFreke.dexlib.util.Output;
import org.JesusFreke.dexlib.util.Input;
import org.JesusFreke.dexlib.util.Leb128Utils;
public class Leb128p1Field extends CachedIntegerValueField {
protected int value;
public Leb128p1Field() {
}
public Leb128p1Field(int value) {
this.value = value;
}
public void writeTo(Output out) {
out.writeUnsignedLeb128(value + 1);
}
public void readFrom(Input in) {
value = in.readUnsignedLeb128() - 1;
}
public int place(int offset) {
return offset + Leb128Utils.unsignedLeb128Size(value + 1);
}
public int getCachedValue() {
return value;
}
public void cacheValue(int value) {
this.value = value;
}
}

View File

@ -0,0 +1,90 @@
/*
* [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.Output;
import java.util.ArrayList;
public class ListSizeField extends CachedIntegerValueField {
private final ArrayList<?> list;
private final CachedIntegerValueField underlyingField;
public ListSizeField(ArrayList list, CachedIntegerValueField underlyingField) {
this.list = list;
this.underlyingField = underlyingField;
}
public void writeTo(Output out) {
underlyingField.writeTo(out);
}
public void readFrom(Input in) {
underlyingField.readFrom(in);
/** the absolute value operation is needed for the case when a list sized is
* encoded as the absolute value of a signed integer
*/
int listSize = Math.abs(underlyingField.getCachedValue());
list.clear();
list.ensureCapacity(listSize);
for (int i = 0; i < listSize; i++) {
list.add(null);
}
}
public int place(int offset) {
underlyingField.cacheValue(list.size());
return underlyingField.place(offset);
}
public int getCachedValue() {
return underlyingField.getCachedValue();
}
public void cacheValue(int value) {
underlyingField.cacheValue(value);
}
public int hashCode() {
//don't affect hash code calculations
return 0;
}
public boolean equals(Object o) {
if (!(o instanceof ListSizeField)) {
return false;
}
ListSizeField other = (ListSizeField)o;
return list.size() == other.list.size();
}
}

View File

@ -0,0 +1,88 @@
/*
* [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;
public class MapField extends CompositeField<MapField> {
private final Field[] fields;
public ItemType getSectionItemType() {
return ItemType.fromInt(sectionType.getCachedValue());
}
public int getSectionSize() {
return sectionInfo.getSectionSize();
}
public int getSectionOffset() {
return sectionInfo.getSectionOffset();
}
private final ShortIntegerField sectionType;
private final ShortIntegerField unused;
private final SectionHeaderInfo sectionInfo;
public MapField(final DexFile dexFile) {
fields = new Field[] {
sectionType = new ShortIntegerField(),
unused = new ShortIntegerField((short)0),
sectionInfo = new SectionHeaderInfo() {
protected Section getSection() {
return dexFile.getSectionForType(getSectionItemType());
}
}
};
}
public MapField(final DexFile dexFile, short sectionType) {
fields = new Field[] {
this.sectionType = new ShortIntegerField(sectionType),
this.unused = new ShortIntegerField((short)0),
this.sectionInfo = new SectionHeaderInfo() {
protected Section getSection() {
return dexFile.getSectionForType(getSectionItemType());
}
}
};
}
public int place(int offset) {
return super.place(offset);
}
public void writeTo(Output out) {
super.writeTo(out);
}
protected Field[] getFields() {
return fields;
}
}

View File

@ -0,0 +1,135 @@
/*
* [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 java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class MapItem extends IndexedItem<MapItem> {
private final Field[] fields;
private ArrayList<MapField> mapEntries = new ArrayList<MapField>();
public MapItem(final DexFile dexFile, int index) {
super(index);
fields = new Field[] {
new ListSizeField(mapEntries, new IntegerField()),
new FieldListField<MapField>(mapEntries) {
protected MapField make() {
return new MapField(dexFile);
}
}
};
}
public int place(int index, int offset) {
for (int i=0; i<mapEntries.size(); i++) {
MapField mapField = mapEntries.get(i);
mapField.place(offset);
if (mapField.getSectionSize() == 0 /*&& mapField.getSectionItemType().getMapValue() > 0x06*/) {
mapEntries.remove(i--);
}
}
return super.place(index, offset);
}
public void writeTo(Output out) {
Collections.sort(mapEntries, new Comparator<MapField>() {
public int compare(MapField o1, MapField o2) {
return ((Integer)o1.getSectionOffset()).compareTo(o2.getSectionOffset());
}
});
super.writeTo(out);
}
public static MapItem makeBlankMapItem(DexFile dexFile) {
MapItem mapItem = new MapItem(dexFile, 0);
mapItem.mapEntries.add(new MapField(dexFile, (short)0x0000));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x0001));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x0002));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x0003));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x0004));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x0005));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x0006));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x1003));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x2001));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x2006));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x1001));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x2002));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x2003));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x2004));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x2005));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x2000));
mapItem.mapEntries.add(new MapField(dexFile, (short)0x1000));
return mapItem;
}
public MapField[] getMapEntries() {
return mapEntries.toArray(new MapField[1]);
}
protected int getAlignment() {
return 4;
}
protected Field[] getFields() {
return fields;
}
public ItemType getItemType() {
return ItemType.TYPE_MAP_LIST;
}
public void copyTo(DexFile dexFile, MapItem copy) {
//nothing to do
}
public int hashCode() {
return 1;
}
public boolean equals(Object o) {
return getClass() == o.getClass();
}
public int compareTo(MapItem o) {
//there is only 1 map item
return 1;
}
}

View File

@ -0,0 +1,106 @@
/*
* [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 class MethodIdItem extends IndexedItem<MethodIdItem> {
private final Field[] fields;
private final IndexedItemReference<TypeIdItem> classType;
private final IndexedItemReference<ProtoIdItem> prototype;
private final IndexedItemReference<StringIdItem> methodName;
public MethodIdItem(DexFile dexFile, int index) {
super(index);
fields = new Field[] {
classType = new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new ShortIntegerField()),
prototype = new IndexedItemReference<ProtoIdItem>(dexFile.ProtoIdsSection, new ShortIntegerField()),
methodName = new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new IntegerField())
};
}
public MethodIdItem(DexFile dexFile, TypeIdItem classType, StringIdItem methodName, ProtoIdItem prototype) {
super(-1);
fields = new Field[] {
this.classType = new IndexedItemReference<TypeIdItem>(dexFile, classType, new ShortIntegerField()),
this.prototype = new IndexedItemReference<ProtoIdItem>(dexFile, prototype, new ShortIntegerField()),
this.methodName = new IndexedItemReference<StringIdItem>(dexFile, methodName, new IntegerField())
};
}
public MethodIdItem(DexFile dexFile, TypeIdItem classType, String methodName, ProtoIdItem prototype) {
this(dexFile, classType, new StringIdItem(dexFile, methodName), prototype);
}
protected int getAlignment() {
return 4;
}
protected Field[] getFields() {
return fields;
}
public ItemType getItemType() {
return ItemType.TYPE_METHOD_ID_ITEM;
}
public TypeIdItem getClassType() {
return classType.getReference();
}
public String getMethodName() {
return methodName.getReference().toString();
}
public void setClassType(TypeIdItem newClassType) {
classType.setReference(newClassType);
}
public String toString() {
return classType.getReference().toString() + " - " + methodName.getReference().toString();
}
public int getParameterWordCount(boolean isStatic) {
return prototype.getReference().getParameterWordCount() + (isStatic?0:1);
}
public int compareTo(MethodIdItem o) {
int result = classType.compareTo(o.classType);
if (result != 0) {
return result;
}
result = methodName.compareTo(o.methodName);
if (result != 0) {
return result;
}
return prototype.compareTo(o.prototype);
}
}

View File

@ -0,0 +1,99 @@
/*
* [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;
import org.JesusFreke.dexlib.util.ByteArray;
public class NullTerminatedByteArrayField implements Field<NullTerminatedByteArrayField> {
protected byte[] value;
public NullTerminatedByteArrayField() {
}
public NullTerminatedByteArrayField(byte[] value) {
this.value = value.clone();
}
public NullTerminatedByteArrayField(ByteArray byteArray) {
value = new byte[byteArray.size()];
byteArray.getBytes(value, 0);
}
public void writeTo(Output out) {
out.write(value);
out.writeByte(0);
}
public void readFrom(Input in) {
int startPosition = in.getCursor();
while (in.readByte() != 0);
int size = in.getCursor() - startPosition - 1;
in.setCursor(startPosition);
value = in.readBytes(size);
in.skipBytes(1);
}
public int place(int offset) {
return offset + value.length + 1;
}
public void copyTo(DexFile dexFile, NullTerminatedByteArrayField copy) {
copy.value = value;
}
public int hashCode() {
int h=1;
for (int i = 0; i < value.length; i++) {
h = h*7 + value[i];
}
return h;
}
public boolean equals(Object o) {
if (!(o instanceof NullTerminatedByteArrayField)) {
return false;
}
NullTerminatedByteArrayField other = (NullTerminatedByteArrayField)o;
if (value.length != other.value.length) {
return false;
}
for (int i = 0; i < value.length; i++) {
if (value[i] != other.value[i]) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,36 @@
/*
* [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 OffsettedItem<T extends OffsettedItem<T>> extends Item<T> {
public OffsettedItem(int offset) {
super(offset);
}
}

View File

@ -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;
import org.JesusFreke.dexlib.util.Output;
import org.JesusFreke.dexlib.util.Input;
public class OffsettedItemReference<T extends OffsettedItem<T>> extends
ItemReference<T,OffsettedItemReference<T>> {
private final CachedIntegerValueField underlyingField;
public OffsettedItemReference(OffsettedSection<T> section, CachedIntegerValueField underlyingField) {
super(section);
this.underlyingField = underlyingField;
}
public OffsettedItemReference(DexFile dexFile, T item, CachedIntegerValueField underlyingField) {
super(dexFile, item);
this.underlyingField = underlyingField;
}
public OffsettedSection<T> getSection() {
return (OffsettedSection<T>)super.getSection();
}
public void writeTo(Output out) {
T item = getReference();
if (item != null && !item.isPlaced()) {
throw new RuntimeException("Trying to write reference to an item that hasn't been placed.");
}
/*if (out.getCursor() != underlyingField.getCachedValue()) {
throw new RuntimeException("Trying to write a reference in a difference location from where it was placed");
}*/
//TODO: this is a hack to force it to reload the correct offset value
if (item == null) {
underlyingField.cacheValue(0);
} else {
underlyingField.cacheValue(item.getOffset());
}
underlyingField.writeTo(out);
}
public void readFrom(Input in) {
underlyingField.readFrom(in);
if (underlyingField.getCachedValue() != 0) {
setReference(getSection().getByOffset(underlyingField.getCachedValue()));
}
}
public int place(int offset) {
if (getReference() != null) {
underlyingField.cacheValue(getReference().getOffset());
} else {
underlyingField.cacheValue(0);
}
return underlyingField.place(offset);
}
}

View File

@ -0,0 +1,83 @@
/*
* [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 java.util.HashMap;
public abstract class OffsettedSection<T extends OffsettedItem<T>> extends Section<T> {
protected HashMap<Integer, T> itemsByOffset;
public OffsettedSection() {
itemsByOffset = new HashMap<Integer, T>();
}
/**
* Retrieves the item that starts at the given offset, or null if
* there are none found. This method is intended to only be used
* while reading in a dex file.
* TODO: find a better way to abstract this
* @param offset the offset of the item to get
* @return the item that starts at the given offset, or null if there
* are none found
*/
public T getByOffset(int offset) {
T item = itemsByOffset.get(offset);
if (item == null) {
item = make(offset);
items.add(item);
itemsByOffset.put(offset, item);
}
return item;
}
public void readFrom(int size, Input in) {
for (int i = 0; i < size; i++) {
T item = getByOffset(in.getCursor());
item.readFrom(in);
in.alignTo(item.getAlignment());
}
}
protected abstract T make(int offset);
public T intern(DexFile dexFile, T item) {
T itemToReturn = getInternedItem(item);
if (itemToReturn == null) {
itemToReturn = make(-1);
items.add(itemToReturn);
item.copyTo(dexFile, itemToReturn);
uniqueItems.put(itemToReturn, itemToReturn);
}
return itemToReturn;
}
}

View File

@ -0,0 +1,112 @@
/*
* [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 ProtoIdItem extends IndexedItem<ProtoIdItem> {
private final Field[] fields;
private final IndexedItemReference<StringIdItem> shortyDescriptor;
private final IndexedItemReference<TypeIdItem> returnType;
private final OffsettedItemReference<TypeListItem> parameters;
public ProtoIdItem(DexFile dexFile, int index) {
super(index);
fields = new Field[] {
shortyDescriptor = new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new IntegerField()),
returnType = new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new IntegerField()),
parameters = new OffsettedItemReference<TypeListItem>(dexFile.TypeListsSection, new IntegerField())
};
}
public ProtoIdItem(DexFile dexFile, TypeIdItem returnType, ArrayList<TypeIdItem> parameters)
{
super(-1);
StringIdItem stringIdItem = new StringIdItem(dexFile, createShortyDescriptor(returnType, parameters));
TypeListItem typeListItem = new TypeListItem(dexFile, parameters);
fields = new Field[] {
this.shortyDescriptor = new IndexedItemReference<StringIdItem>(dexFile, stringIdItem, new IntegerField()),
this.returnType = new IndexedItemReference<TypeIdItem>(dexFile, returnType, new IntegerField()),
this.parameters = new OffsettedItemReference<TypeListItem>(dexFile, typeListItem, new IntegerField())
};
}
private String createShortyDescriptor(TypeIdItem returnType, ArrayList<TypeIdItem> parameters) {
StringBuilder sb = new StringBuilder();
sb.append(returnType.toShorty());
for (TypeIdItem typeIdItem: parameters) {
sb.append(typeIdItem.toShorty());
}
return sb.toString();
}
protected int getAlignment() {
return 4;
}
public int getParameterWordCount() {
TypeListItem typeList = parameters.getReference();
if (typeList == null) {
return 0;
} else {
return typeList.getWordCount();
}
}
protected Field[] getFields() {
return fields;
}
public ItemType getItemType() {
return ItemType.TYPE_PROTO_ID_ITEM;
}
public int compareTo(ProtoIdItem o) {
int result = returnType.compareTo(o.returnType);
if (result != 0) {
return result;
}
TypeListItem thisParameters = parameters.getReference();
if (thisParameters == null) {
return -1;
}
return thisParameters.compareTo(o.parameters.getReference());
}
public String toString() {
return shortyDescriptor.toString();
}
}

View File

@ -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.util.Output;
import org.JesusFreke.dexlib.util.Input;
import java.util.ArrayList;
import java.util.HashMap;
public abstract class Section<T extends Item> {
protected ArrayList<T> items;
protected HashMap<T, T> uniqueItems = null;
/**
* When offset > -1, this section is "placed" at the specified offset. All
* items should have sequential indexes, and be placed appropriately.
*
* To unplace the section, set offset to -1, and set the offset of all
* items to -1
*/
protected int offset = -1;
public Section() {
items = new ArrayList<T>();
}
public int place(int offset) {
this.offset = offset;
for (int i=0; i < items.size(); i++) {
T item = items.get(i);
if (item == null) {
items.remove(i--);
continue;
}
offset = item.place(i, offset);
if (i == 0) {
/** if this item type has an alignment requirement,
* then item.getOffset() may be different than the
* offset before item.place was called, so we have
* to initialize the section offset to the actual
* (post-alignment) offset of the first item
*/
this.offset = item.getOffset();
}
}
return offset;
}
public void unplace() {
for (Item item: items) {
item.unplace();
}
}
public void writeTo(Output out) {
for (int i = 0; i < size(); i++) {
T item = items.get(i);
if (item == null) {
throw new RuntimeException("Cannot write section because all items haven't been initialized");
}
item.writeTo(out);
}
}
public abstract void readFrom(int size, Input in);
protected void setSize(int size) {
if (items.size() > size) {
throw new RuntimeException("This section contains references to items beyond the size of the section");
}
items.ensureCapacity(size);
for (int i = items.size(); i < size; i++) {
items.add(null);
}
}
public int size() {
return items.size();
}
public boolean isPlaced() {
return offset > -1;
}
public int getOffset() {
return offset;
}
protected T getInternedItem(T item) {
if (uniqueItems == null) {
buildInternedItemMap();
}
return uniqueItems.get(item);
}
protected void buildInternedItemMap() {
uniqueItems = new HashMap<T,T>();
for (T item: items) {
uniqueItems.put(item, item);
}
}
public abstract T intern(DexFile dexFile, T item);
}

View File

@ -0,0 +1,83 @@
/*
* [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 SectionHeaderInfo implements Field<SectionHeaderInfo> {
private int sectionSize;
private int sectionOffset;
public SectionHeaderInfo() {
}
protected abstract Section getSection();
public void writeTo(Output out) {
Section section = getSection();
if (!section.isPlaced()) {
throw new RuntimeException("Trying to write a reference to a section that hasn't been placed.");
}
sectionSize = section.size();
sectionOffset = section.getOffset();
out.writeInt(sectionSize);
out.writeInt(sectionOffset);
}
public void readFrom(Input in) {
sectionSize = in.readInt();
sectionOffset = in.readInt();
}
public int getSectionSize() {
return sectionSize;
}
public int getSectionOffset() {
return sectionOffset;
}
public int place(int offset) {
Section section = getSection();
sectionSize = section.size();
sectionOffset = section.getOffset();
return offset+8;
}
public void copyTo(DexFile dexFile, SectionHeaderInfo copy) {
/**
* do nothing. the section size and offset are dynamically generated
* when the copy is written
*/
}
}

View File

@ -0,0 +1,70 @@
/*
* [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 ShortIntegerField extends CachedIntegerValueField {
protected int value = 0;
public ShortIntegerField() {
}
public ShortIntegerField(int value) {
this.value = value;
}
public void writeTo(Output out) {
out.writeShort(value);
}
public void readFrom(Input in) {
value = in.readShort();
}
public int place(int offset) {
return offset + 2;
}
/**
* This method returns the short integer value that has been cached. This
* value is either the value that the field was constructed with, the
* value that was read via <code>readFrom</code>, or the value that was
* cached when <code>place</code> was called
* @return the cached value
*/
public int getCachedValue() {
return value;
}
public void cacheValue(int value) {
this.value = (short)value;
}
}

View File

@ -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;
import org.JesusFreke.dexlib.util.Output;
import org.JesusFreke.dexlib.util.Input;
import org.JesusFreke.dexlib.util.Leb128Utils;
public class SignedLeb128Field extends CachedIntegerValueField {
protected int value;
public SignedLeb128Field() {
}
public SignedLeb128Field(int value) {
this.value = value;
}
public void writeTo(Output out) {
out.writeSignedLeb128(value);
}
public void readFrom(Input in) {
value = in.readSignedLeb128();
}
public int place(int offset) {
return offset + Leb128Utils.signedLeb128Size(value);
}
public int getCachedValue() {
return value;
}
public void cacheValue(int value) {
this.value = value;
}
}

View File

@ -0,0 +1,85 @@
/*
* [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.ByteArray;
import org.JesusFreke.dexlib.util.Utf8Utils;
public class StringDataItem extends OffsettedItem<StringDataItem> implements Comparable<StringDataItem> {
private final Field[] fields;
private String value = null;
private final Leb128Field stringSize;
private final NullTerminatedByteArrayField stringByteArray;
public StringDataItem(int offset) {
super(offset);
fields = new Field[] {
stringSize = new Leb128Field(),
stringByteArray = new NullTerminatedByteArrayField()
};
}
public StringDataItem(String value) {
super(-1);
this.value = value;
fields = new Field[] {
stringSize = new Leb128Field(value.length()),
stringByteArray = new NullTerminatedByteArrayField(Utf8Utils.stringToUtf8Bytes(value))
};
}
public Field[] getFields() {
return fields;
}
public int getAlignment() {
return 1;
}
public ItemType getItemType() {
return ItemType.TYPE_STRING_DATA_ITEM;
}
public String toString() {
if (value == null) {
value = Utf8Utils.utf8BytesToString(new ByteArray(((NullTerminatedByteArrayField)fields[1]).value));
}
return value;
}
public int compareTo(StringDataItem o) {
return toString().compareTo(o.toString());
}
}

View File

@ -0,0 +1,75 @@
/*
* [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 class StringIdItem extends IndexedItem<StringIdItem> {
private final Field[] fields;
private final OffsettedItemReference<StringDataItem> stringData;
public StringIdItem(DexFile dexFile, int index) {
super(index);
fields = new Field[] {
stringData = new OffsettedItemReference<StringDataItem>(dexFile.StringDataSection, new IntegerField())
};
}
public StringIdItem(DexFile dexFile, StringDataItem stringDataItem) {
super(-1);
fields = new Field[] {
stringData = new OffsettedItemReference<StringDataItem>(dexFile, stringDataItem, new IntegerField())
};
}
public StringIdItem(DexFile dexFile, String value) {
this(dexFile, new StringDataItem(value));
}
protected int getAlignment() {
return 4;
}
protected Field[] getFields() {
return fields;
}
public ItemType getItemType() {
return ItemType.TYPE_STRING_ID_ITEM;
}
public String toString() {
return stringData.getReference().toString();
}
public int compareTo(StringIdItem o) {
//sort by the string value
return toString().compareTo(o.toString());
}
}

View File

@ -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;
public class TypeIdItem extends IndexedItem<TypeIdItem> {
private final Field[] fields;
private final IndexedItemReference<StringIdItem> type;
public TypeIdItem(DexFile dexFile, int index) {
super(index);
fields = new Field[] {
type = new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new IntegerField())
};
}
public TypeIdItem(DexFile dexFile, StringIdItem stringIdItem) {
super(-1);
fields = new Field[] {
type = new IndexedItemReference<StringIdItem>(dexFile, stringIdItem, new IntegerField())
};
}
public TypeIdItem(DexFile dexFile, String value) {
super(-1);
StringDataItem stringDataItem = new StringDataItem(value);
StringIdItem stringIdItem = new StringIdItem(dexFile, stringDataItem);
fields = new Field[] {
type = new IndexedItemReference<StringIdItem>(dexFile, stringIdItem, new IntegerField())
};
}
protected int getAlignment() {
return 4;
}
protected Field[] getFields() {
return fields;
}
public int getWordCount() {
String type = this.toString();
/** Only the long and double primitive types are 2 words,
* everything else is a single word
*/
if (type.equals("J") || type.equals("D")) {
return 2;
} else {
return 1;
}
}
public ItemType getItemType() {
return ItemType.TYPE_TYPE_ID_ITEM;
}
public String toString() {
return type.getReference().toString();
}
public int compareTo(TypeIdItem o) {
//sort by the index of the StringIdItem
return type.compareTo(o.type);
}
public String toShorty() {
String type = toString();
if (type.length() > 1) {
return "L";
} else {
return type;
}
}
}

View File

@ -0,0 +1,114 @@
/*
* [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 java.util.ArrayList;
import java.util.List;
public class TypeListItem extends OffsettedItem<TypeListItem> implements Comparable<TypeListItem> {
private final Field[] fields;
private final ArrayList<IndexedItemReference<TypeIdItem>> typeList = new ArrayList<IndexedItemReference<TypeIdItem>>();
public TypeListItem(final DexFile dexFile, int offset) {
super(offset);
fields = new Field[] {
new ListSizeField(typeList, new IntegerField()),
new FieldListField<IndexedItemReference<TypeIdItem>>(typeList) {
protected IndexedItemReference<TypeIdItem> make() {
return new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new ShortIntegerField());
}
}
};
}
public TypeListItem(final DexFile dexFile, List<TypeIdItem> types) {
this(dexFile, 0);
for (TypeIdItem typeIdItem: types) {
typeList.add(new IndexedItemReference<TypeIdItem>(dexFile, typeIdItem, new ShortIntegerField()));
}
}
public List<TypeIdItem> getTypes() {
ArrayList<TypeIdItem> list = new ArrayList<TypeIdItem>(typeList.size());
for (IndexedItemReference<TypeIdItem> typeIdItemReference: typeList) {
list.add(typeIdItemReference.getReference());
}
return list;
}
public Field[] getFields() {
return fields;
}
public int getWordCount() {
int wordCount = 0;
for (IndexedItemReference<TypeIdItem> typeRef: typeList) {
TypeIdItem item = typeRef.getReference();
wordCount += item.getWordCount();
}
return wordCount;
}
public int getAlignment() {
return 4;
}
public ItemType getItemType() {
return ItemType.TYPE_TYPE_LIST;
}
public int compareTo(TypeListItem o) {
if (o == null) {
return 1;
}
int thisSize = typeList.size();
int otherSize = o.typeList.size();
int size = Math.min(thisSize, otherSize);
for (int i = 0; i < size; i++) {
int result = typeList.get(i).compareTo(o.typeList.get(i));
if (result != 0) {
return result;
}
}
if (thisSize < otherSize) {
return -1;
} else if (thisSize > otherSize) {
return 1;
} else {
return 0;
}
}
}

View File

@ -0,0 +1,43 @@
/*
* [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.code.Format;
import org.JesusFreke.dexlib.code.Opcode;
public abstract class Format
{
public abstract int getByteCount();
public abstract String getFormatName();
protected void checkOpcodeFormat(Opcode opcode) {
if (!opcode.format.equals(getFormatName())) {
throw new RuntimeException("Opcode " + opcode.name + " does not use format " + getFormatName());
}
}
}

View File

@ -0,0 +1,59 @@
/*
* [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.code.Format;
import org.JesusFreke.dexlib.code.Instruction;
import org.JesusFreke.dexlib.code.Opcode;
import org.JesusFreke.dexlib.DexFile;
public class Format10x extends Format
{
public static final Format10x Format = new Format10x();
private Format10x() {
}
public Instruction make(DexFile dexFile, byte opcode) {
Opcode op = Opcode.getOpcodeByValue(opcode);
checkOpcodeFormat(op);
return new Instruction(dexFile, new byte[]{opcode,0x00}, null);
}
public int getByteCount()
{
return 2;
}
public String getFormatName()
{
return "10x";
}
}

View File

@ -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.code.Format;
import org.JesusFreke.dexlib.code.Instruction;
import org.JesusFreke.dexlib.code.Opcode;
import org.JesusFreke.dexlib.DexFile;
public class Format11x extends Format
{
public static final Format11x Format = new Format11x();
private Format11x() {
}
public Instruction make(DexFile dexFile, byte opcode, short regA) {
Opcode op = Opcode.getOpcodeByValue(opcode);
checkOpcodeFormat(op);
if (regA >= 2<<8) {
throw new RuntimeException("The register number must be less than v256");
}
return new Instruction(dexFile, new byte[]{opcode,(byte)regA}, null);
}
public int getByteCount()
{
return 2;
}
public String getFormatName()
{
return "11x";
}
}

View File

@ -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.code.Format;
import org.JesusFreke.dexlib.code.Instruction;
import org.JesusFreke.dexlib.code.Opcode;
import org.JesusFreke.dexlib.DexFile;
import org.JesusFreke.dexlib.IndexedItem;
public class Format21c extends Format
{
public static final Format21c Format = new Format21c();
private Format21c() {
}
public Instruction make(DexFile dexFile, byte opcode, short regA, IndexedItem item) {
byte[] bytes = new byte[4];
Opcode op = Opcode.getOpcodeByValue(opcode);
checkOpcodeFormat(op);
if (regA >= 2<<8) {
throw new RuntimeException("The register number must be less than v256");
}
bytes[0] = opcode;
bytes[1] = (byte)regA;
return new Instruction(dexFile, bytes, item);
}
public int getByteCount() {
return 4;
}
public String getFormatName() {
return "21c";
}
}

View File

@ -0,0 +1,69 @@
/*
* [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.code.Format;
import org.JesusFreke.dexlib.code.Instruction;
import org.JesusFreke.dexlib.code.Opcode;
import org.JesusFreke.dexlib.DexFile;
import org.JesusFreke.dexlib.IndexedItem;
public class Format22c extends Format
{
public static final Format22c Format = new Format22c();
private Format22c() {
}
public Instruction make(DexFile dexFile, byte opcode, byte regA, byte regB, IndexedItem item) {
byte[] bytes = new byte[4];
Opcode op = Opcode.getOpcodeByValue(opcode);
checkOpcodeFormat(op);
if (regA >= 16 ||
regB >= 16) {
throw new RuntimeException("The register number must be less than v16");
}
bytes[0] = opcode;
bytes[1] = (byte)((regB << 4) | regA);
return new Instruction(dexFile, bytes, item);
}
public int getByteCount() {
return 4;
}
public String getFormatName() {
return "22c";
}
}

View File

@ -0,0 +1,114 @@
/*
* [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.code.Format;
import org.JesusFreke.dexlib.*;
import org.JesusFreke.dexlib.code.Instruction;
import org.JesusFreke.dexlib.code.Opcode;
import static org.JesusFreke.dexlib.code.Opcode.*;
public class Format35c extends Format
{
public static final Format35c Format = new Format35c();
private Format35c() {
}
public Instruction make(DexFile dexFile, byte opcode, byte regCount, byte regD, byte regE, byte regF, byte regG, byte regA, IndexedItem item) {
byte[] bytes = new byte[6];
Opcode op = Opcode.getOpcodeByValue(opcode);
checkOpcodeFormat(op);
if (regCount > 5) {
throw new RuntimeException("regCount cannot be greater than 5");
}
if (regD >= 16 ||
regE >= 16 ||
regF >= 16 ||
regG >= 16 ||
regA >= 16) {
throw new RuntimeException("All register args must fit in 4 bits");
}
bytes[0] = opcode;
bytes[1] = (byte)((regCount << 4) | regA);
bytes[4] = (byte)((regE << 4) | regD);
bytes[5] = (byte)((regG << 4) | regF);
//go ahead and make the instruction, to verify that item is the correct type. If it isn't,
//the construction will throw an exception
Instruction instruction = new Instruction(dexFile, bytes, item);
if (opcode == FILLED_NEW_ARRAY.value) {
//check data for filled-new-array opcode
String type = ((TypeIdItem)item).toString();
if (type.charAt(0) != '[') {
throw new RuntimeException("The type must be an array type");
}
if (type.charAt(1) == 'J' || type.charAt(1) == 'D') {
throw new RuntimeException("The type cannot be an array of longs or doubles");
}
} else if (opcode >= INVOKE_VIRTUAL.value && opcode <= INVOKE_INTERFACE.value) {
//check data for invoke-* opcodes
MethodIdItem methodIdItem = (MethodIdItem)item;
if (methodIdItem.getParameterWordCount(opcode == INVOKE_STATIC.value) != regCount) {
throw new RuntimeException("regCount does not match the number of arguments of the method");
}
} else {
throw new RuntimeException("Opcode " + Integer.toHexString(opcode) + " does not use the 35c format");
}
return instruction;
}
public int getByteCount() {
return 6;
}
public String getFormatName() {
return "35c";
}
/*@Test
public void testInvoke() {
DexFile dexFile = new DexFile();
ArrayList<TypeIdItem> types = new ArrayList<TypeIdItem>();
types.add(new TypeIdItem(dexFile, "I"));
types.add(new TypeIdItem(dexFile, "I"));
types.add(new TypeIdItem(dexFile, "I"));
types.add(new TypeIdItem(dexFile, "I"));
types.add(new TypeIdItem(dexFile, "I"));
MethodIdItem method = new MethodIdItem(dexFile, new TypeIdItem(dexFile, "test"), "test", new ProtoIdItem(dexFile, new TypeIdItem(dexFile, "V"), types));
Instruction ins = make(dexFile, (byte)INVOKE_VIRTUAL.value, (byte)5, (byte)0, (byte)1, (byte)2, (byte)3, (byte)4, method);
assertTrue("Is everything put in the right place?", java.util.Arrays.equals(ins.getBytes(), new byte[] {0x6e, 0x54, 0x00, 0x00, 0x10, 0x32}));
}*/
}

View File

@ -0,0 +1,118 @@
/*
* [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.code.Format;
import org.JesusFreke.dexlib.*;
import org.JesusFreke.dexlib.code.Instruction;
import org.JesusFreke.dexlib.code.Opcode;
import static org.JesusFreke.dexlib.code.Opcode.*;
public class Format3rc extends Format
{
public static final Format3rc Format = new Format3rc();
public Format3rc() {
}
public Instruction make(DexFile dexFile, byte opcode, short regCount, int startReg, IndexedItem item) {
byte[] bytes = new byte[6];
Opcode op = Opcode.getOpcodeByValue(opcode);
checkOpcodeFormat(op);
if (regCount >= 2<<8) {
throw new RuntimeException("regCount must be less than 256");
}
if (regCount < 0) {
throw new RuntimeException("regCount cannot be negative");
}
if (startReg >= 2<<16) {
throw new RuntimeException("The beginning register of the range must be less than 65536");
}
if (startReg < 0) {
throw new RuntimeException("The beginning register of the range cannot be negative");
}
bytes[0] = opcode;
bytes[1] = (byte)regCount;
bytes[4] = (byte)startReg;
bytes[5] = (byte)(startReg >> 8);
//go ahead and make the instruction now, which will verify that item is the correct type. If it isn't,
//the construction will throw an exception
Instruction instruction = new Instruction(dexFile, bytes, item);
if (opcode == FILLED_NEW_ARRAY_RANGE.value) {
//check data for filled-new-array/range opcode
String type = ((TypeIdItem)item).toString();
if (type.charAt(0) != '[') {
throw new RuntimeException("The type must be an array type");
}
if (type.charAt(1) == 'J' || type.charAt(1) == 'D') {
throw new RuntimeException("The type cannot be an array of longs or doubles");
}
} else if (opcode >= INVOKE_VIRTUAL_RANGE.value && opcode <= INVOKE_INTERFACE_RANGE.value) {
//check data for invoke-*/range opcodes
MethodIdItem methodIdItem = (MethodIdItem)item;
if (methodIdItem.getParameterWordCount(opcode == INVOKE_STATIC.value) != regCount) {
throw new RuntimeException("regCount does not match the number of arguments of the method");
}
} else {
throw new RuntimeException("Opcode " + Integer.toHexString(opcode) + " does not use the 35c format");
}
return instruction;
}
public int getByteCount() {
return 6;
}
public String getFormatName() {
return "3rc";
}
/*@Test
public void testInvoke() {
DexFile dexFile = DexFile.makeBlankDexFile();
ArrayList<TypeIdItem> types = new ArrayList<TypeIdItem>();
types.add(new TypeIdItem(dexFile, "I"));
types.add(new TypeIdItem(dexFile, "I"));
types.add(new TypeIdItem(dexFile, "I"));
types.add(new TypeIdItem(dexFile, "I"));
types.add(new TypeIdItem(dexFile, "I"));
MethodIdItem method = new MethodIdItem(dexFile, new TypeIdItem(dexFile, "test"), "test", new ProtoIdItem(dexFile, new TypeIdItem(dexFile, "V"), types));
Instruction ins = Format.make(dexFile, (byte)INVOKE_VIRTUAL_RANGE.value, (short)6, 65500, method);
byte[] bytes = new byte[] {0x74, 0x06, 0x00, 0x00, (byte)0xDC, (byte)0xFF};
assertTrue("Is everything put in the right place?", java.util.Arrays.equals(ins.getBytes(), bytes));
}*/
}

View File

@ -0,0 +1,194 @@
/*
* [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.code;
import org.JesusFreke.dexlib.*;
import org.JesusFreke.dexlib.util.Input;
import org.JesusFreke.dexlib.util.Output;
//TODO: need to implement the "special" bytecode types, for switches etc.
public final class Instruction implements Field<Instruction> {
private DexFile dexFile;
private byte[] bytes;
private Opcode opcode;
private IndexedItem reference;
public byte[] getBytes() {
return bytes;
}
public Opcode getOpcode() {
return opcode;
}
public IndexedItem getReference() {
return reference;
}
public Instruction(DexFile dexFile) {
this.dexFile = dexFile;
}
public Instruction(DexFile dexFile, byte[] bytes, IndexedItem item) {
this.dexFile = dexFile;
this.bytes = bytes;
this.reference = item;
this.opcode = Opcode.getOpcodeByValue(bytes[0]);
if (!this.opcode.referenceType.checkItem(item)) {
throw new RuntimeException("item is not the correct type for this opcode (got " + item.getClass().toString() + ", expecting " + opcode.referenceType.toString() + ")");
}
}
public void readFrom(Input in) {
int startPos = in.getCursor();
byte opByte = in.readByte();
if (opByte == 0x00) {
reference = null;
byte secondByte = in.readByte();
int count;
switch (secondByte) {
case 0x00:
/** nop */
bytes = new byte[] { 0x00, 0x00 };
return;
case 0x01:
/** packed switch */
count = in.readShort();
in.setCursor(startPos);
bytes = in.readBytes((count * 4) + 8);
return;
case 0x02:
/** sparse switch */
count = in.readShort();
in.setCursor(startPos);
bytes = in.readBytes((count * 8) + 4);
return;
case 0x03:
/** fill array data */
int elementWidth = in.readShort();
count = in.readInt();
in.setCursor(startPos);
bytes = in.readBytes(((elementWidth * count + 1)/2 + 4) * 2);
return;
default:
throw new RuntimeException("Invalid 2nd byte for opcode 0x00");
}
}
this.opcode = Opcode.getOpcodeByValue(opByte);
if (opcode.referenceType != ReferenceType.none) {
in.skipBytes(1);
int referenceIndex = in.readShort();
//handle const string/jumbo as a special case
if (opByte == 0x1b) {
int hiWord = in.readShort();
if (hiWord != 0) {
throw new RuntimeException("32bit string indexes are not supported yet.");
}
}
switch (opcode.referenceType) {
case string:
reference = dexFile.StringIdsSection.getByIndex(referenceIndex);
break;
case type:
reference = dexFile.TypeIdsSection.getByIndex(referenceIndex);
break;
case field:
reference = dexFile.FieldIdsSection.getByIndex(referenceIndex);
break;
case method:
reference = dexFile.MethodIdsSection.getByIndex(referenceIndex);
break;
}
} else {
reference = null;
}
in.setCursor(startPos);
bytes = in.readBytes(opcode.numBytes);
}
public void writeTo(Output out) {
if (bytes[0] == 0 && bytes[1] > 0) {
//the "special instructions" must be 4 byte aligned
out.alignTo(4);
out.write(bytes);
} else if (reference == null) {
out.write(bytes);
} else {
out.write(bytes,0,2);
if (bytes[0] == 0x1b) {
out.writeInt(reference.getIndex());
} else {
int index = reference.getIndex();
if (index > 0xFFFF) {
throw new RuntimeException("String index doesn't fit.");
}
out.writeShort(reference.getIndex());
out.write(bytes, 4, bytes.length - 4);
}
}
}
public void copyTo(DexFile dexFile, Instruction copy) {
copy.bytes = bytes;
copy.opcode = opcode;
switch (opcode.referenceType) {
case string:
copy.reference = dexFile.StringIdsSection.intern(dexFile, (StringIdItem)reference);
break;
case type:
copy.reference = dexFile.TypeIdsSection.intern(dexFile, (TypeIdItem)reference);
break;
case field:
copy.reference = dexFile.FieldIdsSection.intern(dexFile, (FieldIdItem)reference);
break;
case method:
copy.reference = dexFile.MethodIdsSection.intern(dexFile, (MethodIdItem)reference);
break;
case none:
break;
}
}
public int place(int offset) {
return offset + bytes.length;
}
}

View File

@ -0,0 +1,300 @@
/*
* [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.code;
import java.util.ArrayList;
import java.util.HashMap;
public enum Opcode
{
NOP((byte)0x00, "NOP", (byte)2, ReferenceType.none, "10x"),
MOVE((byte)0x01, "MOVE", (byte)2, ReferenceType.none, "12x"),
MOVE_FROM16((byte)0x02, "MOVE/FROM16", (byte)4, ReferenceType.none, "22x"),
MOVE_16((byte)0x03, "MOVE/16", (byte)6, ReferenceType.none, "32x"),
MOVE_WIDE((byte)0x04, "MOVE-WIDE", (byte)2, ReferenceType.none, "12x"),
MOVE_WIDE_FROM16((byte)0x05, "MOVE-WIDE/FROM16", (byte)4, ReferenceType.none, "22x"),
MOVE_WIDE_16((byte)0x06, "MOVE-WIDE/16", (byte)6, ReferenceType.none, "32x"),
MOVE_OBJECT((byte)0x07, "MOVE-OBJECT", (byte)2, ReferenceType.none, "12x"),
MOVE_OBJECT_FROM16((byte)0x08, "MOVE-OBJECT/FROM16", (byte)4, ReferenceType.none, "22x"),
MOVE_OBJECT_16((byte)0x09, "MOVE-OBJECT/16", (byte)6, ReferenceType.none, "32x"),
MOVE_RESULT((byte)0x0a, "MOVE-RESULT", (byte)2, ReferenceType.none, "11x"),
MOVE_RESULT_WIDE((byte)0x0b, "MOVE-RESULT-WIDE", (byte)2, ReferenceType.none, "11x"),
MOVE_RESULT_OBJECT((byte)0x0c, "MOVE-RESULT-OBJECT", (byte)2, ReferenceType.none, "11x"),
MOVE_EXCEPTION((byte)0x0d, "MOVE-EXCEPTION", (byte)2, ReferenceType.none, "11x"),
RETURN_VOID((byte)0x0e, "RETURN-VOID", (byte)2, ReferenceType.none, "10x"),
RETURN((byte)0x0f, "RETURN", (byte)2, ReferenceType.none, "11x"),
RETURN_WIDE((byte)0x10, "RETURN-WIDE", (byte)2, ReferenceType.none, "11x"),
RETURN_OBJECT((byte)0x11, "RETURN-OBJECT", (byte)2, ReferenceType.none, "11x"),
CONST_4((byte)0x12, "CONST-4", (byte)2, ReferenceType.none, "11n"),
CONST_16((byte)0x13, "CONST/16", (byte)4, ReferenceType.none, "21s"),
CONST((byte)0x14, "CONST", (byte)6, ReferenceType.none, "31i"),
CONST_HIGH16((byte)0x15, "CONST/HIGH16", (byte)4, ReferenceType.none, "21h"),
CONST_WIDE_16((byte)0x16, "CONST-WIDE/16", (byte)4, ReferenceType.none, "21s"),
CONST_WIDE_32((byte)0x17, "CONST-WIDE/32", (byte)6, ReferenceType.none, "31i"),
CONST_WIDE((byte)0x18, "CONST-WIDE", (byte)10, ReferenceType.none, "51l"),
CONST_WIDE_HIGH16((byte)0x19, "CONST-WIDE/HIGH16", (byte)4, ReferenceType.none, "21h"),
CONST_STRING((byte)0x1a, "CONST-STRING", (byte)4, ReferenceType.string, "21c"),
CONST_STRING_JUMBO((byte)0x1b, "CONST-STRING/JUMBO", (byte)6, ReferenceType.string, "31c"),
CONST_CLASS((byte)0x1c, "CONST-CLASS", (byte)4, ReferenceType.type, "21c"),
MONITOR_ENTER((byte)0x1d, "MONITOR-ENTER", (byte)2, ReferenceType.none, "11x"),
MONITOR_EXIT((byte)0x1e, "MONITOR-EXIT", (byte)2, ReferenceType.none, "11x"),
CHECK_CAST((byte)0x1f, "CHECK-CAST", (byte)4, ReferenceType.type, "21c"),
INSTANCE_OF((byte)0x20, "INSTANCE-OF", (byte)4, ReferenceType.type, "22c"),
ARRAY_LENGTH((byte)0x21, "ARRAY-LENGTH", (byte)2, ReferenceType.none, "12x"),
NEW_INSTANCE((byte)0x22, "NEW-INSTANCE", (byte)4, ReferenceType.type, "21c"),
NEW_ARRAY((byte)0x23, "NEW-ARRAY", (byte)4, ReferenceType.type, "22c"),
FILLED_NEW_ARRAY((byte)0x24, "FILLED-NEW-ARRAY", (byte)6, ReferenceType.type, "35c"),
FILLED_NEW_ARRAY_RANGE((byte)0x25, "FILLED-NEW-ARRAY-RANGE", (byte)6, ReferenceType.type, "3rc"),
FILL_ARRAY_DATA((byte)0x26, "FILL-ARRAY-DATA", (byte)6, ReferenceType.none, "31t"),
THROW((byte)0x27, "THROW", (byte)2, ReferenceType.none, "11x"),
GOTO((byte)0x28, "GOTO", (byte)2, ReferenceType.none, "10t"),
GOTO_16((byte)0x29, "GOTO/16", (byte)4, ReferenceType.none, "20t"),
GOTO_32((byte)0x2a, "GOTO/32", (byte)6, ReferenceType.none, "30t"),
PACKED_SWITCH((byte)0x2b, "PACKED-SWITCH", (byte)6, ReferenceType.none, "31t"),
SPARSE_SWITCH((byte)0x2c, "SPARSE-SWITCH", (byte)6, ReferenceType.none, "31t"),
CMPL_FLOAT((byte)0x2d, "CMPL-FLOAT", (byte)4, ReferenceType.none, "23x"),
CMPG_FLOAT((byte)0x2e, "CMPG-FLOAT", (byte)4, ReferenceType.none, "23x"),
CMPL_DOUBLE((byte)0x2f, "CMPL-DOUBLE", (byte)4, ReferenceType.none, "23x"),
CMPG_DOUBLE((byte)0x30, "CMPG-DOUBLE", (byte)4, ReferenceType.none, "23x"),
CMP_LONG((byte)0x31, "CMP-LONG", (byte)4, ReferenceType.none, "23x"),
IF_EQ((byte)0x32, "IF-EQ", (byte)4, ReferenceType.none, "22t"),
IF_NE((byte)0x33, "IF-NE", (byte)4, ReferenceType.none, "22t"),
IF_LT((byte)0x34, "IF-LT", (byte)4, ReferenceType.none, "22t"),
IF_GE((byte)0x35, "IF-GE", (byte)4, ReferenceType.none, "22t"),
IF_GT((byte)0x36, "IF-GT", (byte)4, ReferenceType.none, "22t"),
IF_LE((byte)0x37, "IF-LE", (byte)4, ReferenceType.none, "22t"),
IF_EQZ((byte)0x38, "IF-EQZ", (byte)4, ReferenceType.none, "21t"),
IF_NEZ((byte)0x39, "IF-NEZ", (byte)4, ReferenceType.none, "21t"),
IF_LTZ((byte)0x3a, "IF-LTZ", (byte)4, ReferenceType.none, "21t"),
IF_GEZ((byte)0x3b, "IF-GEZ", (byte)4, ReferenceType.none, "21t"),
IF_GTZ((byte)0x3c, "IF-GTZ", (byte)4, ReferenceType.none, "21t"),
IF_LEZ((byte)0x3d, "IF-LEZ", (byte)4, ReferenceType.none, "21t"),
AGET((byte)0x44, "AGET", (byte)4, ReferenceType.none, "23x"),
AGET_WIDE((byte)0x45, "AGET-WIDE", (byte)4, ReferenceType.none, "23x"),
AGET_OBJECT((byte)0x46, "AGET-OBJECT", (byte)4, ReferenceType.none, "23x"),
AGET_BOOLEAN((byte)0x47, "AGET-BOOLEAN", (byte)4, ReferenceType.none, "23x"),
AGET_BYTE((byte)0x48, "AGET-BYTE", (byte)4, ReferenceType.none, "23x"),
AGET_CHAR((byte)0x49, "AGET-CHAR", (byte)4, ReferenceType.none, "23x"),
AGET_SHORT((byte)0x4a, "AGET-SHORT", (byte)4, ReferenceType.none, "23x"),
APUT((byte)0x4b, "APUT", (byte)4, ReferenceType.none, "23x"),
APUT_WIDE((byte)0x4c, "APUT-WIDE", (byte)4, ReferenceType.none, "23x"),
APUT_OBJECT((byte)0x4d, "APUT-OBJECT", (byte)4, ReferenceType.none, "23x"),
APUT_BOOLEAN((byte)0x4e, "APUT-BOOLEAN", (byte)4, ReferenceType.none, "23x"),
APUT_BYTE((byte)0x4f, "APUT-BYTE", (byte)4, ReferenceType.none, "23x"),
APUT_CHAR((byte)0x50, "APUT-CHAR", (byte)4, ReferenceType.none, "23x"),
APUT_SHORT((byte)0x51, "APUT-SHORT", (byte)4, ReferenceType.none, "23x"),
IGET((byte)0x52, "IGET", (byte)4, ReferenceType.field, "22c"),
IGET_WIDE((byte)0x53, "IGET-WIDE", (byte)4, ReferenceType.field, "22c"),
IGET_OBJECT((byte)0x54, "IGET-OBJECT", (byte)4, ReferenceType.field, "22c"),
IGET_BOOLEAN((byte)0x55, "IGET-BOOLEAN", (byte)4, ReferenceType.field, "22c"),
IGET_BYTE((byte)0x56, "IGET-BYTE", (byte)4, ReferenceType.field, "22c"),
IGET_CHAR((byte)0x57, "IGET-CHAR", (byte)4, ReferenceType.field, "22c"),
IGET_SHORT((byte)0x58, "IGET-SHORT", (byte)4, ReferenceType.field, "22c"),
IPUT((byte)0x59, "IPUT", (byte)4, ReferenceType.field, "22c"),
IPUT_WIDE((byte)0x5a, "IPUT-WIDE", (byte)4, ReferenceType.field, "22c"),
IPUT_OBJECT((byte)0x5b, "IPUT-OBJECT", (byte)4, ReferenceType.field, "22c"),
IPUT_BOOLEAN((byte)0x5c, "IPUT-BOOLEAN", (byte)4, ReferenceType.field, "22c"),
IPUT_BYTE((byte)0x5d, "IPUT-BYTE", (byte)4, ReferenceType.field, "22c"),
IPUT_CHAR((byte)0x5e, "IPUT-CHAR", (byte)4, ReferenceType.field, "22c"),
IPUT_SHORT((byte)0x5f, "IPUT-SHORT", (byte)4, ReferenceType.field, "22c"),
SGET((byte)0x60, "SGET", (byte)4, ReferenceType.field, "21c"),
SGET_WIDE((byte)0x61, "SGET-WIDE", (byte)4, ReferenceType.field, "21c"),
SGET_OBJECT((byte)0x62, "SGET-OBJECT", (byte)4, ReferenceType.field, "21c"),
SGET_BOOLEAN((byte)0x63, "SGET-BOOLEAN", (byte)4, ReferenceType.field, "21c"),
SGET_BYTE((byte)0x64, "SGET-BYTE", (byte)4, ReferenceType.field, "21c"),
SGET_CHAR((byte)0x65, "SGET-CHAR", (byte)4, ReferenceType.field, "21c"),
SGET_SHORT((byte)0x66, "SGET-SHORT", (byte)4, ReferenceType.field, "21c"),
SPUT((byte)0x67, "SPUT", (byte)4, ReferenceType.field, "21c"),
SPUT_WIDE((byte)0x68, "SPUT-WIDE", (byte)4, ReferenceType.field, "21c"),
SPUT_OBJECT((byte)0x69, "SPUT-OBJECT", (byte)4, ReferenceType.field, "21c"),
SPUT_BOOLEAN((byte)0x6a, "SPUT-BOOLEAN", (byte)4, ReferenceType.field, "21c"),
SPUT_BYTE((byte)0x6b, "SPUT-BYTE", (byte)4, ReferenceType.field, "21c"),
SPUT_CHAR((byte)0x6c, "SPUT-CHAR", (byte)4, ReferenceType.field, "21c"),
SPUT_SHORT((byte)0x6d, "SPUT-SHORT", (byte)4, ReferenceType.field, "21c"),
INVOKE_VIRTUAL((byte)0x6e, "INVOKE-VIRTUAL", (byte)6, ReferenceType.method, "35c"),
INVOKE_SUPER((byte)0x6f, "INVOKE-SUPER", (byte)6, ReferenceType.method, "35c"),
INVOKE_DIRECT((byte)0x70, "INVOKE-DIRECT", (byte)6, ReferenceType.method, "35c"),
INVOKE_STATIC((byte)0x71, "INVOKE-STATIC", (byte)6, ReferenceType.method, "35c"),
INVOKE_INTERFACE((byte)0x72, "INVOKE-INTERFACE", (byte)6, ReferenceType.method, "35c"),
INVOKE_VIRTUAL_RANGE((byte)0x74, "INVOKE-VIRTUAL/RANGE", (byte)6, ReferenceType.method, "3rc"),
INVOKE_SUPER_RANGE((byte)0x75, "INVOKE-SUPER/RANGE", (byte)6, ReferenceType.method, "3rc"),
INVOKE_DIRECT_RANGE((byte)0x76, "INVOKE-DIRECT/RANGE", (byte)6, ReferenceType.method, "3rc"),
INVOKE_STATIC_RANGE((byte)0x77, "INVOKE-STATIC/RANGE", (byte)6, ReferenceType.method, "3rc"),
INVOKE_INTERFACE_RANGE((byte)0x78, "INVOKE-INTERFACE/RANGE", (byte)6, ReferenceType.method, "3rc"),
NEG_INT((byte)0x7b, "NEG-INT", (byte)2, ReferenceType.none, "12x"),
NOT_INT((byte)0x7c, "NOT-INT", (byte)2, ReferenceType.none, "12x"),
NEG_LONG((byte)0x7d, "NEG-LONG", (byte)2, ReferenceType.none, "12x"),
NOT_LONG((byte)0x7e, "NOT-LONG", (byte)2, ReferenceType.none, "12x"),
NEG_FLOAT((byte)0x7f, "NEG-FLOAT", (byte)2, ReferenceType.none, "12x"),
NEG_DOUBLE((byte)0x80, "NEG-DOUBLE", (byte)2, ReferenceType.none, "12x"),
INT_TO_LONG((byte)0x81, "INT-TO-LONG", (byte)2, ReferenceType.none, "12x"),
INT_TO_FLOAT((byte)0x82, "INT-TO-FLOAT", (byte)2, ReferenceType.none, "12x"),
INT_TO_DOUBLE((byte)0x83, "INT-TO-DOUBLE", (byte)2, ReferenceType.none, "12x"),
LONG_TO_INT((byte)0x84, "LONG-TO-INT", (byte)2, ReferenceType.none, "12x"),
LONG_TO_FLOAT((byte)0x85, "LONG-TO-FLOAT", (byte)2, ReferenceType.none, "12x"),
LONG_TO_DOUBLE((byte)0x86, "LONG-TO-DOUBLE", (byte)2, ReferenceType.none, "12x"),
FLOAT_TO_INT((byte)0x87, "FLOAT-TO-INT", (byte)2, ReferenceType.none, "12x"),
FLOAT_TO_LONG((byte)0x88, "FLOAT-TO-LONG", (byte)2, ReferenceType.none, "12x"),
FLOAT_TO_DOUBLE((byte)0x89, "FLOAT-TO-DOUBLE", (byte)2, ReferenceType.none, "12x"),
DOUBLE_TO_INT((byte)0x8a, "DOUBLE-TO-INT", (byte)2, ReferenceType.none, "12x"),
DOUBLE_TO_LONG((byte)0x8b, "DOUBLE-TO-LONG", (byte)2, ReferenceType.none, "12x"),
DOUBLE_TO_FLOAT((byte)0x8c, "DOUBLE-TO-FLOAT", (byte)2, ReferenceType.none, "12x"),
INT_TO_BYTE((byte)0x8d, "INT-TO-BYTE", (byte)2, ReferenceType.none, "12x"),
INT_TO_CHAR((byte)0x8e, "INT-TO-CHAR", (byte)2, ReferenceType.none, "12x"),
INT_TO_SHORT((byte)0x8f, "INT-TO-SHORT", (byte)2, ReferenceType.none, "12x"),
ADD_INT((byte)0x90, "ADD-INT", (byte)4, ReferenceType.none, "23x"),
SUB_INT((byte)0x91, "SUB-INT", (byte)4, ReferenceType.none, "23x"),
MUL_INT((byte)0x92, "MUL-INT", (byte)4, ReferenceType.none, "23x"),
DIV_INT((byte)0x93, "DIV-INT", (byte)4, ReferenceType.none, "23x"),
REM_INT((byte)0x94, "REM-INT", (byte)4, ReferenceType.none, "23x"),
AND_INT((byte)0x95, "AND-INT", (byte)4, ReferenceType.none, "23x"),
OR_INT((byte)0x96, "OR-INT", (byte)4, ReferenceType.none, "23x"),
XOR_INT((byte)0x97, "XOR-INT", (byte)4, ReferenceType.none, "23x"),
SHL_INT((byte)0x98, "SHL-INT", (byte)4, ReferenceType.none, "23x"),
SHR_INT((byte)0x99, "SHR-INT", (byte)4, ReferenceType.none, "23x"),
USHR_INT((byte)0x9a, "USHR-INT", (byte)4, ReferenceType.none, "23x"),
ADD_LONG((byte)0x9b, "ADD-LONG", (byte)4, ReferenceType.none, "23x"),
SUB_LONG((byte)0x9c, "SUB-LONG", (byte)4, ReferenceType.none, "23x"),
MUL_LONG((byte)0x9d, "MUL-LONG", (byte)4, ReferenceType.none, "23x"),
DIV_LONG((byte)0x9e, "DIV-LONG", (byte)4, ReferenceType.none, "23x"),
REM_LONG((byte)0x9f, "REM-LONG", (byte)4, ReferenceType.none, "23x"),
AND_LONG((byte)0xa0, "AND-LONG", (byte)4, ReferenceType.none, "23x"),
OR_LONG((byte)0xa1, "OR-LONG", (byte)4, ReferenceType.none, "23x"),
XOR_LONG((byte)0xa2, "XOR-LONG", (byte)4, ReferenceType.none, "23x"),
SHL_LONG((byte)0xa3, "SHL-LONG", (byte)4, ReferenceType.none, "23x"),
SHR_LONG((byte)0xa4, "SHR-LONG", (byte)4, ReferenceType.none, "23x"),
USHR_LONG((byte)0xa5, "USHR-LONG", (byte)4, ReferenceType.none, "23x"),
ADD_FLOAT((byte)0xa6, "ADD-FLOAT", (byte)4, ReferenceType.none, "23x"),
SUB_FLOAT((byte)0xa7, "SUB-FLOAT", (byte)4, ReferenceType.none, "23x"),
MUL_FLOAT((byte)0xa8, "MUL-FLOAT", (byte)4, ReferenceType.none, "23x"),
DIV_FLOAT((byte)0xa9, "DIV-FLOAT", (byte)4, ReferenceType.none, "23x"),
REM_FLOAT((byte)0xaa, "REM-FLOAT", (byte)4, ReferenceType.none, "23x"),
ADD_DOUBLE((byte)0xab, "ADD-DOUBLE", (byte)4, ReferenceType.none, "23x"),
SUB_DOUBLE((byte)0xac, "SUB-DOUBLE", (byte)4, ReferenceType.none, "23x"),
MUL_DOUBLE((byte)0xad, "MUL-DOUBLE", (byte)4, ReferenceType.none, "23x"),
DIV_DOUBLE((byte)0xae, "DIV-DOUBLE", (byte)4, ReferenceType.none, "23x"),
REM_DOUBLE((byte)0xaf, "REM-DOUBLE", (byte)4, ReferenceType.none, "23x"),
ADD_INT_2ADDR((byte)0xb0, "ADD-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
SUB_INT_2ADDR((byte)0xb1, "SUB-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
MUL_INT_2ADDR((byte)0xb2, "MUL-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
DIV_INT_2ADDR((byte)0xb3, "DIV-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
REM_INT_2ADDR((byte)0xb4, "REM-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
AND_INT_2ADDR((byte)0xb5, "AND-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
OR_INT_2ADDR((byte)0xb6, "OR-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
XOR_INT_2ADDR((byte)0xb7, "XOR-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
SHL_INT_2ADDR((byte)0xb8, "SHL-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
SHR_INT_2ADDR((byte)0xb9, "SHR-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
USHR_INT_2ADDR((byte)0xba, "USHR-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
ADD_LONG_2ADDR((byte)0xbb, "ADD-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
SUB_LONG_2ADDR((byte)0xbc, "SUB-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
MUL_LONG_2ADDR((byte)0xbd, "MUL-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
DIV_LONG_2ADDR((byte)0xbe, "DIV-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
REM_LONG_2ADDR((byte)0xbf, "REM-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
AND_LONG_2ADDR((byte)0xc0, "AND-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
OR_LONG_2ADDR((byte)0xc1, "OR-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
XOR_LONG_2ADDR((byte)0xc2, "XOR-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
SHL_LONG_2ADDR((byte)0xc3, "SHL-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
SHR_LONG_2ADDR((byte)0xc4, "SHR-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
USHR_LONG_2ADDR((byte)0xc5, "USHR-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
ADD_FLOAT_2ADDR((byte)0xc6, "ADD-FLOAT/2ADDR", (byte)2, ReferenceType.none, "12x"),
SUB_FLOAT_2ADDR((byte)0xc7, "SUB-FLOAT/2ADDR", (byte)2, ReferenceType.none, "12x"),
MUL_FLOAT_2ADDR((byte)0xc8, "MUL-FLOAT/2ADDR", (byte)2, ReferenceType.none, "12x"),
DIV_FLOAT_2ADDR((byte)0xc9, "DIV-FLOAT/2ADDR", (byte)2, ReferenceType.none, "12x"),
REM_FLOAT_2ADDR((byte)0xca, "REM-FLOAT/2ADDR", (byte)2, ReferenceType.none, "12x"),
ADD_DOUBLE_2ADDR((byte)0xcb, "ADD-DOUBLE/2ADDR", (byte)2, ReferenceType.none, "12x"),
SUB_DOUBLE_2ADDR((byte)0xcc, "SUB-DOUBLE/2ADDR", (byte)2, ReferenceType.none, "12x"),
MUL_DOUBLE_2ADDR((byte)0xcd, "MUL-DOUBLE/2ADDR", (byte)2, ReferenceType.none, "12x"),
DIV_DOUBLE_2ADDR((byte)0xce, "DIV-DOUBLE/2ADDR", (byte)2, ReferenceType.none, "12x"),
REM_DOUBLE_2ADDR((byte)0xcf, "REM-DOUBLE/2ADDR", (byte)2, ReferenceType.none, "12x"),
ADD_INT_LIT16((byte)0xd0, "ADD-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
RSUB_INT_LIT16((byte)0xd1, "RSUB-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
MUL_INT_LIT16((byte)0xd2, "MUL-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
DIV_INT_LIT16((byte)0xd3, "DIV-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
REM_INT_LIT16((byte)0xd4, "REM-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
AND_INT_LIT16((byte)0xd5, "AND-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
OR_INT_LIT16((byte)0xd6, "OR-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
XOR_INT_LIT16((byte)0xd7, "XOR-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
ADD_INT_LIT8((byte)0xd8, "ADD-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
RSUB_INT_LIT8((byte)0xd9, "RSUB-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
MUL_INT_LIT8((byte)0xda, "MUL-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
DIV_INT_LIT8((byte)0xdb, "DIV-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
REM_INT_LIT8((byte)0xdc, "REM-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
AND_INT_LIT8((byte)0xdd, "AND-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
OR_INT_LIT8((byte)0xde, "OR-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
XOR_INT_LIT8((byte)0xdf, "XOR-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
SHL_INT_LIT8((byte)0xe0, "SHL-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
SHR_INT_LIT8((byte)0xe1, "SHR-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
USHR_INT_LIT8((byte)0xe2, "USHR-INT/LIT8", (byte)4, ReferenceType.none, "22b");
private static ArrayList<Opcode> opcodesByValue;
private static HashMap<Integer, Opcode> opcodesByName;
static {
try
{
opcodesByValue = new ArrayList<Opcode>();
opcodesByName = new HashMap<Integer, Opcode>();
for (int i=0; i<0x100; i++) {
opcodesByValue.add(null);
}
for (Opcode opcode: Opcode.values()) {
opcodesByValue.set((opcode.value & 0xFF), opcode);
opcodesByName.put(opcode.name.toLowerCase().hashCode(), opcode);
}
}catch (Exception ex) {
System.out.println(ex.toString());
}
}
public static Opcode getOpcodeByName(String opcodeName) {
return opcodesByName.get(opcodeName.toLowerCase().hashCode());
}
public static Opcode getOpcodeByValue(byte opcodeValue) {
return opcodesByValue.get(opcodeValue);
}
public final byte value;
public final String name;
public final byte numBytes;
public final ReferenceType referenceType;
public final String format;
Opcode(byte opcodeValue, String opcodeName, byte numBytes, ReferenceType referenceType, String format) {
this.value = opcodeValue;
this.name = opcodeName;
this.numBytes = numBytes;
this.referenceType = referenceType;
this.format = format;
}
}

View File

@ -0,0 +1,56 @@
/*
* [The "BSD licence"]
* Copyright (c) 2009 Ben Gruver
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.JesusFreke.dexlib.code;
import org.JesusFreke.dexlib.*;
public enum ReferenceType
{
string,
type,
field,
method,
none;
public boolean checkItem(IndexedItem item) {
switch (this) {
case string:
return item instanceof StringIdItem;
case type:
return item instanceof TypeIdItem;
case field:
return item instanceof FieldIdItem;
case method:
return item instanceof MethodIdItem;
case none:
return item == null;
}
return false;
}
}

View File

@ -0,0 +1,53 @@
/*
* [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.debug;
import org.JesusFreke.dexlib.CompositeField;
import org.JesusFreke.dexlib.Field;
import org.JesusFreke.dexlib.ByteField;
import org.JesusFreke.dexlib.SignedLeb128Field;
public class AdvanceLine extends CompositeField<AdvanceLine> implements DebugInstruction<AdvanceLine> {
private final Field[] fields;
public AdvanceLine() {
fields = new Field[] {
new ByteField((byte)0x02),
new SignedLeb128Field()
};
}
protected Field[] getFields() {
return fields;
}
public byte getOpcode() {
return 0x02;
}
}

View File

@ -0,0 +1,50 @@
/*
* [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.debug;
import org.JesusFreke.dexlib.*;
public class AdvancePC extends CompositeField<AdvancePC> implements DebugInstruction<AdvancePC> {
private final Field[] fields;
public AdvancePC() {
fields = new Field[] {
new ByteField((byte)0x01),
new Leb128Field()
};
}
protected Field[] getFields() {
return fields;
}
public byte getOpcode() {
return 0x01;
}
}

View File

@ -0,0 +1,35 @@
/*
* [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.debug;
import org.JesusFreke.dexlib.Field;
public interface DebugInstruction<T extends DebugInstruction> extends Field<T> {
public byte getOpcode();
}

View File

@ -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.debug;
import org.JesusFreke.dexlib.DexFile;
import org.JesusFreke.dexlib.util.Input;
public abstract class DebugInstructionFactory {
public static DebugInstruction readDebugInstruction(DexFile dexFile, Input in) {
int startCursor = in.getCursor();
byte opcode = in.readByte();
in.setCursor(startCursor);
DebugInstruction debugInstruction = makeDebugInstruction(dexFile, opcode);
debugInstruction.readFrom(in);
return debugInstruction;
}
public static DebugInstruction makeDebugInstruction(DexFile dexFile, byte opcode) {
switch (opcode) {
case 0x00:
return new EndSequence();
case 0x01:
return new AdvancePC();
case 0x02:
return new AdvanceLine();
case 0x03:
return new StartLocal(dexFile);
case 0x04:
return new StartLocalExtended(dexFile);
case 0x05:
return new EndLocal();
case 0x06:
return new RestartLocal();
case 0x07:
return new SetPrologueEnd();
case 0x08:
return new SetEpilogueBegin();
case 0x09:
return new SetFile(dexFile);
default:
return new SpecialOpcode(opcode);
}
}
}

View File

@ -0,0 +1,50 @@
/*
* [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.debug;
import org.JesusFreke.dexlib.*;
public class EndLocal extends CompositeField<EndLocal> implements DebugInstruction<EndLocal> {
private final Field[] fields;
public EndLocal() {
fields = new Field[] {
new ByteField((byte)0x05),
new Leb128Field()
};
}
protected Field[] getFields() {
return fields;
}
public byte getOpcode() {
return 0x05;
}
}

View File

@ -0,0 +1,51 @@
/*
* [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.debug;
import org.JesusFreke.dexlib.CompositeField;
import org.JesusFreke.dexlib.Field;
import org.JesusFreke.dexlib.ByteField;
public class EndSequence extends CompositeField<EndSequence> implements DebugInstruction<EndSequence> {
private final Field[] fields;
public EndSequence() {
fields = new Field[] {
new ByteField((byte)0x00)
};
}
protected Field[] getFields() {
return fields;
}
public byte getOpcode() {
return 0x00;
}
}

View File

@ -0,0 +1,50 @@
/*
* [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.debug;
import org.JesusFreke.dexlib.*;
public class RestartLocal extends CompositeField<RestartLocal> implements DebugInstruction<RestartLocal> {
private final Field[] fields;
public RestartLocal() {
fields = new Field[] {
new ByteField((byte)0x06),
new SignedLeb128Field()
};
}
protected Field[] getFields() {
return fields;
}
public byte getOpcode() {
return 0x06;
}
}

View File

@ -0,0 +1,51 @@
/*
* [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.debug;
import org.JesusFreke.dexlib.CompositeField;
import org.JesusFreke.dexlib.Field;
import org.JesusFreke.dexlib.ByteField;
public class SetEpilogueBegin extends CompositeField<SetEpilogueBegin> implements DebugInstruction<SetEpilogueBegin> {
private final Field[] fields;
public SetEpilogueBegin() {
fields = new Field[] {
new ByteField((byte)0x08)
};
}
protected Field[] getFields() {
return fields;
}
public byte getOpcode() {
return 0x08;
}
}

View File

@ -0,0 +1,50 @@
/*
* [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.debug;
import org.JesusFreke.dexlib.*;
public class SetFile extends CompositeField<SetFile> implements DebugInstruction<SetFile> {
private final Field[] fields;
public SetFile(DexFile dexFile) {
fields = new Field[] {
new ByteField((byte)0x09),
new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new Leb128p1Field())
};
}
protected Field[] getFields() {
return fields;
}
public byte getOpcode() {
return 0x09;
}
}

View File

@ -0,0 +1,51 @@
/*
* [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.debug;
import org.JesusFreke.dexlib.CompositeField;
import org.JesusFreke.dexlib.Field;
import org.JesusFreke.dexlib.ByteField;
public class SetPrologueEnd extends CompositeField<SetPrologueEnd> implements DebugInstruction<SetPrologueEnd> {
private final Field[] fields;
public SetPrologueEnd() {
fields = new Field[] {
new ByteField((byte)0x07)
};
}
protected Field[] getFields() {
return fields;
}
public byte getOpcode() {
return 0x07;
}
}

View File

@ -0,0 +1,54 @@
/*
* [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.debug;
import org.JesusFreke.dexlib.CompositeField;
import org.JesusFreke.dexlib.Field;
import org.JesusFreke.dexlib.ByteField;
public class SpecialOpcode extends CompositeField<SpecialOpcode> implements DebugInstruction<SpecialOpcode> {
private final Field[] fields;
private final byte opcode;
public SpecialOpcode(byte opcode) {
this.opcode = opcode;
fields = new Field[] {
new ByteField(opcode)
};
}
protected Field[] getFields() {
return fields;
}
public byte getOpcode() {
return opcode;
}
}

View File

@ -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.debug;
import org.JesusFreke.dexlib.*;
public class StartLocal extends CompositeField<StartLocal> implements DebugInstruction<StartLocal> {
private final Field[] fields;
public StartLocal(DexFile dexFile) {
fields = new Field[] {
new ByteField((byte)0x03),
new SignedLeb128Field(),
new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new Leb128p1Field()),
new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new Leb128p1Field()),
};
}
protected Field[] getFields() {
return fields;
}
public byte getOpcode() {
return 0x03;
}
}

View File

@ -0,0 +1,53 @@
/*
* [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.debug;
import org.JesusFreke.dexlib.*;
public class StartLocalExtended extends CompositeField<StartLocalExtended> implements DebugInstruction<StartLocalExtended> {
private final Field[] fields;
public StartLocalExtended(DexFile dexFile) {
fields = new Field[] {
new ByteField((byte)0x04),
new SignedLeb128Field(),
new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new Leb128p1Field()),
new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new Leb128p1Field()),
new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new Leb128p1Field())
};
}
protected Field[] getFields() {
return fields;
}
public byte getOpcode() {
return 0x04;
}
}

View File

@ -0,0 +1,59 @@
/*
* [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.util;
import java.util.HashMap;
public class AccessFlags
{
public static final int PUBLIC = 0x01;
public static final int PRIVATE = 0x02;
public static final int STATIC = 0x08;
public static final int CONSTRUCTOR = 0x10000;
private static HashMap<String, Integer> accessFlagValues;
static {
accessFlagValues = new HashMap<String, Integer>();
accessFlagValues.put("public", PUBLIC);
accessFlagValues.put("private", PRIVATE);
accessFlagValues.put("static", STATIC);
accessFlagValues.put("constructor", CONSTRUCTOR);
}
public static int getValueForAccessFlag(String accessFlag) {
Integer retVal;
retVal = accessFlagValues.get(accessFlag);
if (retVal == null) {
return 0;
}
return retVal.intValue();
}
}

View File

@ -0,0 +1,379 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.JesusFreke.dexlib.util;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Wrapper for a <code>byte[]</code>, which provides read-only access and
* can "reveal" a partial slice of the underlying array.
*
* <b>Note:</b> Multibyte accessors all use big-endian order.
*/
public final class ByteArray {
/** non-null; underlying array */
private final byte[] bytes;
/** <code>&gt;= 0</code>; start index of the slice (inclusive) */
private final int start;
/** <code>&gt;= 0, &lt;= bytes.length</code>; size computed as
* <code>end - start</code> (in the constructor) */
private final int size;
/**
* Constructs an instance.
*
* @param bytes non-null; the underlying array
* @param start <code>&gt;= 0</code>; start index of the slice (inclusive)
* @param end <code>&gt;= start, &lt;= bytes.length</code>; end index of
* the slice (exclusive)
*/
public ByteArray(byte[] bytes, int start, int end) {
if (bytes == null) {
throw new NullPointerException("bytes == null");
}
if (start < 0) {
throw new IllegalArgumentException("start < 0");
}
if (end < start) {
throw new IllegalArgumentException("end < start");
}
if (end > bytes.length) {
throw new IllegalArgumentException("end > bytes.length");
}
this.bytes = bytes;
this.start = start;
this.size = end - start;
}
/**
* Constructs an instance from an entire <code>byte[]</code>.
*
* @param bytes non-null; the underlying array
*/
public ByteArray(byte[] bytes) {
this(bytes, 0, bytes.length);
}
/**
* Gets the size of the array, in bytes.
*
* @return &gt;= 0; the size
*/
public int size() {
return size;
}
/**
* Returns a slice (that is, a sub-array) of this instance.
*
* @param start <code>&gt;= 0</code>; start index of the slice (inclusive)
* @param end <code>&gt;= start, &lt;= size()</code>; end index of
* the slice (exclusive)
* @return non-null; the slice
*/
public ByteArray slice(int start, int end) {
checkOffsets(start, end);
return new ByteArray(bytes, start + this.start, end + this.start);
}
/**
* Returns the offset into the given array represented by the given
* offset into this instance.
*
* @param offset offset into this instance
* @param bytes non-null; (alleged) underlying array
* @return corresponding offset into <code>bytes</code>
* @throws IllegalArgumentException thrown if <code>bytes</code> is
* not the underlying array of this instance
*/
public int underlyingOffset(int offset, byte[] bytes) {
if (bytes != this.bytes) {
throw new IllegalArgumentException("wrong bytes");
}
return start + offset;
}
/**
* Gets the <code>signed byte</code> value at a particular offset.
*
* @param off <code>&gt;= 0, &lt; size(); offset to fetch
* @return <code>signed byte</code> at that offset
*/
public int getByte(int off) {
checkOffsets(off, off + 1);
return getByte0(off);
}
/**
* Gets the <code>signed short</code> value at a particular offset.
*
* @param off <code>&gt;= 0, &lt; (size() - 1); offset to fetch
* @return <code>signed short</code> at that offset
*/
public int getShort(int off) {
checkOffsets(off, off + 2);
return (getByte0(off) << 8) | getUnsignedByte0(off + 1);
}
/**
* Gets the <code>signed int</code> value at a particular offset.
*
* @param off <code>&gt;= 0, &lt; (size() - 3); offset to fetch
* @return <code>signed int</code> at that offset
*/
public int getInt(int off) {
checkOffsets(off, off + 4);
return (getByte0(off) << 24) |
(getUnsignedByte0(off + 1) << 16) |
(getUnsignedByte0(off + 2) << 8) |
getUnsignedByte0(off + 3);
}
/**
* Gets the <code>signed long</code> value at a particular offset.
*
* @param off <code>&gt;= 0, &lt; (size() - 7); offset to fetch
* @return <code>signed int</code> at that offset
*/
public long getLong(int off) {
checkOffsets(off, off + 8);
int part1 = (getByte0(off) << 24) |
(getUnsignedByte0(off + 1) << 16) |
(getUnsignedByte0(off + 2) << 8) |
getUnsignedByte0(off + 3);
int part2 = (getByte0(off + 4) << 24) |
(getUnsignedByte0(off + 5) << 16) |
(getUnsignedByte0(off + 6) << 8) |
getUnsignedByte0(off + 7);
return (part2 & 0xffffffffL) | ((long) part1) << 32;
}
/**
* Gets the <code>unsigned byte</code> value at a particular offset.
*
* @param off <code>&gt;= 0, &lt; size(); offset to fetch
* @return <code>unsigned byte</code> at that offset
*/
public int getUnsignedByte(int off) {
checkOffsets(off, off + 1);
return getUnsignedByte0(off);
}
/**
* Gets the <code>unsigned short</code> value at a particular offset.
*
* @param off <code>&gt;= 0, &lt; (size() - 1); offset to fetch
* @return <code>unsigned short</code> at that offset
*/
public int getUnsignedShort(int off) {
checkOffsets(off, off + 2);
return (getUnsignedByte0(off) << 8) | getUnsignedByte0(off + 1);
}
/**
* Copies the contents of this instance into the given raw
* <code>byte[]</code> at the given offset. The given array must be
* large enough.
*
* @param out non-null; array to hold the output
* @param offset non-null; index into <code>out</code> for the first
* byte of output
*/
public void getBytes(byte[] out, int offset) {
if ((out.length - offset) < size) {
throw new IndexOutOfBoundsException("(out.length - offset) < " +
"size()");
}
System.arraycopy(bytes, start, out, offset, size);
}
/**
* Checks a range of offsets for validity, throwing if invalid.
*
* @param s start offset (inclusive)
* @param e end offset (exclusive)
*/
private void checkOffsets(int s, int e) {
if ((s < 0) || (e < s) || (e > size)) {
throw new IllegalArgumentException("bad range: " + s + ".." + e +
"; actual size " + size);
}
}
/**
* Gets the <code>signed byte</code> value at the given offset,
* without doing any argument checking.
*
* @param off offset to fetch
* @return byte at that offset
*/
private int getByte0(int off) {
return bytes[start + off];
}
/**
* Gets the <code>unsigned byte</code> value at the given offset,
* without doing any argument checking.
*
* @param off offset to fetch
* @return byte at that offset
*/
private int getUnsignedByte0(int off) {
return bytes[start + off] & 0xff;
}
/**
* Gets a <code>DataInputStream</code> that reads from this instance,
* with the cursor starting at the beginning of this instance's data.
* <b>Note:</b> The returned instance may be cast to {@link #GetCursor}
* if needed.
*
* @return non-null; an appropriately-constructed
* <code>DataInputStream</code> instance
*/
public MyDataInputStream makeDataInputStream() {
return new MyDataInputStream(makeInputStream());
}
/**
* Gets a <code>InputStream</code> that reads from this instance,
* with the cursor starting at the beginning of this instance's data.
* <b>Note:</b> The returned instance may be cast to {@link #GetCursor}
* if needed.
*
* @return non-null; an appropriately-constructed
* <code>InputStream</code> instancex
*/
public MyInputStream makeInputStream() {
return new MyInputStream();
}
/**
* Helper interface that allows one to get the cursor (of a stream).
*/
public interface GetCursor {
/**
* Gets the current cursor.
*
* @return 0..size(); the cursor
*/
public int getCursor();
}
/**
* Helper class for {@link #makeInputStream}, which implements the
* stream functionality.
*/
public class MyInputStream extends InputStream {
/** 0..size; the cursor */
private int cursor;
/** 0..size; the mark */
private int mark;
public MyInputStream() {
cursor = 0;
mark = 0;
}
public int read() throws IOException {
if (cursor >= size) {
return -1;
}
int result = getUnsignedByte0(cursor);
cursor++;
return result;
}
public int read(byte[] arr, int offset, int length) {
if ((offset + length) > arr.length) {
length = arr.length - offset;
}
int maxLength = size - cursor;
if (length > maxLength) {
length = maxLength;
}
System.arraycopy(bytes, cursor, arr, offset, length);
cursor += length;
return length;
}
public int available() {
return size - cursor;
}
public void mark(int reserve) {
mark = cursor;
}
public void reset() {
cursor = mark;
}
public boolean markSupported() {
return true;
}
/**
* Gets the current cursor.
*
* @return 0..size(); the cursor
*/
public int getCursor() {
return cursor;
}
}
/**
* Helper class for {@link #makeDataInputStream}. This is used
* simply so that the cursor of a wrapped {@link #MyInputStream}
* instance may be easily determined.
*/
public class MyDataInputStream extends DataInputStream {
/** non-null; the underlying {@link #MyInputStream} */
private final MyInputStream wrapped;
public MyDataInputStream(MyInputStream wrapped) {
super(wrapped);
this.wrapped = wrapped;
}
/**
* Gets the current cursor.
*
* @return 0..size(); the cursor
*/
public int getCursor() {
return wrapped.getCursor();
}
}
}

View File

@ -0,0 +1,312 @@
/*
* [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.util;
/**
* Implementation of {@link Input} which reads the data from a
* <code>byte[]</code> instance.
*
* <p><b>Note:</b> As per the {@link Input } interface, multi-byte
* reads all use little-endian order.</p>
*/
public class ByteArrayInput
implements Input {
/** non-null; the data itself */
private byte[] data;
/** &gt;= 0; current read cursor */
private int cursor;
/**
* Constructs an instance with the given data
*
* @param data non-null; data array to use for input
*/
public ByteArrayInput(byte[] data) {
if (data == null) {
throw new NullPointerException("data == null");
}
this.data = data;
this.cursor = 0;
}
/**
* Gets the underlying <code>byte[]</code> of this instance
*
* @return non-null; the <code>byte[]</code>
*/
public byte[] getArray() {
return data;
}
/** {@inheritDoc} */
public int getCursor() {
return cursor;
}
/** {@inheritDoc} */
public void setCursor(int cursor) {
if (cursor < 0 || cursor >= data.length)
throw new IndexOutOfBoundsException("The provided cursor value " +
"is not within the bounds of this instance's data array");
this.cursor = cursor;
}
/** {@inheritDoc} */
public void assertCursor(int expectedCursor) {
if (cursor != expectedCursor) {
throw new ExceptionWithContext("expected cursor " +
expectedCursor + "; actual value: " + cursor);
}
}
/** {@inheritDoc} */
public byte readByte() {
int readAt = cursor;
int end = readAt + 1;
if (end > data.length) {
throwBounds();
}
cursor = end;
return data[readAt];
}
/** {@inheritDoc} */
public int readShort() {
int readAt = cursor;
int end = readAt + 2;
if (end > data.length) {
throwBounds();
}
cursor = end;
return (int)((data[readAt] & 0xff) +
((data[readAt + 1] & 0xff) << 8));
}
/** {@inheritDoc} */
public int readInt() {
int readAt = cursor;
int end = readAt + 4;
if (end > data.length) {
throwBounds();
}
cursor = end;
return (data[readAt] & 0xff) +
((data[readAt + 1] & 0xff) << 8) +
((data[readAt + 2] & 0xff) << 16) +
((data[readAt + 3] & 0xff) << 24);
}
/** {@inheritDoc} */
public long readLong() {
int readAt = cursor;
int end = readAt + 8;
if (end > data.length) {
throwBounds();
}
cursor = end;
/**
* TODO: is there a faster/better way to do this?
*/
return (long)((data[readAt] & 0xff) +
((data[readAt + 1] & 0xff) << 8) +
((data[readAt + 2] & 0xff) << 16) +
((data[readAt + 3] & 0xff) << 24))
+
((long)((data[readAt + 4] & 0xff)+
((data[readAt + 5] & 0xff) << 8) +
((data[readAt + 6] & 0xff) << 16) +
((data[readAt + 7] & 0xff) << 24)) << 32);
}
/** {@inheritDoc} */
public int readUnsignedLeb128() {
int end = cursor;
int currentByteValue;
int result;
result = data[end++] & 0xff;
if (result > 0x7f) {
currentByteValue = data[end++] & 0xff;
result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
if (currentByteValue > 0x7f) {
currentByteValue = data[end++] & 0xff;
result |= (currentByteValue & 0x7f) << 14;
if (currentByteValue > 0x7f) {
currentByteValue = data[end++] & 0xff;
result |= (currentByteValue & 0x7f) << 21;
if (currentByteValue > 0x7f) {
currentByteValue = data[end++] & 0xff;
if (currentByteValue > 0x0f) {
throwInvalidLeb();
}
result |= currentByteValue << 28;
}
}
}
}
cursor = end;
return result;
}
/** {@inheritDoc} */
public int readSignedLeb128() {
int end = cursor;
int currentByteValue;
int result;
result = data[end++] & 0xff;
if (result <= 0x7f) {
result = (result << 25) >> 25;
} else {
currentByteValue = data[end++] & 0xff;
result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
if (currentByteValue <= 0x7f) {
result = (result << 18) >> 18;
} else {
currentByteValue = data[end++] & 0xff;
result |= (currentByteValue & 0x7f) << 14;
if (currentByteValue <= 0x7f) {
result = (result << 11) >> 11;
} else {
currentByteValue = data[end++] & 0xff;
result |= (currentByteValue & 0x7f) << 21;
if (currentByteValue <= 0x7f) {
result = (result << 4) >> 4;
} else {
currentByteValue = data[end++] & 0xff;
if (currentByteValue > 0x0f) {
throwInvalidLeb();
}
result |= currentByteValue << 28;
}
}
}
}
cursor = end;
return result;
}
/** {@inheritDoc} */
public void read(byte[] bytes, int offset, int length) {
int end = cursor + length;
if (end > data.length) {
throwBounds();
}
System.arraycopy(data, cursor, bytes, offset, length);
cursor = end;
}
/** {@inheritDoc} */
public void read(byte[] bytes) {
int length = bytes.length;
int end = cursor + length;
if (end > data.length) {
throwBounds();
}
System.arraycopy(data, cursor, bytes, 0, length);
cursor = end;
}
/** {@inheritDoc} */
public byte[] readBytes(int length) {
int end = cursor + length;
if (end > data.length) {
throwBounds();
}
byte[] result = new byte[length];
System.arraycopy(data, cursor, result, 0, length);
cursor = end;
return result;
}
/** {@inheritDoc} */
public void skipBytes(int count) {
int end = cursor + count;
if (end > data.length) {
throwBounds();
}
cursor = end;
}
/** {@inheritDoc} */
public void alignTo(int alignment) {
int mask = alignment - 1;
if ((alignment < 0) || ((mask & alignment) != 0)) {
throw new IllegalArgumentException("bogus alignment");
}
int end = (cursor + mask) & ~mask;
if (end > data.length) {
throwBounds();
}
cursor = end;
}
/**
* Throws the excpetion for when an attempt is made to read past the
* end of the instance.
*/
private static void throwBounds() {
throw new IndexOutOfBoundsException("attempt to read past the end");
}
/**
* Throws the exception for when an invalid LEB128 value is encountered
*/
private static void throwInvalidLeb() {
throw new RuntimeException("invalid LEB128 integer encountered");
}
}

View File

@ -0,0 +1,582 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.JesusFreke.dexlib.util;
import java.util.ArrayList;
/**
* Implementation of {@link AnnotatedOutput} which stores the written data
* into a <code>byte[]</code>.
*
* <p><b>Note:</b> As per the {@link Output} interface, multi-byte
* writes all use little-endian order.</p>
*/
public final class ByteArrayOutput implements Output
{
/** default size for stretchy instances */
private static final int DEFAULT_SIZE = 1000;
/**
* whether the instance is stretchy, that is, whether its array
* may be resized to increase capacity
*/
private final boolean stretchy;
/** non-null; the data itself */
private byte[] data;
/** &gt;= 0; current output cursor */
private int cursor;
/** whether annotations are to be verbose */
private boolean verbose;
/**
* null-ok; list of annotations, or <code>null</code> if this instance
* isn't keeping them
*/
private ArrayList<Annotation> annotations;
/** &gt;= 40 (if used); the desired maximum annotation width */
private int annotationWidth;
/**
* &gt;= 8 (if used); the number of bytes of hex output to use
* in annotations
*/
private int hexCols;
/**
* Constructs an instance with a fixed maximum size. Note that the
* given array is the only one that will be used to store data. In
* particular, no reallocation will occur in order to expand the
* capacity of the resulting instance. Also, the constructed
* instance does not keep annotations by default.
*
* @param data non-null; data array to use for output
*/
public ByteArrayOutput(byte[] data) {
this(data, false);
}
/**
* Constructs a "stretchy" instance. The underlying array may be
* reallocated. The constructed instance does not keep annotations
* by default.
*/
public ByteArrayOutput() {
this(new byte[DEFAULT_SIZE], true);
}
/**
* Internal constructor.
*
* @param data non-null; data array to use for output
* @param stretchy whether the instance is to be stretchy
*/
private ByteArrayOutput(byte[] data, boolean stretchy) {
if (data == null) {
throw new NullPointerException("data == null");
}
this.stretchy = stretchy;
this.data = data;
this.cursor = 0;
this.verbose = false;
this.annotations = null;
this.annotationWidth = 0;
this.hexCols = 0;
}
/**
* Gets the underlying <code>byte[]</code> of this instance, which
* may be larger than the number of bytes written
*
* @see #toByteArray
*
* @return non-null; the <code>byte[]</code>
*/
public byte[] getArray() {
return data;
}
/**
* Constructs and returns a new <code>byte[]</code> that contains
* the written contents exactly (that is, with no extra unwritten
* bytes at the end).
*
* @see #getArray
*
* @return non-null; an appropriately-constructed array
*/
public byte[] toByteArray() {
byte[] result = new byte[cursor];
System.arraycopy(data, 0, result, 0, cursor);
return result;
}
/** {@inheritDoc} */
public int getCursor() {
return cursor;
}
/** {@inheritDoc} */
public void assertCursor(int expectedCursor) {
if (cursor != expectedCursor) {
throw new ExceptionWithContext("expected cursor " +
expectedCursor + "; actual value: " + cursor);
}
}
/** {@inheritDoc} */
public void writeByte(int value) {
int writeAt = cursor;
int end = writeAt + 1;
if (stretchy) {
ensureCapacity(end);
} else if (end > data.length) {
throwBounds();
return;
}
data[writeAt] = (byte) value;
cursor = end;
}
/** {@inheritDoc} */
public void writeShort(int value) {
int writeAt = cursor;
int end = writeAt + 2;
if (stretchy) {
ensureCapacity(end);
} else if (end > data.length) {
throwBounds();
return;
}
data[writeAt] = (byte) value;
data[writeAt + 1] = (byte) (value >> 8);
cursor = end;
}
/** {@inheritDoc} */
public void writeInt(int value) {
int writeAt = cursor;
int end = writeAt + 4;
if (stretchy) {
ensureCapacity(end);
} else if (end > data.length) {
throwBounds();
return;
}
data[writeAt] = (byte) value;
data[writeAt + 1] = (byte) (value >> 8);
data[writeAt + 2] = (byte) (value >> 16);
data[writeAt + 3] = (byte) (value >> 24);
cursor = end;
}
/** {@inheritDoc} */
public void writeLong(long value) {
int writeAt = cursor;
int end = writeAt + 8;
if (stretchy) {
ensureCapacity(end);
} else if (end > data.length) {
throwBounds();
return;
}
int half = (int) value;
data[writeAt] = (byte) half;
data[writeAt + 1] = (byte) (half >> 8);
data[writeAt + 2] = (byte) (half >> 16);
data[writeAt + 3] = (byte) (half >> 24);
half = (int) (value >> 32);
data[writeAt + 4] = (byte) half;
data[writeAt + 5] = (byte) (half >> 8);
data[writeAt + 6] = (byte) (half >> 16);
data[writeAt + 7] = (byte) (half >> 24);
cursor = end;
}
/** {@inheritDoc} */
public int writeUnsignedLeb128(int value) {
int remaining = value >> 7;
int count = 0;
while (remaining != 0) {
writeByte((value & 0x7f) | 0x80);
value = remaining;
remaining >>= 7;
count++;
}
writeByte(value & 0x7f);
return count + 1;
}
/** {@inheritDoc} */
public int writeSignedLeb128(int value) {
int remaining = value >> 7;
int count = 0;
boolean hasMore = true;
int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1;
while (hasMore) {
hasMore = (remaining != end)
|| ((remaining & 1) != ((value >> 6) & 1));
writeByte((value & 0x7f) | (hasMore ? 0x80 : 0));
value = remaining;
remaining >>= 7;
count++;
}
return count;
}
/** {@inheritDoc} */
public void write(ByteArray bytes) {
int blen = bytes.size();
int writeAt = cursor;
int end = writeAt + blen;
if (stretchy) {
ensureCapacity(end);
} else if (end > data.length) {
throwBounds();
return;
}
bytes.getBytes(data, writeAt);
cursor = end;
}
/** {@inheritDoc} */
public void write(byte[] bytes, int offset, int length) {
int writeAt = cursor;
int end = writeAt + length;
int bytesEnd = offset + length;
// twos-complement math trick: ((x < 0) || (y < 0)) <=> ((x|y) < 0)
if (((offset | length | end) < 0) || (bytesEnd > bytes.length)) {
throw new IndexOutOfBoundsException("bytes.length " +
bytes.length + "; " +
offset + "..!" + end);
}
if (stretchy) {
ensureCapacity(end);
} else if (end > data.length) {
throwBounds();
return;
}
System.arraycopy(bytes, offset, data, writeAt, length);
cursor = end;
}
/** {@inheritDoc} */
public void write(byte[] bytes) {
write(bytes, 0, bytes.length);
}
/** {@inheritDoc} */
public void writeZeroes(int count) {
if (count < 0) {
throw new IllegalArgumentException("count < 0");
}
int end = cursor + count;
if (stretchy) {
ensureCapacity(end);
} else if (end > data.length) {
throwBounds();
return;
}
/*
* There is no need to actually write zeroes, since the array is
* already preinitialized with zeroes.
*/
cursor = end;
}
/** {@inheritDoc} */
public void alignTo(int alignment) {
int mask = alignment - 1;
if ((alignment < 0) || ((mask & alignment) != 0)) {
throw new IllegalArgumentException("bogus alignment");
}
int end = (cursor + mask) & ~mask;
if (stretchy) {
ensureCapacity(end);
} else if (end > data.length) {
throwBounds();
return;
}
/*
* There is no need to actually write zeroes, since the array is
* already preinitialized with zeroes.
*/
cursor = end;
}
/** {@inheritDoc} */
public boolean annotates() {
return (annotations != null);
}
/** {@inheritDoc} */
public boolean isVerbose() {
return verbose;
}
/** {@inheritDoc} */
public void annotate(String msg) {
if (annotations == null) {
return;
}
endAnnotation();
annotations.add(new Annotation(cursor, msg));
}
/** {@inheritDoc} */
public void annotate(int amt, String msg) {
if (annotations == null) {
return;
}
endAnnotation();
int asz = annotations.size();
int lastEnd = (asz == 0) ? 0 : annotations.get(asz - 1).getEnd();
int startAt;
if (lastEnd <= cursor) {
startAt = cursor;
} else {
startAt = lastEnd;
}
annotations.add(new Annotation(startAt, startAt + amt, msg));
}
/** {@inheritDoc} */
public void endAnnotation() {
if (annotations == null) {
return;
}
int sz = annotations.size();
if (sz != 0) {
annotations.get(sz - 1).setEndIfUnset(cursor);
}
}
/** {@inheritDoc} */
public int getAnnotationWidth() {
int leftWidth = 8 + (hexCols * 2) + (hexCols / 2);
return annotationWidth - leftWidth;
}
/**
* Indicates that this instance should keep annotations. This method may
* be called only once per instance, and only before any data has been
* written to the it.
*
* @param annotationWidth &gt;= 40; the desired maximum annotation width
* @param verbose whether or not to indicate verbose annotations
*/
public void enableAnnotations(int annotationWidth, boolean verbose) {
if ((annotations != null) || (cursor != 0)) {
throw new RuntimeException("cannot enable annotations");
}
if (annotationWidth < 40) {
throw new IllegalArgumentException("annotationWidth < 40");
}
int hexCols = (((annotationWidth - 7) / 15) + 1) & ~1;
if (hexCols < 6) {
hexCols = 6;
} else if (hexCols > 10) {
hexCols = 10;
}
this.annotations = new ArrayList<Annotation>(1000);
this.annotationWidth = annotationWidth;
this.hexCols = hexCols;
this.verbose = verbose;
}
/**
* Finishes up annotation processing. This closes off any open
* annotations and removes annotations that don't refer to written
* data.
*/
public void finishAnnotating() {
// Close off the final annotation, if any.
endAnnotation();
// Remove annotations that refer to unwritten data.
if (annotations != null) {
int asz = annotations.size();
while (asz > 0) {
Annotation last = annotations.get(asz - 1);
if (last.getStart() > cursor) {
annotations.remove(asz - 1);
asz--;
} else if (last.getEnd() > cursor) {
last.setEnd(cursor);
break;
} else {
break;
}
}
}
}
/**
* Throws the excpetion for when an attempt is made to write past the
* end of the instance.
*/
private static void throwBounds() {
throw new IndexOutOfBoundsException("attempt to write past the end");
}
/**
* Reallocates the underlying array if necessary. Calls to this method
* should be guarded by a test of {@link #stretchy}.
*
* @param desiredSize &gt;= 0; the desired minimum total size of the array
*/
private void ensureCapacity(int desiredSize) {
if (data.length < desiredSize) {
byte[] newData = new byte[desiredSize * 2 + 1000];
System.arraycopy(data, 0, newData, 0, cursor);
data = newData;
}
}
/**
* Annotation on output.
*/
private static class Annotation {
/** &gt;= 0; start of annotated range (inclusive) */
private final int start;
/**
* &gt;= 0; end of annotated range (exclusive);
* <code>Integer.MAX_VALUE</code> if unclosed
*/
private int end;
/** non-null; annotation text */
private final String text;
/**
* Constructs an instance.
*
* @param start &gt;= 0; start of annotated range
* @param end &gt;= start; end of annotated range (exclusive) or
* <code>Integer.MAX_VALUE</code> if unclosed
* @param text non-null; annotation text
*/
public Annotation(int start, int end, String text) {
this.start = start;
this.end = end;
this.text = text;
}
/**
* Constructs an instance. It is initally unclosed.
*
* @param start &gt;= 0; start of annotated range
* @param text non-null; annotation text
*/
public Annotation(int start, String text) {
this(start, Integer.MAX_VALUE, text);
}
/**
* Sets the end as given, but only if the instance is unclosed;
* otherwise, do nothing.
*
* @param end &gt;= start; the end
*/
public void setEndIfUnset(int end) {
if (this.end == Integer.MAX_VALUE) {
this.end = end;
}
}
/**
* Sets the end as given.
*
* @param end &gt;= start; the end
*/
public void setEnd(int end) {
this.end = end;
}
/**
* Gets the start.
*
* @return the start
*/
public int getStart() {
return start;
}
/**
* Gets the end.
*
* @return the end
*/
public int getEnd() {
return end;
}
/**
* Gets the text.
*
* @return non-null; the text
*/
public String getText() {
return text;
}
}
}

View File

@ -0,0 +1,143 @@
/*
* [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.util;
public class EncodedValueUtils {
public static byte getRequiredBytesForSignedIntegralValue(long value) {
/*
* Figure out how many bits are needed to represent the value,
* including a sign bit: The bit count is subtracted from 65
* and not 64 to account for the sign bit. The xor operation
* has the effect of leaving non-negative values alone and
* unary complementing negative values (so that a leading zero
* count always returns a useful number for our present
* purpose).
*/
int requiredBits =
65 - Long.numberOfLeadingZeros(value ^ (value >> 63));
// Round up the requiredBits to a number of bytes.
return (byte)((requiredBits + 0x07) >> 3);
}
public static long decodeSignedIntegralValue(byte[] bytes) {
long value = 0;
for (int i = 0; i < bytes.length; i++) {
value |= (((long)(bytes[i] & 0xFF)) << (i * 8));
}
int shift = (8 - bytes.length) * 8;
return value << shift >> shift;
}
public static byte[] encodeSignedIntegralValue(long value) {
int requiredBytes = getRequiredBytesForSignedIntegralValue(value);
byte[] bytes = new byte[requiredBytes];
for (int i = 0; i < requiredBytes; i++) {
bytes[i] = (byte) value;
value >>= 8;
}
return bytes;
}
public static byte getRequiredBytesForUnsignedIntegralValue(long value) {
// Figure out how many bits are needed to represent the value.
int requiredBits = 64 - Long.numberOfLeadingZeros(value);
if (requiredBits == 0) {
requiredBits = 1;
}
// Round up the requiredBits to a number of bytes.
return (byte)((requiredBits + 0x07) >> 3);
}
public static long decodeUnsignedIntegralValue(byte[] bytes) {
long value = 0;
for (int i = 0; i < bytes.length; i++) {
value |= (((long)(bytes[i] & 0xFF)) << i * 8);
}
return value;
}
public static byte[] encodeUnsignedIntegralValue(long value) {
int requiredBytes = getRequiredBytesForUnsignedIntegralValue(value);
byte[] bytes = new byte[requiredBytes];
for (int i = 0; i < requiredBytes; i++) {
bytes[i] = (byte) value;
value >>= 8;
}
return bytes;
}
public static int getRequiredBytesForRightZeroExtendedValue(long value) {
// Figure out how many bits are needed to represent the value.
int requiredBits = 64 - Long.numberOfTrailingZeros(value);
if (requiredBits == 0) {
requiredBits = 1;
}
// Round up the requiredBits to a number of bytes.
return (requiredBits + 0x07) >> 3;
}
public static long decodeRightZeroExtendedValue(byte[] bytes) {
long value = 0;
for (int i = 0; i < bytes.length; i++) {
value |= (((long)(bytes[i] & 0xFF)) << (i * 8));
}
return value << (8 - bytes.length) * 8;
}
public static byte[] encodeRightZeroExtendedValue(long value) {
int requiredBytes = getRequiredBytesForRightZeroExtendedValue(value);
// Scootch the first bits to be written down to the low-order bits.
value >>= 64 - (requiredBytes * 8);
byte[] bytes = new byte[requiredBytes];
for(int i = 0; i < requiredBytes; i++) {
bytes[i] = (byte)value;
value >>= 8;
}
return bytes;
}
}

View File

@ -0,0 +1,149 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.JesusFreke.dexlib.util;
import java.io.PrintStream;
import java.io.PrintWriter;
/**
* Exception which carries around structured context.
*/
public class ExceptionWithContext
extends RuntimeException {
/** non-null; human-oriented context of the exception */
private StringBuffer context;
/**
* Augments the given exception with the given context, and return the
* result. The result is either the given exception if it was an
* {@link ExceptionWithContext}, or a newly-constructed exception if it
* was not.
*
* @param ex non-null; the exception to augment
* @param str non-null; context to add
* @return non-null; an appropriate instance
*/
public static ExceptionWithContext withContext(Throwable ex, String str) {
ExceptionWithContext ewc;
if (ex instanceof ExceptionWithContext) {
ewc = (ExceptionWithContext) ex;
} else {
ewc = new ExceptionWithContext(ex);
}
ewc.addContext(str);
return ewc;
}
/**
* Constructs an instance.
*
* @param message human-oriented message
*/
public ExceptionWithContext(String message) {
this(message, null);
}
/**
* Constructs an instance.
*
* @param cause null-ok; exception that caused this one
*/
public ExceptionWithContext(Throwable cause) {
this(null, cause);
}
/**
* Constructs an instance.
*
* @param message human-oriented message
* @param cause null-ok; exception that caused this one
*/
public ExceptionWithContext(String message, Throwable cause) {
super((message != null) ? message :
(cause != null) ? cause.getMessage() : null,
cause);
if (cause instanceof ExceptionWithContext) {
String ctx = ((ExceptionWithContext) cause).context.toString();
context = new StringBuffer(ctx.length() + 200);
context.append(ctx);
} else {
context = new StringBuffer(200);
}
}
/** {@inheritDoc} */
@Override
public void printStackTrace(PrintStream out) {
super.printStackTrace(out);
out.println(context);
}
/** {@inheritDoc} */
@Override
public void printStackTrace(PrintWriter out) {
super.printStackTrace(out);
out.println(context);
}
/**
* Adds a line of context to this instance.
*
* @param str non-null; new context
*/
public void addContext(String str) {
if (str == null) {
throw new NullPointerException("str == null");
}
context.append(str);
if (!str.endsWith("\n")) {
context.append('\n');
}
}
/**
* Gets the context.
*
* @return non-null; the context
*/
public String getContext() {
return context.toString();
}
/**
* Prints the message and context.
*
* @param out non-null; where to print to
*/
public void printContext(PrintStream out) {
out.println(getMessage());
out.print(context);
}
/**
* Prints the message and context.
*
* @param out non-null; where to print to
*/
public void printContext(PrintWriter out) {
out.println(getMessage());
out.print(context);
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.JesusFreke.dexlib.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* File I/O utilities.
*/
public final class FileUtils {
/**
* This class is uninstantiable.
*/
private FileUtils() {
// This space intentionally left blank.
}
/**
* Reads the named file, translating {@link IOException} to a
* {@link RuntimeException} of some sort.
*
* @param fileName non-null; name of the file to read
* @return non-null; contents of the file
*/
public static byte[] readFile(String fileName) {
File file = new File(fileName);
return readFile(file);
}
/**
* Reads the given file, translating {@link IOException} to a
* {@link RuntimeException} of some sort.
*
* @param file non-null; the file to read
* @return non-null; contents of the file
*/
public static byte[] readFile(File file) {
if (!file.exists()) {
throw new RuntimeException(file + ": file not found");
}
if (!file.isFile()) {
throw new RuntimeException(file + ": not a file");
}
if (!file.canRead()) {
throw new RuntimeException(file + ": file not readable");
}
long longLength = file.length();
int length = (int) longLength;
if (length != longLength) {
throw new RuntimeException(file + ": file too long");
}
byte[] result = new byte[length];
try {
FileInputStream in = new FileInputStream(file);
int at = 0;
while (length > 0) {
int amt = in.read(result, at, length);
if (amt == -1) {
throw new RuntimeException(file + ": unexpected EOF");
}
at += amt;
length -= amt;
}
in.close();
} catch (IOException ex) {
throw new RuntimeException(file + ": trouble reading", ex);
}
return result;
}
}

View File

@ -0,0 +1,303 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.JesusFreke.dexlib.util;
/**
* Utilities for formatting numbers as hexadecimal.
*/
public final class Hex {
/**
* This class is uninstantiable.
*/
private Hex() {
// This space intentionally left blank.
}
/**
* Formats a <code>long</code> as an 8-byte unsigned hex value.
*
* @param v value to format
* @return non-null; formatted form
*/
public static String u8(long v) {
char[] result = new char[16];
for (int i = 0; i < 16; i++) {
result[15 - i] = Character.forDigit((int) v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an <code>int</code> as a 4-byte unsigned hex value.
*
* @param v value to format
* @return non-null; formatted form
*/
public static String u4(int v) {
char[] result = new char[8];
for (int i = 0; i < 8; i++) {
result[7 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an <code>int</code> as a 3-byte unsigned hex value.
*
* @param v value to format
* @return non-null; formatted form
*/
public static String u3(int v) {
char[] result = new char[6];
for (int i = 0; i < 6; i++) {
result[5 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an <code>int</code> as a 2-byte unsigned hex value.
*
* @param v value to format
* @return non-null; formatted form
*/
public static String u2(int v) {
char[] result = new char[4];
for (int i = 0; i < 4; i++) {
result[3 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an <code>int</code> as either a 2-byte unsigned hex value
* (if the value is small enough) or a 4-byte unsigned hex value (if
* not).
*
* @param v value to format
* @return non-null; formatted form
*/
public static String u2or4(int v) {
if (v == (char) v) {
return u2(v);
} else {
return u4(v);
}
}
/**
* Formats an <code>int</code> as a 1-byte unsigned hex value.
*
* @param v value to format
* @return non-null; formatted form
*/
public static String u1(int v) {
char[] result = new char[2];
for (int i = 0; i < 2; i++) {
result[1 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an <code>int</code> as a 4-bit unsigned hex nibble.
*
* @param v value to format
* @return non-null; formatted form
*/
public static String uNibble(int v) {
char[] result = new char[1];
result[0] = Character.forDigit(v & 0x0f, 16);
return new String(result);
}
/**
* Formats a <code>long</code> as an 8-byte signed hex value.
*
* @param v value to format
* @return non-null; formatted form
*/
public static String s8(long v) {
char[] result = new char[17];
if (v < 0) {
result[0] = '-';
v = -v;
} else {
result[0] = '+';
}
for (int i = 0; i < 16; i++) {
result[16 - i] = Character.forDigit((int) v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an <code>int</code> as a 4-byte signed hex value.
*
* @param v value to format
* @return non-null; formatted form
*/
public static String s4(int v) {
char[] result = new char[9];
if (v < 0) {
result[0] = '-';
v = -v;
} else {
result[0] = '+';
}
for (int i = 0; i < 8; i++) {
result[8 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an <code>int</code> as a 2-byte signed hex value.
*
* @param v value to format
* @return non-null; formatted form
*/
public static String s2(int v) {
char[] result = new char[5];
if (v < 0) {
result[0] = '-';
v = -v;
} else {
result[0] = '+';
}
for (int i = 0; i < 4; i++) {
result[4 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an <code>int</code> as a 1-byte signed hex value.
*
* @param v value to format
* @return non-null; formatted form
*/
public static String s1(int v) {
char[] result = new char[3];
if (v < 0) {
result[0] = '-';
v = -v;
} else {
result[0] = '+';
}
for (int i = 0; i < 2; i++) {
result[2 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats a hex dump of a portion of a <code>byte[]</code>. The result
* is always newline-terminated, unless the passed-in length was zero,
* in which case the result is always the empty string (<code>""</code>).
*
* @param arr non-null; array to format
* @param offset &gt;= 0; offset to the part to dump
* @param length &gt;= 0; number of bytes to dump
* @param outOffset &gt;= 0; first output offset to print
* @param bpl &gt;= 0; number of bytes of output per line
* @param addressLength {2,4,6,8}; number of characters for each address
* header
* @return non-null; a string of the dump
*/
public static String dump(byte[] arr, int offset, int length,
int outOffset, int bpl, int addressLength) {
int end = offset + length;
// twos-complement math trick: ((x < 0) || (y < 0)) <=> ((x|y) < 0)
if (((offset | length | end) < 0) || (end > arr.length)) {
throw new IndexOutOfBoundsException("arr.length " +
arr.length + "; " +
offset + "..!" + end);
}
if (outOffset < 0) {
throw new IllegalArgumentException("outOffset < 0");
}
if (length == 0) {
return "";
}
StringBuffer sb = new StringBuffer(length * 4 + 6);
boolean bol = true;
int col = 0;
while (length > 0) {
if (col == 0) {
String astr;
switch (addressLength) {
case 2: astr = Hex.u1(outOffset); break;
case 4: astr = Hex.u2(outOffset); break;
case 6: astr = Hex.u3(outOffset); break;
default: astr = Hex.u4(outOffset); break;
}
sb.append(astr);
sb.append(": ");
} else if ((col & 1) == 0) {
sb.append(' ');
}
sb.append(Hex.u1(arr[offset]));
outOffset++;
offset++;
col++;
if (col == bpl) {
sb.append('\n');
col = 0;
}
length--;
}
if (col != 0) {
sb.append('\n');
}
return sb.toString();
}
}

View File

@ -0,0 +1,149 @@
/*
* [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.util;
/**
* Interface for a source for binary input. This is similar to
* <code>java.util.DataInput</code>, but no <code>IOExceptions</code>
* are declared, and multibyte input is defined to be little-endian.
*/
public interface Input {
/**
* Gets the current cursor position. This is the same as the number of
* bytes read from this instance.
*
* @return &gt;= 0; the cursor position
*/
public int getCursor();
/**
* Sets the current cursor position.
*
* @return &gt;= 0; the cursor position
*/
public void setCursor(int cursor);
/**
* Asserts that the cursor is the given value.
*
* @param expectedCursor the expected cursor value
* @throws RuntimeException thrown if <code>getCursor() !=
* expectedCursor</code>
*/
public void assertCursor(int expectedCursor);
/**
* Reads a <code>byte</code> from this instance.
*
* @return the byte value that was read
*/
public byte readByte();
/**
* Reads a <code>short</code> from this instance.
*
* @return the short value that was read, as an int
*/
public int readShort();
/**
* Reads an <code>int</code> from this instance.
*
* @return the unsigned int value that was read
*/
public int readInt();
/**
* Reads a <code>long</code> from this instance.
*
* @return the long value that was read
*/
public long readLong();
/**
* Reads a DWARFv3-style signed LEB128 integer. For details,
* see the "Dalvik Executable Format" document or DWARF v3 section
* 7.6.
*
* @return the integer value that was read
*/
public int readSignedLeb128();
/**
* Reads a DWARFv3-style unsigned LEB128 integer. For details,
* see the "Dalvik Executable Format" document or DWARF v3 section
* 7.6.
*
* @return the integer value that was read
*/
public int readUnsignedLeb128();
/**
* reads a <code>byte[]</code> from this instance.
*
* @param bytes non-null; the buffer to read the data into
* @param offset &gt;= 0; offset into <code>bytes</code> for the first
* byte to write
* @param length &gt;= 0; number of bytes to read
*/
public void read(byte[] bytes, int offset, int length);
/**
* reads a <code>byte[]</code> from this instance. This is just
* a convenient shorthand for <code>read(bytes, 0, bytes.length)</code>.
*
* @param bytes non-null; the buffer to read the data into
*/
public void read(byte[] bytes);
/**
* reads a <code>byte[]</code> from this instance
*
* @param length &gt;= 0; number of bytes to read
* @return a byte array containing <code>length</code> bytes
*/
public byte[] readBytes(int length);
/**
* Skips the given number of bytes.
*
* @param count &gt;= 0; the number of bytes to skip
*/
public void skipBytes(int count);
/**
* Skip extra bytes if necessary to force alignment of the output
* cursor as given.
*
* @param alignment &gt; 0; the alignment; must be a power of two
*/
public void alignTo(int alignment);
}

View File

@ -0,0 +1,78 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.JesusFreke.dexlib.util;
/**
* LEB128 (little-endian base 128) utilities.
*/
public final class Leb128Utils {
/**
* This class is uninstantiable.
*/
private Leb128Utils() {
// This space intentionally left blank.
}
/**
* Gets the number of bytes in the unsigned LEB128 encoding of the
* given value.
*
* @param value the value in question
* @return its write size, in bytes
*/
public static int unsignedLeb128Size(int value) {
// TODO: This could be much cleverer.
int remaining = value >> 7;
int count = 0;
while (remaining != 0) {
value = remaining;
remaining >>= 7;
count++;
}
return count + 1;
}
/**
* Gets the number of bytes in the signed LEB128 encoding of the
* given value.
*
* @param value the value in question
* @return its write size, in bytes
*/
public static int signedLeb128Size(int value) {
// TODO: This could be much cleverer.
int remaining = value >> 7;
int count = 0;
boolean hasMore = true;
int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1;
while (hasMore) {
hasMore = (remaining != end)
|| ((remaining & 1) != ((value >> 6) & 1));
value = remaining;
remaining >>= 7;
count++;
}
return count;
}
}

View File

@ -0,0 +1,129 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.JesusFreke.dexlib.util;
/**
* Interface for a sink for binary output. This is similar to
* <code>java.util.DataOutput</code>, but no <code>IOExceptions</code>
* are declared, and multibyte output is defined to be little-endian.
*/
public interface Output {
/**
* Gets the current cursor position. This is the same as the number of
* bytes written to this instance.
*
* @return &gt;= 0; the cursor position
*/
public int getCursor();
/**
* Asserts that the cursor is the given value.
*
* @param expectedCursor the expected cursor value
* @throws RuntimeException thrown if <code>getCursor() !=
* expectedCursor</code>
*/
public void assertCursor(int expectedCursor);
/**
* Writes a <code>byte</code> to this instance.
*
* @param value the value to write; all but the low 8 bits are ignored
*/
public void writeByte(int value);
/**
* Writes a <code>short</code> to this instance.
*
* @param value the value to write; all but the low 16 bits are ignored
*/
public void writeShort(int value);
/**
* Writes an <code>int</code> to this instance.
*
* @param value the value to write
*/
public void writeInt(int value);
/**
* Writes a <code>long</code> to this instance.
*
* @param value the value to write
*/
public void writeLong(long value);
/**
* Writes a DWARFv3-style unsigned LEB128 integer. For details,
* see the "Dalvik Executable Format" document or DWARF v3 section
* 7.6.
*
* @param value value to write, treated as an unsigned value
* @return 1..5; the number of bytes actually written
*/
public int writeUnsignedLeb128(int value);
/**
* Writes a DWARFv3-style unsigned LEB128 integer. For details,
* see the "Dalvik Executable Format" document or DWARF v3 section
* 7.6.
*
* @param value value to write
* @return 1..5; the number of bytes actually written
*/
public int writeSignedLeb128(int value);
/**
* Writes a {@link ByteArray} to this instance.
*
* @param bytes non-null; the array to write
*/
public void write(ByteArray bytes);
/**
* Writes a portion of a <code>byte[]</code> to this instance.
*
* @param bytes non-null; the array to write
* @param offset &gt;= 0; offset into <code>bytes</code> for the first
* byte to write
* @param length &gt;= 0; number of bytes to write
*/
public void write(byte[] bytes, int offset, int length);
/**
* Writes a <code>byte[]</code> to this instance. This is just
* a convenient shorthand for <code>write(bytes, 0, bytes.length)</code>.
*
* @param bytes non-null; the array to write
*/
public void write(byte[] bytes);
/**
* Writes the given number of <code>0</code> bytes.
*
* @param count &gt;= 0; the number of zeroes to write
*/
public void writeZeroes(int count);
/**
* Adds extra bytes if necessary (with value <code>0</code>) to
* force alignment of the output cursor as given.
*
* @param alignment &gt; 0; the alignment; must be a power of two
*/
public void alignTo(int alignment);
}

View File

@ -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.util;
import org.JesusFreke.dexlib.EncodedValue.EncodedValueSubFieldFactory;
import org.JesusFreke.dexlib.EncodedValue.ValueType;
import org.JesusFreke.dexlib.EncodedValue.EncodedValueSubField;
import org.JesusFreke.dexlib.DexFile;
public class TypeUtils
{
public static EncodedValueSubField makeDefaultValueForType(DexFile dexFile, String type) {
switch (type.charAt(0)) {
case 'Z':
return EncodedValueSubFieldFactory.makeEncodedValueField(dexFile, ValueType.VALUE_BOOLEAN);
case 'B':
return EncodedValueSubFieldFactory.makeEncodedValueField(dexFile, ValueType.VALUE_BYTE);
case 'S':
return EncodedValueSubFieldFactory.makeEncodedValueField(dexFile, ValueType.VALUE_SHORT);
case 'C':
return EncodedValueSubFieldFactory.makeEncodedValueField(dexFile, ValueType.VALUE_CHAR);
case 'I':
return EncodedValueSubFieldFactory.makeEncodedValueField(dexFile, ValueType.VALUE_INT);
case 'J':
return EncodedValueSubFieldFactory.makeEncodedValueField(dexFile, ValueType.VALUE_LONG);
case 'F':
return EncodedValueSubFieldFactory.makeEncodedValueField(dexFile, ValueType.VALUE_FLOAT);
case 'D':
return EncodedValueSubFieldFactory.makeEncodedValueField(dexFile, ValueType.VALUE_DOUBLE);
case 'L':
case '[':
//TODO: is the default value for array types null or an empty array?
return EncodedValueSubFieldFactory.makeEncodedValueField(dexFile, ValueType.VALUE_NULL);
}
return null;
}
}

Some files were not shown because too many files have changed in this diff Show More