We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
pwn.shellcraft.linkat second argument is incorrect
https://github.com/Gallopsled/pwntools/blob/bd12d1874f17e1fd6a9b26411ccc7ccd6c31f4cb/pwnlib/shellcraft/templates/common/linux/syscalls/linkat.asm#L30

`from` should be `from_`. The current implementation makes it not possible to pass a string.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pwnlib/data/syscalls/generate.py`
Content:
```
1 #!/usr/bin/env python2
2 from __future__ import division
3 import argparse
4 import keyword
5 import os
6 
7 from pwnlib import constants
8 from pwnlib.context import context
9 
10 # github.com/zachriggle/functions
11 from functions import functions, Function, Argument
12 
13 ARCHITECTURES = ['i386', 'amd64', 'arm', 'aarch64', 'mips']
14 
15 HEADER = '''
16 <%
17 import collections
18 import pwnlib.abi
19 import pwnlib.constants
20 import pwnlib.shellcraft
21 import six
22 %>
23 '''
24 
25 DOCSTRING = '''
26 <%docstring>{name}({arguments_comma_separated}) -> str
27 
28 Invokes the syscall {name}.
29 
30 See 'man 2 {name}' for more information.
31 
32 Arguments:
33 {arg_docs}
34 Returns:
35     {return_type}
36 </%docstring>
37 '''
38 
39 ARGUMENTS = """
40 <%page args="{arguments_default_values}"/>
41 """
42 
43 CALL = """
44 <%
45     abi = pwnlib.abi.ABI.syscall()
46     stack = abi.stack
47     regs = abi.register_arguments[1:]
48     allregs = pwnlib.shellcraft.registers.current()
49 
50     can_pushstr = {string_arguments!r}
51     can_pushstr_array = {array_arguments!r}
52 
53     argument_names = {argument_names!r}
54     argument_values = [{arguments_comma_separated!s}]
55 
56     # Load all of the arguments into their destination registers / stack slots.
57     register_arguments = dict()
58     stack_arguments = collections.OrderedDict()
59     string_arguments = dict()
60     dict_arguments = dict()
61     array_arguments = dict()
62     syscall_repr = []
63 
64     for name, arg in zip(argument_names, argument_values):
65         if arg is not None:
66             syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
67 
68         # If the argument itself (input) is a register...
69         if arg in allregs:
70             index = argument_names.index(name)
71             if index < len(regs):
72                 target = regs[index]
73                 register_arguments[target] = arg
74             elif arg is not None:
75                 stack_arguments[index] = arg
76 
77         # The argument is not a register.  It is a string value, and we
78         # are expecting a string value
79         elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
80             if isinstance(arg, six.text_type):
81                 arg = arg.encode('utf-8')
82             string_arguments[name] = arg
83 
84         # The argument is not a register.  It is a dictionary, and we are
85         # expecting K:V paris.
86         elif name in can_pushstr_array and isinstance(arg, dict):
87             array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]
88 
89         # The arguent is not a register.  It is a list, and we are expecting
90         # a list of arguments.
91         elif name in can_pushstr_array and isinstance(arg, (list, tuple)):
92             array_arguments[name] = arg
93 
94         # The argument is not a register, string, dict, or list.
95         # It could be a constant string ('O_RDONLY') for an integer argument,
96         # an actual integer value, or a constant.
97         else:
98             index = argument_names.index(name)
99             if index < len(regs):
100                 target = regs[index]
101                 register_arguments[target] = arg
102             elif arg is not None:
103                 stack_arguments[target] = arg
104 
105     # Some syscalls have different names on various architectures.
106     # Determine which syscall number to use for the current architecture.
107     for syscall in {syscalls!r}:
108         if hasattr(pwnlib.constants, syscall):
109             break
110     else:
111         raise Exception("Could not locate any syscalls: %r" % syscalls)
112 %>
113     /* {name}(${{', '.join(syscall_repr)}}) */
114 %for name, arg in string_arguments.items():
115     ${{pwnlib.shellcraft.pushstr(arg, append_null=(b'\\x00' not in arg))}}
116     ${{pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}}
117 %endfor
118 %for name, arg in array_arguments.items():
119     ${{pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}}
120 %endfor
121 %for name, arg in stack_arguments.items():
122     ${{pwnlib.shellcraft.push(arg)}}
123 %endfor
124     ${{pwnlib.shellcraft.setregs(register_arguments)}}
125     ${{pwnlib.shellcraft.syscall(syscall)}}
126 """
127 
128 
129 def can_be_constant(arg):
130     if arg.derefcnt == 0:
131         return True
132 
133 
134 def can_be_string(arg):
135     if arg.type == 'char' and arg.derefcnt == 1:
136         return True
137     if arg.type == 'void' and arg.derefcnt == 1:
138         return True
139 
140 def can_be_array(arg):
141     if arg.type == 'char' and arg.derefcnt == 2:
142         return True
143     if arg.type == 'void' and arg.derefcnt == 2:
144         return True
145 
146 
147 def fix_bad_arg_names(func, arg):
148     if arg.name == 'len':
149         return 'length'
150 
151     if arg.name in ('str', 'repr') or keyword.iskeyword(arg.name):
152         return arg.name + '_'
153 
154     if func.name == 'open' and arg.name == 'vararg':
155         return 'mode'
156 
157     return arg.name
158 
159 
160 def get_arg_default(arg):
161     return 0
162 
163 def fix_rt_syscall_name(name):
164     if name.startswith('rt_'):
165         return name[3:]
166     return name
167 
168 def fix_syscall_names(name):
169     # Do not use old_mmap
170     if name == 'SYS_mmap':
171         return ['SYS_mmap2', name]
172     # Some arches don't have vanilla sigreturn
173     if name.endswith('_sigreturn'):
174         return ['SYS_sigreturn', 'SYS_rt_sigreturn']
175     return [name]
176 
177 
178 def main(target):
179     for arch in ARCHITECTURES:
180         with context.local(arch=arch):
181             generate_one(target)
182 
183 def generate_one(target):
184     SYSCALL_NAMES = [c for c in dir(constants) if c.startswith('SYS_')]
185 
186     for syscall in SYSCALL_NAMES:
187         name = syscall[4:]
188 
189         # Skip anything with uppercase
190         if name.lower() != name:
191             print('Skipping %s' % name)
192             continue
193 
194         # Skip anything that starts with 'unused' or 'sys' after stripping
195         if name.startswith('unused'):
196             print('Skipping %s' % name)
197             continue
198 
199         function = functions.get(name, None)
200 
201         if name.startswith('rt_'):
202             name = name[3:]
203 
204         # If we can't find a function, just stub it out with something
205         # that has a vararg argument.
206         if function is None:
207             print('Stubbing out %s' % name)
208             args = [Argument('int', 0, 'vararg')]
209             function = Function('long', 0, name, args)
210 
211         # Some syscalls have different names on different architectures,
212         # or are superceded.  We try to do the "best" thing at runtime.
213         syscalls = fix_syscall_names(syscall)
214 
215         # Set up the argument string for Mako
216         argument_names = []
217         argument_defaults = []
218 
219         #
220 
221         for arg in function.args:
222             argname = fix_bad_arg_names(function, arg)
223             default = get_arg_default(arg)
224 
225             # Mako is unable to use *vararg and *kwarg, so we just stub in
226             # a whole bunch of additional arguments.
227             if argname == 'vararg':
228                 for j in range(5):
229                     argname = 'vararg_%i' % j
230                     argument_names.append(argname)
231                     argument_defaults.append('%s=%s' % (argname, None))
232                 break
233 
234             argument_names.append(argname)
235             argument_defaults.append('%s=%s' % (argname, default))
236 
237         arguments_default_values = ', '.join(argument_defaults)
238         arguments_comma_separated = ', '.join(argument_names)
239 
240         string_arguments = []
241         array_arguments = []
242         arg_docs = []
243 
244         for arg in function.args:
245 
246             if can_be_array(arg):
247                 array_arguments.append(arg.name)
248 
249             if can_be_string(arg):
250                 string_arguments.append(arg.name)
251 
252             argname = arg.name
253             argtype = str(arg.type) + ('*' * arg.derefcnt)
254             arg_docs.append(
255                 '    {argname}({argtype}): {argname}'.format(argname=argname,
256                                                              argtype=argtype))
257 
258         return_type = str(function.type) + ('*' * function.derefcnt)
259         arg_docs = '\n'.join(arg_docs)
260 
261         template_variables = {
262             'name': name,
263             'arg_docs': arg_docs,
264             'syscalls': syscalls,
265             'arguments_default_values': arguments_default_values,
266             'arguments_comma_separated': arguments_comma_separated,
267             'return_type': return_type,
268             'string_arguments': string_arguments,
269             'array_arguments': array_arguments,
270             'argument_names': argument_names,
271         }
272 
273         lines = [
274             HEADER,
275             DOCSTRING.format(**template_variables),
276             ARGUMENTS.format(**template_variables),
277             CALL.format(**template_variables)
278         ]
279 
280         if keyword.iskeyword(name):
281             name += '_'
282         with open(os.path.join(target, name + '.asm'), 'wt') as f:
283             f.write('\n'.join(map(str.strip, lines)) + '\n')
284 
285 if __name__ == '__main__':
286     p = argparse.ArgumentParser()
287     p.add_argument('target_directory')
288     args = p.parse_args()
289     main(args.target_directory)
290
```
--- 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/pwnlib/data/syscalls/generate.py b/pwnlib/data/syscalls/generate.py
--- a/pwnlib/data/syscalls/generate.py
+++ b/pwnlib/data/syscalls/generate.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 from __future__ import division
 import argparse
 import keyword
@@ -137,6 +137,7 @@
     if arg.type == 'void' and arg.derefcnt == 1:
         return True
 
+
 def can_be_array(arg):
     if arg.type == 'char' and arg.derefcnt == 2:
         return True
@@ -160,11 +161,13 @@
 def get_arg_default(arg):
     return 0
 
+
 def fix_rt_syscall_name(name):
     if name.startswith('rt_'):
         return name[3:]
     return name
 
+
 def fix_syscall_names(name):
     # Do not use old_mmap
     if name == 'SYS_mmap':
@@ -180,6 +183,7 @@
         with context.local(arch=arch):
             generate_one(target)
 
+
 def generate_one(target):
     SYSCALL_NAMES = [c for c in dir(constants) if c.startswith('SYS_')]
 
@@ -214,46 +218,50 @@
 
         # Set up the argument string for Mako
         argument_names = []
+        argument_names_ = []
         argument_defaults = []
 
+        string_arguments = []
+        array_arguments = []
+        arg_docs = []
+
         #
 
         for arg in function.args:
-            argname = fix_bad_arg_names(function, arg)
+            argname_ = fix_bad_arg_names(function, arg)
+            argname = argname_.rstrip('_')
             default = get_arg_default(arg)
 
+            if can_be_array(arg):
+                array_arguments.append(argname)
+
+            if can_be_string(arg):
+                string_arguments.append(argname)
+
+            argtype = str(arg.type) + ('*' * arg.derefcnt)
+            arg_docs.append(
+                '    {argname_}({argtype}): {argname}'.format(
+                    argname_=argname_,
+                    argname=argname,
+                    argtype=argtype,
+                ))
+
             # Mako is unable to use *vararg and *kwarg, so we just stub in
             # a whole bunch of additional arguments.
             if argname == 'vararg':
                 for j in range(5):
                     argname = 'vararg_%i' % j
                     argument_names.append(argname)
+                    argument_names_.append(argname)
                     argument_defaults.append('%s=%s' % (argname, None))
                 break
 
             argument_names.append(argname)
-            argument_defaults.append('%s=%s' % (argname, default))
+            argument_names_.append(argname_)
+            argument_defaults.append('%s=%s' % (argname_, default))
 
         arguments_default_values = ', '.join(argument_defaults)
-        arguments_comma_separated = ', '.join(argument_names)
-
-        string_arguments = []
-        array_arguments = []
-        arg_docs = []
-
-        for arg in function.args:
-
-            if can_be_array(arg):
-                array_arguments.append(arg.name)
-
-            if can_be_string(arg):
-                string_arguments.append(arg.name)
-
-            argname = arg.name
-            argtype = str(arg.type) + ('*' * arg.derefcnt)
-            arg_docs.append(
-                '    {argname}({argtype}): {argname}'.format(argname=argname,
-                                                             argtype=argtype))
+        arguments_comma_separated = ', '.join(argument_names_)
 
         return_type = str(function.type) + ('*' * function.derefcnt)
         arg_docs = '\n'.join(arg_docs)
@@ -282,6 +290,7 @@
         with open(os.path.join(target, name + '.asm'), 'wt') as f:
             f.write('\n'.join(map(str.strip, lines)) + '\n')
 
+
 if __name__ == '__main__':
     p = argparse.ArgumentParser()
     p.add_argument('target_directory')

{"golden_diff": "diff --git a/pwnlib/data/syscalls/generate.py b/pwnlib/data/syscalls/generate.py\n--- a/pwnlib/data/syscalls/generate.py\n+++ b/pwnlib/data/syscalls/generate.py\n@@ -1,4 +1,4 @@\n-#!/usr/bin/env python2\n+#!/usr/bin/env python3\n from __future__ import division\n import argparse\n import keyword\n@@ -137,6 +137,7 @@\n     if arg.type == 'void' and arg.derefcnt == 1:\n         return True\n \n+\n def can_be_array(arg):\n     if arg.type == 'char' and arg.derefcnt == 2:\n         return True\n@@ -160,11 +161,13 @@\n def get_arg_default(arg):\n     return 0\n \n+\n def fix_rt_syscall_name(name):\n     if name.startswith('rt_'):\n         return name[3:]\n     return name\n \n+\n def fix_syscall_names(name):\n     # Do not use old_mmap\n     if name == 'SYS_mmap':\n@@ -180,6 +183,7 @@\n         with context.local(arch=arch):\n             generate_one(target)\n \n+\n def generate_one(target):\n     SYSCALL_NAMES = [c for c in dir(constants) if c.startswith('SYS_')]\n \n@@ -214,46 +218,50 @@\n \n         # Set up the argument string for Mako\n         argument_names = []\n+        argument_names_ = []\n         argument_defaults = []\n \n+        string_arguments = []\n+        array_arguments = []\n+        arg_docs = []\n+\n         #\n \n         for arg in function.args:\n-            argname = fix_bad_arg_names(function, arg)\n+            argname_ = fix_bad_arg_names(function, arg)\n+            argname = argname_.rstrip('_')\n             default = get_arg_default(arg)\n \n+            if can_be_array(arg):\n+                array_arguments.append(argname)\n+\n+            if can_be_string(arg):\n+                string_arguments.append(argname)\n+\n+            argtype = str(arg.type) + ('*' * arg.derefcnt)\n+            arg_docs.append(\n+                '    {argname_}({argtype}): {argname}'.format(\n+                    argname_=argname_,\n+                    argname=argname,\n+                    argtype=argtype,\n+                ))\n+\n             # Mako is unable to use *vararg and *kwarg, so we just stub in\n             # a whole bunch of additional arguments.\n             if argname == 'vararg':\n                 for j in range(5):\n                     argname = 'vararg_%i' % j\n                     argument_names.append(argname)\n+                    argument_names_.append(argname)\n                     argument_defaults.append('%s=%s' % (argname, None))\n                 break\n \n             argument_names.append(argname)\n-            argument_defaults.append('%s=%s' % (argname, default))\n+            argument_names_.append(argname_)\n+            argument_defaults.append('%s=%s' % (argname_, default))\n \n         arguments_default_values = ', '.join(argument_defaults)\n-        arguments_comma_separated = ', '.join(argument_names)\n-\n-        string_arguments = []\n-        array_arguments = []\n-        arg_docs = []\n-\n-        for arg in function.args:\n-\n-            if can_be_array(arg):\n-                array_arguments.append(arg.name)\n-\n-            if can_be_string(arg):\n-                string_arguments.append(arg.name)\n-\n-            argname = arg.name\n-            argtype = str(arg.type) + ('*' * arg.derefcnt)\n-            arg_docs.append(\n-                '    {argname}({argtype}): {argname}'.format(argname=argname,\n-                                                             argtype=argtype))\n+        arguments_comma_separated = ', '.join(argument_names_)\n \n         return_type = str(function.type) + ('*' * function.derefcnt)\n         arg_docs = '\\n'.join(arg_docs)\n@@ -282,6 +290,7 @@\n         with open(os.path.join(target, name + '.asm'), 'wt') as f:\n             f.write('\\n'.join(map(str.strip, lines)) + '\\n')\n \n+\n if __name__ == '__main__':\n     p = argparse.ArgumentParser()\n     p.add_argument('target_directory')\n", "issue": "pwn.shellcraft.linkat second argument is incorrect\nhttps://github.com/Gallopsled/pwntools/blob/bd12d1874f17e1fd6a9b26411ccc7ccd6c31f4cb/pwnlib/shellcraft/templates/common/linux/syscalls/linkat.asm#L30\r\n\r\n`from` should be `from_`. The current implementation makes it not possible to pass a string.\n", "before_files": [{"content": "#!/usr/bin/env python2\nfrom __future__ import division\nimport argparse\nimport keyword\nimport os\n\nfrom pwnlib import constants\nfrom pwnlib.context import context\n\n# github.com/zachriggle/functions\nfrom functions import functions, Function, Argument\n\nARCHITECTURES = ['i386', 'amd64', 'arm', 'aarch64', 'mips']\n\nHEADER = '''\n<%\nimport collections\nimport pwnlib.abi\nimport pwnlib.constants\nimport pwnlib.shellcraft\nimport six\n%>\n'''\n\nDOCSTRING = '''\n<%docstring>{name}({arguments_comma_separated}) -> str\n\nInvokes the syscall {name}.\n\nSee 'man 2 {name}' for more information.\n\nArguments:\n{arg_docs}\nReturns:\n    {return_type}\n</%docstring>\n'''\n\nARGUMENTS = \"\"\"\n<%page args=\"{arguments_default_values}\"/>\n\"\"\"\n\nCALL = \"\"\"\n<%\n    abi = pwnlib.abi.ABI.syscall()\n    stack = abi.stack\n    regs = abi.register_arguments[1:]\n    allregs = pwnlib.shellcraft.registers.current()\n\n    can_pushstr = {string_arguments!r}\n    can_pushstr_array = {array_arguments!r}\n\n    argument_names = {argument_names!r}\n    argument_values = [{arguments_comma_separated!s}]\n\n    # Load all of the arguments into their destination registers / stack slots.\n    register_arguments = dict()\n    stack_arguments = collections.OrderedDict()\n    string_arguments = dict()\n    dict_arguments = dict()\n    array_arguments = dict()\n    syscall_repr = []\n\n    for name, arg in zip(argument_names, argument_values):\n        if arg is not None:\n            syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))\n\n        # If the argument itself (input) is a register...\n        if arg in allregs:\n            index = argument_names.index(name)\n            if index < len(regs):\n                target = regs[index]\n                register_arguments[target] = arg\n            elif arg is not None:\n                stack_arguments[index] = arg\n\n        # The argument is not a register.  It is a string value, and we\n        # are expecting a string value\n        elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):\n            if isinstance(arg, six.text_type):\n                arg = arg.encode('utf-8')\n            string_arguments[name] = arg\n\n        # The argument is not a register.  It is a dictionary, and we are\n        # expecting K:V paris.\n        elif name in can_pushstr_array and isinstance(arg, dict):\n            array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]\n\n        # The arguent is not a register.  It is a list, and we are expecting\n        # a list of arguments.\n        elif name in can_pushstr_array and isinstance(arg, (list, tuple)):\n            array_arguments[name] = arg\n\n        # The argument is not a register, string, dict, or list.\n        # It could be a constant string ('O_RDONLY') for an integer argument,\n        # an actual integer value, or a constant.\n        else:\n            index = argument_names.index(name)\n            if index < len(regs):\n                target = regs[index]\n                register_arguments[target] = arg\n            elif arg is not None:\n                stack_arguments[target] = arg\n\n    # Some syscalls have different names on various architectures.\n    # Determine which syscall number to use for the current architecture.\n    for syscall in {syscalls!r}:\n        if hasattr(pwnlib.constants, syscall):\n            break\n    else:\n        raise Exception(\"Could not locate any syscalls: %r\" % syscalls)\n%>\n    /* {name}(${{', '.join(syscall_repr)}}) */\n%for name, arg in string_arguments.items():\n    ${{pwnlib.shellcraft.pushstr(arg, append_null=(b'\\\\x00' not in arg))}}\n    ${{pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}}\n%endfor\n%for name, arg in array_arguments.items():\n    ${{pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}}\n%endfor\n%for name, arg in stack_arguments.items():\n    ${{pwnlib.shellcraft.push(arg)}}\n%endfor\n    ${{pwnlib.shellcraft.setregs(register_arguments)}}\n    ${{pwnlib.shellcraft.syscall(syscall)}}\n\"\"\"\n\n\ndef can_be_constant(arg):\n    if arg.derefcnt == 0:\n        return True\n\n\ndef can_be_string(arg):\n    if arg.type == 'char' and arg.derefcnt == 1:\n        return True\n    if arg.type == 'void' and arg.derefcnt == 1:\n        return True\n\ndef can_be_array(arg):\n    if arg.type == 'char' and arg.derefcnt == 2:\n        return True\n    if arg.type == 'void' and arg.derefcnt == 2:\n        return True\n\n\ndef fix_bad_arg_names(func, arg):\n    if arg.name == 'len':\n        return 'length'\n\n    if arg.name in ('str', 'repr') or keyword.iskeyword(arg.name):\n        return arg.name + '_'\n\n    if func.name == 'open' and arg.name == 'vararg':\n        return 'mode'\n\n    return arg.name\n\n\ndef get_arg_default(arg):\n    return 0\n\ndef fix_rt_syscall_name(name):\n    if name.startswith('rt_'):\n        return name[3:]\n    return name\n\ndef fix_syscall_names(name):\n    # Do not use old_mmap\n    if name == 'SYS_mmap':\n        return ['SYS_mmap2', name]\n    # Some arches don't have vanilla sigreturn\n    if name.endswith('_sigreturn'):\n        return ['SYS_sigreturn', 'SYS_rt_sigreturn']\n    return [name]\n\n\ndef main(target):\n    for arch in ARCHITECTURES:\n        with context.local(arch=arch):\n            generate_one(target)\n\ndef generate_one(target):\n    SYSCALL_NAMES = [c for c in dir(constants) if c.startswith('SYS_')]\n\n    for syscall in SYSCALL_NAMES:\n        name = syscall[4:]\n\n        # Skip anything with uppercase\n        if name.lower() != name:\n            print('Skipping %s' % name)\n            continue\n\n        # Skip anything that starts with 'unused' or 'sys' after stripping\n        if name.startswith('unused'):\n            print('Skipping %s' % name)\n            continue\n\n        function = functions.get(name, None)\n\n        if name.startswith('rt_'):\n            name = name[3:]\n\n        # If we can't find a function, just stub it out with something\n        # that has a vararg argument.\n        if function is None:\n            print('Stubbing out %s' % name)\n            args = [Argument('int', 0, 'vararg')]\n            function = Function('long', 0, name, args)\n\n        # Some syscalls have different names on different architectures,\n        # or are superceded.  We try to do the \"best\" thing at runtime.\n        syscalls = fix_syscall_names(syscall)\n\n        # Set up the argument string for Mako\n        argument_names = []\n        argument_defaults = []\n\n        #\n\n        for arg in function.args:\n            argname = fix_bad_arg_names(function, arg)\n            default = get_arg_default(arg)\n\n            # Mako is unable to use *vararg and *kwarg, so we just stub in\n            # a whole bunch of additional arguments.\n            if argname == 'vararg':\n                for j in range(5):\n                    argname = 'vararg_%i' % j\n                    argument_names.append(argname)\n                    argument_defaults.append('%s=%s' % (argname, None))\n                break\n\n            argument_names.append(argname)\n            argument_defaults.append('%s=%s' % (argname, default))\n\n        arguments_default_values = ', '.join(argument_defaults)\n        arguments_comma_separated = ', '.join(argument_names)\n\n        string_arguments = []\n        array_arguments = []\n        arg_docs = []\n\n        for arg in function.args:\n\n            if can_be_array(arg):\n                array_arguments.append(arg.name)\n\n            if can_be_string(arg):\n                string_arguments.append(arg.name)\n\n            argname = arg.name\n            argtype = str(arg.type) + ('*' * arg.derefcnt)\n            arg_docs.append(\n                '    {argname}({argtype}): {argname}'.format(argname=argname,\n                                                             argtype=argtype))\n\n        return_type = str(function.type) + ('*' * function.derefcnt)\n        arg_docs = '\\n'.join(arg_docs)\n\n        template_variables = {\n            'name': name,\n            'arg_docs': arg_docs,\n            'syscalls': syscalls,\n            'arguments_default_values': arguments_default_values,\n            'arguments_comma_separated': arguments_comma_separated,\n            'return_type': return_type,\n            'string_arguments': string_arguments,\n            'array_arguments': array_arguments,\n            'argument_names': argument_names,\n        }\n\n        lines = [\n            HEADER,\n            DOCSTRING.format(**template_variables),\n            ARGUMENTS.format(**template_variables),\n            CALL.format(**template_variables)\n        ]\n\n        if keyword.iskeyword(name):\n            name += '_'\n        with open(os.path.join(target, name + '.asm'), 'wt') as f:\n            f.write('\\n'.join(map(str.strip, lines)) + '\\n')\n\nif __name__ == '__main__':\n    p = argparse.ArgumentParser()\n    p.add_argument('target_directory')\n    args = p.parse_args()\n    main(args.target_directory)\n", "path": "pwnlib/data/syscalls/generate.py"}], "after_files": [{"content": "#!/usr/bin/env python3\nfrom __future__ import division\nimport argparse\nimport keyword\nimport os\n\nfrom pwnlib import constants\nfrom pwnlib.context import context\n\n# github.com/zachriggle/functions\nfrom functions import functions, Function, Argument\n\nARCHITECTURES = ['i386', 'amd64', 'arm', 'aarch64', 'mips']\n\nHEADER = '''\n<%\nimport collections\nimport pwnlib.abi\nimport pwnlib.constants\nimport pwnlib.shellcraft\nimport six\n%>\n'''\n\nDOCSTRING = '''\n<%docstring>{name}({arguments_comma_separated}) -> str\n\nInvokes the syscall {name}.\n\nSee 'man 2 {name}' for more information.\n\nArguments:\n{arg_docs}\nReturns:\n    {return_type}\n</%docstring>\n'''\n\nARGUMENTS = \"\"\"\n<%page args=\"{arguments_default_values}\"/>\n\"\"\"\n\nCALL = \"\"\"\n<%\n    abi = pwnlib.abi.ABI.syscall()\n    stack = abi.stack\n    regs = abi.register_arguments[1:]\n    allregs = pwnlib.shellcraft.registers.current()\n\n    can_pushstr = {string_arguments!r}\n    can_pushstr_array = {array_arguments!r}\n\n    argument_names = {argument_names!r}\n    argument_values = [{arguments_comma_separated!s}]\n\n    # Load all of the arguments into their destination registers / stack slots.\n    register_arguments = dict()\n    stack_arguments = collections.OrderedDict()\n    string_arguments = dict()\n    dict_arguments = dict()\n    array_arguments = dict()\n    syscall_repr = []\n\n    for name, arg in zip(argument_names, argument_values):\n        if arg is not None:\n            syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))\n\n        # If the argument itself (input) is a register...\n        if arg in allregs:\n            index = argument_names.index(name)\n            if index < len(regs):\n                target = regs[index]\n                register_arguments[target] = arg\n            elif arg is not None:\n                stack_arguments[index] = arg\n\n        # The argument is not a register.  It is a string value, and we\n        # are expecting a string value\n        elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):\n            if isinstance(arg, six.text_type):\n                arg = arg.encode('utf-8')\n            string_arguments[name] = arg\n\n        # The argument is not a register.  It is a dictionary, and we are\n        # expecting K:V paris.\n        elif name in can_pushstr_array and isinstance(arg, dict):\n            array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]\n\n        # The arguent is not a register.  It is a list, and we are expecting\n        # a list of arguments.\n        elif name in can_pushstr_array and isinstance(arg, (list, tuple)):\n            array_arguments[name] = arg\n\n        # The argument is not a register, string, dict, or list.\n        # It could be a constant string ('O_RDONLY') for an integer argument,\n        # an actual integer value, or a constant.\n        else:\n            index = argument_names.index(name)\n            if index < len(regs):\n                target = regs[index]\n                register_arguments[target] = arg\n            elif arg is not None:\n                stack_arguments[target] = arg\n\n    # Some syscalls have different names on various architectures.\n    # Determine which syscall number to use for the current architecture.\n    for syscall in {syscalls!r}:\n        if hasattr(pwnlib.constants, syscall):\n            break\n    else:\n        raise Exception(\"Could not locate any syscalls: %r\" % syscalls)\n%>\n    /* {name}(${{', '.join(syscall_repr)}}) */\n%for name, arg in string_arguments.items():\n    ${{pwnlib.shellcraft.pushstr(arg, append_null=(b'\\\\x00' not in arg))}}\n    ${{pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}}\n%endfor\n%for name, arg in array_arguments.items():\n    ${{pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}}\n%endfor\n%for name, arg in stack_arguments.items():\n    ${{pwnlib.shellcraft.push(arg)}}\n%endfor\n    ${{pwnlib.shellcraft.setregs(register_arguments)}}\n    ${{pwnlib.shellcraft.syscall(syscall)}}\n\"\"\"\n\n\ndef can_be_constant(arg):\n    if arg.derefcnt == 0:\n        return True\n\n\ndef can_be_string(arg):\n    if arg.type == 'char' and arg.derefcnt == 1:\n        return True\n    if arg.type == 'void' and arg.derefcnt == 1:\n        return True\n\n\ndef can_be_array(arg):\n    if arg.type == 'char' and arg.derefcnt == 2:\n        return True\n    if arg.type == 'void' and arg.derefcnt == 2:\n        return True\n\n\ndef fix_bad_arg_names(func, arg):\n    if arg.name == 'len':\n        return 'length'\n\n    if arg.name in ('str', 'repr') or keyword.iskeyword(arg.name):\n        return arg.name + '_'\n\n    if func.name == 'open' and arg.name == 'vararg':\n        return 'mode'\n\n    return arg.name\n\n\ndef get_arg_default(arg):\n    return 0\n\n\ndef fix_rt_syscall_name(name):\n    if name.startswith('rt_'):\n        return name[3:]\n    return name\n\n\ndef fix_syscall_names(name):\n    # Do not use old_mmap\n    if name == 'SYS_mmap':\n        return ['SYS_mmap2', name]\n    # Some arches don't have vanilla sigreturn\n    if name.endswith('_sigreturn'):\n        return ['SYS_sigreturn', 'SYS_rt_sigreturn']\n    return [name]\n\n\ndef main(target):\n    for arch in ARCHITECTURES:\n        with context.local(arch=arch):\n            generate_one(target)\n\n\ndef generate_one(target):\n    SYSCALL_NAMES = [c for c in dir(constants) if c.startswith('SYS_')]\n\n    for syscall in SYSCALL_NAMES:\n        name = syscall[4:]\n\n        # Skip anything with uppercase\n        if name.lower() != name:\n            print('Skipping %s' % name)\n            continue\n\n        # Skip anything that starts with 'unused' or 'sys' after stripping\n        if name.startswith('unused'):\n            print('Skipping %s' % name)\n            continue\n\n        function = functions.get(name, None)\n\n        if name.startswith('rt_'):\n            name = name[3:]\n\n        # If we can't find a function, just stub it out with something\n        # that has a vararg argument.\n        if function is None:\n            print('Stubbing out %s' % name)\n            args = [Argument('int', 0, 'vararg')]\n            function = Function('long', 0, name, args)\n\n        # Some syscalls have different names on different architectures,\n        # or are superceded.  We try to do the \"best\" thing at runtime.\n        syscalls = fix_syscall_names(syscall)\n\n        # Set up the argument string for Mako\n        argument_names = []\n        argument_names_ = []\n        argument_defaults = []\n\n        string_arguments = []\n        array_arguments = []\n        arg_docs = []\n\n        #\n\n        for arg in function.args:\n            argname_ = fix_bad_arg_names(function, arg)\n            argname = argname_.rstrip('_')\n            default = get_arg_default(arg)\n\n            if can_be_array(arg):\n                array_arguments.append(argname)\n\n            if can_be_string(arg):\n                string_arguments.append(argname)\n\n            argtype = str(arg.type) + ('*' * arg.derefcnt)\n            arg_docs.append(\n                '    {argname_}({argtype}): {argname}'.format(\n                    argname_=argname_,\n                    argname=argname,\n                    argtype=argtype,\n                ))\n\n            # Mako is unable to use *vararg and *kwarg, so we just stub in\n            # a whole bunch of additional arguments.\n            if argname == 'vararg':\n                for j in range(5):\n                    argname = 'vararg_%i' % j\n                    argument_names.append(argname)\n                    argument_names_.append(argname)\n                    argument_defaults.append('%s=%s' % (argname, None))\n                break\n\n            argument_names.append(argname)\n            argument_names_.append(argname_)\n            argument_defaults.append('%s=%s' % (argname_, default))\n\n        arguments_default_values = ', '.join(argument_defaults)\n        arguments_comma_separated = ', '.join(argument_names_)\n\n        return_type = str(function.type) + ('*' * function.derefcnt)\n        arg_docs = '\\n'.join(arg_docs)\n\n        template_variables = {\n            'name': name,\n            'arg_docs': arg_docs,\n            'syscalls': syscalls,\n            'arguments_default_values': arguments_default_values,\n            'arguments_comma_separated': arguments_comma_separated,\n            'return_type': return_type,\n            'string_arguments': string_arguments,\n            'array_arguments': array_arguments,\n            'argument_names': argument_names,\n        }\n\n        lines = [\n            HEADER,\n            DOCSTRING.format(**template_variables),\n            ARGUMENTS.format(**template_variables),\n            CALL.format(**template_variables)\n        ]\n\n        if keyword.iskeyword(name):\n            name += '_'\n        with open(os.path.join(target, name + '.asm'), 'wt') as f:\n            f.write('\\n'.join(map(str.strip, lines)) + '\\n')\n\n\nif __name__ == '__main__':\n    p = argparse.ArgumentParser()\n    p.add_argument('target_directory')\n    args = p.parse_args()\n    main(args.target_directory)\n", "path": "pwnlib/data/syscalls/generate.py"}]}