| Elliott Hughes | 6b586e7 | 2021-04-15 13:39:08 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python3 | 
| Pavel Chupin | f12a18b | 2012-12-12 13:11:48 +0400 | [diff] [blame] | 2 |  | 
|  | 3 | # This tool is used to generate the assembler system call stubs, | 
|  | 4 | # the header files listing all available system calls, and the | 
|  | 5 | # makefiles used to build all the stubs. | 
| The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 6 |  | 
| Christopher Ferris | 01bd32e | 2014-08-05 12:19:27 -0700 | [diff] [blame] | 7 | import atexit | 
| Elliott Hughes | 103ccde | 2013-10-16 14:27:59 -0700 | [diff] [blame] | 8 | import filecmp | 
|  | 9 | import glob | 
| Elliott Hughes | 103ccde | 2013-10-16 14:27:59 -0700 | [diff] [blame] | 10 | import re | 
|  | 11 | import shutil | 
|  | 12 | import stat | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 13 | import string | 
| Elliott Hughes | 103ccde | 2013-10-16 14:27:59 -0700 | [diff] [blame] | 14 | import sys | 
| Christopher Ferris | 01bd32e | 2014-08-05 12:19:27 -0700 | [diff] [blame] | 15 | import tempfile | 
| The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 16 |  | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 17 |  | 
| Elliott Hughes | 704772b | 2022-10-10 17:06:43 +0000 | [diff] [blame] | 18 | SupportedArchitectures = [ "arm", "arm64", "riscv64", "x86", "x86_64" ] | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 19 |  | 
| Elliott Hughes | d67b037 | 2019-04-15 14:18:26 -0700 | [diff] [blame] | 20 | syscall_stub_header = \ | 
| Elliott Hughes | 103ccde | 2013-10-16 14:27:59 -0700 | [diff] [blame] | 21 | """ | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 22 | ENTRY(%(func)s) | 
| Pavel Chupin | f12a18b | 2012-12-12 13:11:48 +0400 | [diff] [blame] | 23 | """ | 
|  | 24 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 25 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 26 | # | 
|  | 27 | # ARM assembler templates for each syscall stub | 
|  | 28 | # | 
|  | 29 |  | 
|  | 30 | arm_eabi_call_default = syscall_stub_header + """\ | 
|  | 31 | mov     ip, r7 | 
| Christopher Ferris | f5a9123 | 2016-04-27 18:31:02 -0700 | [diff] [blame] | 32 | .cfi_register r7, ip | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 33 | ldr     r7, =%(__NR_name)s | 
|  | 34 | swi     #0 | 
|  | 35 | mov     r7, ip | 
| Christopher Ferris | f5a9123 | 2016-04-27 18:31:02 -0700 | [diff] [blame] | 36 | .cfi_restore r7 | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 37 | cmn     r0, #(MAX_ERRNO + 1) | 
|  | 38 | bxls    lr | 
|  | 39 | neg     r0, r0 | 
| Elliott Hughes | 011e111 | 2014-09-08 15:25:01 -0700 | [diff] [blame] | 40 | b       __set_errno_internal | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 41 | END(%(func)s) | 
|  | 42 | """ | 
|  | 43 |  | 
|  | 44 | arm_eabi_call_long = syscall_stub_header + """\ | 
|  | 45 | mov     ip, sp | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 46 | stmfd   sp!, {r4, r5, r6, r7} | 
| Christopher Ferris | ed45970 | 2013-12-02 17:44:53 -0800 | [diff] [blame] | 47 | .cfi_def_cfa_offset 16 | 
|  | 48 | .cfi_rel_offset r4, 0 | 
|  | 49 | .cfi_rel_offset r5, 4 | 
|  | 50 | .cfi_rel_offset r6, 8 | 
|  | 51 | .cfi_rel_offset r7, 12 | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 52 | ldmfd   ip, {r4, r5, r6} | 
|  | 53 | ldr     r7, =%(__NR_name)s | 
|  | 54 | swi     #0 | 
|  | 55 | ldmfd   sp!, {r4, r5, r6, r7} | 
| Christopher Ferris | ed45970 | 2013-12-02 17:44:53 -0800 | [diff] [blame] | 56 | .cfi_def_cfa_offset 0 | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 57 | cmn     r0, #(MAX_ERRNO + 1) | 
|  | 58 | bxls    lr | 
|  | 59 | neg     r0, r0 | 
| Elliott Hughes | 011e111 | 2014-09-08 15:25:01 -0700 | [diff] [blame] | 60 | b       __set_errno_internal | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 61 | END(%(func)s) | 
|  | 62 | """ | 
|  | 63 |  | 
|  | 64 |  | 
|  | 65 | # | 
| Elliott Hughes | d67b037 | 2019-04-15 14:18:26 -0700 | [diff] [blame] | 66 | # Arm64 assembler template for each syscall stub | 
| Colin Cross | d1973ca | 2014-01-21 19:50:58 -0800 | [diff] [blame] | 67 | # | 
|  | 68 |  | 
|  | 69 | arm64_call = syscall_stub_header + """\ | 
| Colin Cross | d1973ca | 2014-01-21 19:50:58 -0800 | [diff] [blame] | 70 | mov     x8, %(__NR_name)s | 
|  | 71 | svc     #0 | 
|  | 72 |  | 
| Colin Cross | d1973ca | 2014-01-21 19:50:58 -0800 | [diff] [blame] | 73 | cmn     x0, #(MAX_ERRNO + 1) | 
|  | 74 | cneg    x0, x0, hi | 
| Elliott Hughes | 011e111 | 2014-09-08 15:25:01 -0700 | [diff] [blame] | 75 | b.hi    __set_errno_internal | 
| Colin Cross | d1973ca | 2014-01-21 19:50:58 -0800 | [diff] [blame] | 76 |  | 
|  | 77 | ret | 
|  | 78 | END(%(func)s) | 
|  | 79 | """ | 
|  | 80 |  | 
|  | 81 |  | 
|  | 82 | # | 
| Elliott Hughes | 704772b | 2022-10-10 17:06:43 +0000 | [diff] [blame] | 83 | # RISC-V64 assembler templates for each syscall stub | 
|  | 84 | # | 
|  | 85 |  | 
|  | 86 | riscv64_call = syscall_stub_header + """\ | 
|  | 87 | li      a7, %(__NR_name)s | 
|  | 88 | ecall | 
|  | 89 |  | 
|  | 90 | li      a7, -MAX_ERRNO | 
|  | 91 | bgtu    a0, a7, 1f | 
|  | 92 |  | 
|  | 93 | ret | 
|  | 94 | 1: | 
|  | 95 | neg     a0, a0 | 
| caowencheng | c42c741 | 2023-03-09 09:16:34 +0800 | [diff] [blame] | 96 | tail    __set_errno_internal | 
| Elliott Hughes | 704772b | 2022-10-10 17:06:43 +0000 | [diff] [blame] | 97 | END(%(func)s) | 
|  | 98 | """ | 
|  | 99 |  | 
|  | 100 | # | 
| The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 101 | # x86 assembler templates for each syscall stub | 
|  | 102 | # | 
|  | 103 |  | 
| Christopher Ferris | e4bc756 | 2014-01-06 16:39:10 -0800 | [diff] [blame] | 104 | x86_registers = [ "ebx", "ecx", "edx", "esi", "edi", "ebp" ] | 
| The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 105 |  | 
| Mingwei Shi | be91052 | 2015-11-12 07:02:14 +0000 | [diff] [blame] | 106 | x86_call_prepare = """\ | 
|  | 107 |  | 
|  | 108 | call    __kernel_syscall | 
|  | 109 | pushl   %eax | 
|  | 110 | .cfi_adjust_cfa_offset 4 | 
|  | 111 | .cfi_rel_offset eax, 0 | 
|  | 112 |  | 
|  | 113 | """ | 
|  | 114 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 115 | x86_call = """\ | 
|  | 116 | movl    $%(__NR_name)s, %%eax | 
| Mingwei Shi | be91052 | 2015-11-12 07:02:14 +0000 | [diff] [blame] | 117 | call    *(%%esp) | 
|  | 118 | addl    $4, %%esp | 
|  | 119 |  | 
| Elliott Hughes | 9aceab5 | 2013-03-12 14:57:30 -0700 | [diff] [blame] | 120 | cmpl    $-MAX_ERRNO, %%eax | 
| The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 121 | jb      1f | 
|  | 122 | negl    %%eax | 
|  | 123 | pushl   %%eax | 
| Elliott Hughes | 011e111 | 2014-09-08 15:25:01 -0700 | [diff] [blame] | 124 | call    __set_errno_internal | 
| The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 125 | addl    $4, %%esp | 
| The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 126 | 1: | 
|  | 127 | """ | 
|  | 128 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 129 | x86_return = """\ | 
|  | 130 | ret | 
|  | 131 | END(%(func)s) | 
| The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 132 | """ | 
|  | 133 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 134 |  | 
| Elliott Hughes | cd6780b | 2013-02-07 14:07:00 -0800 | [diff] [blame] | 135 | # | 
| Elliott Hughes | d67b037 | 2019-04-15 14:18:26 -0700 | [diff] [blame] | 136 | # x86_64 assembler template for each syscall stub | 
| Pavel Chupin | f12a18b | 2012-12-12 13:11:48 +0400 | [diff] [blame] | 137 | # | 
|  | 138 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 139 | x86_64_call = """\ | 
|  | 140 | movl    $%(__NR_name)s, %%eax | 
| Pavel Chupin | f12a18b | 2012-12-12 13:11:48 +0400 | [diff] [blame] | 141 | syscall | 
|  | 142 | cmpq    $-MAX_ERRNO, %%rax | 
|  | 143 | jb      1f | 
|  | 144 | negl    %%eax | 
|  | 145 | movl    %%eax, %%edi | 
| Elliott Hughes | 011e111 | 2014-09-08 15:25:01 -0700 | [diff] [blame] | 146 | call    __set_errno_internal | 
| Pavel Chupin | f12a18b | 2012-12-12 13:11:48 +0400 | [diff] [blame] | 147 | 1: | 
|  | 148 | ret | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 149 | END(%(func)s) | 
| Pavel Chupin | f12a18b | 2012-12-12 13:11:48 +0400 | [diff] [blame] | 150 | """ | 
|  | 151 |  | 
| Raghu Gandham | 1fa0d84 | 2012-01-27 17:51:42 -0800 | [diff] [blame] | 152 |  | 
| David 'Digit' Turner | 95d751f | 2010-12-16 16:47:14 +0100 | [diff] [blame] | 153 | def param_uses_64bits(param): | 
|  | 154 | """Returns True iff a syscall parameter description corresponds | 
|  | 155 | to a 64-bit type.""" | 
|  | 156 | param = param.strip() | 
|  | 157 | # First, check that the param type begins with one of the known | 
|  | 158 | # 64-bit types. | 
|  | 159 | if not ( \ | 
|  | 160 | param.startswith("int64_t") or param.startswith("uint64_t") or \ | 
|  | 161 | param.startswith("loff_t") or param.startswith("off64_t") or \ | 
|  | 162 | param.startswith("long long") or param.startswith("unsigned long long") or | 
|  | 163 | param.startswith("signed long long") ): | 
|  | 164 | return False | 
|  | 165 |  | 
|  | 166 | # Second, check that there is no pointer type here | 
|  | 167 | if param.find("*") >= 0: | 
|  | 168 | return False | 
|  | 169 |  | 
|  | 170 | # Ok | 
|  | 171 | return True | 
|  | 172 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 173 |  | 
| David 'Digit' Turner | 95d751f | 2010-12-16 16:47:14 +0100 | [diff] [blame] | 174 | def count_arm_param_registers(params): | 
|  | 175 | """This function is used to count the number of register used | 
| Elliott Hughes | cd6780b | 2013-02-07 14:07:00 -0800 | [diff] [blame] | 176 | to pass parameters when invoking an ARM system call. | 
| David 'Digit' Turner | 95d751f | 2010-12-16 16:47:14 +0100 | [diff] [blame] | 177 | This is because the ARM EABI mandates that 64-bit quantities | 
|  | 178 | must be passed in an even+odd register pair. So, for example, | 
|  | 179 | something like: | 
|  | 180 |  | 
|  | 181 | foo(int fd, off64_t pos) | 
|  | 182 |  | 
|  | 183 | would actually need 4 registers: | 
|  | 184 | r0 -> int | 
|  | 185 | r1 -> unused | 
|  | 186 | r2-r3 -> pos | 
|  | 187 | """ | 
|  | 188 | count = 0 | 
|  | 189 | for param in params: | 
|  | 190 | if param_uses_64bits(param): | 
|  | 191 | if (count & 1) != 0: | 
|  | 192 | count += 1 | 
|  | 193 | count += 2 | 
|  | 194 | else: | 
|  | 195 | count += 1 | 
|  | 196 | return count | 
|  | 197 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 198 |  | 
| David 'Digit' Turner | 95d751f | 2010-12-16 16:47:14 +0100 | [diff] [blame] | 199 | def count_generic_param_registers(params): | 
|  | 200 | count = 0 | 
|  | 201 | for param in params: | 
|  | 202 | if param_uses_64bits(param): | 
|  | 203 | count += 2 | 
|  | 204 | else: | 
|  | 205 | count += 1 | 
|  | 206 | return count | 
|  | 207 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 208 |  | 
| Pavel Chupin | f12a18b | 2012-12-12 13:11:48 +0400 | [diff] [blame] | 209 | def count_generic_param_registers64(params): | 
|  | 210 | count = 0 | 
|  | 211 | for param in params: | 
|  | 212 | count += 1 | 
|  | 213 | return count | 
|  | 214 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 215 |  | 
| Elliott Hughes | cda6209 | 2013-03-22 13:50:44 -0700 | [diff] [blame] | 216 | # This lets us support regular system calls like __NR_write and also weird | 
|  | 217 | # ones like __ARM_NR_cacheflush, where the NR doesn't come at the start. | 
|  | 218 | def make__NR_name(name): | 
| Christopher Ferris | 01bd32e | 2014-08-05 12:19:27 -0700 | [diff] [blame] | 219 | if name.startswith("__ARM_NR_"): | 
| Elliott Hughes | cda6209 | 2013-03-22 13:50:44 -0700 | [diff] [blame] | 220 | return name | 
|  | 221 | else: | 
|  | 222 | return "__NR_%s" % (name) | 
|  | 223 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 224 |  | 
| Elliott Hughes | fff6e27 | 2013-10-24 17:03:20 -0700 | [diff] [blame] | 225 | def add_footer(pointer_length, stub, syscall): | 
|  | 226 | # Add any aliases for this syscall. | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 227 | aliases = syscall["aliases"] | 
|  | 228 | for alias in aliases: | 
| Christopher Ferris | fa5faa0 | 2015-03-24 16:50:46 -0700 | [diff] [blame] | 229 | stub += "\nALIAS_SYMBOL(%s, %s)\n" % (alias, syscall["func"]) | 
| Elliott Hughes | fff6e27 | 2013-10-24 17:03:20 -0700 | [diff] [blame] | 230 |  | 
| Nick Kralevich | 00490ae | 2015-02-03 11:27:25 -0800 | [diff] [blame] | 231 | # Use hidden visibility on LP64 for any functions beginning with underscores. | 
| Elliott Hughes | 50080a2 | 2019-06-19 12:47:53 -0700 | [diff] [blame] | 232 | if pointer_length == 64 and syscall["func"].startswith("__"): | 
| Elliott Hughes | d465eb4 | 2014-02-19 18:59:19 -0800 | [diff] [blame] | 233 | stub += '.hidden ' + syscall["func"] + '\n' | 
| Elliott Hughes | fff6e27 | 2013-10-24 17:03:20 -0700 | [diff] [blame] | 234 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 235 | return stub | 
|  | 236 |  | 
|  | 237 |  | 
|  | 238 | def arm_eabi_genstub(syscall): | 
|  | 239 | num_regs = count_arm_param_registers(syscall["params"]) | 
|  | 240 | if num_regs > 4: | 
|  | 241 | return arm_eabi_call_long % syscall | 
|  | 242 | return arm_eabi_call_default % syscall | 
|  | 243 |  | 
|  | 244 |  | 
| Colin Cross | d1973ca | 2014-01-21 19:50:58 -0800 | [diff] [blame] | 245 | def arm64_genstub(syscall): | 
|  | 246 | return arm64_call % syscall | 
|  | 247 |  | 
|  | 248 |  | 
| Elliott Hughes | 704772b | 2022-10-10 17:06:43 +0000 | [diff] [blame] | 249 | def riscv64_genstub(syscall): | 
|  | 250 | return riscv64_call % syscall | 
|  | 251 |  | 
|  | 252 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 253 | def x86_genstub(syscall): | 
|  | 254 | result     = syscall_stub_header % syscall | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 255 |  | 
|  | 256 | numparams = count_generic_param_registers(syscall["params"]) | 
| Mingwei Shi | be91052 | 2015-11-12 07:02:14 +0000 | [diff] [blame] | 257 | stack_bias = numparams*4 + 8 | 
| Christopher Ferris | e4bc756 | 2014-01-06 16:39:10 -0800 | [diff] [blame] | 258 | offset = 0 | 
|  | 259 | mov_result = "" | 
| Christopher Ferris | 15b91e9 | 2014-05-29 18:17:09 -0700 | [diff] [blame] | 260 | first_push = True | 
| Christopher Ferris | e4bc756 | 2014-01-06 16:39:10 -0800 | [diff] [blame] | 261 | for register in x86_registers[:numparams]: | 
|  | 262 | result     += "    pushl   %%%s\n" % register | 
| Christopher Ferris | 15b91e9 | 2014-05-29 18:17:09 -0700 | [diff] [blame] | 263 | if first_push: | 
|  | 264 | result   += "    .cfi_def_cfa_offset 8\n" | 
|  | 265 | result   += "    .cfi_rel_offset %s, 0\n" % register | 
|  | 266 | first_push = False | 
|  | 267 | else: | 
|  | 268 | result   += "    .cfi_adjust_cfa_offset 4\n" | 
|  | 269 | result   += "    .cfi_rel_offset %s, 0\n" % register | 
| Christopher Ferris | e4bc756 | 2014-01-06 16:39:10 -0800 | [diff] [blame] | 270 | mov_result += "    mov     %d(%%esp), %%%s\n" % (stack_bias+offset, register) | 
| Christopher Ferris | e4bc756 | 2014-01-06 16:39:10 -0800 | [diff] [blame] | 271 | offset += 4 | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 272 |  | 
| Mingwei Shi | be91052 | 2015-11-12 07:02:14 +0000 | [diff] [blame] | 273 | result += x86_call_prepare | 
| Christopher Ferris | 15b91e9 | 2014-05-29 18:17:09 -0700 | [diff] [blame] | 274 | result += mov_result | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 275 | result += x86_call % syscall | 
|  | 276 |  | 
| Christopher Ferris | e4bc756 | 2014-01-06 16:39:10 -0800 | [diff] [blame] | 277 | for register in reversed(x86_registers[:numparams]): | 
|  | 278 | result += "    popl    %%%s\n" % register | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 279 |  | 
|  | 280 | result += x86_return % syscall | 
|  | 281 | return result | 
|  | 282 |  | 
| Serban Constantinescu | feaa89a | 2013-10-07 16:49:09 +0100 | [diff] [blame] | 283 |  | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 284 | def x86_genstub_socketcall(syscall): | 
|  | 285 | #   %ebx <--- Argument 1 - The call id of the needed vectored | 
|  | 286 | #                          syscall (socket, bind, recv, etc) | 
|  | 287 | #   %ecx <--- Argument 2 - Pointer to the rest of the arguments | 
|  | 288 | #                          from the original function called (socket()) | 
|  | 289 |  | 
|  | 290 | result = syscall_stub_header % syscall | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 291 |  | 
|  | 292 | # save the regs we need | 
| Christopher Ferris | e4bc756 | 2014-01-06 16:39:10 -0800 | [diff] [blame] | 293 | result += "    pushl   %ebx\n" | 
| Christopher Ferris | e4bc756 | 2014-01-06 16:39:10 -0800 | [diff] [blame] | 294 | result += "    .cfi_def_cfa_offset 8\n" | 
|  | 295 | result += "    .cfi_rel_offset ebx, 0\n" | 
| Christopher Ferris | 15b91e9 | 2014-05-29 18:17:09 -0700 | [diff] [blame] | 296 | result += "    pushl   %ecx\n" | 
|  | 297 | result += "    .cfi_adjust_cfa_offset 4\n" | 
|  | 298 | result += "    .cfi_rel_offset ecx, 0\n" | 
| Mingwei Shi | be91052 | 2015-11-12 07:02:14 +0000 | [diff] [blame] | 299 | stack_bias = 16 | 
|  | 300 |  | 
|  | 301 | result += x86_call_prepare | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 302 |  | 
|  | 303 | # set the call id (%ebx) | 
| Christopher Ferris | e4bc756 | 2014-01-06 16:39:10 -0800 | [diff] [blame] | 304 | result += "    mov     $%d, %%ebx\n" % syscall["socketcall_id"] | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 305 |  | 
|  | 306 | # set the pointer to the rest of the args into %ecx | 
| Christopher Ferris | e4bc756 | 2014-01-06 16:39:10 -0800 | [diff] [blame] | 307 | result += "    mov     %esp, %ecx\n" | 
|  | 308 | result += "    addl    $%d, %%ecx\n" % (stack_bias) | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 309 |  | 
|  | 310 | # now do the syscall code itself | 
|  | 311 | result += x86_call % syscall | 
|  | 312 |  | 
|  | 313 | # now restore the saved regs | 
| Christopher Ferris | e4bc756 | 2014-01-06 16:39:10 -0800 | [diff] [blame] | 314 | result += "    popl    %ecx\n" | 
|  | 315 | result += "    popl    %ebx\n" | 
| Elliott Hughes | 0437f3f | 2013-10-07 23:53:13 -0700 | [diff] [blame] | 316 |  | 
|  | 317 | # epilog | 
|  | 318 | result += x86_return % syscall | 
|  | 319 | return result | 
|  | 320 |  | 
|  | 321 |  | 
|  | 322 | def x86_64_genstub(syscall): | 
|  | 323 | result = syscall_stub_header % syscall | 
|  | 324 | num_regs = count_generic_param_registers64(syscall["params"]) | 
|  | 325 | if (num_regs > 3): | 
|  | 326 | # rcx is used as 4th argument. Kernel wants it at r10. | 
|  | 327 | result += "    movq    %rcx, %r10\n" | 
|  | 328 |  | 
|  | 329 | result += x86_64_call % syscall | 
|  | 330 | return result | 
|  | 331 |  | 
|  | 332 |  | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 333 | class SysCallsTxtParser: | 
|  | 334 | def __init__(self): | 
|  | 335 | self.syscalls = [] | 
| Elliott Hughes | 1c1dfb8 | 2022-11-08 02:57:55 +0000 | [diff] [blame] | 336 | self.lineno = 0 | 
|  | 337 | self.errors = False | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 338 |  | 
|  | 339 | def E(self, msg): | 
| Elliott Hughes | bc6999f | 2021-02-03 13:13:57 -0800 | [diff] [blame] | 340 | print("%d: %s" % (self.lineno, msg)) | 
| Elliott Hughes | 1c1dfb8 | 2022-11-08 02:57:55 +0000 | [diff] [blame] | 341 | self.errors = True | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 342 |  | 
|  | 343 | def parse_line(self, line): | 
|  | 344 | """ parse a syscall spec line. | 
|  | 345 |  | 
|  | 346 | line processing, format is | 
|  | 347 | return type    func_name[|alias_list][:syscall_name[:socketcall_id]] ( [paramlist] ) architecture_list | 
|  | 348 | """ | 
|  | 349 | pos_lparen = line.find('(') | 
|  | 350 | E          = self.E | 
|  | 351 | if pos_lparen < 0: | 
|  | 352 | E("missing left parenthesis in '%s'" % line) | 
|  | 353 | return | 
|  | 354 |  | 
|  | 355 | pos_rparen = line.rfind(')') | 
|  | 356 | if pos_rparen < 0 or pos_rparen <= pos_lparen: | 
|  | 357 | E("missing or misplaced right parenthesis in '%s'" % line) | 
|  | 358 | return | 
|  | 359 |  | 
|  | 360 | return_type = line[:pos_lparen].strip().split() | 
|  | 361 | if len(return_type) < 2: | 
|  | 362 | E("missing return type in '%s'" % line) | 
|  | 363 | return | 
|  | 364 |  | 
|  | 365 | syscall_func = return_type[-1] | 
| Elliott Hughes | bc6999f | 2021-02-03 13:13:57 -0800 | [diff] [blame] | 366 | return_type  = ' '.join(return_type[:-1]) | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 367 | socketcall_id = -1 | 
|  | 368 |  | 
|  | 369 | pos_colon = syscall_func.find(':') | 
|  | 370 | if pos_colon < 0: | 
|  | 371 | syscall_name = syscall_func | 
|  | 372 | else: | 
|  | 373 | if pos_colon == 0 or pos_colon+1 >= len(syscall_func): | 
|  | 374 | E("misplaced colon in '%s'" % line) | 
|  | 375 | return | 
|  | 376 |  | 
|  | 377 | # now find if there is a socketcall_id for a dispatch-type syscall | 
|  | 378 | # after the optional 2nd colon | 
|  | 379 | pos_colon2 = syscall_func.find(':', pos_colon + 1) | 
|  | 380 | if pos_colon2 < 0: | 
|  | 381 | syscall_name = syscall_func[pos_colon+1:] | 
|  | 382 | syscall_func = syscall_func[:pos_colon] | 
|  | 383 | else: | 
|  | 384 | if pos_colon2+1 >= len(syscall_func): | 
|  | 385 | E("misplaced colon2 in '%s'" % line) | 
|  | 386 | return | 
|  | 387 | syscall_name = syscall_func[(pos_colon+1):pos_colon2] | 
|  | 388 | socketcall_id = int(syscall_func[pos_colon2+1:]) | 
|  | 389 | syscall_func = syscall_func[:pos_colon] | 
|  | 390 |  | 
|  | 391 | alias_delim = syscall_func.find('|') | 
|  | 392 | if alias_delim > 0: | 
|  | 393 | alias_list = syscall_func[alias_delim+1:].strip() | 
|  | 394 | syscall_func = syscall_func[:alias_delim] | 
|  | 395 | alias_delim = syscall_name.find('|') | 
|  | 396 | if alias_delim > 0: | 
|  | 397 | syscall_name = syscall_name[:alias_delim] | 
| Elliott Hughes | bc6999f | 2021-02-03 13:13:57 -0800 | [diff] [blame] | 398 | syscall_aliases = alias_list.split(',') | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 399 | else: | 
|  | 400 | syscall_aliases = [] | 
|  | 401 |  | 
|  | 402 | if pos_rparen > pos_lparen+1: | 
|  | 403 | syscall_params = line[pos_lparen+1:pos_rparen].split(',') | 
| Elliott Hughes | bc6999f | 2021-02-03 13:13:57 -0800 | [diff] [blame] | 404 | params         = ','.join(syscall_params) | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 405 | else: | 
|  | 406 | syscall_params = [] | 
|  | 407 | params         = "void" | 
|  | 408 |  | 
|  | 409 | t = { | 
|  | 410 | "name"    : syscall_name, | 
|  | 411 | "func"    : syscall_func, | 
|  | 412 | "aliases" : syscall_aliases, | 
|  | 413 | "params"  : syscall_params, | 
|  | 414 | "decl"    : "%-15s  %s (%s);" % (return_type, syscall_func, params), | 
|  | 415 | "socketcall_id" : socketcall_id | 
|  | 416 | } | 
|  | 417 |  | 
|  | 418 | # Parse the architecture list. | 
|  | 419 | arch_list = line[pos_rparen+1:].strip() | 
|  | 420 | if arch_list == "all": | 
| Elliott Hughes | ae03b12 | 2019-09-17 16:37:05 -0700 | [diff] [blame] | 421 | for arch in SupportedArchitectures: | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 422 | t[arch] = True | 
|  | 423 | else: | 
| Elliott Hughes | bc6999f | 2021-02-03 13:13:57 -0800 | [diff] [blame] | 424 | for arch in arch_list.split(','): | 
| Elliott Hughes | 2b49904 | 2020-02-13 14:21:55 -0800 | [diff] [blame] | 425 | if arch == "lp32": | 
|  | 426 | for arch in SupportedArchitectures: | 
|  | 427 | if "64" not in arch: | 
|  | 428 | t[arch] = True | 
|  | 429 | elif arch == "lp64": | 
|  | 430 | for arch in SupportedArchitectures: | 
|  | 431 | if "64" in arch: | 
|  | 432 | t[arch] = True | 
|  | 433 | elif arch in SupportedArchitectures: | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 434 | t[arch] = True | 
|  | 435 | else: | 
|  | 436 | E("invalid syscall architecture '%s' in '%s'" % (arch, line)) | 
|  | 437 | return | 
|  | 438 |  | 
|  | 439 | self.syscalls.append(t) | 
|  | 440 |  | 
| Paul Lawrence | 7ea4090 | 2017-02-14 13:32:23 -0800 | [diff] [blame] | 441 | def parse_open_file(self, fp): | 
|  | 442 | for line in fp: | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 443 | self.lineno += 1 | 
|  | 444 | line = line.strip() | 
|  | 445 | if not line: continue | 
|  | 446 | if line[0] == '#': continue | 
|  | 447 | self.parse_line(line) | 
| Elliott Hughes | 1c1dfb8 | 2022-11-08 02:57:55 +0000 | [diff] [blame] | 448 | if self.errors: | 
|  | 449 | sys.exit(1) | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 450 |  | 
| Paul Lawrence | 7ea4090 | 2017-02-14 13:32:23 -0800 | [diff] [blame] | 451 | def parse_file(self, file_path): | 
| Paul Lawrence | 7ea4090 | 2017-02-14 13:32:23 -0800 | [diff] [blame] | 452 | with open(file_path) as fp: | 
| Alessio Balsini | 93d4f8b | 2017-04-11 18:27:29 +0200 | [diff] [blame] | 453 | self.parse_open_file(fp) | 
| Elliott Hughes | dc1fb70 | 2014-08-20 11:16:11 -0700 | [diff] [blame] | 454 |  | 
|  | 455 |  | 
| John Cater | e86e505 | 2019-09-26 14:47:03 -0400 | [diff] [blame] | 456 | def main(arch, syscall_file): | 
| Elliott Hughes | 782c485 | 2019-04-16 12:31:00 -0700 | [diff] [blame] | 457 | parser = SysCallsTxtParser() | 
| John Cater | e86e505 | 2019-09-26 14:47:03 -0400 | [diff] [blame] | 458 | parser.parse_file(syscall_file) | 
| The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 459 |  | 
| Elliott Hughes | 782c485 | 2019-04-16 12:31:00 -0700 | [diff] [blame] | 460 | for syscall in parser.syscalls: | 
|  | 461 | syscall["__NR_name"] = make__NR_name(syscall["name"]) | 
| Pavel Chupin | f12a18b | 2012-12-12 13:11:48 +0400 | [diff] [blame] | 462 |  | 
| Rupert Shuttleworth | e99df59 | 2021-04-15 06:09:04 -0400 | [diff] [blame] | 463 | if "arm" in syscall: | 
| Elliott Hughes | 782c485 | 2019-04-16 12:31:00 -0700 | [diff] [blame] | 464 | syscall["asm-arm"] = add_footer(32, arm_eabi_genstub(syscall), syscall) | 
| The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 465 |  | 
| Rupert Shuttleworth | e99df59 | 2021-04-15 06:09:04 -0400 | [diff] [blame] | 466 | if "arm64" in syscall: | 
| Elliott Hughes | 782c485 | 2019-04-16 12:31:00 -0700 | [diff] [blame] | 467 | syscall["asm-arm64"] = add_footer(64, arm64_genstub(syscall), syscall) | 
| The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 468 |  | 
| Elliott Hughes | 704772b | 2022-10-10 17:06:43 +0000 | [diff] [blame] | 469 | if "riscv64" in syscall: | 
|  | 470 | syscall["asm-riscv64"] = add_footer(64, riscv64_genstub(syscall), syscall) | 
|  | 471 |  | 
| Rupert Shuttleworth | e99df59 | 2021-04-15 06:09:04 -0400 | [diff] [blame] | 472 | if "x86" in syscall: | 
| Elliott Hughes | 782c485 | 2019-04-16 12:31:00 -0700 | [diff] [blame] | 473 | if syscall["socketcall_id"] >= 0: | 
|  | 474 | syscall["asm-x86"] = add_footer(32, x86_genstub_socketcall(syscall), syscall) | 
|  | 475 | else: | 
|  | 476 | syscall["asm-x86"] = add_footer(32, x86_genstub(syscall), syscall) | 
|  | 477 | elif syscall["socketcall_id"] >= 0: | 
|  | 478 | E("socketcall_id for dispatch syscalls is only supported for x86 in '%s'" % t) | 
|  | 479 | return | 
| The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 480 |  | 
| Rupert Shuttleworth | e99df59 | 2021-04-15 06:09:04 -0400 | [diff] [blame] | 481 | if "x86_64" in syscall: | 
| Elliott Hughes | 782c485 | 2019-04-16 12:31:00 -0700 | [diff] [blame] | 482 | syscall["asm-x86_64"] = add_footer(64, x86_64_genstub(syscall), syscall) | 
| The Android Open Source Project | 4e468ed | 2008-12-17 18:03:48 -0800 | [diff] [blame] | 483 |  | 
| Elliott Hughes | 782c485 | 2019-04-16 12:31:00 -0700 | [diff] [blame] | 484 | print("/* Generated by gensyscalls.py. Do not edit. */\n") | 
|  | 485 | print("#include <private/bionic_asm.h>\n") | 
|  | 486 | for syscall in parser.syscalls: | 
| Rupert Shuttleworth | e99df59 | 2021-04-15 06:09:04 -0400 | [diff] [blame] | 487 | if ("asm-%s" % arch) in syscall: | 
| Elliott Hughes | 782c485 | 2019-04-16 12:31:00 -0700 | [diff] [blame] | 488 | print(syscall["asm-%s" % arch]) | 
| Chris Dearman | 5043212 | 2014-02-05 16:59:23 -0800 | [diff] [blame] | 489 |  | 
| Tamas Petz | 19d66e6 | 2019-12-03 17:18:43 +0100 | [diff] [blame] | 490 | if arch == 'arm64': | 
|  | 491 | print('\nNOTE_GNU_PROPERTY()\n') | 
| The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 492 |  | 
| Paul Lawrence | eabc352 | 2016-11-11 11:33:42 -0800 | [diff] [blame] | 493 | if __name__ == "__main__": | 
| John Cater | e86e505 | 2019-09-26 14:47:03 -0400 | [diff] [blame] | 494 | if len(sys.argv) < 2: | 
| Elliott Hughes | bc6999f | 2021-02-03 13:13:57 -0800 | [diff] [blame] | 495 | print("Usage: gensyscalls.py ARCH SOURCE_FILE") | 
| John Cater | e86e505 | 2019-09-26 14:47:03 -0400 | [diff] [blame] | 496 | sys.exit(1) | 
|  | 497 |  | 
|  | 498 | arch = sys.argv[1] | 
|  | 499 | syscall_file = sys.argv[2] | 
|  | 500 | main(arch, syscall_file) |