mirror of
https://github.com/revanced/smali.git
synced 2025-05-04 08:34:25 +02:00
Add initial support for allowing assembly of odex instructions
Initially, only throw-verification-error is supported
This commit is contained in:
parent
bbe539f2d2
commit
94e5a39ad2
@ -28,6 +28,8 @@
|
||||
|
||||
package org.jf.dexlib.Code;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public enum VerificationErrorType {
|
||||
None(0, "no-error"),
|
||||
Generic(1, "generic-error"),
|
||||
@ -40,6 +42,16 @@ public enum VerificationErrorType {
|
||||
ClassChange(8, "class-change-error"),
|
||||
Instantiation(9, "instantiation-error");
|
||||
|
||||
private static HashMap<String, VerificationErrorType> verificationErrorTypesByName;
|
||||
|
||||
static {
|
||||
verificationErrorTypesByName = new HashMap<String, VerificationErrorType>();
|
||||
|
||||
for (VerificationErrorType verificationErrorType: VerificationErrorType.values()) {
|
||||
verificationErrorTypesByName.put(verificationErrorType.getName(), verificationErrorType);
|
||||
}
|
||||
}
|
||||
|
||||
private int value;
|
||||
private String name;
|
||||
private VerificationErrorType(int value, String name) {
|
||||
@ -55,6 +67,10 @@ public enum VerificationErrorType {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static VerificationErrorType fromString(String validationErrorType) {
|
||||
return verificationErrorTypesByName.get(validationErrorType);
|
||||
}
|
||||
|
||||
public static VerificationErrorType getValidationErrorType(int validationErrorType) {
|
||||
switch (validationErrorType) {
|
||||
case 0:
|
||||
|
@ -93,6 +93,7 @@ tokens {
|
||||
I_STATEMENT_FORMAT11n;
|
||||
I_STATEMENT_FORMAT11x;
|
||||
I_STATEMENT_FORMAT12x;
|
||||
I_STATEMENT_FORMAT20bc;
|
||||
I_STATEMENT_FORMAT20t;
|
||||
I_STATEMENT_FORMAT21c_TYPE;
|
||||
I_STATEMENT_FORMAT21c_FIELD;
|
||||
@ -137,11 +138,16 @@ import org.jf.dexlib.Code.Format.*;
|
||||
|
||||
@members {
|
||||
private boolean verboseErrors = false;
|
||||
private boolean allowOdex = false;
|
||||
|
||||
public void setVerboseErrors(boolean verboseErrors) {
|
||||
this.verboseErrors = verboseErrors;
|
||||
}
|
||||
|
||||
public void setAllowOdex(boolean allowOdex) {
|
||||
this.allowOdex = allowOdex;
|
||||
}
|
||||
|
||||
public String getErrorMessage(RecognitionException e,
|
||||
String[] tokenNames) {
|
||||
|
||||
@ -594,6 +600,9 @@ register_list
|
||||
register_range
|
||||
: REGISTER (DOTDOT REGISTER)? -> ^(I_REGISTER_RANGE[$start, "I_REGISTER_RANGE"] REGISTER REGISTER?);
|
||||
|
||||
verification_error_reference
|
||||
: CLASS_DESCRIPTOR | fully_qualified_field | fully_qualified_method;
|
||||
|
||||
catch_directive
|
||||
: CATCH_DIRECTIVE nonvoid_type_descriptor OPEN_BRACE from=label_ref_or_offset DOTDOT to=label_ref_or_offset CLOSE_BRACE using=label_ref_or_offset
|
||||
-> ^(I_CATCH[$start, "I_CATCH"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] nonvoid_type_descriptor $from $to $using);
|
||||
@ -686,10 +695,13 @@ instruction returns [int size]
|
||||
instruction_format12x REGISTER COMMA REGISTER {$size = Format.Format12x.size;}
|
||||
-> ^(I_STATEMENT_FORMAT12x[$start, "I_STATEMENT_FORMAT12x"] instruction_format12x REGISTER REGISTER)
|
||||
| //e.g. throw-verification-error generic-error, Lsome/class;
|
||||
INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE COMMA (CLASS_DESCRIPTOR | fully_qualified_field | fully_qualified_method)
|
||||
INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE COMMA verification_error_reference {$size += Format.Format20bc.size;}
|
||||
{
|
||||
throwOdexedInstructionException(input, $INSTRUCTION_FORMAT20bc.text);
|
||||
if (!allowOdex) {
|
||||
throwOdexedInstructionException(input, $INSTRUCTION_FORMAT20bc.text);
|
||||
}
|
||||
}
|
||||
-> ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE verification_error_reference)
|
||||
| //e.g. goto/16 endloop:
|
||||
INSTRUCTION_FORMAT20t label_ref_or_offset {$size = Format.Format20t.size;}
|
||||
-> ^(I_STATEMENT_FORMAT20t[$start, "I_STATEMENT_FORMAT20t"] INSTRUCTION_FORMAT20t label_ref_or_offset)
|
||||
@ -704,7 +716,7 @@ instruction returns [int size]
|
||||
| //e.g. const-string v1 "Hello World!"
|
||||
INSTRUCTION_FORMAT21c_STRING REGISTER COMMA STRING_LITERAL {$size = Format.Format21c.size;}
|
||||
-> ^(I_STATEMENT_FORMAT21c_STRING[$start, "I_STATEMENT_FORMAT21c_STRING"] INSTRUCTION_FORMAT21c_STRING REGISTER STRING_LITERAL)
|
||||
| //e.g. const-class v2 org/jf/HelloWorld2/HelloWorld2
|
||||
| //e.g. const-class v2 Lorg/jf/HelloWorld2/HelloWorld2;
|
||||
INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA reference_type_descriptor {$size = Format.Format21c.size;}
|
||||
-> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor)
|
||||
| //e.g. const/high16 v1, 1234
|
||||
|
@ -914,6 +914,26 @@ register_range[int totalMethodRegisters, int methodParameterRegisters] returns[i
|
||||
}
|
||||
;
|
||||
|
||||
verification_error_reference returns[Item item]
|
||||
: CLASS_DESCRIPTOR
|
||||
{
|
||||
$item = TypeIdItem.internTypeIdItem(dexFile, $start.getText());
|
||||
}
|
||||
| fully_qualified_field
|
||||
{
|
||||
$item = $fully_qualified_field.fieldIdItem;
|
||||
}
|
||||
| fully_qualified_method
|
||||
{
|
||||
$item = $fully_qualified_method.methodIdItem;
|
||||
};
|
||||
|
||||
verification_error_type returns[VerificationErrorType verificationErrorType]
|
||||
: VERIFICATION_ERROR_TYPE
|
||||
{
|
||||
$verificationErrorType = VerificationErrorType.fromString($VERIFICATION_ERROR_TYPE.text);
|
||||
};
|
||||
|
||||
instruction[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters]
|
||||
: //e.g. goto endloop:
|
||||
{$outRegisters = 0;}
|
||||
@ -959,6 +979,16 @@ instruction[int totalMethodRegisters, int methodParameterRegisters, List<Instruc
|
||||
|
||||
$instructions.add(new Instruction12x(opcode, regA, regB));
|
||||
}
|
||||
| //e.g. throw-verification-error generic-error, Lsome/class;
|
||||
^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc verification_error_type verification_error_reference)
|
||||
{
|
||||
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT20bc.text);
|
||||
|
||||
VerificationErrorType verificationErrorType = $verification_error_type.verificationErrorType;
|
||||
Item referencedItem = $verification_error_reference.item;
|
||||
|
||||
$instructions.add(new Instruction20bc(opcode, verificationErrorType, referencedItem));
|
||||
}
|
||||
| //e.g. goto/16 endloop:
|
||||
^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t offset_or_label)
|
||||
{
|
||||
|
@ -98,6 +98,7 @@ public class main {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean allowOdex = false;
|
||||
boolean sort = false;
|
||||
boolean fixStringConst = true;
|
||||
boolean fixGoto = true;
|
||||
@ -132,6 +133,9 @@ public class main {
|
||||
case 'o':
|
||||
outputDexFile = commandLine.getOptionValue("o");
|
||||
break;
|
||||
case 'x':
|
||||
allowOdex = true;
|
||||
break;
|
||||
case 'D':
|
||||
dumpFileName = commandLine.getOptionValue("D", outputDexFile + ".dump");
|
||||
break;
|
||||
@ -185,7 +189,7 @@ public class main {
|
||||
boolean errors = false;
|
||||
|
||||
for (File file: filesToProcess) {
|
||||
if (!assembleSmaliFile(file, dexFile, verboseErrors, oldLexer, printTokens)) {
|
||||
if (!assembleSmaliFile(file, dexFile, verboseErrors, oldLexer, printTokens, allowOdex)) {
|
||||
errors = true;
|
||||
}
|
||||
}
|
||||
@ -262,7 +266,7 @@ public class main {
|
||||
}
|
||||
|
||||
private static boolean assembleSmaliFile(File smaliFile, DexFile dexFile, boolean verboseErrors, boolean oldLexer,
|
||||
boolean printTokens)
|
||||
boolean printTokens, boolean allowOdex)
|
||||
throws Exception {
|
||||
CommonTokenStream tokens;
|
||||
|
||||
@ -300,6 +304,7 @@ public class main {
|
||||
|
||||
smaliParser parser = new smaliParser(tokens);
|
||||
parser.setVerboseErrors(verboseErrors);
|
||||
parser.setAllowOdex(allowOdex);
|
||||
|
||||
smaliParser.smali_file_return result = parser.smali_file();
|
||||
|
||||
@ -374,6 +379,10 @@ public class main {
|
||||
.withArgName("FILE")
|
||||
.create("o");
|
||||
|
||||
Option allowOdexOption = OptionBuilder.withLongOpt("allow-odex-instructions")
|
||||
.withDescription("allow odex instructions to be compiled into the dex file")
|
||||
.create("x");
|
||||
|
||||
Option dumpOption = OptionBuilder.withLongOpt("dump-to")
|
||||
.withDescription("additionally writes a dump of written dex file to FILE (<dexfile>.dump by default)")
|
||||
.hasOptionalArg()
|
||||
@ -407,6 +416,7 @@ public class main {
|
||||
basicOptions.addOption(versionOption);
|
||||
basicOptions.addOption(helpOption);
|
||||
basicOptions.addOption(outputOption);
|
||||
basicOptions.addOption(allowOdexOption);
|
||||
|
||||
debugOptions.addOption(dumpOption);
|
||||
debugOptions.addOption(sortOption);
|
||||
|
Loading…
x
Reference in New Issue
Block a user