Initial revision

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@360 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 77f2fbe9d7
commit 633f044a20
  1. 11
      jode/doc/jode.texi
  2. 200
      jode/doc/technical.texi
  3. 288
      jode/jode/type/IntegerType.java
  4. 58
      jode/jode/type/NullType.java

@ -0,0 +1,11 @@
\input texinfo @c -*- texinfo -*-
@setfilename jode.info
@settitle Jode, a Java Decompiler
@direntry
* Jode: (jode). A Java Decompiler
@end direntry
@include technical.texi
@bye

@ -0,0 +1,200 @@
@node Technical Info, Top, Top, Top
@chapter Technical Information
This chapter contains information, how the decompiler works.
@menu
* Types::
* Expression analysis::
* Flow analysis::
* Solving unknown stack-ops::
* Highlevel analysis::
@end menu
@node Types, Expression analysis, Technical Info, Technical Info
@section Type checking and guessing
@cindex Types, Conversions
The type class has the following operators:
getSubType
getSuperType
intersection
(getCastHelper?)
(getImplicitCast?)
reference types (classes, interfaces, arrays and null type) often appear
in ranges. They have the methods:
createRangeType
getSpecializedType
getGeneralizedType
The meaning is
ref1.intersection(ref2) =
ref1.getSpecializedType(ref2).createRangeType(ref1.getGeneralizedType(ref2))
<Object - NULL>
<Object[] - NULL>
<Object[] - Serialized[]>
<tUnknown[]>
<Object - tUnknown[]>
{IBCS}[] intersect {CSZ}[] = {CS}[]
<Object - {ICSB}[]> intersect <Serializable - {CSZ}[]>
--> <Serializable - {
The byte code distinguishes five different types:
@enumerate
@item 16 bit integral types (boolean, byte, short, char and int)
@item long
@item float
@item double
@item reference types (objects, interfaces, arrays, null type)
@end enumerate
It sometimes makes a difference between byte, short, char and int, but
not always.
16bit integral types:
We differ seven different 16 bit integral types:
@table @asis
@item I
@code{int} type
@item C
@code{char} type
@item S
@code{short} type
@item B
@code{byte} type
@item Z
@code{boolean} type
@item cS
An @code{int} constant whose value is in @code{short} range.
@item cB
An @code{int} constant whose value is in @code{byte} range.
@end table
Each of this types has a super range and a sub range:
@multitable {type} {(I,C,S,B,Z,cS,cB)} {(I,C,S,B,Z,cS,cB)}
@item type @tab sub types @tab super types
@item I @tab (I,C,S,B,cS,cB) @tab (I)
@item C @tab (C) @tab (I,C)
@item S @tab (S,B,cS,cB) @tab (I,S)
@item B @tab (B,cB) @tab (I,S,B)
@item Z @tab (Z) @tab (Z)
@item cS @tab (cS,cB) @tab (I,S,cS)
@item cB @tab (cB) @tab (I,S,B,cS,cB)
@end multitable
getTop() getBottom() give the type directly.
createRangeType(Type bottom) does the following:
If top == tUnknown , union all supertypes
If top is 16bit type,
intersect (union of subtypes of top) (union of supertypes)
Return tError otherwise.
Type.createRangeType(Type top) does the following:
if Type == tUnknown
if top is IntegerType
new IntegerType(union of subtypes of top)
Hints. We distinguish strong and weak Hints:
strong Hints:
assignment:
lhs.strongHint = mergeHint(lhs.strongHint, rhs.strongHint)
lhs.weakHint = mergeHint(lhs.weakHint, rhs.weakHint)
rhs.strongHint = lhs.strongHint
binary op:
left.weakHint = mergeHints(left.weakHint, right.strongHint?strongHint: weakHint)
binary op
types that may occur directly in bytecode:
(I,Z)
(I)
(Z)
(I,C,S,B,Z)
(I,cS,cB)
(I,cS)
(I,C,cS,cB)
(I,C,cS)
(I,C)
(C)
(S)
(B)
(B,Z)
now the sub (>) and super (<) operators
>(I,Z) = (I,C,S,B,Z,cS,cB) New!
>(I) = (I,C,S,B,cS,cB) New!
>(Z) = (Z)
>(I,C,S,B,Z) = (I,C,S,B,Z,cS,cB)
>(I,cS,cB) = (I,C,S,B,cS,cB)
>(I,cS) = (I,C,S,B,cS,cB)
>(I,C,cS,cB) = (I,C,S,B,cS,cB)
>(I,C,cS) = (I,C,S,B,cS,cB)
>(I,C) = (I,C,S,B,cS,cB)
>(C) = (C)
>(S) = (S,B,cS,cB) New!
>(B) = (B,cB) New!
>(B,Z) = (B,Z,cB) New!
<(I,Z) = (I,Z)
<(I) = (I)
<(Z) = (Z)
<(I,C,S,B,Z) = (I,C,S,B,Z)
<(I,cS,cB) = (I,S,B,cS,cB) New!
<(I,cS) = (I,S,cS) New!
<(I,C,cS,cB) = (I,C,S,B,cS,cB)
<(I,C,cS) = (I,C,S,cS) New!
<(I,C) = (I,C)
<(C) = (I,C)
<(S) = (I,S) New!
<(B) = (I,S,B) New!
<(B,Z) = (I,S,B,Z) New!
>(I,C,S,B,Z,cS,cB) = (I,C,S,B,Z,cS,cB)
>(I,C,S,B,cS,cB) = (I,C,S,B,cS,cB)
>(B,Z,cB) = (B,Z,cB)
>(I,C,S,cS) = (I,C,S,B,cS,cB)
>(I,S,B,Z) = (I,C,S,B,Z,cS,cB)
>(I,S,B,cS,cB) = (I,C,S,B,cS,cB)
<(I,C,S,B,Z,cS,cB) = (I,C,S,B,Z,cS,cB)
<(I,C,S,B,cS,cB) = (I,C,S,B,cS,cB)
<(B,Z,cB) = (I,S,B,Z,cS,cB)
<(I,C,S,cS) = (I,C,S,cS)
<(I,S,B,Z) = (I,S,B,Z)
<(I,S,B,cS,cB) = (I,S,B,cS,cB)
Zu betrachtende 32bit Typen:
(I,Z) = (I,Z)
(I) = (I)
(Z) = (Z)
(I,C,S,B,Z)
(I,cS,cB)
(I,cS)
(I,C,cS,cB)
(I,C,cS)
(I,C)
(B,Z)
(I,C,S,B,Z,cS,cB)
(I,C,S,B,cS,cB)
(B,Z,cB)
(I,C,S,cS)
(I,S,B,Z)
(I,S,B,cS,cB)

@ -0,0 +1,288 @@
/*
* IntegerType (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode;
/**
* This is a type class for 16 bit integral types. There are seven
* different types, namely <code>int, char, short, byte, boolean,
* const short, const byte</code> abbreviated <code>I, C, S, B, Z, cS,
* cB</code>. <code>cB</code> and <code>cS</code> specify constant
* ints whose value is in byte resp. short range. They may be
* converted to B resp. S, but sometimes need an explicit cast.
*
* @author Jochen Hoenicke */
public class IntegerType extends Type {
public static final int IT_I = 0x01;
public static final int IT_C = 0x02;
public static final int IT_S = 0x04;
public static final int IT_B = 0x08;
public static final int IT_Z = 0x10;
public static final int IT_cS = 0x20;
public static final int IT_cB = 0x40;
private static final int NUM_TYPES = 7;
private static final int[] subTypes = {
/*I*/ IT_I|IT_C|IT_S|IT_B/*|IT_cS|IT_cB*/, /*C*/ IT_C,
/*S*/ IT_S|IT_B/*|IT_cS|IT_cB*/, /*B*/ IT_B/*|IT_cB*/,
/*Z*/ IT_Z,
/*cS*/IT_cS|IT_cB, /*cB*/IT_cB
};
private static final int[] superTypes = {
/*I*/ IT_I, /*C*/ IT_I|IT_C,
/*S*/ IT_I|IT_S, /*B*/ IT_I|IT_S|IT_B,
/*Z*/ IT_Z,
/*cS*/IT_I|IT_C|IT_S|IT_cS, /*cB*/IT_I|IT_C|IT_S|IT_B|IT_cS|IT_cB
};
private static final Type[] simpleTypes = {
new IntegerType(IT_I), new IntegerType(IT_C),
new IntegerType(IT_S), new IntegerType(IT_B),
new IntegerType(IT_Z),
new IntegerType(IT_cS), new IntegerType(IT_cB)
};
private static final String[] typeNames = {
"I","C","S","B","Z","cS","cB"
};
int possTypes;
int strongHint = 0;
int weakHint = 0;
/**
* Create a new type with the given type.
*/
public IntegerType(int types) {
super(TC_INTEGER);
possTypes = types;
}
public Type getHint() {
int hint = ((possTypes & IT_Z) != 0 ? IT_Z
: strongHint != 0 ? strongHint
: weakHint != 0 ? weakHint
: possTypes);
int i = 0;
for (int it = 0x1; (it & hint) == 0; it <<= 1)
i++;
return simpleTypes[i];
}
private int getSubTypes() {
int result = 0;
for (int i=0; i < NUM_TYPES; i++) {
if (((1<<i) & possTypes) != 0)
result |= subTypes[i];
}
return result;
}
private int getSuperTypes() {
int result = 0;
for (int i=0; i < NUM_TYPES; i++) {
if (((1<<i) & possTypes) != 0)
result |= superTypes[i];
}
return result;
}
public Type getSubType() {
return new IntegerType(getSubTypes());
}
public Type getSuperType() {
return new IntegerType(getSuperTypes());
}
// /**
// * Returns the common sub type of this and type.
// * @param type the other type.
// * @return the common sub type.
// */
// public Type getSpecializedType(Type type) {
// /* tError , x -> tError
// * x , tUnknown -> x
// * Integer , Integer -> possTypes1 & possTypes2 == 0 ? tError
// */
// if (type == tUnknown)
// return this;
// if (type.typecode != TC_INTEGER)
// return tError;
// IntegerType other = (IntegerType) type;
// int mergeTypes = possTypes & other.possTypes;
// /* HINTING XXX */
// if (mergeTypes == possTypes)
// return this;
// if (mergeTypes == other.possTypes)
// return other;
// if (mergeTypes == 0)
// return tError;
// return new IntegerType(mergeTypes);
// }
// /**
// * Returns the common super type of this and type.
// * @param type the other type.
// * @return the common super type.
// */
// public Type getGeneralizedType(Type type) {
// return getSpecializedType(type);
// }
// /**
// * Create the type corresponding to the range from bottomType to this.
// * @param bottomType the start point of the range
// * @return the range type, or tError if not possible.
// */
// public Type intersection(Type bottomType) {
// /* Note that this can't be tBoolByte or tBoolInt */
// /* x , tError -> tError
// * object , tUnknown -> <object, tUnknown>
// * boolean , tUnknown -> boolean
// * int , tUnknown -> <int, byte>
// * boolint , tUnknown -> boolint
// * tUnknown, x -> getSuperTypes(x)
// * tUnknown, short -> <int, short>
// * short , byte -> <short, byte>
// * byte , short -> tError
// * tUnknown, float -> float
// */
// if (bottomType == tUnknown)
// return this;
// else if (bottomType.typecode != TC_INTEGER)
// return tError;
// /*XXX HINTING*/
// int result = ((IntegerType)bottomType).possTypes & possTypes;
// return new IntegerType(result);
// }
/**
* Checks if this type represents a valid type instead of a list
* of minimum types.
*/
public boolean isValidType() {
return true;
}
/**
* Check if this and &lt;unknown -- type&rt; are not disjunct.
* @param type a simple type; this mustn't be a range type.
* @return true if this is the case.
*/
public boolean isOfType(Type type) {
return (type.typecode == TC_INTEGER
&& (((IntegerType)type).possTypes & possTypes) != 0);
}
public String getDefaultName() {
switch (((IntegerType)getHint()).possTypes) {
case IT_Z:
return "bool";
case IT_C:
return "c";
case IT_B:
case IT_S:
case IT_I:
return "i";
default:
throw new jode.AssertError("Local can't be of constant type!");
}
}
public String getTypeSignature() {
switch (((IntegerType)getHint()).possTypes) {
case IT_Z:
return "Z";
case IT_C:
return "C";
case IT_B:
return "B";
case IT_S:
return "S";
case IT_I:
default:
return "I";
}
}
public String toString() {
switch (possTypes) {
case IT_Z:
return "boolean";
case IT_C:
return "char";
case IT_B:
return "byte";
case IT_S:
return "short";
case IT_I:
return "int";
default:
StringBuffer sb = new StringBuffer("{");
String comma = "";
for (int i=0; i< NUM_TYPES; i++)
if (((1<<i) & possTypes) != 0) {
sb.append(comma).append(typeNames[i]);
comma = ",";
}
sb.append("}");
return sb.toString();
}
}
/**
* Intersect this type with another type and return the new type.
* @param type the other type.
* @return the intersection, or tError, if a type conflict happens.
*/
public Type intersection(Type type) {
if (type == tError)
return type;
if (type == tUnknown)
return this;
int mergeTypes;
if (type.typecode != TC_INTEGER)
mergeTypes = 0;
else {
IntegerType other = (IntegerType) type;
mergeTypes = possTypes & other.possTypes;
/* HINTING XXX */
if (mergeTypes == possTypes)
return this;
if (mergeTypes == other.possTypes)
return other;
}
Type result = mergeTypes == 0 ? tError : new IntegerType(mergeTypes);
if (Decompiler.isTypeDebugging || result == tError) {
Decompiler.err.println("intersecting "+ this +" and "+ type +
" to " + result);
}
return result;
}
public boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof IntegerType)
return ((IntegerType)o).possTypes == possTypes;
return false;
}
}

@ -0,0 +1,58 @@
package jode;
public class NullType extends ClassInterfacesType {
public NullType() {
super(null, null);
typecode = TC_NULL;
}
public Type createRangeType(ClassInterfacesType bottomType) {
return tRange(bottomType, this);
}
/**
* Returns the generalized type of this and type. We have two
* classes and multiple interfaces. The result should be the
* object that is the the super class of both objects and all
* interfaces, that one class or interface of each type
* implements. */
public Type getGeneralizedType(Type type) {
if (type.typecode == TC_RANGE)
type = ((RangeType) type).getTop();
return type;
}
/**
* Returns the specialized type of this and type.
* We have two classes and multiple interfaces. The result
* should be the object that extends both objects
* and the union of all interfaces.
*/
public Type getSpecializedType(Type type) {
if (type.typecode == TC_RANGE)
type = ((RangeType) type).getBottom();
return type;
}
/**
* Marks this type as used, so that the class is imported.
*/
public void useType() {
}
public String toString() {
return "/*NULL*/" + env.classString("java.lang.Object");
}
public boolean equals(Object o) {
return o == this;
}
/**
* Intersect this type with another type and return the new type.
* @param type the other type.
* @return the intersection, or tError, if a type conflict happens.
*/
public Type intersection(Type type) {
throw new AssertError("NULL.intersection");
}
}
Loading…
Cancel
Save