Repository: angr/angr

Issue:
CFG aarch64 crash while loading the library
Description:
angr module CFG crash while loading aarch64 binary. angr is up to date

[libstdc++.so.zip](https://github.com/angr/angr/files/4053925/libstdc%2B%2B.so.zip)
```
import angr
proj = angr.Project('/home/a/Desktop/fuzzing/binary/libstdc++.so.6')
cfg = proj.analyses.CFG()
```
Output for crash:
```
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-cef6a7e02e93> in <module>
----> 1 cfg = proj.analyses.CFG()

~/Desktop/fuzzing/angr-dev/angr/angr/analyses/analysis.py in __call__(self, *args, **kwargs)
    109 
    110         oself._show_progressbar = show_progressbar
--> 111         oself.__init__(*args, **kwargs)
    112         return oself
    113 

~/Desktop/fuzzing/angr-dev/angr/angr/analyses/cfg/cfg.py in __init__(self, **kwargs)
     53 
     54         # Now initializes CFGFast :-)
---> 55         CFGFast.__init__(self, **kwargs)
     56 
     57 from angr.analyses import AnalysesHub

~/Desktop/fuzzing/angr-dev/angr/angr/analyses/cfg/cfg_fast.py in __init__(self, binary, objects, regions, pickle_intermediate_results, symbols, function_prologues, resolve_indirect_jumps, force_segment, force_complete_scan, indirect_jump_target_limit, data_references, cross_references, normalize, start_at_entry, function_starts, extra_memory_regions, data_type_guessing_handlers, arch_options, indirect_jump_resolvers, base_state, exclude_sparse_regions, skip_specific_regions, heuristic_plt_resolving, detect_tail_calls, low_priority, cfb, model, use_patches, start, end, collect_data_references, extra_cross_references, **extra_arch_options)
    641 
    642         # Start working!
--> 643         self._analyze()
    644 
    645     def __getstate__(self):

~/Desktop/fuzzing/angr-dev/angr/angr/analyses/forward_analysis/forward_analysis.py in _analyze(self)
    214             # An example is the CFG recovery.
    215 
--> 216             self._analysis_core_baremetal()
    217 
    218         else:

~/Desktop/fuzzing/angr-dev/angr/angr/analyses/forward_analysis/forward_analysis.py in _analysis_core_baremetal(self)
    342 
    343             if not self._job_info_queue:
--> 344                 self._job_queue_empty()
    345 
    346             if not self._job_info_queue:

~/Desktop/fuzzing/angr-dev/angr/angr/analyses/cfg/cfg_fast.py in _job_queue_empty(self)
   1134         # function 0x100006480 does not return. Hence, we resolve indirect jumps before popping undecided pending jobs.
   1135         if self._resolve_indirect_jumps and self._indirect_jumps_to_resolve:
-> 1136             self._process_unresolved_indirect_jumps()
   1137 
   1138             if self._job_info_queue:

~/Desktop/fuzzing/angr-dev/angr/angr/analyses/cfg/cfg_base.py in _process_unresolved_indirect_jumps(self)
   2207             if self._low_priority:
   2208                 self._release_gil(idx, 20, 0.0001)
-> 2209             all_targets |= self._process_one_indirect_jump(jump)
   2210 
   2211         self._indirect_jumps_to_resolve.clear()

~/Desktop/fuzzing/angr-dev/angr/angr/analyses/cfg/cfg_base.py in _process_one_indirect_jump(self, jump)
   2233                 continue
   2234 
-> 2235             resolved, targets = resolver.resolve(self, jump.addr, jump.func_addr, block, jump.jumpkind)
   2236             if resolved:
   2237                 resolved_by = resolver

~/Desktop/fuzzing/angr-dev/angr/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py in resolve(self, cfg, addr, func_addr, block, jumpkind)
    467 
    468             l.debug("Try resolving %#x with a %d-level backward slice...", addr, slice_steps)
--> 469             r, targets = self._resolve(cfg, addr, func_addr, b)
    470             if r:
    471                 return r, targets

~/Desktop/fuzzing/angr-dev/angr/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py in _resolve(self, cfg, addr, func_addr, b)
    521 
    522         try:
--> 523             stmts_to_instrument, regs_to_initialize = self._jumptable_precheck(b)
    524         except NotAJumpTableNotification:
    525             l.debug("Indirect jump at %#x does not look like a jump table. Skip.", addr)

~/Desktop/fuzzing/angr-dev/angr/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py in _jumptable_precheck(self, b)
    868                 block = self.project.factory.block(block_addr, backup_state=self.base_state)
    869                 stmt_whitelist = annotatedcfg.get_whitelisted_statements(block_addr)
--> 870                 engine.process(state, block=block, whitelist=stmt_whitelist)
    871 
    872                 if state.is_jumptable:

~/Desktop/fuzzing/angr-dev/angr/angr/engines/light/engine.py in process(self, state, *args, **kwargs)
     33         # we are using a completely different state. Therefore, we directly call our _process() method before
     34         # SimEngine becomes flexible enough.
---> 35         self._process(state, None, block=kwargs.pop('block', None), whitelist=kwargs.pop('whitelist', None))
     36 
     37     def _process(self, new_state, successors, *args, **kwargs):

~/Desktop/fuzzing/angr-dev/angr/angr/engines/light/engine.py in _process(self, state, successors, block, whitelist, *args, **kwargs)
     68         self.tyenv = block.vex.tyenv
     69 
---> 70         self._process_Stmt(whitelist=whitelist)
     71 
     72         self.stmt_idx = None

~/Desktop/fuzzing/angr-dev/angr/angr/engines/light/engine.py in _process_Stmt(self, whitelist)
     89                 self.ins_addr = stmt.addr + stmt.delta
     90 
---> 91             self._handle_Stmt(stmt)
     92 
     93         if self.block.vex.jumpkind == 'Ijk_Call':

~/Desktop/fuzzing/angr-dev/angr/angr/engines/light/engine.py in _handle_Stmt(self, stmt)
    109         handler = "_handle_%s" % type(stmt).__name__
    110         if hasattr(self, handler):
--> 111             getattr(self, handler)(stmt)
    112         elif type(stmt).__name__ not in ('IMark', 'AbiHint'):
    113             self.l.error('Unsupported statement type %s.', type(stmt).__name__)

~/Desktop/fuzzing/angr-dev/angr/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py in _handle_WrTmp(self, stmt)
    145     def _handle_WrTmp(self, stmt):
    146         self._tsrc = set()
--> 147         super()._handle_WrTmp(stmt)
    148 
    149         if self._tsrc:

~/Desktop/fuzzing/angr-dev/angr/angr/engines/light/engine.py in _handle_WrTmp(self, stmt)
    115     # synchronize with function _handle_WrTmpData()
    116     def _handle_WrTmp(self, stmt):
--> 117         data = self._expr(stmt.data)
    118         if data is None:
    119             return

~/Desktop/fuzzing/angr-dev/angr/angr/engines/light/engine.py in _expr(self, expr)
    141         handler = "_handle_%s" % type(expr).__name__
    142         if hasattr(self, handler):
--> 143             return getattr(self, handler)(expr)
    144         else:
    145             self.l.error('Unsupported expression type %s.', type(expr).__name__)

~/Desktop/fuzzing/angr-dev/angr/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py in _handle_CCall(self, expr)
    234                 self._handle_Comparison(expr.args[2], expr.args[3])
    235         else:
--> 236             raise ValueError("Unexpected ccall encountered in architecture %s." % self.arch.name)
    237 
    238     def _handle_Comparison(self, arg0, arg1):

ValueError: Unexpected ccall encountered in architecture AARCH64.
```



Enviroments:
```
(angr) a@ubuntu:~/Desktop/fuzzing/angr-dev$ python -m angr.misc.bug_report
angr environment report
=============================
Date: 2020-01-13 05:57:22.679126
Running in virtual environment at /home/a/.virtualenvs/angr
Platform: linux-x86_64
Python version: 3.6.9 (default, Nov  7 2019, 10:44:02) 
[GCC 8.3.0]
######## angr #########
Python found it in /home/a/Desktop/fuzzing/angr-dev/angr/angr
Pip version angr 8.20.1.7
Git info:
	Current commit 89f3d64b77ca9def6297d58b7fd19f67ef5c69b2 from branch master
	Checked out from remote origin: https://github.com/angr/angr.git
######## ailment #########
Python found it in /home/a/Desktop/fuzzing/angr-dev/ailment/ailment
Pip version ailment 8.20.1.7
Git info:
	Current commit c696edc9f31ecccaaa36b1e40ca1bed6c9715242 from branch master
	Checked out from remote origin: https://github.com/angr/ailment.git
######## cle #########
Python found it in /home/a/Desktop/fuzzing/angr-dev/cle/cle
Pip version cle 8.20.1.7
Git info:
	Current commit de4499da5970aab8f762a43a5dccf8a4a472da12 from branch master
	Checked out from remote origin: https://github.com/angr/cle.git
######## pyvex #########
Python found it in /home/a/Desktop/fuzzing/angr-dev/pyvex/pyvex
Pip version pyvex 8.20.1.7
Git info:
	Current commit 4fa68d58618a7635b281c9d06263c75fb9bf357f from branch master
	Checked out from remote origin: https://github.com/angr/pyvex.git
######## claripy #########
Python found it in /home/a/Desktop/fuzzing/angr-dev/claripy/claripy
Pip version claripy 8.20.1.7
Git info:
	Current commit ea20bb80a84aab942f89cffbf035675dc0cf1af4 from branch master
	Checked out from remote origin: https://github.com/angr/claripy.git
######## archinfo #########
Python found it in /home/a/Desktop/fuzzing/angr-dev/archinfo/archinfo
Pip version archinfo 8.20.1.7
Git info:
	Current commit fa979436bd07b4178877d31a5166d28063a89807 from branch master
	Checked out from remote origin: https://github.com/angr/archinfo.git
######## z3 #########
Python found it in /home/a/.virtualenvs/angr/lib/python3.6/site-packages/z3
Pip version z3-solver 4.8.7.0
Couldn't find git info
######## unicorn #########
Python found it in /home/a/.virtualenvs/angr/lib/python3.6/site-packages/unicorn
Pip version unicorn 1.0.1
Couldn't find git info
######### Native Module Info ##########
angr: <CDLL '/home/a/Desktop/fuzzing/angr-dev/angr/angr/lib/angr_native.so', handle 203baf0 at 0x7f10f7d1fc50>
unicorn: <CDLL '/home/a/.virtualenvs/angr/lib/python3.6/site-packages/unicorn/lib/libunicorn.so', handle 177a050 at 0x7f10f6c7bd68>
pyvex: <cffi.api._make_ffi_library.<locals>.FFILibrary object at 0x7f10f7c5ff28>
z3: <CDLL '/home/a/.virtualenvs/angr/lib/python3.6/site-packages/z3/lib/libz3.so', handle 199ceb0 at 0x7f10f4b4af60>
```


Discussion:
I cannot help to much i am not so much advanced programmer to write clean code but i post hear my analyse.   

1.) ~/Desktop/fuzzing/angr-dev/archinfo/archinfo/arch_arm.py-> is_arm_arch(self.arch) -> self.arch.name == 'AARCH' != 'AArch'
```
    27    def is_arm_arch(a):
    28        return a.name.startswith('ARM') or a.name.startswith("AArch")
```
2.)cond_type_enum == 25 ? in AARCH64 conditions are the same as ARM
```
~/Desktop/fuzzing/angr-dev/angr/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py in _handle_CCall(self, expr)
    232         elif is_arm_arch(self.arch):
    233             if cond_type_enum in EXPECTED_COND_TYPES['ARM']:
    234                 self._handle_Comparison(expr.args[2], expr.args[3]) 
```

I think it's a bug. I'll fix it when I have time (hopefully within this week). Thanks for reporting.

Resolving patch:
diff --git a/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py b/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py
--- a/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py
+++ b/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py
@@ -90,6 +90,16 @@ def base_addr_available(self):
         ccall.ARMCondGT,
         ccall.ARMCondLE,
     },
+    'AARCH64': {
+        ccall.ARM64CondCS,
+        ccall.ARM64CondCC,
+        ccall.ARM64CondHI,
+        ccall.ARM64CondLS,
+        ccall.ARM64CondGE,
+        ccall.ARM64CondLT,
+        ccall.ARM64CondGT,
+        ccall.ARM64CondLE,
+    },
 }
 
 
@@ -226,7 +236,7 @@ def _handle_CCall(self, expr):
             return
         cond_type_enum = expr.args[0].con.value
 
-        if self.arch.name in ('X86', 'AMD64'):
+        if self.arch.name in { 'X86', 'AMD64', 'AARCH64' }:
             if cond_type_enum in EXPECTED_COND_TYPES[self.arch.name]:
                 self._handle_Comparison(expr.args[2], expr.args[3])
         elif is_arm_arch(self.arch):


Test patch: