OLD | NEW |
| (Empty) |
1 /* Copyright (c) 2005-2008, Google Inc. | |
2 * All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 * | |
30 * --- | |
31 * Author: Markus Gutschke | |
32 */ | |
33 | |
34 /* This file includes Linux-specific support functions common to the | |
35 * coredumper and the thread lister; primarily, this is a collection | |
36 * of direct system calls, and a couple of symbols missing from | |
37 * standard header files. | |
38 * There are a few options that the including file can set to control | |
39 * the behavior of this file: | |
40 * | |
41 * SYS_CPLUSPLUS: | |
42 * The entire header file will normally be wrapped in 'extern "C" { }", | |
43 * making it suitable for compilation as both C and C++ source. If you | |
44 * do not want to do this, you can set the SYS_CPLUSPLUS macro to inhibit | |
45 * the wrapping. N.B. doing so will suppress inclusion of all prerequisite | |
46 * system header files, too. It is the caller's responsibility to provide | |
47 * the necessary definitions. | |
48 * | |
49 * SYS_ERRNO: | |
50 * All system calls will update "errno" unless overriden by setting the | |
51 * SYS_ERRNO macro prior to including this file. SYS_ERRNO should be | |
52 * an l-value. | |
53 * | |
54 * SYS_INLINE: | |
55 * New symbols will be defined "static inline", unless overridden by | |
56 * the SYS_INLINE macro. | |
57 * | |
58 * SYS_LINUX_SYSCALL_SUPPORT_H | |
59 * This macro is used to avoid multiple inclusions of this header file. | |
60 * If you need to include this file more than once, make sure to | |
61 * unset SYS_LINUX_SYSCALL_SUPPORT_H before each inclusion. | |
62 * | |
63 * SYS_PREFIX: | |
64 * New system calls will have a prefix of "sys_" unless overridden by | |
65 * the SYS_PREFIX macro. Valid values for this macro are [0..9] which | |
66 * results in prefixes "sys[0..9]_". It is also possible to set this | |
67 * macro to -1, which avoids all prefixes. | |
68 * | |
69 * This file defines a few internal symbols that all start with "LSS_". | |
70 * Do not access these symbols from outside this file. They are not part | |
71 * of the supported API. | |
72 */ | |
73 #ifndef SYS_LINUX_SYSCALL_SUPPORT_H | |
74 #define SYS_LINUX_SYSCALL_SUPPORT_H | |
75 | |
76 /* We currently only support x86-32, x86-64, ARM, MIPS, and PPC on Linux. | |
77 * Porting to other related platforms should not be difficult. | |
78 */ | |
79 #if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \ | |
80 defined(__mips__) || defined(__PPC__) || defined(__ARM_EABI__)) \ | |
81 && defined(__linux) | |
82 | |
83 #ifndef SYS_CPLUSPLUS | |
84 #ifdef __cplusplus | |
85 /* Some system header files in older versions of gcc neglect to properly | |
86 * handle being included from C++. As it appears to be harmless to have | |
87 * multiple nested 'extern "C"' blocks, just add another one here. | |
88 */ | |
89 extern "C" { | |
90 #endif | |
91 | |
92 #include <errno.h> | |
93 #include <signal.h> | |
94 #include <stdarg.h> | |
95 #include <string.h> | |
96 #include <sys/ptrace.h> | |
97 #include <sys/resource.h> | |
98 #include <sys/time.h> | |
99 #include <sys/types.h> | |
100 #include <syscall.h> | |
101 #include <unistd.h> | |
102 #include <linux/unistd.h> | |
103 #include <endian.h> | |
104 | |
105 #ifdef __mips__ | |
106 /* Include definitions of the ABI currently in use. */ | |
107 #include <sgidefs.h> | |
108 #endif | |
109 #endif | |
110 | |
111 /* As glibc often provides subtly incompatible data structures (and implicit | |
112 * wrapper functions that convert them), we provide our own kernel data | |
113 * structures for use by the system calls. | |
114 * These structures have been developed by using Linux 2.6.23 headers for | |
115 * reference. Note though, we do not care about exact API compatibility | |
116 * with the kernel, and in fact the kernel often does not have a single | |
117 * API that works across architectures. Instead, we try to mimic the glibc | |
118 * API where reasonable, and only guarantee ABI compatibility with the | |
119 * kernel headers. | |
120 * Most notably, here are a few changes that were made to the structures | |
121 * defined by kernel headers: | |
122 * | |
123 * - we only define structures, but not symbolic names for kernel data | |
124 * types. For the latter, we directly use the native C datatype | |
125 * (i.e. "unsigned" instead of "mode_t"). | |
126 * - in a few cases, it is possible to define identical structures for | |
127 * both 32bit (e.g. i386) and 64bit (e.g. x86-64) platforms by | |
128 * standardizing on the 64bit version of the data types. In particular, | |
129 * this means that we use "unsigned" where the 32bit headers say | |
130 * "unsigned long". | |
131 * - overall, we try to minimize the number of cases where we need to | |
132 * conditionally define different structures. | |
133 * - the "struct kernel_sigaction" class of structures have been | |
134 * modified to more closely mimic glibc's API by introducing an | |
135 * anonymous union for the function pointer. | |
136 * - a small number of field names had to have an underscore appended to | |
137 * them, because glibc defines a global macro by the same name. | |
138 */ | |
139 | |
140 /* include/linux/dirent.h */ | |
141 struct kernel_dirent64 { | |
142 unsigned long long d_ino; | |
143 long long d_off; | |
144 unsigned short d_reclen; | |
145 unsigned char d_type; | |
146 char d_name[256]; | |
147 }; | |
148 | |
149 /* include/linux/dirent.h */ | |
150 struct kernel_dirent { | |
151 long d_ino; | |
152 long d_off; | |
153 unsigned short d_reclen; | |
154 char d_name[256]; | |
155 }; | |
156 | |
157 /* include/linux/uio.h */ | |
158 struct kernel_iovec { | |
159 void *iov_base; | |
160 unsigned long iov_len; | |
161 }; | |
162 | |
163 /* include/linux/socket.h */ | |
164 struct kernel_msghdr { | |
165 void *msg_name; | |
166 int msg_namelen; | |
167 struct kernel_iovec*msg_iov; | |
168 unsigned long msg_iovlen; | |
169 void *msg_control; | |
170 unsigned long msg_controllen; | |
171 unsigned msg_flags; | |
172 }; | |
173 | |
174 /* include/asm-generic/poll.h */ | |
175 struct kernel_pollfd { | |
176 int fd; | |
177 short events; | |
178 short revents; | |
179 }; | |
180 | |
181 /* include/linux/resource.h */ | |
182 struct kernel_rlimit { | |
183 unsigned long rlim_cur; | |
184 unsigned long rlim_max; | |
185 }; | |
186 | |
187 /* include/linux/time.h */ | |
188 struct kernel_timespec { | |
189 long tv_sec; | |
190 long tv_nsec; | |
191 }; | |
192 | |
193 /* include/linux/time.h */ | |
194 struct kernel_timeval { | |
195 long tv_sec; | |
196 long tv_usec; | |
197 }; | |
198 | |
199 /* include/linux/resource.h */ | |
200 struct kernel_rusage { | |
201 struct kernel_timeval ru_utime; | |
202 struct kernel_timeval ru_stime; | |
203 long ru_maxrss; | |
204 long ru_ixrss; | |
205 long ru_idrss; | |
206 long ru_isrss; | |
207 long ru_minflt; | |
208 long ru_majflt; | |
209 long ru_nswap; | |
210 long ru_inblock; | |
211 long ru_oublock; | |
212 long ru_msgsnd; | |
213 long ru_msgrcv; | |
214 long ru_nsignals; | |
215 long ru_nvcsw; | |
216 long ru_nivcsw; | |
217 }; | |
218 | |
219 struct siginfo; | |
220 #if defined(__i386__) || defined(__ARM_EABI__) || defined(__ARM_ARCH_3__) \ | |
221 || defined(__PPC__) | |
222 | |
223 /* include/asm-{arm,i386,mips,ppc}/signal.h */ | |
224 struct kernel_old_sigaction { | |
225 union { | |
226 void (*sa_handler_)(int); | |
227 void (*sa_sigaction_)(int, struct siginfo *, void *); | |
228 }; | |
229 unsigned long sa_mask; | |
230 unsigned long sa_flags; | |
231 void (*sa_restorer)(void); | |
232 } __attribute__((packed,aligned(4))); | |
233 #elif (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) | |
234 #define kernel_old_sigaction kernel_sigaction | |
235 #endif | |
236 | |
237 /* Some kernel functions (e.g. sigaction() in 2.6.23) require that the | |
238 * exactly match the size of the signal set, even though the API was | |
239 * intended to be extensible. We define our own KERNEL_NSIG to deal with | |
240 * this. | |
241 * Please note that glibc provides signals [1.._NSIG-1], whereas the | |
242 * kernel (and this header) provides the range [1..KERNEL_NSIG]. The | |
243 * actual number of signals is obviously the same, but the constants | |
244 * differ by one. | |
245 */ | |
246 #ifdef __mips__ | |
247 #define KERNEL_NSIG 128 | |
248 #else | |
249 #define KERNEL_NSIG 64 | |
250 #endif | |
251 | |
252 /* include/asm-{arm,i386,mips,x86_64}/signal.h */ | |
253 struct kernel_sigset_t { | |
254 unsigned long sig[(KERNEL_NSIG + 8*sizeof(unsigned long) - 1)/ | |
255 (8*sizeof(unsigned long))]; | |
256 }; | |
257 | |
258 /* include/asm-{arm,i386,mips,x86_64,ppc}/signal.h */ | |
259 struct kernel_sigaction { | |
260 #ifdef __mips__ | |
261 unsigned long sa_flags; | |
262 union { | |
263 void (*sa_handler_)(int); | |
264 void (*sa_sigaction_)(int, struct siginfo *, void *); | |
265 }; | |
266 struct kernel_sigset_t sa_mask; | |
267 #else | |
268 union { | |
269 void (*sa_handler_)(int); | |
270 void (*sa_sigaction_)(int, struct siginfo *, void *); | |
271 }; | |
272 unsigned long sa_flags; | |
273 void (*sa_restorer)(void); | |
274 struct kernel_sigset_t sa_mask; | |
275 #endif | |
276 }; | |
277 | |
278 /* include/linux/socket.h */ | |
279 struct kernel_sockaddr { | |
280 unsigned short sa_family; | |
281 char sa_data[14]; | |
282 }; | |
283 | |
284 /* include/asm-{arm,i386,mips,ppc}/stat.h */ | |
285 #ifdef __mips__ | |
286 #if _MIPS_SIM == _MIPS_SIM_ABI64 | |
287 struct kernel_stat { | |
288 #else | |
289 struct kernel_stat64 { | |
290 #endif | |
291 unsigned st_dev; | |
292 unsigned __pad0[3]; | |
293 unsigned long long st_ino; | |
294 unsigned st_mode; | |
295 unsigned st_nlink; | |
296 unsigned st_uid; | |
297 unsigned st_gid; | |
298 unsigned st_rdev; | |
299 unsigned __pad1[3]; | |
300 long long st_size; | |
301 unsigned st_atime_; | |
302 unsigned st_atime_nsec_; | |
303 unsigned st_mtime_; | |
304 unsigned st_mtime_nsec_; | |
305 unsigned st_ctime_; | |
306 unsigned st_ctime_nsec_; | |
307 unsigned st_blksize; | |
308 unsigned __pad2; | |
309 unsigned long long st_blocks; | |
310 }; | |
311 #elif defined __PPC__ | |
312 struct kernel_stat64 { | |
313 unsigned long long st_dev; | |
314 unsigned long long st_ino; | |
315 unsigned st_mode; | |
316 unsigned st_nlink; | |
317 unsigned st_uid; | |
318 unsigned st_gid; | |
319 unsigned long long st_rdev; | |
320 unsigned short int __pad2; | |
321 long long st_size; | |
322 long st_blksize; | |
323 long long st_blocks; | |
324 long st_atime_; | |
325 unsigned long st_atime_nsec_; | |
326 long st_mtime_; | |
327 unsigned long st_mtime_nsec_; | |
328 long st_ctime_; | |
329 unsigned long st_ctime_nsec_; | |
330 unsigned long __unused4; | |
331 unsigned long __unused5; | |
332 }; | |
333 #else | |
334 struct kernel_stat64 { | |
335 unsigned long long st_dev; | |
336 unsigned char __pad0[4]; | |
337 unsigned __st_ino; | |
338 unsigned st_mode; | |
339 unsigned st_nlink; | |
340 unsigned st_uid; | |
341 unsigned st_gid; | |
342 unsigned long long st_rdev; | |
343 unsigned char __pad3[4]; | |
344 long long st_size; | |
345 unsigned st_blksize; | |
346 unsigned long long st_blocks; | |
347 unsigned st_atime_; | |
348 unsigned st_atime_nsec_; | |
349 unsigned st_mtime_; | |
350 unsigned st_mtime_nsec_; | |
351 unsigned st_ctime_; | |
352 unsigned st_ctime_nsec_; | |
353 unsigned long long st_ino; | |
354 }; | |
355 #endif | |
356 | |
357 /* include/asm-{arm,i386,mips,x86_64,ppc}/stat.h */ | |
358 #if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) | |
359 struct kernel_stat { | |
360 /* The kernel headers suggest that st_dev and st_rdev should be 32bit | |
361 * quantities encoding 12bit major and 20bit minor numbers in an interleaved | |
362 * format. In reality, we do not see useful data in the top bits. So, | |
363 * we'll leave the padding in here, until we find a better solution. | |
364 */ | |
365 unsigned short st_dev; | |
366 short pad1; | |
367 unsigned st_ino; | |
368 unsigned short st_mode; | |
369 unsigned short st_nlink; | |
370 unsigned short st_uid; | |
371 unsigned short st_gid; | |
372 unsigned short st_rdev; | |
373 short pad2; | |
374 unsigned st_size; | |
375 unsigned st_blksize; | |
376 unsigned st_blocks; | |
377 unsigned st_atime_; | |
378 unsigned st_atime_nsec_; | |
379 unsigned st_mtime_; | |
380 unsigned st_mtime_nsec_; | |
381 unsigned st_ctime_; | |
382 unsigned st_ctime_nsec_; | |
383 unsigned __unused4; | |
384 unsigned __unused5; | |
385 }; | |
386 #elif defined(__x86_64__) | |
387 struct kernel_stat { | |
388 unsigned long st_dev; | |
389 unsigned long st_ino; | |
390 unsigned long st_nlink; | |
391 unsigned st_mode; | |
392 unsigned st_uid; | |
393 unsigned st_gid; | |
394 unsigned __pad0; | |
395 unsigned long st_rdev; | |
396 long st_size; | |
397 long st_blksize; | |
398 long st_blocks; | |
399 unsigned long st_atime_; | |
400 unsigned long st_atime_nsec_; | |
401 unsigned long st_mtime_; | |
402 unsigned long st_mtime_nsec_; | |
403 unsigned long st_ctime_; | |
404 unsigned long st_ctime_nsec_; | |
405 long __unused[3]; | |
406 }; | |
407 #elif defined(__PPC__) | |
408 struct kernel_stat { | |
409 unsigned st_dev; | |
410 unsigned long st_ino; // ino_t | |
411 unsigned long st_mode; // mode_t | |
412 unsigned short st_nlink; // nlink_t | |
413 unsigned st_uid; // uid_t | |
414 unsigned st_gid; // gid_t | |
415 unsigned st_rdev; | |
416 long st_size; // off_t | |
417 unsigned long st_blksize; | |
418 unsigned long st_blocks; | |
419 unsigned long st_atime_; | |
420 unsigned long st_atime_nsec_; | |
421 unsigned long st_mtime_; | |
422 unsigned long st_mtime_nsec_; | |
423 unsigned long st_ctime_; | |
424 unsigned long st_ctime_nsec_; | |
425 unsigned long __unused4; | |
426 unsigned long __unused5; | |
427 }; | |
428 #elif (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64) | |
429 struct kernel_stat { | |
430 unsigned st_dev; | |
431 int st_pad1[3]; | |
432 unsigned st_ino; | |
433 unsigned st_mode; | |
434 unsigned st_nlink; | |
435 unsigned st_uid; | |
436 unsigned st_gid; | |
437 unsigned st_rdev; | |
438 int st_pad2[2]; | |
439 long st_size; | |
440 int st_pad3; | |
441 long st_atime_; | |
442 long st_atime_nsec_; | |
443 long st_mtime_; | |
444 long st_mtime_nsec_; | |
445 long st_ctime_; | |
446 long st_ctime_nsec_; | |
447 int st_blksize; | |
448 int st_blocks; | |
449 int st_pad4[14]; | |
450 }; | |
451 #endif | |
452 | |
453 /* include/asm-{arm,i386,mips,x86_64,ppc}/statfs.h */ | |
454 #ifdef __mips__ | |
455 #if _MIPS_SIM != _MIPS_SIM_ABI64 | |
456 struct kernel_statfs64 { | |
457 unsigned long f_type; | |
458 unsigned long f_bsize; | |
459 unsigned long f_frsize; | |
460 unsigned long __pad; | |
461 unsigned long long f_blocks; | |
462 unsigned long long f_bfree; | |
463 unsigned long long f_files; | |
464 unsigned long long f_ffree; | |
465 unsigned long long f_bavail; | |
466 struct { int val[2]; } f_fsid; | |
467 unsigned long f_namelen; | |
468 unsigned long f_spare[6]; | |
469 }; | |
470 #endif | |
471 #elif !defined(__x86_64__) | |
472 struct kernel_statfs64 { | |
473 unsigned long f_type; | |
474 unsigned long f_bsize; | |
475 unsigned long long f_blocks; | |
476 unsigned long long f_bfree; | |
477 unsigned long long f_bavail; | |
478 unsigned long long f_files; | |
479 unsigned long long f_ffree; | |
480 struct { int val[2]; } f_fsid; | |
481 unsigned long f_namelen; | |
482 unsigned long f_frsize; | |
483 unsigned long f_spare[5]; | |
484 }; | |
485 #endif | |
486 | |
487 /* include/asm-{arm,i386,mips,x86_64,ppc,generic}/statfs.h */ | |
488 #ifdef __mips__ | |
489 struct kernel_statfs { | |
490 long f_type; | |
491 long f_bsize; | |
492 long f_frsize; | |
493 long f_blocks; | |
494 long f_bfree; | |
495 long f_files; | |
496 long f_ffree; | |
497 long f_bavail; | |
498 struct { int val[2]; } f_fsid; | |
499 long f_namelen; | |
500 long f_spare[6]; | |
501 }; | |
502 #else | |
503 struct kernel_statfs { | |
504 /* x86_64 actually defines all these fields as signed, whereas all other */ | |
505 /* platforms define them as unsigned. Leaving them at unsigned should not */ | |
506 /* cause any problems. */ | |
507 unsigned long f_type; | |
508 unsigned long f_bsize; | |
509 unsigned long f_blocks; | |
510 unsigned long f_bfree; | |
511 unsigned long f_bavail; | |
512 unsigned long f_files; | |
513 unsigned long f_ffree; | |
514 struct { int val[2]; } f_fsid; | |
515 unsigned long f_namelen; | |
516 unsigned long f_frsize; | |
517 unsigned long f_spare[5]; | |
518 }; | |
519 #endif | |
520 | |
521 | |
522 /* Definitions missing from the standard header files */ | |
523 #ifndef O_DIRECTORY | |
524 #if defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) | |
525 #define O_DIRECTORY 0040000 | |
526 #else | |
527 #define O_DIRECTORY 0200000 | |
528 #endif | |
529 #endif | |
530 #ifndef NT_PRXFPREG | |
531 #define NT_PRXFPREG 0x46e62b7f | |
532 #endif | |
533 #ifndef PTRACE_GETFPXREGS | |
534 #define PTRACE_GETFPXREGS ((enum __ptrace_request)18) | |
535 #endif | |
536 #ifndef PR_GET_DUMPABLE | |
537 #define PR_GET_DUMPABLE 3 | |
538 #endif | |
539 #ifndef PR_SET_DUMPABLE | |
540 #define PR_SET_DUMPABLE 4 | |
541 #endif | |
542 #ifndef AT_FDCWD | |
543 #define AT_FDCWD (-100) | |
544 #endif | |
545 #ifndef AT_SYMLINK_NOFOLLOW | |
546 #define AT_SYMLINK_NOFOLLOW 0x100 | |
547 #endif | |
548 #ifndef AT_REMOVEDIR | |
549 #define AT_REMOVEDIR 0x200 | |
550 #endif | |
551 #ifndef MREMAP_FIXED | |
552 #define MREMAP_FIXED 2 | |
553 #endif | |
554 #ifndef SA_RESTORER | |
555 #define SA_RESTORER 0x04000000 | |
556 #endif | |
557 | |
558 #if defined(__i386__) | |
559 #ifndef __NR_setresuid | |
560 #define __NR_setresuid 164 | |
561 #define __NR_setresgid 170 | |
562 #endif | |
563 #ifndef __NR_rt_sigaction | |
564 #define __NR_rt_sigaction 174 | |
565 #define __NR_rt_sigprocmask 175 | |
566 #define __NR_rt_sigpending 176 | |
567 #define __NR_rt_sigsuspend 179 | |
568 #endif | |
569 #ifndef __NR_pread64 | |
570 #define __NR_pread64 180 | |
571 #endif | |
572 #ifndef __NR_pwrite64 | |
573 #define __NR_pwrite64 181 | |
574 #endif | |
575 #ifndef __NR_ugetrlimit | |
576 #define __NR_ugetrlimit 191 | |
577 #endif | |
578 #ifndef __NR_stat64 | |
579 #define __NR_stat64 195 | |
580 #endif | |
581 #ifndef __NR_fstat64 | |
582 #define __NR_fstat64 197 | |
583 #endif | |
584 #ifndef __NR_setresuid32 | |
585 #define __NR_setresuid32 208 | |
586 #define __NR_setresgid32 210 | |
587 #endif | |
588 #ifndef __NR_setfsuid32 | |
589 #define __NR_setfsuid32 215 | |
590 #define __NR_setfsgid32 216 | |
591 #endif | |
592 #ifndef __NR_getdents64 | |
593 #define __NR_getdents64 220 | |
594 #endif | |
595 #ifndef __NR_gettid | |
596 #define __NR_gettid 224 | |
597 #endif | |
598 #ifndef __NR_readahead | |
599 #define __NR_readahead 225 | |
600 #endif | |
601 #ifndef __NR_setxattr | |
602 #define __NR_setxattr 226 | |
603 #endif | |
604 #ifndef __NR_lsetxattr | |
605 #define __NR_lsetxattr 227 | |
606 #endif | |
607 #ifndef __NR_getxattr | |
608 #define __NR_getxattr 229 | |
609 #endif | |
610 #ifndef __NR_lgetxattr | |
611 #define __NR_lgetxattr 230 | |
612 #endif | |
613 #ifndef __NR_futex | |
614 #define __NR_futex 240 | |
615 #endif | |
616 #ifndef __NR_sched_setaffinity | |
617 #define __NR_sched_setaffinity 241 | |
618 #define __NR_sched_getaffinity 242 | |
619 #endif | |
620 #ifndef __NR_set_tid_address | |
621 #define __NR_set_tid_address 258 | |
622 #endif | |
623 #ifndef __NR_statfs64 | |
624 #define __NR_statfs64 268 | |
625 #endif | |
626 #ifndef __NR_fstatfs64 | |
627 #define __NR_fstatfs64 269 | |
628 #endif | |
629 #ifndef __NR_fadvise64_64 | |
630 #define __NR_fadvise64_64 272 | |
631 #endif | |
632 #ifndef __NR_openat | |
633 #define __NR_openat 295 | |
634 #endif | |
635 #ifndef __NR_fstatat64 | |
636 #define __NR_fstatat64 300 | |
637 #endif | |
638 #ifndef __NR_unlinkat | |
639 #define __NR_unlinkat 301 | |
640 #endif | |
641 #ifndef __NR_move_pages | |
642 #define __NR_move_pages 317 | |
643 #endif | |
644 /* End of i386 definitions */ | |
645 #elif defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) | |
646 #ifndef __NR_setresuid | |
647 #define __NR_setresuid (__NR_SYSCALL_BASE + 164) | |
648 #define __NR_setresgid (__NR_SYSCALL_BASE + 170) | |
649 #endif | |
650 #ifndef __NR_rt_sigaction | |
651 #define __NR_rt_sigaction (__NR_SYSCALL_BASE + 174) | |
652 #define __NR_rt_sigprocmask (__NR_SYSCALL_BASE + 175) | |
653 #define __NR_rt_sigpending (__NR_SYSCALL_BASE + 176) | |
654 #define __NR_rt_sigsuspend (__NR_SYSCALL_BASE + 179) | |
655 #endif | |
656 #ifndef __NR_pread64 | |
657 #define __NR_pread64 (__NR_SYSCALL_BASE + 180) | |
658 #endif | |
659 #ifndef __NR_pwrite64 | |
660 #define __NR_pwrite64 (__NR_SYSCALL_BASE + 181) | |
661 #endif | |
662 #ifndef __NR_ugetrlimit | |
663 #define __NR_ugetrlimit (__NR_SYSCALL_BASE + 191) | |
664 #endif | |
665 #ifndef __NR_stat64 | |
666 #define __NR_stat64 (__NR_SYSCALL_BASE + 195) | |
667 #endif | |
668 #ifndef __NR_fstat64 | |
669 #define __NR_fstat64 (__NR_SYSCALL_BASE + 197) | |
670 #endif | |
671 #ifndef __NR_setresuid32 | |
672 #define __NR_setresuid32 (__NR_SYSCALL_BASE + 208) | |
673 #define __NR_setresgid32 (__NR_SYSCALL_BASE + 210) | |
674 #endif | |
675 #ifndef __NR_setfsuid32 | |
676 #define __NR_setfsuid32 (__NR_SYSCALL_BASE + 215) | |
677 #define __NR_setfsgid32 (__NR_SYSCALL_BASE + 216) | |
678 #endif | |
679 #ifndef __NR_getdents64 | |
680 #define __NR_getdents64 (__NR_SYSCALL_BASE + 217) | |
681 #endif | |
682 #ifndef __NR_gettid | |
683 #define __NR_gettid (__NR_SYSCALL_BASE + 224) | |
684 #endif | |
685 #ifndef __NR_readahead | |
686 #define __NR_readahead (__NR_SYSCALL_BASE + 225) | |
687 #endif | |
688 #ifndef __NR_setxattr | |
689 #define __NR_setxattr (__NR_SYSCALL_BASE + 226) | |
690 #endif | |
691 #ifndef __NR_lsetxattr | |
692 #define __NR_lsetxattr (__NR_SYSCALL_BASE + 227) | |
693 #endif | |
694 #ifndef __NR_getxattr | |
695 #define __NR_getxattr (__NR_SYSCALL_BASE + 229) | |
696 #endif | |
697 #ifndef __NR_lgetxattr | |
698 #define __NR_lgetxattr (__NR_SYSCALL_BASE + 230) | |
699 #endif | |
700 #ifndef __NR_futex | |
701 #define __NR_futex (__NR_SYSCALL_BASE + 240) | |
702 #endif | |
703 #ifndef __NR_sched_setaffinity | |
704 #define __NR_sched_setaffinity (__NR_SYSCALL_BASE + 241) | |
705 #define __NR_sched_getaffinity (__NR_SYSCALL_BASE + 242) | |
706 #endif | |
707 #ifndef __NR_set_tid_address | |
708 #define __NR_set_tid_address (__NR_SYSCALL_BASE + 256) | |
709 #endif | |
710 #ifndef __NR_statfs64 | |
711 #define __NR_statfs64 (__NR_SYSCALL_BASE + 266) | |
712 #endif | |
713 #ifndef __NR_fstatfs64 | |
714 #define __NR_fstatfs64 (__NR_SYSCALL_BASE + 267) | |
715 #endif | |
716 #ifndef __NR_move_pages | |
717 #define __NR_move_pages (__NR_SYSCALL_BASE + 344) | |
718 #endif | |
719 /* End of ARM 3/EABI definitions
*/ | |
720 #elif defined(__x86_64__) | |
721 #ifndef __NR_setresuid | |
722 #define __NR_setresuid 117 | |
723 #define __NR_setresgid 119 | |
724 #endif | |
725 #ifndef __NR_gettid | |
726 #define __NR_gettid 186 | |
727 #endif | |
728 #ifndef __NR_readahead | |
729 #define __NR_readahead 187 | |
730 #endif | |
731 #ifndef __NR_setxattr | |
732 #define __NR_setxattr 188 | |
733 #endif | |
734 #ifndef __NR_lsetxattr | |
735 #define __NR_lsetxattr 189 | |
736 #endif | |
737 #ifndef __NR_getxattr | |
738 #define __NR_getxattr 191 | |
739 #endif | |
740 #ifndef __NR_lgetxattr | |
741 #define __NR_lgetxattr 192 | |
742 #endif | |
743 #ifndef __NR_futex | |
744 #define __NR_futex 202 | |
745 #endif | |
746 #ifndef __NR_sched_setaffinity | |
747 #define __NR_sched_setaffinity 203 | |
748 #define __NR_sched_getaffinity 204 | |
749 #endif | |
750 #ifndef __NR_getdents64 | |
751 #define __NR_getdents64 217 | |
752 #endif | |
753 #ifndef __NR_set_tid_address | |
754 #define __NR_set_tid_address 218 | |
755 #endif | |
756 #ifndef __NR_fadvise64 | |
757 #define __NR_fadvise64 221 | |
758 #endif | |
759 #ifndef __NR_openat | |
760 #define __NR_openat 257 | |
761 #endif | |
762 #ifndef __NR_newfstatat | |
763 #define __NR_newfstatat 262 | |
764 #endif | |
765 #ifndef __NR_unlinkat | |
766 #define __NR_unlinkat 263 | |
767 #endif | |
768 #ifndef __NR_move_pages | |
769 #define __NR_move_pages 279 | |
770 #endif | |
771 /* End of x86-64 definitions */ | |
772 #elif defined(__mips__) | |
773 #if _MIPS_SIM == _MIPS_SIM_ABI32 | |
774 #ifndef __NR_setresuid | |
775 #define __NR_setresuid (__NR_Linux + 185) | |
776 #define __NR_setresgid (__NR_Linux + 190) | |
777 #endif | |
778 #ifndef __NR_rt_sigaction | |
779 #define __NR_rt_sigaction (__NR_Linux + 194) | |
780 #define __NR_rt_sigprocmask (__NR_Linux + 195) | |
781 #define __NR_rt_sigpending (__NR_Linux + 196) | |
782 #define __NR_rt_sigsuspend (__NR_Linux + 199) | |
783 #endif | |
784 #ifndef __NR_pread64 | |
785 #define __NR_pread64 (__NR_Linux + 200) | |
786 #endif | |
787 #ifndef __NR_pwrite64 | |
788 #define __NR_pwrite64 (__NR_Linux + 201) | |
789 #endif | |
790 #ifndef __NR_stat64 | |
791 #define __NR_stat64 (__NR_Linux + 213) | |
792 #endif | |
793 #ifndef __NR_fstat64 | |
794 #define __NR_fstat64 (__NR_Linux + 215) | |
795 #endif | |
796 #ifndef __NR_getdents64 | |
797 #define __NR_getdents64 (__NR_Linux + 219) | |
798 #endif | |
799 #ifndef __NR_gettid | |
800 #define __NR_gettid (__NR_Linux + 222) | |
801 #endif | |
802 #ifndef __NR_readahead | |
803 #define __NR_readahead (__NR_Linux + 223) | |
804 #endif | |
805 #ifndef __NR_setxattr | |
806 #define __NR_setxattr (__NR_Linux + 224) | |
807 #endif | |
808 #ifndef __NR_lsetxattr | |
809 #define __NR_lsetxattr (__NR_Linux + 225) | |
810 #endif | |
811 #ifndef __NR_getxattr | |
812 #define __NR_getxattr (__NR_Linux + 227) | |
813 #endif | |
814 #ifndef __NR_lgetxattr | |
815 #define __NR_lgetxattr (__NR_Linux + 228) | |
816 #endif | |
817 #ifndef __NR_futex | |
818 #define __NR_futex (__NR_Linux + 238) | |
819 #endif | |
820 #ifndef __NR_sched_setaffinity | |
821 #define __NR_sched_setaffinity (__NR_Linux + 239) | |
822 #define __NR_sched_getaffinity (__NR_Linux + 240) | |
823 #endif | |
824 #ifndef __NR_set_tid_address | |
825 #define __NR_set_tid_address (__NR_Linux + 252) | |
826 #endif | |
827 #ifndef __NR_statfs64 | |
828 #define __NR_statfs64 (__NR_Linux + 255) | |
829 #endif | |
830 #ifndef __NR_fstatfs64 | |
831 #define __NR_fstatfs64 (__NR_Linux + 256) | |
832 #endif | |
833 #ifndef __NR_openat | |
834 #define __NR_openat (__NR_Linux + 288) | |
835 #endif | |
836 #ifndef __NR_fstatat | |
837 #define __NR_fstatat (__NR_Linux + 293) | |
838 #endif | |
839 #ifndef __NR_unlinkat | |
840 #define __NR_unlinkat (__NR_Linux + 294) | |
841 #endif | |
842 #ifndef __NR_move_pages | |
843 #define __NR_move_pages (__NR_Linux + 308) | |
844 #endif | |
845 /* End of MIPS (old 32bit API) definitions */ | |
846 #elif _MIPS_SIM == _MIPS_SIM_ABI64 | |
847 #ifndef __NR_setresuid | |
848 #define __NR_setresuid (__NR_Linux + 115) | |
849 #define __NR_setresgid (__NR_Linux + 117) | |
850 #endif | |
851 #ifndef __NR_gettid | |
852 #define __NR_gettid (__NR_Linux + 178) | |
853 #endif | |
854 #ifndef __NR_readahead | |
855 #define __NR_readahead (__NR_Linux + 179) | |
856 #endif | |
857 #ifndef __NR_setxattr | |
858 #define __NR_setxattr (__NR_Linux + 180) | |
859 #endif | |
860 #ifndef __NR_lsetxattr | |
861 #define __NR_lsetxattr (__NR_Linux + 181) | |
862 #endif | |
863 #ifndef __NR_getxattr | |
864 #define __NR_getxattr (__NR_Linux + 183) | |
865 #endif | |
866 #ifndef __NR_lgetxattr | |
867 #define __NR_lgetxattr (__NR_Linux + 184) | |
868 #endif | |
869 #ifndef __NR_futex | |
870 #define __NR_futex (__NR_Linux + 194) | |
871 #endif | |
872 #ifndef __NR_sched_setaffinity | |
873 #define __NR_sched_setaffinity (__NR_Linux + 195) | |
874 #define __NR_sched_getaffinity (__NR_Linux + 196) | |
875 #endif | |
876 #ifndef __NR_set_tid_address | |
877 #define __NR_set_tid_address (__NR_Linux + 212) | |
878 #endif | |
879 #ifndef __NR_openat | |
880 #define __NR_openat (__NR_Linux + 247) | |
881 #endif | |
882 #ifndef __NR_fstatat | |
883 #define __NR_fstatat (__NR_Linux + 252) | |
884 #endif | |
885 #ifndef __NR_unlinkat | |
886 #define __NR_unlinkat (__NR_Linux + 253) | |
887 #endif | |
888 #ifndef __NR_move_pages | |
889 #define __NR_move_pages (__NR_Linux + 267) | |
890 #endif | |
891 /* End of MIPS (64bit API) definitions */ | |
892 #else | |
893 #ifndef __NR_setresuid | |
894 #define __NR_setresuid (__NR_Linux + 115) | |
895 #define __NR_setresgid (__NR_Linux + 117) | |
896 #endif | |
897 #ifndef __NR_gettid | |
898 #define __NR_gettid (__NR_Linux + 178) | |
899 #endif | |
900 #ifndef __NR_readahead | |
901 #define __NR_readahead (__NR_Linux + 179) | |
902 #endif | |
903 #ifndef __NR_setxattr | |
904 #define __NR_setxattr (__NR_Linux + 180) | |
905 #endif | |
906 #ifndef __NR_lsetxattr | |
907 #define __NR_lsetxattr (__NR_Linux + 181) | |
908 #endif | |
909 #ifndef __NR_getxattr | |
910 #define __NR_getxattr (__NR_Linux + 183) | |
911 #endif | |
912 #ifndef __NR_lgetxattr | |
913 #define __NR_lgetxattr (__NR_Linux + 184) | |
914 #endif | |
915 #ifndef __NR_futex | |
916 #define __NR_futex (__NR_Linux + 194) | |
917 #endif | |
918 #ifndef __NR_sched_setaffinity | |
919 #define __NR_sched_setaffinity (__NR_Linux + 195) | |
920 #define __NR_sched_getaffinity (__NR_Linux + 196) | |
921 #endif | |
922 #ifndef __NR_set_tid_address | |
923 #define __NR_set_tid_address (__NR_Linux + 213) | |
924 #endif | |
925 #ifndef __NR_statfs64 | |
926 #define __NR_statfs64 (__NR_Linux + 217) | |
927 #endif | |
928 #ifndef __NR_fstatfs64 | |
929 #define __NR_fstatfs64 (__NR_Linux + 218) | |
930 #endif | |
931 #ifndef __NR_openat | |
932 #define __NR_openat (__NR_Linux + 251) | |
933 #endif | |
934 #ifndef __NR_fstatat | |
935 #define __NR_fstatat (__NR_Linux + 256) | |
936 #endif | |
937 #ifndef __NR_unlinkat | |
938 #define __NR_unlinkat (__NR_Linux + 257) | |
939 #endif | |
940 #ifndef __NR_move_pages | |
941 #define __NR_move_pages (__NR_Linux + 271) | |
942 #endif | |
943 /* End of MIPS (new 32bit API) definitions */ | |
944 #endif | |
945 /* End of MIPS definitions */ | |
946 #elif defined(__PPC__) | |
947 #ifndef __NR_setfsuid | |
948 #define __NR_setfsuid 138 | |
949 #define __NR_setfsgid 139 | |
950 #endif | |
951 #ifndef __NR_setresuid | |
952 #define __NR_setresuid 164 | |
953 #define __NR_setresgid 169 | |
954 #endif | |
955 #ifndef __NR_rt_sigaction | |
956 #define __NR_rt_sigaction 173 | |
957 #define __NR_rt_sigprocmask 174 | |
958 #define __NR_rt_sigpending 175 | |
959 #define __NR_rt_sigsuspend 178 | |
960 #endif | |
961 #ifndef __NR_pread64 | |
962 #define __NR_pread64 179 | |
963 #endif | |
964 #ifndef __NR_pwrite64 | |
965 #define __NR_pwrite64 180 | |
966 #endif | |
967 #ifndef __NR_ugetrlimit | |
968 #define __NR_ugetrlimit 190 | |
969 #endif | |
970 #ifndef __NR_readahead | |
971 #define __NR_readahead 191 | |
972 #endif | |
973 #ifndef __NR_stat64 | |
974 #define __NR_stat64 195 | |
975 #endif | |
976 #ifndef __NR_fstat64 | |
977 #define __NR_fstat64 197 | |
978 #endif | |
979 #ifndef __NR_getdents64 | |
980 #define __NR_getdents64 202 | |
981 #endif | |
982 #ifndef __NR_gettid | |
983 #define __NR_gettid 207 | |
984 #endif | |
985 #ifndef __NR_setxattr | |
986 #define __NR_setxattr 209 | |
987 #endif | |
988 #ifndef __NR_lsetxattr | |
989 #define __NR_lsetxattr 210 | |
990 #endif | |
991 #ifndef __NR_getxattr | |
992 #define __NR_getxattr 212 | |
993 #endif | |
994 #ifndef __NR_lgetxattr | |
995 #define __NR_lgetxattr 213 | |
996 #endif | |
997 #ifndef __NR_futex | |
998 #define __NR_futex 221 | |
999 #endif | |
1000 #ifndef __NR_sched_setaffinity | |
1001 #define __NR_sched_setaffinity 222 | |
1002 #define __NR_sched_getaffinity 223 | |
1003 #endif | |
1004 #ifndef __NR_set_tid_address | |
1005 #define __NR_set_tid_address 232 | |
1006 #endif | |
1007 #ifndef __NR_statfs64 | |
1008 #define __NR_statfs64 252 | |
1009 #endif | |
1010 #ifndef __NR_fstatfs64 | |
1011 #define __NR_fstatfs64 253 | |
1012 #endif | |
1013 #ifndef __NR_fadvise64_64 | |
1014 #define __NR_fadvise64_64 254 | |
1015 #endif | |
1016 #ifndef __NR_openat | |
1017 #define __NR_openat 286 | |
1018 #endif | |
1019 #ifndef __NR_fstatat64 | |
1020 #define __NR_fstatat64 291 | |
1021 #endif | |
1022 #ifndef __NR_unlinkat | |
1023 #define __NR_unlinkat 292 | |
1024 #endif | |
1025 #ifndef __NR_move_pages | |
1026 #define __NR_move_pages 301 | |
1027 #endif | |
1028 /* End of powerpc defininitions */ | |
1029 #endif | |
1030 | |
1031 | |
1032 /* After forking, we must make sure to only call system calls. */ | |
1033 #if __BOUNDED_POINTERS__ | |
1034 #error "Need to port invocations of syscalls for bounded ptrs" | |
1035 #else | |
1036 /* The core dumper and the thread lister get executed after threads | |
1037 * have been suspended. As a consequence, we cannot call any functions | |
1038 * that acquire locks. Unfortunately, libc wraps most system calls | |
1039 * (e.g. in order to implement pthread_atfork, and to make calls | |
1040 * cancellable), which means we cannot call these functions. Instead, | |
1041 * we have to call syscall() directly. | |
1042 */ | |
1043 #undef LSS_ERRNO | |
1044 #ifdef SYS_ERRNO | |
1045 /* Allow the including file to override the location of errno. This can | |
1046 * be useful when using clone() with the CLONE_VM option. | |
1047 */ | |
1048 #define LSS_ERRNO SYS_ERRNO | |
1049 #else | |
1050 #define LSS_ERRNO errno | |
1051 #endif | |
1052 | |
1053 #undef LSS_INLINE | |
1054 #ifdef SYS_INLINE | |
1055 #define LSS_INLINE SYS_INLINE | |
1056 #else | |
1057 #define LSS_INLINE static inline | |
1058 #endif | |
1059 | |
1060 /* Allow the including file to override the prefix used for all new | |
1061 * system calls. By default, it will be set to "sys_". | |
1062 */ | |
1063 #undef LSS_NAME | |
1064 #ifndef SYS_PREFIX | |
1065 #define LSS_NAME(name) sys_##name | |
1066 #elif SYS_PREFIX < 0 | |
1067 #define LSS_NAME(name) name | |
1068 #elif SYS_PREFIX == 0 | |
1069 #define LSS_NAME(name) sys0_##name | |
1070 #elif SYS_PREFIX == 1 | |
1071 #define LSS_NAME(name) sys1_##name | |
1072 #elif SYS_PREFIX == 2 | |
1073 #define LSS_NAME(name) sys2_##name | |
1074 #elif SYS_PREFIX == 3 | |
1075 #define LSS_NAME(name) sys3_##name | |
1076 #elif SYS_PREFIX == 4 | |
1077 #define LSS_NAME(name) sys4_##name | |
1078 #elif SYS_PREFIX == 5 | |
1079 #define LSS_NAME(name) sys5_##name | |
1080 #elif SYS_PREFIX == 6 | |
1081 #define LSS_NAME(name) sys6_##name | |
1082 #elif SYS_PREFIX == 7 | |
1083 #define LSS_NAME(name) sys7_##name | |
1084 #elif SYS_PREFIX == 8 | |
1085 #define LSS_NAME(name) sys8_##name | |
1086 #elif SYS_PREFIX == 9 | |
1087 #define LSS_NAME(name) sys9_##name | |
1088 #endif | |
1089 | |
1090 #undef LSS_RETURN | |
1091 #if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) \ | |
1092 || defined(__ARM_EABI__)) | |
1093 /* Failing system calls return a negative result in the range of | |
1094 * -1..-4095. These are "errno" values with the sign inverted. | |
1095 */ | |
1096 #define LSS_RETURN(type, res) \ | |
1097 do { \ | |
1098 if ((unsigned long)(res) >= (unsigned long)(-4095)) { \ | |
1099 LSS_ERRNO = -(res); \ | |
1100 res = -1; \ | |
1101 } \ | |
1102 return (type) (res); \ | |
1103 } while (0) | |
1104 #elif defined(__mips__) | |
1105 /* On MIPS, failing system calls return -1, and set errno in a | |
1106 * separate CPU register. | |
1107 */ | |
1108 #define LSS_RETURN(type, res, err) \ | |
1109 do { \ | |
1110 if (err) { \ | |
1111 LSS_ERRNO = (res); \ | |
1112 res = -1; \ | |
1113 } \ | |
1114 return (type) (res); \ | |
1115 } while (0) | |
1116 #elif defined(__PPC__) | |
1117 /* On PPC, failing system calls return -1, and set errno in a | |
1118 * separate CPU register. See linux/unistd.h. | |
1119 */ | |
1120 #define LSS_RETURN(type, res, err) \ | |
1121 do { \ | |
1122 if (err & 0x10000000 ) { \ | |
1123 LSS_ERRNO = (res); \ | |
1124 res = -1; \ | |
1125 } \ | |
1126 return (type) (res); \ | |
1127 } while (0) | |
1128 #endif | |
1129 #if defined(__i386__) | |
1130 /* In PIC mode (e.g. when building shared libraries), gcc for i386 | |
1131 * reserves ebx. Unfortunately, most distribution ship with implementations | |
1132 * of _syscallX() which clobber ebx. | |
1133 * Also, most definitions of _syscallX() neglect to mark "memory" as being | |
1134 * clobbered. This causes problems with compilers, that do a better job | |
1135 * at optimizing across __asm__ calls. | |
1136 * So, we just have to redefine all of the _syscallX() macros. | |
1137 */ | |
1138 #undef LSS_BODY | |
1139 #define LSS_BODY(type,args...) \ | |
1140 long __res; \ | |
1141 __asm__ __volatile__("push %%ebx\n" \ | |
1142 "movl %2,%%ebx\n" \ | |
1143 "int $0x80\n" \ | |
1144 "pop %%ebx" \ | |
1145 args \ | |
1146 : "memory"); \ | |
1147 LSS_RETURN(type,__res) | |
1148 #undef _syscall0 | |
1149 #define _syscall0(type,name) \ | |
1150 type LSS_NAME(name)(void) { \ | |
1151 long __res; \ | |
1152 __asm__ volatile("int $0x80" \ | |
1153 : "=a" (__res) \ | |
1154 : "0" (__NR_##name) \ | |
1155 : "memory"); \ | |
1156 LSS_RETURN(type,__res); \ | |
1157 } | |
1158 #undef _syscall1 | |
1159 #define _syscall1(type,name,type1,arg1) \ | |
1160 type LSS_NAME(name)(type1 arg1) { \ | |
1161 LSS_BODY(type, \ | |
1162 : "=a" (__res) \ | |
1163 : "0" (__NR_##name), "ri" ((long)(arg1))); \ | |
1164 } | |
1165 #undef _syscall2 | |
1166 #define _syscall2(type,name,type1,arg1,type2,arg2) \ | |
1167 type LSS_NAME(name)(type1 arg1,type2 arg2) { \ | |
1168 LSS_BODY(type, \ | |
1169 : "=a" (__res) \ | |
1170 : "0" (__NR_##name),"ri" ((long)(arg1)), "c" ((long)(arg2))); \ | |
1171 } | |
1172 #undef _syscall3 | |
1173 #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ | |
1174 type LSS_NAME(name)(type1 arg1,type2 arg2,type3 arg3) { \ | |
1175 LSS_BODY(type, \ | |
1176 : "=a" (__res) \ | |
1177 : "0" (__NR_##name), "ri" ((long)(arg1)), "c" ((long)(arg2)), \ | |
1178 "d" ((long)(arg3))); \ | |
1179 } | |
1180 #undef _syscall4 | |
1181 #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ | |
1182 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ | |
1183 LSS_BODY(type, \ | |
1184 : "=a" (__res) \ | |
1185 : "0" (__NR_##name), "ri" ((long)(arg1)), "c" ((long)(arg2)), \ | |
1186 "d" ((long)(arg3)),"S" ((long)(arg4))); \ | |
1187 } | |
1188 #undef _syscall5 | |
1189 #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ | |
1190 type5,arg5) \ | |
1191 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
1192 type5 arg5) { \ | |
1193 long __res; \ | |
1194 __asm__ __volatile__("push %%ebx\n" \ | |
1195 "movl %2,%%ebx\n" \ | |
1196 "movl %1,%%eax\n" \ | |
1197 "int $0x80\n" \ | |
1198 "pop %%ebx" \ | |
1199 : "=a" (__res) \ | |
1200 : "i" (__NR_##name), "ri" ((long)(arg1)), \ | |
1201 "c" ((long)(arg2)), "d" ((long)(arg3)), \ | |
1202 "S" ((long)(arg4)), "D" ((long)(arg5)) \ | |
1203 : "memory"); \ | |
1204 LSS_RETURN(type,__res); \ | |
1205 } | |
1206 #undef _syscall6 | |
1207 #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ | |
1208 type5,arg5,type6,arg6) \ | |
1209 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
1210 type5 arg5, type6 arg6) { \ | |
1211 long __res; \ | |
1212 struct { long __a1; long __a6; } __s = { (long)arg1, (long) arg6 }; \ | |
1213 __asm__ __volatile__("push %%ebp\n" \ | |
1214 "push %%ebx\n" \ | |
1215 "movl 4(%2),%%ebp\n" \ | |
1216 "movl 0(%2), %%ebx\n" \ | |
1217 "movl %1,%%eax\n" \ | |
1218 "int $0x80\n" \ | |
1219 "pop %%ebx\n" \ | |
1220 "pop %%ebp" \ | |
1221 : "=a" (__res) \ | |
1222 : "i" (__NR_##name), "0" ((long)(&__s)), \ | |
1223 "c" ((long)(arg2)), "d" ((long)(arg3)), \ | |
1224 "S" ((long)(arg4)), "D" ((long)(arg5)) \ | |
1225 : "memory"); \ | |
1226 LSS_RETURN(type,__res); \ | |
1227 } | |
1228 LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, | |
1229 int flags, void *arg, int *parent_tidptr, | |
1230 void *newtls, int *child_tidptr) { | |
1231 long __res; | |
1232 __asm__ __volatile__(/* if (fn == NULL) | |
1233 * return -EINVAL; | |
1234 */ | |
1235 "movl %3,%%ecx\n" | |
1236 "jecxz 1f\n" | |
1237 | |
1238 /* if (child_stack == NULL) | |
1239 * return -EINVAL; | |
1240 */ | |
1241 "movl %4,%%ecx\n" | |
1242 "jecxz 1f\n" | |
1243 | |
1244 /* Set up alignment of the child stack: | |
1245 * child_stack = (child_stack & ~0xF) - 20; | |
1246 */ | |
1247 "andl $-16,%%ecx\n" | |
1248 "subl $20,%%ecx\n" | |
1249 | |
1250 /* Push "arg" and "fn" onto the stack that will be | |
1251 * used by the child. | |
1252 */ | |
1253 "movl %6,%%eax\n" | |
1254 "movl %%eax,4(%%ecx)\n" | |
1255 "movl %3,%%eax\n" | |
1256 "movl %%eax,(%%ecx)\n" | |
1257 | |
1258 /* %eax = syscall(%eax = __NR_clone, | |
1259 * %ebx = flags, | |
1260 * %ecx = child_stack, | |
1261 * %edx = parent_tidptr, | |
1262 * %esi = newtls, | |
1263 * %edi = child_tidptr) | |
1264 * Also, make sure that %ebx gets preserved as it is | |
1265 * used in PIC mode. | |
1266 */ | |
1267 "movl %8,%%esi\n" | |
1268 "movl %7,%%edx\n" | |
1269 "movl %5,%%eax\n" | |
1270 "movl %9,%%edi\n" | |
1271 "pushl %%ebx\n" | |
1272 "movl %%eax,%%ebx\n" | |
1273 "movl %2,%%eax\n" | |
1274 "int $0x80\n" | |
1275 | |
1276 /* In the parent: restore %ebx | |
1277 * In the child: move "fn" into %ebx | |
1278 */ | |
1279 "popl %%ebx\n" | |
1280 | |
1281 /* if (%eax != 0) | |
1282 * return %eax; | |
1283 */ | |
1284 "test %%eax,%%eax\n" | |
1285 "jnz 1f\n" | |
1286 | |
1287 /* In the child, now. Terminate frame pointer chain. | |
1288 */ | |
1289 "movl $0,%%ebp\n" | |
1290 | |
1291 /* Call "fn". "arg" is already on the stack. | |
1292 */ | |
1293 "call *%%ebx\n" | |
1294 | |
1295 /* Call _exit(%ebx). Unfortunately older versions | |
1296 * of gcc restrict the number of arguments that can | |
1297 * be passed to asm(). So, we need to hard-code the | |
1298 * system call number. | |
1299 */ | |
1300 "movl %%eax,%%ebx\n" | |
1301 "movl $1,%%eax\n" | |
1302 "int $0x80\n" | |
1303 | |
1304 /* Return to parent. | |
1305 */ | |
1306 "1:\n" | |
1307 : "=a" (__res) | |
1308 : "0"(-EINVAL), "i"(__NR_clone), | |
1309 "m"(fn), "m"(child_stack), "m"(flags), "m"(arg), | |
1310 "m"(parent_tidptr), "m"(newtls), "m"(child_tidptr) | |
1311 : "memory", "ecx", "edx", "esi", "edi"); | |
1312 LSS_RETURN(int, __res); | |
1313 } | |
1314 | |
1315 #define __NR__fadvise64_64 __NR_fadvise64_64 | |
1316 LSS_INLINE _syscall6(int, _fadvise64_64, int, fd, | |
1317 unsigned, offset_lo, unsigned, offset_hi, | |
1318 unsigned, len_lo, unsigned, len_hi, | |
1319 int, advice) | |
1320 | |
1321 LSS_INLINE int LSS_NAME(fadvise64)(int fd, loff_t offset, | |
1322 loff_t len, int advice) { | |
1323 return LSS_NAME(_fadvise64_64)(fd, | |
1324 (unsigned)offset, (unsigned)(offset >>32), | |
1325 (unsigned)len, (unsigned)(len >> 32), | |
1326 advice); | |
1327 } | |
1328 | |
1329 LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) { | |
1330 /* On i386, the kernel does not know how to return from a signal | |
1331 * handler. Instead, it relies on user space to provide a | |
1332 * restorer function that calls the {rt_,}sigreturn() system call. | |
1333 * Unfortunately, we cannot just reference the glibc version of this | |
1334 * function, as glibc goes out of its way to make it inaccessible. | |
1335 */ | |
1336 void (*res)(void); | |
1337 __asm__ __volatile__("call 2f\n" | |
1338 "0:.align 16\n" | |
1339 "1:movl %1,%%eax\n" | |
1340 "int $0x80\n" | |
1341 "2:popl %0\n" | |
1342 "addl $(1b-0b),%0\n" | |
1343 : "=a" (res) | |
1344 : "i" (__NR_rt_sigreturn)); | |
1345 return res; | |
1346 } | |
1347 LSS_INLINE void (*LSS_NAME(restore)(void))(void) { | |
1348 /* On i386, the kernel does not know how to return from a signal | |
1349 * handler. Instead, it relies on user space to provide a | |
1350 * restorer function that calls the {rt_,}sigreturn() system call. | |
1351 * Unfortunately, we cannot just reference the glibc version of this | |
1352 * function, as glibc goes out of its way to make it inaccessible. | |
1353 */ | |
1354 void (*res)(void); | |
1355 __asm__ __volatile__("call 2f\n" | |
1356 "0:.align 16\n" | |
1357 "1:pop %%eax\n" | |
1358 "movl %1,%%eax\n" | |
1359 "int $0x80\n" | |
1360 "2:popl %0\n" | |
1361 "addl $(1b-0b),%0\n" | |
1362 : "=a" (res) | |
1363 : "i" (__NR_sigreturn)); | |
1364 return res; | |
1365 } | |
1366 #elif defined(__x86_64__) | |
1367 /* There are no known problems with any of the _syscallX() macros | |
1368 * currently shipping for x86_64, but we still need to be able to define | |
1369 * our own version so that we can override the location of the errno | |
1370 * location (e.g. when using the clone() system call with the CLONE_VM | |
1371 * option). | |
1372 */ | |
1373 #undef LSS_BODY | |
1374 #define LSS_BODY(type,name, ...) \ | |
1375 long __res; \ | |
1376 __asm__ __volatile__("syscall" : "=a" (__res) : "0" (__NR_##name), \ | |
1377 ##__VA_ARGS__ : "r11", "rcx", "memory"); \ | |
1378 LSS_RETURN(type, __res) | |
1379 #undef _syscall0 | |
1380 #define _syscall0(type,name) \ | |
1381 type LSS_NAME(name)() { \ | |
1382 LSS_BODY(type, name); \ | |
1383 } | |
1384 #undef _syscall1 | |
1385 #define _syscall1(type,name,type1,arg1) \ | |
1386 type LSS_NAME(name)(type1 arg1) { \ | |
1387 LSS_BODY(type, name, "D" ((long)(arg1))); \ | |
1388 } | |
1389 #undef _syscall2 | |
1390 #define _syscall2(type,name,type1,arg1,type2,arg2) \ | |
1391 type LSS_NAME(name)(type1 arg1, type2 arg2) { \ | |
1392 LSS_BODY(type, name, "D" ((long)(arg1)), "S" ((long)(arg2))); \ | |
1393 } | |
1394 #undef _syscall3 | |
1395 #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ | |
1396 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ | |
1397 LSS_BODY(type, name, "D" ((long)(arg1)), "S" ((long)(arg2)), \ | |
1398 "d" ((long)(arg3))); \ | |
1399 } | |
1400 #undef _syscall4 | |
1401 #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ | |
1402 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ | |
1403 long __res; \ | |
1404 __asm__ __volatile__("movq %5,%%r10; syscall" : \ | |
1405 "=a" (__res) : "0" (__NR_##name), \ | |
1406 "D" ((long)(arg1)), "S" ((long)(arg2)), "d" ((long)(arg3)), \ | |
1407 "g" ((long)(arg4)) : "r10", "r11", "rcx", "memory"); \ | |
1408 LSS_RETURN(type, __res); \ | |
1409 } | |
1410 #undef _syscall5 | |
1411 #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ | |
1412 type5,arg5) \ | |
1413 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
1414 type5 arg5) { \ | |
1415 long __res; \ | |
1416 __asm__ __volatile__("movq %5,%%r10; movq %6,%%r8; syscall" : \ | |
1417 "=a" (__res) : "0" (__NR_##name), \ | |
1418 "D" ((long)(arg1)), "S" ((long)(arg2)), "d" ((long)(arg3)), \ | |
1419 "g" ((long)(arg4)), "g" ((long)(arg5)) : \ | |
1420 "r8", "r10", "r11", "rcx", "memory"); \ | |
1421 LSS_RETURN(type, __res); \ | |
1422 } | |
1423 #undef _syscall6 | |
1424 #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ | |
1425 type5,arg5,type6,arg6) \ | |
1426 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
1427 type5 arg5, type6 arg6) { \ | |
1428 long __res; \ | |
1429 __asm__ __volatile__("movq %5,%%r10; movq %6,%%r8; movq %7,%%r9;" \ | |
1430 "syscall" : \ | |
1431 "=a" (__res) : "0" (__NR_##name), \ | |
1432 "D" ((long)(arg1)), "S" ((long)(arg2)), "d" ((long)(arg3)), \ | |
1433 "g" ((long)(arg4)), "g" ((long)(arg5)), "g" ((long)(arg6)) : \ | |
1434 "r8", "r9", "r10", "r11", "rcx", "memory"); \ | |
1435 LSS_RETURN(type, __res); \ | |
1436 } | |
1437 LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, | |
1438 int flags, void *arg, int *parent_tidptr, | |
1439 void *newtls, int *child_tidptr) { | |
1440 long __res; | |
1441 { | |
1442 register void *__tls __asm__("r8") = newtls; | |
1443 register int *__ctid __asm__("r10") = child_tidptr; | |
1444 __asm__ __volatile__(/* if (fn == NULL) | |
1445 * return -EINVAL; | |
1446 */ | |
1447 "testq %4,%4\n" | |
1448 "jz 1f\n" | |
1449 | |
1450 /* if (child_stack == NULL) | |
1451 * return -EINVAL; | |
1452 */ | |
1453 "testq %5,%5\n" | |
1454 "jz 1f\n" | |
1455 | |
1456 /* childstack -= 2*sizeof(void *); | |
1457 */ | |
1458 "subq $16,%5\n" | |
1459 | |
1460 /* Push "arg" and "fn" onto the stack that will be | |
1461 * used by the child. | |
1462 */ | |
1463 "movq %7,8(%5)\n" | |
1464 "movq %4,0(%5)\n" | |
1465 | |
1466 /* %rax = syscall(%rax = __NR_clone, | |
1467 * %rdi = flags, | |
1468 * %rsi = child_stack, | |
1469 * %rdx = parent_tidptr, | |
1470 * %r8 = new_tls, | |
1471 * %r10 = child_tidptr) | |
1472 */ | |
1473 "movq %2,%%rax\n" | |
1474 "syscall\n" | |
1475 | |
1476 /* if (%rax != 0) | |
1477 * return; | |
1478 */ | |
1479 "testq %%rax,%%rax\n" | |
1480 "jnz 1f\n" | |
1481 | |
1482 /* In the child. Terminate frame pointer chain. | |
1483 */ | |
1484 "xorq %%rbp,%%rbp\n" | |
1485 | |
1486 /* Call "fn(arg)". | |
1487 */ | |
1488 "popq %%rax\n" | |
1489 "popq %%rdi\n" | |
1490 "call *%%rax\n" | |
1491 | |
1492 /* Call _exit(%ebx). | |
1493 */ | |
1494 "movq %%rax,%%rdi\n" | |
1495 "movq %3,%%rax\n" | |
1496 "syscall\n" | |
1497 | |
1498 /* Return to parent. | |
1499 */ | |
1500 "1:\n" | |
1501 : "=a" (__res) | |
1502 : "0"(-EINVAL), "i"(__NR_clone), "i"(__NR_exit), | |
1503 "r"(fn), "S"(child_stack), "D"(flags), "r"(arg), | |
1504 "d"(parent_tidptr), "r"(__tls), "r"(__ctid) | |
1505 : "memory", "r11", "rcx"); | |
1506 } | |
1507 LSS_RETURN(int, __res); | |
1508 } | |
1509 LSS_INLINE _syscall4(int, fadvise64, int, fd, loff_t, offset, loff_t, len, | |
1510 int, advice) | |
1511 | |
1512 LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) { | |
1513 /* On x86-64, the kernel does not know how to return from | |
1514 * a signal handler. Instead, it relies on user space to provide a | |
1515 * restorer function that calls the rt_sigreturn() system call. | |
1516 * Unfortunately, we cannot just reference the glibc version of this | |
1517 * function, as glibc goes out of its way to make it inaccessible. | |
1518 */ | |
1519 void (*res)(void); | |
1520 __asm__ __volatile__("call 2f\n" | |
1521 "0:.align 16\n" | |
1522 "1:movq %1,%%rax\n" | |
1523 "syscall\n" | |
1524 "2:popq %0\n" | |
1525 "addq $(1b-0b),%0\n" | |
1526 : "=a" (res) | |
1527 : "i" (__NR_rt_sigreturn)); | |
1528 return res; | |
1529 } | |
1530 #elif defined(__ARM_ARCH_3__) | |
1531 #undef LSS_REG | |
1532 #define LSS_REG(r,a) register long __r##r __asm__("r"#r) = (long)a | |
1533 #undef LSS_BODY | |
1534 #define LSS_BODY(type,name,args...) \ | |
1535 register long __res_r0 __asm__("r0"); \ | |
1536 long __res; \ | |
1537 __asm__ __volatile__ (__syscall(name) \ | |
1538 : "=r"(__res_r0) : args : "lr", "memory"); \ | |
1539 __res = __res_r0; \ | |
1540 LSS_RETURN(type, __res) | |
1541 #undef _syscall0 | |
1542 #define _syscall0(type, name) \ | |
1543 type LSS_NAME(name)() { \ | |
1544 LSS_BODY(type, name); \ | |
1545 } | |
1546 #undef _syscall1 | |
1547 #define _syscall1(type, name, type1, arg1) \ | |
1548 type LSS_NAME(name)(type1 arg1) { \ | |
1549 LSS_REG(0, arg1); LSS_BODY(type, name, "r"(__r0)); \ | |
1550 } | |
1551 #undef _syscall2 | |
1552 #define _syscall2(type, name, type1, arg1, type2, arg2) \ | |
1553 type LSS_NAME(name)(type1 arg1, type2 arg2) { \ | |
1554 LSS_REG(0, arg1); LSS_REG(1, arg2); \ | |
1555 LSS_BODY(type, name, "r"(__r0), "r"(__r1)); \ | |
1556 } | |
1557 #undef _syscall3 | |
1558 #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ | |
1559 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ | |
1560 LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ | |
1561 LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2)); \ | |
1562 } | |
1563 #undef _syscall4 | |
1564 #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ | |
1565 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ | |
1566 LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ | |
1567 LSS_REG(3, arg4); \ | |
1568 LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3)); \ | |
1569 } | |
1570 #undef _syscall5 | |
1571 #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ | |
1572 type5,arg5) \ | |
1573 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
1574 type5 arg5) { \ | |
1575 LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ | |
1576 LSS_REG(3, arg4); LSS_REG(4, arg5); \ | |
1577 LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \ | |
1578 "r"(__r4)); \ | |
1579 } | |
1580 #undef _syscall6 | |
1581 #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ | |
1582 type5,arg5,type6,arg6) \ | |
1583 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
1584 type5 arg5, type6 arg6) { \ | |
1585 LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ | |
1586 LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6); \ | |
1587 LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \ | |
1588 "r"(__r4), "r"(__r5)); \ | |
1589 } | |
1590 LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, | |
1591 int flags, void *arg, int *parent_tidptr, | |
1592 void *newtls, int *child_tidptr) { | |
1593 long __res; | |
1594 { | |
1595 register int __flags __asm__("r0") = flags; | |
1596 register void *__stack __asm__("r1") = child_stack; | |
1597 register void *__ptid __asm__("r2") = parent_tidptr; | |
1598 register void *__tls __asm__("r3") = newtls; | |
1599 register int *__ctid __asm__("r4") = child_tidptr; | |
1600 __asm__ __volatile__(/* if (fn == NULL || child_stack == NULL) | |
1601 * return -EINVAL; | |
1602 */ | |
1603 "cmp %2,#0\n" | |
1604 "cmpne %3,#0\n" | |
1605 "moveq %0,%1\n" | |
1606 "beq 1f\n" | |
1607 | |
1608 /* Push "arg" and "fn" onto the stack that will be | |
1609 * used by the child. | |
1610 */ | |
1611 "str %5,[%3,#-4]!\n" | |
1612 "str %2,[%3,#-4]!\n" | |
1613 | |
1614 /* %r0 = syscall(%r0 = flags, | |
1615 * %r1 = child_stack, | |
1616 * %r2 = parent_tidptr, | |
1617 * %r3 = newtls, | |
1618 * %r4 = child_tidptr) | |
1619 */ | |
1620 __syscall(clone)"\n" | |
1621 | |
1622 /* if (%r0 != 0) | |
1623 * return %r0; | |
1624 */ | |
1625 "movs %0,r0\n" | |
1626 "bne 1f\n" | |
1627 | |
1628 /* In the child, now. Call "fn(arg)". | |
1629 */ | |
1630 "ldr r0,[sp, #4]\n" | |
1631 "mov lr,pc\n" | |
1632 "ldr pc,[sp]\n" | |
1633 | |
1634 /* Call _exit(%r0). | |
1635 */ | |
1636 __syscall(exit)"\n" | |
1637 "1:\n" | |
1638 : "=r" (__res) | |
1639 : "i"(-EINVAL), | |
1640 "r"(fn), "r"(__stack), "r"(__flags), "r"(arg), | |
1641 "r"(__ptid), "r"(__tls), "r"(__ctid) | |
1642 : "lr", "memory"); | |
1643 } | |
1644 LSS_RETURN(int, __res); | |
1645 } | |
1646 #elif defined(__ARM_EABI__) | |
1647 /* Most definitions of _syscallX() neglect to mark "memory" as being | |
1648 * clobbered. This causes problems with compilers, that do a better job | |
1649 * at optimizing across __asm__ calls. | |
1650 * So, we just have to redefine all fo the _syscallX() macros. | |
1651 */ | |
1652 #undef LSS_REG | |
1653 #define LSS_REG(r,a) register long __r##r __asm__("r"#r) = (long)a | |
1654 #undef LSS_BODY | |
1655 #define LSS_BODY(type,name,args...) \ | |
1656 register long __res_r0 __asm__("r0"); \ | |
1657 long __res; \ | |
1658 __asm__ __volatile__ ("push {r7}\n" \ | |
1659 "mov r7, %1\n" \ | |
1660 "swi 0x0\n" \ | |
1661 "pop {r7}\n" \ | |
1662 : "=r"(__res_r0) \ | |
1663 : "i"(__NR_##name) , ## args \ | |
1664 : "lr", "memory"); \ | |
1665 __res = __res_r0; \ | |
1666 LSS_RETURN(type, __res) | |
1667 #undef _syscall0 | |
1668 #define _syscall0(type, name) \ | |
1669 type LSS_NAME(name)() { \ | |
1670 LSS_BODY(type, name); \ | |
1671 } | |
1672 #undef _syscall1 | |
1673 #define _syscall1(type, name, type1, arg1) \ | |
1674 type LSS_NAME(name)(type1 arg1) { \ | |
1675 LSS_REG(0, arg1); LSS_BODY(type, name, "r"(__r0)); \ | |
1676 } | |
1677 #undef _syscall2 | |
1678 #define _syscall2(type, name, type1, arg1, type2, arg2) \ | |
1679 type LSS_NAME(name)(type1 arg1, type2 arg2) { \ | |
1680 LSS_REG(0, arg1); LSS_REG(1, arg2); \ | |
1681 LSS_BODY(type, name, "r"(__r0), "r"(__r1)); \ | |
1682 } | |
1683 #undef _syscall3 | |
1684 #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ | |
1685 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ | |
1686 LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ | |
1687 LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2)); \ | |
1688 } | |
1689 #undef _syscall4 | |
1690 #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ | |
1691 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ | |
1692 LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ | |
1693 LSS_REG(3, arg4); \ | |
1694 LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3)); \ | |
1695 } | |
1696 #undef _syscall5 | |
1697 #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ | |
1698 type5,arg5) \ | |
1699 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
1700 type5 arg5) { \ | |
1701 LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ | |
1702 LSS_REG(3, arg4); LSS_REG(4, arg5); \ | |
1703 LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \ | |
1704 "r"(__r4)); \ | |
1705 } | |
1706 #undef _syscall6 | |
1707 #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ | |
1708 type5,arg5,type6,arg6) \ | |
1709 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
1710 type5 arg5, type6 arg6) { \ | |
1711 LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ | |
1712 LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6); \ | |
1713 LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \ | |
1714 "r"(__r4), "r"(__r5)); \ | |
1715 } | |
1716 LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, | |
1717 int flags, void *arg, int *parent_tidptr, | |
1718 void *newtls, int *child_tidptr) { | |
1719 long __res; | |
1720 { | |
1721 register int __flags __asm__("r0") = flags; | |
1722 register void *__stack __asm__("r1") = child_stack; | |
1723 register void *__ptid __asm__("r2") = parent_tidptr; | |
1724 register void *__tls __asm__("r3") = newtls; | |
1725 register int *__ctid __asm__("r4") = child_tidptr; | |
1726 __asm__ __volatile__(/* if (fn == NULL || child_stack == NULL) | |
1727 * return -EINVAL; | |
1728 */ | |
1729 "cmp %2,#0\n" | |
1730 "cmpne %3,#0\n" | |
1731 "moveq %0,%1\n" | |
1732 "beq 1f\n" | |
1733 | |
1734 /* Push "arg" and "fn" onto the stack that will be | |
1735 * used by the child. | |
1736 */ | |
1737 "str %5,[%3,#-4]!\n" | |
1738 "str %2,[%3,#-4]!\n" | |
1739 | |
1740 /* %r0 = syscall(%r0 = flags, | |
1741 * %r1 = child_stack, | |
1742 * %r2 = parent_tidptr, | |
1743 * %r3 = newtls, | |
1744 * %r4 = child_tidptr) | |
1745 */ | |
1746 "mov r7, %9\n" | |
1747 "swi 0x0\n" | |
1748 | |
1749 /* if (%r0 != 0) | |
1750 * return %r0; | |
1751 */ | |
1752 "movs %0,r0\n" | |
1753 "bne 1f\n" | |
1754 | |
1755 /* In the child, now. Call "fn(arg)". | |
1756 */ | |
1757 "ldr r0,[sp, #4]\n" | |
1758 "mov lr,pc\n" | |
1759 "ldr pc,[sp]\n" | |
1760 | |
1761 /* Call _exit(%r0). | |
1762 */ | |
1763 "mov r7, %10\n" | |
1764 "swi 0x0\n" | |
1765 "1:\n" | |
1766 : "=r" (__res) | |
1767 : "i"(-EINVAL), | |
1768 "r"(fn), "r"(__stack), "r"(__flags), "r"(arg), | |
1769 "r"(__ptid), "r"(__tls), "r"(__ctid), | |
1770 "i"(__NR_clone), "i"(__NR_exit) | |
1771 : "lr", "memory"); | |
1772 } | |
1773 LSS_RETURN(int, __res); | |
1774 } | |
1775 #elif defined(__mips__) | |
1776 #undef LSS_REG | |
1777 #define LSS_REG(r,a) register unsigned long __r##r __asm__("$"#r) = \ | |
1778 (unsigned long)(a) | |
1779 #undef LSS_BODY | |
1780 #define LSS_BODY(type,name,r7,...) \ | |
1781 register unsigned long __v0 __asm__("$2") = __NR_##name; \ | |
1782 __asm__ __volatile__ ("syscall\n" \ | |
1783 : "=&r"(__v0), r7 (__r7) \ | |
1784 : "0"(__v0), ##__VA_ARGS__ \ | |
1785 : "$8", "$9", "$10", "$11", "$12", \ | |
1786 "$13", "$14", "$15", "$24", "memory"); \ | |
1787 LSS_RETURN(type, __v0, __r7) | |
1788 #undef _syscall0 | |
1789 #define _syscall0(type, name) \ | |
1790 type LSS_NAME(name)() { \ | |
1791 register unsigned long __r7 __asm__("$7"); \ | |
1792 LSS_BODY(type, name, "=r"); \ | |
1793 } | |
1794 #undef _syscall1 | |
1795 #define _syscall1(type, name, type1, arg1) \ | |
1796 type LSS_NAME(name)(type1 arg1) { \ | |
1797 register unsigned long __r7 __asm__("$7"); \ | |
1798 LSS_REG(4, arg1); LSS_BODY(type, name, "=r", "r"(__r4)); \ | |
1799 } | |
1800 #undef _syscall2 | |
1801 #define _syscall2(type, name, type1, arg1, type2, arg2) \ | |
1802 type LSS_NAME(name)(type1 arg1, type2 arg2) { \ | |
1803 register unsigned long __r7 __asm__("$7"); \ | |
1804 LSS_REG(4, arg1); LSS_REG(5, arg2); \ | |
1805 LSS_BODY(type, name, "=r", "r"(__r4), "r"(__r5)); \ | |
1806 } | |
1807 #undef _syscall3 | |
1808 #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ | |
1809 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ | |
1810 register unsigned long __r7 __asm__("$7"); \ | |
1811 LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ | |
1812 LSS_BODY(type, name, "=r", "r"(__r4), "r"(__r5), "r"(__r6)); \ | |
1813 } | |
1814 #undef _syscall4 | |
1815 #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ | |
1816 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ | |
1817 LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ | |
1818 LSS_REG(7, arg4); \ | |
1819 LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6)); \ | |
1820 } | |
1821 #undef _syscall5 | |
1822 #if _MIPS_SIM == _MIPS_SIM_ABI32 | |
1823 /* The old 32bit MIPS system call API passes the fifth and sixth argument | |
1824 * on the stack, whereas the new APIs use registers "r8" and "r9". | |
1825 */ | |
1826 #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ | |
1827 type5,arg5) \ | |
1828 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
1829 type5 arg5) { \ | |
1830 LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ | |
1831 LSS_REG(7, arg4); \ | |
1832 register unsigned long __v0 __asm__("$2"); \ | |
1833 __asm__ __volatile__ (".set noreorder\n" \ | |
1834 "lw $2, %6\n" \ | |
1835 "subu $29, 32\n" \ | |
1836 "sw $2, 16($29)\n" \ | |
1837 "li $2, %2\n" \ | |
1838 "syscall\n" \ | |
1839 "addiu $29, 32\n" \ | |
1840 ".set reorder\n" \ | |
1841 : "=&r"(__v0), "+r" (__r7) \ | |
1842 : "i" (__NR_##name), "r"(__r4), "r"(__r5), \ | |
1843 "r"(__r6), "m" ((unsigned long)arg5) \ | |
1844 : "$8", "$9", "$10", "$11", "$12", \ | |
1845 "$13", "$14", "$15", "$24", "memory"); \ | |
1846 LSS_RETURN(type, __v0, __r7); \ | |
1847 } | |
1848 #else | |
1849 #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ | |
1850 type5,arg5) \ | |
1851 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
1852 type5 arg5) { \ | |
1853 LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ | |
1854 LSS_REG(7, arg4); LSS_REG(8, arg5); \ | |
1855 LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6), \ | |
1856 "r"(__r8)); \ | |
1857 } | |
1858 #endif | |
1859 #undef _syscall6 | |
1860 #if _MIPS_SIM == _MIPS_SIM_ABI32 | |
1861 /* The old 32bit MIPS system call API passes the fifth and sixth argument | |
1862 * on the stack, whereas the new APIs use registers "r8" and "r9". | |
1863 */ | |
1864 #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ | |
1865 type5,arg5,type6,arg6) \ | |
1866 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
1867 type5 arg5, type6 arg6) { \ | |
1868 LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ | |
1869 LSS_REG(7, arg4); \ | |
1870 register unsigned long __v0 __asm__("$2"); \ | |
1871 __asm__ __volatile__ (".set noreorder\n" \ | |
1872 "lw $2, %6\n" \ | |
1873 "lw $8, %7\n" \ | |
1874 "subu $29, 32\n" \ | |
1875 "sw $2, 16($29)\n" \ | |
1876 "sw $8, 20($29)\n" \ | |
1877 "li $2, %2\n" \ | |
1878 "syscall\n" \ | |
1879 "addiu $29, 32\n" \ | |
1880 ".set reorder\n" \ | |
1881 : "=&r"(__v0), "+r" (__r7) \ | |
1882 : "i" (__NR_##name), "r"(__r4), "r"(__r5), \ | |
1883 "r"(__r6), "r" ((unsigned long)arg5), \ | |
1884 "r" ((unsigned long)arg6) \ | |
1885 : "$8", "$9", "$10", "$11", "$12", \ | |
1886 "$13", "$14", "$15", "$24", "memory"); \ | |
1887 LSS_RETURN(type, __v0, __r7); \ | |
1888 } | |
1889 #else | |
1890 #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ | |
1891 type5,arg5,type6,arg6) \ | |
1892 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
1893 type5 arg5,type6 arg6) { \ | |
1894 LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ | |
1895 LSS_REG(7, arg4); LSS_REG(8, arg5); LSS_REG(9, arg6); \ | |
1896 LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6), \ | |
1897 "r"(__r8), "r"(__r9)); \ | |
1898 } | |
1899 #endif | |
1900 LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, | |
1901 int flags, void *arg, int *parent_tidptr, | |
1902 void *newtls, int *child_tidptr) { | |
1903 register unsigned long __v0 __asm__("$2"); | |
1904 register unsigned long __r7 __asm__("$7") = (unsigned long)newtls; | |
1905 { | |
1906 register int __flags __asm__("$4") = flags; | |
1907 register void *__stack __asm__("$5") = child_stack; | |
1908 register void *__ptid __asm__("$6") = parent_tidptr; | |
1909 register int *__ctid __asm__("$8") = child_tidptr; | |
1910 __asm__ __volatile__( | |
1911 #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 | |
1912 "subu $29,24\n" | |
1913 #elif _MIPS_SIM == _MIPS_SIM_NABI32 | |
1914 "sub $29,16\n" | |
1915 #else | |
1916 "dsubu $29,16\n" | |
1917 #endif | |
1918 | |
1919 /* if (fn == NULL || child_stack == NULL) | |
1920 * return -EINVAL; | |
1921 */ | |
1922 "li %0,%2\n" | |
1923 "beqz %5,1f\n" | |
1924 "beqz %6,1f\n" | |
1925 | |
1926 /* Push "arg" and "fn" onto the stack that will be | |
1927 * used by the child. | |
1928 */ | |
1929 #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 | |
1930 "subu %6,32\n" | |
1931 "sw %5,0(%6)\n" | |
1932 "sw %8,4(%6)\n" | |
1933 #elif _MIPS_SIM == _MIPS_SIM_NABI32 | |
1934 "sub %6,32\n" | |
1935 "sw %5,0(%6)\n" | |
1936 "sw %8,8(%6)\n" | |
1937 #else | |
1938 "dsubu %6,32\n" | |
1939 "sd %5,0(%6)\n" | |
1940 "sd %8,8(%6)\n" | |
1941 #endif | |
1942 | |
1943 /* $7 = syscall($4 = flags, | |
1944 * $5 = child_stack, | |
1945 * $6 = parent_tidptr, | |
1946 * $7 = newtls, | |
1947 * $8 = child_tidptr) | |
1948 */ | |
1949 "li $2,%3\n" | |
1950 "syscall\n" | |
1951 | |
1952 /* if ($7 != 0) | |
1953 * return $2; | |
1954 */ | |
1955 "bnez $7,1f\n" | |
1956 "bnez $2,1f\n" | |
1957 | |
1958 /* In the child, now. Call "fn(arg)". | |
1959 */ | |
1960 #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 | |
1961 "lw $25,0($29)\n" | |
1962 "lw $4,4($29)\n" | |
1963 #elif _MIPS_SIM == _MIPS_SIM_NABI32 | |
1964 "lw $25,0($29)\n" | |
1965 "lw $4,8($29)\n" | |
1966 #else | |
1967 "ld $25,0($29)\n" | |
1968 "ld $4,8($29)\n" | |
1969 #endif | |
1970 "jalr $25\n" | |
1971 | |
1972 /* Call _exit($2) | |
1973 */ | |
1974 "move $4,$2\n" | |
1975 "li $2,%4\n" | |
1976 "syscall\n" | |
1977 | |
1978 "1:\n" | |
1979 #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 | |
1980 "addu $29, 24\n" | |
1981 #elif _MIPS_SIM == _MIPS_SIM_NABI32 | |
1982 "add $29, 16\n" | |
1983 #else | |
1984 "daddu $29,16\n" | |
1985 #endif | |
1986 : "=&r" (__v0), "=r" (__r7) | |
1987 : "i"(-EINVAL), "i"(__NR_clone), "i"(__NR_exit), | |
1988 "r"(fn), "r"(__stack), "r"(__flags), "r"(arg), | |
1989 "r"(__ptid), "r"(__r7), "r"(__ctid) | |
1990 : "$9", "$10", "$11", "$12", "$13", "$14", "$15", | |
1991 "$24", "memory"); | |
1992 } | |
1993 LSS_RETURN(int, __v0, __r7); | |
1994 } | |
1995 #elif defined (__PPC__) | |
1996 #undef LSS_LOADARGS_0 | |
1997 #define LSS_LOADARGS_0(name, dummy...) \ | |
1998 __sc_0 = __NR_##name | |
1999 #undef LSS_LOADARGS_1 | |
2000 #define LSS_LOADARGS_1(name, arg1) \ | |
2001 LSS_LOADARGS_0(name); \ | |
2002 __sc_3 = (unsigned long) (arg1) | |
2003 #undef LSS_LOADARGS_2 | |
2004 #define LSS_LOADARGS_2(name, arg1, arg2) \ | |
2005 LSS_LOADARGS_1(name, arg1); \ | |
2006 __sc_4 = (unsigned long) (arg2) | |
2007 #undef LSS_LOADARGS_3 | |
2008 #define LSS_LOADARGS_3(name, arg1, arg2, arg3) \ | |
2009 LSS_LOADARGS_2(name, arg1, arg2); \ | |
2010 __sc_5 = (unsigned long) (arg3) | |
2011 #undef LSS_LOADARGS_4 | |
2012 #define LSS_LOADARGS_4(name, arg1, arg2, arg3, arg4) \ | |
2013 LSS_LOADARGS_3(name, arg1, arg2, arg3); \ | |
2014 __sc_6 = (unsigned long) (arg4) | |
2015 #undef LSS_LOADARGS_5 | |
2016 #define LSS_LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \ | |
2017 LSS_LOADARGS_4(name, arg1, arg2, arg3, arg4); \ | |
2018 __sc_7 = (unsigned long) (arg5) | |
2019 #undef LSS_LOADARGS_6 | |
2020 #define LSS_LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \ | |
2021 LSS_LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \ | |
2022 __sc_8 = (unsigned long) (arg6) | |
2023 #undef LSS_ASMINPUT_0 | |
2024 #define LSS_ASMINPUT_0 "0" (__sc_0) | |
2025 #undef LSS_ASMINPUT_1 | |
2026 #define LSS_ASMINPUT_1 LSS_ASMINPUT_0, "1" (__sc_3) | |
2027 #undef LSS_ASMINPUT_2 | |
2028 #define LSS_ASMINPUT_2 LSS_ASMINPUT_1, "2" (__sc_4) | |
2029 #undef LSS_ASMINPUT_3 | |
2030 #define LSS_ASMINPUT_3 LSS_ASMINPUT_2, "3" (__sc_5) | |
2031 #undef LSS_ASMINPUT_4 | |
2032 #define LSS_ASMINPUT_4 LSS_ASMINPUT_3, "4" (__sc_6) | |
2033 #undef LSS_ASMINPUT_5 | |
2034 #define LSS_ASMINPUT_5 LSS_ASMINPUT_4, "5" (__sc_7) | |
2035 #undef LSS_ASMINPUT_6 | |
2036 #define LSS_ASMINPUT_6 LSS_ASMINPUT_5, "6" (__sc_8) | |
2037 #undef LSS_BODY | |
2038 #define LSS_BODY(nr, type, name, args...) \ | |
2039 long __sc_ret, __sc_err; \ | |
2040 { \ | |
2041 register unsigned long __sc_0 __asm__ ("r0"); \ | |
2042 register unsigned long __sc_3 __asm__ ("r3"); \ | |
2043 register unsigned long __sc_4 __asm__ ("r4"); \ | |
2044 register unsigned long __sc_5 __asm__ ("r5"); \ | |
2045 register unsigned long __sc_6 __asm__ ("r6"); \ | |
2046 register unsigned long __sc_7 __asm__ ("r7"); \ | |
2047 register unsigned long __sc_8 __asm__ ("r8"); \ | |
2048 \ | |
2049 LSS_LOADARGS_##nr(name, args); \ | |
2050 __asm__ __volatile__ \ | |
2051 ("sc\n\t" \ | |
2052 "mfcr %0" \ | |
2053 : "=&r" (__sc_0), \ | |
2054 "=&r" (__sc_3), "=&r" (__sc_4), \ | |
2055 "=&r" (__sc_5), "=&r" (__sc_6), \ | |
2056 "=&r" (__sc_7), "=&r" (__sc_8) \ | |
2057 : LSS_ASMINPUT_##nr \ | |
2058 : "cr0", "ctr", "memory", \ | |
2059 "r9", "r10", "r11", "r12"); \ | |
2060 __sc_ret = __sc_3; \ | |
2061 __sc_err = __sc_0; \ | |
2062 } \ | |
2063 LSS_RETURN(type, __sc_ret, __sc_err) | |
2064 #undef _syscall0 | |
2065 #define _syscall0(type, name) \ | |
2066 type LSS_NAME(name)(void) { \ | |
2067 LSS_BODY(0, type, name); \ | |
2068 } | |
2069 #undef _syscall1 | |
2070 #define _syscall1(type, name, type1, arg1) \ | |
2071 type LSS_NAME(name)(type1 arg1) { \ | |
2072 LSS_BODY(1, type, name, arg1); \ | |
2073 } | |
2074 #undef _syscall2 | |
2075 #define _syscall2(type, name, type1, arg1, type2, arg2) \ | |
2076 type LSS_NAME(name)(type1 arg1, type2 arg2) { \ | |
2077 LSS_BODY(2, type, name, arg1, arg2); \ | |
2078 } | |
2079 #undef _syscall3 | |
2080 #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ | |
2081 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ | |
2082 LSS_BODY(3, type, name, arg1, arg2, arg3); \ | |
2083 } | |
2084 #undef _syscall4 | |
2085 #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \ | |
2086 type4, arg4) \ | |
2087 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ | |
2088 LSS_BODY(4, type, name, arg1, arg2, arg3, arg4); \ | |
2089 } | |
2090 #undef _syscall5 | |
2091 #define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \ | |
2092 type4, arg4, type5, arg5) \ | |
2093 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
2094 type5 arg5) { \ | |
2095 LSS_BODY(5, type, name, arg1, arg2, arg3, arg4, arg5); \ | |
2096 } | |
2097 #undef _syscall6 | |
2098 #define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \ | |
2099 type4, arg4, type5, arg5, type6, arg6) \ | |
2100 type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ | |
2101 type5 arg5, type6 arg6) { \ | |
2102 LSS_BODY(6, type, name, arg1, arg2, arg3, arg4, arg5, arg6); \ | |
2103 } | |
2104 /* clone function adapted from glibc 2.3.6 clone.S */ | |
2105 /* TODO(csilvers): consider wrapping some args up in a struct, like we | |
2106 * do for i386's _syscall6, so we can compile successfully on gcc 2.95 | |
2107 */ | |
2108 LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, | |
2109 int flags, void *arg, int *parent_tidptr, | |
2110 void *newtls, int *child_tidptr) { | |
2111 long __ret, __err; | |
2112 { | |
2113 register int (*__fn)(void *) __asm__ ("r8") = fn; | |
2114 register void *__cstack __asm__ ("r4") = child_stack; | |
2115 register int __flags __asm__ ("r3") = flags; | |
2116 register void * __arg __asm__ ("r9") = arg; | |
2117 register int * __ptidptr __asm__ ("r5") = parent_tidptr; | |
2118 register void * __newtls __asm__ ("r6") = newtls; | |
2119 register int * __ctidptr __asm__ ("r7") = child_tidptr; | |
2120 __asm__ __volatile__( | |
2121 /* check for fn == NULL | |
2122 * and child_stack == NULL | |
2123 */ | |
2124 "cmpwi cr0, %6, 0\n\t" | |
2125 "cmpwi cr1, %7, 0\n\t" | |
2126 "cror cr0*4+eq, cr1*4+eq, cr0*4+eq\n\t" | |
2127 "beq- cr0, 1f\n\t" | |
2128 | |
2129 /* set up stack frame for child */ | |
2130 "clrrwi %7, %7, 4\n\t" | |
2131 "li 0, 0\n\t" | |
2132 "stwu 0, -16(%7)\n\t" | |
2133 | |
2134 /* fn, arg, child_stack are saved across the syscall: r28-30 */ | |
2135 "mr 28, %6\n\t" | |
2136 "mr 29, %7\n\t" | |
2137 "mr 27, %9\n\t" | |
2138 | |
2139 /* syscall */ | |
2140 "li 0, %4\n\t" | |
2141 /* flags already in r3 | |
2142 * child_stack already in r4 | |
2143 * ptidptr already in r5 | |
2144 * newtls already in r6 | |
2145 * ctidptr already in r7 | |
2146 */ | |
2147 "sc\n\t" | |
2148 | |
2149 /* Test if syscall was successful */ | |
2150 "cmpwi cr1, 3, 0\n\t" | |
2151 "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t" | |
2152 "bne- cr1, 1f\n\t" | |
2153 | |
2154 /* Do the function call */ | |
2155 "mtctr 28\n\t" | |
2156 "mr 3, 27\n\t" | |
2157 "bctrl\n\t" | |
2158 | |
2159 /* Call _exit(r3) */ | |
2160 "li 0, %5\n\t" | |
2161 "sc\n\t" | |
2162 | |
2163 /* Return to parent */ | |
2164 "1:\n" | |
2165 "mfcr %1\n\t" | |
2166 "mr %0, 3\n\t" | |
2167 : "=r" (__ret), "=r" (__err) | |
2168 : "0" (-1), "1" (EINVAL), | |
2169 "i" (__NR_clone), "i" (__NR_exit), | |
2170 "r" (__fn), "r" (__cstack), "r" (__flags), | |
2171 "r" (__arg), "r" (__ptidptr), "r" (__newtls), | |
2172 "r" (__ctidptr) | |
2173 : "cr0", "cr1", "memory", "ctr", | |
2174 "r0", "r29", "r27", "r28"); | |
2175 } | |
2176 LSS_RETURN(int, __ret, __err); | |
2177 } | |
2178 #endif | |
2179 #define __NR__exit __NR_exit | |
2180 #define __NR__gettid __NR_gettid | |
2181 #define __NR__mremap __NR_mremap | |
2182 LSS_INLINE _syscall1(int, chdir, const char *,p) | |
2183 LSS_INLINE _syscall1(int, close, int, f) | |
2184 LSS_INLINE _syscall1(int, dup, int, f) | |
2185 LSS_INLINE _syscall2(int, dup2, int, s, | |
2186 int, d) | |
2187 LSS_INLINE _syscall3(int, execve, const char*, f, | |
2188 const char*const*,a,const char*const*, e) | |
2189 LSS_INLINE _syscall1(int, _exit, int, e) | |
2190 LSS_INLINE _syscall3(int, fcntl, int, f, | |
2191 int, c, long, a) | |
2192 LSS_INLINE _syscall0(pid_t, fork) | |
2193 LSS_INLINE _syscall2(int, fstat, int, f, | |
2194 struct kernel_stat*, b) | |
2195 LSS_INLINE _syscall2(int, fstatfs, int, f, | |
2196 struct kernel_statfs*, b) | |
2197 LSS_INLINE _syscall4(int, futex, int*, a, | |
2198 int, o, int, v, | |
2199 struct kernel_timespec*, t) | |
2200 LSS_INLINE _syscall3(int, getdents, int, f, | |
2201 struct kernel_dirent*, d, int, c) | |
2202 LSS_INLINE _syscall3(int, getdents64, int, f, | |
2203 struct kernel_dirent64*, d, int, c) | |
2204 LSS_INLINE _syscall0(gid_t, getegid) | |
2205 LSS_INLINE _syscall0(uid_t, geteuid) | |
2206 LSS_INLINE _syscall0(pid_t, getpgrp) | |
2207 LSS_INLINE _syscall0(pid_t, getpid) | |
2208 LSS_INLINE _syscall0(pid_t, getppid) | |
2209 LSS_INLINE _syscall2(int, getpriority, int, a, | |
2210 int, b) | |
2211 #if !defined(__ARM_EABI__) | |
2212 LSS_INLINE _syscall2(int, getrlimit, int, r, | |
2213 struct kernel_rlimit*, l) | |
2214 #endif | |
2215 LSS_INLINE _syscall1(pid_t, getsid, pid_t, p) | |
2216 LSS_INLINE _syscall0(pid_t, _gettid) | |
2217 LSS_INLINE _syscall2(pid_t, gettimeofday, struct kernel_timeval*, t, | |
2218 void*, tz) | |
2219 LSS_INLINE _syscall5(int, setxattr, const char *,p, | |
2220 const char *, n, const void *,v, | |
2221 size_t, s, int, f) | |
2222 LSS_INLINE _syscall5(int, lsetxattr, const char *,p, | |
2223 const char *, n, const void *,v, | |
2224 size_t, s, int, f) | |
2225 LSS_INLINE _syscall4(ssize_t, getxattr, const char *,p, | |
2226 const char *, n, void *, v, size_t, s) | |
2227 LSS_INLINE _syscall4(ssize_t, lgetxattr, const char *,p, | |
2228 const char *, n, void *, v, size_t, s) | |
2229 LSS_INLINE _syscall2(int, kill, pid_t, p, | |
2230 int, s) | |
2231 LSS_INLINE _syscall3(off_t, lseek, int, f, | |
2232 off_t, o, int, w) | |
2233 LSS_INLINE _syscall2(int, munmap, void*, s, | |
2234 size_t, l) | |
2235 LSS_INLINE _syscall6(long, move_pages, pid_t, p, | |
2236 unsigned long, n, void **,g, int *, d, | |
2237 int *, s, int, f) | |
2238 LSS_INLINE _syscall5(void*, _mremap, void*, o, | |
2239 size_t, os, size_t, ns, | |
2240 unsigned long, f, void *, a) | |
2241 LSS_INLINE _syscall3(int, open, const char*, p, | |
2242 int, f, int, m) | |
2243 LSS_INLINE _syscall3(int, poll, struct kernel_pollfd*, u, | |
2244 unsigned int, n, int, t) | |
2245 LSS_INLINE _syscall2(int, prctl, int, o, | |
2246 long, a) | |
2247 LSS_INLINE _syscall4(long, ptrace, int, r, | |
2248 pid_t, p, void *, a, void *, d) | |
2249 LSS_INLINE _syscall3(ssize_t, read, int, f, | |
2250 void *, b, size_t, c) | |
2251 LSS_INLINE _syscall3(int, readlink, const char*, p, | |
2252 char*, b, size_t, s) | |
2253 LSS_INLINE _syscall4(int, rt_sigaction, int, s, | |
2254 const struct kernel_sigaction*, a, | |
2255 struct kernel_sigaction*, o, size_t, c) | |
2256 LSS_INLINE _syscall2(int, rt_sigpending, struct kernel_sigset_t *, s, | |
2257 size_t, c) | |
2258 LSS_INLINE _syscall4(int, rt_sigprocmask, int, h, | |
2259 const struct kernel_sigset_t*, s, | |
2260 struct kernel_sigset_t*, o, size_t, c) | |
2261 LSS_INLINE _syscall2(int, rt_sigsuspend, | |
2262 const struct kernel_sigset_t*, s, size_t, c) | |
2263 LSS_INLINE _syscall3(int, sched_getaffinity,pid_t, p, | |
2264 unsigned int, l, unsigned long *, m) | |
2265 LSS_INLINE _syscall3(int, sched_setaffinity,pid_t, p, | |
2266 unsigned int, l, unsigned long *, m) | |
2267 LSS_INLINE _syscall0(int, sched_yield) | |
2268 LSS_INLINE _syscall1(long, set_tid_address, int *, t) | |
2269 LSS_INLINE _syscall1(int, setfsgid, gid_t, g) | |
2270 LSS_INLINE _syscall1(int, setfsuid, uid_t, u) | |
2271 LSS_INLINE _syscall2(int, setpgid, pid_t, p, | |
2272 pid_t, g) | |
2273 LSS_INLINE _syscall3(int, setpriority, int, a, | |
2274 int, b, int, p) | |
2275 LSS_INLINE _syscall3(int, setresgid, gid_t, r, | |
2276 gid_t, e, gid_t, s) | |
2277 LSS_INLINE _syscall3(int, setresuid, uid_t, r, | |
2278 uid_t, e, uid_t, s) | |
2279 LSS_INLINE _syscall2(int, setrlimit, int, r, | |
2280 const struct kernel_rlimit*, l) | |
2281 LSS_INLINE _syscall0(pid_t, setsid) | |
2282 LSS_INLINE _syscall2(int, sigaltstack, const stack_t*, s, | |
2283 const stack_t*, o) | |
2284 LSS_INLINE _syscall2(int, stat, const char*, f, | |
2285 struct kernel_stat*, b) | |
2286 LSS_INLINE _syscall2(int, statfs, const char*, f, | |
2287 struct kernel_statfs*, b) | |
2288 LSS_INLINE _syscall1(int, unlink, const char*, f) | |
2289 LSS_INLINE _syscall3(ssize_t, write, int, f, | |
2290 const void *, b, size_t, c) | |
2291 LSS_INLINE _syscall3(ssize_t, writev, int, f, | |
2292 const struct kernel_iovec*, v, size_t, c) | |
2293 #if defined(__x86_64__) || \ | |
2294 (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32) | |
2295 LSS_INLINE _syscall3(int, recvmsg, int, s, | |
2296 struct kernel_msghdr*, m, int, f) | |
2297 LSS_INLINE _syscall3(int, sendmsg, int, s, | |
2298 const struct kernel_msghdr*, m, int, f) | |
2299 LSS_INLINE _syscall6(int, sendto, int, s, | |
2300 const void*, m, size_t, l, | |
2301 int, f, | |
2302 const struct kernel_sockaddr*, a, int, t) | |
2303 LSS_INLINE _syscall2(int, shutdown, int, s, | |
2304 int, h) | |
2305 LSS_INLINE _syscall3(int, socket, int, d, | |
2306 int, t, int, p) | |
2307 LSS_INLINE _syscall4(int, socketpair, int, d, | |
2308 int, t, int, p, int*, s) | |
2309 #endif | |
2310 #if defined(__x86_64__) | |
2311 LSS_INLINE _syscall6(void*, mmap, void*, s, | |
2312 size_t, l, int, p, | |
2313 int, f, int, d, | |
2314 __off64_t, o) | |
2315 LSS_INLINE _syscall4(int, newfstatat, int, d, | |
2316 const char *, p, | |
2317 struct kernel_stat*, b, int, f) | |
2318 | |
2319 LSS_INLINE int LSS_NAME(setfsgid32)(gid_t gid) { | |
2320 return LSS_NAME(setfsgid)(gid); | |
2321 } | |
2322 | |
2323 LSS_INLINE int LSS_NAME(setfsuid32)(uid_t uid) { | |
2324 return LSS_NAME(setfsuid)(uid); | |
2325 } | |
2326 | |
2327 LSS_INLINE int LSS_NAME(setresgid32)(gid_t rgid, gid_t egid, gid_t sgid) { | |
2328 return LSS_NAME(setresgid)(rgid, egid, sgid); | |
2329 } | |
2330 | |
2331 LSS_INLINE int LSS_NAME(setresuid32)(uid_t ruid, uid_t euid, uid_t suid) { | |
2332 return LSS_NAME(setresuid)(ruid, euid, suid); | |
2333 } | |
2334 | |
2335 LSS_INLINE int LSS_NAME(sigaction)(int signum, | |
2336 const struct kernel_sigaction *act, | |
2337 struct kernel_sigaction *oldact) { | |
2338 /* On x86_64, the kernel requires us to always set our own | |
2339 * SA_RESTORER in order to be able to return from a signal handler. | |
2340 * This function must have a "magic" signature that the "gdb" | |
2341 * (and maybe the kernel?) can recognize. | |
2342 */ | |
2343 if (act != NULL && !(act->sa_flags & SA_RESTORER)) { | |
2344 struct kernel_sigaction a = *act; | |
2345 a.sa_flags |= SA_RESTORER; | |
2346 a.sa_restorer = LSS_NAME(restore_rt)(); | |
2347 return LSS_NAME(rt_sigaction)(signum, &a, oldact, | |
2348 (KERNEL_NSIG+7)/8); | |
2349 } else { | |
2350 return LSS_NAME(rt_sigaction)(signum, act, oldact, | |
2351 (KERNEL_NSIG+7)/8); | |
2352 } | |
2353 } | |
2354 | |
2355 LSS_INLINE int LSS_NAME(sigpending)(struct kernel_sigset_t *set) { | |
2356 return LSS_NAME(rt_sigpending)(set, (KERNEL_NSIG+7)/8); | |
2357 } | |
2358 | |
2359 LSS_INLINE int LSS_NAME(sigprocmask)(int how, | |
2360 const struct kernel_sigset_t *set, | |
2361 struct kernel_sigset_t *oldset) { | |
2362 return LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8); | |
2363 } | |
2364 | |
2365 LSS_INLINE int LSS_NAME(sigsuspend)(const struct kernel_sigset_t *set) { | |
2366 return LSS_NAME(rt_sigsuspend)(set, (KERNEL_NSIG+7)/8); | |
2367 } | |
2368 #endif | |
2369 #if defined(__x86_64__) || defined(__ARM_ARCH_3__) || \ | |
2370 defined(__ARM_EABI__) || \ | |
2371 (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32) | |
2372 LSS_INLINE _syscall4(pid_t, wait4, pid_t, p, | |
2373 int*, s, int, o, | |
2374 struct kernel_rusage*, r) | |
2375 | |
2376 LSS_INLINE pid_t LSS_NAME(waitpid)(pid_t pid, int *status, int options){ | |
2377 return LSS_NAME(wait4)(pid, status, options, 0); | |
2378 } | |
2379 #endif | |
2380 #if defined(__i386__) || defined(__x86_64__) | |
2381 LSS_INLINE _syscall4(int, openat, int, d, const char *, p, int, f, int, m) | |
2382 LSS_INLINE _syscall3(int, unlinkat, int, d, const char *, p, int, f) | |
2383 #endif | |
2384 #if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) | |
2385 #define __NR__setfsgid32 __NR_setfsgid32 | |
2386 #define __NR__setfsuid32 __NR_setfsuid32 | |
2387 #define __NR__setresgid32 __NR_setresgid32 | |
2388 #define __NR__setresuid32 __NR_setresuid32 | |
2389 #if defined(__ARM_EABI__) | |
2390 LSS_INLINE _syscall2(int, ugetrlimit, int, r, | |
2391 struct kernel_rlimit*, l) | |
2392 #endif | |
2393 LSS_INLINE _syscall1(int, _setfsgid32, gid_t, f) | |
2394 LSS_INLINE _syscall1(int, _setfsuid32, uid_t, f) | |
2395 LSS_INLINE _syscall3(int, _setresgid32, gid_t, r, | |
2396 gid_t, e, gid_t, s) | |
2397 LSS_INLINE _syscall3(int, _setresuid32, uid_t, r, | |
2398 uid_t, e, uid_t, s) | |
2399 | |
2400 LSS_INLINE int LSS_NAME(setfsgid32)(gid_t gid) { | |
2401 int rc; | |
2402 if ((rc = LSS_NAME(_setfsgid32)(gid)) < 0 && | |
2403 LSS_ERRNO == ENOSYS) { | |
2404 if ((unsigned int)gid & ~0xFFFFu) { | |
2405 rc = EINVAL; | |
2406 } else { | |
2407 rc = LSS_NAME(setfsgid)(gid); | |
2408 } | |
2409 } | |
2410 return rc; | |
2411 } | |
2412 | |
2413 LSS_INLINE int LSS_NAME(setfsuid32)(uid_t uid) { | |
2414 int rc; | |
2415 if ((rc = LSS_NAME(_setfsuid32)(uid)) < 0 && | |
2416 LSS_ERRNO == ENOSYS) { | |
2417 if ((unsigned int)uid & ~0xFFFFu) { | |
2418 rc = EINVAL; | |
2419 } else { | |
2420 rc = LSS_NAME(setfsuid)(uid); | |
2421 } | |
2422 } | |
2423 return rc; | |
2424 } | |
2425 | |
2426 LSS_INLINE int LSS_NAME(setresgid32)(gid_t rgid, gid_t egid, gid_t sgid) { | |
2427 int rc; | |
2428 if ((rc = LSS_NAME(_setresgid32)(rgid, egid, sgid)) < 0 && | |
2429 LSS_ERRNO == ENOSYS) { | |
2430 if ((unsigned int)rgid & ~0xFFFFu || | |
2431 (unsigned int)egid & ~0xFFFFu || | |
2432 (unsigned int)sgid & ~0xFFFFu) { | |
2433 rc = EINVAL; | |
2434 } else { | |
2435 rc = LSS_NAME(setresgid)(rgid, egid, sgid); | |
2436 } | |
2437 } | |
2438 return rc; | |
2439 } | |
2440 | |
2441 LSS_INLINE int LSS_NAME(setresuid32)(uid_t ruid, uid_t euid, uid_t suid) { | |
2442 int rc; | |
2443 if ((rc = LSS_NAME(_setresuid32)(ruid, euid, suid)) < 0 && | |
2444 LSS_ERRNO == ENOSYS) { | |
2445 if ((unsigned int)ruid & ~0xFFFFu || | |
2446 (unsigned int)euid & ~0xFFFFu || | |
2447 (unsigned int)suid & ~0xFFFFu) { | |
2448 rc = EINVAL; | |
2449 } else { | |
2450 rc = LSS_NAME(setresuid)(ruid, euid, suid); | |
2451 } | |
2452 } | |
2453 return rc; | |
2454 } | |
2455 #endif | |
2456 LSS_INLINE int LSS_NAME(sigemptyset)(struct kernel_sigset_t *set) { | |
2457 memset(&set->sig, 0, sizeof(set->sig)); | |
2458 return 0; | |
2459 } | |
2460 | |
2461 LSS_INLINE int LSS_NAME(sigfillset)(struct kernel_sigset_t *set) { | |
2462 memset(&set->sig, -1, sizeof(set->sig)); | |
2463 return 0; | |
2464 } | |
2465 | |
2466 LSS_INLINE int LSS_NAME(sigaddset)(struct kernel_sigset_t *set, | |
2467 int signum) { | |
2468 if (signum < 1 || signum > (int)(8*sizeof(set->sig))) { | |
2469 LSS_ERRNO = EINVAL; | |
2470 return -1; | |
2471 } else { | |
2472 set->sig[(signum - 1)/(8*sizeof(set->sig[0]))] | |
2473 |= 1UL << ((signum - 1) % (8*sizeof(set->sig[0]))); | |
2474 return 0; | |
2475 } | |
2476 } | |
2477 | |
2478 LSS_INLINE int LSS_NAME(sigdelset)(struct kernel_sigset_t *set, | |
2479 int signum) { | |
2480 if (signum < 1 || signum > (int)(8*sizeof(set->sig))) { | |
2481 LSS_ERRNO = EINVAL; | |
2482 return -1; | |
2483 } else { | |
2484 set->sig[(signum - 1)/(8*sizeof(set->sig[0]))] | |
2485 &= ~(1UL << ((signum - 1) % (8*sizeof(set->sig[0])))); | |
2486 return 0; | |
2487 } | |
2488 } | |
2489 | |
2490 LSS_INLINE int LSS_NAME(sigismember)(struct kernel_sigset_t *set, | |
2491 int signum) { | |
2492 if (signum < 1 || signum > (int)(8*sizeof(set->sig))) { | |
2493 LSS_ERRNO = EINVAL; | |
2494 return -1; | |
2495 } else { | |
2496 return !!(set->sig[(signum - 1)/(8*sizeof(set->sig[0]))] & | |
2497 (1UL << ((signum - 1) % (8*sizeof(set->sig[0]))))); | |
2498 } | |
2499 } | |
2500 #if defined(__i386__) || defined(__ARM_ARCH_3__) || \ | |
2501 defined(__ARM_EABI__) || \ | |
2502 (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || defined(__PPC__) | |
2503 #define __NR__sigaction __NR_sigaction | |
2504 #define __NR__sigpending __NR_sigpending | |
2505 #define __NR__sigprocmask __NR_sigprocmask | |
2506 #define __NR__sigsuspend __NR_sigsuspend | |
2507 #define __NR__socketcall __NR_socketcall | |
2508 LSS_INLINE _syscall2(int, fstat64, int, f, | |
2509 struct kernel_stat64 *, b) | |
2510 LSS_INLINE _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, | |
2511 loff_t *, res, uint, wh) | |
2512 #if !defined(__ARM_EABI__) | |
2513 LSS_INLINE _syscall1(void*, mmap, void*, a) | |
2514 #endif | |
2515 LSS_INLINE _syscall6(void*, mmap2, void*, s, | |
2516 size_t, l, int, p, | |
2517 int, f, int, d, | |
2518 __off64_t, o) | |
2519 LSS_INLINE _syscall3(int, _sigaction, int, s, | |
2520 const struct kernel_old_sigaction*, a, | |
2521 struct kernel_old_sigaction*, o) | |
2522 LSS_INLINE _syscall1(int, _sigpending, unsigned long*, s) | |
2523 LSS_INLINE _syscall3(int, _sigprocmask, int, h, | |
2524 const unsigned long*, s, | |
2525 unsigned long*, o) | |
2526 #ifdef __PPC__ | |
2527 LSS_INLINE _syscall1(int, _sigsuspend, unsigned long, s) | |
2528 #else | |
2529 LSS_INLINE _syscall3(int, _sigsuspend, const void*, a, | |
2530 int, b, | |
2531 unsigned long, s) | |
2532 #endif | |
2533 LSS_INLINE _syscall2(int, stat64, const char *, p, | |
2534 struct kernel_stat64 *, b) | |
2535 | |
2536 LSS_INLINE int LSS_NAME(sigaction)(int signum, | |
2537 const struct kernel_sigaction *act, | |
2538 struct kernel_sigaction *oldact) { | |
2539 int old_errno = LSS_ERRNO; | |
2540 int rc; | |
2541 struct kernel_sigaction a; | |
2542 if (act != NULL) { | |
2543 a = *act; | |
2544 #ifdef __i386__ | |
2545 /* On i386, the kernel requires us to always set our own | |
2546 * SA_RESTORER when using realtime signals. Otherwise, it does not | |
2547 * know how to return from a signal handler. This function must have | |
2548 * a "magic" signature that the "gdb" (and maybe the kernel?) can | |
2549 * recognize. | |
2550 * Apparently, a SA_RESTORER is implicitly set by the kernel, when | |
2551 * using non-realtime signals. | |
2552 * | |
2553 * TODO: Test whether ARM needs a restorer | |
2554 */ | |
2555 if (!(a.sa_flags & SA_RESTORER)) { | |
2556 a.sa_flags |= SA_RESTORER; | |
2557 a.sa_restorer = (a.sa_flags & SA_SIGINFO) | |
2558 ? LSS_NAME(restore_rt)() : LSS_NAME(restore)(); | |
2559 } | |
2560 #endif | |
2561 } | |
2562 rc = LSS_NAME(rt_sigaction)(signum, act ? &a : act, oldact, | |
2563 (KERNEL_NSIG+7)/8); | |
2564 if (rc < 0 && LSS_ERRNO == ENOSYS) { | |
2565 struct kernel_old_sigaction oa, ooa, *ptr_a = &oa, *ptr_oa = &ooa; | |
2566 if (!act) { | |
2567 ptr_a = NULL; | |
2568 } else { | |
2569 oa.sa_handler_ = act->sa_handler_; | |
2570 memcpy(&oa.sa_mask, &act->sa_mask, sizeof(oa.sa_mask)); | |
2571 #ifndef __mips__ | |
2572 oa.sa_restorer = act->sa_restorer; | |
2573 #endif | |
2574 oa.sa_flags = act->sa_flags; | |
2575 } | |
2576 if (!oldact) { | |
2577 ptr_oa = NULL; | |
2578 } | |
2579 LSS_ERRNO = old_errno; | |
2580 rc = LSS_NAME(_sigaction)(signum, ptr_a, ptr_oa); | |
2581 if (rc == 0 && oldact) { | |
2582 if (act) { | |
2583 memcpy(oldact, act, sizeof(*act)); | |
2584 } else { | |
2585 memset(oldact, 0, sizeof(*oldact)); | |
2586 } | |
2587 oldact->sa_handler_ = ptr_oa->sa_handler_; | |
2588 oldact->sa_flags = ptr_oa->sa_flags; | |
2589 memcpy(&oldact->sa_mask, &ptr_oa->sa_mask, sizeof(ptr_oa->sa_mask)); | |
2590 #ifndef __mips__ | |
2591 oldact->sa_restorer = ptr_oa->sa_restorer; | |
2592 #endif | |
2593 } | |
2594 } | |
2595 return rc; | |
2596 } | |
2597 | |
2598 LSS_INLINE int LSS_NAME(sigpending)(struct kernel_sigset_t *set) { | |
2599 int old_errno = LSS_ERRNO; | |
2600 int rc = LSS_NAME(rt_sigpending)(set, (KERNEL_NSIG+7)/8); | |
2601 if (rc < 0 && LSS_ERRNO == ENOSYS) { | |
2602 LSS_ERRNO = old_errno; | |
2603 LSS_NAME(sigemptyset)(set); | |
2604 rc = LSS_NAME(_sigpending)(&set->sig[0]); | |
2605 } | |
2606 return rc; | |
2607 } | |
2608 | |
2609 LSS_INLINE int LSS_NAME(sigprocmask)(int how, | |
2610 const struct kernel_sigset_t *set, | |
2611 struct kernel_sigset_t *oldset) { | |
2612 int olderrno = LSS_ERRNO; | |
2613 int rc = LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8); | |
2614 if (rc < 0 && LSS_ERRNO == ENOSYS) { | |
2615 LSS_ERRNO = olderrno; | |
2616 if (oldset) { | |
2617 LSS_NAME(sigemptyset)(oldset); | |
2618 } | |
2619 rc = LSS_NAME(_sigprocmask)(how, | |
2620 set ? &set->sig[0] : NULL, | |
2621 oldset ? &oldset->sig[0] : NULL); | |
2622 } | |
2623 return rc; | |
2624 } | |
2625 | |
2626 LSS_INLINE int LSS_NAME(sigsuspend)(const struct kernel_sigset_t *set) { | |
2627 int olderrno = LSS_ERRNO; | |
2628 int rc = LSS_NAME(rt_sigsuspend)(set, (KERNEL_NSIG+7)/8); | |
2629 if (rc < 0 && LSS_ERRNO == ENOSYS) { | |
2630 LSS_ERRNO = olderrno; | |
2631 rc = LSS_NAME(_sigsuspend)( | |
2632 #ifndef __PPC__ | |
2633 set, 0, | |
2634 #endif | |
2635 set->sig[0]); | |
2636 } | |
2637 return rc; | |
2638 } | |
2639 #endif | |
2640 #if defined(__PPC__) | |
2641 #undef LSS_SC_LOADARGS_0 | |
2642 #define LSS_SC_LOADARGS_0(dummy...) | |
2643 #undef LSS_SC_LOADARGS_1 | |
2644 #define LSS_SC_LOADARGS_1(arg1) \ | |
2645 __sc_4 = (unsigned long) (arg1) | |
2646 #undef LSS_SC_LOADARGS_2 | |
2647 #define LSS_SC_LOADARGS_2(arg1, arg2) \ | |
2648 LSS_SC_LOADARGS_1(arg1); \ | |
2649 __sc_5 = (unsigned long) (arg2) | |
2650 #undef LSS_SC_LOADARGS_3 | |
2651 #define LSS_SC_LOADARGS_3(arg1, arg2, arg3) \ | |
2652 LSS_SC_LOADARGS_2(arg1, arg2); \ | |
2653 __sc_6 = (unsigned long) (arg3) | |
2654 #undef LSS_SC_LOADARGS_4 | |
2655 #define LSS_SC_LOADARGS_4(arg1, arg2, arg3, arg4) \ | |
2656 LSS_SC_LOADARGS_3(arg1, arg2, arg3); \ | |
2657 __sc_7 = (unsigned long) (arg4) | |
2658 #undef LSS_SC_LOADARGS_5 | |
2659 #define LSS_SC_LOADARGS_5(arg1, arg2, arg3, arg4, arg5) \ | |
2660 LSS_SC_LOADARGS_4(arg1, arg2, arg3, arg4); \ | |
2661 __sc_8 = (unsigned long) (arg5) | |
2662 #undef LSS_SC_BODY | |
2663 #define LSS_SC_BODY(nr, type, opt, args...) \ | |
2664 long __sc_ret, __sc_err; \ | |
2665 { \ | |
2666 register unsigned long __sc_0 __asm__ ("r0") = __NR_socketcall; \ | |
2667 register unsigned long __sc_3 __asm__ ("r3") = opt; \ | |
2668 register unsigned long __sc_4 __asm__ ("r4"); \ | |
2669 register unsigned long __sc_5 __asm__ ("r5"); \ | |
2670 register unsigned long __sc_6 __asm__ ("r6"); \ | |
2671 register unsigned long __sc_7 __asm__ ("r7"); \ | |
2672 register unsigned long __sc_8 __asm__ ("r8"); \ | |
2673 LSS_SC_LOADARGS_##nr(args); \ | |
2674 __asm__ __volatile__ \ | |
2675 ("stwu 1, -48(1)\n\t" \ | |
2676 "stw 4, 20(1)\n\t" \ | |
2677 "stw 5, 24(1)\n\t" \ | |
2678 "stw 6, 28(1)\n\t" \ | |
2679 "stw 7, 32(1)\n\t" \ | |
2680 "stw 8, 36(1)\n\t" \ | |
2681 "addi 4, 1, 20\n\t" \ | |
2682 "sc\n\t" \ | |
2683 "mfcr %0" \ | |
2684 : "=&r" (__sc_0), \ | |
2685 "=&r" (__sc_3), "=&r" (__sc_4), \ | |
2686 "=&r" (__sc_5), "=&r" (__sc_6), \ | |
2687 "=&r" (__sc_7), "=&r" (__sc_8) \ | |
2688 : LSS_ASMINPUT_##nr \ | |
2689 : "cr0", "ctr", "memory"); \ | |
2690 __sc_ret = __sc_3; \ | |
2691 __sc_err = __sc_0; \ | |
2692 } \ | |
2693 LSS_RETURN(type, __sc_ret, __sc_err) | |
2694 | |
2695 LSS_INLINE ssize_t LSS_NAME(recvmsg)(int s,struct kernel_msghdr *msg, | |
2696 int flags){ | |
2697 LSS_SC_BODY(3, ssize_t, 17, s, msg, flags); | |
2698 } | |
2699 | |
2700 LSS_INLINE ssize_t LSS_NAME(sendmsg)(int s, | |
2701 const struct kernel_msghdr *msg, | |
2702 int flags) { | |
2703 LSS_SC_BODY(3, ssize_t, 16, s, msg, flags); | |
2704 } | |
2705 | |
2706 // TODO(csilvers): why is this ifdef'ed out? | |
2707 #if 0 | |
2708 LSS_INLINE ssize_t LSS_NAME(sendto)(int s, const void *buf, size_t len, | |
2709 int flags, | |
2710 const struct kernel_sockaddr *to, | |
2711 unsigned int tolen) { | |
2712 LSS_BODY(6, ssize_t, 11, s, buf, len, flags, to, tolen); | |
2713 } | |
2714 #endif | |
2715 | |
2716 LSS_INLINE int LSS_NAME(shutdown)(int s, int how) { | |
2717 LSS_SC_BODY(2, int, 13, s, how); | |
2718 } | |
2719 | |
2720 LSS_INLINE int LSS_NAME(socket)(int domain, int type, int protocol) { | |
2721 LSS_SC_BODY(3, int, 1, domain, type, protocol); | |
2722 } | |
2723 | |
2724 LSS_INLINE int LSS_NAME(socketpair)(int d, int type, int protocol, | |
2725 int sv[2]) { | |
2726 LSS_SC_BODY(4, int, 8, d, type, protocol, sv); | |
2727 } | |
2728 #endif | |
2729 #if defined(__ARM_EABI__) | |
2730 LSS_INLINE _syscall3(ssize_t, recvmsg, int, s, struct kernel_msghdr*, msg, | |
2731 int, flags); | |
2732 LSS_INLINE _syscall3(ssize_t, sendmsg, int, s, const struct kernel_msghdr*, | |
2733 msg, int, flags); | |
2734 LSS_INLINE _syscall6(ssize_t, sendto, int, s, const void*, buf, size_t, len, | |
2735 int, falgs, const struct kernel_sockaddr*, to, | |
2736 unsigned int, tolen); | |
2737 LSS_INLINE _syscall2(int, shutdown, int, s, int, how); | |
2738 LSS_INLINE _syscall3(int, socket, int, domain, int, type, int, protocol); | |
2739 LSS_INLINE _syscall4(int, socketpair, int, d, int, type, int, protocol, | |
2740 int*, sv); | |
2741 #endif | |
2742 #if defined(__i386__) || defined(__ARM_ARCH_3__) || \ | |
2743 (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) | |
2744 #define __NR__socketcall __NR_socketcall | |
2745 LSS_INLINE _syscall2(int, _socketcall, int, c, | |
2746 va_list, a) | |
2747 LSS_INLINE int LSS_NAME(socketcall)(int op, ...) { | |
2748 int rc; | |
2749 va_list ap; | |
2750 va_start(ap, op); | |
2751 rc = LSS_NAME(_socketcall)(op, ap); | |
2752 va_end(ap); | |
2753 return rc; | |
2754 } | |
2755 LSS_INLINE ssize_t LSS_NAME(recvmsg)(int s,struct kernel_msghdr *msg, | |
2756 int flags){ | |
2757 return (ssize_t)LSS_NAME(socketcall)(17, s, msg, flags); | |
2758 } | |
2759 LSS_INLINE ssize_t LSS_NAME(sendmsg)(int s, | |
2760 const struct kernel_msghdr *msg, | |
2761 int flags) { | |
2762 return (ssize_t)LSS_NAME(socketcall)(16, s, msg, flags); | |
2763 } | |
2764 LSS_INLINE ssize_t LSS_NAME(sendto)(int s, const void *buf, size_t len, | |
2765 int flags, | |
2766 const struct kernel_sockaddr *to, | |
2767 unsigned int tolen) { | |
2768 return (ssize_t)LSS_NAME(socketcall)(11, s, buf, len, flags, to, tolen); | |
2769 } | |
2770 LSS_INLINE int LSS_NAME(shutdown)(int s, int how) { | |
2771 return LSS_NAME(socketcall)(13, s, how); | |
2772 } | |
2773 LSS_INLINE int LSS_NAME(socket)(int domain, int type, int protocol) { | |
2774 return LSS_NAME(socketcall)(1, domain, type, protocol); | |
2775 } | |
2776 | |
2777 LSS_INLINE int LSS_NAME(socketpair)(int d, int type, int protocol, | |
2778 int sv[2]) { | |
2779 return LSS_NAME(socketcall)(8, d, type, protocol, sv); | |
2780 } | |
2781 #endif | |
2782 #if defined(__i386__) || defined(__PPC__) | |
2783 LSS_INLINE _syscall4(int, fstatat64, int, d, | |
2784 const char *, p, | |
2785 struct kernel_stat64 *, b, int, f) | |
2786 #endif | |
2787 #if defined(__i386__) || defined(__PPC__) || \ | |
2788 (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) | |
2789 LSS_INLINE _syscall3(pid_t, waitpid, pid_t, p, | |
2790 int*, s, int, o) | |
2791 #endif | |
2792 #if defined(__mips__) | |
2793 /* sys_pipe() on MIPS has non-standard calling conventions, as it returns | |
2794 * both file handles through CPU registers. | |
2795 */ | |
2796 LSS_INLINE int LSS_NAME(pipe)(int *p) { | |
2797 register unsigned long __v0 __asm__("$2") = __NR_pipe; | |
2798 register unsigned long __v1 __asm__("$3"); | |
2799 register unsigned long __r7 __asm__("$7"); | |
2800 __asm__ __volatile__ ("syscall\n" | |
2801 : "=&r"(__v0), "=&r"(__v1), "+r" (__r7) | |
2802 : "0"(__v0) | |
2803 : "$8", "$9", "$10", "$11", "$12", | |
2804 "$13", "$14", "$15", "$24", "memory"); | |
2805 if (__r7) { | |
2806 LSS_ERRNO = __v0; | |
2807 return -1; | |
2808 } else { | |
2809 p[0] = __v0; | |
2810 p[1] = __v1; | |
2811 return 0; | |
2812 } | |
2813 } | |
2814 #else | |
2815 LSS_INLINE _syscall1(int, pipe, int *, p) | |
2816 #endif | |
2817 /* TODO(csilvers): see if ppc can/should support this as well */ | |
2818 #if defined(__i386__) || defined(__ARM_ARCH_3__) || \ | |
2819 defined(__ARM_EABI__) || \ | |
2820 (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64) | |
2821 #define __NR__statfs64 __NR_statfs64 | |
2822 #define __NR__fstatfs64 __NR_fstatfs64 | |
2823 LSS_INLINE _syscall3(int, _statfs64, const char*, p, | |
2824 size_t, s,struct kernel_statfs64*, b) | |
2825 LSS_INLINE _syscall3(int, _fstatfs64, int, f, | |
2826 size_t, s,struct kernel_statfs64*, b) | |
2827 LSS_INLINE int LSS_NAME(statfs64)(const char *p, | |
2828 struct kernel_statfs64 *b) { | |
2829 return LSS_NAME(_statfs64)(p, sizeof(*b), b); | |
2830 } | |
2831 LSS_INLINE int LSS_NAME(fstatfs64)(int f,struct kernel_statfs64 *b) { | |
2832 return LSS_NAME(_fstatfs64)(f, sizeof(*b), b); | |
2833 } | |
2834 #endif | |
2835 | |
2836 LSS_INLINE int LSS_NAME(execv)(const char *path, const char *const argv[]) { | |
2837 extern char **environ; | |
2838 return LSS_NAME(execve)(path, argv, (const char *const *)environ); | |
2839 } | |
2840 | |
2841 LSS_INLINE pid_t LSS_NAME(gettid)() { | |
2842 pid_t tid = LSS_NAME(_gettid)(); | |
2843 if (tid != -1) { | |
2844 return tid; | |
2845 } | |
2846 return LSS_NAME(getpid)(); | |
2847 } | |
2848 | |
2849 LSS_INLINE void *LSS_NAME(mremap)(void *old_address, size_t old_size, | |
2850 size_t new_size, int flags, ...) { | |
2851 va_list ap; | |
2852 void *new_address, *rc; | |
2853 va_start(ap, flags); | |
2854 new_address = va_arg(ap, void *); | |
2855 rc = LSS_NAME(_mremap)(old_address, old_size, new_size, | |
2856 flags, new_address); | |
2857 va_end(ap); | |
2858 return rc; | |
2859 } | |
2860 | |
2861 LSS_INLINE int LSS_NAME(ptrace_detach)(pid_t pid) { | |
2862 /* PTRACE_DETACH can sometimes forget to wake up the tracee and it | |
2863 * then sends job control signals to the real parent, rather than to | |
2864 * the tracer. We reduce the risk of this happening by starting a | |
2865 * whole new time slice, and then quickly sending a SIGCONT signal | |
2866 * right after detaching from the tracee. | |
2867 */ | |
2868 int rc, err; | |
2869 LSS_NAME(sched_yield)(); | |
2870 rc = LSS_NAME(ptrace)(PTRACE_DETACH, pid, (void *)0, (void *)0); | |
2871 err = LSS_ERRNO; | |
2872 LSS_NAME(kill)(pid, SIGCONT); | |
2873 LSS_ERRNO = err; | |
2874 return rc; | |
2875 } | |
2876 | |
2877 LSS_INLINE int LSS_NAME(raise)(int sig) { | |
2878 return LSS_NAME(kill)(LSS_NAME(getpid)(), sig); | |
2879 } | |
2880 | |
2881 LSS_INLINE int LSS_NAME(setpgrp)() { | |
2882 return LSS_NAME(setpgid)(0, 0); | |
2883 } | |
2884 | |
2885 LSS_INLINE int LSS_NAME(sysconf)(int name) { | |
2886 extern int __getpagesize(void); | |
2887 switch (name) { | |
2888 case _SC_OPEN_MAX: { | |
2889 struct kernel_rlimit limit; | |
2890 #if defined(__ARM_EABI__) | |
2891 return LSS_NAME(ugetrlimit)(RLIMIT_NOFILE, &limit) < 0 | |
2892 ? 8192 : limit.rlim_cur; | |
2893 #else | |
2894 return LSS_NAME(getrlimit)(RLIMIT_NOFILE, &limit) < 0 | |
2895 ? 8192 : limit.rlim_cur; | |
2896 #endif | |
2897 } | |
2898 case _SC_PAGESIZE: | |
2899 return __getpagesize(); | |
2900 default: | |
2901 errno = ENOSYS; | |
2902 return -1; | |
2903 } | |
2904 } | |
2905 #if defined(__x86_64__) || \ | |
2906 (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI64) | |
2907 /* pread64() and pwrite64() do not exist on 64-bit systems... */ | |
2908 LSS_INLINE _syscall3(int, readahead, int, f, | |
2909 loff_t, o, unsigned, c) | |
2910 #else | |
2911 #define __NR__pread64 __NR_pread64 | |
2912 #define __NR__pwrite64 __NR_pwrite64 | |
2913 #define __NR__readahead __NR_readahead | |
2914 LSS_INLINE _syscall5(ssize_t, _pread64, int, f, | |
2915 void *, b, size_t, c, unsigned, o1, | |
2916 unsigned, o2) | |
2917 LSS_INLINE _syscall5(ssize_t, _pwrite64, int, f, | |
2918 const void *, b, size_t, c, unsigned, o1, | |
2919 long, o2) | |
2920 LSS_INLINE _syscall4(int, _readahead, int, f, | |
2921 unsigned, o1, unsigned, o2, size_t, c) | |
2922 /* We force 64bit-wide parameters onto the stack, then access each | |
2923 * 32-bit component individually. This guarantees that we build the | |
2924 * correct parameters independent of the native byte-order of the | |
2925 * underlying architecture. | |
2926 */ | |
2927 LSS_INLINE ssize_t LSS_NAME(pread64)(int fd, void *buf, size_t count, | |
2928 loff_t off) { | |
2929 union { loff_t off; unsigned arg[2]; } o = { off }; | |
2930 return LSS_NAME(_pread64)(fd, buf, count, o.arg[0], o.arg[1]); | |
2931 } | |
2932 LSS_INLINE ssize_t LSS_NAME(pwrite64)(int fd, const void *buf, | |
2933 size_t count, loff_t off) { | |
2934 union { loff_t off; unsigned arg[2]; } o = { off }; | |
2935 return LSS_NAME(_pwrite64)(fd, buf, count, o.arg[0], o.arg[1]); | |
2936 } | |
2937 LSS_INLINE int LSS_NAME(readahead)(int fd, loff_t off, int len) { | |
2938 union { loff_t off; unsigned arg[2]; } o = { off }; | |
2939 return LSS_NAME(_readahead)(fd, o.arg[0], o.arg[1], len); | |
2940 } | |
2941 #endif | |
2942 #endif | |
2943 | |
2944 #if defined(__cplusplus) && !defined(SYS_CPLUSPLUS) | |
2945 } | |
2946 #endif | |
2947 | |
2948 #endif | |
2949 #endif | |
OLD | NEW |