docs: def _create_jobs(self, target, jumpkind, current_function_addr, irsb, addr, cfg_node, ins_addr, stmt_idx):
          """
          Given a node and details of a successor, makes a list of CFGJobs
          and if it is a call or exit marks it appropriately so in the CFG
  
          :param int target:          Destination of the resultant job
          :param str jumpkind:        The jumpkind of the edge going to this node
          :param int current_function_addr: Address of the current function
          :param pyvex.IRSB irsb:     IRSB of the predecessor node
          :param int addr:            The predecessor address
          :param CFGNode cfg_node:    The CFGNode of the predecessor node
          :param int ins_addr:        Address of the source instruction.
          :param int stmt_idx:        ID of the source statement.
          :return:                    a list of CFGJobs
          :rtype:                     list
          """
  
          if type(target) is pyvex.IRExpr.Const:  # pylint: disable=unidiomatic-typecheck
              target_addr = target.con.value
          elif type(target) in (pyvex.IRConst.U8, pyvex.IRConst.U16, pyvex.IRConst.U32, pyvex.IRConst.U64):  # pylint: disable=unidiomatic-typecheck
              target_addr = target.value
          elif type(target) is int:  # pylint: disable=unidiomatic-typecheck
              target_addr = target
          else:
              target_addr = None
  
          if target_addr in self._known_thunks and jumpkind == 'Ijk_Boring':
              thunk_kind = self._known_thunks[target_addr][0]
              if thunk_kind == 'ret':
                  jumpkind = 'Ijk_Ret'
                  target_addr = None
              elif thunk_kind == 'jmp':
                  pass # ummmmmm not sure about this one
              else:
                  raise AngrCFGError("This shouldn't be possible")
  
          jobs = [ ]
          is_syscall = jumpkind.startswith("Ijk_Sys")
  
          # Special handling:
          # If a call instruction has a target that points to the immediate next instruction, we treat it as a boring jump
          if jumpkind == "Ijk_Call" and \
                  not self.project.arch.call_pushes_ret and \
                  cfg_node.instruction_addrs and \
                  ins_addr == cfg_node.instruction_addrs[-1] and \
                  target_addr == irsb.addr + irsb.size:
              jumpkind = "Ijk_Boring"
  
          if target_addr is None:
              # The target address is not a concrete value
  
              if jumpkind == "Ijk_Ret":
                  # This block ends with a return instruction.
                  if current_function_addr != -1:
                      self._function_exits[current_function_addr].add(addr)
                      self._function_add_return_site(addr, current_function_addr)
                      self.functions[current_function_addr].returning = True
                      self._pending_jobs.add_returning_function(current_function_addr)
  
                  cfg_node.has_return = True
  
              elif self._resolve_indirect_jumps and \
                      (jumpkind in ('Ijk_Boring', 'Ijk_Call', 'Ijk_InvalICache') or jumpkind.startswith('Ijk_Sys')):
                  # This is an indirect jump. Try to resolve it.
                  # FIXME: in some cases, a statementless irsb will be missing its instr addresses
                  # and this next part will fail. Use the real IRSB instead
                  irsb = cfg_node.block.vex
                  cfg_node.instruction_addrs = irsb.instruction_addresses
                  resolved, resolved_targets, ij = self._indirect_jump_encountered(addr, cfg_node, irsb,
                                                                                   current_function_addr, stmt_idx)
                  if resolved:
                      for resolved_target in resolved_targets:
                          if jumpkind == 'Ijk_Call':
                              jobs += self._create_job_call(cfg_node.addr, irsb, cfg_node, stmt_idx, ins_addr,
                                                            current_function_addr, resolved_target, jumpkind)
                          else:
                              edge = FunctionTransitionEdge(cfg_node, resolved_target, current_function_addr,
                                                            to_outside=False, stmt_idx=stmt_idx, ins_addr=ins_addr,
                                                            )
                              ce = CFGJob(resolved_target, current_function_addr, jumpkind,
                                          last_addr=resolved_target, src_node=cfg_node, src_stmt_idx=stmt_idx,
                                          src_ins_addr=ins_addr, func_edges=[ edge ],
                                          )
                              jobs.append(ce)
                      return jobs
  
                  if jumpkind in ("Ijk_Boring", 'Ijk_InvalICache'):
                      resolved_as_plt = False
  
                      if irsb and self._heuristic_plt_resolving:
                          # Test it on the initial state. Does it jump to a valid location?
                          # It will be resolved only if this is a .plt entry
                          resolved_as_plt = self._resolve_plt(addr, irsb, ij)
  
                          if resolved_as_plt:
                              jump_target = next(iter(ij.resolved_targets))
                              target_func_addr = jump_target  # TODO: FIX THIS
  
                              edge = FunctionTransitionEdge(cfg_node, jump_target, current_function_addr,
                                                            to_outside=True, dst_func_addr=jump_target,
                                                            stmt_idx=stmt_idx, ins_addr=ins_addr,
                                                            )
                              ce = CFGJob(jump_target, target_func_addr, jumpkind, last_addr=jump_target,
                                          src_node=cfg_node, src_stmt_idx=stmt_idx, src_ins_addr=ins_addr,
                                          func_edges=[edge],
                                          )
                              jobs.append(ce)
  
                      if resolved_as_plt:
                          # has been resolved as a PLT entry. Remove it from indirect_jumps_to_resolve
                          if ij.addr in self._indirect_jumps_to_resolve:
                              self._indirect_jumps_to_resolve.remove(ij.addr)
                              self._deregister_analysis_job(current_function_addr, ij)
                      else:
                          # add it to indirect_jumps_to_resolve
                          self._indirect_jumps_to_resolve.add(ij)
  
                          # register it as a job for the current function
                          self._register_analysis_job(current_function_addr, ij)
  
                  else:  # jumpkind == "Ijk_Call" or jumpkind.startswith('Ijk_Sys')
                      self._indirect_jumps_to_resolve.add(ij)
                      self._register_analysis_job(current_function_addr, ij)
  
                      jobs += self._create_job_call(addr, irsb, cfg_node, stmt_idx, ins_addr, current_function_addr, None,
                                                    jumpkind, is_syscall=is_syscall
                                                    )
  
          elif target_addr is not None:
              # This is a direct jump with a concrete target.
  
              # pylint: disable=too-many-nested-blocks
              if jumpkind in ('Ijk_Boring', 'Ijk_InvalICache'):
                  # if the target address is at another section, it has to be jumping to a new function
                  if not self._addrs_belong_to_same_section(addr, target_addr):
                      target_func_addr = target_addr
                      to_outside = True
                  else:
                      # it might be a jumpout
                      target_func_addr = None
                      real_target_addr = get_real_address_if_arm(self.project.arch, target_addr)
                      if real_target_addr in self._traced_addresses:
                          node = self.model.get_any_node(target_addr)
                          if node is not None:
                              target_func_addr = node.function_address
                      if target_func_addr is None:
                          target_func_addr = current_function_addr
  
                      to_outside = not target_func_addr == current_function_addr
  
                  edge = FunctionTransitionEdge(cfg_node, target_addr, current_function_addr,
                                                to_outside=to_outside,
                                                dst_func_addr=target_func_addr,
                                                ins_addr=ins_addr,
                                                stmt_idx=stmt_idx,
                                                )
  
                  ce = CFGJob(target_addr, target_func_addr, jumpkind, last_addr=addr, src_node=cfg_node,
                              src_ins_addr=ins_addr, src_stmt_idx=stmt_idx, func_edges=[ edge ])
                  jobs.append(ce)
  
              elif jumpkind == 'Ijk_Call' or jumpkind.startswith("Ijk_Sys"):
                  jobs += self._create_job_call(addr, irsb, cfg_node, stmt_idx, ins_addr, current_function_addr,
                                                target_addr, jumpkind, is_syscall=is_syscall
                                                )
  
              else:
                  # TODO: Support more jumpkinds
                  l.debug("Unsupported jumpkind %s", jumpkind)
                  l.debug("Instruction address: %#x", ins_addr)
  
          return jobs