Skip to content

Commit

Permalink
support dex 038
Browse files Browse the repository at this point in the history
  • Loading branch information
pxb1988 committed Aug 31, 2023
1 parent caf241d commit 0862aae
Show file tree
Hide file tree
Showing 26 changed files with 599 additions and 123 deletions.
Original file line number Diff line number Diff line change
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 @@ -199,6 +198,11 @@ method_handler
| type=('invoke-static'|'invoke-instance'|'invoke-direct'|'invoke-interface'|'invoke-constructor') '@' mtd=METHOD_FULL
;

// FIXME samli syntax only write out method_handler's method field
call_site
: name=sAnnotationKeyName '(' method_name=STRING ',' method_type=METHOD_PROTO (',' sBaseValue)* ')' '@' bsm=METHOD_FULL
;

sInstruction
:fline
|flocal
Expand Down Expand Up @@ -415,9 +419,9 @@ fm45cc : op='invoke-polymorphic' '{' (REGISTER (',' REGISTER)* )? '}' ',' metho
;
fm4rcc : op='invoke-polymorphic/range' '{' (rstart=REGISTER '..' rend=REGISTER)? '}' ',' method=METHOD_FULL ',' proto=METHOD_PROTO
;
fmcustomc : op='invoke-custom' '{' (REGISTER (',' REGISTER)* )? '}' ',' sArrayValue
fmcustomc : op='invoke-custom' '{' (REGISTER (',' REGISTER)* )? '}' ',' call_site
;
fmcustomrc : op='invoke-custom/range' '{' (rstart=REGISTER '..' rend=REGISTER)? '}' ',' sArrayValue
fmcustomrc : op='invoke-custom/range' '{' (rstart=REGISTER '..' rend=REGISTER)? '}' ',' call_site
;
ftrc : op='filled-new-array/range' '{' (rstart=REGISTER '..' rend=REGISTER)? '}' ',' type=(OBJECT_TYPE|ARRAY_TYPE);
f31t: op=('fill-array-data'|'packed-switch'|'sparse-switch') r1=REGISTER ',' label=LABEL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,65 @@ public Object visitFm5c(SmaliParser.Fm5cContext ctx) {
return null;
}

@Override
public Object visitFm4rcc(SmaliParser.Fm4rccContext ctx) {
if (ctx.rstart != null) {
int start = m.pareReg(ctx.rstart.getText());
int end = m.pareReg(ctx.rend.getText());
int size = end - start + 1;
int[] rs = new int[size];
for (int i = 0; i < size; i++) {
rs[i] = start + i;
}
scv.visitMethodStmt(getOp(ctx.op), rs, parseMethodAndUnescape(ctx.method.getText()), parseProtoAndUnescape(ctx.proto.getText()));
} else {
scv.visitMethodStmt(getOp(ctx.op), new int[0], parseMethodAndUnescape(ctx.method.getText()), parseProtoAndUnescape(ctx.proto.getText()));
}
return null;
}

@Override
public Object visitFm45cc(SmaliParser.Fm45ccContext ctx) {
Op op = getOp(ctx.op);
List<TerminalNode> ts = ctx.REGISTER();
int[] rs = new int[ts.size()];
for (int i = 0; i < ts.size(); i++) {
rs[i] = m.pareReg(ts.get(i).getSymbol().getText());
}
scv.visitMethodStmt(op, rs, parseMethodAndUnescape(ctx.method.getText()), parseProtoAndUnescape(ctx.proto.getText()));
return null;
}

@Override
public Object visitFmcustomc(SmaliParser.FmcustomcContext ctx) {
Op op = getOp(ctx.op);

List<TerminalNode> ts = ctx.REGISTER();
int[] rs = new int[ts.size()];
for (int i = 0; i < ts.size(); i++) {
rs[i] = m.pareReg(ts.get(i).getSymbol().getText());
}
scv.visitMethodStmt(op, rs, parseCallSite(ctx.call_site()));
return null;
}

@Override
public Object visitFmcustomrc(SmaliParser.FmcustomrcContext ctx) {
if (ctx.rstart != null) {
int start = m.pareReg(ctx.rstart.getText());
int end = m.pareReg(ctx.rend.getText());
int size = end - start + 1;
int[] rs = new int[size];
for (int i = 0; i < size; i++) {
rs[i] = start + i;
}
scv.visitMethodStmt(getOp(ctx.op), rs, parseCallSite(ctx.call_site()));
} else {
scv.visitMethodStmt(getOp(ctx.op), new int[0], parseCallSite(ctx.call_site()));
}
return null;
}

@Override
public Object visitFmrc(SmaliParser.FmrcContext ctx) {
if (ctx.rstart != null) {
Expand Down Expand Up @@ -554,6 +613,25 @@ public Object visitFepiogue(SmaliParser.FepiogueContext ctx) {
scv.visitEnd();
}

private static CallSite parseCallSite(SmaliParser.Call_siteContext callSiteContext) {

List<SmaliParser.SBaseValueContext> sBaseValueContexts = callSiteContext.sBaseValue();
Object[] args = new Object[sBaseValueContexts.size()];
int i = 0;
for (SmaliParser.SBaseValueContext baseValueContext : sBaseValueContexts) {
args[i] = parseBaseValue(baseValueContext);
i++;
}

return new CallSite(
unEscapeId(callSiteContext.name.getText()),
new MethodHandle(MethodHandle.INVOKE_STATIC, parseMethodAndUnescape(callSiteContext.bsm.getText())),
unescapeStr(callSiteContext.method_name.getText()),
parseProtoAndUnescape(callSiteContext.method_type.getText()),
args
);
}

private static MethodHandle parseMethodHandler(SmaliParser.Method_handlerContext methodHandlerContext) {
MethodHandle value;
switch (methodHandlerContext.type.getText()) {
Expand Down Expand Up @@ -781,6 +859,10 @@ private static void acceptAnnotation(DexAnnotationVisitor dexAnnotationVisitor,
Object value = parseBaseValue(baseValueContext);
dexAnnotationVisitor.visit(name, value);
break;
case SmaliParser.RULE_method_handler:
MethodHandle methodHandle = parseMethodHandler((SmaliParser.Method_handlerContext) t);
dexAnnotationVisitor.visit(name, methodHandle);
break;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,14 +385,25 @@ public void visitMethodStmt(Op op, int[] args, Method method, Proto proto) {
}

@Override
public void visitMethodStmt(Op op, int[] args, String name, Proto proto, MethodHandle bsm, Object... bsmArgs) {
public void visitMethodStmt(Op op, int[] args, CallSite callSite) {
StringBuilder sb = new StringBuilder();
sb.append("{ ").append( BaksmaliDumper.escapeValue(bsm)).append(", ").append(BaksmaliDumper.escapeValue(name)).append(", ").append(BaksmaliDumper.escapeMethodDesc(proto));
for(Object o: bsmArgs) {
sb.append(", ").append(BaksmaliDumper.escapeValue(o));
Object[] extraArguments = callSite.getExtraArguments();

// invoke-custom/range {v0 .. v5}, call_site_1("runDynamic", (IIIIII)V, 0x378)@L038;->bsm(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;

sb
.append(BaksmaliDumper.escapeId(callSite.getName()))
.append('(')
.append(BaksmaliDumper.escapeValue(callSite.getMethodName()))
.append(", ")
.append(BaksmaliDumper.escapeMethodDesc(callSite.getMethodProto()));
if (extraArguments != null && extraArguments.length > 0) {
for (Object o : extraArguments) {
sb.append(", ").append(BaksmaliDumper.escapeValue(o));
}
}
sb.append("}");

// FIXME samli syntax only write out method_handler's method field
sb.append(")@").append(BaksmaliDumper.escapeMethod(callSite.getBootstrapMethodHandler().getMethod()));

if (args.length > 0) {
if (op.format == InstructionFormat.kFmt3rc) { // invoke-x/range
Expand Down
9 changes: 1 addition & 8 deletions d2j-smali/src/test/java/a/SmaliTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,7 @@ public void test2() throws IOException {

private void dotest(File dexFile) throws IOException {
int dexVersion = new DexFileReader(dexFile).getDexVersion();
Opcodes opcodes;
if (dexVersion >= DexConstants.DEX_039) {
opcodes = Opcodes.forApi(28);
} else if (dexVersion >= DexConstants.DEX_037) {
opcodes = Opcodes.forApi(26);
} else {
opcodes = Opcodes.forApi(0);
}
Opcodes opcodes = Opcodes.forApi(DexConstants.toMiniAndroidApiLevel(dexVersion));
DexBackedDexFile dex;
try {
dex = DexFileFactory.loadDexFile(dexFile, opcodes);
Expand Down
37 changes: 37 additions & 0 deletions dex-reader-api/src/main/java/com/googlecode/d2j/CallSite.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.googlecode.d2j;

public class CallSite {
private String name;
private MethodHandle bootstrapMethodHandler;
private String methodName;
private Proto methodProto;
private Object[] extraArguments;

public CallSite(String name, MethodHandle bootstrapMethodHandler, String methodName, Proto methodProto, Object... extraArguments) {
this.name = name;
this.bootstrapMethodHandler = bootstrapMethodHandler;
this.methodName = methodName;
this.methodProto = methodProto;
this.extraArguments = extraArguments;
}

public String getName() {
return name;
}

public MethodHandle getBootstrapMethodHandler() {
return bootstrapMethodHandler;
}

public String getMethodName() {
return methodName;
}

public Proto getMethodProto() {
return methodProto;
}

public Object[] getExtraArguments() {
return extraArguments;
}
}
15 changes: 15 additions & 0 deletions dex-reader-api/src/main/java/com/googlecode/d2j/DexConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,25 @@ public abstract interface DexConstants {
String ANNOTATION_INNER_CLASS_TYPE = "Ldalvik/annotation/InnerClass;";
String ANNOTATION_MEMBER_CLASSES_TYPE = "Ldalvik/annotation/MemberClasses;";

static int toMiniAndroidApiLevel(int dexVersion) {
if (dexVersion <= DEX_035 || dexVersion <= DEX_036) {
return 0;
} else if (dexVersion == DEX_037) {
return 24;
} else if (dexVersion == DEX_038) {
return 26;
} else {
return 28;
}
}
int DEX_035 = 0x00303335;
@Deprecated
int DEX_036 = 0x00303336;
// android 7.0, api 24
int DEX_037 = 0x00303337;
// android 8.0, api 26
int DEX_038 = 0x00303338;
// android 9.0, api 28
int DEX_039 = 0x00303339;
int DEX_040 = 0x00303340;
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ public void visitMethodStmt(final Op op, final int[] args, final Method method)
}

@Override
public void visitMethodStmt(Op op, int[] args, String name, Proto proto, MethodHandle bsm, Object... bsmArgs) {
add(new MethodCustomStmtNode(op, args, name, proto, bsm, bsmArgs));
public void visitMethodStmt(Op op, int[] args, CallSite callSite) {
add(new MethodCustomStmtNode(op, args, callSite));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,26 @@
*/
package com.googlecode.d2j.node.insn;

import com.googlecode.d2j.MethodHandle;
import com.googlecode.d2j.CallSite;
import com.googlecode.d2j.Proto;
import com.googlecode.d2j.reader.Op;
import com.googlecode.d2j.visitors.DexCodeVisitor;

public class MethodCustomStmtNode extends AbstractMethodStmtNode {
public final String name;
public final Proto proto;
public final MethodHandle bsm;
public final Object[] bsmArgs;
public final CallSite callSite;

public MethodCustomStmtNode(Op op, int[] args, String name, Proto proto, MethodHandle bsm, Object[] bsmArgs) {
public MethodCustomStmtNode(Op op, int[] args, CallSite callSite) {
super(op, args);
this.proto = proto;
this.name = name;
this.bsm = bsm;
this.bsmArgs = bsmArgs;
this.callSite = callSite;
}

@Override
public void accept(DexCodeVisitor cv) {
cv.visitMethodStmt(op, args, name, proto, bsm, bsmArgs);
cv.visitMethodStmt(op, args, callSite);
}

@Override
public Proto getProto() {
return proto;
return callSite.getMethodProto();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,9 @@ public void visitMethodStmt(Op op, int[] args, Method method) {
* OP_INVOKE_CUSTOM
* </pre>
*/
public void visitMethodStmt(Op op, int[] args, String name, Proto proto, MethodHandle bsm, Object... bsmArgs) {
public void visitMethodStmt(Op op, int[] args, CallSite callSite) {
if (visitor != null) {
visitor.visitMethodStmt(op, args, name, proto, bsm, bsmArgs);
visitor.visitMethodStmt(op, args, callSite);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ public DexFileReader(ByteBuffer in) {
int call_site_ids_size = 0;
int method_handle_ids_off = 0;
int method_handle_ids_size = 0;
if (dex_version > DEX_037) {
if (dex_version >= DEX_038) {
in.position(map_off);
int size = in.getInt();
for (int i = 0; i < size; i++) {
Expand Down Expand Up @@ -1642,9 +1642,7 @@ private void acceptInsn(byte[] insns, DexCodeVisitor dcv, BitSet nextInsn, BitSe
if (op.indexType == InstructionIndexType.kIndexTypeRef) {
dcv.visitFilledNewArrayStmt(op, regs, getType(b));
} else if (op.indexType == InstructionIndexType.kIndexCallSiteRef) {
Object[] callsite = getCallSite(b);
Object[] constArgs = Arrays.copyOfRange(callsite, 3, callsite.length);
dcv.visitMethodStmt(op, regs, (String) callsite[1], (Proto) callsite[2], (MethodHandle) callsite[0], constArgs);
dcv.visitMethodStmt(op, regs, getCallSite(b));
} else {
dcv.visitMethodStmt(op, regs, getMethod(b));
}
Expand All @@ -1661,9 +1659,7 @@ private void acceptInsn(byte[] insns, DexCodeVisitor dcv, BitSet nextInsn, BitSe
if (op.indexType == InstructionIndexType.kIndexTypeRef) {
dcv.visitFilledNewArrayStmt(op, regs, getType(b));
} else if (op.indexType == InstructionIndexType.kIndexCallSiteRef) {
Object[] callsite = getCallSite(b);
Object[] constArgs = Arrays.copyOfRange(callsite, 3, callsite.length - 3);
dcv.visitMethodStmt(op, regs, (String) callsite[1], (Proto) callsite[2], (MethodHandle) callsite[0], constArgs);
dcv.visitMethodStmt(op, regs, getCallSite(b));
} else {
dcv.visitMethodStmt(op, regs, getMethod(b));
}
Expand Down Expand Up @@ -1785,11 +1781,24 @@ private void acceptInsn(byte[] insns, DexCodeVisitor dcv, BitSet nextInsn, BitSe
}
}

private Object[] getCallSite(int b) {
private CallSite getCallSite(int b) {
callSiteIdIn.position(b * 4);
int call_site_off = callSiteIdIn.getInt();

return read_encoded_array_item(call_site_off);
Object[] call_site_items = read_encoded_array_item(call_site_off);
Object[] constArgs;
if (call_site_items.length > 3) {
constArgs = Arrays.copyOfRange(call_site_items, 3, call_site_items.length);
} else {
constArgs = new Object[0];
}

return new CallSite(
String.format("call_site_%d", b),
(MethodHandle) call_site_items[0],
(String) call_site_items[1],
(Proto) call_site_items[2],
constArgs);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ public void visitJumpStmt(Op op, int a, int b, DexLabel label) {
}

@Override
public void visitMethodStmt(Op op, int[] args, String name, Proto proto, MethodHandle bsm, Object... bsmArgs) {
m.s("code.visitMethodStmt(%s,%s,%s,%s,%s,%s);", op(op), Escape.v(args), Escape.v(name), Escape.v(proto), Escape.v(bsm), Escape.v(bsmArgs));
public void visitMethodStmt(Op op, int[] args, CallSite callSite) {
m.s("code.visitMethodStmt(%s,%s,%s);", op(op), Escape.v(args), Escape.v(callSite));
}

@Override
Expand Down
Loading

0 comments on commit 0862aae

Please sign in to comment.