Source code for libdebug.interfaces.debugging_interface
#
# This file is part of libdebug Python library (https://github.com/libdebug/libdebug).
# Copyright (c) 2023-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 abc import ABC, abstractmethod
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from libdebug.data.breakpoint import Breakpoint
from libdebug.data.memory_map import MemoryMap
from libdebug.data.signal_hook import SignalHook
from libdebug.data.syscall_hook import SyscallHook
from libdebug.state.thread_context import ThreadContext
[docs]
class DebuggingInterface(ABC):
"""The interface used by `_InternalDebugger` to communicate with the available debugging backends, such as `ptrace` or `gdb`."""
def __init__(self: DebuggingInterface) -> None:
"""Initializes the DebuggingInterface classs."""
[docs]
@abstractmethod
def reset(self: DebuggingInterface) -> None:
"""Resets the state of the interface."""
[docs]
@abstractmethod
def run(self: DebuggingInterface) -> None:
"""Runs the specified process."""
[docs]
@abstractmethod
def attach(self: DebuggingInterface, pid: int) -> None:
"""Attaches to the specified process.
Args:
pid (int): the pid of the process to attach to.
"""
[docs]
@abstractmethod
def detach(self: DebuggingInterface) -> None:
"""Detaches from the process."""
[docs]
@abstractmethod
def kill(self: DebuggingInterface) -> None:
"""Instantly terminates the process."""
[docs]
@abstractmethod
def cont(self: DebuggingInterface) -> None:
"""Continues the execution of the process."""
[docs]
@abstractmethod
def wait(self: DebuggingInterface) -> None:
"""Waits for the process to stop."""
[docs]
@abstractmethod
def migrate_to_gdb(self: DebuggingInterface) -> None:
"""Migrates the current process to GDB."""
[docs]
@abstractmethod
def migrate_from_gdb(self: DebuggingInterface) -> None:
"""Migrates the current process from GDB."""
[docs]
@abstractmethod
def step(self: DebuggingInterface, thread: ThreadContext) -> None:
"""Executes a single instruction of the specified thread.
Args:
thread (ThreadContext): The thread to step.
"""
[docs]
@abstractmethod
def step_until(self: DebuggingInterface, thread: ThreadContext, address: int, max_steps: int) -> None:
"""Executes instructions of the specified thread until the specified address is reached.
Args:
thread (ThreadContext): The thread to step.
address (int): The address to reach.
max_steps (int): The maximum number of steps to execute.
"""
[docs]
@abstractmethod
def finish(self: DebuggingInterface, thread: ThreadContext, heuristic: str) -> None:
"""Continues execution until the current function returns or the process stops.
The command requires a heuristic to determine the end of the function. The available heuristics are:
- `backtrace`: The debugger will place a breakpoint on the saved return address found on the stack and continue execution on all threads.
- `step-mode`: The debugger will step on the specified thread until the current function returns. This will be slower.
Args:
thread (ThreadContext): The thread to finish.
heuristic (str, optional): The heuristic to use. Defaults to "backtrace".
"""
[docs]
@abstractmethod
def maps(self: DebuggingInterface) -> list[MemoryMap]:
"""Returns the memory maps of the process."""
[docs]
@abstractmethod
def set_breakpoint(self: DebuggingInterface, bp: Breakpoint) -> None:
"""Sets a breakpoint at the specified address.
Args:
bp (Breakpoint): The breakpoint to set.
"""
[docs]
@abstractmethod
def unset_breakpoint(self: DebuggingInterface, bp: Breakpoint) -> None:
"""Restores the original instruction flow at the specified address.
Args:
bp (Breakpoint): The breakpoint to restore.
"""
[docs]
@abstractmethod
def set_syscall_hook(self: DebuggingInterface, hook: SyscallHook) -> None:
"""Sets a syscall hook.
Args:
hook (SyscallHook): The syscall hook to set.
"""
[docs]
@abstractmethod
def unset_syscall_hook(self: DebuggingInterface, hook: SyscallHook) -> None:
"""Unsets a syscall hook.
Args:
hook (SyscallHook): The syscall hook to unset.
"""
[docs]
@abstractmethod
def set_signal_hook(self: DebuggingInterface, hook: SignalHook) -> None:
"""Sets a signal hook.
Args:
hook (SignalHook): The signal hook to set.
"""
[docs]
@abstractmethod
def unset_signal_hook(self: DebuggingInterface, hook: SignalHook) -> None:
"""Unsets a signal hook.
Args:
hook (SignalHook): The signal hook to unset.
"""
[docs]
@abstractmethod
def peek_memory(self: DebuggingInterface, address: int) -> int:
"""Reads the memory at the specified address.
Args:
address (int): The address to read.
Returns:
int: The read memory value.
"""
[docs]
@abstractmethod
def poke_memory(self: DebuggingInterface, address: int, data: int) -> None:
"""Writes the memory at the specified address.
Args:
address (int): The address to write.
data (int): The value to write.
"""