1/* 2 * [The "BSD licence"] 3 * Copyright (c) 2010 Ben Gruver 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29tree grammar smaliTreeWalker; 30 31options { 32 tokenVocab=smaliParser; 33 ASTLabelType=CommonTree; 34} 35 36@header { 37package org.jf.smali; 38 39import com.google.common.collect.ImmutableSortedMap; 40import java.util.HashMap; 41import java.util.LinkedList; 42import java.util.regex.*; 43import java.lang.Float; 44import java.lang.Double; 45 46import org.jf.dexlib.*; 47import org.jf.dexlib.EncodedValue.*; 48import org.jf.dexlib.Util.*; 49import org.jf.dexlib.Code.*; 50import org.jf.dexlib.Code.Format.*; 51} 52 53@members { 54 public DexFile dexFile; 55 public TypeIdItem classType; 56 private boolean verboseErrors = false; 57 58 public void setVerboseErrors(boolean verboseErrors) { 59 this.verboseErrors = verboseErrors; 60 } 61 62 private byte parseRegister_nibble(String register, int totalMethodRegisters, int methodParameterRegisters) 63 throws SemanticException { 64 //register should be in the format "v12" 65 int val = Byte.parseByte(register.substring(1)); 66 if (register.charAt(0) == 'p') { 67 val = totalMethodRegisters - methodParameterRegisters + val; 68 } 69 if (val >= 2<<4) { 70 throw new SemanticException(input, "The maximum allowed register in this context is list of registers is v15"); 71 } 72 //the parser wouldn't have accepted a negative register, i.e. v-1, so we don't have to check for val<0; 73 return (byte)val; 74 } 75 76 //return a short, because java's byte is signed 77 private short parseRegister_byte(String register, int totalMethodRegisters, int methodParameterRegisters) 78 throws SemanticException { 79 //register should be in the format "v123" 80 int val = Short.parseShort(register.substring(1)); 81 if (register.charAt(0) == 'p') { 82 val = totalMethodRegisters - methodParameterRegisters + val; 83 } 84 if (val >= 2<<8) { 85 throw new SemanticException(input, "The maximum allowed register in this context is v255"); 86 } 87 return (short)val; 88 } 89 90 //return an int because java's short is signed 91 private int parseRegister_short(String register, int totalMethodRegisters, int methodParameterRegisters) 92 throws SemanticException { 93 //register should be in the format "v12345" 94 int val = Integer.parseInt(register.substring(1)); 95 if (register.charAt(0) == 'p') { 96 val = totalMethodRegisters - methodParameterRegisters + val; 97 } 98 if (val >= 2<<16) { 99 throw new SemanticException(input, "The maximum allowed register in this context is v65535"); 100 } 101 //the parser wouldn't accept a negative register, i.e. v-1, so we don't have to check for val<0; 102 return val; 103 } 104 105 public String getErrorMessage(RecognitionException e, String[] tokenNames) { 106 if ( e instanceof SemanticException ) { 107 return e.getMessage(); 108 } else { 109 return super.getErrorMessage(e, tokenNames); 110 } 111 } 112 113 public String getErrorHeader(RecognitionException e) { 114 return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]"; 115 } 116} 117 118 119 120smali_file 121 : ^(I_CLASS_DEF header methods fields annotations) 122 { 123 AnnotationDirectoryItem annotationDirectoryItem = null; 124 ClassDefItem classDefItem = null; 125 ClassDataItem classDataItem = null; 126 127 if ($methods.methodAnnotations != null || 128 $methods.parameterAnnotations != null || 129 $fields.fieldAnnotations != null || 130 $annotations.annotationSetItem != null) { 131 annotationDirectoryItem = AnnotationDirectoryItem.internAnnotationDirectoryItem( 132 dexFile, 133 $annotations.annotationSetItem, 134 $fields.fieldAnnotations, 135 $methods.methodAnnotations, 136 $methods.parameterAnnotations); 137 } 138 139 if ($fields.staticFields.size() != 0 || $fields.instanceFields.size() != 0 || 140 $methods.directMethods.size() != 0 || $methods.virtualMethods.size()!= 0) { 141 classDataItem = ClassDataItem.internClassDataItem(dexFile, $fields.staticFields, $fields.instanceFields, 142 $methods.directMethods, $methods.virtualMethods); 143 } 144 145 classDefItem = ClassDefItem.internClassDefItem(dexFile, $header.classType, $header.accessFlags, 146 $header.superType, $header.implementsList, $header.sourceSpec, annotationDirectoryItem, 147 classDataItem, $fields.staticFieldInitialValues); 148 }; 149 catch [Exception ex] { 150 if (verboseErrors) { 151 ex.printStackTrace(System.err); 152 } 153 reportError(new SemanticException(input, ex)); 154 } 155 156 157header returns[TypeIdItem classType, int accessFlags, TypeIdItem superType, TypeListItem implementsList, StringIdItem sourceSpec] 158: class_spec super_spec? implements_list source_spec 159 { 160 classType = $class_spec.type; 161 $classType = classType; 162 $accessFlags = $class_spec.accessFlags; 163 $superType = $super_spec.type; 164 $implementsList = $implements_list.implementsList; 165 $sourceSpec = $source_spec.source; 166 }; 167 168 169class_spec returns[TypeIdItem type, int accessFlags] 170 : class_type_descriptor access_list 171 { 172 $type = $class_type_descriptor.type; 173 $accessFlags = $access_list.value; 174 }; 175 176super_spec returns[TypeIdItem type] 177 : ^(I_SUPER class_type_descriptor) 178 { 179 $type = $class_type_descriptor.type; 180 }; 181 182 183implements_spec returns[TypeIdItem type] 184 : ^(I_IMPLEMENTS class_type_descriptor) 185 { 186 $type = $class_type_descriptor.type; 187 }; 188 189implements_list returns[TypeListItem implementsList] 190@init { List<TypeIdItem> typeList; } 191 : {typeList = new LinkedList<TypeIdItem>();} 192 (implements_spec {typeList.add($implements_spec.type);} )* 193 { 194 if (typeList.size() > 0) { 195 $implementsList = TypeListItem.internTypeListItem(dexFile, typeList); 196 } else { 197 $implementsList = null; 198 } 199 }; 200 201source_spec returns[StringIdItem source] 202 : {$source = null;} 203 ^(I_SOURCE string_literal {$source = StringIdItem.internStringIdItem(dexFile, $string_literal.value);}) 204 | /*epsilon*/; 205 206 207 208access_list returns [int value] 209 @init 210 { 211 $value = 0; 212 } 213 : ^(I_ACCESS_LIST 214 ( 215 ACCESS_SPEC 216 { 217 $value |= AccessFlags.getAccessFlag($ACCESS_SPEC.getText()).getValue(); 218 } 219 )*); 220 221 222fields returns[List<ClassDataItem.EncodedField> staticFields, List<ClassDataItem.EncodedField> instanceFields, 223 List<ClassDefItem.StaticFieldInitializer> staticFieldInitialValues, List<AnnotationDirectoryItem.FieldAnnotation> fieldAnnotations] 224 @init 225 { 226 $staticFields = new LinkedList<ClassDataItem.EncodedField>(); 227 $instanceFields = new LinkedList<ClassDataItem.EncodedField>(); 228 $staticFieldInitialValues = new ArrayList<ClassDefItem.StaticFieldInitializer>(); 229 } 230 : ^(I_FIELDS 231 (field 232 { 233 if ($field.encodedField.isStatic()) { 234 $staticFields.add($field.encodedField); 235 $staticFieldInitialValues.add(new ClassDefItem.StaticFieldInitializer( 236 $field.encodedValue, $field.encodedField)); 237 } else { 238 $instanceFields.add($field.encodedField); 239 } 240 if ($field.fieldAnnotationSet != null) { 241 if ($fieldAnnotations == null) { 242 $fieldAnnotations = new LinkedList<AnnotationDirectoryItem.FieldAnnotation>(); 243 } 244 AnnotationDirectoryItem.FieldAnnotation fieldAnnotation = new AnnotationDirectoryItem.FieldAnnotation( 245 $field.encodedField.field, $field.fieldAnnotationSet); 246 $fieldAnnotations.add(fieldAnnotation); 247 } 248 })*); 249 250methods returns[List<ClassDataItem.EncodedMethod> directMethods, 251 List<ClassDataItem.EncodedMethod> virtualMethods, 252 List<AnnotationDirectoryItem.MethodAnnotation> methodAnnotations, 253 List<AnnotationDirectoryItem.ParameterAnnotation> parameterAnnotations] 254 @init 255 { 256 $directMethods = new LinkedList<ClassDataItem.EncodedMethod>(); 257 $virtualMethods = new LinkedList<ClassDataItem.EncodedMethod>(); 258 } 259 : ^(I_METHODS 260 (method 261 { 262 if ($method.encodedMethod.isDirect()) { 263 $directMethods.add($method.encodedMethod); 264 } else { 265 $virtualMethods.add($method.encodedMethod); 266 } 267 if ($method.methodAnnotationSet != null) { 268 if ($methodAnnotations == null) { 269 $methodAnnotations = new LinkedList<AnnotationDirectoryItem.MethodAnnotation>(); 270 } 271 AnnotationDirectoryItem.MethodAnnotation methodAnnotation = 272 new AnnotationDirectoryItem.MethodAnnotation($method.encodedMethod.method, $method.methodAnnotationSet); 273 $methodAnnotations.add(methodAnnotation); 274 } 275 if ($method.parameterAnnotationSets != null) { 276 if ($parameterAnnotations == null) { 277 $parameterAnnotations = new LinkedList<AnnotationDirectoryItem.ParameterAnnotation>(); 278 } 279 AnnotationDirectoryItem.ParameterAnnotation parameterAnnotation = 280 new AnnotationDirectoryItem.ParameterAnnotation($method.encodedMethod.method, 281 $method.parameterAnnotationSets); 282 $parameterAnnotations.add(parameterAnnotation); 283 } 284 })*); 285 286field returns [ClassDataItem.EncodedField encodedField, EncodedValue encodedValue, AnnotationSetItem fieldAnnotationSet] 287 :^(I_FIELD SIMPLE_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?) 288 { 289 StringIdItem memberName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); 290 TypeIdItem fieldType = $nonvoid_type_descriptor.type; 291 292 FieldIdItem fieldIdItem = FieldIdItem.internFieldIdItem(dexFile, classType, fieldType, memberName); 293 $encodedField = new ClassDataItem.EncodedField(fieldIdItem, $access_list.value); 294 295 if ($field_initial_value.encodedValue != null) { 296 if (!$encodedField.isStatic()) { 297 throw new SemanticException(input, "Initial field values can only be specified for static fields."); 298 } 299 300 $encodedValue = $field_initial_value.encodedValue; 301 } else { 302 $encodedValue = null; 303 } 304 305 if ($annotations.annotationSetItem != null) { 306 $fieldAnnotationSet = $annotations.annotationSetItem; 307 } 308 }; 309 310 311field_initial_value returns[EncodedValue encodedValue] 312 : ^(I_FIELD_INITIAL_VALUE literal) {$encodedValue = $literal.encodedValue;} 313 | /*epsilon*/; 314 315literal returns[EncodedValue encodedValue] 316 : integer_literal { $encodedValue = new IntEncodedValue($integer_literal.value); } 317 | long_literal { $encodedValue = new LongEncodedValue($long_literal.value); } 318 | short_literal { $encodedValue = new ShortEncodedValue($short_literal.value); } 319 | byte_literal { $encodedValue = new ByteEncodedValue($byte_literal.value); } 320 | float_literal { $encodedValue = new FloatEncodedValue($float_literal.value); } 321 | double_literal { $encodedValue = new DoubleEncodedValue($double_literal.value); } 322 | char_literal { $encodedValue = new CharEncodedValue($char_literal.value); } 323 | string_literal { $encodedValue = new StringEncodedValue(StringIdItem.internStringIdItem(dexFile, $string_literal.value)); } 324 | bool_literal { $encodedValue = $bool_literal.value?BooleanEncodedValue.TrueValue:BooleanEncodedValue.FalseValue; } 325 | NULL_LITERAL { $encodedValue = NullEncodedValue.NullValue; } 326 | type_descriptor { $encodedValue = new TypeEncodedValue($type_descriptor.type); } 327 | array_literal { $encodedValue = new ArrayEncodedValue($array_literal.values); } 328 | subannotation { $encodedValue = new AnnotationEncodedValue($subannotation.annotationType, $subannotation.elementNames, $subannotation.elementValues); } 329 | field_literal { $encodedValue = new FieldEncodedValue($field_literal.value); } 330 | method_literal { $encodedValue = new MethodEncodedValue($method_literal.value); } 331 | enum_literal { $encodedValue = new EnumEncodedValue($enum_literal.value); }; 332 333 334//everything but string 335fixed_size_literal returns[byte[\] value] 336 : integer_literal { $value = LiteralTools.intToBytes($integer_literal.value); } 337 | long_literal { $value = LiteralTools.longToBytes($long_literal.value); } 338 | short_literal { $value = LiteralTools.shortToBytes($short_literal.value); } 339 | byte_literal { $value = new byte[] { $byte_literal.value }; } 340 | float_literal { $value = LiteralTools.floatToBytes($float_literal.value); } 341 | double_literal { $value = LiteralTools.doubleToBytes($double_literal.value); } 342 | char_literal { $value = LiteralTools.charToBytes($char_literal.value); } 343 | bool_literal { $value = LiteralTools.boolToBytes($bool_literal.value); }; 344 345//everything but string 346fixed_64bit_literal returns[long value] 347 : integer_literal { $value = $integer_literal.value; } 348 | long_literal { $value = $long_literal.value; } 349 | short_literal { $value = $short_literal.value; } 350 | byte_literal { $value = $byte_literal.value; } 351 | float_literal { $value = Float.floatToRawIntBits($float_literal.value); } 352 | double_literal { $value = Double.doubleToRawLongBits($double_literal.value); } 353 | char_literal { $value = $char_literal.value; } 354 | bool_literal { $value = $bool_literal.value?1:0; }; 355 356//everything but string and double 357//long is allowed, but it must fit into an int 358fixed_32bit_literal returns[int value] 359 : integer_literal { $value = $integer_literal.value; } 360 | long_literal { LiteralTools.checkInt($long_literal.value); $value = (int)$long_literal.value; } 361 | short_literal { $value = $short_literal.value; } 362 | byte_literal { $value = $byte_literal.value; } 363 | float_literal { $value = Float.floatToRawIntBits($float_literal.value); } 364 | char_literal { $value = $char_literal.value; } 365 | bool_literal { $value = $bool_literal.value?1:0; }; 366 367array_elements returns[List<byte[\]> values] 368 : {$values = new ArrayList<byte[]>();} 369 ^(I_ARRAY_ELEMENTS 370 (fixed_size_literal 371 { 372 $values.add($fixed_size_literal.value); 373 })*); 374 375packed_switch_target_count returns[int targetCount] 376 : I_PACKED_SWITCH_TARGET_COUNT {$targetCount = Integer.parseInt($I_PACKED_SWITCH_TARGET_COUNT.text);}; 377 378packed_switch_targets[int baseAddress] returns[int[\] targets] 379 : 380 ^(I_PACKED_SWITCH_TARGETS 381 packed_switch_target_count 382 { 383 int targetCount = $packed_switch_target_count.targetCount; 384 $targets = new int[targetCount]; 385 int targetsPosition = 0; 386 } 387 388 (offset_or_label 389 { 390 $targets[targetsPosition++] = ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress; 391 })* 392 ); 393 394sparse_switch_target_count returns[int targetCount] 395 : I_SPARSE_SWITCH_TARGET_COUNT {$targetCount = Integer.parseInt($I_SPARSE_SWITCH_TARGET_COUNT.text);}; 396 397sparse_switch_keys[int targetCount] returns[int[\] keys] 398 : { 399 $keys = new int[$targetCount]; 400 int keysPosition = 0; 401 } 402 ^(I_SPARSE_SWITCH_KEYS 403 (fixed_32bit_literal 404 { 405 $keys[keysPosition++] = $fixed_32bit_literal.value; 406 })* 407 ); 408 409 410sparse_switch_targets[int baseAddress, int targetCount] returns[int[\] targets] 411 : { 412 $targets = new int[$targetCount]; 413 int targetsPosition = 0; 414 } 415 ^(I_SPARSE_SWITCH_TARGETS 416 (offset_or_label 417 { 418 $targets[targetsPosition++] = ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress; 419 })* 420 ); 421 422method returns[ClassDataItem.EncodedMethod encodedMethod, 423 AnnotationSetItem methodAnnotationSet, 424 AnnotationSetRefList parameterAnnotationSets] 425 scope 426 { 427 HashMap<String, Integer> labels; 428 TryListBuilder tryList; 429 int currentAddress; 430 DebugInfoBuilder debugInfo; 431 HashMap<Integer, Integer> packedSwitchDeclarations; 432 HashMap<Integer, Integer> sparseSwitchDeclarations; 433 } 434 @init 435 { 436 MethodIdItem methodIdItem = null; 437 int totalMethodRegisters = 0; 438 int methodParameterRegisters = 0; 439 int accessFlags = 0; 440 boolean isStatic = false; 441 } 442 : { 443 $method::labels = new HashMap<String, Integer>(); 444 $method::tryList = new TryListBuilder(); 445 $method::currentAddress = 0; 446 $method::debugInfo = new DebugInfoBuilder(); 447 $method::packedSwitchDeclarations = new HashMap<Integer, Integer>(); 448 $method::sparseSwitchDeclarations = new HashMap<Integer, Integer>(); 449 } 450 ^(I_METHOD 451 method_name_and_prototype 452 access_list 453 { 454 methodIdItem = $method_name_and_prototype.methodIdItem; 455 accessFlags = $access_list.value; 456 isStatic = (accessFlags & AccessFlags.STATIC.getValue()) != 0; 457 methodParameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); 458 if (!isStatic) { 459 methodParameterRegisters++; 460 } 461 } 462 (registers_directive 463 { 464 if ($registers_directive.isLocalsDirective) { 465 totalMethodRegisters = $registers_directive.registers + methodParameterRegisters; 466 } else { 467 totalMethodRegisters = $registers_directive.registers; 468 } 469 } 470 )? 471 labels 472 packed_switch_declarations 473 sparse_switch_declarations 474 statements[totalMethodRegisters, methodParameterRegisters] 475 catches 476 parameters 477 ordered_debug_directives[totalMethodRegisters, methodParameterRegisters] 478 annotations 479 ) 480 { 481 Pair<List<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>> temp = $method::tryList.encodeTries(); 482 List<CodeItem.TryItem> tries = temp.first; 483 List<CodeItem.EncodedCatchHandler> handlers = temp.second; 484 485 DebugInfoItem debugInfoItem = $method::debugInfo.encodeDebugInfo(dexFile); 486 487 CodeItem codeItem; 488 489 boolean isAbstract = false; 490 boolean isNative = false; 491 492 if ((accessFlags & AccessFlags.ABSTRACT.getValue()) != 0) { 493 isAbstract = true; 494 } else if ((accessFlags & AccessFlags.NATIVE.getValue()) != 0) { 495 isNative = true; 496 } 497 498 if ($statements.instructions.size() == 0) { 499 if (!isAbstract && !isNative) { 500 throw new SemanticException(input, $I_METHOD, "A non-abstract/non-native method must have at least 1 instruction"); 501 } 502 503 String methodType; 504 if (isAbstract) { 505 methodType = "an abstract"; 506 } else { 507 methodType = "a native"; 508 } 509 510 if ($registers_directive.start != null) { 511 if ($registers_directive.isLocalsDirective) { 512 throw new SemanticException(input, $registers_directive.start, "A .locals directive is not valid in \%s method", methodType); 513 } else { 514 throw new SemanticException(input, $registers_directive.start, "A .registers directive is not valid in \%s method", methodType); 515 } 516 } 517 518 if ($method::labels.size() > 0) { 519 throw new SemanticException(input, $I_METHOD, "Labels cannot be present in \%s method", methodType); 520 } 521 522 if ((tries != null && tries.size() > 0) || (handlers != null && handlers.size() > 0)) { 523 throw new SemanticException(input, $I_METHOD, "try/catch blocks cannot be present in \%s method", methodType); 524 } 525 526 if (debugInfoItem != null) { 527 throw new SemanticException(input, $I_METHOD, "debug directives cannot be present in \%s method", methodType); 528 } 529 530 codeItem = null; 531 } else { 532 if (isAbstract) { 533 throw new SemanticException(input, $I_METHOD, "An abstract method cannot have any instructions"); 534 } 535 if (isNative) { 536 throw new SemanticException(input, $I_METHOD, "A native method cannot have any instructions"); 537 } 538 539 if ($registers_directive.start == null) { 540 throw new SemanticException(input, $I_METHOD, "A .registers or .locals directive must be present for a non-abstract/non-final method"); 541 } 542 543 if (totalMethodRegisters < methodParameterRegisters) { 544 throw new SemanticException(input, $registers_directive.start, "This method requires at least " + 545 Integer.toString(methodParameterRegisters) + 546 " registers, for the method parameters"); 547 } 548 549 int methodParameterCount = methodIdItem.getPrototype().getParameterRegisterCount(); 550 if ($method::debugInfo.getParameterNameCount() > methodParameterCount) { 551 throw new SemanticException(input, $I_METHOD, "Too many parameter names specified. This method only has " + 552 Integer.toString(methodParameterCount) + 553 " parameters."); 554 } 555 556 codeItem = CodeItem.internCodeItem(dexFile, 557 totalMethodRegisters, 558 methodParameterRegisters, 559 $statements.maxOutRegisters, 560 debugInfoItem, 561 $statements.instructions, 562 tries, 563 handlers); 564 } 565 566 $encodedMethod = new ClassDataItem.EncodedMethod(methodIdItem, accessFlags, codeItem); 567 568 if ($annotations.annotationSetItem != null) { 569 $methodAnnotationSet = $annotations.annotationSetItem; 570 } 571 572 if ($parameters.parameterAnnotations != null) { 573 $parameterAnnotationSets = $parameters.parameterAnnotations; 574 } 575 }; 576 577method_prototype returns[ProtoIdItem protoIdItem] 578 : ^(I_METHOD_PROTOTYPE ^(I_METHOD_RETURN_TYPE type_descriptor) field_type_list) 579 { 580 TypeIdItem returnType = $type_descriptor.type; 581 List<TypeIdItem> parameterTypes = $field_type_list.types; 582 TypeListItem parameterTypeListItem = null; 583 if (parameterTypes != null && parameterTypes.size() > 0) { 584 parameterTypeListItem = TypeListItem.internTypeListItem(dexFile, parameterTypes); 585 } 586 587 $protoIdItem = ProtoIdItem.internProtoIdItem(dexFile, returnType, parameterTypeListItem); 588 }; 589 590method_name_and_prototype returns[MethodIdItem methodIdItem] 591 : SIMPLE_NAME method_prototype 592 { 593 String methodNameString = $SIMPLE_NAME.text; 594 StringIdItem methodName = StringIdItem.internStringIdItem(dexFile, methodNameString); 595 ProtoIdItem protoIdItem = $method_prototype.protoIdItem; 596 597 $methodIdItem = MethodIdItem.internMethodIdItem(dexFile, classType, protoIdItem, methodName); 598 }; 599 600field_type_list returns[List<TypeIdItem> types] 601 @init 602 { 603 $types = new LinkedList<TypeIdItem>(); 604 } 605 : ( 606 nonvoid_type_descriptor 607 { 608 $types.add($nonvoid_type_descriptor.type); 609 } 610 )*; 611 612 613fully_qualified_method returns[MethodIdItem methodIdItem] 614 : reference_type_descriptor SIMPLE_NAME method_prototype 615 { 616 TypeIdItem classType = $reference_type_descriptor.type; 617 StringIdItem methodName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); 618 ProtoIdItem prototype = $method_prototype.protoIdItem; 619 $methodIdItem = MethodIdItem.internMethodIdItem(dexFile, classType, prototype, methodName); 620 }; 621 622fully_qualified_field returns[FieldIdItem fieldIdItem] 623 : reference_type_descriptor SIMPLE_NAME nonvoid_type_descriptor 624 { 625 TypeIdItem classType = $reference_type_descriptor.type; 626 StringIdItem fieldName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); 627 TypeIdItem fieldType = $nonvoid_type_descriptor.type; 628 $fieldIdItem = FieldIdItem.internFieldIdItem(dexFile, classType, fieldType, fieldName); 629 }; 630 631registers_directive returns[boolean isLocalsDirective, int registers] 632 : {$registers = 0;} 633 ^(( I_REGISTERS {$isLocalsDirective = false;} 634 | I_LOCALS {$isLocalsDirective = true;} 635 ) 636 short_integral_literal {$registers = $short_integral_literal.value;} 637 ); 638 639labels 640 : ^(I_LABELS label_def*); 641 642label_def 643 : ^(I_LABEL SIMPLE_NAME address) 644 { 645 if ($method::labels.containsKey($SIMPLE_NAME.text)) { 646 throw new SemanticException(input, $I_LABEL, "Label " + $SIMPLE_NAME.text + " has multiple defintions."); 647 } 648 649 $method::labels.put($SIMPLE_NAME.text, $address.address); 650 }; 651 652packed_switch_declarations 653 : ^(I_PACKED_SWITCH_DECLARATIONS packed_switch_declaration*); 654packed_switch_declaration 655 : ^(I_PACKED_SWITCH_DECLARATION address offset_or_label_absolute[$address.address]) 656 { 657 int switchDataAddress = $offset_or_label_absolute.address; 658 if ((switchDataAddress \% 2) != 0) { 659 switchDataAddress++; 660 } 661 if (!$method::packedSwitchDeclarations.containsKey(switchDataAddress)) { 662 $method::packedSwitchDeclarations.put(switchDataAddress, $address.address); 663 } 664 }; 665 666sparse_switch_declarations 667 : ^(I_SPARSE_SWITCH_DECLARATIONS sparse_switch_declaration*); 668sparse_switch_declaration 669 : ^(I_SPARSE_SWITCH_DECLARATION address offset_or_label_absolute[$address.address]) 670 { 671 int switchDataAddress = $offset_or_label_absolute.address; 672 if ((switchDataAddress \% 2) != 0) { 673 switchDataAddress++; 674 } 675 if (!$method::sparseSwitchDeclarations.containsKey(switchDataAddress)) { 676 $method::sparseSwitchDeclarations.put(switchDataAddress, $address.address); 677 } 678 679 }; 680 681catches : ^(I_CATCHES catch_directive* catchall_directive*); 682 683catch_directive 684 : ^(I_CATCH address nonvoid_type_descriptor from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address] 685 using=offset_or_label_absolute[$address.address]) 686 { 687 TypeIdItem type = $nonvoid_type_descriptor.type; 688 int startAddress = $from.address; 689 int endAddress = $to.address; 690 int handlerAddress = $using.address; 691 692 $method::tryList.addHandler(type, startAddress, endAddress, handlerAddress); 693 }; 694 695catchall_directive 696 : ^(I_CATCHALL address from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address] 697 using=offset_or_label_absolute[$address.address]) 698 { 699 int startAddress = $from.address; 700 int endAddress = $to.address; 701 int handlerAddress = $using.address; 702 703 $method::tryList.addCatchAllHandler(startAddress, endAddress, handlerAddress); 704 }; 705 706address returns[int address] 707 : I_ADDRESS 708 { 709 $address = Integer.parseInt($I_ADDRESS.text); 710 }; 711 712parameters returns[AnnotationSetRefList parameterAnnotations] 713 @init 714 { 715 int parameterCount = 0; 716 List<AnnotationSetItem> annotationSetItems = new ArrayList<AnnotationSetItem>(); 717 } 718 : ^(I_PARAMETERS (parameter 719 { 720 if ($parameter.parameterAnnotationSet != null) { 721 while (annotationSetItems.size() < parameterCount) { 722 annotationSetItems.add(AnnotationSetItem.internAnnotationSetItem(dexFile, null)); 723 } 724 annotationSetItems.add($parameter.parameterAnnotationSet); 725 } 726 727 parameterCount++; 728 })* 729 ) 730 { 731 if (annotationSetItems.size() > 0) { 732 while (annotationSetItems.size() < parameterCount) { 733 annotationSetItems.add(AnnotationSetItem.internAnnotationSetItem(dexFile, null)); 734 } 735 $parameterAnnotations = AnnotationSetRefList.internAnnotationSetRefList(dexFile, annotationSetItems); 736 } 737 }; 738 739parameter returns[AnnotationSetItem parameterAnnotationSet] 740 : ^(I_PARAMETER (string_literal {$method::debugInfo.addParameterName($string_literal.value);} 741 | {$method::debugInfo.addParameterName(null);} 742 ) 743 annotations {$parameterAnnotationSet = $annotations.annotationSetItem;} 744 ); 745 746ordered_debug_directives[int totalMethodRegisters, int methodParameterRegisters] 747 : ^(I_ORDERED_DEBUG_DIRECTIVES 748 ( line 749 | local[$totalMethodRegisters, $methodParameterRegisters] 750 | end_local[$totalMethodRegisters, $methodParameterRegisters] 751 | restart_local[$totalMethodRegisters, $methodParameterRegisters] 752 | prologue 753 | epilogue 754 | source 755 )* 756 ); 757 758line 759 : ^(I_LINE integral_literal address) 760 { 761 $method::debugInfo.addLine($address.address, $integral_literal.value); 762 }; 763 764local[int totalMethodRegisters, int methodParameterRegisters] 765 : ^(I_LOCAL REGISTER SIMPLE_NAME nonvoid_type_descriptor string_literal? address) 766 { 767 int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 768 769 if ($string_literal.value != null) { 770 $method::debugInfo.addLocalExtended($address.address, registerNumber, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type.getTypeDescriptor(), $string_literal.value); 771 } else { 772 $method::debugInfo.addLocal($address.address, registerNumber, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type.getTypeDescriptor()); 773 } 774 }; 775 776end_local[int totalMethodRegisters, int methodParameterRegisters] 777 : ^(I_END_LOCAL REGISTER address) 778 { 779 int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 780 781 $method::debugInfo.addEndLocal($address.address, registerNumber); 782 }; 783 784restart_local[int totalMethodRegisters, int methodParameterRegisters] 785 : ^(I_RESTART_LOCAL REGISTER address) 786 { 787 int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 788 789 $method::debugInfo.addRestartLocal($address.address, registerNumber); 790 }; 791 792prologue 793 : ^(I_PROLOGUE address) 794 { 795 $method::debugInfo.addPrologue($address.address); 796 }; 797 798epilogue 799 : ^(I_EPILOGUE address) 800 { 801 $method::debugInfo.addEpilogue($address.address); 802 }; 803 804source 805 : ^(I_SOURCE string_literal address) 806 { 807 $method::debugInfo.addSetFile($address.address, $string_literal.value); 808 }; 809 810statements[int totalMethodRegisters, int methodParameterRegisters] returns[List<Instruction> instructions, int maxOutRegisters] 811 @init 812 { 813 $instructions = new LinkedList<Instruction>(); 814 $maxOutRegisters = 0; 815 } 816 : ^(I_STATEMENTS (instruction[$totalMethodRegisters, $methodParameterRegisters, $instructions] 817 { 818 $method::currentAddress += $instructions.get($instructions.size() - 1).getSize($method::currentAddress); 819 if ($maxOutRegisters < $instruction.outRegisters) { 820 $maxOutRegisters = $instruction.outRegisters; 821 } 822 })*); 823 824label_ref returns[int labelAddress] 825 : SIMPLE_NAME 826 { 827 Integer labelAdd = $method::labels.get($SIMPLE_NAME.text); 828 829 if (labelAdd == null) { 830 throw new SemanticException(input, $SIMPLE_NAME, "Label \"" + $SIMPLE_NAME.text + "\" is not defined."); 831 } 832 833 $labelAddress = labelAdd; 834 }; 835 836offset returns[int offsetValue] 837 : OFFSET 838 { 839 String offsetText = $OFFSET.text; 840 if (offsetText.charAt(0) == '+') { 841 offsetText = offsetText.substring(1); 842 } 843 $offsetValue = LiteralTools.parseInt(offsetText); 844 }; 845 846offset_or_label_absolute[int baseAddress] returns[int address] 847 : offset {$address = $offset.offsetValue + $baseAddress;} 848 | label_ref {$address = $label_ref.labelAddress;}; 849 850offset_or_label returns[int offsetValue] 851 : offset {$offsetValue = $offset.offsetValue;} 852 | label_ref {$offsetValue = $label_ref.labelAddress-$method::currentAddress;}; 853 854 855register_list[int totalMethodRegisters, int methodParameterRegisters] returns[byte[\] registers, byte registerCount] 856 @init 857 { 858 $registers = new byte[5]; 859 $registerCount = 0; 860 } 861 : ^(I_REGISTER_LIST 862 (REGISTER 863 { 864 if ($registerCount == 5) { 865 throw new SemanticException(input, $I_REGISTER_LIST, "A list of registers can only have a maximum of 5 registers. Use the <op>/range alternate opcode instead."); 866 } 867 $registers[$registerCount++] = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 868 })*); 869 870register_range[int totalMethodRegisters, int methodParameterRegisters] returns[int startRegister, int endRegister] 871 : ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?) 872 { 873 if ($startReg == null) { 874 $startRegister = 0; 875 $endRegister = -1; 876 } else { 877 $startRegister = parseRegister_short($startReg.text, $totalMethodRegisters, $methodParameterRegisters); 878 if ($endReg == null) { 879 $endRegister = $startRegister; 880 } else { 881 $endRegister = parseRegister_short($endReg.text, $totalMethodRegisters, $methodParameterRegisters); 882 } 883 884 int registerCount = $endRegister-$startRegister+1; 885 if (registerCount < 1) { 886 throw new SemanticException(input, $I_REGISTER_RANGE, "A register range must have the lower register listed first"); 887 } 888 } 889 } 890 ; 891 892verification_error_reference returns[Item item] 893 : CLASS_DESCRIPTOR 894 { 895 $item = TypeIdItem.internTypeIdItem(dexFile, $start.getText()); 896 } 897 | fully_qualified_field 898 { 899 $item = $fully_qualified_field.fieldIdItem; 900 } 901 | fully_qualified_method 902 { 903 $item = $fully_qualified_method.methodIdItem; 904 }; 905 906verification_error_type returns[VerificationErrorType verificationErrorType] 907 : VERIFICATION_ERROR_TYPE 908 { 909 $verificationErrorType = VerificationErrorType.fromString($VERIFICATION_ERROR_TYPE.text); 910 }; 911 912instruction[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 913 : insn_format10t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format10t.outRegisters; } 914 | insn_format10x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format10x.outRegisters; } 915 | insn_format11n[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format11n.outRegisters; } 916 | insn_format11x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format11x.outRegisters; } 917 | insn_format12x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format12x.outRegisters; } 918 | insn_format20bc[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format20bc.outRegisters; } 919 | insn_format20t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format20t.outRegisters; } 920 | insn_format21c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_field.outRegisters; } 921 | insn_format21c_string[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_string.outRegisters; } 922 | insn_format21c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_type.outRegisters; } 923 | insn_format21h[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21h.outRegisters; } 924 | insn_format21s[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21s.outRegisters; } 925 | insn_format21t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21t.outRegisters; } 926 | insn_format22b[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22b.outRegisters; } 927 | insn_format22c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22c_field.outRegisters; } 928 | insn_format22c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22c_type.outRegisters; } 929 | insn_format22s[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22s.outRegisters; } 930 | insn_format22t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22t.outRegisters; } 931 | insn_format22x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22x.outRegisters; } 932 | insn_format23x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format23x.outRegisters; } 933 | insn_format30t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format30t.outRegisters; } 934 | insn_format31c[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31c.outRegisters; } 935 | insn_format31i[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31i.outRegisters; } 936 | insn_format31t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31t.outRegisters; } 937 | insn_format32x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format32x.outRegisters; } 938 | insn_format35c_method[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format35c_method.outRegisters; } 939 | insn_format35c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format35c_type.outRegisters; } 940 | insn_format3rc_method[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format3rc_method.outRegisters; } 941 | insn_format3rc_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format3rc_type.outRegisters; } 942 | insn_format41c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format41c_type.outRegisters; } 943 | insn_format41c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format41c_field.outRegisters; } 944 | insn_format51l_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format51l_type.outRegisters; } 945 | insn_format52c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format52c_type.outRegisters; } 946 | insn_format52c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format52c_field.outRegisters; } 947 | insn_format5rc_method[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format5rc_method.outRegisters; } 948 | insn_format5rc_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format5rc_type.outRegisters; } 949 | insn_array_data_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_array_data_directive.outRegisters; } 950 | insn_packed_switch_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_packed_switch_directive.outRegisters; } 951 | insn_sparse_switch_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_sparse_switch_directive.outRegisters; }; 952 catch [Exception ex] { 953 reportError(new SemanticException(input, ex)); 954 recover(input, null); 955 } 956 957 958insn_format10t[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 959 : //e.g. goto endloop: 960 {$outRegisters = 0;} 961 ^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label) 962 { 963 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10t.text); 964 965 int addressOffset = $offset_or_label.offsetValue; 966 967 $instructions.add(new Instruction10t(opcode, addressOffset)); 968 }; 969 970insn_format10x[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 971 : //e.g. return 972 ^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x) 973 { 974 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10x.text); 975 $instructions.add(new Instruction10x(opcode)); 976 }; 977 978insn_format11n[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 979 : //e.g. const/4 v0, 5 980 ^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal) 981 { 982 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11n.text); 983 byte regA = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 984 985 short litB = $short_integral_literal.value; 986 LiteralTools.checkNibble(litB); 987 988 $instructions.add(new Instruction11n(opcode, regA, (byte)litB)); 989 }; 990 991insn_format11x[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 992 : //e.g. move-result-object v1 993 ^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER) 994 { 995 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11x.text); 996 short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 997 998 $instructions.add(new Instruction11x(opcode, regA)); 999 }; 1000 1001insn_format12x[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1002 : //e.g. move v1 v2 1003 ^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER) 1004 { 1005 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT12x.text); 1006 byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); 1007 byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); 1008 1009 $instructions.add(new Instruction12x(opcode, regA, regB)); 1010 }; 1011 1012insn_format20bc[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1013 : //e.g. throw-verification-error generic-error, Lsome/class; 1014 ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc verification_error_type verification_error_reference) 1015 { 1016 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT20bc.text); 1017 1018 VerificationErrorType verificationErrorType = $verification_error_type.verificationErrorType; 1019 Item referencedItem = $verification_error_reference.item; 1020 1021 $instructions.add(new Instruction20bc(opcode, verificationErrorType, referencedItem)); 1022 }; 1023 1024insn_format20t[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1025 : //e.g. goto/16 endloop: 1026 ^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t offset_or_label) 1027 { 1028 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT20t.text); 1029 1030 int addressOffset = $offset_or_label.offsetValue; 1031 1032 $instructions.add(new Instruction20t(opcode, addressOffset)); 1033 }; 1034 1035insn_format21c_field[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1036 : //e.g. sget_object v0, java/lang/System/out LJava/io/PrintStream; 1037 ^(I_STATEMENT_FORMAT21c_FIELD inst=(INSTRUCTION_FORMAT21c_FIELD | INSTRUCTION_FORMAT21c_FIELD_ODEX) REGISTER fully_qualified_field) 1038 { 1039 Opcode opcode = Opcode.getOpcodeByName($inst.text); 1040 short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 1041 1042 FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; 1043 1044 $instructions.add(new Instruction21c(opcode, regA, fieldIdItem)); 1045 }; 1046 1047insn_format21c_string[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1048 : //e.g. const-string v1, "Hello World!" 1049 ^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal) 1050 { 1051 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text); 1052 short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 1053 1054 StringIdItem stringIdItem = StringIdItem.internStringIdItem(dexFile, $string_literal.value); 1055 1056 instructions.add(new Instruction21c(opcode, regA, stringIdItem)); 1057 }; 1058 1059insn_format21c_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1060 : //e.g. const-class v2, org/jf/HelloWorld2/HelloWorld2 1061 ^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor) 1062 { 1063 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text); 1064 short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 1065 1066 TypeIdItem typeIdItem = $reference_type_descriptor.type; 1067 1068 $instructions.add(new Instruction21c(opcode, regA, typeIdItem)); 1069 }; 1070 1071insn_format21h[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1072 : //e.g. const/high16 v1, 1234 1073 ^(I_STATEMENT_FORMAT21h INSTRUCTION_FORMAT21h REGISTER short_integral_literal) 1074 { 1075 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21h.text); 1076 short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 1077 1078 short litB = $short_integral_literal.value; 1079 1080 instructions.add(new Instruction21h(opcode, regA, litB)); 1081 }; 1082 1083insn_format21s[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1084 : //e.g. const/16 v1, 1234 1085 ^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal) 1086 { 1087 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21s.text); 1088 short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 1089 1090 short litB = $short_integral_literal.value; 1091 1092 $instructions.add(new Instruction21s(opcode, regA, litB)); 1093 }; 1094 1095insn_format21t[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1096 : //e.g. if-eqz v0, endloop: 1097 ^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER offset_or_label) 1098 { 1099 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21t.text); 1100 short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 1101 1102 int addressOffset = $offset_or_label.offsetValue; 1103 1104 if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) { 1105 throw new SemanticException(input, $offset_or_label.start, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767]."); 1106 } 1107 1108 $instructions.add(new Instruction21t(opcode, regA, (short)addressOffset)); 1109 }; 1110 1111insn_format22b[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1112 : //e.g. add-int v0, v1, 123 1113 ^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal) 1114 { 1115 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22b.text); 1116 short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters); 1117 short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters); 1118 1119 short litC = $short_integral_literal.value; 1120 LiteralTools.checkByte(litC); 1121 1122 $instructions.add(new Instruction22b(opcode, regA, regB, (byte)litC)); 1123 }; 1124 1125insn_format22c_field[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1126 : //e.g. iput-object v1, v0, org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; 1127 ^(I_STATEMENT_FORMAT22c_FIELD inst=(INSTRUCTION_FORMAT22c_FIELD | INSTRUCTION_FORMAT22c_FIELD_ODEX) registerA=REGISTER registerB=REGISTER fully_qualified_field) 1128 { 1129 Opcode opcode = Opcode.getOpcodeByName($inst.text); 1130 byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); 1131 byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); 1132 1133 FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; 1134 1135 $instructions.add(new Instruction22c(opcode, regA, regB, fieldIdItem)); 1136 }; 1137 1138insn_format22c_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1139 : //e.g. instance-of v0, v1, Ljava/lang/String; 1140 ^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor) 1141 { 1142 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22c_TYPE.text); 1143 byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); 1144 byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); 1145 1146 TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; 1147 1148 $instructions.add(new Instruction22c(opcode, regA, regB, typeIdItem)); 1149 }; 1150 1151insn_format22s[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1152 : //e.g. add-int/lit16 v0, v1, 12345 1153 ^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal) 1154 { 1155 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22s.text); 1156 byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); 1157 byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); 1158 1159 short litC = $short_integral_literal.value; 1160 1161 $instructions.add(new Instruction22s(opcode, regA, regB, litC)); 1162 }; 1163 1164insn_format22t[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1165 : //e.g. if-eq v0, v1, endloop: 1166 ^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER offset_or_label) 1167 { 1168 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22t.text); 1169 byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); 1170 byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); 1171 1172 int addressOffset = $offset_or_label.offsetValue; 1173 1174 if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) { 1175 throw new SemanticException(input, $offset_or_label.start, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767]."); 1176 } 1177 1178 $instructions.add(new Instruction22t(opcode, regA, regB, (short)addressOffset)); 1179 }; 1180 1181insn_format22x[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1182 : //e.g. move/from16 v1, v1234 1183 ^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER) 1184 { 1185 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22x.text); 1186 short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters); 1187 int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters); 1188 1189 $instructions.add(new Instruction22x(opcode, regA, regB)); 1190 }; 1191 1192insn_format23x[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1193 : //e.g. add-int v1, v2, v3 1194 ^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER) 1195 { 1196 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT23x.text); 1197 short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters); 1198 short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters); 1199 short regC = parseRegister_byte($registerC.text, $totalMethodRegisters, $methodParameterRegisters); 1200 1201 $instructions.add(new Instruction23x(opcode, regA, regB, regC)); 1202 }; 1203 1204insn_format30t[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1205 : //e.g. goto/32 endloop: 1206 ^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t offset_or_label) 1207 { 1208 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT30t.text); 1209 1210 int addressOffset = $offset_or_label.offsetValue; 1211 1212 $instructions.add(new Instruction30t(opcode, addressOffset)); 1213 }; 1214 1215insn_format31c[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1216 : //e.g. const-string/jumbo v1 "Hello World!" 1217 ^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal) 1218 { 1219 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31c.text); 1220 short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 1221 1222 StringIdItem stringIdItem = StringIdItem.internStringIdItem(dexFile, $string_literal.value); 1223 1224 $instructions.add(new Instruction31c(opcode, regA, stringIdItem)); 1225 }; 1226 1227insn_format31i[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1228 : //e.g. const v0, 123456 1229 ^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal) 1230 { 1231 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31i.text); 1232 short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 1233 1234 int litB = $fixed_32bit_literal.value; 1235 1236 $instructions.add(new Instruction31i(opcode, regA, litB)); 1237 }; 1238 1239insn_format31t[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1240 : //e.g. fill-array-data v0, ArrayData: 1241 ^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER offset_or_label) 1242 { 1243 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31t.text); 1244 1245 short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 1246 1247 int addressOffset = $offset_or_label.offsetValue; 1248 if (($method::currentAddress + addressOffset) \% 2 != 0) { 1249 addressOffset++; 1250 } 1251 1252 $instructions.add(new Instruction31t(opcode, regA, addressOffset)); 1253 }; 1254 1255insn_format32x[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1256 : //e.g. move/16 v5678, v1234 1257 ^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER) 1258 { 1259 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT32x.text); 1260 int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters); 1261 int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters); 1262 1263 $instructions.add(new Instruction32x(opcode, regA, regB)); 1264 }; 1265 1266insn_format35c_method[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1267 : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V 1268 ^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method) 1269 { 1270 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT35c_METHOD.text); 1271 1272 //this depends on the fact that register_list returns a byte[5] 1273 byte[] registers = $register_list.registers; 1274 byte registerCount = $register_list.registerCount; 1275 $outRegisters = registerCount; 1276 1277 MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem; 1278 1279 $instructions.add(new Instruction35c(opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], methodIdItem)); 1280 }; 1281 1282insn_format35c_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1283 : //e.g. filled-new-array {v0,v1}, I 1284 ^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor) 1285 { 1286 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT35c_TYPE.text); 1287 1288 //this depends on the fact that register_list returns a byte[5] 1289 byte[] registers = $register_list.registers; 1290 byte registerCount = $register_list.registerCount; 1291 $outRegisters = registerCount; 1292 1293 TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; 1294 1295 $instructions.add(new Instruction35c(opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], typeIdItem)); 1296 }; 1297 1298insn_format3rc_method[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1299 : //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; 1300 ^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method) 1301 { 1302 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT3rc_METHOD.text); 1303 int startRegister = $register_range.startRegister; 1304 int endRegister = $register_range.endRegister; 1305 1306 int registerCount = endRegister-startRegister+1; 1307 $outRegisters = registerCount; 1308 1309 MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem; 1310 1311 $instructions.add(new Instruction3rc(opcode, (short)registerCount, startRegister, methodIdItem)); 1312 }; 1313 1314insn_format3rc_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1315 : //e.g. filled-new-array/range {v0..v6} I 1316 ^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor) 1317 { 1318 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT3rc_TYPE.text); 1319 int startRegister = $register_range.startRegister; 1320 int endRegister = $register_range.endRegister; 1321 1322 int registerCount = endRegister-startRegister+1; 1323 $outRegisters = registerCount; 1324 1325 TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; 1326 1327 $instructions.add(new Instruction3rc(opcode, (short)registerCount, startRegister, typeIdItem)); 1328 }; 1329 1330insn_format41c_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1331 : //e.g. const-class/jumbo v2, org/jf/HelloWorld2/HelloWorld2 1332 ^(I_STATEMENT_FORMAT41c_TYPE INSTRUCTION_FORMAT41c_TYPE REGISTER reference_type_descriptor) 1333 { 1334 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT41c_TYPE.text); 1335 int regA = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 1336 1337 TypeIdItem typeIdItem = $reference_type_descriptor.type; 1338 1339 $instructions.add(new Instruction41c(opcode, regA, typeIdItem)); 1340 }; 1341 1342insn_format41c_field[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1343 : //e.g. sget-object/jumbo v0, Ljava/lang/System;->out:LJava/io/PrintStream; 1344 ^(I_STATEMENT_FORMAT41c_FIELD INSTRUCTION_FORMAT41c_FIELD REGISTER fully_qualified_field) 1345 { 1346 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT41c_FIELD.text); 1347 int regA = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 1348 1349 FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; 1350 1351 $instructions.add(new Instruction41c(opcode, regA, fieldIdItem)); 1352 }; 1353 1354insn_format51l_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1355 : //e.g. const-wide v0, 5000000000L 1356 ^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal) 1357 { 1358 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT51l.text); 1359 short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); 1360 1361 long litB = $fixed_64bit_literal.value; 1362 1363 $instructions.add(new Instruction51l(opcode, regA, litB)); 1364 }; 1365 1366insn_format52c_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1367 : //e.g. instance-of/jumbo v0, v1, Ljava/lang/String; 1368 ^(I_STATEMENT_FORMAT52c_TYPE INSTRUCTION_FORMAT52c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor) 1369 { 1370 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT52c_TYPE.text); 1371 int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters); 1372 int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters); 1373 1374 TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; 1375 1376 $instructions.add(new Instruction52c(opcode, regA, regB, typeIdItem)); 1377 }; 1378 1379insn_format52c_field[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1380 : //e.g. iput-object/jumbo v1, v0, Lorg/jf/HelloWorld2/HelloWorld2;->helloWorld:Ljava/lang/String; 1381 ^(I_STATEMENT_FORMAT52c_FIELD INSTRUCTION_FORMAT52c_FIELD registerA=REGISTER registerB=REGISTER fully_qualified_field) 1382 { 1383 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT52c_FIELD.text); 1384 int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters); 1385 int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters); 1386 1387 FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; 1388 1389 $instructions.add(new Instruction52c(opcode, regA, regB, fieldIdItem)); 1390 }; 1391 1392insn_format5rc_method[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1393 : //e.g. invoke-virtual/jumbo {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; 1394 ^(I_STATEMENT_FORMAT5rc_METHOD INSTRUCTION_FORMAT5rc_METHOD register_range[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method) 1395 { 1396 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT5rc_METHOD.text); 1397 int startRegister = $register_range.startRegister; 1398 int endRegister = $register_range.endRegister; 1399 1400 int registerCount = endRegister-startRegister+1; 1401 $outRegisters = registerCount; 1402 1403 MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem; 1404 1405 $instructions.add(new Instruction5rc(opcode, registerCount, startRegister, methodIdItem)); 1406 }; 1407 1408insn_format5rc_type[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1409 : //e.g. filled-new-array/jumbo {v0..v6} I 1410 ^(I_STATEMENT_FORMAT5rc_TYPE INSTRUCTION_FORMAT5rc_TYPE register_range[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor) 1411 { 1412 Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT5rc_TYPE.text); 1413 int startRegister = $register_range.startRegister; 1414 int endRegister = $register_range.endRegister; 1415 1416 int registerCount = endRegister-startRegister+1; 1417 $outRegisters = registerCount; 1418 1419 TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; 1420 1421 $instructions.add(new Instruction5rc(opcode, registerCount, startRegister, typeIdItem)); 1422 }; 1423 1424insn_array_data_directive[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1425 : //e.g. .array-data 4 1000000 .end array-data 1426 ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements) 1427 { 1428 if (($method::currentAddress \% 2) != 0) { 1429 $instructions.add(new Instruction10x(Opcode.NOP)); 1430 $method::currentAddress++; 1431 } 1432 1433 int elementWidth = $short_integral_literal.value; 1434 List<byte[]> byteValues = $array_elements.values; 1435 1436 int length = 0; 1437 for (byte[] byteValue: byteValues) { 1438 length+=byteValue.length; 1439 } 1440 1441 byte[] encodedValues = new byte[length]; 1442 int index = 0; 1443 for (byte[] byteValue: byteValues) { 1444 System.arraycopy(byteValue, 0, encodedValues, index, byteValue.length); 1445 index+=byteValue.length; 1446 } 1447 1448 $instructions.add(new ArrayDataPseudoInstruction(elementWidth, encodedValues)); 1449 }; 1450 1451insn_packed_switch_directive[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1452 : 1453 ^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal) 1454 { 1455 if (($method::currentAddress \% 2) != 0) { 1456 $instructions.add(new Instruction10x(Opcode.NOP)); 1457 $method::currentAddress++; 1458 } 1459 Integer baseAddress = $method::packedSwitchDeclarations.get($method::currentAddress); 1460 if (baseAddress == null) { 1461 baseAddress = 0; 1462 } 1463 } 1464 packed_switch_targets[baseAddress]) 1465 { 1466 1467 int startKey = $fixed_32bit_literal.value; 1468 int[] targets = $packed_switch_targets.targets; 1469 1470 $instructions.add(new PackedSwitchDataPseudoInstruction(startKey, targets)); 1471 }; 1472 1473insn_sparse_switch_directive[int totalMethodRegisters, int methodParameterRegisters, List<Instruction> instructions] returns[int outRegisters] 1474 : 1475 ^(I_STATEMENT_SPARSE_SWITCH sparse_switch_target_count sparse_switch_keys[$sparse_switch_target_count.targetCount] 1476 { 1477 if (($method::currentAddress \% 2) != 0) { 1478 $instructions.add(new Instruction10x(Opcode.NOP)); 1479 $method::currentAddress++; 1480 } 1481 Integer baseAddress = $method::sparseSwitchDeclarations.get($method::currentAddress); 1482 if (baseAddress == null) { 1483 baseAddress = 0; 1484 } 1485 } 1486 1487 sparse_switch_targets[baseAddress, $sparse_switch_target_count.targetCount]) 1488 { 1489 int[] keys = $sparse_switch_keys.keys; 1490 int[] targets = $sparse_switch_targets.targets; 1491 1492 $instructions.add(new SparseSwitchDataPseudoInstruction(keys, targets)); 1493 }; 1494 1495nonvoid_type_descriptor returns [TypeIdItem type] 1496 : (PRIMITIVE_TYPE 1497 | CLASS_DESCRIPTOR 1498 | ARRAY_DESCRIPTOR) 1499 { 1500 $type = TypeIdItem.internTypeIdItem(dexFile, $start.getText()); 1501 }; 1502 1503 1504reference_type_descriptor returns [TypeIdItem type] 1505 : (CLASS_DESCRIPTOR 1506 | ARRAY_DESCRIPTOR) 1507 { 1508 $type = TypeIdItem.internTypeIdItem(dexFile, $start.getText()); 1509 }; 1510 1511 1512 1513 1514 1515 1516class_type_descriptor returns [TypeIdItem type] 1517 : CLASS_DESCRIPTOR 1518 { 1519 $type = TypeIdItem.internTypeIdItem(dexFile, $CLASS_DESCRIPTOR.text); 1520 }; 1521 1522type_descriptor returns [TypeIdItem type] 1523 : VOID_TYPE {$type = TypeIdItem.internTypeIdItem(dexFile, "V");} 1524 | nonvoid_type_descriptor {$type = $nonvoid_type_descriptor.type;} 1525 ; 1526 1527short_integral_literal returns[short value] 1528 : long_literal 1529 { 1530 LiteralTools.checkShort($long_literal.value); 1531 $value = (short)$long_literal.value; 1532 } 1533 | integer_literal 1534 { 1535 LiteralTools.checkShort($integer_literal.value); 1536 $value = (short)$integer_literal.value; 1537 } 1538 | short_literal {$value = $short_literal.value;} 1539 | char_literal {$value = (short)$char_literal.value;} 1540 | byte_literal {$value = $byte_literal.value;}; 1541 1542integral_literal returns[int value] 1543 : long_literal 1544 { 1545 LiteralTools.checkInt($long_literal.value); 1546 $value = (int)$long_literal.value; 1547 } 1548 | integer_literal {$value = $integer_literal.value;} 1549 | short_literal {$value = $short_literal.value;} 1550 | byte_literal {$value = $byte_literal.value;}; 1551 1552 1553integer_literal returns[int value] 1554 : INTEGER_LITERAL { $value = LiteralTools.parseInt($INTEGER_LITERAL.text); }; 1555 1556long_literal returns[long value] 1557 : LONG_LITERAL { $value = LiteralTools.parseLong($LONG_LITERAL.text); }; 1558 1559short_literal returns[short value] 1560 : SHORT_LITERAL { $value = LiteralTools.parseShort($SHORT_LITERAL.text); }; 1561 1562byte_literal returns[byte value] 1563 : BYTE_LITERAL { $value = LiteralTools.parseByte($BYTE_LITERAL.text); }; 1564 1565float_literal returns[float value] 1566 : FLOAT_LITERAL { $value = LiteralTools.parseFloat($FLOAT_LITERAL.text); }; 1567 1568double_literal returns[double value] 1569 : DOUBLE_LITERAL { $value = LiteralTools.parseDouble($DOUBLE_LITERAL.text); }; 1570 1571char_literal returns[char value] 1572 : CHAR_LITERAL { $value = $CHAR_LITERAL.text.charAt(1); }; 1573 1574string_literal returns[String value] 1575 : STRING_LITERAL 1576 { 1577 $value = $STRING_LITERAL.text; 1578 $value = $value.substring(1,$value.length()-1); 1579 }; 1580 1581bool_literal returns[boolean value] 1582 : BOOL_LITERAL { $value = Boolean.parseBoolean($BOOL_LITERAL.text); }; 1583 1584array_literal returns[EncodedValue[\] values] 1585 : {ArrayList<EncodedValue> valuesList = new ArrayList<EncodedValue>();} 1586 ^(I_ENCODED_ARRAY (literal {valuesList.add($literal.encodedValue);})*) 1587 { 1588 $values = new EncodedValue[valuesList.size()]; 1589 valuesList.toArray($values); 1590 }; 1591 1592 1593annotations returns[AnnotationSetItem annotationSetItem] 1594 : {ArrayList<AnnotationItem> annotationList = new ArrayList<AnnotationItem>();} 1595 ^(I_ANNOTATIONS (annotation {annotationList.add($annotation.annotationItem);} )*) 1596 { 1597 if (annotationList.size() > 0) { 1598 $annotationSetItem = AnnotationSetItem.internAnnotationSetItem(dexFile, annotationList); 1599 } 1600 }; 1601 1602 1603annotation returns[AnnotationItem annotationItem] 1604 : ^(I_ANNOTATION ANNOTATION_VISIBILITY subannotation) 1605 { 1606 AnnotationVisibility visibility = AnnotationVisibility.valueOf($ANNOTATION_VISIBILITY.text.toUpperCase()); 1607 AnnotationEncodedSubValue encodedAnnotation = new AnnotationEncodedSubValue($subannotation.annotationType, 1608 $subannotation.elementNames, $subannotation.elementValues); 1609 $annotationItem = AnnotationItem.internAnnotationItem(dexFile, visibility, encodedAnnotation); 1610 }; 1611 1612annotation_element returns[StringIdItem elementName, EncodedValue elementValue] 1613 : ^(I_ANNOTATION_ELEMENT SIMPLE_NAME literal) 1614 { 1615 $elementName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); 1616 $elementValue = $literal.encodedValue; 1617 }; 1618 1619subannotation returns[TypeIdItem annotationType, StringIdItem[\] elementNames, EncodedValue[\] elementValues] 1620 : {ImmutableSortedMap.Builder<StringIdItem, EncodedValue> elementBuilder = 1621 ImmutableSortedMap.<StringIdItem, EncodedValue>naturalOrder();} 1622 ^(I_SUBANNOTATION 1623 class_type_descriptor 1624 (annotation_element 1625 { 1626 elementBuilder.put($annotation_element.elementName, $annotation_element.elementValue); 1627 } 1628 )* 1629 ) 1630 { 1631 ImmutableSortedMap<StringIdItem, EncodedValue> elementMap = elementBuilder.build(); 1632 1633 $annotationType = $class_type_descriptor.type; 1634 1635 $elementNames = new StringIdItem[elementMap.size()]; 1636 $elementValues = new EncodedValue[elementMap.size()]; 1637 1638 elementMap.keySet().toArray($elementNames); 1639 elementMap.values().toArray($elementValues); 1640 }; 1641 1642field_literal returns[FieldIdItem value] 1643 : ^(I_ENCODED_FIELD fully_qualified_field) 1644 { 1645 $value = $fully_qualified_field.fieldIdItem; 1646 }; 1647 1648method_literal returns[MethodIdItem value] 1649 : ^(I_ENCODED_METHOD fully_qualified_method) 1650 { 1651 $value = $fully_qualified_method.methodIdItem; 1652 }; 1653 1654enum_literal returns[FieldIdItem value] 1655 : ^(I_ENCODED_ENUM fully_qualified_field) 1656 { 1657 $value = $fully_qualified_field.fieldIdItem; 1658 }; 1659