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