Multithreading ============== .. _multithreading: libdebug provides a simple way to debug multithreaded programs. Each time the process is cloned, the new thread is automatically traced and registered in the `threads` property of the debugger object. .. code-block:: python # Create a debugger object d = debugger("./threaded_test") # Start debugging and continue until the first stopping event d.run() d.cont() # Print thread id and program counter value for all threads for thread in d.threads: print(thread.thread_id, hex(thread.regs.rip)) d.cont() # Kill all threads d.kill() Objects in the `threads` list are `ThreadContext` objects, which behave similarly to the debugger. Each thread object has a `regs` property that exposes the registers of the thread and a `memory` property for memory access. You can access these properties exactly as you did with the debugger object. See :doc:`basic_features` for more information. Control Flow Operations ----------------------- Control flow is synchronous between threads: they are either either are all stopped or all running. To this end, the debugger stops all the threads every time a single thread stops. This is a design choice to avoid unexpected behavior as a result of concurrency. The following is a list of behaviors to keep in mind when using control flow funcions in multithreaded programs. - `cont` will continue all threads. - `step` and `step_until` will step the selected thread. - `finish` will have different behavior depending on the selected heuristic. - `backtrace` will continue on all threads but will stop at any breakpoint that any of the threads hit. - `step-mode` will step exclusively on the thread that has been specified. Breakpoints ----------- Breakpoints are shared between all threads. This means that if a breakpoint is hit by one thread, all threads will stop. This is a design choice to avoid unexpected behavior as a result of concurrency. This, of course, requires a way for the user to distinguish which thread has hit the breakpoint. The :class:`libdebug.data.breakpoint.Breakpoint` class contains a function called `hit_on`. Given a thread, it will return whether the breakpoint has been hit on that thread. .. code-block:: python # Create a breakpoint at address 0x4005a0 bp = d.breakpoint(0x15a0) d.cont() # Print thread id and program counter value for all threads for thread in d.threads: if bp.hit_on(thread): print("Thread", thread.thread_id, "hit the breakpoint")