Repository: pwndbg/pwndbg

Issue:
Don't hard code a native register sized type as being called "int"
https://github.com/pwndbg/pwndbg/blob/fbd2bb3abfc2500aae76d159e23015008e879b8d/pwndbg/arguments.py#L155

This is only true for languages in the C family.


Discussion:
Do you know a better way to determine this?
1. You could search the current compilation unit for a type of the right size
2. Why is it actually necessary for the debuginfo to contain such a type. Why not just create it yourself, or avoid it's use.
> You could search the current compilation unit for a type of the right size

Which GDB command or API calls can we use for that?

> Why is it actually necessary for the debuginfo to contain such a type. Why not just create it yourself, or avoid it's use.

Same as above. The GDB API doesn't allow to create our own instances of the `gdb.Type` objects. That's sad but we have to live with it for now, until ofc someone wants to go ahead and add it there.

This is also problematic here: https://github.com/pwndbg/pwndbg/blob/fbd2bb3abfc2500aae76d159e23015008e879b8d/pwndbg/typeinfo.py#L51-L70 - we fetch types via names, wishfully thinking they exist...
And those types may vary depending on the debugging symbols of the binary and on the `language` parameter (see `show language` or `set language <lang>` in GDB).

Also: is the line you specified used for referencing the argument via its type? I mean, why this issue? Does it introduce some bugs here and there, depending on the architecture etc?

I think we can't reliably detect the type & ABI of a given function unless we e.g. inspect how a given call is made and what the function does in its beginning - and even if we do it - this will most likely not be fully accurate. 
> The GDB API doesn't allow to create our own instances of the gdb.Type objects.

Ok, I understand.

> Also: is the line you specified used for referencing the argument via its type? I mean, why this issue? Does it introduce some bugs here and there, depending on the architecture etc?

I tried to find the reason the call arguments in the disassembly showed only register names and not the names defined in the debuginfo.

```
► 0x5555555578b6 <main+85>     call   mini_core_hello_world::start <0x5555555553e9>         
        rdi: 0x555555555849 (mini_core_hello_world::main) ◂— push   rbp                      
        rsi: 0x1
        rdx: 0x7fffffffdf88 —▸ 0x7fffffffe2dd ◂— '/home/bjorn/Documenten/cg_clif/target/out/mi
        rcx: 0x0
```

While looking at the source code I found this hard coded `int`. I only later noticed that there is a hard coded list of function argument names in the source code, rather than reading it from the debuginfo `DW_TAG_formal_parameter`.
Ah, yes. I think it would be nice to have a mode where we read it from the debuginfo. I am not sure if GDB API gives that right away though :'(.
It looks like this can be determined dynamically, but we'll still have to do mapping to e.g. `long` or `int` as necessary:


```py
>>> gdb.selected_frame().read_register('rax').type.sizeof
8
>>> gdb.selected_frame().read_register('eax').type.sizeof
4
```

And for GDB prior to 7.9

```
>>> gdb.parse_and_eval('$rax').type.sizeof
8
```

Resolving patch:
diff --git a/pwndbg/regs.py b/pwndbg/regs.py
--- a/pwndbg/regs.py
+++ b/pwndbg/regs.py
@@ -293,7 +293,8 @@ def __getattr__(self, attr):
                 if attr.lower() == 'xpsr':
                     attr = 'xPSR'
                 value = get_register(attr)
-                value = value.cast(pwndbg.typeinfo.ptrdiff)
+                size = pwndbg.typeinfo.unsigned.get(value.type.sizeof, pwndbg.typeinfo.ulong)
+                value = value.cast(size)
 
             value = int(value)
             return value & pwndbg.arch.ptrmask
diff --git a/pwndbg/typeinfo.py b/pwndbg/typeinfo.py
--- a/pwndbg/typeinfo.py
+++ b/pwndbg/typeinfo.py
@@ -55,15 +55,28 @@ def update():
     module.ushort = lookup_types('unsigned short', 'ushort', 'u16', 'uint16')
     module.uint   = lookup_types('unsigned int', 'uint', 'u32', 'uint32')
     module.void   = lookup_types('void', '()')
+    
     module.uint8  = module.uchar
     module.uint16 = module.ushort
     module.uint32 = module.uint
     module.uint64 = lookup_types('unsigned long long', 'ulong', 'u64', 'uint64')
+    module.unsigned = {
+        1: module.uint8,
+        2: module.uint16,
+        4: module.uint32,
+        8: module.uint64
+    }
 
     module.int8   = lookup_types('char', 'i8', 'int8')
     module.int16  = lookup_types('short', 'i16', 'int16')
     module.int32  = lookup_types('int', 'i32', 'int32')
     module.int64  = lookup_types('long long', 'long', 'i64', 'int64')
+    module.signed = {
+        1: module.int8,
+        2: module.int16,
+        4: module.int32,
+        8: module.int64
+    }
 
     module.pvoid  = void.pointer()
     module.ppvoid = pvoid.pointer()


Test patch: