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