We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Enabling reverse stack growth
**Is your feature request related to a problem? Please describe.**
In GEF it is possible to visualize the stack growth in reverse (i.e., upper addresses go to higher positions). This is possible by setting up the context.grow_stack_down parameter.

**Describe the solution you'd like**
It would be very nice to have the equivalent functionality in Pwndbg (or if there is already, make it more accessible).

--- 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 from typing import DefaultDict
13 
14 import pwndbg.chain
15 import pwndbg.color.telescope as T
16 import pwndbg.commands
17 import pwndbg.gdblib.arch
18 import pwndbg.gdblib.config
19 import pwndbg.gdblib.memory
20 import pwndbg.gdblib.regs
21 import pwndbg.gdblib.typeinfo
22 from pwndbg.color import theme
23 from pwndbg.commands import CommandCategory
24 
25 telescope_lines = pwndbg.gdblib.config.add_param(
26     "telescope-lines", 8, "number of lines to printed by the telescope command"
27 )
28 skip_repeating_values = pwndbg.gdblib.config.add_param(
29     "telescope-skip-repeating-val",
30     True,
31     "whether to skip repeating values of the telescope command",
32 )
33 skip_repeating_values_minimum = pwndbg.gdblib.config.add_param(
34     "telescope-skip-repeating-val-minimum",
35     3,
36     "minimum amount of repeated values before skipping lines",
37 )
38 print_framepointer_offset = pwndbg.gdblib.config.add_param(
39     "telescope-framepointer-offset",
40     True,
41     "print offset to framepointer for each address, if sufficiently small",
42 )
43 
44 offset_separator = theme.add_param(
45     "telescope-offset-separator", "│", "offset separator of the telescope command"
46 )
47 offset_delimiter = theme.add_param(
48     "telescope-offset-delimiter", ":", "offset delimiter of the telescope command"
49 )
50 repeating_marker = theme.add_param(
51     "telescope-repeating-marker", "... ↓", "repeating values marker of the telescope command"
52 )
53 
54 
55 parser = argparse.ArgumentParser(
56     description="Recursively dereferences pointers starting at the specified address."
57 )
58 parser.add_argument(
59     "-r",
60     "--reverse",
61     dest="reverse",
62     action="store_true",
63     default=False,
64     help="Show <count> previous addresses instead of next ones",
65 )
66 
67 parser.add_argument(
68     "-f",
69     "--frame",
70     dest="frame",
71     action="store_true",
72     default=False,
73     help="Show the stack frame, from rsp to rbp",
74 )
75 
76 parser.add_argument(
77     "address", nargs="?", default="$sp", type=int, help="The address to telescope at."
78 )
79 
80 parser.add_argument(
81     "count", nargs="?", default=telescope_lines, type=int, help="The number of lines to show."
82 )
83 
84 
85 @pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.MEMORY)
86 @pwndbg.commands.OnlyWhenRunning
87 def telescope(address=None, count=telescope_lines, to_string=False, reverse=False, frame=False):
88     """
89     Recursively dereferences pointers starting at the specified address
90     ($sp by default)
91     """
92     ptrsize = pwndbg.gdblib.typeinfo.ptrsize
93     if telescope.repeat:
94         address = telescope.last_address + ptrsize
95         telescope.offset += 1
96     else:
97         telescope.offset = 0
98 
99     address = int(address if address else pwndbg.gdblib.regs.sp) & pwndbg.gdblib.arch.ptrmask
100     input_address = address
101     count = max(int(count), 1) & pwndbg.gdblib.arch.ptrmask
102     delimiter = T.delimiter(offset_delimiter)
103     separator = T.separator(offset_separator)
104 
105     # Allow invocation of "telescope 20" to dump 20 bytes at the stack pointer
106     if address < pwndbg.gdblib.memory.MMAP_MIN_ADDR and not pwndbg.gdblib.memory.peek(address):
107         count = address
108         address = pwndbg.gdblib.regs.sp
109 
110     # Allow invocation of telescope -r to dump previous addresses
111     if reverse:
112         address -= (count - 1) * ptrsize
113 
114     # Allow invocation of telescope -f (--frame) to dump all addresses in a frame
115     if frame:
116         sp = pwndbg.gdblib.regs.sp
117         bp = pwndbg.gdblib.regs[pwndbg.gdblib.regs.frame]
118         if sp > bp:
119             print("Cannot display stack frame because base pointer is below stack pointer")
120             return
121 
122         for page in pwndbg.gdblib.vmmap.get():
123             if sp in page and bp not in page:
124                 print(
125                     "Cannot display stack frame because base pointer is not on the same page with stack pointer"
126                 )
127                 return
128 
129         address = sp
130         count = int((bp - sp) / ptrsize) + 1
131 
132     # Allow invocation of "telescope a b" to dump all bytes from A to B
133     if int(address) <= int(count):
134         # adjust count if it is an address. use ceil division as count is number of
135         # ptrsize values and we don't want to strip out a value if dest is unaligned
136         count -= address
137         count = max(math.ceil(count / ptrsize), 1)
138 
139     # Map of address to register string
140     reg_values: DefaultDict[int, list[str]] = collections.defaultdict(lambda: [])
141     for reg in pwndbg.gdblib.regs.common:
142         reg_values[pwndbg.gdblib.regs[reg]].append(reg)
143 
144     start = address
145     stop = address + (count * ptrsize)
146     step = ptrsize
147 
148     # Find all registers which show up in the trace, map address to regs
149     regs: dict[int, str] = {}
150     for i in range(start, stop, step):
151         values = list(reg_values[i])
152 
153         # Find all regs that point to somewhere in the current ptrsize step
154         for width in range(1, pwndbg.gdblib.arch.ptrsize):
155             values.extend("%s-%i" % (r, width) for r in reg_values[i + width])
156 
157         regs[i] = " ".join(values)
158 
159     # Find the longest set of register information (length of string), used for padding
160     if regs:
161         longest_regs = max(map(len, regs.values()))
162     else:
163         longest_regs = 0
164 
165     # Print everything out
166     result = []
167     last = None
168     collapse_buffer: list[str] = []
169     skipped_padding = (
170         2
171         + len(offset_delimiter)
172         + 4
173         + len(offset_separator)
174         + 1
175         + longest_regs
176         + 1
177         - len(repeating_marker)
178     )
179 
180     # Collapse repeating values exceeding minimum delta.
181     def collapse_repeating_values() -> None:
182         # The first line was already printed, hence increment by 1
183         if collapse_buffer and len(collapse_buffer) + 1 >= skip_repeating_values_minimum:
184             result.append(
185                 T.repeating_marker(
186                     "%s%s%i skipped"
187                     % (repeating_marker, " " * skipped_padding, len(collapse_buffer))
188                 )
189             )
190         else:
191             result.extend(collapse_buffer)
192         collapse_buffer.clear()
193 
194     bp = None
195     if print_framepointer_offset and pwndbg.gdblib.regs.frame is not None:
196         # regs.frame can be None on aarch64
197         bp = pwndbg.gdblib.regs[pwndbg.gdblib.regs.frame]
198 
199     for i, addr in enumerate(range(start, stop, step)):
200         if not pwndbg.gdblib.memory.peek(addr):
201             collapse_repeating_values()
202             result.append("<Could not read memory at %#x>" % addr)
203             break
204 
205         line = T.offset(
206             "%02x%s%04x%s"
207             % (
208                 i + telescope.offset,
209                 delimiter,
210                 addr - start + (telescope.offset * ptrsize),
211                 separator,
212             )
213         ) + " ".join(
214             (
215                 regs_or_frame_offset(addr, bp, regs, longest_regs),
216                 pwndbg.chain.format(addr),
217             )
218         )
219 
220         # Buffer repeating values.
221         if skip_repeating_values:
222             value = pwndbg.gdblib.memory.pvoid(addr)
223             if last == value and addr != input_address:
224                 collapse_buffer.append(line)
225                 continue
226             collapse_repeating_values()
227             last = value
228 
229         result.append(line)
230 
231     collapse_repeating_values()
232     telescope.offset += i
233     telescope.last_address = addr
234 
235     if not to_string:
236         print("\n".join(result))
237 
238     return result
239 
240 
241 def regs_or_frame_offset(addr: int, bp: int | None, regs: dict[int, str], longest_regs: int) -> str:
242     # bp only set if print_framepointer_offset=True
243     # len(regs[addr]) == 1 if no registers pointer to address
244     if bp is None or len(regs[addr]) > 1 or not -0xFFF <= addr - bp <= 0xFFF:
245         return " " + T.register(regs[addr].ljust(longest_regs))
246     else:
247         # If offset to frame pointer as hex fits in hex 3 digits, print it
248         return ("%+04x" % (addr - bp)).ljust(longest_regs + 1)
249 
250 
251 parser = argparse.ArgumentParser(
252     description="Dereferences on stack data with specified count and offset."
253 )
254 parser.add_argument(
255     "-f",
256     "--frame",
257     dest="frame",
258     action="store_true",
259     default=False,
260     help="Show the stack frame, from rsp to rbp",
261 )
262 parser.add_argument("count", nargs="?", default=8, type=int, help="number of element to dump")
263 parser.add_argument(
264     "offset",
265     nargs="?",
266     default=0,
267     type=int,
268     help="Element offset from $sp (support negative offset)",
269 )
270 
271 
272 @pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.STACK)
273 @pwndbg.commands.OnlyWhenRunning
274 def stack(count, offset, frame) -> None:
275     ptrsize = pwndbg.gdblib.typeinfo.ptrsize
276     telescope.repeat = stack.repeat
277     telescope(address=pwndbg.gdblib.regs.sp + offset * ptrsize, count=count, frame=frame)
278 
279 
280 parser = argparse.ArgumentParser(
281     description="Dereferences on stack data, printing the entire stack frame with specified count and offset ."
282 )
283 parser.add_argument("count", nargs="?", default=8, type=int, help="number of element to dump")
284 parser.add_argument(
285     "offset",
286     nargs="?",
287     default=0,
288     type=int,
289     help="Element offset from $sp (support negative offset)",
290 )
291 
292 
293 @pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.STACK)
294 @pwndbg.commands.OnlyWhenRunning
295 def stackf(count, offset) -> None:
296     ptrsize = pwndbg.gdblib.typeinfo.ptrsize
297     telescope.repeat = stack.repeat
298     telescope(address=pwndbg.gdblib.regs.sp + offset * ptrsize, count=count, frame=True)
299 
300 
301 telescope.last_address = 0
302 telescope.offset = 0
303
```
--- 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
@@ -73,6 +73,16 @@
     help="Show the stack frame, from rsp to rbp",
 )
 
+parser.add_argument(
+    "-i",
+    "--inverse",
+    dest="inverse",
+    action="store_true",
+    default=False,
+    help="Show the stack reverse growth",
+)
+
+
 parser.add_argument(
     "address", nargs="?", default="$sp", type=int, help="The address to telescope at."
 )
@@ -84,7 +94,9 @@
 
 @pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.MEMORY)
 @pwndbg.commands.OnlyWhenRunning
-def telescope(address=None, count=telescope_lines, to_string=False, reverse=False, frame=False):
+def telescope(
+    address=None, count=telescope_lines, to_string=False, reverse=False, frame=False, inverse=False
+):
     """
     Recursively dereferences pointers starting at the specified address
     ($sp by default)
@@ -141,9 +153,14 @@
     for reg in pwndbg.gdblib.regs.common:
         reg_values[pwndbg.gdblib.regs[reg]].append(reg)
 
-    start = address
-    stop = address + (count * ptrsize)
-    step = ptrsize
+    if not inverse:
+        start = address
+        stop = address + (count * ptrsize)
+        step = ptrsize
+    else:
+        start = address + ((count - 1) * ptrsize)
+        stop = address - ptrsize
+        step = -1 * ptrsize
 
     # Find all registers which show up in the trace, map address to regs
     regs: dict[int, str] = {}
@@ -201,13 +218,18 @@
             collapse_repeating_values()
             result.append("<Could not read memory at %#x>" % addr)
             break
-
+        if inverse:
+            line_offset = addr - (stop + ptrsize) + (telescope.offset * ptrsize)
+            idx_offset = int((start - stop - ptrsize) / ptrsize) - (i + telescope.offset)
+        else:
+            line_offset = addr - start + (telescope.offset * ptrsize)
+            idx_offset = i + telescope.offset
         line = T.offset(
             "%02x%s%04x%s"
             % (
-                i + telescope.offset,
+                idx_offset,
                 delimiter,
-                addr - start + (telescope.offset * ptrsize),
+                line_offset,
                 separator,
             )
         ) + " ".join(
@@ -259,6 +281,16 @@
     default=False,
     help="Show the stack frame, from rsp to rbp",
 )
+
+parser.add_argument(
+    "-i",
+    "--inverse",
+    dest="inverse",
+    action="store_true",
+    default=False,
+    help="Show reverse stack growth",
+)
+
 parser.add_argument("count", nargs="?", default=8, type=int, help="number of element to dump")
 parser.add_argument(
     "offset",
@@ -271,10 +303,12 @@
 
 @pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.STACK)
 @pwndbg.commands.OnlyWhenRunning
-def stack(count, offset, frame) -> None:
+def stack(count, offset, frame, inverse) -> None:
     ptrsize = pwndbg.gdblib.typeinfo.ptrsize
     telescope.repeat = stack.repeat
-    telescope(address=pwndbg.gdblib.regs.sp + offset * ptrsize, count=count, frame=frame)
+    telescope(
+        address=pwndbg.gdblib.regs.sp + offset * ptrsize, count=count, frame=frame, inverse=inverse
+    )
 
 
 parser = argparse.ArgumentParser(

{"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@@ -73,6 +73,16 @@\n     help=\"Show the stack frame, from rsp to rbp\",\n )\n \n+parser.add_argument(\n+    \"-i\",\n+    \"--inverse\",\n+    dest=\"inverse\",\n+    action=\"store_true\",\n+    default=False,\n+    help=\"Show the stack reverse growth\",\n+)\n+\n+\n parser.add_argument(\n     \"address\", nargs=\"?\", default=\"$sp\", type=int, help=\"The address to telescope at.\"\n )\n@@ -84,7 +94,9 @@\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, frame=False):\n+def telescope(\n+    address=None, count=telescope_lines, to_string=False, reverse=False, frame=False, inverse=False\n+):\n     \"\"\"\n     Recursively dereferences pointers starting at the specified address\n     ($sp by default)\n@@ -141,9 +153,14 @@\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+    if not inverse:\n+        start = address\n+        stop = address + (count * ptrsize)\n+        step = ptrsize\n+    else:\n+        start = address + ((count - 1) * ptrsize)\n+        stop = address - ptrsize\n+        step = -1 * ptrsize\n \n     # Find all registers which show up in the trace, map address to regs\n     regs: dict[int, str] = {}\n@@ -201,13 +218,18 @@\n             collapse_repeating_values()\n             result.append(\"<Could not read memory at %#x>\" % addr)\n             break\n-\n+        if inverse:\n+            line_offset = addr - (stop + ptrsize) + (telescope.offset * ptrsize)\n+            idx_offset = int((start - stop - ptrsize) / ptrsize) - (i + telescope.offset)\n+        else:\n+            line_offset = addr - start + (telescope.offset * ptrsize)\n+            idx_offset = i + telescope.offset\n         line = T.offset(\n             \"%02x%s%04x%s\"\n             % (\n-                i + telescope.offset,\n+                idx_offset,\n                 delimiter,\n-                addr - start + (telescope.offset * ptrsize),\n+                line_offset,\n                 separator,\n             )\n         ) + \" \".join(\n@@ -259,6 +281,16 @@\n     default=False,\n     help=\"Show the stack frame, from rsp to rbp\",\n )\n+\n+parser.add_argument(\n+    \"-i\",\n+    \"--inverse\",\n+    dest=\"inverse\",\n+    action=\"store_true\",\n+    default=False,\n+    help=\"Show reverse stack growth\",\n+)\n+\n parser.add_argument(\"count\", nargs=\"?\", default=8, type=int, help=\"number of element to dump\")\n parser.add_argument(\n     \"offset\",\n@@ -271,10 +303,12 @@\n \n @pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.STACK)\n @pwndbg.commands.OnlyWhenRunning\n-def stack(count, offset, frame) -> None:\n+def stack(count, offset, frame, inverse) -> None:\n     ptrsize = pwndbg.gdblib.typeinfo.ptrsize\n     telescope.repeat = stack.repeat\n-    telescope(address=pwndbg.gdblib.regs.sp + offset * ptrsize, count=count, frame=frame)\n+    telescope(\n+        address=pwndbg.gdblib.regs.sp + offset * ptrsize, count=count, frame=frame, inverse=inverse\n+    )\n \n \n parser = argparse.ArgumentParser(\n", "issue": "Enabling reverse stack growth\n**Is your feature request related to a problem? Please describe.**\r\nIn GEF it is possible to visualize the stack growth in reverse (i.e., upper addresses go to higher positions). This is possible by setting up the context.grow_stack_down parameter.\r\n\r\n**Describe the solution you'd like**\r\nIt would be very nice to have the equivalent functionality in Pwndbg (or if there is already, make it more accessible).\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\nfrom typing import DefaultDict\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)\nprint_framepointer_offset = pwndbg.gdblib.config.add_param(\n    \"telescope-framepointer-offset\",\n    True,\n    \"print offset to framepointer for each address, if sufficiently small\",\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 all addresses in a frame\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    # Map of address to register string\n    reg_values: DefaultDict[int, list[str]] = 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, map address to regs\n    regs: dict[int, str] = {}\n    for i in range(start, stop, step):\n        values = list(reg_values[i])\n\n        # Find all regs that point to somewhere in the current ptrsize step\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 (length of string), used for padding\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    bp = None\n    if print_framepointer_offset and pwndbg.gdblib.regs.frame is not None:\n        # regs.frame can be None on aarch64\n        bp = pwndbg.gdblib.regs[pwndbg.gdblib.regs.frame]\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 = T.offset(\n            \"%02x%s%04x%s\"\n            % (\n                i + telescope.offset,\n                delimiter,\n                addr - start + (telescope.offset * ptrsize),\n                separator,\n            )\n        ) + \" \".join(\n            (\n                regs_or_frame_offset(addr, bp, regs, 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\ndef regs_or_frame_offset(addr: int, bp: int | None, regs: dict[int, str], longest_regs: int) -> str:\n    # bp only set if print_framepointer_offset=True\n    # len(regs[addr]) == 1 if no registers pointer to address\n    if bp is None or len(regs[addr]) > 1 or not -0xFFF <= addr - bp <= 0xFFF:\n        return \" \" + T.register(regs[addr].ljust(longest_regs))\n    else:\n        # If offset to frame pointer as hex fits in hex 3 digits, print it\n        return (\"%+04x\" % (addr - bp)).ljust(longest_regs + 1)\n\n\nparser = argparse.ArgumentParser(\n    description=\"Dereferences on stack data with specified count and offset.\"\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)\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, frame) -> None:\n    ptrsize = pwndbg.gdblib.typeinfo.ptrsize\n    telescope.repeat = stack.repeat\n    telescope(address=pwndbg.gdblib.regs.sp + offset * ptrsize, count=count, frame=frame)\n\n\nparser = argparse.ArgumentParser(\n    description=\"Dereferences on stack data, printing the entire stack frame 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 stackf(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, frame=True)\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\nfrom typing import DefaultDict\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)\nprint_framepointer_offset = pwndbg.gdblib.config.add_param(\n    \"telescope-framepointer-offset\",\n    True,\n    \"print offset to framepointer for each address, if sufficiently small\",\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    \"-i\",\n    \"--inverse\",\n    dest=\"inverse\",\n    action=\"store_true\",\n    default=False,\n    help=\"Show the stack reverse growth\",\n)\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(\n    address=None, count=telescope_lines, to_string=False, reverse=False, frame=False, inverse=False\n):\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 all addresses in a frame\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    # Map of address to register string\n    reg_values: DefaultDict[int, list[str]] = collections.defaultdict(lambda: [])\n    for reg in pwndbg.gdblib.regs.common:\n        reg_values[pwndbg.gdblib.regs[reg]].append(reg)\n\n    if not inverse:\n        start = address\n        stop = address + (count * ptrsize)\n        step = ptrsize\n    else:\n        start = address + ((count - 1) * ptrsize)\n        stop = address - ptrsize\n        step = -1 * ptrsize\n\n    # Find all registers which show up in the trace, map address to regs\n    regs: dict[int, str] = {}\n    for i in range(start, stop, step):\n        values = list(reg_values[i])\n\n        # Find all regs that point to somewhere in the current ptrsize step\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 (length of string), used for padding\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    bp = None\n    if print_framepointer_offset and pwndbg.gdblib.regs.frame is not None:\n        # regs.frame can be None on aarch64\n        bp = pwndbg.gdblib.regs[pwndbg.gdblib.regs.frame]\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        if inverse:\n            line_offset = addr - (stop + ptrsize) + (telescope.offset * ptrsize)\n            idx_offset = int((start - stop - ptrsize) / ptrsize) - (i + telescope.offset)\n        else:\n            line_offset = addr - start + (telescope.offset * ptrsize)\n            idx_offset = i + telescope.offset\n        line = T.offset(\n            \"%02x%s%04x%s\"\n            % (\n                idx_offset,\n                delimiter,\n                line_offset,\n                separator,\n            )\n        ) + \" \".join(\n            (\n                regs_or_frame_offset(addr, bp, regs, 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\ndef regs_or_frame_offset(addr: int, bp: int | None, regs: dict[int, str], longest_regs: int) -> str:\n    # bp only set if print_framepointer_offset=True\n    # len(regs[addr]) == 1 if no registers pointer to address\n    if bp is None or len(regs[addr]) > 1 or not -0xFFF <= addr - bp <= 0xFFF:\n        return \" \" + T.register(regs[addr].ljust(longest_regs))\n    else:\n        # If offset to frame pointer as hex fits in hex 3 digits, print it\n        return (\"%+04x\" % (addr - bp)).ljust(longest_regs + 1)\n\n\nparser = argparse.ArgumentParser(\n    description=\"Dereferences on stack data with specified count and offset.\"\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    \"-i\",\n    \"--inverse\",\n    dest=\"inverse\",\n    action=\"store_true\",\n    default=False,\n    help=\"Show reverse stack growth\",\n)\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, frame, inverse) -> None:\n    ptrsize = pwndbg.gdblib.typeinfo.ptrsize\n    telescope.repeat = stack.repeat\n    telescope(\n        address=pwndbg.gdblib.regs.sp + offset * ptrsize, count=count, frame=frame, inverse=inverse\n    )\n\n\nparser = argparse.ArgumentParser(\n    description=\"Dereferences on stack data, printing the entire stack frame 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 stackf(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, frame=True)\n\n\ntelescope.last_address = 0\ntelescope.offset = 0\n", "path": "pwndbg/commands/telescope.py"}]}