Repository: pwndbg/pwndbg

Issue:
`telescope -r` should always display the input address
`telescope -r addr` will skip displaying `addr` if the value at that address is equal to the previous few values:
```
pwndbg> p &target_address
$1 = (unsigned long *) 0x5555555582a0 <target_address>
pwndbg> telescope -r &target_address
00:0000│     0x555555558208 (buf+360) ◂— 0x0
... ↓        4 skipped
05:0028│ rax 0x555555558230 (buf+400) ◂— 0x80
06:0030│     0x555555558238 (buf+408) ◂— 0x0
... ↓        13 skipped
```
We should make this command always display the address that the user asked for:
```
pwndbg> telescope -r &target_address
00:0000│     0x555555558208 (buf+360) ◂— 0x0
... ↓        4 skipped
05:0028│ rax 0x555555558230 (buf+400) ◂— 0x80
06:0030│     0x555555558238 (buf+408) ◂— 0x0
... ↓        12 skipped
13:0098│     0x5555555582a0 (target_address) ◂— 0x0
```


Discussion:
I found that telescope behaves strangely if `set history remove-duplicates unlimited`.

The `check_repeated` depends on the history of gdb. 
https://github.com/pwndbg/pwndbg/blob/e456b317d7d9c3767ebf45b907d31178c3418d3e/pwndbg/commands/__init__.py#L113-L148

If `remove-duplicates` is set, the `check_repeated` is not working normally. That's what I mentioned in https://github.com/pwndbg/pwndbg/issues/1072#issuecomment-1274925956

I can't find another way to implement the `check_repeated`. I'm removing the `set history remove-duplicates unlimited` from my `~/.gdbinit`.

Resolving patch:
diff --git a/pwndbg/commands/telescope.py b/pwndbg/commands/telescope.py
--- a/pwndbg/commands/telescope.py
+++ b/pwndbg/commands/telescope.py
@@ -81,6 +81,7 @@ def telescope(address=None, count=telescope_lines, to_string=False, reverse=Fals
         telescope.offset = 0
 
     address = int(address if address else pwndbg.gdblib.regs.sp) & pwndbg.gdblib.arch.ptrmask
+    input_address = address
     count = max(int(count), 1) & pwndbg.gdblib.arch.ptrmask
     delimiter = T.delimiter(offset_delimiter)
     separator = T.separator(offset_separator)
@@ -179,7 +180,7 @@ def collapse_repeating_values() -> None:
         # Buffer repeating values.
         if skip_repeating_values:
             value = pwndbg.gdblib.memory.pvoid(addr)
-            if last == value:
+            if last == value and addr != input_address:
                 collapse_buffer.append(line)
                 continue
             collapse_repeating_values()


Test patch:
diff --git a/tests/gdb-tests/tests/test_command_telescope.py b/tests/gdb-tests/tests/test_command_telescope.py
--- a/tests/gdb-tests/tests/test_command_telescope.py
+++ b/tests/gdb-tests/tests/test_command_telescope.py
@@ -82,3 +82,21 @@ def test_telescope_command_with_address_as_count_and_reversed_flag(start_binary)
     rsp = pwndbg.gdblib.regs.rsp
 
     assert out == ["00:0000│     %#x ◂— 0x0" % (rsp - 8), "01:0008│ rsp %#x ◂— 0x1" % rsp]
+
+
+def test_command_telescope_reverse_skipped_records_shows_input_address(start_binary):
+    """
+    Tests reversed telescope with skipped records shows input address
+    """
+    start_binary(TELESCOPE_BINARY)
+
+    gdb.execute("break break_here")
+    gdb.execute("run")
+    gdb.execute("up")
+    pwndbg.gdblib.memory.write(pwndbg.gdblib.regs.rsp - 8 * 3, b"\x00" * 8 * 4)
+
+    expected_value = hex(pwndbg.gdblib.regs.rsp)
+    result_str = gdb.execute("telescope -r $rsp", to_string=True)
+    result_lines = result_str.strip("\n").split("\n")
+
+    assert expected_value in result_lines[-1]