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