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