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