mirror of
https://github.com/revanced/smali.git
synced 2025-05-28 03:40:12 +02:00
Add support for hidden api restrictions to smali and baksmali
The hidden api restrictions are exposed in the smali language as additional access flags for fields and methods
This commit is contained in:
parent
721fffc60e
commit
c3bbc771f5
@ -31,6 +31,7 @@ package org.jf.baksmali.Adaptors;
|
||||
import org.jf.baksmali.Adaptors.EncodedValue.EncodedValueAdaptor;
|
||||
import org.jf.baksmali.BaksmaliOptions;
|
||||
import org.jf.dexlib2.AccessFlags;
|
||||
import org.jf.dexlib2.HiddenApiRestriction;
|
||||
import org.jf.dexlib2.iface.Annotation;
|
||||
import org.jf.dexlib2.iface.Field;
|
||||
import org.jf.dexlib2.iface.value.EncodedValue;
|
||||
@ -39,6 +40,7 @@ import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
public class FieldDefinition {
|
||||
public static void writeTo(BaksmaliOptions options, IndentingWriter writer, Field field,
|
||||
@ -60,7 +62,7 @@ public class FieldDefinition {
|
||||
}
|
||||
|
||||
writer.write(".field ");
|
||||
writeAccessFlags(writer, field.getAccessFlags());
|
||||
writeAccessFlagsAndRestrictions(writer, field.getAccessFlags(), field.getHiddenApiRestrictions());
|
||||
writer.write(field.getName());
|
||||
writer.write(':');
|
||||
writer.write(field.getType());
|
||||
@ -92,10 +94,16 @@ public class FieldDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeAccessFlags(IndentingWriter writer, int accessFlags) throws IOException {
|
||||
private static void writeAccessFlagsAndRestrictions(
|
||||
IndentingWriter writer, int accessFlags, Set<HiddenApiRestriction> hiddenApiRestrictions)
|
||||
throws IOException {
|
||||
for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForField(accessFlags)) {
|
||||
writer.write(accessFlag.toString());
|
||||
writer.write(' ');
|
||||
}
|
||||
for (HiddenApiRestriction hiddenApiRestriction : hiddenApiRestrictions) {
|
||||
writer.write(hiddenApiRestriction.toString());
|
||||
writer.write(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,10 +33,7 @@ import com.google.common.collect.Lists;
|
||||
import org.jf.baksmali.Adaptors.Debug.DebugMethodItem;
|
||||
import org.jf.baksmali.Adaptors.Format.InstructionMethodItemFactory;
|
||||
import org.jf.baksmali.BaksmaliOptions;
|
||||
import org.jf.dexlib2.AccessFlags;
|
||||
import org.jf.dexlib2.Format;
|
||||
import org.jf.dexlib2.Opcode;
|
||||
import org.jf.dexlib2.ReferenceType;
|
||||
import org.jf.dexlib2.*;
|
||||
import org.jf.dexlib2.analysis.AnalysisException;
|
||||
import org.jf.dexlib2.analysis.AnalyzedInstruction;
|
||||
import org.jf.dexlib2.analysis.MethodAnalyzer;
|
||||
@ -165,7 +162,7 @@ public class MethodDefinition {
|
||||
public static void writeEmptyMethodTo(IndentingWriter writer, Method method,
|
||||
BaksmaliOptions options) throws IOException {
|
||||
writer.write(".method ");
|
||||
writeAccessFlags(writer, method.getAccessFlags());
|
||||
writeAccessFlagsAndRestrictions(writer, method.getAccessFlags(), method.getHiddenApiRestrictions());
|
||||
writer.write(method.getName());
|
||||
writer.write("(");
|
||||
ImmutableList<MethodParameter> methodParameters = ImmutableList.copyOf(method.getParameters());
|
||||
@ -196,7 +193,7 @@ public class MethodDefinition {
|
||||
}
|
||||
|
||||
writer.write(".method ");
|
||||
writeAccessFlags(writer, method.getAccessFlags());
|
||||
writeAccessFlagsAndRestrictions(writer, method.getAccessFlags(), method.getHiddenApiRestrictions());
|
||||
writer.write(method.getName());
|
||||
writer.write("(");
|
||||
for (MethodParameter parameter: methodParameters) {
|
||||
@ -303,12 +300,17 @@ public class MethodDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeAccessFlags(IndentingWriter writer, int accessFlags)
|
||||
private static void writeAccessFlagsAndRestrictions(
|
||||
IndentingWriter writer, int accessFlags, Set<HiddenApiRestriction> hiddenApiRestrictions)
|
||||
throws IOException {
|
||||
for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(accessFlags)) {
|
||||
writer.write(accessFlag.toString());
|
||||
writer.write(' ');
|
||||
}
|
||||
for (HiddenApiRestriction hiddenApiRestriction : hiddenApiRestrictions) {
|
||||
writer.write(hiddenApiRestriction.toString());
|
||||
writer.write(' ');
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeParameters(IndentingWriter writer, Method method,
|
||||
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class HiddenApiRestrictionsRoundtripTest extends RoundtripTest {
|
||||
@Test
|
||||
public void testHiddenApiRestrictions() {
|
||||
BaksmaliOptions options = new BaksmaliOptions();
|
||||
options.apiLevel = 29;
|
||||
runTest("HiddenApiRestrictions", options);
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2020, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.jf.dexlib2.dexbacked.DexBackedClassDef;
|
||||
import org.jf.dexlib2.dexbacked.raw.ItemType;
|
||||
import org.jf.smali.SmaliTestUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class HiddenApiRestrictionsTest {
|
||||
|
||||
@Test
|
||||
public void testNoHiddenApiRestrictions() throws IOException, RecognitionException {
|
||||
String source = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
".method public static main([Ljava/lang/String;)V\n" +
|
||||
" .registers 1\n" +
|
||||
" return-void\n" +
|
||||
".end method";
|
||||
|
||||
DexBackedClassDef classDef = SmaliTestUtils.compileSmali(source, 29);
|
||||
|
||||
Assert.assertNull(classDef.dexFile.getMapItemForSection(ItemType.HIDDENAPI_CLASS_DATA_ITEM));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithHiddenApiRestrictions() throws IOException, RecognitionException {
|
||||
String source = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
".method public whitelist static main([Ljava/lang/String;)V\n" +
|
||||
" .registers 1\n" +
|
||||
" return-void\n" +
|
||||
".end method";
|
||||
|
||||
DexBackedClassDef classDef = SmaliTestUtils.compileSmali(source, 29);
|
||||
|
||||
Assert.assertNotNull(classDef.dexFile.getMapItemForSection(ItemType.HIDDENAPI_CLASS_DATA_ITEM));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithHiddenApiRestrictionsWithLowerApi() throws IOException, RecognitionException {
|
||||
String source = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
".method public whitelist static main([Ljava/lang/String;)V\n" +
|
||||
" .registers 1\n" +
|
||||
" return-void\n" +
|
||||
".end method";
|
||||
|
||||
try {
|
||||
SmaliTestUtils.compileSmali(source, 28);
|
||||
Assert.fail();
|
||||
} catch (RuntimeException ex) {
|
||||
// expected exception
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
.class public LHiddenApiRestrictions;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
.field public static whitelist staticField:I
|
||||
|
||||
.field public core-platform-api domainSpecificFlagTest:I
|
||||
|
||||
.field public blacklist instanceField:I
|
||||
|
||||
.method public blacklist virtualMethod()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method private greylist-max-o directMethod()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method private core-platform-api corePlatformApiTest()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method greylist-max-q private core-platform-api corePlatformApiAndHiddenApiTest()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
@ -0,0 +1,40 @@
|
||||
.class public LHiddenApiRestrictions;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# static fields
|
||||
.field public static whitelist staticField:I
|
||||
|
||||
|
||||
# instance fields
|
||||
.field public whitelist core-platform-api domainSpecificFlagTest:I
|
||||
|
||||
.field public blacklist instanceField:I
|
||||
|
||||
|
||||
# direct methods
|
||||
.method private greylist-max-q core-platform-api corePlatformApiAndHiddenApiTest()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method private whitelist core-platform-api corePlatformApiTest()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method private greylist-max-o directMethod()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
|
||||
# virtual methods
|
||||
.method public blacklist virtualMethod()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
@ -33,6 +33,8 @@ package org.jf.dexlib2;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
@ -58,6 +60,15 @@ public enum HiddenApiRestriction {
|
||||
CORE_PLATFORM_API
|
||||
};
|
||||
|
||||
private static final Map<String, HiddenApiRestriction> hiddenApiRestrictionsByName;
|
||||
|
||||
static {
|
||||
hiddenApiRestrictionsByName = new HashMap<>();
|
||||
for (HiddenApiRestriction hiddenApiRestriction : HiddenApiRestriction.values()) {
|
||||
hiddenApiRestrictionsByName.put(hiddenApiRestriction.toString(), hiddenApiRestriction);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int HIDDENAPI_FLAG_MASK = 0x7;
|
||||
|
||||
private final int value;
|
||||
@ -134,4 +145,8 @@ public enum HiddenApiRestriction {
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public static HiddenApiRestriction forName(String name) {
|
||||
return hiddenApiRestrictionsByName.get(name);
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ tokens {
|
||||
FIELD_OFFSET;
|
||||
FLOAT_LITERAL;
|
||||
FLOAT_LITERAL_OR_ID;
|
||||
HIDDENAPI_RESTRICTION;
|
||||
IMPLEMENTS_DIRECTIVE;
|
||||
INLINE_INDEX;
|
||||
INSTRUCTION_FORMAT10t;
|
||||
@ -167,6 +168,7 @@ tokens {
|
||||
I_IMPLEMENTS;
|
||||
I_SOURCE;
|
||||
I_ACCESS_LIST;
|
||||
I_ACCESS_OR_RESTRICTION_LIST;
|
||||
I_METHODS;
|
||||
I_FIELDS;
|
||||
I_FIELD;
|
||||
@ -479,6 +481,13 @@ source_spec
|
||||
access_list
|
||||
: ACCESS_SPEC* -> ^(I_ACCESS_LIST[$start,"I_ACCESS_LIST"] ACCESS_SPEC*);
|
||||
|
||||
access_or_restriction
|
||||
: ACCESS_SPEC | HIDDENAPI_RESTRICTION;
|
||||
|
||||
access_or_restriction_list
|
||||
: access_or_restriction*
|
||||
-> ^(I_ACCESS_OR_RESTRICTION_LIST[$start,"I_ACCESS_AND_RESTRICTION_LIST"] access_or_restriction*);
|
||||
|
||||
|
||||
/*When there are annotations immediately after a field definition, we don't know whether they are field annotations
|
||||
or class annotations until we determine if there is an .end field directive. In either case, we still "consume" and parse
|
||||
@ -486,19 +495,19 @@ the annotations. If it turns out that they are field annotations, we include the
|
||||
add them to the $smali_file::classAnnotations list*/
|
||||
field
|
||||
@init {List<CommonTree> annotations = new ArrayList<CommonTree>();}
|
||||
: FIELD_DIRECTIVE access_list member_name COLON nonvoid_type_descriptor (EQUAL literal)?
|
||||
: FIELD_DIRECTIVE access_or_restriction_list member_name COLON nonvoid_type_descriptor (EQUAL literal)?
|
||||
( ({input.LA(1) == ANNOTATION_DIRECTIVE}? annotation {annotations.add($annotation.tree);})*
|
||||
( END_FIELD_DIRECTIVE
|
||||
-> ^(I_FIELD[$start, "I_FIELD"] member_name access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS annotation*))
|
||||
-> ^(I_FIELD[$start, "I_FIELD"] member_name access_or_restriction_list ^(I_FIELD_TYPE nonvoid_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS annotation*))
|
||||
| /*epsilon*/ {$smali_file::classAnnotations.addAll(annotations);}
|
||||
-> ^(I_FIELD[$start, "I_FIELD"] member_name access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS))
|
||||
-> ^(I_FIELD[$start, "I_FIELD"] member_name access_or_restriction_list ^(I_FIELD_TYPE nonvoid_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS))
|
||||
)
|
||||
);
|
||||
|
||||
method
|
||||
: METHOD_DIRECTIVE access_list member_name method_prototype statements_and_directives
|
||||
: METHOD_DIRECTIVE access_or_restriction_list member_name method_prototype statements_and_directives
|
||||
END_METHOD_DIRECTIVE
|
||||
-> ^(I_METHOD[$start, "I_METHOD"] member_name method_prototype access_list statements_and_directives);
|
||||
-> ^(I_METHOD[$start, "I_METHOD"] member_name method_prototype access_or_restriction_list statements_and_directives);
|
||||
|
||||
statements_and_directives
|
||||
scope
|
||||
|
@ -223,7 +223,7 @@ source_spec returns[String source]
|
||||
^(I_SOURCE string_literal {$source = $string_literal.value;})
|
||||
| /*epsilon*/;
|
||||
|
||||
access_list returns [int value]
|
||||
access_list returns[int value]
|
||||
@init
|
||||
{
|
||||
$value = 0;
|
||||
@ -236,6 +236,51 @@ access_list returns [int value]
|
||||
}
|
||||
)*);
|
||||
|
||||
access_or_restriction_list returns[int value, Set<HiddenApiRestriction> hiddenApiRestrictions]
|
||||
@init
|
||||
{
|
||||
$value = 0;
|
||||
HiddenApiRestriction hiddenApiRestriction = null;
|
||||
HiddenApiRestriction domainSpecificApiRestriction = null;
|
||||
}
|
||||
: ^(I_ACCESS_OR_RESTRICTION_LIST
|
||||
(
|
||||
ACCESS_SPEC
|
||||
{
|
||||
$value |= AccessFlags.getAccessFlag($ACCESS_SPEC.getText()).getValue();
|
||||
}
|
||||
|
|
||||
HIDDENAPI_RESTRICTION
|
||||
{
|
||||
if (opcodes.api < 29) {
|
||||
throw new SemanticException(input, $HIDDENAPI_RESTRICTION, "Hidden API restrictions are only supported on api 29 and above.");
|
||||
}
|
||||
|
||||
HiddenApiRestriction restriction = HiddenApiRestriction.forName($HIDDENAPI_RESTRICTION.getText());
|
||||
if (restriction.isDomainSpecificApiFlag()) {
|
||||
if (domainSpecificApiRestriction != null) {
|
||||
throw new SemanticException(input, $HIDDENAPI_RESTRICTION, "Only one domain-specific api restriction may be specified.");
|
||||
}
|
||||
domainSpecificApiRestriction = restriction;
|
||||
} else {
|
||||
if (hiddenApiRestriction != null) {
|
||||
throw new SemanticException(input, $HIDDENAPI_RESTRICTION, "Only one hidden api restriction may be specified.");
|
||||
}
|
||||
hiddenApiRestriction = restriction;
|
||||
}
|
||||
}
|
||||
)*)
|
||||
{
|
||||
List<HiddenApiRestriction> restrictions = new ArrayList<>(2);
|
||||
if (hiddenApiRestriction != null) {
|
||||
restrictions.add(hiddenApiRestriction);
|
||||
}
|
||||
if (domainSpecificApiRestriction != null) {
|
||||
restrictions.add(domainSpecificApiRestriction);
|
||||
}
|
||||
$hiddenApiRestrictions = ImmutableSet.copyOf(restrictions);
|
||||
};
|
||||
|
||||
|
||||
fields returns[List<BuilderField> fields]
|
||||
@init {$fields = Lists.newArrayList();}
|
||||
@ -254,17 +299,17 @@ methods returns[List<BuilderMethod> methods]
|
||||
})*);
|
||||
|
||||
field returns [BuilderField field]
|
||||
:^(I_FIELD SIMPLE_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?)
|
||||
:^(I_FIELD SIMPLE_NAME access_or_restriction_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?)
|
||||
{
|
||||
int accessFlags = $access_list.value;
|
||||
|
||||
int accessFlags = $access_or_restriction_list.value;
|
||||
Set<HiddenApiRestriction> hiddenApiRestrictions = $access_or_restriction_list.hiddenApiRestrictions;
|
||||
|
||||
if (!AccessFlags.STATIC.isSet(accessFlags) && $field_initial_value.encodedValue != null) {
|
||||
throw new SemanticException(input, "Initial field values can only be specified for static fields.");
|
||||
}
|
||||
|
||||
$field = dexBuilder.internField(classType, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type, $access_list.value,
|
||||
$field_initial_value.encodedValue, $annotations.annotations, ImmutableSet.of());
|
||||
$field = dexBuilder.internField(classType, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type, accessFlags,
|
||||
$field_initial_value.encodedValue, $annotations.annotations, hiddenApiRestrictions);
|
||||
};
|
||||
|
||||
|
||||
@ -363,13 +408,15 @@ method returns[BuilderMethod ret]
|
||||
$method::methodParameterRegisters = 0;
|
||||
int accessFlags = 0;
|
||||
$method::isStatic = false;
|
||||
Set<HiddenApiRestriction> hiddenApiRestrictions = null;
|
||||
}
|
||||
:
|
||||
^(I_METHOD
|
||||
method_name_and_prototype
|
||||
access_list
|
||||
access_or_restriction_list
|
||||
{
|
||||
accessFlags = $access_list.value;
|
||||
accessFlags = $access_or_restriction_list.value;
|
||||
hiddenApiRestrictions = $access_or_restriction_list.hiddenApiRestrictions;
|
||||
$method::isStatic = AccessFlags.STATIC.isSet(accessFlags);
|
||||
$method::methodParameterRegisters =
|
||||
MethodUtil.getParameterRegisterCount($method_name_and_prototype.parameters, $method::isStatic);
|
||||
@ -467,7 +514,7 @@ method returns[BuilderMethod ret]
|
||||
$method_name_and_prototype.returnType,
|
||||
accessFlags,
|
||||
$annotations.annotations,
|
||||
ImmutableSet.of(),
|
||||
hiddenApiRestrictions,
|
||||
methodImplementation);
|
||||
};
|
||||
|
||||
|
@ -38,8 +38,8 @@ import org.antlr.runtime.TokenSource;
|
||||
import org.antlr.runtime.tree.CommonTree;
|
||||
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
||||
import org.jf.dexlib2.Opcodes;
|
||||
import org.jf.dexlib2.dexbacked.DexBackedClassDef;
|
||||
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.jf.dexlib2.writer.builder.DexBuilder;
|
||||
import org.jf.dexlib2.writer.io.MemoryDataStore;
|
||||
|
||||
@ -49,11 +49,11 @@ import java.io.StringReader;
|
||||
|
||||
public class SmaliTestUtils {
|
||||
|
||||
public static ClassDef compileSmali(String smaliText) throws RecognitionException, IOException {
|
||||
public static DexBackedClassDef compileSmali(String smaliText) throws RecognitionException, IOException {
|
||||
return compileSmali(smaliText, 15);
|
||||
}
|
||||
|
||||
public static ClassDef compileSmali(String smaliText, int apiLevel)
|
||||
public static DexBackedClassDef compileSmali(String smaliText, int apiLevel)
|
||||
throws RecognitionException, IOException {
|
||||
CommonTokenStream tokens;
|
||||
LexerErrorInterface lexer;
|
||||
|
@ -470,6 +470,11 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
|
||||
return newToken(ACCESS_SPEC);
|
||||
}
|
||||
|
||||
"whitelist" | "greylist" | "blacklist" | "greylist-max-o" | "greylist-max-p" | "greylist-max-q" |
|
||||
"core-platform-api" {
|
||||
return newToken(HIDDENAPI_RESTRICTION);
|
||||
}
|
||||
|
||||
"no-error" | "generic-error" | "no-such-class" | "no-such-field" | "no-such-method" | "illegal-class-access" |
|
||||
"illegal-field-access" | "illegal-method-access" | "class-change-error" | "instantiation-error" {
|
||||
return newToken(VERIFICATION_ERROR_TYPE);
|
||||
|
Loading…
x
Reference in New Issue
Block a user