smaliParser.g revision b6435e7a475c64189906fb12e5408041bf3e750a
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 29parser grammar smaliParser; 30 31options { 32 output=AST; 33 ASTLabelType=CommonTree; 34} 35 36tokens { 37 //Lexer tokens 38 ACCESS_SPEC; 39 ANNOTATION_DIRECTIVE; 40 ANNOTATION_VISIBILITY; 41 ARRAY_DATA_DIRECTIVE; 42 ARRAY_DESCRIPTOR; 43 ARROW; 44 BASE_ARRAY_DESCRIPTOR; 45 BASE_CHAR_LITERAL; 46 BASE_CLASS_DESCRIPTOR; 47 BASE_FLOAT; 48 BASE_FLOAT_OR_ID; 49 BASE_INTEGER; 50 BASE_PRIMITIVE_TYPE; 51 BASE_SIMPLE_NAME; 52 BASE_STRING_LITERAL; 53 BASE_TYPE; 54 BINARY_EXPONENT; 55 BOOL_LITERAL; 56 BYTE_LITERAL; 57 CATCH_DIRECTIVE; 58 CATCHALL_DIRECTIVE; 59 CHAR_LITERAL; 60 CLASS_DESCRIPTOR; 61 CLASS_DIRECTIVE; 62 CLOSE_BRACE; 63 CLOSE_PAREN; 64 COLON; 65 COMMA; 66 DECIMAL_EXPONENT; 67 DOTDOT; 68 DOUBLE_LITERAL; 69 DOUBLE_LITERAL_OR_ID; 70 END_ANNOTATION_DIRECTIVE; 71 END_ARRAY_DATA_DIRECTIVE; 72 END_FIELD_DIRECTIVE; 73 END_LOCAL_DIRECTIVE; 74 END_METHOD_DIRECTIVE; 75 END_PACKED_SWITCH_DIRECTIVE; 76 END_PARAMETER_DIRECTIVE; 77 END_SPARSE_SWITCH_DIRECTIVE; 78 END_SUBANNOTATION_DIRECTIVE; 79 ENUM_DIRECTIVE; 80 EPILOGUE_DIRECTIVE; 81 EQUAL; 82 ESCAPE_SEQUENCE; 83 FIELD_DIRECTIVE; 84 FIELD_OFFSET; 85 FLOAT_LITERAL; 86 FLOAT_LITERAL_OR_ID; 87 HEX_DIGIT; 88 HEX_DIGITS; 89 HEX_PREFIX; 90 IMPLEMENTS_DIRECTIVE; 91 INLINE_INDEX; 92 INSTRUCTION_FORMAT10t; 93 INSTRUCTION_FORMAT10x; 94 INSTRUCTION_FORMAT10x_ODEX; 95 INSTRUCTION_FORMAT11n; 96 INSTRUCTION_FORMAT11x; 97 INSTRUCTION_FORMAT12x; 98 INSTRUCTION_FORMAT12x_OR_ID; 99 INSTRUCTION_FORMAT20bc; 100 INSTRUCTION_FORMAT20t; 101 INSTRUCTION_FORMAT21c_FIELD; 102 INSTRUCTION_FORMAT21c_FIELD_ODEX; 103 INSTRUCTION_FORMAT21c_STRING; 104 INSTRUCTION_FORMAT21c_TYPE; 105 INSTRUCTION_FORMAT21ih; 106 INSTRUCTION_FORMAT21lh; 107 INSTRUCTION_FORMAT21s; 108 INSTRUCTION_FORMAT21t; 109 INSTRUCTION_FORMAT22b; 110 INSTRUCTION_FORMAT22c_FIELD; 111 INSTRUCTION_FORMAT22c_FIELD_ODEX; 112 INSTRUCTION_FORMAT22c_TYPE; 113 INSTRUCTION_FORMAT22cs_FIELD; 114 INSTRUCTION_FORMAT22s; 115 INSTRUCTION_FORMAT22s_OR_ID; 116 INSTRUCTION_FORMAT22t; 117 INSTRUCTION_FORMAT22x; 118 INSTRUCTION_FORMAT23x; 119 INSTRUCTION_FORMAT30t; 120 INSTRUCTION_FORMAT31c; 121 INSTRUCTION_FORMAT31i; 122 INSTRUCTION_FORMAT31i_OR_ID; 123 INSTRUCTION_FORMAT31t; 124 INSTRUCTION_FORMAT32x; 125 INSTRUCTION_FORMAT35c_METHOD; 126 INSTRUCTION_FORMAT35c_METHOD_ODEX; 127 INSTRUCTION_FORMAT35c_TYPE; 128 INSTRUCTION_FORMAT35mi_METHOD; 129 INSTRUCTION_FORMAT35ms_METHOD; 130 INSTRUCTION_FORMAT3rc_METHOD; 131 INSTRUCTION_FORMAT3rc_METHOD_ODEX; 132 INSTRUCTION_FORMAT3rc_TYPE; 133 INSTRUCTION_FORMAT3rmi_METHOD; 134 INSTRUCTION_FORMAT3rms_METHOD; 135 INSTRUCTION_FORMAT51l; 136 INVALID_TOKEN; 137 LINE_COMMENT; 138 LINE_DIRECTIVE; 139 LOCAL_DIRECTIVE; 140 LOCALS_DIRECTIVE; 141 LONG_LITERAL; 142 METHOD_DIRECTIVE; 143 METHOD_NAME; 144 NEGATIVE_INTEGER_LITERAL; 145 NULL_LITERAL; 146 OFFSET; 147 OPEN_BRACE; 148 OPEN_PAREN; 149 PACKED_SWITCH_DIRECTIVE; 150 PARAM_LIST; 151 PARAM_LIST_OR_ID; 152 PARAMETER_DIRECTIVE; 153 POSITIVE_INTEGER_LITERAL; 154 PRIMITIVE_TYPE; 155 PROLOGUE_DIRECTIVE; 156 REGISTER; 157 REGISTERS_DIRECTIVE; 158 RESTART_LOCAL_DIRECTIVE; 159 SHORT_LITERAL; 160 SIMPLE_NAME; 161 SOURCE_DIRECTIVE; 162 SPARSE_SWITCH_DIRECTIVE; 163 STRING_LITERAL; 164 SUBANNOTATION_DIRECTIVE; 165 SUPER_DIRECTIVE; 166 VERIFICATION_ERROR_TYPE; 167 VOID_TYPE; 168 VTABLE_INDEX; 169 WHITE_SPACE; 170 171 //A couple of generated types that we remap other tokens to, to simplify the generated AST 172 LABEL; 173 INTEGER_LITERAL; 174 175 //I_* tokens are imaginary tokens used as parent AST nodes 176 I_CLASS_DEF; 177 I_SUPER; 178 I_IMPLEMENTS; 179 I_SOURCE; 180 I_ACCESS_LIST; 181 I_METHODS; 182 I_FIELDS; 183 I_FIELD; 184 I_FIELD_TYPE; 185 I_FIELD_INITIAL_VALUE; 186 I_METHOD; 187 I_METHOD_PROTOTYPE; 188 I_METHOD_RETURN_TYPE; 189 I_REGISTERS; 190 I_LOCALS; 191 I_LABELS; 192 I_LABEL; 193 I_ANNOTATIONS; 194 I_ANNOTATION; 195 I_ANNOTATION_ELEMENT; 196 I_SUBANNOTATION; 197 I_ENCODED_FIELD; 198 I_ENCODED_METHOD; 199 I_ENCODED_ENUM; 200 I_ENCODED_ARRAY; 201 I_ARRAY_ELEMENT_SIZE; 202 I_ARRAY_ELEMENTS; 203 I_PACKED_SWITCH_START_KEY; 204 I_PACKED_SWITCH_ELEMENTS; 205 I_PACKED_SWITCH_DECLARATION; 206 I_PACKED_SWITCH_DECLARATIONS; 207 I_SPARSE_SWITCH_ELEMENTS; 208 I_SPARSE_SWITCH_DECLARATION; 209 I_SPARSE_SWITCH_DECLARATIONS; 210 I_ADDRESS; 211 I_CATCH; 212 I_CATCHALL; 213 I_CATCHES; 214 I_PARAMETER; 215 I_PARAMETERS; 216 I_PARAMETER_NOT_SPECIFIED; 217 I_ORDERED_DEBUG_DIRECTIVES; 218 I_LINE; 219 I_LOCAL; 220 I_END_LOCAL; 221 I_RESTART_LOCAL; 222 I_PROLOGUE; 223 I_EPILOGUE; 224 I_STATEMENTS; 225 I_STATEMENT_FORMAT10t; 226 I_STATEMENT_FORMAT10x; 227 I_STATEMENT_FORMAT11n; 228 I_STATEMENT_FORMAT11x; 229 I_STATEMENT_FORMAT12x; 230 I_STATEMENT_FORMAT20bc; 231 I_STATEMENT_FORMAT20t; 232 I_STATEMENT_FORMAT21c_TYPE; 233 I_STATEMENT_FORMAT21c_FIELD; 234 I_STATEMENT_FORMAT21c_STRING; 235 I_STATEMENT_FORMAT21ih; 236 I_STATEMENT_FORMAT21lh; 237 I_STATEMENT_FORMAT21s; 238 I_STATEMENT_FORMAT21t; 239 I_STATEMENT_FORMAT22b; 240 I_STATEMENT_FORMAT22c_FIELD; 241 I_STATEMENT_FORMAT22c_TYPE; 242 I_STATEMENT_FORMAT22s; 243 I_STATEMENT_FORMAT22t; 244 I_STATEMENT_FORMAT22x; 245 I_STATEMENT_FORMAT23x; 246 I_STATEMENT_FORMAT30t; 247 I_STATEMENT_FORMAT31c; 248 I_STATEMENT_FORMAT31i; 249 I_STATEMENT_FORMAT31t; 250 I_STATEMENT_FORMAT32x; 251 I_STATEMENT_FORMAT35c_METHOD; 252 I_STATEMENT_FORMAT35c_TYPE; 253 I_STATEMENT_FORMAT3rc_METHOD; 254 I_STATEMENT_FORMAT3rc_TYPE; 255 I_STATEMENT_FORMAT51l; 256 I_STATEMENT_ARRAY_DATA; 257 I_STATEMENT_PACKED_SWITCH; 258 I_STATEMENT_SPARSE_SWITCH; 259 I_REGISTER_RANGE; 260 I_REGISTER_LIST; 261} 262 263@header { 264package org.jf.smali; 265 266import org.jf.dexlib2.Format; 267import org.jf.dexlib2.Opcode; 268import org.jf.dexlib2.Opcodes; 269} 270 271 272@members { 273 public static final int ERROR_CHANNEL = 100; 274 275 private boolean verboseErrors = false; 276 private boolean allowOdex = false; 277 private int apiLevel = 15; 278 private Opcodes opcodes = new Opcodes(apiLevel); 279 280 public void setVerboseErrors(boolean verboseErrors) { 281 this.verboseErrors = verboseErrors; 282 } 283 284 public void setAllowOdex(boolean allowOdex) { 285 this.allowOdex = allowOdex; 286 } 287 288 public void setApiLevel(int apiLevel) { 289 this.opcodes = new Opcodes(apiLevel); 290 this.apiLevel = apiLevel; 291 } 292 293 public String getErrorMessage(RecognitionException e, 294 String[] tokenNames) { 295 296 if (verboseErrors) { 297 List stack = getRuleInvocationStack(e, this.getClass().getName()); 298 String msg = null; 299 300 if (e instanceof NoViableAltException) { 301 NoViableAltException nvae = (NoViableAltException)e; 302 msg = " no viable alt; token="+getTokenErrorDisplay(e.token)+ 303 " (decision="+nvae.decisionNumber+ 304 " state "+nvae.stateNumber+")"+ 305 " decision=<<"+nvae.grammarDecisionDescription+">>"; 306 } else { 307 msg = super.getErrorMessage(e, tokenNames); 308 } 309 310 return stack + " " + msg; 311 } else { 312 return super.getErrorMessage(e, tokenNames); 313 } 314 } 315 316 public String getTokenErrorDisplay(Token t) { 317 if (!verboseErrors) { 318 String s = t.getText(); 319 if ( s==null ) { 320 if ( t.getType()==Token.EOF ) { 321 s = "<EOF>"; 322 } 323 else { 324 s = "<"+tokenNames[t.getType()]+">"; 325 } 326 } 327 s = s.replaceAll("\n","\\\\n"); 328 s = s.replaceAll("\r","\\\\r"); 329 s = s.replaceAll("\t","\\\\t"); 330 return "'"+s+"'"; 331 } 332 333 CommonToken ct = (CommonToken)t; 334 335 String channelStr = ""; 336 if (t.getChannel()>0) { 337 channelStr=",channel="+t.getChannel(); 338 } 339 String txt = t.getText(); 340 if ( txt!=null ) { 341 txt = txt.replaceAll("\n","\\\\n"); 342 txt = txt.replaceAll("\r","\\\\r"); 343 txt = txt.replaceAll("\t","\\\\t"); 344 } 345 else { 346 txt = "<no text>"; 347 } 348 return "[@"+t.getTokenIndex()+","+ct.getStartIndex()+":"+ct.getStopIndex()+"='"+txt+"',<"+tokenNames[t.getType()]+">"+channelStr+","+t.getLine()+":"+t.getCharPositionInLine()+"]"; 349 } 350 351 public String getErrorHeader(RecognitionException e) { 352 return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]"; 353 } 354 355 private CommonTree buildTree(int type, String text, List<CommonTree> children) { 356 CommonTree root = new CommonTree(new CommonToken(type, text)); 357 for (CommonTree child: children) { 358 root.addChild(child); 359 } 360 return root; 361 } 362 363 private CommonToken getParamListSubToken(CommonToken baseToken, String str, int typeStartIndex) { 364 CommonToken token = new CommonToken(baseToken); 365 token.setStartIndex(baseToken.getStartIndex() + typeStartIndex); 366 367 switch (str.charAt(typeStartIndex)) { 368 case 'Z': 369 case 'B': 370 case 'S': 371 case 'C': 372 case 'I': 373 case 'J': 374 case 'F': 375 case 'D': 376 { 377 token.setType(PRIMITIVE_TYPE); 378 token.setText(str.substring(typeStartIndex, typeStartIndex+1)); 379 token.setStopIndex(baseToken.getStartIndex() + typeStartIndex); 380 break; 381 } 382 case 'L': 383 { 384 int i = typeStartIndex; 385 while (str.charAt(++i) != ';'); 386 387 token.setType(CLASS_DESCRIPTOR); 388 token.setText(str.substring(typeStartIndex, i + 1)); 389 token.setStopIndex(baseToken.getStartIndex() + i); 390 break; 391 } 392 case '[': 393 { 394 int i = typeStartIndex; 395 while (str.charAt(++i) == '['); 396 397 if (str.charAt(i++) == 'L') { 398 while (str.charAt(i++) != ';'); 399 } 400 401 token.setType(ARRAY_DESCRIPTOR); 402 token.setText(str.substring(typeStartIndex, i)); 403 token.setStopIndex(baseToken.getStartIndex() + i - 1); 404 break; 405 } 406 default: 407 throw new RuntimeException(String.format("Invalid character '\%c' in param list \"\%s\" at position \%d", str.charAt(typeStartIndex), str, typeStartIndex)); 408 } 409 410 return token; 411 } 412 413 private CommonTree parseParamList(CommonToken paramListToken) { 414 String paramList = paramListToken.getText(); 415 CommonTree root = new CommonTree(); 416 417 int startIndex = paramListToken.getStartIndex(); 418 419 int i=0; 420 while (i<paramList.length()) { 421 CommonToken token = getParamListSubToken(paramListToken, paramList, i); 422 root.addChild(new CommonTree(token)); 423 i += token.getText().length(); 424 } 425 426 if (root.getChildCount() == 0) { 427 return null; 428 } 429 return root; 430 } 431 432 private void throwOdexedInstructionException(IntStream input, String odexedInstruction) 433 throws OdexedInstructionException { 434 /*this has to be done in a separate method, otherwise java will complain about the 435 auto-generated code in the rule after the throw not being reachable*/ 436 throw new OdexedInstructionException(input, odexedInstruction); 437 } 438} 439 440 441smali_file 442 scope 443 { 444 boolean hasClassSpec; 445 boolean hasSuperSpec; 446 boolean hasSourceSpec; 447 List<CommonTree> classAnnotations; 448 } 449 @init 450 { $smali_file::hasClassSpec = $smali_file::hasSuperSpec = $smali_file::hasSourceSpec = false; 451 $smali_file::classAnnotations = new ArrayList<CommonTree>(); 452 } 453 : 454 ( {!$smali_file::hasClassSpec}?=> class_spec {$smali_file::hasClassSpec = true;} 455 | {!$smali_file::hasSuperSpec}?=> super_spec {$smali_file::hasSuperSpec = true;} 456 | implements_spec 457 | {!$smali_file::hasSourceSpec}?=> source_spec {$smali_file::hasSourceSpec = true;} 458 | method 459 | field 460 | annotation {$smali_file::classAnnotations.add($annotation.tree);} 461 )+ 462 EOF 463 { 464 if (!$smali_file::hasClassSpec) { 465 throw new SemanticException(input, "The file must contain a .class directive"); 466 } 467 468 if (!$smali_file::hasSuperSpec) { 469 if (!$class_spec.className.equals("Ljava/lang/Object;")) { 470 throw new SemanticException(input, "The file must contain a .super directive"); 471 } 472 } 473 } 474 -> ^(I_CLASS_DEF 475 class_spec 476 super_spec? 477 implements_spec* 478 source_spec? 479 ^(I_METHODS method*) ^(I_FIELDS field*) {buildTree(I_ANNOTATIONS, "I_ANNOTATIONS", $smali_file::classAnnotations)}); 480 481class_spec returns[String className] 482 : CLASS_DIRECTIVE access_list CLASS_DESCRIPTOR {$className = $CLASS_DESCRIPTOR.text;} -> CLASS_DESCRIPTOR access_list; 483 484super_spec 485 : SUPER_DIRECTIVE CLASS_DESCRIPTOR -> ^(I_SUPER[$start, "I_SUPER"] CLASS_DESCRIPTOR); 486 487implements_spec 488 : IMPLEMENTS_DIRECTIVE CLASS_DESCRIPTOR -> ^(I_IMPLEMENTS[$start, "I_IMPLEMENTS"] CLASS_DESCRIPTOR); 489 490source_spec 491 : SOURCE_DIRECTIVE STRING_LITERAL -> ^(I_SOURCE[$start, "I_SOURCE"] STRING_LITERAL); 492 493access_list 494 : ACCESS_SPEC* -> ^(I_ACCESS_LIST[$start,"I_ACCESS_LIST"] ACCESS_SPEC*); 495 496 497/*When there are annotations immediately after a field definition, we don't know whether they are field annotations 498or class annotations until we determine if there is an .end field directive. In either case, we still "consume" and parse 499the annotations. If it turns out that they are field annotations, we include them in the I_FIELD AST. Otherwise, we 500add them to the $smali_file::classAnnotations list*/ 501field 502 @init {List<CommonTree> annotations = new ArrayList<CommonTree>();} 503 : FIELD_DIRECTIVE access_list simple_name COLON nonvoid_type_descriptor (EQUAL literal)? 504 ( ({input.LA(1) == ANNOTATION_DIRECTIVE}? annotation {annotations.add($annotation.tree);})* 505 ( END_FIELD_DIRECTIVE 506 -> ^(I_FIELD[$start, "I_FIELD"] simple_name access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS annotation*)) 507 | /*epsilon*/ {$smali_file::classAnnotations.addAll(annotations);} 508 -> ^(I_FIELD[$start, "I_FIELD"] simple_name access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS)) 509 ) 510 ); 511 512method 513 scope {int currentAddress;} 514 : {$method::currentAddress = 0;} 515 METHOD_DIRECTIVE access_list method_name method_prototype statements_and_directives 516 END_METHOD_DIRECTIVE 517 -> ^(I_METHOD[$start, "I_METHOD"] method_name method_prototype access_list statements_and_directives); 518 519statements_and_directives 520 scope 521 { 522 boolean hasRegistersDirective; 523 List<CommonTree> packedSwitchDeclarations; 524 List<CommonTree> sparseSwitchDeclarations; 525 List<CommonTree> methodAnnotations; 526 } 527 : { 528 $method::currentAddress = 0; 529 $statements_and_directives::hasRegistersDirective = false; 530 $statements_and_directives::packedSwitchDeclarations = new ArrayList<CommonTree>(); 531 $statements_and_directives::sparseSwitchDeclarations = new ArrayList<CommonTree>(); 532 $statements_and_directives::methodAnnotations = new ArrayList<CommonTree>(); 533 } 534 ( instruction {$method::currentAddress += $instruction.size/2;} 535 | registers_directive 536 | label 537 | catch_directive 538 | catchall_directive 539 | parameter_directive 540 | ordered_debug_directive 541 | annotation {$statements_and_directives::methodAnnotations.add($annotation.tree);} 542 )* 543 -> registers_directive? 544 ^(I_LABELS label*) 545 {buildTree(I_PACKED_SWITCH_DECLARATIONS, "I_PACKED_SWITCH_DECLARATIONS", $statements_and_directives::packedSwitchDeclarations)} 546 {buildTree(I_SPARSE_SWITCH_DECLARATIONS, "I_SPARSE_SWITCH_DECLARATIONS", $statements_and_directives::sparseSwitchDeclarations)} 547 ^(I_STATEMENTS instruction*) 548 ^(I_CATCHES catch_directive* catchall_directive*) 549 ^(I_PARAMETERS parameter_directive*) 550 ^(I_ORDERED_DEBUG_DIRECTIVES ordered_debug_directive*) 551 {buildTree(I_ANNOTATIONS, "I_ANNOTATIONS", $statements_and_directives::methodAnnotations)}; 552 553registers_directive 554 : ( 555 directive=REGISTERS_DIRECTIVE regCount=integral_literal -> ^(I_REGISTERS[$REGISTERS_DIRECTIVE, "I_REGISTERS"] $regCount) 556 | directive=LOCALS_DIRECTIVE regCount2=integral_literal -> ^(I_LOCALS[$LOCALS_DIRECTIVE, "I_LOCALS"] $regCount2) 557 ) 558 { 559 if ($statements_and_directives::hasRegistersDirective) { 560 throw new SemanticException(input, $directive, "There can only be a single .registers or .locals directive in a method"); 561 } 562 $statements_and_directives::hasRegistersDirective=true; 563 }; 564 565/*identifiers are much more general than most languages. Any of the below can either be 566the indicated type OR an identifier, depending on the context*/ 567simple_name 568 : SIMPLE_NAME 569 | ACCESS_SPEC -> SIMPLE_NAME[$ACCESS_SPEC] 570 | VERIFICATION_ERROR_TYPE -> SIMPLE_NAME[$VERIFICATION_ERROR_TYPE] 571 | POSITIVE_INTEGER_LITERAL -> SIMPLE_NAME[$POSITIVE_INTEGER_LITERAL] 572 | NEGATIVE_INTEGER_LITERAL -> SIMPLE_NAME[$NEGATIVE_INTEGER_LITERAL] 573 | FLOAT_LITERAL_OR_ID -> SIMPLE_NAME[$FLOAT_LITERAL_OR_ID] 574 | DOUBLE_LITERAL_OR_ID -> SIMPLE_NAME[$DOUBLE_LITERAL_OR_ID] 575 | BOOL_LITERAL -> SIMPLE_NAME[$BOOL_LITERAL] 576 | NULL_LITERAL -> SIMPLE_NAME[$NULL_LITERAL] 577 | REGISTER -> SIMPLE_NAME[$REGISTER] 578 | PARAM_LIST_OR_ID -> SIMPLE_NAME[$PARAM_LIST_OR_ID] 579 | PRIMITIVE_TYPE -> SIMPLE_NAME[$PRIMITIVE_TYPE] 580 | VOID_TYPE -> SIMPLE_NAME[$VOID_TYPE] 581 | ANNOTATION_VISIBILITY -> SIMPLE_NAME[$ANNOTATION_VISIBILITY] 582 | INSTRUCTION_FORMAT10t -> SIMPLE_NAME[$INSTRUCTION_FORMAT10t] 583 | INSTRUCTION_FORMAT10x -> SIMPLE_NAME[$INSTRUCTION_FORMAT10x] 584 | INSTRUCTION_FORMAT10x_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT10x_ODEX] 585 | INSTRUCTION_FORMAT11x -> SIMPLE_NAME[$INSTRUCTION_FORMAT11x] 586 | INSTRUCTION_FORMAT12x_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT12x_OR_ID] 587 | INSTRUCTION_FORMAT21c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD] 588 | INSTRUCTION_FORMAT21c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD_ODEX] 589 | INSTRUCTION_FORMAT21c_STRING -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_STRING] 590 | INSTRUCTION_FORMAT21c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_TYPE] 591 | INSTRUCTION_FORMAT21t -> SIMPLE_NAME[$INSTRUCTION_FORMAT21t] 592 | INSTRUCTION_FORMAT22c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD] 593 | INSTRUCTION_FORMAT22c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD_ODEX] 594 | INSTRUCTION_FORMAT22c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_TYPE] 595 | INSTRUCTION_FORMAT22cs_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22cs_FIELD] 596 | INSTRUCTION_FORMAT22s_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT22s_OR_ID] 597 | INSTRUCTION_FORMAT22t -> SIMPLE_NAME[$INSTRUCTION_FORMAT22t] 598 | INSTRUCTION_FORMAT23x -> SIMPLE_NAME[$INSTRUCTION_FORMAT23x] 599 | INSTRUCTION_FORMAT31i_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT31i_OR_ID] 600 | INSTRUCTION_FORMAT31t -> SIMPLE_NAME[$INSTRUCTION_FORMAT31t] 601 | INSTRUCTION_FORMAT35c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD] 602 | INSTRUCTION_FORMAT35c_METHOD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD_ODEX] 603 | INSTRUCTION_FORMAT35c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_TYPE] 604 | INSTRUCTION_FORMAT35mi_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35mi_METHOD] 605 | INSTRUCTION_FORMAT35ms_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35ms_METHOD] 606 | INSTRUCTION_FORMAT51l -> SIMPLE_NAME[$INSTRUCTION_FORMAT51l]; 607 608method_name 609 : simple_name 610 | METHOD_NAME -> SIMPLE_NAME[$METHOD_NAME]; 611 612method_prototype 613 : OPEN_PAREN param_list CLOSE_PAREN type_descriptor 614 -> ^(I_METHOD_PROTOTYPE[$start, "I_METHOD_PROTOTYPE"] ^(I_METHOD_RETURN_TYPE type_descriptor) param_list?); 615 616param_list 617 : PARAM_LIST -> { parseParamList((CommonToken)$PARAM_LIST) } 618 | PARAM_LIST_OR_ID -> { parseParamList((CommonToken)$PARAM_LIST_OR_ID) } 619 | nonvoid_type_descriptor*; 620 621type_descriptor 622 : VOID_TYPE 623 | PRIMITIVE_TYPE 624 | CLASS_DESCRIPTOR 625 | ARRAY_DESCRIPTOR; 626 627nonvoid_type_descriptor 628 : PRIMITIVE_TYPE 629 | CLASS_DESCRIPTOR 630 | ARRAY_DESCRIPTOR; 631 632reference_type_descriptor 633 : CLASS_DESCRIPTOR 634 | ARRAY_DESCRIPTOR; 635 636integer_literal 637 : POSITIVE_INTEGER_LITERAL -> INTEGER_LITERAL[$POSITIVE_INTEGER_LITERAL] 638 | NEGATIVE_INTEGER_LITERAL -> INTEGER_LITERAL[$NEGATIVE_INTEGER_LITERAL]; 639 640float_literal 641 : FLOAT_LITERAL_OR_ID -> FLOAT_LITERAL[$FLOAT_LITERAL_OR_ID] 642 | FLOAT_LITERAL; 643 644double_literal 645 : DOUBLE_LITERAL_OR_ID -> DOUBLE_LITERAL[$DOUBLE_LITERAL_OR_ID] 646 | DOUBLE_LITERAL; 647 648literal 649 : LONG_LITERAL 650 | integer_literal 651 | SHORT_LITERAL 652 | BYTE_LITERAL 653 | float_literal 654 | double_literal 655 | CHAR_LITERAL 656 | STRING_LITERAL 657 | BOOL_LITERAL 658 | NULL_LITERAL 659 | array_literal 660 | subannotation 661 | type_field_method_literal 662 | enum_literal; 663 664parsed_integer_literal returns[int value] 665 : integer_literal { $value = LiteralTools.parseInt($integer_literal.text); }; 666 667integral_literal 668 : LONG_LITERAL 669 | integer_literal 670 | SHORT_LITERAL 671 | CHAR_LITERAL 672 | BYTE_LITERAL; 673 674fixed_32bit_literal 675 : LONG_LITERAL 676 | integer_literal 677 | SHORT_LITERAL 678 | BYTE_LITERAL 679 | float_literal 680 | CHAR_LITERAL 681 | BOOL_LITERAL; 682 683fixed_literal returns[int size] 684 : integer_literal {$size = 4;} 685 | LONG_LITERAL {$size = 8;} 686 | SHORT_LITERAL {$size = 2;} 687 | BYTE_LITERAL {$size = 1;} 688 | float_literal {$size = 4;} 689 | double_literal {$size = 8;} 690 | CHAR_LITERAL {$size = 2;} 691 | BOOL_LITERAL {$size = 1;}; 692 693array_literal 694 : OPEN_BRACE (literal (COMMA literal)* | ) CLOSE_BRACE 695 -> ^(I_ENCODED_ARRAY[$start, "I_ENCODED_ARRAY"] literal*); 696 697annotation_element 698 : simple_name EQUAL literal 699 -> ^(I_ANNOTATION_ELEMENT[$start, "I_ANNOTATION_ELEMENT"] simple_name literal); 700 701annotation 702 : ANNOTATION_DIRECTIVE ANNOTATION_VISIBILITY CLASS_DESCRIPTOR 703 annotation_element* END_ANNOTATION_DIRECTIVE 704 -> ^(I_ANNOTATION[$start, "I_ANNOTATION"] ANNOTATION_VISIBILITY ^(I_SUBANNOTATION[$start, "I_SUBANNOTATION"] CLASS_DESCRIPTOR annotation_element*)); 705 706subannotation 707 : SUBANNOTATION_DIRECTIVE CLASS_DESCRIPTOR annotation_element* END_SUBANNOTATION_DIRECTIVE 708 -> ^(I_SUBANNOTATION[$start, "I_SUBANNOTATION"] CLASS_DESCRIPTOR annotation_element*); 709 710enum_literal 711 : ENUM_DIRECTIVE reference_type_descriptor ARROW simple_name COLON reference_type_descriptor 712 -> ^(I_ENCODED_ENUM reference_type_descriptor simple_name reference_type_descriptor); 713 714type_field_method_literal 715 : reference_type_descriptor 716 ( ARROW 717 ( simple_name COLON nonvoid_type_descriptor -> ^(I_ENCODED_FIELD reference_type_descriptor simple_name nonvoid_type_descriptor) 718 | method_name method_prototype -> ^(I_ENCODED_METHOD reference_type_descriptor method_name method_prototype) 719 ) 720 | -> reference_type_descriptor 721 ) 722 | PRIMITIVE_TYPE 723 | VOID_TYPE; 724 725fully_qualified_method 726 : reference_type_descriptor ARROW method_name method_prototype 727 -> reference_type_descriptor method_name method_prototype; 728 729fully_qualified_field 730 : reference_type_descriptor ARROW simple_name COLON nonvoid_type_descriptor 731 -> reference_type_descriptor simple_name nonvoid_type_descriptor; 732 733label 734 : COLON simple_name -> ^(I_LABEL[$COLON, "I_LABEL"] simple_name I_ADDRESS[$start, Integer.toString($method::currentAddress)]); 735 736label_ref_or_offset 737 : COLON simple_name -> simple_name 738 | OFFSET 739 | NEGATIVE_INTEGER_LITERAL -> OFFSET[$NEGATIVE_INTEGER_LITERAL]; 740 741register_list 742 : REGISTER (COMMA REGISTER)* -> ^(I_REGISTER_LIST[$start, "I_REGISTER_LIST"] REGISTER*) 743 | ->^(I_REGISTER_LIST[$start, "I_REGISTER_LIST"]); 744 745register_range 746 : (startreg=REGISTER (DOTDOT endreg=REGISTER)?)? -> ^(I_REGISTER_RANGE[$start, "I_REGISTER_RANGE"] $startreg? $endreg?); 747 748verification_error_reference 749 : CLASS_DESCRIPTOR | fully_qualified_field | fully_qualified_method; 750 751catch_directive 752 : CATCH_DIRECTIVE nonvoid_type_descriptor OPEN_BRACE from=label_ref_or_offset DOTDOT to=label_ref_or_offset CLOSE_BRACE using=label_ref_or_offset 753 -> ^(I_CATCH[$start, "I_CATCH"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] nonvoid_type_descriptor $from $to $using); 754 755catchall_directive 756 : CATCHALL_DIRECTIVE OPEN_BRACE from=label_ref_or_offset DOTDOT to=label_ref_or_offset CLOSE_BRACE using=label_ref_or_offset 757 -> ^(I_CATCHALL[$start, "I_CATCHALL"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] $from $to $using); 758 759/*When there are annotations immediately after a parameter definition, we don't know whether they are parameter annotations 760or method annotations until we determine if there is an .end parameter directive. In either case, we still "consume" and parse 761the annotations. If it turns out that they are parameter annotations, we include them in the I_PARAMETER AST. Otherwise, we 762add them to the $statements_and_directives::methodAnnotations list*/ 763parameter_directive 764 @init {List<CommonTree> annotations = new ArrayList<CommonTree>();} 765 : PARAMETER_DIRECTIVE REGISTER (COMMA STRING_LITERAL)? 766 ({input.LA(1) == ANNOTATION_DIRECTIVE}? annotation {annotations.add($annotation.tree);})* 767 768 ( END_PARAMETER_DIRECTIVE 769 -> ^(I_PARAMETER[$start, "I_PARAMETER"] REGISTER STRING_LITERAL? ^(I_ANNOTATIONS annotation*)) 770 | /*epsilon*/ {$statements_and_directives::methodAnnotations.addAll(annotations);} 771 -> ^(I_PARAMETER[$start, "I_PARAMETER"] REGISTER STRING_LITERAL? ^(I_ANNOTATIONS)) 772 ); 773 774ordered_debug_directive 775 : line_directive 776 | local_directive 777 | end_local_directive 778 | restart_local_directive 779 | prologue_directive 780 | epilogue_directive 781 | source_directive; 782 783line_directive 784 : LINE_DIRECTIVE integral_literal 785 -> ^(I_LINE[$start, "I_LINE"] integral_literal I_ADDRESS[$start, Integer.toString($method::currentAddress)]); 786 787local_directive 788 : LOCAL_DIRECTIVE REGISTER (COMMA (NULL_LITERAL | name=STRING_LITERAL) COLON (VOID_TYPE | nonvoid_type_descriptor) 789 (COMMA signature=STRING_LITERAL)? )? 790 -> ^(I_LOCAL[$start, "I_LOCAL"] REGISTER NULL_LITERAL? $name? nonvoid_type_descriptor? $signature? 791 I_ADDRESS[$start, Integer.toString($method::currentAddress)]); 792 793end_local_directive 794 : END_LOCAL_DIRECTIVE REGISTER 795 -> ^(I_END_LOCAL[$start, "I_END_LOCAL"] REGISTER I_ADDRESS[$start, Integer.toString($method::currentAddress)]); 796 797restart_local_directive 798 : RESTART_LOCAL_DIRECTIVE REGISTER 799 -> ^(I_RESTART_LOCAL[$start, "I_RESTART_LOCAL"] REGISTER I_ADDRESS[$start, Integer.toString($method::currentAddress)]); 800 801prologue_directive 802 : PROLOGUE_DIRECTIVE 803 -> ^(I_PROLOGUE[$start, "I_PROLOGUE"] I_ADDRESS[$start, Integer.toString($method::currentAddress)]); 804 805epilogue_directive 806 : EPILOGUE_DIRECTIVE 807 -> ^(I_EPILOGUE[$start, "I_EPILOGUE"] I_ADDRESS[$start, Integer.toString($method::currentAddress)]); 808 809source_directive 810 : SOURCE_DIRECTIVE STRING_LITERAL? 811 -> ^(I_SOURCE[$start, "I_SOURCE"] STRING_LITERAL? I_ADDRESS[$start, Integer.toString($method::currentAddress)]); 812 813instruction_format12x 814 : INSTRUCTION_FORMAT12x 815 | INSTRUCTION_FORMAT12x_OR_ID -> INSTRUCTION_FORMAT12x[$INSTRUCTION_FORMAT12x_OR_ID]; 816 817instruction_format22s 818 : INSTRUCTION_FORMAT22s 819 | INSTRUCTION_FORMAT22s_OR_ID -> INSTRUCTION_FORMAT22s[$INSTRUCTION_FORMAT22s_OR_ID]; 820 821instruction_format31i 822 : INSTRUCTION_FORMAT31i 823 | INSTRUCTION_FORMAT31i_OR_ID -> INSTRUCTION_FORMAT31i[$INSTRUCTION_FORMAT31i_OR_ID]; 824 825 826 827instruction returns [int size] 828 : insn_format10t { $size = $insn_format10t.size; } 829 | insn_format10x { $size = $insn_format10x.size; } 830 | insn_format10x_odex { $size = $insn_format10x_odex.size; } 831 | insn_format11n { $size = $insn_format11n.size; } 832 | insn_format11x { $size = $insn_format11x.size; } 833 | insn_format12x { $size = $insn_format12x.size; } 834 | insn_format20bc { $size = $insn_format20bc.size; } 835 | insn_format20t { $size = $insn_format20t.size; } 836 | insn_format21c_field { $size = $insn_format21c_field.size; } 837 | insn_format21c_field_odex { $size = $insn_format21c_field_odex.size; } 838 | insn_format21c_string { $size = $insn_format21c_string.size; } 839 | insn_format21c_type { $size = $insn_format21c_type.size; } 840 | insn_format21ih { $size = $insn_format21ih.size; } 841 | insn_format21lh { $size = $insn_format21lh.size; } 842 | insn_format21s { $size = $insn_format21s.size; } 843 | insn_format21t { $size = $insn_format21t.size; } 844 | insn_format22b { $size = $insn_format22b.size; } 845 | insn_format22c_field { $size = $insn_format22c_field.size; } 846 | insn_format22c_field_odex { $size = $insn_format22c_field_odex.size; } 847 | insn_format22c_type { $size = $insn_format22c_type.size; } 848 | insn_format22cs_field { $size = $insn_format22cs_field.size; } 849 | insn_format22s { $size = $insn_format22s.size; } 850 | insn_format22t { $size = $insn_format22t.size; } 851 | insn_format22x { $size = $insn_format22x.size; } 852 | insn_format23x { $size = $insn_format23x.size; } 853 | insn_format30t { $size = $insn_format30t.size; } 854 | insn_format31c { $size = $insn_format31c.size; } 855 | insn_format31i { $size = $insn_format31i.size; } 856 | insn_format31t { $size = $insn_format31t.size; } 857 | insn_format32x { $size = $insn_format32x.size; } 858 | insn_format35c_method { $size = $insn_format35c_method.size; } 859 | insn_format35c_type { $size = $insn_format35c_type.size; } 860 | insn_format35c_method_odex { $size = $insn_format35c_method_odex.size; } 861 | insn_format35mi_method { $size = $insn_format35mi_method.size; } 862 | insn_format35ms_method { $size = $insn_format35ms_method.size; } 863 | insn_format3rc_method { $size = $insn_format3rc_method.size; } 864 | insn_format3rc_method_odex { $size = $insn_format3rc_method_odex.size; } 865 | insn_format3rc_type { $size = $insn_format3rc_type.size; } 866 | insn_format3rmi_method { $size = $insn_format3rmi_method.size; } 867 | insn_format3rms_method { $size = $insn_format3rms_method.size; } 868 | insn_format51l { $size = $insn_format51l.size; } 869 | insn_array_data_directive { $size = $insn_array_data_directive.size; } 870 | insn_packed_switch_directive { $size = $insn_packed_switch_directive.size; } 871 | insn_sparse_switch_directive { $size = $insn_sparse_switch_directive.size; }; 872 873insn_format10t returns [int size] 874 : //e.g. goto endloop: 875 //e.g. goto +3 876 INSTRUCTION_FORMAT10t label_ref_or_offset {$size = Format.Format10t.size;} 877 -> ^(I_STATEMENT_FORMAT10t[$start, "I_STATEMENT_FORMAT10t"] INSTRUCTION_FORMAT10t label_ref_or_offset); 878 879insn_format10x returns [int size] 880 : //e.g. return-void 881 INSTRUCTION_FORMAT10x {$size = Format.Format10x.size;} 882 -> ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x); 883 884insn_format10x_odex returns [int size] 885 : //e.g. return-void-barrier 886 INSTRUCTION_FORMAT10x_ODEX {$size = Format.Format10x.size;} 887 { 888 throwOdexedInstructionException(input, $INSTRUCTION_FORMAT10x_ODEX.text); 889 }; 890 891insn_format11n returns [int size] 892 : //e.g. const/4 v0, 5 893 INSTRUCTION_FORMAT11n REGISTER COMMA integral_literal {$size = Format.Format11n.size;} 894 -> ^(I_STATEMENT_FORMAT11n[$start, "I_STATEMENT_FORMAT11n"] INSTRUCTION_FORMAT11n REGISTER integral_literal); 895 896insn_format11x returns [int size] 897 : //e.g. move-result-object v1 898 INSTRUCTION_FORMAT11x REGISTER {$size = Format.Format11x.size;} 899 -> ^(I_STATEMENT_FORMAT11x[$start, "I_STATEMENT_FORMAT11x"] INSTRUCTION_FORMAT11x REGISTER); 900 901insn_format12x returns [int size] 902 : //e.g. move v1 v2 903 instruction_format12x REGISTER COMMA REGISTER {$size = Format.Format12x.size;} 904 -> ^(I_STATEMENT_FORMAT12x[$start, "I_STATEMENT_FORMAT12x"] instruction_format12x REGISTER REGISTER); 905 906insn_format20bc returns [int size] 907 : //e.g. throw-verification-error generic-error, Lsome/class; 908 INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE COMMA verification_error_reference {$size += Format.Format20bc.size;} 909 { 910 if (!allowOdex || opcodes.getOpcodeByName($INSTRUCTION_FORMAT20bc.text) == null || apiLevel >= 14) { 911 throwOdexedInstructionException(input, $INSTRUCTION_FORMAT20bc.text); 912 } 913 } 914 -> ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE verification_error_reference); 915 916insn_format20t returns [int size] 917 : //e.g. goto/16 endloop: 918 INSTRUCTION_FORMAT20t label_ref_or_offset {$size = Format.Format20t.size;} 919 -> ^(I_STATEMENT_FORMAT20t[$start, "I_STATEMENT_FORMAT20t"] INSTRUCTION_FORMAT20t label_ref_or_offset); 920 921insn_format21c_field returns [int size] 922 : //e.g. sget-object v0, java/lang/System/out LJava/io/PrintStream; 923 INSTRUCTION_FORMAT21c_FIELD REGISTER COMMA fully_qualified_field {$size = Format.Format21c.size;} 924 -> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field); 925 926insn_format21c_field_odex returns [int size] 927 : //e.g. sget-object-volatile v0, java/lang/System/out LJava/io/PrintStream; 928 INSTRUCTION_FORMAT21c_FIELD_ODEX REGISTER COMMA fully_qualified_field {$size = Format.Format21c.size;} 929 { 930 if (!allowOdex || opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_FIELD_ODEX.text) == null || apiLevel >= 14) { 931 throwOdexedInstructionException(input, $INSTRUCTION_FORMAT21c_FIELD_ODEX.text); 932 } 933 } 934 -> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_FORMAT21c_FIELD_ODEX REGISTER fully_qualified_field); 935 936insn_format21c_string returns [int size] 937 : //e.g. const-string v1, "Hello World!" 938 INSTRUCTION_FORMAT21c_STRING REGISTER COMMA STRING_LITERAL {$size = Format.Format21c.size;} 939 -> ^(I_STATEMENT_FORMAT21c_STRING[$start, "I_STATEMENT_FORMAT21c_STRING"] INSTRUCTION_FORMAT21c_STRING REGISTER STRING_LITERAL); 940 941insn_format21c_type returns [int size] 942 : //e.g. const-class v2, Lorg/jf/HelloWorld2/HelloWorld2; 943 INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA reference_type_descriptor {$size = Format.Format21c.size;} 944 -> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor); 945 946insn_format21ih returns [int size] 947 : //e.g. const/high16 v1, 1234 948 INSTRUCTION_FORMAT21ih REGISTER COMMA fixed_32bit_literal {$size = Format.Format21ih.size;} 949 -> ^(I_STATEMENT_FORMAT21ih[$start, "I_STATEMENT_FORMAT21ih"] INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal); 950 951insn_format21lh returns [int size] 952 : //e.g. const-wide/high16 v1, 1234 953 INSTRUCTION_FORMAT21lh REGISTER COMMA fixed_32bit_literal {$size = Format.Format21lh.size;} 954 -> ^(I_STATEMENT_FORMAT21lh[$start, "I_STATEMENT_FORMAT21lh"] INSTRUCTION_FORMAT21lh REGISTER fixed_32bit_literal); 955 956insn_format21s returns [int size] 957 : //e.g. const/16 v1, 1234 958 INSTRUCTION_FORMAT21s REGISTER COMMA integral_literal {$size = Format.Format21s.size;} 959 -> ^(I_STATEMENT_FORMAT21s[$start, "I_STATEMENT_FORMAT21s"] INSTRUCTION_FORMAT21s REGISTER integral_literal); 960 961insn_format21t returns [int size] 962 : //e.g. if-eqz v0, endloop: 963 INSTRUCTION_FORMAT21t REGISTER COMMA (label_ref_or_offset) {$size = Format.Format21t.size;} 964 -> ^(I_STATEMENT_FORMAT21t[$start, "I_STATEMENT_FORMAT21t"] INSTRUCTION_FORMAT21t REGISTER label_ref_or_offset); 965 966insn_format22b returns [int size] 967 : //e.g. add-int v0, v1, 123 968 INSTRUCTION_FORMAT22b REGISTER COMMA REGISTER COMMA integral_literal {$size = Format.Format22b.size;} 969 -> ^(I_STATEMENT_FORMAT22b[$start, "I_STATEMENT_FORMAT22b"] INSTRUCTION_FORMAT22b REGISTER REGISTER integral_literal); 970 971insn_format22c_field returns [int size] 972 : //e.g. iput-object v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; 973 INSTRUCTION_FORMAT22c_FIELD REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format22c.size;} 974 -> ^(I_STATEMENT_FORMAT22c_FIELD[$start, "I_STATEMENT_FORMAT22c_FIELD"] INSTRUCTION_FORMAT22c_FIELD REGISTER REGISTER fully_qualified_field); 975 976insn_format22c_field_odex returns [int size] 977 : //e.g. iput-object-volatile v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; 978 INSTRUCTION_FORMAT22c_FIELD_ODEX REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format22c.size;} 979 { 980 if (!allowOdex || opcodes.getOpcodeByName($INSTRUCTION_FORMAT22c_FIELD_ODEX.text) == null || apiLevel >= 14) { 981 throwOdexedInstructionException(input, $INSTRUCTION_FORMAT22c_FIELD_ODEX.text); 982 } 983 } 984 -> ^(I_STATEMENT_FORMAT22c_FIELD[$start, "I_STATEMENT_FORMAT22c_FIELD"] INSTRUCTION_FORMAT22c_FIELD_ODEX REGISTER REGISTER fully_qualified_field); 985 986insn_format22c_type returns [int size] 987 : //e.g. instance-of v0, v1, Ljava/lang/String; 988 INSTRUCTION_FORMAT22c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor {$size = Format.Format22c.size;} 989 -> ^(I_STATEMENT_FORMAT22c_TYPE[$start, "I_STATEMENT_FORMAT22c_TYPE"] INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor); 990 991insn_format22cs_field returns [int size] 992 : //e.g. iget-quick v0, v1, field@0xc 993 INSTRUCTION_FORMAT22cs_FIELD REGISTER COMMA REGISTER COMMA FIELD_OFFSET 994 { 995 throwOdexedInstructionException(input, $INSTRUCTION_FORMAT22cs_FIELD.text); 996 }; 997 998insn_format22s returns [int size] 999 : //e.g. add-int/lit16 v0, v1, 12345 1000 instruction_format22s REGISTER COMMA REGISTER COMMA integral_literal {$size = Format.Format22s.size;} 1001 -> ^(I_STATEMENT_FORMAT22s[$start, "I_STATEMENT_FORMAT22s"] instruction_format22s REGISTER REGISTER integral_literal); 1002 1003insn_format22t returns [int size] 1004 : //e.g. if-eq v0, v1, endloop: 1005 INSTRUCTION_FORMAT22t REGISTER COMMA REGISTER COMMA label_ref_or_offset {$size = Format.Format22t.size;} 1006 -> ^(I_STATEMENT_FORMAT22t[$start, "I_STATEMENT_FFORMAT22t"] INSTRUCTION_FORMAT22t REGISTER REGISTER label_ref_or_offset); 1007 1008insn_format22x returns [int size] 1009 : //e.g. move/from16 v1, v1234 1010 INSTRUCTION_FORMAT22x REGISTER COMMA REGISTER {$size = Format.Format22x.size;} 1011 -> ^(I_STATEMENT_FORMAT22x[$start, "I_STATEMENT_FORMAT22x"] INSTRUCTION_FORMAT22x REGISTER REGISTER); 1012 1013insn_format23x returns [int size] 1014 : //e.g. add-int v1, v2, v3 1015 INSTRUCTION_FORMAT23x REGISTER COMMA REGISTER COMMA REGISTER {$size = Format.Format23x.size;} 1016 -> ^(I_STATEMENT_FORMAT23x[$start, "I_STATEMENT_FORMAT23x"] INSTRUCTION_FORMAT23x REGISTER REGISTER REGISTER); 1017 1018insn_format30t returns [int size] 1019 : //e.g. goto/32 endloop: 1020 INSTRUCTION_FORMAT30t label_ref_or_offset {$size = Format.Format30t.size;} 1021 -> ^(I_STATEMENT_FORMAT30t[$start, "I_STATEMENT_FORMAT30t"] INSTRUCTION_FORMAT30t label_ref_or_offset); 1022 1023insn_format31c returns [int size] 1024 : //e.g. const-string/jumbo v1 "Hello World!" 1025 INSTRUCTION_FORMAT31c REGISTER COMMA STRING_LITERAL {$size = Format.Format31c.size;} 1026 ->^(I_STATEMENT_FORMAT31c[$start, "I_STATEMENT_FORMAT31c"] INSTRUCTION_FORMAT31c REGISTER STRING_LITERAL); 1027 1028insn_format31i returns [int size] 1029 : //e.g. const v0, 123456 1030 instruction_format31i REGISTER COMMA fixed_32bit_literal {$size = Format.Format31i.size;} 1031 -> ^(I_STATEMENT_FORMAT31i[$start, "I_STATEMENT_FORMAT31i"] instruction_format31i REGISTER fixed_32bit_literal); 1032 1033insn_format31t returns [int size] 1034 : //e.g. fill-array-data v0, ArrayData: 1035 INSTRUCTION_FORMAT31t REGISTER COMMA label_ref_or_offset {$size = Format.Format31t.size;} 1036 { 1037 if ($INSTRUCTION_FORMAT31t.text.equals("packed-switch")) { 1038 CommonTree root = new CommonTree(new CommonToken(I_PACKED_SWITCH_DECLARATION, "I_PACKED_SWITCH_DECLARATION")); 1039 CommonTree address = new CommonTree(new CommonToken(I_ADDRESS, Integer.toString($method::currentAddress))); 1040 root.addChild(address); 1041 root.addChild($label_ref_or_offset.tree.dupNode()); 1042 $statements_and_directives::packedSwitchDeclarations.add(root); 1043 } else if ($INSTRUCTION_FORMAT31t.text.equals("sparse-switch")) { 1044 CommonTree root = new CommonTree(new CommonToken(I_SPARSE_SWITCH_DECLARATION, "I_SPARSE_SWITCH_DECLARATION")); 1045 CommonTree address = new CommonTree(new CommonToken(I_ADDRESS, Integer.toString($method::currentAddress))); 1046 root.addChild(address); 1047 root.addChild($label_ref_or_offset.tree.dupNode()); 1048 $statements_and_directives::sparseSwitchDeclarations.add(root); 1049 } 1050 } 1051 -> ^(I_STATEMENT_FORMAT31t[$start, "I_STATEMENT_FORMAT31t"] INSTRUCTION_FORMAT31t REGISTER label_ref_or_offset); 1052 1053insn_format32x returns [int size] 1054 : //e.g. move/16 v4567, v1234 1055 INSTRUCTION_FORMAT32x REGISTER COMMA REGISTER {$size = Format.Format32x.size;} 1056 -> ^(I_STATEMENT_FORMAT32x[$start, "I_STATEMENT_FORMAT32x"] INSTRUCTION_FORMAT32x REGISTER REGISTER); 1057 1058insn_format35c_method returns [int size] 1059 : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V 1060 INSTRUCTION_FORMAT35c_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format35c.size;} 1061 -> ^(I_STATEMENT_FORMAT35c_METHOD[$start, "I_STATEMENT_FORMAT35c_METHOD"] INSTRUCTION_FORMAT35c_METHOD register_list fully_qualified_method); 1062 1063insn_format35c_type returns [int size] 1064 : //e.g. filled-new-array {v0,v1}, I 1065 INSTRUCTION_FORMAT35c_TYPE OPEN_BRACE register_list CLOSE_BRACE COMMA nonvoid_type_descriptor {$size = Format.Format35c.size;} 1066 -> ^(I_STATEMENT_FORMAT35c_TYPE[$start, "I_STATEMENT_FORMAT35c_TYPE"] INSTRUCTION_FORMAT35c_TYPE register_list nonvoid_type_descriptor); 1067 1068insn_format35c_method_odex returns [int size] 1069 : //e.g. invoke-direct {p0}, Ljava/lang/Object;-><init>()V 1070 INSTRUCTION_FORMAT35c_METHOD_ODEX OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method 1071 { 1072 throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35c_METHOD_ODEX.text); 1073 }; 1074 1075insn_format35mi_method returns [int size] 1076 : //e.g. execute-inline {v0, v1}, inline@0x4 1077 INSTRUCTION_FORMAT35mi_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA INLINE_INDEX 1078 { 1079 throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35mi_METHOD.text); 1080 }; 1081 1082insn_format35ms_method returns [int size] 1083 : //e.g. invoke-virtual-quick {v0, v1}, vtable@0x4 1084 INSTRUCTION_FORMAT35ms_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA VTABLE_INDEX 1085 { 1086 throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35ms_METHOD.text); 1087 }; 1088 1089insn_format3rc_method returns [int size] 1090 : //e.g. invoke-virtual/range {v25..v26}, java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; 1091 INSTRUCTION_FORMAT3rc_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format3rc.size;} 1092 -> ^(I_STATEMENT_FORMAT3rc_METHOD[$start, "I_STATEMENT_FORMAT3rc_METHOD"] INSTRUCTION_FORMAT3rc_METHOD register_range fully_qualified_method); 1093 1094insn_format3rc_method_odex returns [int size] 1095 : //e.g. invoke-object-init/range {p0}, Ljava/lang/Object;-><init>()V 1096 INSTRUCTION_FORMAT3rc_METHOD_ODEX OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method 1097 { 1098 throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rc_METHOD_ODEX.text); 1099 }; 1100 1101insn_format3rc_type returns [int size] 1102 : //e.g. filled-new-array/range {v0..v6}, I 1103 INSTRUCTION_FORMAT3rc_TYPE OPEN_BRACE register_range CLOSE_BRACE COMMA nonvoid_type_descriptor {$size = Format.Format3rc.size;} 1104 -> ^(I_STATEMENT_FORMAT3rc_TYPE[$start, "I_STATEMENT_FORMAT3rc_TYPE"] INSTRUCTION_FORMAT3rc_TYPE register_range nonvoid_type_descriptor); 1105 1106insn_format3rmi_method returns [int size] 1107 : //e.g. execute-inline/range {v0 .. v10}, inline@0x14 1108 INSTRUCTION_FORMAT3rmi_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA INLINE_INDEX 1109 { 1110 throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rmi_METHOD.text); 1111 }; 1112 1113insn_format3rms_method returns [int size] 1114 : //e.g. invoke-virtual-quick/range {v0 .. v10}, vtable@0x14 1115 INSTRUCTION_FORMAT3rms_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA VTABLE_INDEX 1116 { 1117 throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rms_METHOD.text); 1118 }; 1119 1120insn_format51l returns [int size] 1121 : //e.g. const-wide v0, 5000000000L 1122 INSTRUCTION_FORMAT51l REGISTER COMMA fixed_literal {$size = Format.Format51l.size;} 1123 -> ^(I_STATEMENT_FORMAT51l[$start, "I_STATEMENT_FORMAT51l"] INSTRUCTION_FORMAT51l REGISTER fixed_literal); 1124 1125insn_array_data_directive returns [int size] 1126 : ARRAY_DATA_DIRECTIVE 1127 parsed_integer_literal 1128 { 1129 int elementWidth = $parsed_integer_literal.value; 1130 if (elementWidth != 4 && elementWidth != 8 && elementWidth != 1 && elementWidth != 2) { 1131 throw new SemanticException(input, $start, "Invalid element width: \%d. Must be 1, 2, 4 or 8", elementWidth); 1132 } 1133 } 1134 1135 (fixed_literal {$size+=elementWidth;})* END_ARRAY_DATA_DIRECTIVE 1136 {$size = (($size + 1) & ~1) + 8;} 1137 1138 -> ^(I_STATEMENT_ARRAY_DATA[$start, "I_STATEMENT_ARRAY_DATA"] ^(I_ARRAY_ELEMENT_SIZE parsed_integer_literal) 1139 ^(I_ARRAY_ELEMENTS fixed_literal*)); 1140 1141insn_packed_switch_directive returns [int size] 1142 : PACKED_SWITCH_DIRECTIVE 1143 fixed_32bit_literal 1144 1145 (switch_target += label_ref_or_offset {$size+=4;})* 1146 1147 END_PACKED_SWITCH_DIRECTIVE {$size = $size + 8;} 1148 1149 -> ^(I_STATEMENT_PACKED_SWITCH[$start, "I_STATEMENT_PACKED_SWITCH"] 1150 ^(I_PACKED_SWITCH_START_KEY[$start, "I_PACKED_SWITCH_START_KEY"] fixed_32bit_literal) 1151 ^(I_PACKED_SWITCH_ELEMENTS[$start, "I_PACKED_SWITCH_ELEMENTS"] 1152 $switch_target*) 1153 ); 1154 1155insn_sparse_switch_directive returns [int size] 1156 : SPARSE_SWITCH_DIRECTIVE 1157 (fixed_32bit_literal ARROW switch_target += label_ref_or_offset {$size += 8;})* 1158 1159 END_SPARSE_SWITCH_DIRECTIVE {$size = $size + 4;} 1160 1161 -> ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"] 1162 ^(I_SPARSE_SWITCH_ELEMENTS[$start, "I_SPARSE_SWITCH_ELEMENTS"] (fixed_32bit_literal $switch_target)*));