Skip to content

I can not re-create the same breakpoint(, after my removing it) #86

@asdf0123

Description

@asdf0123

The sample source code is shown below. The output implies that the second bp=p.createBreakpoint(breakpoint_address) doesn't work.(Version: 0.9.9)

import subprocess
from ptrace.debugger import PtraceDebugger, ProcessExit
from ptrace.debugger.memory_mapping import readProcessMappings
if __name__=="__main__":
	debugger = PtraceDebugger()
	conn = subprocess.Popen(["./helloworld"])
	p = debugger.addProcess(conn.pid, is_attached=False)
	p.attach()
	 
	breakpoint_address = 0x405CD0  # Replace with actual address
	bp=p.createBreakpoint(breakpoint_address)
	print(list(hex(ele) for ele in debugger.dict[conn.pid].breakpoints.keys()))
	p.removeBreakpoint(bp)
	print(list(hex(ele) for ele in debugger.dict[conn.pid].breakpoints.keys()))
	bp=p.createBreakpoint(breakpoint_address)
	print(list(hex(ele) for ele in debugger.dict[conn.pid].breakpoints.keys()))

output:

['0x405cd0']
[]
[]
Traceback (most recent call last):
  File "ptracebug.py", line 17, in <module>
    p.removeBreakpoint(bp)
  File "/root/miniconda3/lib/python3.8/site-packages/ptrace/debugger/process.py", line 759, in removeBreakpoint
    del self.breakpoints[breakpoint.address]
KeyError: 4218064
Exception ignored in: <function Breakpoint.__del__ at 0x7f714e311430>
Traceback (most recent call last):
  File "/root/miniconda3/lib/python3.8/site-packages/ptrace/debugger/breakpoint.py", line 64, in __del__
  File "/root/miniconda3/lib/python3.8/site-packages/ptrace/debugger/breakpoint.py", line 55, in desinstall
  File "/root/miniconda3/lib/python3.8/site-packages/ptrace/debugger/process.py", line 759, in removeBreakpoint
KeyError: 4218064

I viewed the source code and find something confusing. PtraceProcess.removeBreakpoint calls Breakpoint.del, Breakpoint.del calls Breakpoint.desinstall and Breakpoint.desinstall calls PtraceProcess.removeBreakpoint...
INFINITE RECURSION! No wonder there's is an (ignored) exception.

ptrace/debugger/process.py

class PtraceProcess(object):
    #...
    def removeBreakpoint(self, breakpoint):
        del self.breakpoints[breakpoint.address]
    #...

ptrace/debugger/breakpoint.py

class Breakpoint(object):
    #...
    def desinstall(self, set_ip=False):
        """
        Remove the breakpoint from the associated process. If set_ip is True,
        restore the instruction pointer to the address of the breakpoint.
        """
        if not self._installed:
            return
        self._installed = False
        info("Desinstall %s" % self)
        process = self.process()
        if not process:
            return
        if process.running:
            process.writeBytes(self.address, self.old_bytes)
        if set_ip:
            process.setInstrPointer(self.address)
        process.removeBreakpoint(self)
    #...
    def __del__(self):
        try:
            self.desinstall(False)
        except PtraceError:
            pass

To deal with it, i suggest using (set or list) instead of dictionary to record active breakpoints(ptrace/debugger/process.py, Line 162). In the dictionary, the key and the value.address are bound to be the same, so there is redundant information in the data structure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions