Source code for libdebug.data.syscall_handler
#
# This file is part of libdebug Python library (https://github.com/libdebug/libdebug).
# Copyright (c) 2024 Roberto Alessandro Bertolini, Gabriele Digregorio. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for details.
#
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any
from libdebug.debugger.internal_debugger_instance_manager import provide_internal_debugger
if TYPE_CHECKING:
from collections.abc import Callable
from libdebug.state.thread_context import ThreadContext
[docs]
@dataclass
class SyscallHandler:
"""Handle a syscall executed by the target process.
Attributes:
syscall_number (int): The syscall number to handle.
on_enter_user (Callable[[ThreadContext, int], None]): The callback defined by the user to execute when the
syscall is entered.
on_exit_user (Callable[[ThreadContext, int], None]): The callback defined by the user to execute when the
syscall is exited.
on_enter_pprint (Callable[[ThreadContext, int], None]): The callback defined by the pretty print to execute when
the syscall is entered.
on_exit_pprint (Callable[[ThreadContext, int], None]): The callback defined by the pretty print to execute when
the syscall is exited.
recursive (bool): Whether, when the syscall is hijacked with another one, the syscall handler associated with
the new syscall should be considered as well. Defaults to False.
enabled (bool): Whether the syscall will be handled or not.
hit_count (int): The number of times the syscall has been handled.
"""
syscall_number: int
on_enter_user: Callable[[ThreadContext, int], None]
on_exit_user: Callable[[ThreadContext, int], None]
on_enter_pprint: Callable[[ThreadContext, int, Any], None]
on_exit_pprint: Callable[[int | tuple[int, int]], None]
recursive: bool = False
enabled: bool = True
hit_count: int = 0
_has_entered: bool = False
_skip_exit: bool = False
[docs]
def enable(self: SyscallHandler) -> None:
"""Handle the syscall."""
provide_internal_debugger(self)._ensure_process_stopped()
self.enabled = True
self._has_entered = False
[docs]
def disable(self: SyscallHandler) -> None:
"""Unhandle the syscall."""
provide_internal_debugger(self)._ensure_process_stopped()
self.enabled = False
self._has_entered = False
[docs]
def hit_on_enter(self: SyscallHandler, thread_context: ThreadContext) -> bool:
"""Returns whether the syscall handler has been hit during the syscall entry on the given thread context."""
return self.enabled and thread_context.syscall_number == self.syscall_number and self._has_entered
[docs]
def hit_on_exit(self: SyscallHandler, thread_context: ThreadContext) -> bool:
"""Returns whether the syscall handler has been hit during the syscall exit on the given thread context."""
return self.enabled and thread_context.syscall_number == self.syscall_number and not self._has_entered
def __hash__(self: SyscallHandler) -> int:
"""Return the hash of the syscall handler, based just on the syscall number."""
return hash(self.syscall_number)