def get_called_functions(
        self, event: TraceEvent | None = None, only_after_event: bool = False
    ) -> Sequence[tuple[Function, TraceEvent]]:
        """
        Enumerate 1st order outgoing calls of function at `event`.
        """
        if event is None:
            if self._trace_dbg.state:
                event = self._trace_dbg.state.event
            else:
                return []

        # Get current function
        func = self.get_function_for_event(event)
        if func is None:
            _l.warning("Could not determine function for event %s", event)
            return []

        func, event = func
        _l.debug("Function for event %s: %s", event, func.name)

        if not only_after_event:
            # Rewind to function entry
            # FIXME: Does not properly handle nested calls to this function!
            while event.Addr() != func.addr:
                event = self._btrace.get_prev_bb_event(event, vcpu=self._trace_dbg.vcpu)
                if event is None:
                    _l.error("Did not find start of function %s (%#x) in trace", func.name, func.addr)
                    return []

        called_addrs = []
        keep_looking = True
        while keep_looking:
            # Step until next function exit
            called_func_entry_event = self._btrace.get_next_bb_event(event, vcpu=self._trace_dbg.vcpu)
            if called_func_entry_event is None:
                # End of trace
                break

            # FIXME: Possible failure in func.block_addrs_set not matching
            addr = called_func_entry_event.Addr()
            is_a_function_exit = (addr not in func.block_addrs_set) or (addr == func.addr)
            if not is_a_function_exit:
                event = called_func_entry_event
                continue

            # Check exit type
            exit_block_addr = event.Addr()
            b = self.workspace.main_instance.project.factory.block(exit_block_addr)
            if b.vex.jumpkind == "Ijk_Ret":
                _l.debug("Exit is a return to caller")
                break

            called_addrs.append((addr, called_func_entry_event))

            if b.vex.jumpkind != "Ijk_Call":
                _l.debug("Exit is a tail-call")
                break

            # FIXME: fallthru might indicate trace vs cfg inconsistency
            # Seek through events to find return site of this call
            event = called_func_entry_event
            ret_addr = b.instruction_addrs[0] + b.size
            num_nested_calls = 0
            if self.workspace.main_instance.project.arch.name == "AMD64":
                # FIXME Remove this hardcoding
                stack_reg = 7
                expected_sp = called_func_entry_event.Regs(stack_reg) + 8
            else:
                raise AssertionError("FIXME: Stack pointer check for non-x86_64")

            _l.debug("Seeking to return site for call...")
            while True:
                event = self._btrace.get_next_exec_event(event, addr=ret_addr, vcpu=self._trace_dbg.vcpu)
                if event is None:
                    _l.error(
                        "Unexpected end of trace while looking for return site in %s @ %#x "
                        "(call may have caused termination)",
                        func.name,
                        ret_addr,
                    )
                    keep_looking = False
                    break

                # Check the stack pointer at return site to ensure it matches target call
                # and does not actually belong to a nested call
                bb_event = self._btrace.get_prev_bb_event(event, vcpu=self._trace_dbg.vcpu)
                if bb_event.Regs(stack_reg) == expected_sp:
                    _l.debug("Found return block at event %s", bb_event)
                    event = bb_event
                    break
                _l.debug("Skipping over nested call (%d)", num_nested_calls)
                num_nested_calls += 1

        all_funcs = self.workspace.main_instance.project.kb.functions
        return [((all_funcs.get(addr, addr)), e) for (addr, e) in called_addrs]

        Enumerate 1st order outgoing calls of function at `event`.
        
angrmanagement/logic/debugger/bintrace.py