Repository: pwndbg/pwndbg

Issue:
Wrong context regs display on [remote?] targets that use multiple threads
### Description

While I was debugging a 32-bit process on an ARM Android device, I sometimes noticed that atleast one of the register addresses in pwndbg view is wrong.
This has happened several times for different registers.

Examples (happened in two different debugging sessions):
```
pwndbg> regs r0
 R0   0xee69a868 —▸ 0xee460a00 ◂— 0x0
pwndbg> i r r0
r0             0xee4335c8       3997382088

pwndbg> i r sp
sp             0xf136d698       0xf136d698
pwndbg> regs sp
*SP   0xf007a820 —▸ 0xf007a834 ◂— 0xffffffff
```

It happened to me again today while debugging so I tried to ask about this in the IRC channel before opening an issue and when trying to debug the problem, one guy said that this problem is somehow similar with [Issue 460](https://github.com/pwndbg/pwndbg/issues/460) and asked me if I could try the things mentioned there.

After trying to disable caching with:
```
pwndbg> python import pwndbg; pwndbg.memoize.memoize.caching = False
```

The pwndbg registers view got immediately updated with the correct addresses for the registers.
Unfortunately, disabling caching make pwndbg really slow.


### Steps to reproduce

I don't have any consistent way to reproduce the issue as it's not always happening and not easy to notice.

### My setup

pwndbg> version
Gdb:      8.1
Python:   3.6.5 (default, May 11 2018, 04:00:52)  [GCC 8.1.0]
Pwndbg:   1.0.0 build: 71d29df
Capstone: 4.0.1024
Unicorn:  1.0.1


Discussion:
@hencohen This is a remote-debugging session, isn't it?
Does it happen only if the app has multiple thread?

@disconnect3d that's correct, It is a remote-debugging session.
I can't be sure as it's hard to notice when this happens but when it happened to me I indeed was debugging a multi-threaded process
I will try to reproduce it using the example provided by @bruce30262 at https://github.com/pwndbg/pwndbg/issues/460#issuecomment-387954695 using qemu-aarch64.

If someone wants to help with this:
* you need a gdb that supports targeting aarch64 arch (see `set arch <tab>` to check which archs does ur gdb support) - one can install `gdb-multiarch` package on Ubuntu or build such gdb from source using `--enable-targets=all` - more or less instructions for that can be found here: https://gist.github.com/disconnect3d/0126b56b7e8f15ef06d1a50a1c52dd6f
* compile the binary using cross-compilation with proper gdb, on ubuntu 18+ it is sth like `aarch64-linux-gnu-gcc -o bin main.c -lpthread`
* install/use qemu to spawn gdbserver with the binary: `qemu-aarch64 -g 4444 -L /usr/aarch64-linux-gnu ./bin`
* in gdb use `target remote localhost:4444`
TLDR: I have debugged it a bit and I think I found the issue. I also found two other issues (see point 0) which I will address later on. I am going to push the fix to `dev`. @hencohen please check whether it works for you or not.

---

0. To debug this binary compiled for qemu, one need to comment out those two lines: https://github.com/pwndbg/pwndbg/blob/dev/pwndbg/vmmap.py#L153-L154 - otherwise we are missing the memory page for code and so thinks don't work correctly. This is another bug and I am not sure if this is the best solution as some of the memory pages seems to be not accessible by the binary (I guess its qemu process blocking from accessing its memory?). At my machine the binary was compiled with PIE so I had to make breakpoints using `breakrva <address>`. This revealed another bug with `breakrva` as it doesn't accept gdb names like `breakrva main` - we will have to fix this too.

1. The bug can be spotted by `breakrva <addres of thr_func1>` then continuing to this place. `i r sp` vs `context regs` will show diferent sp value.

2. Recently fix for this issue made by us - adding a `before_prompt` hook here https://github.com/pwndbg/pwndbg/blob/dev/pwndbg/regs.py#L269-L285 seems to be not enough because in context code we use the `pwndbg.regs.last` cache which is updated here: https://github.com/pwndbg/pwndbg/blob/dev/pwndbg/regs.py#L425-L430. It seems that this is not called when needed.

3. By decorating `update_last` so that it is fired also on `stop` events:
```python
@pwndbg.events.cont
@pwndbg.events.stop
def update_last():
```
the problem gets fixed and regs display seems good. The question left is: is this enough? Should we also fire this on `before_prompt` event? Maybe. Maybe not. If we add `before_prompt` here pwndbg will throw errors when gdb is launched as `before_prompt` will be fired and `update_last` will fail if binary is not running.


Resolving patch:
diff --git a/pwndbg/regs.py b/pwndbg/regs.py
--- a/pwndbg/regs.py
+++ b/pwndbg/regs.py
@@ -423,6 +423,7 @@ def __repr__(self):
 
 
 @pwndbg.events.cont
+@pwndbg.events.stop
 def update_last():
     M = sys.modules[__name__]
     M.last = {k:M[k] for k in M.common}


Test patch: