Warning: That file was not part of the compilation database. It may have many parsing errors.

1/* Copyright (C) 1992-2022 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library. If not, see
16 <https://www.gnu.org/licenses/>. */
17
18#ifndef _LINUX_ARM_SYSDEP_H
19#define _LINUX_ARM_SYSDEP_H 1
20
21/* There is some commonality. */
22#include <sysdeps/unix/sysv/linux/sysdep.h>
23#include <sysdeps/unix/arm/sysdep.h>
24
25/* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */
26#include <dl-sysdep.h>
27
28#include <tls.h>
29
30/* For Linux we can use the system call table in the header file
31 /usr/include/asm/unistd.h
32 of the kernel. But these symbols do not follow the SYS_* syntax
33 so we have to redefine the `SYS_ify' macro here. */
34#undef SYS_ify
35#define SYS_ify(syscall_name) (__NR_##syscall_name)
36
37#include <bits/hwcap.h>
38
39#ifdef __ASSEMBLER__
40
41#ifndef ARCH_HAS_HARD_TP
42/* Internal macro calling the linux kernel kuser_get_tls helper.
43 Note that in thumb mode, a constant pool break is often out of range, so
44 we always expand the constant inline. */
45# ifdef __thumb2__
46# define GET_TLS_BODY \
47 movw r0, #0x0fe0; \
48 movt r0, #0xffff; \
49 blx r0
50# else
51# define GET_TLS_BODY \
52 mov r0, #0xffff0fff; /* Point to the high page. */ \
53 mov lr, pc; /* Save our return address. */ \
54 sub pc, r0, #31 /* Jump to the TLS entry. */
55# endif
56
57/* Helper to get the TLS base pointer. Save LR in TMP, return in R0,
58 and no other registers clobbered. TMP may be LR itself to indicate
59 that no save is necessary. */
60# undef GET_TLS
61# define GET_TLS(TMP) \
62 .ifnc TMP, lr; \
63 mov TMP, lr; \
64 cfi_register (lr, TMP); \
65 GET_TLS_BODY; \
66 mov lr, TMP; \
67 cfi_restore (lr); \
68 .else; \
69 GET_TLS_BODY; \
70 .endif
71#endif /* ARCH_HAS_HARD_TP */
72
73/* Linux uses a negative return value to indicate syscall errors,
74 unlike most Unices, which use the condition codes' carry flag.
75
76 Since version 2.1 the return value of a system call might be
77 negative even if the call succeeded. E.g., the `lseek' system call
78 might return a large offset. Therefore we must not anymore test
79 for < 0, but test for a real error by making sure the value in R0
80 is a real error number. Linus said he will make sure the no syscall
81 returns a value in -1 .. -4095 as a valid result so we can safely
82 test with -4095. */
83
84#undef PSEUDO
85#define PSEUDO(name, syscall_name, args) \
86 .text; \
87 ENTRY (name); \
88 DO_CALL (syscall_name, args); \
89 cmn r0, $4096;
90
91#define PSEUDO_RET \
92 it cc; \
93 RETINSTR(cc, lr); \
94 b PLTJMP(SYSCALL_ERROR)
95#undef ret
96#define ret PSEUDO_RET
97
98#undef PSEUDO_END
99#define PSEUDO_END(name) \
100 SYSCALL_ERROR_HANDLER; \
101 END (name)
102
103#undef PSEUDO_NOERRNO
104#define PSEUDO_NOERRNO(name, syscall_name, args) \
105 .text; \
106 ENTRY (name); \
107 DO_CALL (syscall_name, args);
108
109#define PSEUDO_RET_NOERRNO \
110 DO_RET (lr);
111
112#undef ret_NOERRNO
113#define ret_NOERRNO PSEUDO_RET_NOERRNO
114
115#undef PSEUDO_END_NOERRNO
116#define PSEUDO_END_NOERRNO(name) \
117 END (name)
118
119/* The function has to return the error code. */
120#undef PSEUDO_ERRVAL
121#define PSEUDO_ERRVAL(name, syscall_name, args) \
122 .text; \
123 ENTRY (name) \
124 DO_CALL (syscall_name, args); \
125 rsb r0, r0, #0
126
127#undef PSEUDO_END_ERRVAL
128#define PSEUDO_END_ERRVAL(name) \
129 END (name)
130
131#define ret_ERRVAL PSEUDO_RET_NOERRNO
132
133#if !IS_IN (libc)
134# define SYSCALL_ERROR __local_syscall_error
135# if RTLD_PRIVATE_ERRNO
136# define SYSCALL_ERROR_HANDLER \
137__local_syscall_error: \
138 rsb r0, r0, #0; \
139 LDST_PCREL(str, r0, r1, C_SYMBOL_NAME(rtld_errno)); \
140 mvn r0, #0; \
141 DO_RET(lr)
142# else
143# if defined(__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__)
144# define POP_PC \
145 pop { lr }; \
146 cfi_adjust_cfa_offset (-4); \
147 cfi_restore (lr); \
148 bx lr
149# else
150# define POP_PC pop { pc }
151# endif
152# define SYSCALL_ERROR_HANDLER \
153__local_syscall_error: \
154 push { lr }; \
155 cfi_adjust_cfa_offset (4); \
156 cfi_rel_offset (lr, 0); \
157 push { r0 }; \
158 cfi_adjust_cfa_offset (4); \
159 bl PLTJMP(C_SYMBOL_NAME(__errno_location)); \
160 pop { r1 }; \
161 cfi_adjust_cfa_offset (-4); \
162 rsb r1, r1, #0; \
163 str r1, [r0]; \
164 mvn r0, #0; \
165 POP_PC;
166# endif
167#else
168# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
169# define SYSCALL_ERROR __syscall_error
170#endif
171
172/* The ARM EABI user interface passes the syscall number in r7, instead
173 of in the swi. This is more efficient, because the kernel does not need
174 to fetch the swi from memory to find out the number; which can be painful
175 with separate I-cache and D-cache. Make sure to use 0 for the SWI
176 argument; otherwise the (optional) compatibility code for APCS binaries
177 may be invoked. */
178
179/* Linux takes system call args in registers:
180 arg 1 r0
181 arg 2 r1
182 arg 3 r2
183 arg 4 r3
184 arg 5 r4 (this is different from the APCS convention)
185 arg 6 r5
186 arg 7 r6
187
188 The compiler is going to form a call by coming here, through PSEUDO, with
189 arguments
190 syscall number in the DO_CALL macro
191 arg 1 r0
192 arg 2 r1
193 arg 3 r2
194 arg 4 r3
195 arg 5 [sp]
196 arg 6 [sp+4]
197 arg 7 [sp+8]
198
199 We need to shuffle values between R4..R6 and the stack so that the
200 caller's v1..v3 and stack frame are not corrupted, and the kernel
201 sees the right arguments.
202
203*/
204
205/* We must save and restore r7 (call-saved) for the syscall number.
206 We never make function calls from inside here (only potentially
207 signal handlers), so we do not bother with doubleword alignment.
208
209 Just like the APCS syscall convention, the EABI syscall convention uses
210 r0 through r6 for up to seven syscall arguments. None are ever passed to
211 the kernel on the stack, although incoming arguments are on the stack for
212 syscalls with five or more arguments.
213
214 The assembler will convert the literal pool load to a move for most
215 syscalls. */
216
217#undef DO_CALL
218#define DO_CALL(syscall_name, args) \
219 DOARGS_##args; \
220 ldr r7, =SYS_ify (syscall_name); \
221 swi 0x0; \
222 UNDOARGS_##args
223
224#undef DOARGS_0
225#define DOARGS_0 \
226 .fnstart; \
227 push { r7 }; \
228 cfi_adjust_cfa_offset (4); \
229 cfi_rel_offset (r7, 0); \
230 .save { r7 }
231#undef DOARGS_1
232#define DOARGS_1 DOARGS_0
233#undef DOARGS_2
234#define DOARGS_2 DOARGS_0
235#undef DOARGS_3
236#define DOARGS_3 DOARGS_0
237#undef DOARGS_4
238#define DOARGS_4 DOARGS_0
239#undef DOARGS_5
240#define DOARGS_5 \
241 .fnstart; \
242 push {r4, r7}; \
243 cfi_adjust_cfa_offset (8); \
244 cfi_rel_offset (r4, 0); \
245 cfi_rel_offset (r7, 4); \
246 .save { r4, r7 }; \
247 ldr r4, [sp, #8]
248#undef DOARGS_6
249#define DOARGS_6 \
250 .fnstart; \
251 mov ip, sp; \
252 push {r4, r5, r7}; \
253 cfi_adjust_cfa_offset (12); \
254 cfi_rel_offset (r4, 0); \
255 cfi_rel_offset (r5, 4); \
256 cfi_rel_offset (r7, 8); \
257 .save { r4, r5, r7 }; \
258 ldmia ip, {r4, r5}
259#undef DOARGS_7
260#define DOARGS_7 \
261 .fnstart; \
262 mov ip, sp; \
263 push {r4, r5, r6, r7}; \
264 cfi_adjust_cfa_offset (16); \
265 cfi_rel_offset (r4, 0); \
266 cfi_rel_offset (r5, 4); \
267 cfi_rel_offset (r6, 8); \
268 cfi_rel_offset (r7, 12); \
269 .save { r4, r5, r6, r7 }; \
270 ldmia ip, {r4, r5, r6}
271
272#undef UNDOARGS_0
273#define UNDOARGS_0 \
274 pop {r7}; \
275 cfi_adjust_cfa_offset (-4); \
276 cfi_restore (r7); \
277 .fnend
278#undef UNDOARGS_1
279#define UNDOARGS_1 UNDOARGS_0
280#undef UNDOARGS_2
281#define UNDOARGS_2 UNDOARGS_0
282#undef UNDOARGS_3
283#define UNDOARGS_3 UNDOARGS_0
284#undef UNDOARGS_4
285#define UNDOARGS_4 UNDOARGS_0
286#undef UNDOARGS_5
287#define UNDOARGS_5 \
288 pop {r4, r7}; \
289 cfi_adjust_cfa_offset (-8); \
290 cfi_restore (r4); \
291 cfi_restore (r7); \
292 .fnend
293#undef UNDOARGS_6
294#define UNDOARGS_6 \
295 pop {r4, r5, r7}; \
296 cfi_adjust_cfa_offset (-12); \
297 cfi_restore (r4); \
298 cfi_restore (r5); \
299 cfi_restore (r7); \
300 .fnend
301#undef UNDOARGS_7
302#define UNDOARGS_7 \
303 pop {r4, r5, r6, r7}; \
304 cfi_adjust_cfa_offset (-16); \
305 cfi_restore (r4); \
306 cfi_restore (r5); \
307 cfi_restore (r6); \
308 cfi_restore (r7); \
309 .fnend
310
311#else /* not __ASSEMBLER__ */
312
313#if defined(__thumb__)
314/* We can not expose the use of r7 to the compiler. GCC (as
315 of 4.5) uses r7 as the hard frame pointer for Thumb - although
316 for Thumb-2 it isn't obviously a better choice than r11.
317 And GCC does not support asms that conflict with the frame
318 pointer.
319
320 This would be easier if syscall numbers never exceeded 255,
321 but they do. For the moment the LOAD_ARGS_7 is sacrificed.
322 We can't use push/pop inside the asm because that breaks
323 unwinding (i.e. thread cancellation) for this frame. We can't
324 locally save and restore r7, because we do not know if this
325 function uses r7 or if it is our caller's r7; if it is our caller's,
326 then unwinding will fail higher up the stack. So we move the
327 syscall out of line and provide its own unwind information. */
328# undef INTERNAL_SYSCALL_RAW
329# define INTERNAL_SYSCALL_RAW(name, nr, args...) \
330 ({ \
331 register int _a1 asm ("a1"); \
332 int _nametmp = name; \
333 LOAD_ARGS_##nr (args) \
334 register int _name asm ("ip") = _nametmp; \
335 asm volatile ("bl __libc_do_syscall" \
336 : "=r" (_a1) \
337 : "r" (_name) ASM_ARGS_##nr \
338 : "memory", "lr"); \
339 _a1; })
340#else /* ARM */
341# undef INTERNAL_SYSCALL_RAW
342# define INTERNAL_SYSCALL_RAW(name, nr, args...) \
343 ({ \
344 register int _a1 asm ("r0"), _nr asm ("r7"); \
345 LOAD_ARGS_##nr (args) \
346 _nr = name; \
347 asm volatile ("swi 0x0 @ syscall " #name \
348 : "=r" (_a1) \
349 : "r" (_nr) ASM_ARGS_##nr \
350 : "memory"); \
351 _a1; })
352#endif
353
354#undef INTERNAL_SYSCALL
355#define INTERNAL_SYSCALL(name, nr, args...) \
356 INTERNAL_SYSCALL_RAW(SYS_ify(name), nr, args)
357
358#define VDSO_NAME "LINUX_2.6"
359#define VDSO_HASH 61765110
360
361/* List of system calls which are supported as vsyscalls. */
362#define HAVE_CLOCK_GETTIME_VSYSCALL "__vdso_clock_gettime"
363#define HAVE_CLOCK_GETTIME64_VSYSCALL "__vdso_clock_gettime64"
364#define HAVE_GETTIMEOFDAY_VSYSCALL "__vdso_gettimeofday"
365
366#define LOAD_ARGS_0()
367#define ASM_ARGS_0
368#define LOAD_ARGS_1(a1) \
369 int _a1tmp = (int) (a1); \
370 LOAD_ARGS_0 () \
371 _a1 = _a1tmp;
372#define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1)
373#define LOAD_ARGS_2(a1, a2) \
374 int _a2tmp = (int) (a2); \
375 LOAD_ARGS_1 (a1) \
376 register int _a2 asm ("a2") = _a2tmp;
377#define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2)
378#define LOAD_ARGS_3(a1, a2, a3) \
379 int _a3tmp = (int) (a3); \
380 LOAD_ARGS_2 (a1, a2) \
381 register int _a3 asm ("a3") = _a3tmp;
382#define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3)
383#define LOAD_ARGS_4(a1, a2, a3, a4) \
384 int _a4tmp = (int) (a4); \
385 LOAD_ARGS_3 (a1, a2, a3) \
386 register int _a4 asm ("a4") = _a4tmp;
387#define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4)
388#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \
389 int _v1tmp = (int) (a5); \
390 LOAD_ARGS_4 (a1, a2, a3, a4) \
391 register int _v1 asm ("v1") = _v1tmp;
392#define ASM_ARGS_5 ASM_ARGS_4, "r" (_v1)
393#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \
394 int _v2tmp = (int) (a6); \
395 LOAD_ARGS_5 (a1, a2, a3, a4, a5) \
396 register int _v2 asm ("v2") = _v2tmp;
397#define ASM_ARGS_6 ASM_ARGS_5, "r" (_v2)
398#ifndef __thumb__
399# define LOAD_ARGS_7(a1, a2, a3, a4, a5, a6, a7) \
400 int _v3tmp = (int) (a7); \
401 LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6) \
402 register int _v3 asm ("v3") = _v3tmp;
403# define ASM_ARGS_7 ASM_ARGS_6, "r" (_v3)
404#endif
405
406/* For EABI, non-constant syscalls are actually pretty easy... */
407#undef INTERNAL_SYSCALL_NCS
408#define INTERNAL_SYSCALL_NCS(number, nr, args...) \
409 INTERNAL_SYSCALL_RAW (number, nr, args)
410
411#define SINGLE_THREAD_BY_GLOBAL 1
412
413#endif /* __ASSEMBLER__ */
414
415#endif /* linux/arm/sysdep.h */
416

Warning: That file was not part of the compilation database. It may have many parsing errors.

source code of glibc/sysdeps/unix/sysv/linux/arm/sysdep.h