mirror of
https://github.com/revanced/smali.git
synced 2025-05-29 04:10:13 +02:00
Add usage type support for field usages
This commit is contained in:
parent
9b86fcabff
commit
9bedfc8e3e
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -24,9 +24,11 @@ smali.FILE
|
||||
PsiElement(LITERAL)
|
||||
PsiElement(ENUM_DIRECTIVE)('.enum')
|
||||
PsiWhiteSpace(' ')
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user