我目前正在构建一个 Java 反编译器。
为了辅助模式识别,我正在通过ANTLR构造一个简单的语法,并使用ANTLRWorks解释器进行调试。
以下是到目前为止的初步语法。在沿着这条路线前进时,我假设我能够将某些 JVM 字节码简化为下面的语法可以检测到的表达式。
您在这种方法中看到了哪些问题?6 月 29 日 2:36 GMT 1更新了 Ira 评论的语法
grammar JVM;
options {k=3;}
WS : (' '|'\r'|'\n'|'\t')+ {$channel=HIDDEN;}
;
INT : ('0'..'9')+ ;
UINT : ('_' INT)?;
IFEQ : 'ifeq';
IFGE : 'ifge';
IFGT : 'ifgt';
IFLE : 'ifle';
IFLT : 'iflt';
IFNE : 'ifne';
IFACMP_CONDTYPE : 'if_acmp' ('eq'|'ne'|'lt'|'ge'|'gt'|'le');
// THIS : 'aload_0';
LDC : 'ldc2_w'|'ldc_w'|'ldc';
LOADREFERENCE
// : THIS
: 'aload' UINT;
// | 'aload_2'
// | 'aload_3';
DLOAD : 'dload' UINT;
LOADINT : 'iload_0'
| 'iload_1'
| 'iload_2'
| 'iload_3'
;
DCONST : 'dconst' UINT;
ICONST : 'iconst' UINT;
goal : jvmStatement2+ ;
//fragment
//jvmStatement1
// : returnStatement
// | newArrayStatement
// | storeStatement
// | assignmentStatement
// | assertStatement
// | invokeStatement
// | ifStatement
// | gotoStatement
// ;
fragment // to test assert
jvmStatement2
: returnStatement // 2
| newArrayStatement // 3
| storeStatement // 4
| invokeStatement // 5
| assignmentStatement // 6
| assertStatement // 7
| ifStatement // 8
| gotoStatement
;
fragment
setAssertionStatus
: ifStatement pushIntegerConstant
gotoStatement pushIntegerConstant setStaticFieldInClass;
fragment
fetchFieldFromObject
: LOADREFERENCE 'getfield' INT;
fragment
loadDoubleFromLocalVariable
: DLOAD;
fragment
loadFloatFromLocalVariable
: 'fload' UINT;
fragment
loadIntFromLocalVariable
: LOADINT;
fragment
loadLongFromLocalVariable
: 'lload' UINT;
fragment
loadReferenceFromLocalVariable
: 'aload' UINT;
fragment
loadReferenceFromArray
: 'aaload';
fragment
storeReference
: storeIntoByteOrBooleanArray;
fragment
storeReferenceIntoLocalVariable
: 'astore' UINT;
fragment
storeDoubleIntoLocalVariable
: 'dstore' INT;
fragment
storeFloatIntoLocalVariable
: 'fstore' UINT;
fragment
storeIntIntoLocalVariable
: 'istore' (INT|UINT);
fragment
storeLongIntoLocalVariable
: 'lstore' UINT;
fragment
storeIntoByteOrBooleanArray
: 'bastore';
fragment
storeIntoReferenceArray
: 'aastore';
fragment
pushNull: 'aconst_null';
fragment
pushByte: 'bipush' INT;
fragment
pushIntegerConstant
: ICONST;
fragment
pushDoubleConstant
: DCONST;
fragment
pushLongConstant
: 'lconst' UINT;
fragment
pushFloatConstant
: 'fconst' UINT;
fragment
pushItemFromRuntimeConstantPool
: LDC INT;
fragment invokeStatementArgument: constantExpr
| createAnonymousClass;
fragment createAnonymousClass
: createNewObject dup thisInstance;
fragment invokeStatementArguments: invokeStatementArgument*;
fragment invokeStatement: getStaticField? invokeStatementArguments invokeMethod;
fragment
invokeMethod
: invokeInstanceMethod
| invokeVirtualMethod
| invokeStaticMethod
;
fragment
invokeInstanceMethod
: 'invokespecial' INT;
fragment
invokeVirtualMethod
: 'invokevirtual' INT;
fragment
invokeStaticMethod
: 'invokestatic' INT;
fragment
newArrayStatement
: 'newarray' simpleType;
fragment
setFieldInObject
: 'putfield' INT;
fragment setStaticFieldInClass
: 'putstatic' INT;
fragment
simpleType
: ('boolean'|'byte'|'char'|'double'|'float'|'int'|'long'|'short');
fragment
returnVoid
: 'return';
fragment
returnSimpleType
: returnReference
| returnDouble
| returnFloat
| returnInteger
| returnLong;
fragment
returnReference
: 'areturn';
fragment
returnDouble
: 'dreturn';
fragment returnFloat
: 'freturn';
fragment returnInteger
: 'ireturn';
fragment returnLong
: 'lreturn';
fragment
returnStatement
: returnVoid
| constantExpr returnSimpleType;
fragment
dupX1
: 'dup_x1';
fragment
dup
: 'dup';
fragment
storeStatement
: storeReferenceIntoLocalVariable
| storeIntIntoLocalVariable
| setStaticFieldInClass
| storeIntoReferenceArray
| setFieldInObject;
fragment
convertDouble
: convertDoubleToFloat | convertDoubleToInt | convertDoubleToLong;
fragment
convertDoubleToFloat
: 'd2f';
fragment
convertDoubleToInt
: 'd2i';
fragment
convertDoubleToLong
: 'd2l';
fragment
convertFloat
: convertFloatToDouble|convertFloatToInt|convertFloatToLong;
fragment
convertFloatToDouble
: 'f2d';
fragment
convertFloatToInt
: 'f2i';
fragment
convertFloatToLong
: 'f2l';
fragment
convertInt
: convertIntToByte
|convertIntToChar
|convertIntToDouble
|convertIntToFloat
|convertIntToLong
|convertIntToShort;
fragment
convertIntToByte
: 'i2b';
fragment
convertIntToChar
: 'i2c';
fragment
convertIntToDouble
: 'i2d';
fragment
convertIntToFloat
: 'i2f';
fragment
convertIntToLong
: 'i2l';
fragment
convertIntToShort
: 'i2s';
fragment
branchComparison
:branchIfReferenceComparison
|branchIfIntComparison
|branchIfIntComparisonWithZero
|branchIfReferenceNotNull
|branchIfReferenceNull;
fragment
branchIfReferenceComparison
: 'if_acmp' condType;
fragment
branchIfIntComparison
: 'if_icmp' condType INT;
fragment
branchIfIntComparisonWithZero
: (IFEQ|IFGE|IFGT|IFLE|IFLT|IFNE) INT;
fragment
gotoStatement
: 'goto' INT;
fragment
ifStatementCompare
: (IFEQ INT)
| (IFNE INT);
fragment
ifStatement
: booleanExpression ifStatementCompare;
fragment
ifType : 'ifeq'
|'ifne'
|'iflt'
|'ifge'
|'ifgt'
|'ifle';
fragment
branchIfReferenceNotNull
: 'ifnonnull' ;
fragment
branchIfReferenceNull
: 'ifnull';
fragment
condType: 'eq'
|'ne'
|'lt'
|'ge'
|'gt'
|'le';
fragment
checkCast
: 'checkcast' INT;
fragment
createNewArrayOfReference
: constantExpr 'anewarray' INT;
fragment
createNewObject
: 'new' INT;
fragment
assignmentStatement
// : pushItemFromRuntimeConstantPool storeStatement
: (constantExpr)+ storeStatement
| invokeInheritedConstructor
| expressionStatement
// | setAssertionStatus
;
fragment
invokeInheritedConstructor
: loadReferenceFromLocalVariable invokeInstanceMethod;
fragment
throwExceptionOrError
: 'athrow';
fragment
getStaticField
: 'getstatic' INT;
fragment
newInstance
: 'new' INT;
fragment // this needs to be extended to recognize more patterns
booleanExpression
: integerComparison
| loadIntFromLocalVariable
| invokeMethod;
fragment
integerComparison
: loadIntFromLocalVariable loadIntFromLocalVariable branchIfIntComparison;
fragment assertIfAssertEnabled: getStaticField branchIfIntComparisonWithZero;
fragment assertCondition:booleanExpression branchIfIntComparisonWithZero;
fragment assertThrow:createNewObject dup assertMessage throwExceptionOrError;
fragment assertMessage:pushItemFromRuntimeConstantPool invokeMethod;
fragment assertStatement:assertIfAssertEnabled assertCondition assertThrow;
fragment
stringPlusNumber
:pushItemFromRuntimeConstantPool invokeMethod
loadReferenceFromLocalVariable invokeMethod invokeMethod invokeMethod;
fragment expressionStatement: statementExpression;
fragment
statementExpression
: preIncrementExpression
| preDecrementExpression
// | postIncrementExpression
// | postDecrementExpression
| newByteArray
| ternaryExpression
| createAndStoreObject // assignment expression
| createNewArrayStatement
| fetchFieldFromObject
;
fragment
createNewArrayStatement // with elements
: createNewArrayOfReference createNewArrayInitElement+;
createNewArrayInitElement
: (dup constantExpr getStaticField storeStatement);
fragment
createAndStoreObject
: createNewObject dup invokeStatement storeStatement;
fragment ternaryExpression // doesn't cover all situations yet
: loadIntFromLocalVariable ifStatementCompare loadIntFromLocalVariable gotoStatement
loadIntFromLocalVariable storeStatement;
fragment preIncrementExpression: preIncrementInteger;
fragment preDecrementExpression: preDecrementFloat|preDecrementLong|preDecrementDouble;
fragment doubleExpression: pushDoubleConstant;
fragment integerExpression: pushIntegerConstant;
fragment longExpression: pushLongConstant;
fragment floatExpression: pushFloatConstant;
fragment preIncrementInteger: loadReferenceFromLocalVariable dup fetchFieldFromObject integerExpression
iAdd dupX1? setFieldInObject;
fragment preDecrementDouble: loadDoubleFromLocalVariable doubleExpression dSub storeDoubleIntoLocalVariable;
fragment preDecrementLong: loadLongFromLocalVariable longExpression lSub storeLongIntoLocalVariable;
fragment preDecrementFloat: loadFloatFromLocalVariable floatExpression fSub storeFloatIntoLocalVariable;
fragment newByteArray: newByteArrayWithNull|newByteArrayWithData;
// byte[] b = {'c', 'h', 'u', 'a'};
fragment newByteArrayWithData: constantExpr newArrayStatement byteArrayElements;
fragment byteArrayElements: constantExpr constantExpr storeIntoByteOrBooleanArray;
fragment constantExpr:
//loadReferenceFromLocalVariable
LOADREFERENCE
|loadDoubleFromLocalVariable
|loadFloatFromLocalVariable
|loadIntFromLocalVariable
|loadLongFromLocalVariable
|pushByte
|pushDoubleConstant
|pushFloatConstant
|pushIntegerConstant
|pushItemFromRuntimeConstantPool
|pushLongConstant
|pushNull
|fetchFieldFromObject
;
// byte[] c = null;
// String s = null;
fragment newByteArrayWithNull: pushNull (checkCast)? storeReference;
fragment thisInstance: LOADREFERENCE invokeMethod;
fragment ternaryOperator
: ifStatementCompare pushIntegerConstant gotoStatement pushIntegerConstant setStaticFieldInClass;
fragment floatMultiply
: constantExpr constantExpr dMul;
fragment iAdd: 'iadd';
fragment dSub: 'dsub';
fragment fSub: 'fsub';
fragment lSub: 'lsub';
fragment lAdd: 'ladd';
fragment dMul: 'dmul';
例如,当前的语法(上述的进一步演变)可以转向
getstatic 25
ifne 25
iload_1
iload_2
if_icmpgt 25
new 25
dup
invokespecial 44
athrow
return
进入