Skip to content

Commit

Permalink
Merge pull request #74 from REAndroid/smali-callsite-parser
Browse files Browse the repository at this point in the history
Parse smali call site invoke instructions
  • Loading branch information
REAndroid authored Oct 8, 2024
2 parents 1e1409e + 10c251c commit b206d6e
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 4 deletions.
38 changes: 34 additions & 4 deletions src/main/java/com/reandroid/dex/common/MethodHandleType.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@
package com.reandroid.dex.common;

import com.reandroid.dex.smali.SmaliFormat;
import com.reandroid.dex.smali.SmaliReader;
import com.reandroid.dex.smali.SmaliWriter;
import com.reandroid.utils.CompareUtil;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class MethodHandleType implements Comparable<MethodHandleType>, SmaliFormat {

Expand All @@ -34,6 +37,7 @@ public class MethodHandleType implements Comparable<MethodHandleType>, SmaliForm
public static final MethodHandleType INVOKE_INTERFACE;

private static final MethodHandleType[] VALUES;
private static final Map<String, MethodHandleType> nameMap;

static {

Expand All @@ -47,7 +51,7 @@ public class MethodHandleType implements Comparable<MethodHandleType>, SmaliForm
INVOKE_DIRECT = new MethodHandleType(7, "invoke-direct", false);
INVOKE_INTERFACE = new MethodHandleType(8, "invoke-interface", false);

VALUES = new MethodHandleType[] {
MethodHandleType [] values = new MethodHandleType[] {
STATIC_PUT,
STATIC_GET,
INSTANCE_PUT,
Expand All @@ -58,6 +62,14 @@ public class MethodHandleType implements Comparable<MethodHandleType>, SmaliForm
INVOKE_DIRECT,
INVOKE_INTERFACE
};
VALUES = values;
int length = values.length;
Map<String, MethodHandleType> map = new HashMap<>(length);
nameMap = map;
for (int i = 0; i < length; i++) {
MethodHandleType type = values[i];
map.put(type.name, type);
}
}

private final int type;
Expand All @@ -69,9 +81,6 @@ private MethodHandleType(int type, String name, boolean field) {
this.name = name;
this.field = field;
}
private MethodHandleType(int type, String name) {
this(type, name, false);
}

public String name() {
return name;
Expand Down Expand Up @@ -120,4 +129,25 @@ public static MethodHandleType valueOf(int type) {
}
return null;
}
public static MethodHandleType valueOf(String name) {
return nameMap.get(name);
}

public static MethodHandleType read(SmaliReader reader) {
reader.skipWhitespaces();
int position = reader.position();
char c = reader.getASCII(position);
if (c != 's' && c != 'i') {
return null;
}
int i = reader.indexOfBeforeLineEnd('@');
if (i < 0) {
return null;
}
MethodHandleType type = valueOf(reader.readString(i - position).trim());
if (type == null) {
reader.position(position);
}
return type;
}
}
59 changes: 59 additions & 0 deletions src/main/java/com/reandroid/dex/key/ArrayKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@
*/
package com.reandroid.dex.key;

import com.reandroid.dex.smali.SmaliParseException;
import com.reandroid.dex.smali.SmaliReader;
import com.reandroid.dex.smali.SmaliWriter;
import com.reandroid.utils.CompareUtil;
import com.reandroid.utils.ObjectsUtil;
import com.reandroid.utils.collection.ArrayCollection;
import com.reandroid.utils.collection.ArrayIterator;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

public class ArrayKey implements Key, Iterable<Key> {

Expand Down Expand Up @@ -138,4 +142,59 @@ public boolean equals(Object obj) {
}
return true;
}

public static ArrayKey read(SmaliReader reader, char end) throws IOException {
reader.skipWhitespacesOrComment();
if (reader.getASCII(reader.position()) == end) {
reader.readASCII();
return new ArrayKey(new Key[0]);
}
List<Key> results = new ArrayCollection<>();
while (true) {
Key key = readNext(reader);
results.add(key);
reader.skipWhitespacesOrComment();
if (reader.getASCII(reader.position()) == end) {
break;
}
SmaliParseException.expect(reader, ',');
}
SmaliParseException.expect(reader, end);
return new ArrayKey(results.toArray(new Key[results.size()]));
}
private static Key readNext(SmaliReader reader) throws IOException {
reader.skipWhitespacesOrComment();
char c = reader.getASCII(reader.position());
if (c == '"') {
return StringKey.read(reader);
}
Key key = MethodHandleKey.read(reader);
if (key != null) {
return key;
}
key = TypeKey.primitiveType(c);
if (key != null) {
reader.readASCII();
return key;
}
int lineEnd = reader.indexOfBeforeLineEnd(',');
if (lineEnd < 0) {
lineEnd = reader.indexOfLineEnd();
}
if (c == 'L' || c == '[') {
int i = reader.indexOfBeforeLineEnd('>');
if (i < 0 || i > lineEnd) {
return TypeKey.read(reader);
}
c = reader.getASCII(i + 1);
if (c == '(') {
return MethodKey.read(reader);
}
if (c != ':') {
throw new SmaliParseException("Expecting ':'", reader);
}
return FieldKey.read(reader);
}
return StringKey.read(reader);
}
}
31 changes: 31 additions & 0 deletions src/main/java/com/reandroid/dex/key/CallSiteKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
*/
package com.reandroid.dex.key;

import com.reandroid.dex.common.MethodHandleType;
import com.reandroid.dex.smali.SmaliParseException;
import com.reandroid.dex.smali.SmaliReader;
import com.reandroid.dex.smali.SmaliWriter;

import java.io.IOException;
Expand Down Expand Up @@ -88,4 +91,32 @@ public String toString() {
}
return builder.toString();
}

public static CallSiteKey read(SmaliReader reader) throws IOException {
reader.skipWhitespaces();
String label = readCallSiteLabel(reader);
SmaliParseException.expect(reader, '(');
StringKey name = StringKey.read(reader);
reader.skipWhitespacesOrComment();
SmaliParseException.expect(reader, ',');
ProtoKey protoKey = ProtoKey.read(reader);
reader.skipWhitespacesOrComment();
SmaliParseException.expect(reader, ',');
ArrayKey arguments = ArrayKey.read(reader, ')');
reader.skipWhitespacesOrComment();
SmaliParseException.expect(reader, '@');
MethodHandleKey methodHandleKey = MethodHandleKey.read(MethodHandleType.INVOKE_STATIC, reader);
return new CallSiteKey(methodHandleKey, name, protoKey, arguments);
}
private static String readCallSiteLabel(SmaliReader reader) throws IOException {
int position = reader.position();
if (reader.getASCII(position) == '(') {
return null;
}
int i = reader.indexOfBeforeLineEnd('(');
if (i < 0) {
throw new SmaliParseException("Expecting call site", reader);
}
return reader.readString(i - position);
}
}
21 changes: 21 additions & 0 deletions src/main/java/com/reandroid/dex/key/MethodHandleKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package com.reandroid.dex.key;

import com.reandroid.dex.common.MethodHandleType;
import com.reandroid.dex.smali.SmaliParseException;
import com.reandroid.dex.smali.SmaliReader;
import com.reandroid.dex.smali.SmaliWriter;
import com.reandroid.utils.CompareUtil;
import com.reandroid.utils.ObjectsUtil;
Expand Down Expand Up @@ -108,4 +110,23 @@ public int hashCode() {
public String toString() {
return getHandleType() + "@" + getMember();
}

public static MethodHandleKey read(SmaliReader reader) throws IOException {
MethodHandleType handleType = MethodHandleType.read(reader);
if (handleType == null) {
return null;
}
SmaliParseException.expect(reader, '@');
return read(handleType, reader);
}

public static MethodHandleKey read(MethodHandleType handleType, SmaliReader reader) throws IOException {
Key key;
if (handleType.isField()) {
key = FieldKey.read(reader);
} else {
key = MethodKey.read(reader);
}
return new MethodHandleKey(handleType, key);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ public void parse(Opcode<?> opcode, SmaliReader reader) throws IOException {
key = FieldKey.read(reader);
}else if(sectionType == SectionType.METHOD_ID){
key = MethodKey.read(reader);
}else if(sectionType == SectionType.CALL_SITE_ID){
key = CallSiteKey.read(reader);
}else {
throw new SmaliParseException("Invalid key", reader);
}
Expand Down

0 comments on commit b206d6e

Please sign in to comment.