We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`nextret` keeps going after the binary segfaults
If the binary segfaults when running `nextret` (and potentially the other `next*` commands), it keeps trying to continue until you kill it:
```
Program received signal SIGSEGV, Segmentation fault.
0x00007f7a8b4f9ae4 in __vfscanf_internal (s=0x7f7a8b6b0aa0 <_IO_2_1_stdin_>, format=0x4020ca "%s", argptr=argptr@entry=0x7ffeb13483a8, mode_flags=mode_flags@entry=2) at ./stdio-c
ommon/vfscanf-internal.c:339
339     in ./stdio-common/vfscanf-internal.c

Program received signal SIGSEGV, Segmentation fault.
0x00007f7a8b4f9ae4 in __vfscanf_internal (s=0x7f7a8b6b0aa0 <_IO_2_1_stdin_>, format=0x4020ca "%s", argptr=argptr@entry=0x7ffeb13483a8, mode_flags=mode_flags@entry=2) at ./stdio-c
ommon/vfscanf-internal.c:339
339     in ./stdio-common/vfscanf-internal.c

Program received signal SIGSEGV, Segmentation fault.
0x00007f7a8b4f9ae4 in __vfscanf_internal (s=0x7f7a8b6b0aa0 <_IO_2_1_stdin_>, format=0x4020ca "%s", argptr=argptr@entry=0x7ffeb13483a8, mode_flags=mode_flags@entry=2) at ./stdio-c
ommon/vfscanf-internal.c:339
339     in ./stdio-common/vfscanf-internal.c
```

We should stop after the first segfault and return to the prompt.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pwndbg/gdblib/proc.py`
Content:
```
1 """
2 Provides values which would be available from /proc which
3 are not fulfilled by other modules and some process/gdb flow
4 related information.
5 """
6 
7 import functools
8 import sys
9 from types import ModuleType
10 from typing import Any
11 from typing import Callable
12 
13 import gdb
14 
15 import pwndbg.gdblib.qemu
16 import pwndbg.lib.memoize
17 
18 
19 class module(ModuleType):
20     @property
21     def pid(self):
22         # QEMU usermode emulation always returns 42000 for some reason.
23         # In any case, we can't use the info.
24         if pwndbg.gdblib.qemu.is_qemu_usermode():
25             return pwndbg.gdblib.qemu.pid()
26 
27         i = gdb.selected_inferior()
28         if i is not None:
29             return i.pid
30         return 0
31 
32     @property
33     def tid(self):
34         if pwndbg.gdblib.qemu.is_qemu_usermode():
35             return pwndbg.gdblib.qemu.pid()
36 
37         i = gdb.selected_thread()
38         if i is not None:
39             return i.ptid[1]
40 
41         return self.pid
42 
43     @property
44     def alive(self):
45         return gdb.selected_thread() is not None
46 
47     @property
48     def thread_is_stopped(self):
49         """
50         This detects whether selected thread is stopped.
51         It is not stopped in situations when gdb is executing commands
52         that are attached to a breakpoint by `command` command.
53 
54         For more info see issue #229 ( https://github.com/pwndbg/pwndbg/issues/299 )
55         :return: Whether gdb executes commands attached to bp with `command` command.
56         """
57         return gdb.selected_thread().is_stopped()
58 
59     @property
60     def exe(self):
61         """
62         Returns the debugged file name.
63 
64         On remote targets, this may be prefixed with "target:" string.
65         See this by executing those in two terminals:
66         1. gdbserver 127.0.0.1:1234 /bin/ls
67         2. gdb -ex "target remote :1234" -ex "pi pwndbg.gdblib.proc.exe"
68 
69         If you need to process the debugged file use:
70             `pwndbg.gdblib.file.get_file(pwndbg.gdblib.proc.exe)`
71         """
72         return gdb.current_progspace().filename
73 
74     def OnlyWhenRunning(self, func):
75         @functools.wraps(func)
76         def wrapper(*a, **kw):
77             if self.alive:
78                 return func(*a, **kw)
79 
80         return wrapper
81 
82 
83 OnlyWhenRunning: Callable[[Any], Any]
84 # To prevent garbage collection
85 tether = sys.modules[__name__]
86 
87 sys.modules[__name__] = module(__name__, "")
88
```

Path: `pwndbg/gdblib/next.py`
Content:
```
1 """
2 Commands for setting temporary breakpoints on the next
3 instruction of some type (call, branch, etc.)
4 """
5 
6 import re
7 
8 import capstone
9 import gdb
10 
11 import pwndbg.disasm
12 import pwndbg.gdblib.events
13 import pwndbg.gdblib.proc
14 import pwndbg.gdblib.regs
15 from pwndbg.color import message
16 
17 jumps = set((capstone.CS_GRP_CALL, capstone.CS_GRP_JUMP, capstone.CS_GRP_RET, capstone.CS_GRP_IRET))
18 
19 interrupts = set((capstone.CS_GRP_INT,))
20 
21 
22 @pwndbg.gdblib.events.exit
23 def clear_temp_breaks():
24     if not pwndbg.gdblib.proc.alive:
25         breakpoints = gdb.breakpoints()
26         if breakpoints:
27             for bp in breakpoints:
28                 if (
29                     bp.temporary and not bp.visible
30                 ):  # visible is used instead of internal because older gdb's don't support internal
31                     bp.delete()
32 
33 
34 def next_int(address=None):
35     """
36     If there is a syscall in the current basic black,
37     return the instruction of the one closest to $PC.
38 
39     Otherwise, return None.
40     """
41     if address is None:
42         ins = pwndbg.disasm.one(pwndbg.gdblib.regs.pc)
43         if not ins:
44             return None
45         address = ins.next
46 
47     ins = pwndbg.disasm.one(address)
48     while ins:
49         if set(ins.groups) & jumps:
50             return None
51         if set(ins.groups) & interrupts:
52             return ins
53         ins = pwndbg.disasm.one(ins.next)
54 
55     return None
56 
57 
58 def next_branch(address=None):
59     if address is None:
60         ins = pwndbg.disasm.one(pwndbg.gdblib.regs.pc)
61         if not ins:
62             return None
63         address = ins.next
64 
65     ins = pwndbg.disasm.one(address)
66     while ins:
67         if set(ins.groups) & jumps:
68             return ins
69         ins = pwndbg.disasm.one(ins.next)
70 
71     return None
72 
73 
74 def break_next_branch(address=None):
75     ins = next_branch(address)
76 
77     if ins:
78         gdb.Breakpoint("*%#x" % ins.address, internal=True, temporary=True)
79         gdb.execute("continue", from_tty=False, to_string=True)
80         return ins
81 
82 
83 def break_next_interrupt(address=None):
84     ins = next_int(address)
85 
86     if ins:
87         gdb.Breakpoint("*%#x" % ins.address, internal=True, temporary=True)
88         gdb.execute("continue", from_tty=False, to_string=True)
89         return ins
90 
91 
92 def break_next_call(symbol_regex=None):
93     while pwndbg.gdblib.proc.alive:
94         ins = break_next_branch()
95 
96         if not ins:
97             break
98 
99         # continue if not a call
100         if capstone.CS_GRP_CALL not in ins.groups:
101             continue
102 
103         # return call if we don't search for a symbol
104         if not symbol_regex:
105             return ins
106 
107         # return call if we match target address
108         if ins.target_const and re.match("%s$" % symbol_regex, hex(ins.target)):
109             return ins
110 
111         # return call if we match symbol name
112         if ins.symbol and re.match("%s$" % symbol_regex, ins.symbol):
113             return ins
114 
115 
116 def break_next_ret(address=None):
117     while pwndbg.gdblib.proc.alive:
118         ins = break_next_branch(address)
119 
120         if not ins:
121             break
122 
123         if capstone.CS_GRP_RET in ins.groups:
124             return ins
125 
126 
127 def break_on_program_code():
128     """
129     Breaks on next instruction that belongs to process' objfile code.
130     :return: True for success, False when process ended or when pc is at the code.
131     """
132     exe = pwndbg.gdblib.proc.exe
133     binary_exec_page_ranges = [
134         (p.start, p.end) for p in pwndbg.vmmap.get() if p.objfile == exe and p.execute
135     ]
136 
137     pc = pwndbg.gdblib.regs.pc
138     for start, end in binary_exec_page_ranges:
139         if start <= pc < end:
140             print(message.error("The pc is already at the binary objfile code. Not stepping."))
141             return False
142 
143     while pwndbg.gdblib.proc.alive:
144         gdb.execute("si", from_tty=False, to_string=False)
145 
146         pc = pwndbg.gdblib.regs.pc
147         for start, end in binary_exec_page_ranges:
148             if start <= pc < end:
149                 return True
150 
151     return False
152 
153 
154 def break_on_next(address=None):
155     address = address or pwndbg.gdblib.regs.pc
156     ins = pwndbg.disasm.one(address)
157 
158     gdb.Breakpoint("*%#x" % (ins.address + ins.size), temporary=True)
159     gdb.execute("continue", from_tty=False, to_string=True)
160
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pwndbg/gdblib/next.py b/pwndbg/gdblib/next.py
--- a/pwndbg/gdblib/next.py
+++ b/pwndbg/gdblib/next.py
@@ -91,6 +91,10 @@
 
 def break_next_call(symbol_regex=None):
     while pwndbg.gdblib.proc.alive:
+        # Break on signal as it may be a segfault
+        if pwndbg.gdblib.proc.stopped_with_signal:
+            return
+
         ins = break_next_branch()
 
         if not ins:
@@ -115,6 +119,10 @@
 
 def break_next_ret(address=None):
     while pwndbg.gdblib.proc.alive:
+        # Break on signal as it may be a segfault
+        if pwndbg.gdblib.proc.stopped_with_signal:
+            return
+
         ins = break_next_branch(address)
 
         if not ins:
@@ -126,13 +134,14 @@
 
 def break_on_program_code():
     """
-    Breaks on next instruction that belongs to process' objfile code.
-    :return: True for success, False when process ended or when pc is at the code.
+    Breaks on next instruction that belongs to process' objfile code
+
+    :return: True for success, False when process ended or when pc is not at the code or if a signal occurred
     """
     exe = pwndbg.gdblib.proc.exe
-    binary_exec_page_ranges = [
+    binary_exec_page_ranges = tuple(
         (p.start, p.end) for p in pwndbg.vmmap.get() if p.objfile == exe and p.execute
-    ]
+    )
 
     pc = pwndbg.gdblib.regs.pc
     for start, end in binary_exec_page_ranges:
@@ -140,12 +149,18 @@
             print(message.error("The pc is already at the binary objfile code. Not stepping."))
             return False
 
-    while pwndbg.gdblib.proc.alive:
-        gdb.execute("si", from_tty=False, to_string=False)
+    proc = pwndbg.gdblib.proc
+    regs = pwndbg.gdblib.regs
+
+    while proc.alive:
+        # Break on signal as it may be a segfault
+        if proc.stopped_with_signal:
+            return False
+
+        o = gdb.execute("si", from_tty=False, to_string=True)
 
-        pc = pwndbg.gdblib.regs.pc
         for start, end in binary_exec_page_ranges:
-            if start <= pc < end:
+            if start <= regs.pc < end:
                 return True
 
     return False
diff --git a/pwndbg/gdblib/proc.py b/pwndbg/gdblib/proc.py
--- a/pwndbg/gdblib/proc.py
+++ b/pwndbg/gdblib/proc.py
@@ -42,6 +42,11 @@
 
     @property
     def alive(self):
+        """
+        Informs whether the process has a thread. However, note that it will
+        still return True for a segfaulted thread. To detect that, consider
+        using the `stopped_with_signal` method.
+        """
         return gdb.selected_thread() is not None
 
     @property
@@ -56,6 +61,15 @@
         """
         return gdb.selected_thread().is_stopped()
 
+    @property
+    def stopped_with_signal(self) -> bool:
+        """
+        Returns whether the program has stopped with a signal
+
+        Can be used to detect segfaults (but will also detect other signals)
+        """
+        return "It stopped with signal " in gdb.execute("info program", to_string=True)
+
     @property
     def exe(self):
         """

{"golden_diff": "diff --git a/pwndbg/gdblib/next.py b/pwndbg/gdblib/next.py\n--- a/pwndbg/gdblib/next.py\n+++ b/pwndbg/gdblib/next.py\n@@ -91,6 +91,10 @@\n \n def break_next_call(symbol_regex=None):\n     while pwndbg.gdblib.proc.alive:\n+        # Break on signal as it may be a segfault\n+        if pwndbg.gdblib.proc.stopped_with_signal:\n+            return\n+\n         ins = break_next_branch()\n \n         if not ins:\n@@ -115,6 +119,10 @@\n \n def break_next_ret(address=None):\n     while pwndbg.gdblib.proc.alive:\n+        # Break on signal as it may be a segfault\n+        if pwndbg.gdblib.proc.stopped_with_signal:\n+            return\n+\n         ins = break_next_branch(address)\n \n         if not ins:\n@@ -126,13 +134,14 @@\n \n def break_on_program_code():\n     \"\"\"\n-    Breaks on next instruction that belongs to process' objfile code.\n-    :return: True for success, False when process ended or when pc is at the code.\n+    Breaks on next instruction that belongs to process' objfile code\n+\n+    :return: True for success, False when process ended or when pc is not at the code or if a signal occurred\n     \"\"\"\n     exe = pwndbg.gdblib.proc.exe\n-    binary_exec_page_ranges = [\n+    binary_exec_page_ranges = tuple(\n         (p.start, p.end) for p in pwndbg.vmmap.get() if p.objfile == exe and p.execute\n-    ]\n+    )\n \n     pc = pwndbg.gdblib.regs.pc\n     for start, end in binary_exec_page_ranges:\n@@ -140,12 +149,18 @@\n             print(message.error(\"The pc is already at the binary objfile code. Not stepping.\"))\n             return False\n \n-    while pwndbg.gdblib.proc.alive:\n-        gdb.execute(\"si\", from_tty=False, to_string=False)\n+    proc = pwndbg.gdblib.proc\n+    regs = pwndbg.gdblib.regs\n+\n+    while proc.alive:\n+        # Break on signal as it may be a segfault\n+        if proc.stopped_with_signal:\n+            return False\n+\n+        o = gdb.execute(\"si\", from_tty=False, to_string=True)\n \n-        pc = pwndbg.gdblib.regs.pc\n         for start, end in binary_exec_page_ranges:\n-            if start <= pc < end:\n+            if start <= regs.pc < end:\n                 return True\n \n     return False\ndiff --git a/pwndbg/gdblib/proc.py b/pwndbg/gdblib/proc.py\n--- a/pwndbg/gdblib/proc.py\n+++ b/pwndbg/gdblib/proc.py\n@@ -42,6 +42,11 @@\n \n     @property\n     def alive(self):\n+        \"\"\"\n+        Informs whether the process has a thread. However, note that it will\n+        still return True for a segfaulted thread. To detect that, consider\n+        using the `stopped_with_signal` method.\n+        \"\"\"\n         return gdb.selected_thread() is not None\n \n     @property\n@@ -56,6 +61,15 @@\n         \"\"\"\n         return gdb.selected_thread().is_stopped()\n \n+    @property\n+    def stopped_with_signal(self) -> bool:\n+        \"\"\"\n+        Returns whether the program has stopped with a signal\n+\n+        Can be used to detect segfaults (but will also detect other signals)\n+        \"\"\"\n+        return \"It stopped with signal \" in gdb.execute(\"info program\", to_string=True)\n+\n     @property\n     def exe(self):\n         \"\"\"\n", "issue": "`nextret` keeps going after the binary segfaults\nIf the binary segfaults when running `nextret` (and potentially the other `next*` commands), it keeps trying to continue until you kill it:\r\n```\r\nProgram received signal SIGSEGV, Segmentation fault.\r\n0x00007f7a8b4f9ae4 in __vfscanf_internal (s=0x7f7a8b6b0aa0 <_IO_2_1_stdin_>, format=0x4020ca \"%s\", argptr=argptr@entry=0x7ffeb13483a8, mode_flags=mode_flags@entry=2) at ./stdio-c\r\nommon/vfscanf-internal.c:339\r\n339     in ./stdio-common/vfscanf-internal.c\r\n\r\nProgram received signal SIGSEGV, Segmentation fault.\r\n0x00007f7a8b4f9ae4 in __vfscanf_internal (s=0x7f7a8b6b0aa0 <_IO_2_1_stdin_>, format=0x4020ca \"%s\", argptr=argptr@entry=0x7ffeb13483a8, mode_flags=mode_flags@entry=2) at ./stdio-c\r\nommon/vfscanf-internal.c:339\r\n339     in ./stdio-common/vfscanf-internal.c\r\n\r\nProgram received signal SIGSEGV, Segmentation fault.\r\n0x00007f7a8b4f9ae4 in __vfscanf_internal (s=0x7f7a8b6b0aa0 <_IO_2_1_stdin_>, format=0x4020ca \"%s\", argptr=argptr@entry=0x7ffeb13483a8, mode_flags=mode_flags@entry=2) at ./stdio-c\r\nommon/vfscanf-internal.c:339\r\n339     in ./stdio-common/vfscanf-internal.c\r\n```\r\n\r\nWe should stop after the first segfault and return to the prompt.\n", "before_files": [{"content": "\"\"\"\nProvides values which would be available from /proc which\nare not fulfilled by other modules and some process/gdb flow\nrelated information.\n\"\"\"\n\nimport functools\nimport sys\nfrom types import ModuleType\nfrom typing import Any\nfrom typing import Callable\n\nimport gdb\n\nimport pwndbg.gdblib.qemu\nimport pwndbg.lib.memoize\n\n\nclass module(ModuleType):\n    @property\n    def pid(self):\n        # QEMU usermode emulation always returns 42000 for some reason.\n        # In any case, we can't use the info.\n        if pwndbg.gdblib.qemu.is_qemu_usermode():\n            return pwndbg.gdblib.qemu.pid()\n\n        i = gdb.selected_inferior()\n        if i is not None:\n            return i.pid\n        return 0\n\n    @property\n    def tid(self):\n        if pwndbg.gdblib.qemu.is_qemu_usermode():\n            return pwndbg.gdblib.qemu.pid()\n\n        i = gdb.selected_thread()\n        if i is not None:\n            return i.ptid[1]\n\n        return self.pid\n\n    @property\n    def alive(self):\n        return gdb.selected_thread() is not None\n\n    @property\n    def thread_is_stopped(self):\n        \"\"\"\n        This detects whether selected thread is stopped.\n        It is not stopped in situations when gdb is executing commands\n        that are attached to a breakpoint by `command` command.\n\n        For more info see issue #229 ( https://github.com/pwndbg/pwndbg/issues/299 )\n        :return: Whether gdb executes commands attached to bp with `command` command.\n        \"\"\"\n        return gdb.selected_thread().is_stopped()\n\n    @property\n    def exe(self):\n        \"\"\"\n        Returns the debugged file name.\n\n        On remote targets, this may be prefixed with \"target:\" string.\n        See this by executing those in two terminals:\n        1. gdbserver 127.0.0.1:1234 /bin/ls\n        2. gdb -ex \"target remote :1234\" -ex \"pi pwndbg.gdblib.proc.exe\"\n\n        If you need to process the debugged file use:\n            `pwndbg.gdblib.file.get_file(pwndbg.gdblib.proc.exe)`\n        \"\"\"\n        return gdb.current_progspace().filename\n\n    def OnlyWhenRunning(self, func):\n        @functools.wraps(func)\n        def wrapper(*a, **kw):\n            if self.alive:\n                return func(*a, **kw)\n\n        return wrapper\n\n\nOnlyWhenRunning: Callable[[Any], Any]\n# To prevent garbage collection\ntether = sys.modules[__name__]\n\nsys.modules[__name__] = module(__name__, \"\")\n", "path": "pwndbg/gdblib/proc.py"}, {"content": "\"\"\"\nCommands for setting temporary breakpoints on the next\ninstruction of some type (call, branch, etc.)\n\"\"\"\n\nimport re\n\nimport capstone\nimport gdb\n\nimport pwndbg.disasm\nimport pwndbg.gdblib.events\nimport pwndbg.gdblib.proc\nimport pwndbg.gdblib.regs\nfrom pwndbg.color import message\n\njumps = set((capstone.CS_GRP_CALL, capstone.CS_GRP_JUMP, capstone.CS_GRP_RET, capstone.CS_GRP_IRET))\n\ninterrupts = set((capstone.CS_GRP_INT,))\n\n\n@pwndbg.gdblib.events.exit\ndef clear_temp_breaks():\n    if not pwndbg.gdblib.proc.alive:\n        breakpoints = gdb.breakpoints()\n        if breakpoints:\n            for bp in breakpoints:\n                if (\n                    bp.temporary and not bp.visible\n                ):  # visible is used instead of internal because older gdb's don't support internal\n                    bp.delete()\n\n\ndef next_int(address=None):\n    \"\"\"\n    If there is a syscall in the current basic black,\n    return the instruction of the one closest to $PC.\n\n    Otherwise, return None.\n    \"\"\"\n    if address is None:\n        ins = pwndbg.disasm.one(pwndbg.gdblib.regs.pc)\n        if not ins:\n            return None\n        address = ins.next\n\n    ins = pwndbg.disasm.one(address)\n    while ins:\n        if set(ins.groups) & jumps:\n            return None\n        if set(ins.groups) & interrupts:\n            return ins\n        ins = pwndbg.disasm.one(ins.next)\n\n    return None\n\n\ndef next_branch(address=None):\n    if address is None:\n        ins = pwndbg.disasm.one(pwndbg.gdblib.regs.pc)\n        if not ins:\n            return None\n        address = ins.next\n\n    ins = pwndbg.disasm.one(address)\n    while ins:\n        if set(ins.groups) & jumps:\n            return ins\n        ins = pwndbg.disasm.one(ins.next)\n\n    return None\n\n\ndef break_next_branch(address=None):\n    ins = next_branch(address)\n\n    if ins:\n        gdb.Breakpoint(\"*%#x\" % ins.address, internal=True, temporary=True)\n        gdb.execute(\"continue\", from_tty=False, to_string=True)\n        return ins\n\n\ndef break_next_interrupt(address=None):\n    ins = next_int(address)\n\n    if ins:\n        gdb.Breakpoint(\"*%#x\" % ins.address, internal=True, temporary=True)\n        gdb.execute(\"continue\", from_tty=False, to_string=True)\n        return ins\n\n\ndef break_next_call(symbol_regex=None):\n    while pwndbg.gdblib.proc.alive:\n        ins = break_next_branch()\n\n        if not ins:\n            break\n\n        # continue if not a call\n        if capstone.CS_GRP_CALL not in ins.groups:\n            continue\n\n        # return call if we don't search for a symbol\n        if not symbol_regex:\n            return ins\n\n        # return call if we match target address\n        if ins.target_const and re.match(\"%s$\" % symbol_regex, hex(ins.target)):\n            return ins\n\n        # return call if we match symbol name\n        if ins.symbol and re.match(\"%s$\" % symbol_regex, ins.symbol):\n            return ins\n\n\ndef break_next_ret(address=None):\n    while pwndbg.gdblib.proc.alive:\n        ins = break_next_branch(address)\n\n        if not ins:\n            break\n\n        if capstone.CS_GRP_RET in ins.groups:\n            return ins\n\n\ndef break_on_program_code():\n    \"\"\"\n    Breaks on next instruction that belongs to process' objfile code.\n    :return: True for success, False when process ended or when pc is at the code.\n    \"\"\"\n    exe = pwndbg.gdblib.proc.exe\n    binary_exec_page_ranges = [\n        (p.start, p.end) for p in pwndbg.vmmap.get() if p.objfile == exe and p.execute\n    ]\n\n    pc = pwndbg.gdblib.regs.pc\n    for start, end in binary_exec_page_ranges:\n        if start <= pc < end:\n            print(message.error(\"The pc is already at the binary objfile code. Not stepping.\"))\n            return False\n\n    while pwndbg.gdblib.proc.alive:\n        gdb.execute(\"si\", from_tty=False, to_string=False)\n\n        pc = pwndbg.gdblib.regs.pc\n        for start, end in binary_exec_page_ranges:\n            if start <= pc < end:\n                return True\n\n    return False\n\n\ndef break_on_next(address=None):\n    address = address or pwndbg.gdblib.regs.pc\n    ins = pwndbg.disasm.one(address)\n\n    gdb.Breakpoint(\"*%#x\" % (ins.address + ins.size), temporary=True)\n    gdb.execute(\"continue\", from_tty=False, to_string=True)\n", "path": "pwndbg/gdblib/next.py"}], "after_files": [{"content": "\"\"\"\nProvides values which would be available from /proc which\nare not fulfilled by other modules and some process/gdb flow\nrelated information.\n\"\"\"\n\nimport functools\nimport sys\nfrom types import ModuleType\nfrom typing import Any\nfrom typing import Callable\n\nimport gdb\n\nimport pwndbg.gdblib.qemu\nimport pwndbg.lib.memoize\n\n\nclass module(ModuleType):\n    @property\n    def pid(self):\n        # QEMU usermode emulation always returns 42000 for some reason.\n        # In any case, we can't use the info.\n        if pwndbg.gdblib.qemu.is_qemu_usermode():\n            return pwndbg.gdblib.qemu.pid()\n\n        i = gdb.selected_inferior()\n        if i is not None:\n            return i.pid\n        return 0\n\n    @property\n    def tid(self):\n        if pwndbg.gdblib.qemu.is_qemu_usermode():\n            return pwndbg.gdblib.qemu.pid()\n\n        i = gdb.selected_thread()\n        if i is not None:\n            return i.ptid[1]\n\n        return self.pid\n\n    @property\n    def alive(self):\n        \"\"\"\n        Informs whether the process has a thread. However, note that it will\n        still return True for a segfaulted thread. To detect that, consider\n        using the `stopped_with_signal` method.\n        \"\"\"\n        return gdb.selected_thread() is not None\n\n    @property\n    def thread_is_stopped(self):\n        \"\"\"\n        This detects whether selected thread is stopped.\n        It is not stopped in situations when gdb is executing commands\n        that are attached to a breakpoint by `command` command.\n\n        For more info see issue #229 ( https://github.com/pwndbg/pwndbg/issues/299 )\n        :return: Whether gdb executes commands attached to bp with `command` command.\n        \"\"\"\n        return gdb.selected_thread().is_stopped()\n\n    @property\n    def stopped_with_signal(self) -> bool:\n        \"\"\"\n        Returns whether the program has stopped with a signal\n\n        Can be used to detect segfaults (but will also detect other signals)\n        \"\"\"\n        return \"It stopped with signal \" in gdb.execute(\"info program\", to_string=True)\n\n    @property\n    def exe(self):\n        \"\"\"\n        Returns the debugged file name.\n\n        On remote targets, this may be prefixed with \"target:\" string.\n        See this by executing those in two terminals:\n        1. gdbserver 127.0.0.1:1234 /bin/ls\n        2. gdb -ex \"target remote :1234\" -ex \"pi pwndbg.gdblib.proc.exe\"\n\n        If you need to process the debugged file use:\n            `pwndbg.gdblib.file.get_file(pwndbg.gdblib.proc.exe)`\n        \"\"\"\n        return gdb.current_progspace().filename\n\n    def OnlyWhenRunning(self, func):\n        @functools.wraps(func)\n        def wrapper(*a, **kw):\n            if self.alive:\n                return func(*a, **kw)\n\n        return wrapper\n\n\nOnlyWhenRunning: Callable[[Any], Any]\n# To prevent garbage collection\ntether = sys.modules[__name__]\n\nsys.modules[__name__] = module(__name__, \"\")\n", "path": "pwndbg/gdblib/proc.py"}, {"content": "\"\"\"\nCommands for setting temporary breakpoints on the next\ninstruction of some type (call, branch, etc.)\n\"\"\"\n\nimport re\n\nimport capstone\nimport gdb\n\nimport pwndbg.disasm\nimport pwndbg.gdblib.events\nimport pwndbg.gdblib.proc\nimport pwndbg.gdblib.regs\nfrom pwndbg.color import message\n\njumps = set((capstone.CS_GRP_CALL, capstone.CS_GRP_JUMP, capstone.CS_GRP_RET, capstone.CS_GRP_IRET))\n\ninterrupts = set((capstone.CS_GRP_INT,))\n\n\n@pwndbg.gdblib.events.exit\ndef clear_temp_breaks():\n    if not pwndbg.gdblib.proc.alive:\n        breakpoints = gdb.breakpoints()\n        if breakpoints:\n            for bp in breakpoints:\n                if (\n                    bp.temporary and not bp.visible\n                ):  # visible is used instead of internal because older gdb's don't support internal\n                    bp.delete()\n\n\ndef next_int(address=None):\n    \"\"\"\n    If there is a syscall in the current basic black,\n    return the instruction of the one closest to $PC.\n\n    Otherwise, return None.\n    \"\"\"\n    if address is None:\n        ins = pwndbg.disasm.one(pwndbg.gdblib.regs.pc)\n        if not ins:\n            return None\n        address = ins.next\n\n    ins = pwndbg.disasm.one(address)\n    while ins:\n        if set(ins.groups) & jumps:\n            return None\n        if set(ins.groups) & interrupts:\n            return ins\n        ins = pwndbg.disasm.one(ins.next)\n\n    return None\n\n\ndef next_branch(address=None):\n    if address is None:\n        ins = pwndbg.disasm.one(pwndbg.gdblib.regs.pc)\n        if not ins:\n            return None\n        address = ins.next\n\n    ins = pwndbg.disasm.one(address)\n    while ins:\n        if set(ins.groups) & jumps:\n            return ins\n        ins = pwndbg.disasm.one(ins.next)\n\n    return None\n\n\ndef break_next_branch(address=None):\n    ins = next_branch(address)\n\n    if ins:\n        gdb.Breakpoint(\"*%#x\" % ins.address, internal=True, temporary=True)\n        gdb.execute(\"continue\", from_tty=False, to_string=True)\n        return ins\n\n\ndef break_next_interrupt(address=None):\n    ins = next_int(address)\n\n    if ins:\n        gdb.Breakpoint(\"*%#x\" % ins.address, internal=True, temporary=True)\n        gdb.execute(\"continue\", from_tty=False, to_string=True)\n        return ins\n\n\ndef break_next_call(symbol_regex=None):\n    while pwndbg.gdblib.proc.alive:\n        # Break on signal as it may be a segfault\n        if pwndbg.gdblib.proc.stopped_with_signal:\n            return\n\n        ins = break_next_branch()\n\n        if not ins:\n            break\n\n        # continue if not a call\n        if capstone.CS_GRP_CALL not in ins.groups:\n            continue\n\n        # return call if we don't search for a symbol\n        if not symbol_regex:\n            return ins\n\n        # return call if we match target address\n        if ins.target_const and re.match(\"%s$\" % symbol_regex, hex(ins.target)):\n            return ins\n\n        # return call if we match symbol name\n        if ins.symbol and re.match(\"%s$\" % symbol_regex, ins.symbol):\n            return ins\n\n\ndef break_next_ret(address=None):\n    while pwndbg.gdblib.proc.alive:\n        # Break on signal as it may be a segfault\n        if pwndbg.gdblib.proc.stopped_with_signal:\n            return\n\n        ins = break_next_branch(address)\n\n        if not ins:\n            break\n\n        if capstone.CS_GRP_RET in ins.groups:\n            return ins\n\n\ndef break_on_program_code():\n    \"\"\"\n    Breaks on next instruction that belongs to process' objfile code\n\n    :return: True for success, False when process ended or when pc is not at the code or if a signal occurred\n    \"\"\"\n    exe = pwndbg.gdblib.proc.exe\n    binary_exec_page_ranges = tuple(\n        (p.start, p.end) for p in pwndbg.vmmap.get() if p.objfile == exe and p.execute\n    )\n\n    pc = pwndbg.gdblib.regs.pc\n    for start, end in binary_exec_page_ranges:\n        if start <= pc < end:\n            print(message.error(\"The pc is already at the binary objfile code. Not stepping.\"))\n            return False\n\n    proc = pwndbg.gdblib.proc\n    regs = pwndbg.gdblib.regs\n\n    while proc.alive:\n        # Break on signal as it may be a segfault\n        if proc.stopped_with_signal:\n            return False\n\n        o = gdb.execute(\"si\", from_tty=False, to_string=True)\n\n        for start, end in binary_exec_page_ranges:\n            if start <= regs.pc < end:\n                return True\n\n    return False\n\n\ndef break_on_next(address=None):\n    address = address or pwndbg.gdblib.regs.pc\n    ins = pwndbg.disasm.one(address)\n\n    gdb.Breakpoint(\"*%#x\" % (ins.address + ins.size), temporary=True)\n    gdb.execute(\"continue\", from_tty=False, to_string=True)\n", "path": "pwndbg/gdblib/next.py"}]}