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