Skip to content

Commit

Permalink
support dex 039 and 040
Browse files Browse the repository at this point in the history
  • Loading branch information
pxb1988 committed Aug 31, 2023
1 parent 8363e21 commit 17f162e
Show file tree
Hide file tree
Showing 23 changed files with 227 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ fragment
FRAGMENT_ARRAY_TYPE: ('[')+ (FRAGMENT_PRIMITIVE_TYPE|FRAGMENT_OBJECT_TYPE);

fragment
FRAGMENT_ID: (ESC_SEQ| ~('\\'|'\r'|'\n'|'\t'|' '|':'|'-'|'='|','|'{'|'}'|'('|')'|'+'|'\"'|'\''|'#'|'/'|'.'|';'))+;
FRAGMENT_ID: (ESC_SEQ| ~('\\'|'\r'|'\n'|'\t'|' '|':'|'-'|'='|','|'{'|'}'|'('|')'|'+'|'\"'|'\''|'#'|'/'|'.'|';'|'@'))+;
fragment
FRAGMENT_METHOD_PROTO: '(' (FRAGMENT_OBJECT_TYPE|FRAGMENT_ARRAY_TYPE|FRAGMENT_PRIMITIVE_TYPE)* ')' ('V' | FRAGMENT_OBJECT_TYPE|FRAGMENT_ARRAY_TYPE|FRAGMENT_PRIMITIVE_TYPE)
;
Expand Down Expand Up @@ -175,8 +175,7 @@ sAnnotationValue
:sSubannotation
|sBaseValue
|sArrayValue
| ( '.iget' | '.iput' | '.sget' | '.sput' ) FIELD_FULL
| ( '.invoke-instance' | '.invoke-static' ) METHOD_FULL
| method_handler
;// field,method,array,subannotation
sBaseValue
:STRING
Expand All @@ -194,6 +193,10 @@ sBaseValue
;
sArrayValue: '{' sAnnotationValue? (',' sAnnotationValue)* '}';

method_handler
: type=('static-get'|'static-put'|'instance-get'|'instance-put') '@' fld=FIELD_FULL
| type=('invoke-static'|'invoke-instance'|'invoke-direct'|'invoke-interface'|'invoke-constructor') '@' mtd=METHOD_FULL
;

sInstruction
:fline
Expand Down Expand Up @@ -269,6 +272,8 @@ fconst
r1=REGISTER ',' cst=(INT|LONG)
| op=('const-string'|'const-string/jumbo') r1=REGISTER ',' cst=STRING
| op=('const-class'|'check-cast'|'new-instance') r1=REGISTER ',' cst=(OBJECT_TYPE|ARRAY_TYPE)
| op='const-method-type' r1=REGISTER ',' cst=METHOD_PROTO
| op='const-method-handle' r1=REGISTER ',' h=method_handler
;
ff1c : op=(SGET
|'sget-wide'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,42 @@ public Object visitFconst(SmaliParser.FconstContext ctx) {
scv.visitConstStmt(op, r, v);
}
break;
case CONST_METHOD_HANDLE:
switch (ctx.h.type.getText()) {
case "static-get":
scv.visitConstStmt(op, r, new MethodHandle(MethodHandle.STATIC_GET, parseFieldAndUnescape(ctx.h.fld.getText())));
break;
case "static-put":
scv.visitConstStmt(op, r, new MethodHandle(MethodHandle.STATIC_PUT, parseFieldAndUnescape(ctx.h.fld.getText())));
break;
case "instance-get":
scv.visitConstStmt(op, r, new MethodHandle(MethodHandle.INSTANCE_GET, parseFieldAndUnescape(ctx.h.fld.getText())));
break;
case "instance-put":
scv.visitConstStmt(op, r, new MethodHandle(MethodHandle.INSTANCE_PUT, parseFieldAndUnescape(ctx.h.fld.getText())));
break;
case "invoke-static":
scv.visitConstStmt(op, r, new MethodHandle(MethodHandle.INVOKE_STATIC, parseMethodAndUnescape(ctx.h.mtd.getText())));
break;
case "invoke-instance":
scv.visitConstStmt(op, r, new MethodHandle(MethodHandle.INVOKE_INSTANCE, parseMethodAndUnescape(ctx.h.mtd.getText())));
break;
case "invoke-direct":
scv.visitConstStmt(op, r, new MethodHandle(MethodHandle.INVOKE_DIRECT, parseMethodAndUnescape(ctx.h.mtd.getText())));
break;
case "invoke-interface":
scv.visitConstStmt(op, r, new MethodHandle(MethodHandle.INVOKE_INTERFACE, parseMethodAndUnescape(ctx.h.mtd.getText())));
break;
case "invoke-constructor":
scv.visitConstStmt(op, r, new MethodHandle(MethodHandle.INVOKE_CONSTRUCTOR, parseMethodAndUnescape(ctx.h.mtd.getText())));
break;
default:
throw new RuntimeException("not support yet: " + ctx.h.type);
}
break;
case CONST_METHOD_TYPE:
scv.visitConstStmt(op, r, parseProtoAndUnescape(ctx.cst.getText()));
break;
default:
throw new RuntimeException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,24 +278,24 @@ static String escapeValue(Object obj) {
private static String escapeMethodHandle(MethodHandle obj) {
switch (obj.getType()) {
case MethodHandle.INSTANCE_GET:
return ".iget " + escapeField(obj.getField());
return "instance-get@" + escapeField(obj.getField());
case MethodHandle.INSTANCE_PUT:
return ".iput " + escapeField(obj.getField());
return "instance-put@" + escapeField(obj.getField());
case MethodHandle.STATIC_GET:
return ".sget " + escapeField(obj.getField());
return "static-get@" + escapeField(obj.getField());
case MethodHandle.STATIC_PUT:
return ".sput " + escapeField(obj.getField());
return "static-put@" + escapeField(obj.getField());

case MethodHandle.INVOKE_INSTANCE:
return ".invoke-instance " + escapeMethod(obj.getMethod());
return "invoke-instance@" + escapeMethod(obj.getMethod());
case MethodHandle.INVOKE_STATIC:
return ".invoke-static " + escapeMethod(obj.getMethod());
return "invoke-static@" + escapeMethod(obj.getMethod());
case MethodHandle.INVOKE_CONSTRUCTOR:
return ".invoke-constructor " + escapeMethod(obj.getMethod());
return "invoke-constructor@" + escapeMethod(obj.getMethod());
case MethodHandle.INVOKE_DIRECT:
return ".invoke-direct " + escapeMethod(obj.getMethod());
return "invoke-direct@" + escapeMethod(obj.getMethod());
case MethodHandle.INVOKE_INTERFACE:
return ".invoke-interface " + escapeMethod(obj.getMethod());
return "invoke-interface@" + escapeMethod(obj.getMethod());
default:
}
return "?";
Expand Down
22 changes: 15 additions & 7 deletions d2j-smali/src/main/java/com/googlecode/d2j/smali/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.googlecode.d2j.DexConstants;
import com.googlecode.d2j.Field;
import com.googlecode.d2j.Method;
import com.googlecode.d2j.Proto;
import com.googlecode.d2j.Visibility;
import com.googlecode.d2j.reader.Op;
import com.googlecode.d2j.visitors.DexAnnotationVisitor;
Expand Down Expand Up @@ -477,23 +478,30 @@ public static int reg2ParamIdx(Method m, int reg, int locals, boolean isStatic)
return -1;
}

public static Method parseMethodAndUnescape(String owner, String part) throws RuntimeException {
int x = part.indexOf('(');
if (x < 0) {
throw new RuntimeException();
}
public static Proto parseProtoAndUnescape(String part) throws RuntimeException {
int x = 0;
int y = part.indexOf(')', x);
if (y < 0) {
throw new RuntimeException();
}

String methodName = unEscapeId(part.substring(0, x));
String[] params = toTypeList(part.substring(x + 1, y));
for (int i = 0; i < params.length; i++) {
params[i] = unEscapeId(params[i]);
}
String ret = unEscapeId(part.substring(y + 1));
return new Method(owner, methodName, params, ret);
return new Proto(params, ret);
}

public static Method parseMethodAndUnescape(String owner, String part) throws RuntimeException {
int x = part.indexOf('(');
if (x < 0) {
throw new RuntimeException();
}

String methodName = unEscapeId(part.substring(0, x));

return new Method(owner, methodName, parseProtoAndUnescape(part.substring(x)));
}

public static Method parseMethodAndUnescape(String full) throws RuntimeException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,12 @@ public static Constant nShort(short i) {
public static Constant nString(String i) {
return new Constant(i);
}

public static Constant nMethodHandle(MethodHandle i) {
return new Constant(i);
}
public static Constant nProto(Proto i) {
return new Constant(i);
}
public static BinopExpr nAdd(Value a, Value b, String type) {
return new BinopExpr(VT.ADD, a, b, type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public void execute(DexStmtNode insn, DvmInterpreter<V> interpreter) {
case CONST_STRING:
case CONST_STRING_JUMBO:
case CONST_CLASS:
case CONST_METHOD_HANDLE:
case CONST_METHOD_TYPE:
setReg(((ConstStmtNode) insn).a, interpreter.newOperation(insn));
setTmp(null);
break;
Expand Down Expand Up @@ -378,7 +380,7 @@ public void execute(DexStmtNode insn, DvmInterpreter<V> interpreter) {
setTmp(null);
break;
default:
throw new RuntimeException();
throw new RuntimeException("not support " + insn.op);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@
kIndexFieldOffset, // field offset (for static linked fields)
kIndexMethodAndProtoRef, // 038,
kIndexCallSiteRef, // 038,
kIndexMethodHandleRef, // 039, constant method handle reference index
kIndexProtoRef, // 039, prototype reference index
};
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ public enum Op implements CFG {
| kInstrInvoke, true), //
INVOKE_CUSTOM_RANGE(0xfd, "invoke-custom/range", kFmt3rc, kIndexCallSiteRef, kInstrCanContinue | kInstrCanThrow
| kInstrInvoke, true), //
CONST_METHOD_HANDLE(0xfe, "const-method-handle", kFmt21c, kIndexMethodHandleRef, kInstrCanContinue | kInstrCanThrow
, true), //
CONST_METHOD_TYPE(0xff, "const-method-type", kFmt21c, kIndexProtoRef, kInstrCanContinue | kInstrCanThrow
, true), //
BAD_OP(-1, "bad-opcode", null, kIndexNone, 0, false), //
;
public int opcode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,23 @@ public void visitTypeStmt(Op op, int a, int b, String type) {
}

/**
* <pre>
* CONST * CONST_WIDE * CONST_STRING * CONST_CLASS *
* </pre>
*
* @param op
* @param ra
* @see Op#CONST
* @see Op#CONST_4
* @see Op#CONST_16
* @see Op#CONST_HIGH16
* @see Op#CONST_WIDE
* @see Op#CONST_WIDE_16
* @see Op#CONST_WIDE_32
* @see Op#CONST_WIDE_HIGH16
* @see Op#CONST_STRING
* @see Op#CONST_STRING_JUMBO
* @see Op#CONST_CLASS
* @see Op#CONST_METHOD_HANDLE
* @see Op#CONST_METHOD_TYPE
* @param op CONST*
* @param ra register
* @param value
* int/long/type
* Integer,Long,DexType,MethodHandle,Proto
*/
public void visitConstStmt(Op op, int ra, Object value) {
if (visitor != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1589,6 +1589,12 @@ private void acceptInsn(byte[] insns, DexCodeVisitor dcv, BitSet nextInsn, BitSe
dcv.visitTypeStmt(op, a, -1, getType(b));
}
break;
case kIndexMethodHandleRef:
dcv.visitConstStmt(op, a, getMethodHandle(b));
break;
case kIndexProtoRef:
dcv.visitConstStmt(op, a, getProto(b));
break;
default:
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.googlecode.d2j.DexType;
import com.googlecode.d2j.Field;
import com.googlecode.d2j.Method;
import com.googlecode.d2j.MethodHandle;
import com.googlecode.d2j.Proto;
import com.googlecode.d2j.node.DexCodeNode;
import com.googlecode.d2j.node.TryCatchNode;
import com.googlecode.d2j.node.analysis.DvmFrame;
Expand Down Expand Up @@ -560,6 +562,10 @@ public DvmValue newOperation(DexStmtNode insn) {
case CONST_STRING:
case CONST_STRING_JUMBO:
return b(nString((String) ((ConstStmtNode) insn).value));
case CONST_METHOD_HANDLE:
return b(nMethodHandle((MethodHandle) ((ConstStmtNode) insn).value));
case CONST_METHOD_TYPE:
return b(nProto((Proto) ((ConstStmtNode) insn).value));
case SGET:
case SGET_BOOLEAN:
case SGET_BYTE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.googlecode.d2j.DexType;
import com.googlecode.d2j.Method;
import com.googlecode.d2j.MethodHandle;
import com.googlecode.d2j.Proto;
import com.googlecode.d2j.asm.LdcOptimizeAdapter;
import com.googlecode.d2j.dex.Dex2Asm;
Expand Down Expand Up @@ -679,8 +680,8 @@ private void accept(Value value, MethodVisitor asm) {
Constant cst = (Constant) value;
if (cst.value.equals(Constant.Null)) {
asm.visitInsn(ACONST_NULL);
} else if (cst.value instanceof DexType) {
asm.visitLdcInsn(Type.getType(((DexType) cst.value).desc));
} else if (cst.value instanceof DexType || cst.value instanceof MethodHandle || cst.value instanceof Proto) {
asm.visitLdcInsn(Dex2Asm.convertConstantValue(cst.value));
} else {
asm.visitLdcInsn(cst.value);
}
Expand Down
18 changes: 9 additions & 9 deletions dex-translator/src/main/java/com/googlecode/d2j/dex/Dex2Asm.java
Original file line number Diff line number Diff line change
Expand Up @@ -602,31 +602,31 @@ public static Object convertConstantValue(Object ele) {
MethodHandle mh = (MethodHandle) ele;
switch (mh.getType()) {
case MethodHandle.INSTANCE_GET:
h = new Handle(Opcodes.H_GETFIELD, toInternalName(mh.getField().getOwner()), mh.getField().getName(), mh.getField().getType());
h = new Handle(Opcodes.H_GETFIELD, toInternalName(mh.getField().getOwner()), mh.getField().getName(), mh.getField().getType(), false);
break;
case MethodHandle.INSTANCE_PUT:
h = new Handle(Opcodes.H_PUTFIELD, toInternalName(mh.getField().getOwner()), mh.getField().getName(), mh.getField().getType());
h = new Handle(Opcodes.H_PUTFIELD, toInternalName(mh.getField().getOwner()), mh.getField().getName(), mh.getField().getType(), false);
break;
case MethodHandle.STATIC_GET:
h = new Handle(Opcodes.H_GETFIELD, toInternalName(mh.getField().getOwner()), mh.getField().getName(), mh.getField().getType());
h = new Handle(Opcodes.H_GETSTATIC, toInternalName(mh.getField().getOwner()), mh.getField().getName(), mh.getField().getType(), false);
break;
case MethodHandle.STATIC_PUT:
h = new Handle(Opcodes.H_PUTFIELD, toInternalName(mh.getField().getOwner()), mh.getField().getName(), mh.getField().getType());
h = new Handle(Opcodes.H_PUTSTATIC, toInternalName(mh.getField().getOwner()), mh.getField().getName(), mh.getField().getType(), false);
break;
case MethodHandle.INVOKE_INSTANCE:
h = new Handle(Opcodes.H_INVOKEVIRTUAL, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc());
h = new Handle(Opcodes.H_INVOKEVIRTUAL, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc(), false);
break;
case MethodHandle.INVOKE_STATIC:
h = new Handle(Opcodes.H_INVOKESTATIC, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc());
h = new Handle(Opcodes.H_INVOKESTATIC, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc(), false);
break;
case MethodHandle.INVOKE_CONSTRUCTOR:
h = new Handle(Opcodes.H_NEWINVOKESPECIAL, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc());
h = new Handle(Opcodes.H_NEWINVOKESPECIAL, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc(), false);
break;
case MethodHandle.INVOKE_DIRECT:
h = new Handle(Opcodes.H_INVOKESPECIAL, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc());
h = new Handle(Opcodes.H_INVOKESPECIAL, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc(), false);
break;
case MethodHandle.INVOKE_INTERFACE:
h = new Handle(Opcodes.H_INVOKEINTERFACE, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc());
h = new Handle(Opcodes.H_INVOKEINTERFACE, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc(), true);
break;
}
ele = h;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,12 @@ public ClassVisitor create(String classInternalName) {
CfOptions cfOptions = new CfOptions();
cfOptions.strictNameCheck = false;
DexOptions dexOptions = new DexOptions();
if (fileNode != null && fileNode.dexVersion >= DexConstants.DEX_037) {
dexOptions.minSdkVersion = 26;
if (fileNode != null) {
if (fileNode.dexVersion >= DexConstants.DEX_039) {
dexOptions.minSdkVersion = 28;
} else if (fileNode.dexVersion >= DexConstants.DEX_037) {
dexOptions.minSdkVersion = 26;
}
}

DirectClassFile dcf = new DirectClassFile(data, rca.getClassName() + ".class", true);
Expand Down
Binary file not shown.
Binary file added dex-translator/src/test/resources/dexes/dex040.dex
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ public void visitFillArrayDataStmt(Op op, int ra, Object value) {
@Override
public void visitConstStmt(Op op, int ra, Object value) {
switch (op.format) {
case kFmt21c:// value is field,type,string
case kFmt21c:// value is field,type,string,method_handle,proto
case kFmt31c:// value is string,
value = cp.wrapEncodedItem(value);
ops.add(new CodeWriter.IndexedInsn(op, ra, 0, (BaseItem) value));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ void buildMapListItem() {
SectionType.TYPE_FIELD_ID_ITEM, cp.fields.values());
SectionItem<MethodIdItem> methodIdSection = new SectionItem<>(
SectionType.TYPE_METHOD_ID_ITEM, cp.methods.values());
SectionItem<MethodHandleItem> methodHandlerSection = new SectionItem<>(
SectionType.TYPE_METHOD_HANDLE_ITEM, cp.methodHandlers.values());
SectionItem<ClassDefItem> classDefSection = new SectionItem<>(
SectionType.TYPE_CLASS_DEF_ITEM, cp.buildSortedClassDefItems());
SectionItem<TypeListItem> typeListSection = new SectionItem<>(
Expand Down Expand Up @@ -200,6 +202,7 @@ void buildMapListItem() {
items.add(protoIdSection);
items.add(fieldIdSection);
items.add(methodIdSection);
items.add(methodHandlerSection);
items.add(classDefSection);

items.addAll(dataSectionItems);
Expand Down
Loading

0 comments on commit 17f162e

Please sign in to comment.