We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
System calls display is wrong for x86 syscalls on x86-64
When we step on `int 0x80` in a 64-bit (x86-64) program, we display wrong syscall number and arguments.
System calls display is wrong for x86 syscalls on x86-64
When we step on `int 0x80` in a 64-bit (x86-64) program, we display wrong syscall number and arguments.

--- 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/constants/__init__.py`
Content:
```
1 import pwndbg.gdblib.arch
2 
3 from . import aarch64
4 from . import amd64
5 from . import arm
6 from . import i386
7 from . import mips
8 from . import thumb
9 
10 arches = {"arm": arm, "armcm": arm, "i386": i386, "mips": mips, "x86-64": amd64, "aarch64": aarch64}
11 
12 
13 def syscall(value):
14     """
15     Given a value for a syscall number (e.g. execve == 11), return
16     the *name* of the syscall.
17     """
18     arch = arches.get(pwndbg.gdblib.arch.current, None)
19 
20     if not arch:
21         return None
22 
23     prefix = "__NR_"
24 
25     for k, v in arch.__dict__.items():
26         if v != value:
27             continue
28 
29         if not k.startswith(prefix):
30             continue
31 
32         return k[len(prefix) :].lower()
33 
34     return None
35
```

Path: `pwndbg/arguments.py`
Content:
```
1 """
2 Allows describing functions, specifically enumerating arguments which
3 may be passed in a combination of registers and stack values.
4 """
5 import gdb
6 from capstone import CS_GRP_CALL
7 from capstone import CS_GRP_INT
8 
9 import pwndbg.chain
10 import pwndbg.constants
11 import pwndbg.disasm
12 import pwndbg.gdblib.arch
13 import pwndbg.gdblib.memory
14 import pwndbg.gdblib.regs
15 import pwndbg.gdblib.symbol
16 import pwndbg.gdblib.typeinfo
17 import pwndbg.ida
18 import pwndbg.lib.abi
19 import pwndbg.lib.funcparser
20 import pwndbg.lib.functions
21 from pwndbg.commands.nearpc import c as N
22 
23 ida_replacements = {
24     "__int64": "signed long long int",
25     "__int32": "signed int",
26     "__int16": "signed short",
27     "__int8": "signed char",
28     "__uint64": "unsigned long long int",
29     "__uint32": "unsigned int",
30     "__uint16": "unsigned short",
31     "__uint8": "unsigned char",
32     "_BOOL_1": "unsigned char",
33     "_BOOL_2": "unsigned short",
34     "_BOOL_4": "unsigned int",
35     "_BYTE": "unsigned char",
36     "_WORD": "unsigned short",
37     "_DWORD": "unsigned int",
38     "_QWORD": "unsigned long long",
39     "__pure": "",
40     "__hidden": "",
41     "__return_ptr": "",
42     "__struct_ptr": "",
43     "__array_ptr": "",
44     "__fastcall": "",
45     "__cdecl": "",
46     "__thiscall": "",
47     "__userpurge": "",
48 }
49 
50 
51 def get_syscall_name(instruction):
52     if CS_GRP_INT not in instruction.groups:
53         return None
54 
55     syscall_register = pwndbg.lib.abi.ABI.syscall().syscall_register
56 
57     # If we are on x86/x64, return no syscall name for other instructions than syscall and int 0x80
58     if syscall_register in ("eax", "rax"):
59         mnemonic = instruction.mnemonic
60         if not (mnemonic == "syscall" or (mnemonic == "int" and instruction.op_str == "0x80")):
61             return None
62 
63     syscall_number = getattr(pwndbg.gdblib.regs, syscall_register)
64     return pwndbg.constants.syscall(syscall_number) or "<unk_%d>" % syscall_number
65 
66 
67 def get(instruction):
68     """
69     Returns an array containing the arguments to the current function,
70     if $pc is a 'call' or 'bl' type instruction.
71 
72     Otherwise, returns None.
73     """
74     n_args_default = 4
75 
76     if instruction is None:
77         return []
78 
79     if instruction.address != pwndbg.gdblib.regs.pc:
80         return []
81 
82     if CS_GRP_CALL in instruction.groups:
83         try:
84             abi = pwndbg.lib.abi.ABI.default()
85         except KeyError:
86             return []
87 
88         # Not sure of any OS which allows multiple operands on
89         # a call instruction.
90         assert len(instruction.operands) == 1
91 
92         target = instruction.operands[0].int
93 
94         if not target:
95             return []
96 
97         name = pwndbg.gdblib.symbol.get(target)
98         if not name:
99             return []
100     elif CS_GRP_INT in instruction.groups:
101         # Get the syscall number and name
102         name = get_syscall_name(instruction)
103         abi = pwndbg.lib.abi.ABI.syscall()
104         target = None
105 
106         if name is None:
107             return []
108     else:
109         return []
110 
111     result = []
112     name = name or ""
113 
114     sym = gdb.lookup_symbol(name)
115     name = name.replace("isoc99_", "")  # __isoc99_sscanf
116     name = name.replace("@plt", "")  # getpwiod@plt
117 
118     # If we have particular `XXX_chk` function in our database, we use it.
119     # Otherwise, we show args for its unchecked version.
120     # We also lstrip `_` in here, as e.g. `__printf_chk` needs the underscores.
121     if name not in pwndbg.lib.functions.functions:
122         name = name.replace("_chk", "")
123         name = name.strip().lstrip("_")  # _malloc
124 
125     func = pwndbg.lib.functions.functions.get(name, None)
126 
127     # Try to extract the data from GDB.
128     # Note that this is currently broken, pending acceptance of
129     # my patch: https://sourceware.org/ml/gdb-patches/2015-06/msg00268.html
130     if sym and sym[0]:
131         try:
132             n_args_default = len(sym[0].type.fields())
133         except TypeError:
134             pass
135 
136     # Try to grab the data out of IDA
137     if not func and target:
138         typename = pwndbg.ida.GetType(target)
139 
140         if typename:
141             typename += ";"
142 
143             # GetType() does not include the name.
144             typename = typename.replace("(", " function_name(", 1)
145 
146             for k, v in ida_replacements.items():
147                 typename = typename.replace(k, v)
148 
149             func = pwndbg.lib.funcparser.ExtractFuncDeclFromSource(typename + ";")
150 
151     if func:
152         args = func.args
153     else:
154         args = (
155             pwndbg.lib.functions.Argument("int", 0, argname(i, abi)) for i in range(n_args_default)
156         )
157 
158     for i, arg in enumerate(args):
159         result.append((arg, argument(i, abi)))
160 
161     return result
162 
163 
164 def argname(n, abi=None):
165     abi = abi or pwndbg.lib.abi.ABI.default()
166     regs = abi.register_arguments
167 
168     if n < len(regs):
169         return regs[n]
170 
171     return "arg[%i]" % n
172 
173 
174 def argument(n, abi=None):
175     """
176     Returns the nth argument, as if $pc were a 'call' or 'bl' type
177     instruction.
178     Works only for ABIs that use registers for arguments.
179     """
180     abi = abi or pwndbg.lib.abi.ABI.default()
181     regs = abi.register_arguments
182 
183     if n < len(regs):
184         return getattr(pwndbg.gdblib.regs, regs[n])
185 
186     n -= len(regs)
187 
188     sp = pwndbg.gdblib.regs.sp + (n * pwndbg.gdblib.arch.ptrsize)
189 
190     return int(pwndbg.gdblib.memory.poi(pwndbg.gdblib.typeinfo.ppvoid, sp))
191 
192 
193 def arguments(abi=None):
194     """
195     Yields (arg_name, arg_value) tuples for arguments from a given ABI.
196     Works only for ABIs that use registers for arguments.
197     """
198     abi = abi or pwndbg.lib.abi.ABI.default()
199     regs = abi.register_arguments
200 
201     for i in range(len(regs)):
202         yield argname(i, abi), argument(i, abi)
203 
204 
205 def format_args(instruction):
206     result = []
207     for arg, value in get(instruction):
208         code = arg.type != "char"
209         pretty = pwndbg.chain.format(value, code=code)
210 
211         # Enhance args display
212         if arg.name == "fd" and isinstance(value, int):
213             path = pwndbg.gdblib.file.readlink("/proc/%d/fd/%d" % (pwndbg.gdblib.proc.pid, value))
214             if path:
215                 pretty += " (%s)" % path
216 
217         result.append("%-10s %s" % (N.argument(arg.name) + ":", pretty))
218     return result
219
```
--- 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/arguments.py b/pwndbg/arguments.py
--- a/pwndbg/arguments.py
+++ b/pwndbg/arguments.py
@@ -53,15 +53,26 @@
         return None
 
     syscall_register = pwndbg.lib.abi.ABI.syscall().syscall_register
+    syscall_arch = pwndbg.gdblib.arch.current
 
-    # If we are on x86/x64, return no syscall name for other instructions than syscall and int 0x80
+    # On x86/x64 `syscall` and `int <value>` instructions are in CS_GRP_INT
+    # but only `syscall` and `int 0x80` actually execute syscalls on Linux.
+    # So here, we return no syscall name for other instructions and we also
+    # handle a case when 32-bit syscalls are executed on x64
     if syscall_register in ("eax", "rax"):
         mnemonic = instruction.mnemonic
-        if not (mnemonic == "syscall" or (mnemonic == "int" and instruction.op_str == "0x80")):
+
+        is_32bit = mnemonic == "int" and instruction.op_str == "0x80"
+        if not (mnemonic == "syscall" or is_32bit):
             return None
 
+        # On x64 the int 0x80 instruction executes 32-bit syscalls from i386
+        # On x86, the syscall_arch is already i386, so its all fine
+        if is_32bit:
+            syscall_arch = "i386"
+
     syscall_number = getattr(pwndbg.gdblib.regs, syscall_register)
-    return pwndbg.constants.syscall(syscall_number) or "<unk_%d>" % syscall_number
+    return pwndbg.constants.syscall(syscall_number, syscall_arch) or "<unk_%d>" % syscall_number
 
 
 def get(instruction):
diff --git a/pwndbg/constants/__init__.py b/pwndbg/constants/__init__.py
--- a/pwndbg/constants/__init__.py
+++ b/pwndbg/constants/__init__.py
@@ -10,20 +10,20 @@
 arches = {"arm": arm, "armcm": arm, "i386": i386, "mips": mips, "x86-64": amd64, "aarch64": aarch64}
 
 
-def syscall(value):
+def syscall(number, arch):
     """
-    Given a value for a syscall number (e.g. execve == 11), return
-    the *name* of the syscall.
+    Given a syscall number and architecture, returns the name of the syscall.
+    E.g. execve == 59 on x86-64
     """
-    arch = arches.get(pwndbg.gdblib.arch.current, None)
+    arch = arches.get(arch, None)
 
-    if not arch:
+    if arch is None:
         return None
 
     prefix = "__NR_"
 
     for k, v in arch.__dict__.items():
-        if v != value:
+        if v != number:
             continue
 
         if not k.startswith(prefix):

{"golden_diff": "diff --git a/pwndbg/arguments.py b/pwndbg/arguments.py\n--- a/pwndbg/arguments.py\n+++ b/pwndbg/arguments.py\n@@ -53,15 +53,26 @@\n         return None\n \n     syscall_register = pwndbg.lib.abi.ABI.syscall().syscall_register\n+    syscall_arch = pwndbg.gdblib.arch.current\n \n-    # If we are on x86/x64, return no syscall name for other instructions than syscall and int 0x80\n+    # On x86/x64 `syscall` and `int <value>` instructions are in CS_GRP_INT\n+    # but only `syscall` and `int 0x80` actually execute syscalls on Linux.\n+    # So here, we return no syscall name for other instructions and we also\n+    # handle a case when 32-bit syscalls are executed on x64\n     if syscall_register in (\"eax\", \"rax\"):\n         mnemonic = instruction.mnemonic\n-        if not (mnemonic == \"syscall\" or (mnemonic == \"int\" and instruction.op_str == \"0x80\")):\n+\n+        is_32bit = mnemonic == \"int\" and instruction.op_str == \"0x80\"\n+        if not (mnemonic == \"syscall\" or is_32bit):\n             return None\n \n+        # On x64 the int 0x80 instruction executes 32-bit syscalls from i386\n+        # On x86, the syscall_arch is already i386, so its all fine\n+        if is_32bit:\n+            syscall_arch = \"i386\"\n+\n     syscall_number = getattr(pwndbg.gdblib.regs, syscall_register)\n-    return pwndbg.constants.syscall(syscall_number) or \"<unk_%d>\" % syscall_number\n+    return pwndbg.constants.syscall(syscall_number, syscall_arch) or \"<unk_%d>\" % syscall_number\n \n \n def get(instruction):\ndiff --git a/pwndbg/constants/__init__.py b/pwndbg/constants/__init__.py\n--- a/pwndbg/constants/__init__.py\n+++ b/pwndbg/constants/__init__.py\n@@ -10,20 +10,20 @@\n arches = {\"arm\": arm, \"armcm\": arm, \"i386\": i386, \"mips\": mips, \"x86-64\": amd64, \"aarch64\": aarch64}\n \n \n-def syscall(value):\n+def syscall(number, arch):\n     \"\"\"\n-    Given a value for a syscall number (e.g. execve == 11), return\n-    the *name* of the syscall.\n+    Given a syscall number and architecture, returns the name of the syscall.\n+    E.g. execve == 59 on x86-64\n     \"\"\"\n-    arch = arches.get(pwndbg.gdblib.arch.current, None)\n+    arch = arches.get(arch, None)\n \n-    if not arch:\n+    if arch is None:\n         return None\n \n     prefix = \"__NR_\"\n \n     for k, v in arch.__dict__.items():\n-        if v != value:\n+        if v != number:\n             continue\n \n         if not k.startswith(prefix):\n", "issue": "System calls display is wrong for x86 syscalls on x86-64\nWhen we step on `int 0x80` in a 64-bit (x86-64) program, we display wrong syscall number and arguments.\nSystem calls display is wrong for x86 syscalls on x86-64\nWhen we step on `int 0x80` in a 64-bit (x86-64) program, we display wrong syscall number and arguments.\n", "before_files": [{"content": "import pwndbg.gdblib.arch\n\nfrom . import aarch64\nfrom . import amd64\nfrom . import arm\nfrom . import i386\nfrom . import mips\nfrom . import thumb\n\narches = {\"arm\": arm, \"armcm\": arm, \"i386\": i386, \"mips\": mips, \"x86-64\": amd64, \"aarch64\": aarch64}\n\n\ndef syscall(value):\n    \"\"\"\n    Given a value for a syscall number (e.g. execve == 11), return\n    the *name* of the syscall.\n    \"\"\"\n    arch = arches.get(pwndbg.gdblib.arch.current, None)\n\n    if not arch:\n        return None\n\n    prefix = \"__NR_\"\n\n    for k, v in arch.__dict__.items():\n        if v != value:\n            continue\n\n        if not k.startswith(prefix):\n            continue\n\n        return k[len(prefix) :].lower()\n\n    return None\n", "path": "pwndbg/constants/__init__.py"}, {"content": "\"\"\"\nAllows describing functions, specifically enumerating arguments which\nmay be passed in a combination of registers and stack values.\n\"\"\"\nimport gdb\nfrom capstone import CS_GRP_CALL\nfrom capstone import CS_GRP_INT\n\nimport pwndbg.chain\nimport pwndbg.constants\nimport pwndbg.disasm\nimport pwndbg.gdblib.arch\nimport pwndbg.gdblib.memory\nimport pwndbg.gdblib.regs\nimport pwndbg.gdblib.symbol\nimport pwndbg.gdblib.typeinfo\nimport pwndbg.ida\nimport pwndbg.lib.abi\nimport pwndbg.lib.funcparser\nimport pwndbg.lib.functions\nfrom pwndbg.commands.nearpc import c as N\n\nida_replacements = {\n    \"__int64\": \"signed long long int\",\n    \"__int32\": \"signed int\",\n    \"__int16\": \"signed short\",\n    \"__int8\": \"signed char\",\n    \"__uint64\": \"unsigned long long int\",\n    \"__uint32\": \"unsigned int\",\n    \"__uint16\": \"unsigned short\",\n    \"__uint8\": \"unsigned char\",\n    \"_BOOL_1\": \"unsigned char\",\n    \"_BOOL_2\": \"unsigned short\",\n    \"_BOOL_4\": \"unsigned int\",\n    \"_BYTE\": \"unsigned char\",\n    \"_WORD\": \"unsigned short\",\n    \"_DWORD\": \"unsigned int\",\n    \"_QWORD\": \"unsigned long long\",\n    \"__pure\": \"\",\n    \"__hidden\": \"\",\n    \"__return_ptr\": \"\",\n    \"__struct_ptr\": \"\",\n    \"__array_ptr\": \"\",\n    \"__fastcall\": \"\",\n    \"__cdecl\": \"\",\n    \"__thiscall\": \"\",\n    \"__userpurge\": \"\",\n}\n\n\ndef get_syscall_name(instruction):\n    if CS_GRP_INT not in instruction.groups:\n        return None\n\n    syscall_register = pwndbg.lib.abi.ABI.syscall().syscall_register\n\n    # If we are on x86/x64, return no syscall name for other instructions than syscall and int 0x80\n    if syscall_register in (\"eax\", \"rax\"):\n        mnemonic = instruction.mnemonic\n        if not (mnemonic == \"syscall\" or (mnemonic == \"int\" and instruction.op_str == \"0x80\")):\n            return None\n\n    syscall_number = getattr(pwndbg.gdblib.regs, syscall_register)\n    return pwndbg.constants.syscall(syscall_number) or \"<unk_%d>\" % syscall_number\n\n\ndef get(instruction):\n    \"\"\"\n    Returns an array containing the arguments to the current function,\n    if $pc is a 'call' or 'bl' type instruction.\n\n    Otherwise, returns None.\n    \"\"\"\n    n_args_default = 4\n\n    if instruction is None:\n        return []\n\n    if instruction.address != pwndbg.gdblib.regs.pc:\n        return []\n\n    if CS_GRP_CALL in instruction.groups:\n        try:\n            abi = pwndbg.lib.abi.ABI.default()\n        except KeyError:\n            return []\n\n        # Not sure of any OS which allows multiple operands on\n        # a call instruction.\n        assert len(instruction.operands) == 1\n\n        target = instruction.operands[0].int\n\n        if not target:\n            return []\n\n        name = pwndbg.gdblib.symbol.get(target)\n        if not name:\n            return []\n    elif CS_GRP_INT in instruction.groups:\n        # Get the syscall number and name\n        name = get_syscall_name(instruction)\n        abi = pwndbg.lib.abi.ABI.syscall()\n        target = None\n\n        if name is None:\n            return []\n    else:\n        return []\n\n    result = []\n    name = name or \"\"\n\n    sym = gdb.lookup_symbol(name)\n    name = name.replace(\"isoc99_\", \"\")  # __isoc99_sscanf\n    name = name.replace(\"@plt\", \"\")  # getpwiod@plt\n\n    # If we have particular `XXX_chk` function in our database, we use it.\n    # Otherwise, we show args for its unchecked version.\n    # We also lstrip `_` in here, as e.g. `__printf_chk` needs the underscores.\n    if name not in pwndbg.lib.functions.functions:\n        name = name.replace(\"_chk\", \"\")\n        name = name.strip().lstrip(\"_\")  # _malloc\n\n    func = pwndbg.lib.functions.functions.get(name, None)\n\n    # Try to extract the data from GDB.\n    # Note that this is currently broken, pending acceptance of\n    # my patch: https://sourceware.org/ml/gdb-patches/2015-06/msg00268.html\n    if sym and sym[0]:\n        try:\n            n_args_default = len(sym[0].type.fields())\n        except TypeError:\n            pass\n\n    # Try to grab the data out of IDA\n    if not func and target:\n        typename = pwndbg.ida.GetType(target)\n\n        if typename:\n            typename += \";\"\n\n            # GetType() does not include the name.\n            typename = typename.replace(\"(\", \" function_name(\", 1)\n\n            for k, v in ida_replacements.items():\n                typename = typename.replace(k, v)\n\n            func = pwndbg.lib.funcparser.ExtractFuncDeclFromSource(typename + \";\")\n\n    if func:\n        args = func.args\n    else:\n        args = (\n            pwndbg.lib.functions.Argument(\"int\", 0, argname(i, abi)) for i in range(n_args_default)\n        )\n\n    for i, arg in enumerate(args):\n        result.append((arg, argument(i, abi)))\n\n    return result\n\n\ndef argname(n, abi=None):\n    abi = abi or pwndbg.lib.abi.ABI.default()\n    regs = abi.register_arguments\n\n    if n < len(regs):\n        return regs[n]\n\n    return \"arg[%i]\" % n\n\n\ndef argument(n, abi=None):\n    \"\"\"\n    Returns the nth argument, as if $pc were a 'call' or 'bl' type\n    instruction.\n    Works only for ABIs that use registers for arguments.\n    \"\"\"\n    abi = abi or pwndbg.lib.abi.ABI.default()\n    regs = abi.register_arguments\n\n    if n < len(regs):\n        return getattr(pwndbg.gdblib.regs, regs[n])\n\n    n -= len(regs)\n\n    sp = pwndbg.gdblib.regs.sp + (n * pwndbg.gdblib.arch.ptrsize)\n\n    return int(pwndbg.gdblib.memory.poi(pwndbg.gdblib.typeinfo.ppvoid, sp))\n\n\ndef arguments(abi=None):\n    \"\"\"\n    Yields (arg_name, arg_value) tuples for arguments from a given ABI.\n    Works only for ABIs that use registers for arguments.\n    \"\"\"\n    abi = abi or pwndbg.lib.abi.ABI.default()\n    regs = abi.register_arguments\n\n    for i in range(len(regs)):\n        yield argname(i, abi), argument(i, abi)\n\n\ndef format_args(instruction):\n    result = []\n    for arg, value in get(instruction):\n        code = arg.type != \"char\"\n        pretty = pwndbg.chain.format(value, code=code)\n\n        # Enhance args display\n        if arg.name == \"fd\" and isinstance(value, int):\n            path = pwndbg.gdblib.file.readlink(\"/proc/%d/fd/%d\" % (pwndbg.gdblib.proc.pid, value))\n            if path:\n                pretty += \" (%s)\" % path\n\n        result.append(\"%-10s %s\" % (N.argument(arg.name) + \":\", pretty))\n    return result\n", "path": "pwndbg/arguments.py"}], "after_files": [{"content": "import pwndbg.gdblib.arch\n\nfrom . import aarch64\nfrom . import amd64\nfrom . import arm\nfrom . import i386\nfrom . import mips\nfrom . import thumb\n\narches = {\"arm\": arm, \"armcm\": arm, \"i386\": i386, \"mips\": mips, \"x86-64\": amd64, \"aarch64\": aarch64}\n\n\ndef syscall(number, arch):\n    \"\"\"\n    Given a syscall number and architecture, returns the name of the syscall.\n    E.g. execve == 59 on x86-64\n    \"\"\"\n    arch = arches.get(arch, None)\n\n    if arch is None:\n        return None\n\n    prefix = \"__NR_\"\n\n    for k, v in arch.__dict__.items():\n        if v != number:\n            continue\n\n        if not k.startswith(prefix):\n            continue\n\n        return k[len(prefix) :].lower()\n\n    return None\n", "path": "pwndbg/constants/__init__.py"}, {"content": "\"\"\"\nAllows describing functions, specifically enumerating arguments which\nmay be passed in a combination of registers and stack values.\n\"\"\"\nimport gdb\nfrom capstone import CS_GRP_CALL\nfrom capstone import CS_GRP_INT\n\nimport pwndbg.chain\nimport pwndbg.constants\nimport pwndbg.disasm\nimport pwndbg.gdblib.arch\nimport pwndbg.gdblib.memory\nimport pwndbg.gdblib.regs\nimport pwndbg.gdblib.symbol\nimport pwndbg.gdblib.typeinfo\nimport pwndbg.ida\nimport pwndbg.lib.abi\nimport pwndbg.lib.funcparser\nimport pwndbg.lib.functions\nfrom pwndbg.commands.nearpc import c as N\n\nida_replacements = {\n    \"__int64\": \"signed long long int\",\n    \"__int32\": \"signed int\",\n    \"__int16\": \"signed short\",\n    \"__int8\": \"signed char\",\n    \"__uint64\": \"unsigned long long int\",\n    \"__uint32\": \"unsigned int\",\n    \"__uint16\": \"unsigned short\",\n    \"__uint8\": \"unsigned char\",\n    \"_BOOL_1\": \"unsigned char\",\n    \"_BOOL_2\": \"unsigned short\",\n    \"_BOOL_4\": \"unsigned int\",\n    \"_BYTE\": \"unsigned char\",\n    \"_WORD\": \"unsigned short\",\n    \"_DWORD\": \"unsigned int\",\n    \"_QWORD\": \"unsigned long long\",\n    \"__pure\": \"\",\n    \"__hidden\": \"\",\n    \"__return_ptr\": \"\",\n    \"__struct_ptr\": \"\",\n    \"__array_ptr\": \"\",\n    \"__fastcall\": \"\",\n    \"__cdecl\": \"\",\n    \"__thiscall\": \"\",\n    \"__userpurge\": \"\",\n}\n\n\ndef get_syscall_name(instruction):\n    if CS_GRP_INT not in instruction.groups:\n        return None\n\n    syscall_register = pwndbg.lib.abi.ABI.syscall().syscall_register\n    syscall_arch = pwndbg.gdblib.arch.current\n\n    # On x86/x64 `syscall` and `int <value>` instructions are in CS_GRP_INT\n    # but only `syscall` and `int 0x80` actually execute syscalls on Linux.\n    # So here, we return no syscall name for other instructions and we also\n    # handle a case when 32-bit syscalls are executed on x64\n    if syscall_register in (\"eax\", \"rax\"):\n        mnemonic = instruction.mnemonic\n\n        is_32bit = mnemonic == \"int\" and instruction.op_str == \"0x80\"\n        if not (mnemonic == \"syscall\" or is_32bit):\n            return None\n\n        # On x64 the int 0x80 instruction executes 32-bit syscalls from i386\n        # On x86, the syscall_arch is already i386, so its all fine\n        if is_32bit:\n            syscall_arch = \"i386\"\n\n    syscall_number = getattr(pwndbg.gdblib.regs, syscall_register)\n    return pwndbg.constants.syscall(syscall_number, syscall_arch) or \"<unk_%d>\" % syscall_number\n\n\ndef get(instruction):\n    \"\"\"\n    Returns an array containing the arguments to the current function,\n    if $pc is a 'call' or 'bl' type instruction.\n\n    Otherwise, returns None.\n    \"\"\"\n    n_args_default = 4\n\n    if instruction is None:\n        return []\n\n    if instruction.address != pwndbg.gdblib.regs.pc:\n        return []\n\n    if CS_GRP_CALL in instruction.groups:\n        try:\n            abi = pwndbg.lib.abi.ABI.default()\n        except KeyError:\n            return []\n\n        # Not sure of any OS which allows multiple operands on\n        # a call instruction.\n        assert len(instruction.operands) == 1\n\n        target = instruction.operands[0].int\n\n        if not target:\n            return []\n\n        name = pwndbg.gdblib.symbol.get(target)\n        if not name:\n            return []\n    elif CS_GRP_INT in instruction.groups:\n        # Get the syscall number and name\n        name = get_syscall_name(instruction)\n        abi = pwndbg.lib.abi.ABI.syscall()\n        target = None\n\n        if name is None:\n            return []\n    else:\n        return []\n\n    result = []\n    name = name or \"\"\n\n    sym = gdb.lookup_symbol(name)\n    name = name.replace(\"isoc99_\", \"\")  # __isoc99_sscanf\n    name = name.replace(\"@plt\", \"\")  # getpwiod@plt\n\n    # If we have particular `XXX_chk` function in our database, we use it.\n    # Otherwise, we show args for its unchecked version.\n    # We also lstrip `_` in here, as e.g. `__printf_chk` needs the underscores.\n    if name not in pwndbg.lib.functions.functions:\n        name = name.replace(\"_chk\", \"\")\n        name = name.strip().lstrip(\"_\")  # _malloc\n\n    func = pwndbg.lib.functions.functions.get(name, None)\n\n    # Try to extract the data from GDB.\n    # Note that this is currently broken, pending acceptance of\n    # my patch: https://sourceware.org/ml/gdb-patches/2015-06/msg00268.html\n    if sym and sym[0]:\n        try:\n            n_args_default = len(sym[0].type.fields())\n        except TypeError:\n            pass\n\n    # Try to grab the data out of IDA\n    if not func and target:\n        typename = pwndbg.ida.GetType(target)\n\n        if typename:\n            typename += \";\"\n\n            # GetType() does not include the name.\n            typename = typename.replace(\"(\", \" function_name(\", 1)\n\n            for k, v in ida_replacements.items():\n                typename = typename.replace(k, v)\n\n            func = pwndbg.lib.funcparser.ExtractFuncDeclFromSource(typename + \";\")\n\n    if func:\n        args = func.args\n    else:\n        args = (\n            pwndbg.lib.functions.Argument(\"int\", 0, argname(i, abi)) for i in range(n_args_default)\n        )\n\n    for i, arg in enumerate(args):\n        result.append((arg, argument(i, abi)))\n\n    return result\n\n\ndef argname(n, abi=None):\n    abi = abi or pwndbg.lib.abi.ABI.default()\n    regs = abi.register_arguments\n\n    if n < len(regs):\n        return regs[n]\n\n    return \"arg[%i]\" % n\n\n\ndef argument(n, abi=None):\n    \"\"\"\n    Returns the nth argument, as if $pc were a 'call' or 'bl' type\n    instruction.\n    Works only for ABIs that use registers for arguments.\n    \"\"\"\n    abi = abi or pwndbg.lib.abi.ABI.default()\n    regs = abi.register_arguments\n\n    if n < len(regs):\n        return getattr(pwndbg.gdblib.regs, regs[n])\n\n    n -= len(regs)\n\n    sp = pwndbg.gdblib.regs.sp + (n * pwndbg.gdblib.arch.ptrsize)\n\n    return int(pwndbg.gdblib.memory.poi(pwndbg.gdblib.typeinfo.ppvoid, sp))\n\n\ndef arguments(abi=None):\n    \"\"\"\n    Yields (arg_name, arg_value) tuples for arguments from a given ABI.\n    Works only for ABIs that use registers for arguments.\n    \"\"\"\n    abi = abi or pwndbg.lib.abi.ABI.default()\n    regs = abi.register_arguments\n\n    for i in range(len(regs)):\n        yield argname(i, abi), argument(i, abi)\n\n\ndef format_args(instruction):\n    result = []\n    for arg, value in get(instruction):\n        code = arg.type != \"char\"\n        pretty = pwndbg.chain.format(value, code=code)\n\n        # Enhance args display\n        if arg.name == \"fd\" and isinstance(value, int):\n            path = pwndbg.gdblib.file.readlink(\"/proc/%d/fd/%d\" % (pwndbg.gdblib.proc.pid, value))\n            if path:\n                pretty += \" (%s)\" % path\n\n        result.append(\"%-10s %s\" % (N.argument(arg.name) + \":\", pretty))\n    return result\n", "path": "pwndbg/arguments.py"}]}