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