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