1# pylint:disable=no-self-use 2from typing import Tuple, Optional 3import logging 4 5import ailment 6import pyvex 7import archinfo 8 9from ...engines.vex.claripy.irop import UnsupportedIROpError, vexop_to_simop 10from ...code_location import CodeLocation 11from ...utils.constants import DEFAULT_STATEMENT 12from ..engine import SimEngine 13 14 15class SimEngineLight(SimEngine): 16 def __init__(self): 17 super(SimEngineLight, self).__init__() 18 19 self.l = logging.getLogger(self.__module__ + "." + self.__class__.__name__) 20 21 # local variables 22 self.state = None 23 self.arch = None 24 self.block = None 25 self._call_stack = None 26 27 self.stmt_idx = None 28 self.ins_addr = None 29 self.tmps = None 30 31 # for VEX blocks only 32 self.tyenv = None 33 34 def process(self, state, *args, **kwargs): 35 # we are using a completely different state. Therefore, we directly call our _process() method before 36 # SimEngine becomes flexible enough. 37 self._process(state, None, block=kwargs.pop('block', None), whitelist=kwargs.pop('whitelist', None)) 38 39 def _process(self, new_state, successors, *args, **kwargs): 40 raise NotImplementedError() 41 42 def _check(self, state, *args, **kwargs): 43 return True 44 45 # 46 # Helper methods 47 # 48 49 @property 50 def _context(self) -> Optional[Tuple[int]]: 51 if self._call_stack is None: 52 # contextless mode 53 return None 54 55 if not self._call_stack: 56 # contextful but the callstack is empty 57 return tuple() 58 59 # Convert to Tuple to make `context` hashable if not None 60 call_stack_addresses = tuple(self._call_stack) 61 return call_stack_addresses 62 63 def _codeloc(self, block_only=False): 64 return CodeLocation(self.block.addr, 65 None if block_only else self.stmt_idx, 66 ins_addr=None if block_only else self.ins_addr, 67 context=self._context 68 ) 69 70 71class SimEngineLightVEXMixin: 72 73 def _process(self, state, successors, *args, block, whitelist=None, **kwargs): # pylint:disable=arguments-differ,unused-argument 74 75 # initialize local variables 76 self.tmps = {} 77 self.block = block 78 self.state = state 79 80 if state is not None: 81 self.arch: archinfo.Arch = state.arch 82 83 self.tyenv = block.vex.tyenv 84 85 self._process_Stmt(whitelist=whitelist) 86 87 self.stmt_idx = None 88 self.ins_addr = None 89 90 def _process_Stmt(self, whitelist=None): 91 92 if whitelist is not None: 93 # optimize whitelist lookups 94 whitelist = set(whitelist) 95 96 for stmt_idx, stmt in enumerate(self.block.vex.statements): 97 if whitelist is not None and stmt_idx not in whitelist: 98 continue 99 self.stmt_idx = stmt_idx 100 101 if type(stmt) is pyvex.IRStmt.IMark: 102 # Note that we cannot skip IMarks as they are used later to trigger observation events 103 # The bug caused by skipping IMarks is reported at https://github.com/angr/angr/pull/1150 104 self.ins_addr = stmt.addr + stmt.delta 105 106 self._handle_Stmt(stmt) 107 108 self._process_block_end() 109 110 def _process_block_end(self): 111 # handle calls to another function 112 # Note that without global information, we cannot handle cases where we *jump* to another function (jumpkind == 113 # "Ijk_Boring"). Users are supposed to overwrite this method, detect these cases with the help of global 114 # information (such as CFG or symbol addresses), and handle them accordingly. 115 if self.block.vex.jumpkind == 'Ijk_Call': 116 self.stmt_idx = DEFAULT_STATEMENT 117 handler = '_handle_function' 118 if hasattr(self, handler): 119 func_addr = self._expr(self.block.vex.next) 120 if func_addr is not None: 121 getattr(self, handler)(func_addr) 122 else: 123 self.l.debug('Cannot determine the callee address at %#x.', self.block.addr) 124 else: 125 self.l.warning('Function handler not implemented.') 126 127 # 128 # Statement handlers 129 # 130 131 def _handle_Stmt(self, stmt): 132 handler = "_handle_%s" % type(stmt).__name__ 133 if hasattr(self, handler): 134 getattr(self, handler)(stmt) 135 elif type(stmt).__name__ not in ('IMark', 'AbiHint'): 136 self.l.error('Unsupported statement type %s.', type(stmt).__name__) 137 138 # synchronize with function _handle_WrTmpData() 139 def _handle_WrTmp(self, stmt): 140 data = self._expr(stmt.data) 141 if data is None: 142 return 143 144 self.tmps[stmt.tmp] = data 145 146 # invoked by LoadG 147 def _handle_WrTmpData(self, tmp, data): 148 if data is None: 149 return 150 self.tmps[tmp] = data 151 152 def _handle_Put(self, stmt): 153 raise NotImplementedError('Please implement the Put handler with your own logic.') 154 155 def _handle_Store(self, stmt): 156 raise NotImplementedError('Please implement the Store handler with your own logic.') 157 158 def _handle_StoreG(self, stmt): 159 raise NotImplementedError('Please implement the StoreG handler with your own logic.') 160 161 def _handle_LLSC(self, stmt: pyvex.IRStmt.LLSC): 162 raise NotImplementedError('Please implement the LLSC handler with your own logic.') 163 164 # 165 # Expression handlers 166 # 167 168 def _expr(self, expr): 169 170 handler = "_handle_%s" % type(expr).__name__ 171 if hasattr(self, handler): 172 return getattr(self, handler)(expr) 173 else: 174 self.l.error('Unsupported expression type %s.', type(expr).__name__) 175 return None 176 177 def _handle_RdTmp(self, expr): 178 tmp = expr.tmp 179 180 if tmp in self.tmps: 181 return self.tmps[tmp] 182 return None 183 184 def _handle_Get(self, expr): 185 raise NotImplementedError('Please implement the Get handler with your own logic.') 186 187 def _handle_Load(self, expr): 188 raise NotImplementedError('Please implement the Load handler with your own logic.') 189 190 def _handle_LoadG(self, stmt): 191 raise NotImplementedError('Please implement the LoadG handler with your own logic.') 192 193 def _handle_Exit(self, stmt): 194 self._expr(stmt.guard) 195 self._expr(stmt.dst) 196 197 def _handle_ITE(self, expr): 198 # EDG says: Not sure how generic this is. 199 cond = self._expr(expr.cond) 200 if cond is True: 201 return self._expr(expr.iftrue) 202 elif cond is False: 203 return self._expr(expr.iffalse) 204 else: 205 return None 206 207 def _handle_Unop(self, expr): 208 handler = None 209 210 # All conversions are handled by the Conversion handler 211 simop = None 212 try: 213 simop = vexop_to_simop(expr.op) 214 except UnsupportedIROpError: 215 pass 216 217 if simop is not None and simop.op_attrs.get('conversion', None): 218 handler = '_handle_Conversion' 219 # Notice order of "Not" comparisons 220 elif expr.op == 'Iop_Not1': 221 handler = '_handle_Not1' 222 elif expr.op.startswith('Iop_Not'): 223 handler = '_handle_Not' 224 225 if handler is not None and hasattr(self, handler): 226 return getattr(self, handler)(expr) 227 else: 228 self.l.error('Unsupported Unop %s.', expr.op) 229 return None 230 231 def _handle_Binop(self, expr): 232 handler = None 233 if expr.op.startswith('Iop_And'): 234 handler = '_handle_And' 235 elif expr.op.startswith('Iop_Mod'): 236 handler = '_handle_Mod' 237 elif expr.op.startswith('Iop_Or'): 238 handler = '_handle_Or' 239 elif expr.op.startswith('Iop_Add'): 240 handler = '_handle_Add' 241 elif expr.op.startswith('Iop_Sub'): 242 handler = '_handle_Sub' 243 elif expr.op.startswith('Iop_Mul'): 244 handler = "_handle_Mul" 245 elif expr.op.startswith('Iop_Div'): 246 handler = "_handle_Div" 247 elif expr.op.startswith('Iop_Xor'): 248 handler = '_handle_Xor' 249 elif expr.op.startswith('Iop_Shl'): 250 handler = '_handle_Shl' 251 elif expr.op.startswith('Iop_Shr'): 252 handler = '_handle_Shr' 253 elif expr.op.startswith('Iop_Sal'): 254 # intended use of SHL 255 handler = '_handle_Shl' 256 elif expr.op.startswith('Iop_Sar'): 257 handler = '_handle_Sar' 258 elif expr.op.startswith('Iop_CmpEQ'): 259 handler = '_handle_CmpEQ' 260 elif expr.op.startswith('Iop_CmpNE'): 261 handler = '_handle_CmpNE' 262 elif expr.op.startswith('Iop_CmpLT'): 263 handler = '_handle_CmpLT' 264 elif expr.op.startswith('Iop_CmpLE'): 265 handler = '_handle_CmpLE' 266 elif expr.op.startswith('Iop_CmpGE'): 267 handler = '_handle_CmpGE' 268 elif expr.op.startswith('Iop_CmpGT'): 269 handler = '_handle_CmpGT' 270 elif expr.op.startswith('Iop_CmpORD'): 271 handler = '_handle_CmpORD' 272 elif expr.op == 'Iop_32HLto64': 273 handler = '_handle_32HLto64' 274 elif expr.op.startswith('Const'): 275 handler = '_handle_Const' 276 if handler is not None and hasattr(self, handler): 277 return getattr(self, handler)(expr) 278 else: 279 self.l.error('Unsupported Binop %s.', expr.op) 280 281 return None 282 283 def _handle_CCall(self, expr): # pylint:disable=useless-return 284 self.l.warning('Unsupported expression type CCall with callee %s.', str(expr.cee)) 285 return None 286 287 # 288 # Unary operation handlers 289 # 290 291 def _handle_U32(self, expr): 292 return expr.value 293 294 def _handle_U64(self, expr): 295 return expr.value 296 297 def _handle_U16(self, expr): 298 return expr.value 299 300 def _handle_U8(self, expr): 301 return expr.value 302 303 def _handle_U1(self, expr): 304 return expr.value 305 306 def _handle_Const(self, expr): # pylint:disable=no-self-use 307 return expr.con.value 308 309 def _handle_Conversion(self, expr): 310 expr = self._expr(expr.args[0]) 311 if expr is None: 312 return None 313 314 # FIXME: implement real conversion 315 return expr 316 317 # 318 # Binary operation handlers 319 # 320 321 def _handle_And(self, expr): 322 arg0, arg1 = expr.args 323 expr_0 = self._expr(arg0) 324 if expr_0 is None: 325 return None 326 expr_1 = self._expr(arg1) 327 if expr_1 is None: 328 return None 329 330 try: 331 return expr_0 & expr_1 332 except TypeError as e: 333 self.l.warning(e) 334 return None 335 336 def _handle_Or(self, expr): 337 arg0, arg1 = expr.args 338 expr_0 = self._expr(arg0) 339 if expr_0 is None: 340 return None 341 expr_1 = self._expr(arg1) 342 if expr_1 is None: 343 return None 344 345 try: 346 return expr_0 | expr_1 347 except TypeError as e: 348 self.l.warning(e) 349 return None 350 351 def _handle_Not1(self, expr): 352 return self._handle_Not(expr) 353 354 def _handle_Not(self, expr): 355 arg0 = expr.args[0] 356 expr_0 = self._expr(arg0) 357 if expr_0 is None: 358 return None 359 try: 360 return ~expr_0 # pylint:disable=invalid-unary-operand-type 361 except TypeError as e: 362 self.l.exception(e) 363 return None 364 365 def _handle_Add(self, expr): 366 arg0, arg1 = expr.args 367 expr_0 = self._expr(arg0) 368 if expr_0 is None: 369 return None 370 expr_1 = self._expr(arg1) 371 if expr_1 is None: 372 return None 373 374 try: 375 if isinstance(expr_0, int) and isinstance(expr_1, int): 376 # self.tyenv is not used 377 mask = (1 << expr.result_size(self.tyenv)) - 1 378 return (expr_0 + expr_1) & mask 379 else: 380 return expr_0 + expr_1 381 except TypeError as e: 382 self.l.warning(e) 383 return None 384 385 def _handle_Sub(self, expr): 386 arg0, arg1 = expr.args 387 expr_0 = self._expr(arg0) 388 if expr_0 is None: 389 return None 390 expr_1 = self._expr(arg1) 391 if expr_1 is None: 392 return None 393 394 try: 395 if isinstance(expr_0, int) and isinstance(expr_1, int): 396 # self.tyenv is not used 397 mask = (1 << expr.result_size(self.tyenv)) - 1 398 return (expr_0 - expr_1) & mask 399 else: 400 return expr_0 - expr_1 401 except TypeError as e: 402 self.l.warning(e) 403 return None 404 405 def _handle_Mul(self, expr): 406 arg0, arg1 = expr.args 407 expr_0 = self._expr(arg0) 408 if expr_0 is None: 409 return None 410 expr_1 = self._expr(arg1) 411 if expr_1 is None: 412 return None 413 414 try: 415 if isinstance(expr_0, int) and isinstance(expr_1, int): 416 # self.tyenv is not used 417 mask = (1 << expr.result_size(self.tyenv)) - 1 418 return (expr_0 * expr_1) & mask 419 else: 420 return expr_0 * expr_1 421 except TypeError as e: 422 self.l.warning(e) 423 return None 424 425 def _handle_Div(self, expr): 426 arg0, arg1 = expr.args 427 expr_0 = self._expr(arg0) 428 if expr_0 is None: 429 return None 430 expr_1 = self._expr(arg1) 431 if expr_1 is None: 432 return None 433 434 try: 435 # TODO: Probably should take care of the sign 436 return expr_0 // expr_1 437 except TypeError as e: 438 self.l.warning(e) 439 return None 440 except ZeroDivisionError as e: 441 self.l.warning(e) 442 return None 443 444 def _handle_Mod(self, expr): 445 arg0, arg1 = expr.args 446 expr_0 = self._expr(arg0) 447 if expr_0 is None: 448 return None 449 expr_1 = self._expr(arg1) 450 if expr_1 is None: 451 return None 452 453 try: 454 # TODO: Probably should take care of the sign 455 return expr_0 - (expr_0 // expr_1)*expr_1 456 except TypeError as e: 457 self.l.warning(e) 458 return None 459 460 def _handle_Xor(self, expr): 461 arg0, arg1 = expr.args 462 expr_0 = self._expr(arg0) 463 if expr_0 is None: 464 return None 465 expr_1 = self._expr(arg1) 466 if expr_1 is None: 467 return None 468 469 try: 470 return expr_0 ^ expr_1 471 except TypeError as e: 472 self.l.warning(e) 473 return None 474 475 def _handle_Shl(self, expr): 476 arg0, arg1 = expr.args 477 478 expr_0 = self._expr(arg0) 479 if expr_0 is None: 480 return None 481 expr_1 = self._expr(arg1) 482 if expr_1 is None: 483 return None 484 #elif expr_1 < 0: 485 # expr.args = [expr_0, -1*expr_1] 486 # return self._handle_Shr(expr) 487 try: 488 if isinstance(expr_0, int) and isinstance(expr_1, int): 489 # self.tyenv is not used 490 mask = (1 << expr.result_size(self.tyenv)) - 1 491 if expr_1 < 0: 492 return (expr_0 >> -expr_1) & mask 493 else: 494 return (expr_0 << expr_1) & mask 495 else: 496 return expr_0 << expr_1 497 except TypeError as e: 498 self.l.warning(e) 499 return None 500 501 def _handle_Shr(self, expr): 502 arg0, arg1 = expr.args 503 expr_0 = self._expr(arg0) 504 if expr_0 is None: 505 return None 506 expr_1 = self._expr(arg1) 507 if expr_1 is None: 508 return None 509 510 try: 511 if expr_1 < 0: 512 return expr_0 << -expr_1 513 else: 514 return expr_0 >> expr_1 515 except TypeError as e: 516 self.l.warning(e) 517 return None 518 519 def _handle_Sar(self, expr): 520 # EDG asks: is this right? 521 arg0, arg1 = expr.args 522 expr_0 = self._expr(arg0) 523 if expr_0 is None: 524 return None 525 expr_1 = self._expr(arg1) 526 if expr_1 is None: 527 return None 528 try: 529 return expr_0 >> expr_1 530 except TypeError as e: 531 self.l.warning(e) 532 return None 533 534 def _handle_CmpEQ(self, expr): 535 arg0, arg1 = expr.args 536 expr_0 = self._expr(arg0) 537 if expr_0 is None: 538 return None 539 expr_1 = self._expr(arg1) 540 if expr_1 is None: 541 return None 542 543 try: 544 return expr_0 == expr_1 545 except TypeError as ex: 546 self.l.warning(ex) 547 return None 548 549 def _handle_CmpNE(self, expr): 550 arg0, arg1 = expr.args 551 expr_0 = self._expr(arg0) 552 if expr_0 is None: 553 return None 554 expr_1 = self._expr(arg1) 555 if expr_1 is None: 556 return None 557 558 try: 559 return expr_0 != expr_1 560 except TypeError as ex: 561 self.l.warning(ex) 562 return None 563 564 def _handle_CmpLE(self, expr): 565 arg0, arg1 = expr.args 566 expr_0 = self._expr(arg0) 567 if expr_0 is None: 568 return None 569 expr_1 = self._expr(arg1) 570 if expr_1 is None: 571 return None 572 573 try: 574 return expr_0 <= expr_1 575 except TypeError as ex: 576 self.l.warning(ex) 577 return None 578 579 def _handle_CmpGE(self, expr): 580 arg0, arg1 = expr.args 581 expr_0 = self._expr(arg0) 582 if expr_0 is None: 583 return None 584 expr_1 = self._expr(arg1) 585 if expr_1 is None: 586 return None 587 588 try: 589 return expr_0 >= expr_1 590 except TypeError as ex: 591 self.l.warning(ex) 592 return None 593 594 def _handle_CmpLT(self, expr): 595 arg0, arg1 = expr.args 596 expr_0 = self._expr(arg0) 597 if expr_0 is None: 598 return None 599 expr_1 = self._expr(arg1) 600 if expr_1 is None: 601 return None 602 603 try: 604 return expr_0 < expr_1 605 except TypeError as ex: 606 self.l.warning(ex) 607 return None 608 609 def _handle_CmpGT(self, expr): 610 arg0, arg1 = expr.args 611 expr_0 = self._expr(arg0) 612 if expr_0 is None: 613 return None 614 expr_1 = self._expr(arg1) 615 if expr_1 is None: 616 return None 617 618 try: 619 return expr_0 > expr_1 620 except TypeError as ex: 621 self.l.warning(ex) 622 return None 623 624 def _handle_MBE(self, expr): # pylint:disable=unused-argument 625 # Yeah.... no. 626 return None 627 628 def _handle_32HLto64(self, expr): 629 arg0, arg1 = expr.args 630 expr_0 = self._expr(arg0) 631 if expr_0 is None: 632 return None 633 expr_1 = self._expr(arg1) 634 if expr_1 is None: 635 return None 636 637 return None 638 639 640class SimEngineLightAILMixin: 641 642 def _process(self, state, successors, *args, block=None, whitelist=None, **kwargs): # pylint:disable=arguments-differ,unused-argument 643 644 self.tmps = {} 645 self.block = block 646 self.state = state 647 self.arch = state.arch 648 649 self._process_Stmt(whitelist=whitelist) 650 651 self.stmt_idx = None 652 self.ins_addr = None 653 654 def _process_Stmt(self, whitelist=None): 655 656 if whitelist is not None: 657 whitelist = set(whitelist) 658 659 for stmt_idx, stmt in enumerate(self.block.statements): 660 if whitelist is not None and stmt_idx not in whitelist: 661 continue 662 663 self.stmt_idx = stmt_idx 664 self.ins_addr = stmt.ins_addr 665 666 self._handle_Stmt(stmt) 667 668 def _expr(self, expr): 669 670 expr_type_name = type(expr).__name__ 671 if isinstance(expr, ailment.Stmt.Call): 672 # Call can be both an expression and a statement. Add a suffix to make sure we are working on the expression 673 # variant. 674 expr_type_name += "Expr" 675 676 h = None 677 handler = "_handle_%s" % expr_type_name 678 if hasattr(self, handler): 679 h = getattr(self, handler) 680 681 if h is None: 682 handler = "_ail_handle_%s" % expr_type_name 683 if hasattr(self, handler): 684 h = getattr(self, handler) 685 686 if h is not None: 687 return h(expr) 688 self.l.warning('Unsupported expression type %s.', type(expr).__name__) 689 return None 690 691 # 692 # Helper methods 693 # 694 695 def _codeloc(self): 696 return CodeLocation(self.block.addr, self.stmt_idx, ins_addr=self.ins_addr, context=self._context) 697 698 # 699 # Statement handlers 700 # 701 702 def _handle_Stmt(self, stmt): 703 handler = "_handle_%s" % type(stmt).__name__ 704 if hasattr(self, handler): 705 getattr(self, handler)(stmt) 706 return 707 708 # compatibility 709 old_handler = "_ail_handle_%s" % type(stmt).__name__ 710 if hasattr(self, old_handler): 711 getattr(self, old_handler)(stmt) 712 return 713 714 self.l.warning('Unsupported statement type %s.', type(stmt).__name__) 715 716 def _ail_handle_Jump(self, stmt): 717 raise NotImplementedError('Please implement the Jump handler with your own logic.') 718 719 def _ail_handle_Call(self, stmt): 720 raise NotImplementedError('Please implement the Call handler with your own logic.') 721 722 def _ail_handle_Return(self, stmt): 723 raise NotImplementedError('Please implement the Return handler with your own logic.') 724 725 # 726 # Expression handlers 727 # 728 729 def _ail_handle_Const(self, expr): # pylint:disable=no-self-use 730 return expr.value 731 732 def _ail_handle_Tmp(self, expr): 733 tmp_idx = expr.tmp_idx 734 735 try: 736 return self.tmps[tmp_idx] 737 except KeyError: 738 return None 739 740 def _ail_handle_Load(self, expr): 741 raise NotImplementedError('Please implement the Load handler with your own logic.') 742 743 def _ail_handle_CallExpr(self, expr): 744 raise NotImplementedError('Please implement the CallExpr handler with your own logic.') 745 746 def _ail_handle_UnaryOp(self, expr): 747 handler_name = '_ail_handle_%s' % expr.op 748 try: 749 handler = getattr(self, handler_name) 750 except AttributeError: 751 self.l.warning('Unsupported UnaryOp %s.', expr.op) 752 return None 753 754 return handler(expr) 755 756 def _ail_handle_BinaryOp(self, expr): 757 handler_name = '_ail_handle_%s' % expr.op 758 try: 759 handler = getattr(self, handler_name) 760 except AttributeError: 761 self.l.warning('Unsupported BinaryOp %s.', expr.op) 762 return None 763 764 return handler(expr) 765 766 # 767 # Binary operation handlers 768 # 769 770 def _ail_handle_CmpLT(self, expr): 771 772 arg0, arg1 = expr.operands 773 774 expr_0 = self._expr(arg0) 775 expr_1 = self._expr(arg1) 776 if expr_0 is None: 777 expr_0 = arg0 778 if expr_1 is None: 779 expr_1 = arg1 780 781 try: 782 return expr_0 <= expr_1 783 except TypeError: 784 return ailment.Expr.BinaryOp(expr.idx, 'CmpLT', [expr_0, expr_1], expr.signed, **expr.tags) 785 786 def _ail_handle_Add(self, expr): 787 788 arg0, arg1 = expr.operands 789 790 expr_0 = self._expr(arg0) 791 expr_1 = self._expr(arg1) 792 if expr_0 is None: 793 expr_0 = arg0 794 if expr_1 is None: 795 expr_1 = arg1 796 797 try: 798 return expr_0 + expr_1 799 except TypeError: 800 return ailment.Expr.BinaryOp(expr.idx, 'Add', [expr_0, expr_1], expr.signed, **expr.tags) 801 802 def _ail_handle_Sub(self, expr): 803 804 arg0, arg1 = expr.operands 805 806 expr_0 = self._expr(arg0) 807 expr_1 = self._expr(arg1) 808 809 if expr_0 is None: 810 expr_0 = arg0 811 if expr_1 is None: 812 expr_1 = arg1 813 814 try: 815 return expr_0 - expr_1 816 except TypeError: 817 return ailment.Expr.BinaryOp(expr.idx, 'Sub', [expr_0, expr_1], expr.signed, **expr.tags) 818 819 def _ail_handle_Div(self, expr): 820 821 arg0, arg1 = expr.operands 822 823 expr_0 = self._expr(arg0) 824 expr_1 = self._expr(arg1) 825 826 if expr_0 is None: 827 expr_0 = arg0 828 if expr_1 is None: 829 expr_1 = arg1 830 831 try: 832 return expr_0 // expr_1 833 except TypeError: 834 return ailment.Expr.BinaryOp(expr.idx, 'Div', [expr_0, expr_1], expr.signed, **expr.tags) 835 836 def _ail_handle_DivMod(self, expr): 837 return self._ail_handle_Div(expr) 838 839 def _ail_handle_Mul(self, expr): 840 841 arg0, arg1 = expr.operands 842 843 expr_0 = self._expr(arg0) 844 expr_1 = self._expr(arg1) 845 846 if expr_0 is None: 847 expr_0 = arg0 848 if expr_1 is None: 849 expr_1 = arg1 850 851 try: 852 return expr_0 * expr_1 853 except TypeError: 854 return ailment.Expr.BinaryOp(expr.idx, 'Mul', [expr_0, expr_1], expr.signed, **expr.tags) 855 856 def _ail_handle_Mull(self, expr): 857 return self._ail_handle_Mul(expr) 858 859 def _ail_handle_And(self, expr): 860 861 arg0, arg1 = expr.operands 862 863 expr_0 = self._expr(arg0) 864 expr_1 = self._expr(arg1) 865 866 if expr_0 is None: 867 expr_0 = arg0 868 if expr_1 is None: 869 expr_1 = arg1 870 871 try: 872 return expr_0 & expr_1 873 except TypeError: 874 return ailment.Expr.BinaryOp(expr.idx, 'And', [expr_0, expr_1], expr.signed, **expr.tags) 875 876 def _ail_handle_Or(self, expr): 877 878 arg0, arg1 = expr.operands 879 880 expr_0 = self._expr(arg0) 881 expr_1 = self._expr(arg1) 882 883 if expr_0 is None: 884 expr_0 = arg0 885 if expr_1 is None: 886 expr_1 = arg1 887 888 try: 889 return expr_0 | expr_1 890 except TypeError: 891 return ailment.Expr.BinaryOp(expr.idx, 'Or', [expr_0, expr_1], expr.signed, **expr.tags) 892 893 def _ail_handle_Xor(self, expr): 894 895 arg0, arg1 = expr.operands 896 897 expr_0 = self._expr(arg0) 898 expr_1 = self._expr(arg1) 899 900 if expr_0 is None: 901 expr_0 = arg0 902 if expr_1 is None: 903 expr_1 = arg1 904 905 try: 906 return expr_0 ^ expr_1 907 except TypeError: 908 return ailment.Expr.BinaryOp(expr.idx, 'Xor', [expr_0, expr_1], expr.signed, **expr.tags) 909 910 def _ail_handle_Shr(self, expr): 911 912 arg0, arg1 = expr.operands 913 expr_0 = self._expr(arg0) 914 expr_1 = self._expr(arg1) 915 916 if expr_0 is None: 917 expr_0 = arg0 918 if expr_1 is None: 919 expr_1 = arg1 920 921 try: 922 return expr_0 >> expr_1 923 except TypeError: 924 return ailment.Expr.BinaryOp(expr.idx, 'Shr', [expr_0, expr_1], expr.signed, **expr.tags) 925 926 def _ail_handle_Shl(self, expr): 927 928 arg0, arg1 = expr.operands 929 expr_0 = self._expr(arg0) 930 expr_1 = self._expr(arg1) 931 932 if expr_0 is None: 933 expr_0 = arg0 934 if expr_1 is None: 935 expr_1 = arg1 936 937 try: 938 return expr_0 << expr_1 939 except TypeError: 940 return ailment.Expr.BinaryOp(expr.idx, 'Shl', [expr_0, expr_1], expr.signed, **expr.tags) 941 942 def _ail_handle_Sal(self, expr): 943 return self._ail_handle_Shl(expr) 944 945 def _ail_handle_Sar(self, expr): 946 947 arg0, arg1 = expr.operands 948 expr_0 = self._expr(arg0) 949 expr_1 = self._expr(arg1) 950 951 if expr_0 is None: 952 expr_0 = arg0 953 if expr_1 is None: 954 expr_1 = arg1 955 956 try: 957 return expr_0 >> expr_1 958 except TypeError: 959 return ailment.Expr.BinaryOp(expr.idx, 'Sar', [expr_0, expr_1], expr.signed, **expr.tags) 960 961 def _ail_handle_Concat(self, expr): 962 963 arg0, arg1 = expr.operands 964 expr_0 = self._expr(arg0) 965 expr_1 = self._expr(arg1) 966 967 if expr_0 is None: 968 expr_0 = arg0 969 if expr_1 is None: 970 expr_1 = arg1 971 972 return ailment.Expr.BinaryOp(expr.idx, 'Concat', [expr_0, expr_1], expr.signed, **expr.tags) 973 974 # 975 # Unary operation handlers 976 # 977 978 def _ail_handle_Convert(self, expr): 979 data = self._expr(expr.operand) 980 if data is not None: 981 if type(data) is int: 982 return data 983 return None 984 985 def _ail_handle_Not(self, expr): 986 987 data = self._expr(expr.operand) 988 if data is None: 989 return None 990 991 try: 992 return ~data # pylint:disable=invalid-unary-operand-type 993 except TypeError: 994 return ailment.Expr.UnaryOp(expr.idx, 'Not', data, **expr.tags) 995 996 997# Compatibility 998SimEngineLightVEX = SimEngineLightVEXMixin 999SimEngineLightAIL = SimEngineLightAILMixin 1000