We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add `telescope --frame`
It'd be nice to have a `telescope` command that prints out the stack frame, from `rsp` to `rbp`. Obviously this only works if the program actually uses a frame pointer.

It would be equivalent to this:
```
pwndbg> p ($rbp-$rsp)/8 + 1
$5 = 9
pwndbg> telescope $rsp $$
00:0000│ rsp 0x7ffe5f4951a0 ◂— 0x300000001
01:0008│     0x7ffe5f4951a8 —▸ 0x7ffe5f495220 ◂— 0x170c94ca0
02:0010│     0x7ffe5f4951b0 —▸ 0x7f6870c96168 —▸ 0x563e09600000 ◂— jg     0x563e09600047
03:0018│     0x7ffe5f4951b8 ◂— 0xf0
04:0020│ rsi 0x7ffe5f4951c0 ◂— 0xb1ed2074ada5ce5
05:0028│     0x7ffe5f4951c8 ◂— 0xda37756c736484c1
06:0030│     0x7ffe5f4951d0 —▸ 0x7ffe5f4951fe ◂— 0x563e096013e00000
07:0038│     0x7ffe5f4951d8 ◂— 0x56657596c3d91600
08:0040│ rbp 0x7ffe5f4951e0 —▸ 0x7ffe5f495200 —▸ 0x563e096013e0 ◂— push   r15
```

--- 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/commands/telescope.py`
Content:
```
1 """
2 Prints out pointer chains starting at some address in memory.
3 
4 Generally used to print out the stack or register values.
5 """
6 
7 from __future__ import annotations
8 
9 import argparse
10 import collections
11 import math
12 
13 import pwndbg.chain
14 import pwndbg.color.telescope as T
15 import pwndbg.commands
16 import pwndbg.gdblib.arch
17 import pwndbg.gdblib.config
18 import pwndbg.gdblib.memory
19 import pwndbg.gdblib.regs
20 import pwndbg.gdblib.typeinfo
21 from pwndbg.color import theme
22 from pwndbg.commands import CommandCategory
23 
24 telescope_lines = pwndbg.gdblib.config.add_param(
25     "telescope-lines", 8, "number of lines to printed by the telescope command"
26 )
27 skip_repeating_values = pwndbg.gdblib.config.add_param(
28     "telescope-skip-repeating-val",
29     True,
30     "whether to skip repeating values of the telescope command",
31 )
32 skip_repeating_values_minimum = pwndbg.gdblib.config.add_param(
33     "telescope-skip-repeating-val-minimum",
34     3,
35     "minimum amount of repeated values before skipping lines",
36 )
37 
38 offset_separator = theme.add_param(
39     "telescope-offset-separator", "│", "offset separator of the telescope command"
40 )
41 offset_delimiter = theme.add_param(
42     "telescope-offset-delimiter", ":", "offset delimiter of the telescope command"
43 )
44 repeating_marker = theme.add_param(
45     "telescope-repeating-marker", "... ↓", "repeating values marker of the telescope command"
46 )
47 
48 
49 parser = argparse.ArgumentParser(
50     description="Recursively dereferences pointers starting at the specified address."
51 )
52 parser.add_argument(
53     "-r",
54     "--reverse",
55     dest="reverse",
56     action="store_true",
57     default=False,
58     help="Show <count> previous addresses instead of next ones",
59 )
60 
61 parser.add_argument(
62     "address", nargs="?", default="$sp", type=int, help="The address to telescope at."
63 )
64 
65 parser.add_argument(
66     "count", nargs="?", default=telescope_lines, type=int, help="The number of lines to show."
67 )
68 
69 
70 @pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.MEMORY)
71 @pwndbg.commands.OnlyWhenRunning
72 def telescope(address=None, count=telescope_lines, to_string=False, reverse=False):
73     """
74     Recursively dereferences pointers starting at the specified address
75     ($sp by default)
76     """
77     ptrsize = pwndbg.gdblib.typeinfo.ptrsize
78     if telescope.repeat:
79         address = telescope.last_address + ptrsize
80         telescope.offset += 1
81     else:
82         telescope.offset = 0
83 
84     address = int(address if address else pwndbg.gdblib.regs.sp) & pwndbg.gdblib.arch.ptrmask
85     input_address = address
86     count = max(int(count), 1) & pwndbg.gdblib.arch.ptrmask
87     delimiter = T.delimiter(offset_delimiter)
88     separator = T.separator(offset_separator)
89 
90     # Allow invocation of "telescope 20" to dump 20 bytes at the stack pointer
91     if address < pwndbg.gdblib.memory.MMAP_MIN_ADDR and not pwndbg.gdblib.memory.peek(address):
92         count = address
93         address = pwndbg.gdblib.regs.sp
94 
95     # Allow invocation of telescope -r to dump previous addresses
96     if reverse:
97         address -= (count - 1) * ptrsize
98 
99     # Allow invocation of "telescope a b" to dump all bytes from A to B
100     if int(address) <= int(count):
101         # adjust count if it is an address. use ceil division as count is number of
102         # ptrsize values and we don't want to strip out a value if dest is unaligned
103         count -= address
104         count = max(math.ceil(count / ptrsize), 1)
105 
106     reg_values = collections.defaultdict(lambda: [])
107     for reg in pwndbg.gdblib.regs.common:
108         reg_values[pwndbg.gdblib.regs[reg]].append(reg)
109 
110     start = address
111     stop = address + (count * ptrsize)
112     step = ptrsize
113 
114     # Find all registers which show up in the trace
115     regs = {}
116     for i in range(start, stop, step):
117         values = list(reg_values[i])
118 
119         for width in range(1, pwndbg.gdblib.arch.ptrsize):
120             values.extend("%s-%i" % (r, width) for r in reg_values[i + width])
121 
122         regs[i] = " ".join(values)
123 
124     # Find the longest set of register information
125     if regs:
126         longest_regs = max(map(len, regs.values()))
127     else:
128         longest_regs = 0
129 
130     # Print everything out
131     result = []
132     last = None
133     collapse_buffer: list[str] = []
134     skipped_padding = (
135         2
136         + len(offset_delimiter)
137         + 4
138         + len(offset_separator)
139         + 1
140         + longest_regs
141         + 1
142         - len(repeating_marker)
143     )
144 
145     # Collapse repeating values exceeding minimum delta.
146     def collapse_repeating_values() -> None:
147         # The first line was already printed, hence increment by 1
148         if collapse_buffer and len(collapse_buffer) + 1 >= skip_repeating_values_minimum:
149             result.append(
150                 T.repeating_marker(
151                     "%s%s%i skipped"
152                     % (repeating_marker, " " * skipped_padding, len(collapse_buffer))
153                 )
154             )
155         else:
156             result.extend(collapse_buffer)
157         collapse_buffer.clear()
158 
159     for i, addr in enumerate(range(start, stop, step)):
160         if not pwndbg.gdblib.memory.peek(addr):
161             collapse_repeating_values()
162             result.append("<Could not read memory at %#x>" % addr)
163             break
164 
165         line = " ".join(
166             (
167                 T.offset(
168                     "%02x%s%04x%s"
169                     % (
170                         i + telescope.offset,
171                         delimiter,
172                         addr - start + (telescope.offset * ptrsize),
173                         separator,
174                     )
175                 ),
176                 T.register(regs[addr].ljust(longest_regs)),
177                 pwndbg.chain.format(addr),
178             )
179         )
180 
181         # Buffer repeating values.
182         if skip_repeating_values:
183             value = pwndbg.gdblib.memory.pvoid(addr)
184             if last == value and addr != input_address:
185                 collapse_buffer.append(line)
186                 continue
187             collapse_repeating_values()
188             last = value
189 
190         result.append(line)
191 
192     collapse_repeating_values()
193     telescope.offset += i
194     telescope.last_address = addr
195 
196     if not to_string:
197         print("\n".join(result))
198 
199     return result
200 
201 
202 parser = argparse.ArgumentParser(
203     description="Dereferences on stack data with specified count and offset."
204 )
205 parser.add_argument("count", nargs="?", default=8, type=int, help="number of element to dump")
206 parser.add_argument(
207     "offset",
208     nargs="?",
209     default=0,
210     type=int,
211     help="Element offset from $sp (support negative offset)",
212 )
213 
214 
215 @pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.STACK)
216 @pwndbg.commands.OnlyWhenRunning
217 def stack(count, offset) -> None:
218     ptrsize = pwndbg.gdblib.typeinfo.ptrsize
219     telescope.repeat = stack.repeat
220     telescope(address=pwndbg.gdblib.regs.sp + offset * ptrsize, count=count)
221 
222 
223 telescope.last_address = 0
224 telescope.offset = 0
225
```
--- 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/commands/telescope.py b/pwndbg/commands/telescope.py
--- a/pwndbg/commands/telescope.py
+++ b/pwndbg/commands/telescope.py
@@ -58,6 +58,15 @@
     help="Show <count> previous addresses instead of next ones",
 )
 
+parser.add_argument(
+    "-f",
+    "--frame",
+    dest="frame",
+    action="store_true",
+    default=False,
+    help="Show the stack frame, from rsp to rbp",
+)
+
 parser.add_argument(
     "address", nargs="?", default="$sp", type=int, help="The address to telescope at."
 )
@@ -69,7 +78,7 @@
 
 @pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.MEMORY)
 @pwndbg.commands.OnlyWhenRunning
-def telescope(address=None, count=telescope_lines, to_string=False, reverse=False):
+def telescope(address=None, count=telescope_lines, to_string=False, reverse=False, frame=False):
     """
     Recursively dereferences pointers starting at the specified address
     ($sp by default)
@@ -96,6 +105,24 @@
     if reverse:
         address -= (count - 1) * ptrsize
 
+    # Allow invocation of telescope -f (--frame) to dump frame addresses
+    if frame:
+        sp = pwndbg.gdblib.regs.sp
+        bp = pwndbg.gdblib.regs[pwndbg.gdblib.regs.frame]
+        if sp > bp:
+            print("Cannot display stack frame because base pointer is below stack pointer")
+            return
+
+        for page in pwndbg.gdblib.vmmap.get():
+            if sp in page and bp not in page:
+                print(
+                    "Cannot display stack frame because base pointer is not on the same page with stack pointer"
+                )
+                return
+
+        address = sp
+        count = int((bp - sp) / ptrsize) + 1
+
     # Allow invocation of "telescope a b" to dump all bytes from A to B
     if int(address) <= int(count):
         # adjust count if it is an address. use ceil division as count is number of

{"golden_diff": "diff --git a/pwndbg/commands/telescope.py b/pwndbg/commands/telescope.py\n--- a/pwndbg/commands/telescope.py\n+++ b/pwndbg/commands/telescope.py\n@@ -58,6 +58,15 @@\n     help=\"Show <count> previous addresses instead of next ones\",\n )\n \n+parser.add_argument(\n+    \"-f\",\n+    \"--frame\",\n+    dest=\"frame\",\n+    action=\"store_true\",\n+    default=False,\n+    help=\"Show the stack frame, from rsp to rbp\",\n+)\n+\n parser.add_argument(\n     \"address\", nargs=\"?\", default=\"$sp\", type=int, help=\"The address to telescope at.\"\n )\n@@ -69,7 +78,7 @@\n \n @pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.MEMORY)\n @pwndbg.commands.OnlyWhenRunning\n-def telescope(address=None, count=telescope_lines, to_string=False, reverse=False):\n+def telescope(address=None, count=telescope_lines, to_string=False, reverse=False, frame=False):\n     \"\"\"\n     Recursively dereferences pointers starting at the specified address\n     ($sp by default)\n@@ -96,6 +105,24 @@\n     if reverse:\n         address -= (count - 1) * ptrsize\n \n+    # Allow invocation of telescope -f (--frame) to dump frame addresses\n+    if frame:\n+        sp = pwndbg.gdblib.regs.sp\n+        bp = pwndbg.gdblib.regs[pwndbg.gdblib.regs.frame]\n+        if sp > bp:\n+            print(\"Cannot display stack frame because base pointer is below stack pointer\")\n+            return\n+\n+        for page in pwndbg.gdblib.vmmap.get():\n+            if sp in page and bp not in page:\n+                print(\n+                    \"Cannot display stack frame because base pointer is not on the same page with stack pointer\"\n+                )\n+                return\n+\n+        address = sp\n+        count = int((bp - sp) / ptrsize) + 1\n+\n     # Allow invocation of \"telescope a b\" to dump all bytes from A to B\n     if int(address) <= int(count):\n         # adjust count if it is an address. use ceil division as count is number of\n", "issue": "Add `telescope --frame`\nIt'd be nice to have a `telescope` command that prints out the stack frame, from `rsp` to `rbp`. Obviously this only works if the program actually uses a frame pointer.\r\n\r\nIt would be equivalent to this:\r\n```\r\npwndbg> p ($rbp-$rsp)/8 + 1\r\n$5 = 9\r\npwndbg> telescope $rsp $$\r\n00:0000\u2502 rsp 0x7ffe5f4951a0 \u25c2\u2014 0x300000001\r\n01:0008\u2502     0x7ffe5f4951a8 \u2014\u25b8 0x7ffe5f495220 \u25c2\u2014 0x170c94ca0\r\n02:0010\u2502     0x7ffe5f4951b0 \u2014\u25b8 0x7f6870c96168 \u2014\u25b8 0x563e09600000 \u25c2\u2014 jg     0x563e09600047\r\n03:0018\u2502     0x7ffe5f4951b8 \u25c2\u2014 0xf0\r\n04:0020\u2502 rsi 0x7ffe5f4951c0 \u25c2\u2014 0xb1ed2074ada5ce5\r\n05:0028\u2502     0x7ffe5f4951c8 \u25c2\u2014 0xda37756c736484c1\r\n06:0030\u2502     0x7ffe5f4951d0 \u2014\u25b8 0x7ffe5f4951fe \u25c2\u2014 0x563e096013e00000\r\n07:0038\u2502     0x7ffe5f4951d8 \u25c2\u2014 0x56657596c3d91600\r\n08:0040\u2502 rbp 0x7ffe5f4951e0 \u2014\u25b8 0x7ffe5f495200 \u2014\u25b8 0x563e096013e0 \u25c2\u2014 push   r15\r\n```\n", "before_files": [{"content": "\"\"\"\nPrints out pointer chains starting at some address in memory.\n\nGenerally used to print out the stack or register values.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport collections\nimport math\n\nimport pwndbg.chain\nimport pwndbg.color.telescope as T\nimport pwndbg.commands\nimport pwndbg.gdblib.arch\nimport pwndbg.gdblib.config\nimport pwndbg.gdblib.memory\nimport pwndbg.gdblib.regs\nimport pwndbg.gdblib.typeinfo\nfrom pwndbg.color import theme\nfrom pwndbg.commands import CommandCategory\n\ntelescope_lines = pwndbg.gdblib.config.add_param(\n    \"telescope-lines\", 8, \"number of lines to printed by the telescope command\"\n)\nskip_repeating_values = pwndbg.gdblib.config.add_param(\n    \"telescope-skip-repeating-val\",\n    True,\n    \"whether to skip repeating values of the telescope command\",\n)\nskip_repeating_values_minimum = pwndbg.gdblib.config.add_param(\n    \"telescope-skip-repeating-val-minimum\",\n    3,\n    \"minimum amount of repeated values before skipping lines\",\n)\n\noffset_separator = theme.add_param(\n    \"telescope-offset-separator\", \"\u2502\", \"offset separator of the telescope command\"\n)\noffset_delimiter = theme.add_param(\n    \"telescope-offset-delimiter\", \":\", \"offset delimiter of the telescope command\"\n)\nrepeating_marker = theme.add_param(\n    \"telescope-repeating-marker\", \"... \u2193\", \"repeating values marker of the telescope command\"\n)\n\n\nparser = argparse.ArgumentParser(\n    description=\"Recursively dereferences pointers starting at the specified address.\"\n)\nparser.add_argument(\n    \"-r\",\n    \"--reverse\",\n    dest=\"reverse\",\n    action=\"store_true\",\n    default=False,\n    help=\"Show <count> previous addresses instead of next ones\",\n)\n\nparser.add_argument(\n    \"address\", nargs=\"?\", default=\"$sp\", type=int, help=\"The address to telescope at.\"\n)\n\nparser.add_argument(\n    \"count\", nargs=\"?\", default=telescope_lines, type=int, help=\"The number of lines to show.\"\n)\n\n\n@pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.MEMORY)\n@pwndbg.commands.OnlyWhenRunning\ndef telescope(address=None, count=telescope_lines, to_string=False, reverse=False):\n    \"\"\"\n    Recursively dereferences pointers starting at the specified address\n    ($sp by default)\n    \"\"\"\n    ptrsize = pwndbg.gdblib.typeinfo.ptrsize\n    if telescope.repeat:\n        address = telescope.last_address + ptrsize\n        telescope.offset += 1\n    else:\n        telescope.offset = 0\n\n    address = int(address if address else pwndbg.gdblib.regs.sp) & pwndbg.gdblib.arch.ptrmask\n    input_address = address\n    count = max(int(count), 1) & pwndbg.gdblib.arch.ptrmask\n    delimiter = T.delimiter(offset_delimiter)\n    separator = T.separator(offset_separator)\n\n    # Allow invocation of \"telescope 20\" to dump 20 bytes at the stack pointer\n    if address < pwndbg.gdblib.memory.MMAP_MIN_ADDR and not pwndbg.gdblib.memory.peek(address):\n        count = address\n        address = pwndbg.gdblib.regs.sp\n\n    # Allow invocation of telescope -r to dump previous addresses\n    if reverse:\n        address -= (count - 1) * ptrsize\n\n    # Allow invocation of \"telescope a b\" to dump all bytes from A to B\n    if int(address) <= int(count):\n        # adjust count if it is an address. use ceil division as count is number of\n        # ptrsize values and we don't want to strip out a value if dest is unaligned\n        count -= address\n        count = max(math.ceil(count / ptrsize), 1)\n\n    reg_values = collections.defaultdict(lambda: [])\n    for reg in pwndbg.gdblib.regs.common:\n        reg_values[pwndbg.gdblib.regs[reg]].append(reg)\n\n    start = address\n    stop = address + (count * ptrsize)\n    step = ptrsize\n\n    # Find all registers which show up in the trace\n    regs = {}\n    for i in range(start, stop, step):\n        values = list(reg_values[i])\n\n        for width in range(1, pwndbg.gdblib.arch.ptrsize):\n            values.extend(\"%s-%i\" % (r, width) for r in reg_values[i + width])\n\n        regs[i] = \" \".join(values)\n\n    # Find the longest set of register information\n    if regs:\n        longest_regs = max(map(len, regs.values()))\n    else:\n        longest_regs = 0\n\n    # Print everything out\n    result = []\n    last = None\n    collapse_buffer: list[str] = []\n    skipped_padding = (\n        2\n        + len(offset_delimiter)\n        + 4\n        + len(offset_separator)\n        + 1\n        + longest_regs\n        + 1\n        - len(repeating_marker)\n    )\n\n    # Collapse repeating values exceeding minimum delta.\n    def collapse_repeating_values() -> None:\n        # The first line was already printed, hence increment by 1\n        if collapse_buffer and len(collapse_buffer) + 1 >= skip_repeating_values_minimum:\n            result.append(\n                T.repeating_marker(\n                    \"%s%s%i skipped\"\n                    % (repeating_marker, \" \" * skipped_padding, len(collapse_buffer))\n                )\n            )\n        else:\n            result.extend(collapse_buffer)\n        collapse_buffer.clear()\n\n    for i, addr in enumerate(range(start, stop, step)):\n        if not pwndbg.gdblib.memory.peek(addr):\n            collapse_repeating_values()\n            result.append(\"<Could not read memory at %#x>\" % addr)\n            break\n\n        line = \" \".join(\n            (\n                T.offset(\n                    \"%02x%s%04x%s\"\n                    % (\n                        i + telescope.offset,\n                        delimiter,\n                        addr - start + (telescope.offset * ptrsize),\n                        separator,\n                    )\n                ),\n                T.register(regs[addr].ljust(longest_regs)),\n                pwndbg.chain.format(addr),\n            )\n        )\n\n        # Buffer repeating values.\n        if skip_repeating_values:\n            value = pwndbg.gdblib.memory.pvoid(addr)\n            if last == value and addr != input_address:\n                collapse_buffer.append(line)\n                continue\n            collapse_repeating_values()\n            last = value\n\n        result.append(line)\n\n    collapse_repeating_values()\n    telescope.offset += i\n    telescope.last_address = addr\n\n    if not to_string:\n        print(\"\\n\".join(result))\n\n    return result\n\n\nparser = argparse.ArgumentParser(\n    description=\"Dereferences on stack data with specified count and offset.\"\n)\nparser.add_argument(\"count\", nargs=\"?\", default=8, type=int, help=\"number of element to dump\")\nparser.add_argument(\n    \"offset\",\n    nargs=\"?\",\n    default=0,\n    type=int,\n    help=\"Element offset from $sp (support negative offset)\",\n)\n\n\n@pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.STACK)\n@pwndbg.commands.OnlyWhenRunning\ndef stack(count, offset) -> None:\n    ptrsize = pwndbg.gdblib.typeinfo.ptrsize\n    telescope.repeat = stack.repeat\n    telescope(address=pwndbg.gdblib.regs.sp + offset * ptrsize, count=count)\n\n\ntelescope.last_address = 0\ntelescope.offset = 0\n", "path": "pwndbg/commands/telescope.py"}], "after_files": [{"content": "\"\"\"\nPrints out pointer chains starting at some address in memory.\n\nGenerally used to print out the stack or register values.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport collections\nimport math\n\nimport pwndbg.chain\nimport pwndbg.color.telescope as T\nimport pwndbg.commands\nimport pwndbg.gdblib.arch\nimport pwndbg.gdblib.config\nimport pwndbg.gdblib.memory\nimport pwndbg.gdblib.regs\nimport pwndbg.gdblib.typeinfo\nfrom pwndbg.color import theme\nfrom pwndbg.commands import CommandCategory\n\ntelescope_lines = pwndbg.gdblib.config.add_param(\n    \"telescope-lines\", 8, \"number of lines to printed by the telescope command\"\n)\nskip_repeating_values = pwndbg.gdblib.config.add_param(\n    \"telescope-skip-repeating-val\",\n    True,\n    \"whether to skip repeating values of the telescope command\",\n)\nskip_repeating_values_minimum = pwndbg.gdblib.config.add_param(\n    \"telescope-skip-repeating-val-minimum\",\n    3,\n    \"minimum amount of repeated values before skipping lines\",\n)\n\noffset_separator = theme.add_param(\n    \"telescope-offset-separator\", \"\u2502\", \"offset separator of the telescope command\"\n)\noffset_delimiter = theme.add_param(\n    \"telescope-offset-delimiter\", \":\", \"offset delimiter of the telescope command\"\n)\nrepeating_marker = theme.add_param(\n    \"telescope-repeating-marker\", \"... \u2193\", \"repeating values marker of the telescope command\"\n)\n\n\nparser = argparse.ArgumentParser(\n    description=\"Recursively dereferences pointers starting at the specified address.\"\n)\nparser.add_argument(\n    \"-r\",\n    \"--reverse\",\n    dest=\"reverse\",\n    action=\"store_true\",\n    default=False,\n    help=\"Show <count> previous addresses instead of next ones\",\n)\n\nparser.add_argument(\n    \"-f\",\n    \"--frame\",\n    dest=\"frame\",\n    action=\"store_true\",\n    default=False,\n    help=\"Show the stack frame, from rsp to rbp\",\n)\n\nparser.add_argument(\n    \"address\", nargs=\"?\", default=\"$sp\", type=int, help=\"The address to telescope at.\"\n)\n\nparser.add_argument(\n    \"count\", nargs=\"?\", default=telescope_lines, type=int, help=\"The number of lines to show.\"\n)\n\n\n@pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.MEMORY)\n@pwndbg.commands.OnlyWhenRunning\ndef telescope(address=None, count=telescope_lines, to_string=False, reverse=False, frame=False):\n    \"\"\"\n    Recursively dereferences pointers starting at the specified address\n    ($sp by default)\n    \"\"\"\n    ptrsize = pwndbg.gdblib.typeinfo.ptrsize\n    if telescope.repeat:\n        address = telescope.last_address + ptrsize\n        telescope.offset += 1\n    else:\n        telescope.offset = 0\n\n    address = int(address if address else pwndbg.gdblib.regs.sp) & pwndbg.gdblib.arch.ptrmask\n    input_address = address\n    count = max(int(count), 1) & pwndbg.gdblib.arch.ptrmask\n    delimiter = T.delimiter(offset_delimiter)\n    separator = T.separator(offset_separator)\n\n    # Allow invocation of \"telescope 20\" to dump 20 bytes at the stack pointer\n    if address < pwndbg.gdblib.memory.MMAP_MIN_ADDR and not pwndbg.gdblib.memory.peek(address):\n        count = address\n        address = pwndbg.gdblib.regs.sp\n\n    # Allow invocation of telescope -r to dump previous addresses\n    if reverse:\n        address -= (count - 1) * ptrsize\n\n    # Allow invocation of telescope -f (--frame) to dump frame addresses\n    if frame:\n        sp = pwndbg.gdblib.regs.sp\n        bp = pwndbg.gdblib.regs[pwndbg.gdblib.regs.frame]\n        if sp > bp:\n            print(\"Cannot display stack frame because base pointer is below stack pointer\")\n            return\n\n        for page in pwndbg.gdblib.vmmap.get():\n            if sp in page and bp not in page:\n                print(\n                    \"Cannot display stack frame because base pointer is not on the same page with stack pointer\"\n                )\n                return\n\n        address = sp\n        count = int((bp - sp) / ptrsize) + 1\n\n    # Allow invocation of \"telescope a b\" to dump all bytes from A to B\n    if int(address) <= int(count):\n        # adjust count if it is an address. use ceil division as count is number of\n        # ptrsize values and we don't want to strip out a value if dest is unaligned\n        count -= address\n        count = max(math.ceil(count / ptrsize), 1)\n\n    reg_values = collections.defaultdict(lambda: [])\n    for reg in pwndbg.gdblib.regs.common:\n        reg_values[pwndbg.gdblib.regs[reg]].append(reg)\n\n    start = address\n    stop = address + (count * ptrsize)\n    step = ptrsize\n\n    # Find all registers which show up in the trace\n    regs = {}\n    for i in range(start, stop, step):\n        values = list(reg_values[i])\n\n        for width in range(1, pwndbg.gdblib.arch.ptrsize):\n            values.extend(\"%s-%i\" % (r, width) for r in reg_values[i + width])\n\n        regs[i] = \" \".join(values)\n\n    # Find the longest set of register information\n    if regs:\n        longest_regs = max(map(len, regs.values()))\n    else:\n        longest_regs = 0\n\n    # Print everything out\n    result = []\n    last = None\n    collapse_buffer: list[str] = []\n    skipped_padding = (\n        2\n        + len(offset_delimiter)\n        + 4\n        + len(offset_separator)\n        + 1\n        + longest_regs\n        + 1\n        - len(repeating_marker)\n    )\n\n    # Collapse repeating values exceeding minimum delta.\n    def collapse_repeating_values() -> None:\n        # The first line was already printed, hence increment by 1\n        if collapse_buffer and len(collapse_buffer) + 1 >= skip_repeating_values_minimum:\n            result.append(\n                T.repeating_marker(\n                    \"%s%s%i skipped\"\n                    % (repeating_marker, \" \" * skipped_padding, len(collapse_buffer))\n                )\n            )\n        else:\n            result.extend(collapse_buffer)\n        collapse_buffer.clear()\n\n    for i, addr in enumerate(range(start, stop, step)):\n        if not pwndbg.gdblib.memory.peek(addr):\n            collapse_repeating_values()\n            result.append(\"<Could not read memory at %#x>\" % addr)\n            break\n\n        line = \" \".join(\n            (\n                T.offset(\n                    \"%02x%s%04x%s\"\n                    % (\n                        i + telescope.offset,\n                        delimiter,\n                        addr - start + (telescope.offset * ptrsize),\n                        separator,\n                    )\n                ),\n                T.register(regs[addr].ljust(longest_regs)),\n                pwndbg.chain.format(addr),\n            )\n        )\n\n        # Buffer repeating values.\n        if skip_repeating_values:\n            value = pwndbg.gdblib.memory.pvoid(addr)\n            if last == value and addr != input_address:\n                collapse_buffer.append(line)\n                continue\n            collapse_repeating_values()\n            last = value\n\n        result.append(line)\n\n    collapse_repeating_values()\n    telescope.offset += i\n    telescope.last_address = addr\n\n    if not to_string:\n        print(\"\\n\".join(result))\n\n    return result\n\n\nparser = argparse.ArgumentParser(\n    description=\"Dereferences on stack data with specified count and offset.\"\n)\nparser.add_argument(\"count\", nargs=\"?\", default=8, type=int, help=\"number of element to dump\")\nparser.add_argument(\n    \"offset\",\n    nargs=\"?\",\n    default=0,\n    type=int,\n    help=\"Element offset from $sp (support negative offset)\",\n)\n\n\n@pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.STACK)\n@pwndbg.commands.OnlyWhenRunning\ndef stack(count, offset) -> None:\n    ptrsize = pwndbg.gdblib.typeinfo.ptrsize\n    telescope.repeat = stack.repeat\n    telescope(address=pwndbg.gdblib.regs.sp + offset * ptrsize, count=count)\n\n\ntelescope.last_address = 0\ntelescope.offset = 0\n", "path": "pwndbg/commands/telescope.py"}]}