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