aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gruver <bgruv@google.com>2015-03-25 19:45:20 -0700
committerBen Gruver <bgruv@google.com>2015-03-25 19:45:20 -0700
commit9bedfc8e3e51c2b2435aab425533dc5043c84a9e (patch)
tree1c85db59d4cb4337cfe87cea3aaf88b948b66675
parent9b86fcabff509f4a521bfe717b4633fb381fde03 (diff)
downloadsmali-9bedfc8e3e51c2b2435aab425533dc5043c84a9e.tar.gz
Add usage type support for field usages
-rw-r--r--smali/src/main/antlr/smaliParser.g5
-rw-r--r--smalidea/src/main/antlr3/smalideaParser.g14
-rw-r--r--smalidea/src/main/java/org/jf/smalidea/findUsages/SmaliUsageTypeProvider.java38
-rw-r--r--smalidea/src/test/java/org/jf/smalidea/findUsages/FieldUsageTypeTest.java115
-rw-r--r--smalidea/testData/InvalidEnumLiteral.txt22
5 files changed, 172 insertions, 22 deletions
diff --git a/smali/src/main/antlr/smaliParser.g b/smali/src/main/antlr/smaliParser.g
index aab52738..9fcf2f1d 100644
--- a/smali/src/main/antlr/smaliParser.g
+++ b/smali/src/main/antlr/smaliParser.g
@@ -687,9 +687,10 @@ subannotation
: SUBANNOTATION_DIRECTIVE CLASS_DESCRIPTOR annotation_element* END_SUBANNOTATION_DIRECTIVE
-> ^(I_SUBANNOTATION[$start, "I_SUBANNOTATION"] CLASS_DESCRIPTOR annotation_element*);
+// TODO: how does dalvik handle a primitive or array type, or a non-enum type?
enum_literal
- : ENUM_DIRECTIVE reference_type_descriptor ARROW simple_name COLON reference_type_descriptor
- -> ^(I_ENCODED_ENUM reference_type_descriptor simple_name reference_type_descriptor);
+ : ENUM_DIRECTIVE field_reference
+ -> ^(I_ENCODED_ENUM field_reference);
type_field_method_literal
: reference_type_descriptor
diff --git a/smalidea/src/main/antlr3/smalideaParser.g b/smalidea/src/main/antlr3/smalideaParser.g
index ac7192d5..0da263f2 100644
--- a/smalidea/src/main/antlr3/smalideaParser.g
+++ b/smalidea/src/main/antlr3/smalideaParser.g
@@ -693,7 +693,7 @@ array_literal
enum_literal
@init { Marker marker = mark(); }
- : ENUM_DIRECTIVE reference_type_descriptor arrow simple_name colon reference_type_descriptor
+ : ENUM_DIRECTIVE fully_qualified_field
{ marker.done(SmaliElementTypes.LITERAL); };
catch [RecognitionException re] {
recover(input, re);
@@ -702,15 +702,9 @@ enum_literal
type_field_method_literal
@init { Marker marker = mark(); }
- : ( reference_type_descriptor
- ( arrow
- ( member_name colon nonvoid_type_descriptor
- | member_name method_prototype_reference
- )
- | /* epsilon */
- )
- | primitive_type
- | void_type)
+ : ( type_descriptor
+ | fully_qualified_field
+ | fully_qualified_method)
{ marker.done(SmaliElementTypes.LITERAL); };
catch [RecognitionException re] {
recover(input, re);
diff --git a/smalidea/src/main/java/org/jf/smalidea/findUsages/SmaliUsageTypeProvider.java b/smalidea/src/main/java/org/jf/smalidea/findUsages/SmaliUsageTypeProvider.java
index a0069b86..13ca82a2 100644
--- a/smalidea/src/main/java/org/jf/smalidea/findUsages/SmaliUsageTypeProvider.java
+++ b/smalidea/src/main/java/org/jf/smalidea/findUsages/SmaliUsageTypeProvider.java
@@ -33,6 +33,7 @@ package org.jf.smalidea.findUsages;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiField;
import com.intellij.psi.PsiReference;
import com.intellij.psi.tree.IElementType;
import com.intellij.usages.impl.rules.UsageType;
@@ -63,6 +64,8 @@ public class SmaliUsageTypeProvider implements UsageTypeProvider {
if (referenced != null) {
if (referenced instanceof PsiClass) {
return findClassUsageType(element);
+ } else if (referenced instanceof PsiField) {
+ return findFieldUsageType(element);
}
}
}
@@ -72,6 +75,18 @@ public class SmaliUsageTypeProvider implements UsageTypeProvider {
private final Set<Opcode> newArrayInstructions = EnumSet.of(Opcode.FILLED_NEW_ARRAY, Opcode.NEW_ARRAY,
Opcode.FILLED_NEW_ARRAY_RANGE);
+ private final Set<Opcode> fieldReadInstructions = EnumSet.of(Opcode.IGET, Opcode.IGET_BOOLEAN, Opcode.IGET_BYTE,
+ Opcode.IGET_CHAR, Opcode.IGET_OBJECT, Opcode.IGET_OBJECT_VOLATILE, Opcode.IGET_SHORT, Opcode.IGET_VOLATILE,
+ Opcode.IGET_WIDE, Opcode.IGET_WIDE_VOLATILE, Opcode.SGET, Opcode.SGET_BOOLEAN, Opcode.SGET_BYTE,
+ Opcode.SGET_CHAR, Opcode.SGET_OBJECT, Opcode.SGET_OBJECT_VOLATILE, Opcode.SGET_SHORT, Opcode.SGET_VOLATILE,
+ Opcode.SGET_WIDE, Opcode.SGET_WIDE_VOLATILE);
+
+ private final Set<Opcode> fieldWriteInstructions = EnumSet.of(Opcode.IPUT, Opcode.IPUT_BOOLEAN, Opcode.IPUT_BYTE,
+ Opcode.IPUT_CHAR, Opcode.IPUT_OBJECT, Opcode.IPUT_OBJECT_VOLATILE, Opcode.IPUT_SHORT, Opcode.IPUT_VOLATILE,
+ Opcode.IPUT_WIDE, Opcode.IPUT_WIDE_VOLATILE, Opcode.SPUT, Opcode.SPUT_BOOLEAN, Opcode.SPUT_BYTE,
+ Opcode.SPUT_CHAR, Opcode.SPUT_OBJECT, Opcode.SPUT_OBJECT_VOLATILE, Opcode.SPUT_SHORT, Opcode.SPUT_VOLATILE,
+ Opcode.SPUT_WIDE, Opcode.SPUT_WIDE_VOLATILE);
+
@Nullable
private UsageType findClassUsageType(@NotNull PsiElement element) {
PsiElement originalElement = element;
@@ -141,4 +156,27 @@ public class SmaliUsageTypeProvider implements UsageTypeProvider {
}
return UsageType.UNCLASSIFIED;
}
+
+ @Nullable
+ private UsageType findFieldUsageType(@NotNull PsiElement element) {
+ PsiElement originalElement = element;
+
+ while (element != null) {
+ element = element.getParent();
+
+ if (element instanceof SmaliInstruction) {
+ Opcode opcode = ((SmaliInstruction) element).getOpcode();
+ if (fieldReadInstructions.contains(opcode)) {
+ return UsageType.READ;
+ } else if (fieldWriteInstructions.contains(opcode)) {
+ return UsageType.WRITE;
+ } else if (opcode == Opcode.THROW_VERIFICATION_ERROR) {
+ return VERIFICATION_ERROR;
+ }
+ } if (element instanceof SmaliLiteral) {
+ return LITERAL;
+ }
+ }
+ return UsageType.UNCLASSIFIED;
+ }
}
diff --git a/smalidea/src/test/java/org/jf/smalidea/findUsages/FieldUsageTypeTest.java b/smalidea/src/test/java/org/jf/smalidea/findUsages/FieldUsageTypeTest.java
new file mode 100644
index 00000000..128c97b5
--- /dev/null
+++ b/smalidea/src/test/java/org/jf/smalidea/findUsages/FieldUsageTypeTest.java
@@ -0,0 +1,115 @@
+package org.jf.smalidea.findUsages;
+
+import com.intellij.usages.impl.rules.UsageType;
+
+public class FieldUsageTypeTest extends UsageTypeTest {
+ public FieldUsageTypeTest() {
+ super(new SmaliUsageTypeProvider());
+ }
+
+ public void testFieldUsageTypes() throws Exception {
+ doTest("blah.smali", "" +
+ ".class public Lblah;\n" +
+ ".super Ljava/lang/Object;\n" +
+ "\n" +
+ ".annotation runtime Lblah;\n" +
+ " element = Lblah;->bl<ref:1>ah:Lblah;\n" +
+ " element2 = .enum Lblah;->bl<ref:2>ah:Lblah;\n" +
+ ".end annotation\n" +
+ "\n" +
+ ".field public blah:Lblah;\n" +
+ "\n" +
+ ".method public blah(Lblah;)Lblah;\n" +
+ " .registers 2\n" +
+ "\n" +
+ " iget v0, v0, Lblah;->bl<ref:3>ah:Lblah;\n" +
+ " iget-object v0, v0, Lblah;->bl<ref:4>ah:Lblah;\n" +
+ " iget-byte v0, v0, Lblah;->bl<ref:5>ah:Lblah;\n" +
+ " iget-char v0, v0, Lblah;->bl<ref:6>ah:Lblah;\n" +
+ " iget-object v0, v0, Lblah;->bl<ref:7>ah:Lblah;\n" +
+ " iget-object-volatile v0, v0, Lblah;->bl<ref:8>ah:Lblah;\n" +
+ " iget-short v0, v0, Lblah;->bl<ref:9>ah:Lblah;\n" +
+ " iget-volatile v0, v0, Lblah;->bl<ref:10>ah:Lblah;\n" +
+ " iget-wide v0, v0, Lblah;->bl<ref:11>ah:Lblah;\n" +
+ " iget-wide-volatile v0, v0, Lblah;->bl<ref:12>ah:Lblah;\n" +
+ " sget v0, Lblah;->bl<ref:13>ah:Lblah;\n" +
+ " sget-boolean v0, Lblah;->bl<ref:14>ah:Lblah;\n" +
+ " sget-byte v0, Lblah;->bl<ref:15>ah:Lblah;\n" +
+ " sget-char v0, Lblah;->bl<ref:16>ah:Lblah;\n" +
+ " sget-object v0, Lblah;->bl<ref:17>ah:Lblah;\n" +
+ " sget-object-volatile v0, Lblah;->bl<ref:18>ah:Lblah;\n" +
+ " sget-short v0, Lblah;->bl<ref:19>ah:Lblah;\n" +
+ " sget-volatile v0, Lblah;->bl<ref:20>ah:Lblah;\n" +
+ " sget-wide v0, Lblah;->bl<ref:21>ah:Lblah;\n" +
+ " sget-wide-volatile v0, Lblah;->bl<ref:22>ah:Lblah;\n" +
+ " \n" +
+ " iput v0, v0, Lblah;->bl<ref:23>ah:Lblah;\n" +
+ " iput-object v0, v0, Lblah;->bl<ref:24>ah:Lblah;\n" +
+ " iput-byte v0, v0, Lblah;->bl<ref:25>ah:Lblah;\n" +
+ " iput-char v0, v0, Lblah;->bl<ref:26>ah:Lblah;\n" +
+ " iput-object v0, v0, Lblah;->bl<ref:27>ah:Lblah;\n" +
+ " iput-object-volatile v0, v0, Lblah;->bl<ref:28>ah:Lblah;\n" +
+ " iput-short v0, v0, Lblah;->bl<ref:29>ah:Lblah;\n" +
+ " iput-volatile v0, v0, Lblah;->bl<ref:30>ah:Lblah;\n" +
+ " iput-wide v0, v0, Lblah;->bl<ref:31>ah:Lblah;\n" +
+ " iput-wide-volatile v0, v0, Lblah;->bl<ref:32>ah:Lblah;\n" +
+ " sput v0, Lblah;->bl<ref:33>ah:Lblah;\n" +
+ " sput-boolean v0, Lblah;->bl<ref:34>ah:Lblah;\n" +
+ " sput-byte v0, Lblah;->bl<ref:35>ah:Lblah;\n" +
+ " sput-char v0, Lblah;->bl<ref:36>ah:Lblah;\n" +
+ " sput-object v0, Lblah;->bl<ref:37>ah:Lblah;\n" +
+ " sput-object-volatile v0, Lblah;->bl<ref:38>ah:Lblah;\n" +
+ " sput-short v0, Lblah;->bl<ref:39>ah:Lblah;\n" +
+ " sput-volatile v0, Lblah;->bl<ref:40>ah:Lblah;\n" +
+ " sput-wide v0, Lblah;->bl<ref:41>ah:Lblah;\n" +
+ " sput-wide-volatile v0, Lblah;->bl<ref:42>ah:Lblah;\n" +
+ "\n" +
+ " throw-verification-error generic-error, Lblah;->bl<ref:43>ah:Lblah;\n" +
+ "\n" +
+ " return-void\n" +
+ ".end method\n",
+ 1, SmaliUsageTypeProvider.LITERAL,
+ 2, SmaliUsageTypeProvider.LITERAL,
+ 3, UsageType.READ,
+ 4, UsageType.READ,
+ 5, UsageType.READ,
+ 6, UsageType.READ,
+ 7, UsageType.READ,
+ 8, UsageType.READ,
+ 9, UsageType.READ,
+ 10, UsageType.READ,
+ 11, UsageType.READ,
+ 12, UsageType.READ,
+ 13, UsageType.READ,
+ 14, UsageType.READ,
+ 15, UsageType.READ,
+ 16, UsageType.READ,
+ 17, UsageType.READ,
+ 18, UsageType.READ,
+ 19, UsageType.READ,
+ 20, UsageType.READ,
+ 21, UsageType.READ,
+ 22, UsageType.READ,
+ 23, UsageType.WRITE,
+ 24, UsageType.WRITE,
+ 25, UsageType.WRITE,
+ 26, UsageType.WRITE,
+ 27, UsageType.WRITE,
+ 28, UsageType.WRITE,
+ 29, UsageType.WRITE,
+ 30, UsageType.WRITE,
+ 31, UsageType.WRITE,
+ 32, UsageType.WRITE,
+ 33, UsageType.WRITE,
+ 34, UsageType.WRITE,
+ 35, UsageType.WRITE,
+ 36, UsageType.WRITE,
+ 37, UsageType.WRITE,
+ 38, UsageType.WRITE,
+ 39, UsageType.WRITE,
+ 40, UsageType.WRITE,
+ 41, UsageType.WRITE,
+ 42, UsageType.WRITE,
+ 43, SmaliUsageTypeProvider.VERIFICATION_ERROR);
+ }
+}
diff --git a/smalidea/testData/InvalidEnumLiteral.txt b/smalidea/testData/InvalidEnumLiteral.txt
index 2b595727..b2acd87d 100644
--- a/smalidea/testData/InvalidEnumLiteral.txt
+++ b/smalidea/testData/InvalidEnumLiteral.txt
@@ -24,13 +24,15 @@ smali.FILE
PsiElement(LITERAL)
PsiElement(ENUM_DIRECTIVE)('.enum')
PsiWhiteSpace(' ')
- PsiElement(CLASS_TYPE)
- PsiElement(CLASS_DESCRIPTOR)('Lblah;')
- PsiElement(ARROW)('->')
- PsiElement(SIMPLE_NAME)('blah')
- PsiWhiteSpace(' ')
- PsiErrorElement:mismatched input '.blah' expecting COLON
- PsiElement(BAD_CHARACTER)('.blah')
- PsiWhiteSpace(' ')
- PsiElement(CLASS_TYPE)
- PsiElement(CLASS_DESCRIPTOR)('Lblah;') \ No newline at end of file
+ PsiElement(FIELD_REFERENCE)
+ PsiElement(CLASS_TYPE)
+ PsiElement(CLASS_DESCRIPTOR)('Lblah;')
+ PsiElement(ARROW)('->')
+ PsiElement(MEMBER_NAME)
+ PsiElement(SIMPLE_NAME)('blah')
+ PsiWhiteSpace(' ')
+ PsiErrorElement:mismatched input '.blah' expecting COLON
+ PsiElement(BAD_CHARACTER)('.blah')
+ PsiWhiteSpace(' ')
+ PsiElement(CLASS_TYPE)
+ PsiElement(CLASS_DESCRIPTOR)('Lblah;') \ No newline at end of file