Repository: pwndbg/pwndbg

Issue:
gsbase  command  ValueError: Unknown register.
<!--
Before reporting a new issue, make sure that we do not have any duplicates already open.
If there is one it might be good to take part in the discussion there.

Please make sure you have checked that the issue persists on LATEST pwndbg version.

Below is a template for BUG REPORTS.
Don't include it if this is a FEATURE REQUEST.
-->


### Description

<!--
Briefly describe the problem you are having in a few paragraphs.
-->



### Steps to reproduce

<!--
What do we have to do to reproduce the problem?
If this is connected to particular C/asm code or a binary,
please provide the binary or if possible, a smallest C code that reproduces the issue.
-->

I was following class videos on using pwndbg to look for stack canary values.  Compile the following sample crackme with

`gcc -m32 -g -O0 -mpreferred-stack-boundary=2 -fstack-protector -o  crackme0x00-ssp-exec -z execstack  crackme0x00.c`

```
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[])
{
  setreuid(geteuid(), geteuid());
  char buf[16];
  printf("IOLI Crackme Level 0x00\n");
  printf("Password:");

  scanf("%s", buf);

  if (!strcmp(buf, "20020"))
    printf("Password OK :)\n");
  else
    printf("Invalid Password!\n");

  return 0;
}
```

Open file with pwndbg 

```
$ gdb-pwndbg crackme0x00-ssp-exec
```

With pwndbg set a breakpoint and run the file as follows

```
pwndbg> break *main+25
pwndbg> r
```

Type the `gsbase` command after

```
pwndbg> gsbase

```

Notice the ValueError: Unknown register error.


Gdb session history:
```
break *main+25
r
gsbase
set exception-verbose on
gsbase
bugreport
```

### My setup

<!--
Show us your gdb/python/pwndbg/OS/IDA Pro version (depending on your case).

NOTE: We are currently testing Pwndbg only on Ubuntu installations but it should work fine on other distros as well.

This can be displayed in pwndbg through `version` command.

If it is somehow unavailable, use:
* `show version` - for gdb
* `py import sys; print(sys.version)` - for python
* pwndbg version/git commit id
-->

```
Platform: Linux-5.4.0-1068-aws-x86_64-with-Ubuntu-18.04-bionic
Gdb:      8.1.1
Python:   3.6.9 (default, Nov 25 2022, 14:10:45)  [GCC 8.4.0]
Pwndbg:   1.1.1 build: ca33d16
Capstone: 4.0.1024
Unicorn:  2.0.7
This GDB was configured as follows:
   configure --host=x86_64-linux-gnu --target=x86_64-linux-gnu
             --with-auto-load-dir=$debugdir:$datadir/auto-load
             --with-auto-load-safe-path=$debugdir:$datadir/auto-load
             --with-expat
             --with-gdb-datadir=/usr/share/gdb (relocatable)
             --with-jit-reader-dir=/usr/lib/gdb (relocatable)
             --without-libunwind-ia64
             --with-lzma
             --with-python=/usr (relocatable)
             --without-guile
             --with-separate-debug-dir=/usr/lib/debug (relocatable)
             --with-system-gdbinit=/etc/gdb/gdbinit
             --with-babeltrace

("Relocatable" means the directory can be moved with the GDB installation
tree, and GDB will still find it.)

```

### Traceback
```
pwndbg> gsbase
Traceback (most recent call last):
  File "/usr/pwndbg/pwndbg/commands/__init__.py", line 184, in __call__
    return self.function(*args, **kwargs)
  File "/usr/pwndbg/pwndbg/commands/__init__.py", line 315, in _OnlyWhenRunning
    return function(*a, **kw)
  File "/usr/pwndbg/pwndbg/commands/segments.py", line 43, in gsbase
    print(hex(int(pwndbg.gdblib.regs.gsbase)))
  File "/usr/pwndbg/pwndbg/lib/memoize.py", line 57, in __call__
    value = self.func(*args, **kwargs)
  File "/usr/pwndbg/pwndbg/gdblib/regs.py", line 188, in gsbase
    return self._fs_gs_helper("gs_base", ARCH_GET_GS)
  File "/usr/pwndbg/pwndbg/lib/memoize.py", line 57, in __call__
    value = self.func(*args, **kwargs)
  File "/usr/pwndbg/pwndbg/gdblib/regs.py", line 198, in _fs_gs_helper
    return get_register(regname)
  File "/usr/pwndbg/pwndbg/gdblib/proc.py", line 92, in wrapper
    return func(*a, **kw)
  File "/usr/pwndbg/pwndbg/gdblib/regs.py", line 29, in gdb79_get_register
    return gdb.selected_frame().read_register(name)
ValueError: Unknown register.
```

If I go all the way back to this commit `b203d53b8a01c016dc5536854320ca39b81a92b1`  the same command works.


```
Gdb session history:
break *main+25
r
gsbase

pwndbg> gsbase
0xf7fd10c0
pwndbg>
```

I also tried with the latest(as at bug report) release tag commit hash `git checkout 894f6e2103d69777a944c544d203d28559331057`  and it also fails

```
pwndbg> gsbase
Traceback (most recent call last):
  File "/usr/pwndbg/pwndbg/commands/__init__.py", line 147, in __call__
    return self.function(*args, **kwargs)
  File "/usr/pwndbg/pwndbg/commands/__init__.py", line 266, in _OnlyWhenRunning
    return function(*a, **kw)
  File "/usr/pwndbg/pwndbg/commands/segments.py", line 38, in gsbase
    print(hex(int(pwndbg.gdblib.regs.gsbase)))
  File "/usr/pwndbg/pwndbg/lib/memoize.py", line 45, in __call__
    value = self.func(*args, **kwargs)
  File "/usr/pwndbg/pwndbg/gdblib/regs.py", line 184, in gsbase
    return self._fs_gs_helper("gs_base", ARCH_GET_GS)
  File "/usr/pwndbg/pwndbg/lib/memoize.py", line 45, in __call__
    value = self.func(*args, **kwargs)
  File "/usr/pwndbg/pwndbg/gdblib/regs.py", line 194, in _fs_gs_helper
    return get_register(regname)
  File "/usr/pwndbg/pwndbg/gdblib/proc.py", line 92, in wrapper
    return func(*a, **kw)
  File "/usr/pwndbg/pwndbg/gdblib/regs.py", line 28, in gdb79_get_register
    return gdb.selected_frame().read_register(name)
ValueError: Unknown register.

If that is an issue, you can report it on https://github.com/pwndbg/pwndbg/issues
(Please don't forget to search if it hasn't been reported before)
To generate the report and open a browser, you may run `bugreport --run-browser`
PS: Pull requests are welcome
> /usr/pwndbg/pwndbg/gdblib/regs.py(28)gdb79_get_register()
-> return gdb.selected_frame().read_register(name)
(Pdb)
```






Discussion:
> If I go all the way back to this commit b203d53b8a01c016dc5536854320ca39b81a92b1 the same command works.

So which commit did break this? ;)
> So which commit did break this? ;)

Total of 490 commits between that a current dev HEAD and last known good. I would have loved to narrow it down a bit more, unfortunately I can't right now 😢 

<<part edited by Disconnect3d to remove 490 lines with commit ids :P>>
> Total of 490 commits between that a current dev HEAD and last known good. I would have loved to narrow it down a bit more, unfortunately I can't right now 😢

This can be automated with some `git bisect` magic; I'll do that. Thanks for reporting this.

Resolving patch:
diff --git a/pwndbg/commands/segments.py b/pwndbg/commands/segments.py
--- a/pwndbg/commands/segments.py
+++ b/pwndbg/commands/segments.py
@@ -17,6 +17,7 @@ def invoke(self, arg=0):
         return result + arg
 
 
+# TODO/FIXME: This should be defined only for x86 and x86_64
 segment("fsbase")
 segment("gsbase")
 
@@ -25,6 +26,7 @@ def invoke(self, arg=0):
     "Prints out the FS base address. See also $fsbase.", category=CommandCategory.REGISTER
 )
 @pwndbg.commands.OnlyWhenRunning
+@pwndbg.commands.OnlyWithArch(["i386", "x86-64"])
 def fsbase() -> None:
     """
     Prints out the FS base address. See also $fsbase.
@@ -36,6 +38,7 @@ def fsbase() -> None:
     "Prints out the GS base address. See also $gsbase.", category=CommandCategory.REGISTER
 )
 @pwndbg.commands.OnlyWhenRunning
+@pwndbg.commands.OnlyWithArch(["i386", "x86-64"])
 def gsbase() -> None:
     """
     Prints out the GS base address. See also $gsbase.
diff --git a/pwndbg/gdblib/regs.py b/pwndbg/gdblib/regs.py
--- a/pwndbg/gdblib/regs.py
+++ b/pwndbg/gdblib/regs.py
@@ -194,7 +194,7 @@ def _fs_gs_helper(self, regname, which):
 
         # For GDB >= 8.x we can use get_register directly
         # Elsewhere we have to get the register via ptrace
-        if get_register == gdb79_get_register:
+        if pwndbg.gdblib.arch.current == "x86-64" and get_register == gdb79_get_register:
             return get_register(regname)
 
         # We can't really do anything if the process is remote.


Test patch: