1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 /* nolibc.h 3 * Copyright (C) 2017-2018 Willy Tarreau <w@1wt.eu> 4 */ 5 6 /* some archs (at least aarch64) don't expose the regular syscalls anymore by 7 * default, either because they have an "_at" replacement, or because there are 8 * more modern alternatives. For now we'd rather still use them. 9 */ 10 #define __ARCH_WANT_SYSCALL_NO_AT 11 #define __ARCH_WANT_SYSCALL_NO_FLAGS 12 #define __ARCH_WANT_SYSCALL_DEPRECATED 13 14 #include <asm/unistd.h> 15 #include <asm/ioctls.h> 16 #include <asm/errno.h> 17 #include <linux/fs.h> 18 #include <linux/loop.h> 19 20 #define NOLIBC 21 22 /* Build a static executable this way : 23 * $ gcc -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \ 24 * -static -include nolibc.h -lgcc -o hello hello.c 25 * 26 * Useful calling convention table found here : 27 * http://man7.org/linux/man-pages/man2/syscall.2.html 28 * 29 * This doc is even better : 30 * https://w3challs.com/syscalls/ 31 */ 32 33 34 /* this way it will be removed if unused */ 35 static int errno; 36 37 #ifndef NOLIBC_IGNORE_ERRNO 38 #define SET_ERRNO(v) do { errno = (v); } while (0) 39 #else 40 #define SET_ERRNO(v) do { } while (0) 41 #endif 42 43 /* errno codes all ensure that they will not conflict with a valid pointer 44 * because they all correspond to the highest addressable memry page. 45 */ 46 #define MAX_ERRNO 4095 47 48 /* Declare a few quite common macros and types that usually are in stdlib.h, 49 * stdint.h, ctype.h, unistd.h and a few other common locations. 50 */ 51 52 #define NULL ((void *)0) 53 54 /* stdint types */ 55 typedef unsigned char uint8_t; 56 typedef signed char int8_t; 57 typedef unsigned short uint16_t; 58 typedef signed short int16_t; 59 typedef unsigned int uint32_t; 60 typedef signed int int32_t; 61 typedef unsigned long long uint64_t; 62 typedef signed long long int64_t; 63 typedef unsigned long size_t; 64 typedef signed long ssize_t; 65 typedef unsigned long uintptr_t; 66 typedef signed long intptr_t; 67 typedef signed long ptrdiff_t; 68 69 /* for stat() */ 70 typedef unsigned int dev_t; 71 typedef unsigned long ino_t; 72 typedef unsigned int mode_t; 73 typedef signed int pid_t; 74 typedef unsigned int uid_t; 75 typedef unsigned int gid_t; 76 typedef unsigned long nlink_t; 77 typedef signed long off_t; 78 typedef signed long blksize_t; 79 typedef signed long blkcnt_t; 80 typedef signed long time_t; 81 82 /* for poll() */ 83 struct pollfd { 84 int fd; 85 short int events; 86 short int revents; 87 }; 88 89 /* for select() */ 90 struct timeval { 91 long tv_sec; 92 long tv_usec; 93 }; 94 95 /* for pselect() */ 96 struct timespec { 97 long tv_sec; 98 long tv_nsec; 99 }; 100 101 /* for gettimeofday() */ 102 struct timezone { 103 int tz_minuteswest; 104 int tz_dsttime; 105 }; 106 107 /* for getdents64() */ 108 struct linux_dirent64 { 109 uint64_t d_ino; 110 int64_t d_off; 111 unsigned short d_reclen; 112 unsigned char d_type; 113 char d_name[]; 114 }; 115 116 /* commonly an fd_set represents 256 FDs */ 117 #define FD_SETSIZE 256 118 typedef struct { uint32_t fd32[FD_SETSIZE/32]; } fd_set; 119 120 /* needed by wait4() */ 121 struct rusage { 122 struct timeval ru_utime; 123 struct timeval ru_stime; 124 long ru_maxrss; 125 long ru_ixrss; 126 long ru_idrss; 127 long ru_isrss; 128 long ru_minflt; 129 long ru_majflt; 130 long ru_nswap; 131 long ru_inblock; 132 long ru_oublock; 133 long ru_msgsnd; 134 long ru_msgrcv; 135 long ru_nsignals; 136 long ru_nvcsw; 137 long ru_nivcsw; 138 }; 139 140 /* stat flags (WARNING, octal here) */ 141 #define S_IFDIR 0040000 142 #define S_IFCHR 0020000 143 #define S_IFBLK 0060000 144 #define S_IFREG 0100000 145 #define S_IFIFO 0010000 146 #define S_IFLNK 0120000 147 #define S_IFSOCK 0140000 148 #define S_IFMT 0170000 149 150 #define S_ISDIR(mode) (((mode) & S_IFDIR) == S_IFDIR) 151 #define S_ISCHR(mode) (((mode) & S_IFCHR) == S_IFCHR) 152 #define S_ISBLK(mode) (((mode) & S_IFBLK) == S_IFBLK) 153 #define S_ISREG(mode) (((mode) & S_IFREG) == S_IFREG) 154 #define S_ISFIFO(mode) (((mode) & S_IFIFO) == S_IFIFO) 155 #define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK) 156 #define S_ISSOCK(mode) (((mode) & S_IFSOCK) == S_IFSOCK) 157 158 #define DT_UNKNOWN 0 159 #define DT_FIFO 1 160 #define DT_CHR 2 161 #define DT_DIR 4 162 #define DT_BLK 6 163 #define DT_REG 8 164 #define DT_LNK 10 165 #define DT_SOCK 12 166 167 /* all the *at functions */ 168 #ifndef AT_FDWCD 169 #define AT_FDCWD -100 170 #endif 171 172 /* lseek */ 173 #define SEEK_SET 0 174 #define SEEK_CUR 1 175 #define SEEK_END 2 176 177 /* reboot */ 178 #define LINUX_REBOOT_MAGIC1 0xfee1dead 179 #define LINUX_REBOOT_MAGIC2 0x28121969 180 #define LINUX_REBOOT_CMD_HALT 0xcdef0123 181 #define LINUX_REBOOT_CMD_POWER_OFF 0x4321fedc 182 #define LINUX_REBOOT_CMD_RESTART 0x01234567 183 #define LINUX_REBOOT_CMD_SW_SUSPEND 0xd000fce2 184 185 186 /* The format of the struct as returned by the libc to the application, which 187 * significantly differs from the format returned by the stat() syscall flavours. 188 */ 189 struct stat { 190 dev_t st_dev; /* ID of device containing file */ 191 ino_t st_ino; /* inode number */ 192 mode_t st_mode; /* protection */ 193 nlink_t st_nlink; /* number of hard links */ 194 uid_t st_uid; /* user ID of owner */ 195 gid_t st_gid; /* group ID of owner */ 196 dev_t st_rdev; /* device ID (if special file) */ 197 off_t st_size; /* total size, in bytes */ 198 blksize_t st_blksize; /* blocksize for file system I/O */ 199 blkcnt_t st_blocks; /* number of 512B blocks allocated */ 200 time_t st_atime; /* time of last access */ 201 time_t st_mtime; /* time of last modification */ 202 time_t st_ctime; /* time of last status change */ 203 }; 204 205 #define WEXITSTATUS(status) (((status) & 0xff00) >> 8) 206 #define WIFEXITED(status) (((status) & 0x7f) == 0) 207 208 209 /* Below comes the architecture-specific code. For each architecture, we have 210 * the syscall declarations and the _start code definition. This is the only 211 * global part. On all architectures the kernel puts everything in the stack 212 * before jumping to _start just above us, without any return address (_start 213 * is not a function but an entry pint). So at the stack pointer we find argc. 214 * Then argv[] begins, and ends at the first NULL. Then we have envp which 215 * starts and ends with a NULL as well. So envp=argv+argc+1. 216 */ 217 218 #if defined(__x86_64__) 219 /* Syscalls for x86_64 : 220 * - registers are 64-bit 221 * - syscall number is passed in rax 222 * - arguments are in rdi, rsi, rdx, r10, r8, r9 respectively 223 * - the system call is performed by calling the syscall instruction 224 * - syscall return comes in rax 225 * - rcx and r8..r11 may be clobbered, others are preserved. 226 * - the arguments are cast to long and assigned into the target registers 227 * which are then simply passed as registers to the asm code, so that we 228 * don't have to experience issues with register constraints. 229 * - the syscall number is always specified last in order to allow to force 230 * some registers before (gcc refuses a %-register at the last position). 231 */ 232 233 #define my_syscall0(num) \ 234 ({ \ 235 long _ret; \ 236 register long _num asm("rax") = (num); \ 237 \ 238 asm volatile ( \ 239 "syscall\n" \ 240 : "=a" (_ret) \ 241 : ""(_num) \ 242 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \ 243 ); \ 244 _ret; \ 245 }) 246 247 #define my_syscall1(num, arg1) \ 248 ({ \ 249 long _ret; \ 250 register long _num asm("rax") = (num); \ 251 register long _arg1 asm("rdi") = (long)(arg1); \ 252 \ 253 asm volatile ( \ 254 "syscall\n" \ 255 : "=a" (_ret) \ 256 : "r"(_arg1), \ 257 ""(_num) \ 258 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \ 259 ); \ 260 _ret; \ 261 }) 262 263 #define my_syscall2(num, arg1, arg2) \ 264 ({ \ 265 long _ret; \ 266 register long _num asm("rax") = (num); \ 267 register long _arg1 asm("rdi") = (long)(arg1); \ 268 register long _arg2 asm("rsi") = (long)(arg2); \ 269 \ 270 asm volatile ( \ 271 "syscall\n" \ 272 : "=a" (_ret) \ 273 : "r"(_arg1), "r"(_arg2), \ 274 ""(_num) \ 275 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \ 276 ); \ 277 _ret; \ 278 }) 279 280 #define my_syscall3(num, arg1, arg2, arg3) \ 281 ({ \ 282 long _ret; \ 283 register long _num asm("rax") = (num); \ 284 register long _arg1 asm("rdi") = (long)(arg1); \ 285 register long _arg2 asm("rsi") = (long)(arg2); \ 286 register long _arg3 asm("rdx") = (long)(arg3); \ 287 \ 288 asm volatile ( \ 289 "syscall\n" \ 290 : "=a" (_ret) \ 291 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ 292 ""(_num) \ 293 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \ 294 ); \ 295 _ret; \ 296 }) 297 298 #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 299 ({ \ 300 long _ret; \ 301 register long _num asm("rax") = (num); \ 302 register long _arg1 asm("rdi") = (long)(arg1); \ 303 register long _arg2 asm("rsi") = (long)(arg2); \ 304 register long _arg3 asm("rdx") = (long)(arg3); \ 305 register long _arg4 asm("r10") = (long)(arg4); \ 306 \ 307 asm volatile ( \ 308 "syscall\n" \ 309 : "=a" (_ret), "=r"(_arg4) \ 310 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 311 ""(_num) \ 312 : "rcx", "r8", "r9", "r11", "memory", "cc" \ 313 ); \ 314 _ret; \ 315 }) 316 317 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 318 ({ \ 319 long _ret; \ 320 register long _num asm("rax") = (num); \ 321 register long _arg1 asm("rdi") = (long)(arg1); \ 322 register long _arg2 asm("rsi") = (long)(arg2); \ 323 register long _arg3 asm("rdx") = (long)(arg3); \ 324 register long _arg4 asm("r10") = (long)(arg4); \ 325 register long _arg5 asm("r8") = (long)(arg5); \ 326 \ 327 asm volatile ( \ 328 "syscall\n" \ 329 : "=a" (_ret), "=r"(_arg4), "=r"(_arg5) \ 330 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 331 ""(_num) \ 332 : "rcx", "r9", "r11", "memory", "cc" \ 333 ); \ 334 _ret; \ 335 }) 336 337 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 338 ({ \ 339 long _ret; \ 340 register long _num asm("rax") = (num); \ 341 register long _arg1 asm("rdi") = (long)(arg1); \ 342 register long _arg2 asm("rsi") = (long)(arg2); \ 343 register long _arg3 asm("rdx") = (long)(arg3); \ 344 register long _arg4 asm("r10") = (long)(arg4); \ 345 register long _arg5 asm("r8") = (long)(arg5); \ 346 register long _arg6 asm("r9") = (long)(arg6); \ 347 \ 348 asm volatile ( \ 349 "syscall\n" \ 350 : "=a" (_ret), "=r"(_arg4), "=r"(_arg5) \ 351 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 352 "r"(_arg6), ""(_num) \ 353 : "rcx", "r11", "memory", "cc" \ 354 ); \ 355 _ret; \ 356 }) 357 358 /* startup code */ 359 asm(".section .text\n" 360 ".global _start\n" 361 "_start:\n" 362 "pop %rdi\n" // argc (first arg, %rdi) 363 "mov %rsp, %rsi\n" // argv[] (second arg, %rsi) 364 "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx) 365 "and $-16, %rsp\n" // x86 ABI : esp must be 16-byte aligned when 366 "sub $8, %rsp\n" // entering the callee 367 "call main\n" // main() returns the status code, we'll exit with it. 368 "movzb %al, %rdi\n" // retrieve exit code from 8 lower bits 369 "mov $60, %rax\n" // NR_exit == 60 370 "syscall\n" // really exit 371 "hlt\n" // ensure it does not return 372 ""); 373 374 /* fcntl / open */ 375 #define O_RDONLY 0 376 #define O_WRONLY 1 377 #define O_RDWR 2 378 #define O_CREAT 0x40 379 #define O_EXCL 0x80 380 #define O_NOCTTY 0x100 381 #define O_TRUNC 0x200 382 #define O_APPEND 0x400 383 #define O_NONBLOCK 0x800 384 #define O_DIRECTORY 0x10000 385 386 /* The struct returned by the stat() syscall, equivalent to stat64(). The 387 * syscall returns 116 bytes and stops in the middle of __unused. 388 */ 389 struct sys_stat_struct { 390 unsigned long st_dev; 391 unsigned long st_ino; 392 unsigned long st_nlink; 393 unsigned int st_mode; 394 unsigned int st_uid; 395 396 unsigned int st_gid; 397 unsigned int __pad0; 398 unsigned long st_rdev; 399 long st_size; 400 long st_blksize; 401 402 long st_blocks; 403 unsigned long st_atime; 404 unsigned long st_atime_nsec; 405 unsigned long st_mtime; 406 407 unsigned long st_mtime_nsec; 408 unsigned long st_ctime; 409 unsigned long st_ctime_nsec; 410 long __unused[3]; 411 }; 412 413 #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) 414 /* Syscalls for i386 : 415 * - mostly similar to x86_64 416 * - registers are 32-bit 417 * - syscall number is passed in eax 418 * - arguments are in ebx, ecx, edx, esi, edi, ebp respectively 419 * - all registers are preserved (except eax of course) 420 * - the system call is performed by calling int $0x80 421 * - syscall return comes in eax 422 * - the arguments are cast to long and assigned into the target registers 423 * which are then simply passed as registers to the asm code, so that we 424 * don't have to experience issues with register constraints. 425 * - the syscall number is always specified last in order to allow to force 426 * some registers before (gcc refuses a %-register at the last position). 427 * 428 * Also, i386 supports the old_select syscall if newselect is not available 429 */ 430 #define __ARCH_WANT_SYS_OLD_SELECT 431 432 #define my_syscall0(num) \ 433 ({ \ 434 long _ret; \ 435 register long _num asm("eax") = (num); \ 436 \ 437 asm volatile ( \ 438 "int $0x80\n" \ 439 : "=a" (_ret) \ 440 : ""(_num) \ 441 : "memory", "cc" \ 442 ); \ 443 _ret; \ 444 }) 445 446 #define my_syscall1(num, arg1) \ 447 ({ \ 448 long _ret; \ 449 register long _num asm("eax") = (num); \ 450 register long _arg1 asm("ebx") = (long)(arg1); \ 451 \ 452 asm volatile ( \ 453 "int $0x80\n" \ 454 : "=a" (_ret) \ 455 : "r"(_arg1), \ 456 ""(_num) \ 457 : "memory", "cc" \ 458 ); \ 459 _ret; \ 460 }) 461 462 #define my_syscall2(num, arg1, arg2) \ 463 ({ \ 464 long _ret; \ 465 register long _num asm("eax") = (num); \ 466 register long _arg1 asm("ebx") = (long)(arg1); \ 467 register long _arg2 asm("ecx") = (long)(arg2); \ 468 \ 469 asm volatile ( \ 470 "int $0x80\n" \ 471 : "=a" (_ret) \ 472 : "r"(_arg1), "r"(_arg2), \ 473 ""(_num) \ 474 : "memory", "cc" \ 475 ); \ 476 _ret; \ 477 }) 478 479 #define my_syscall3(num, arg1, arg2, arg3) \ 480 ({ \ 481 long _ret; \ 482 register long _num asm("eax") = (num); \ 483 register long _arg1 asm("ebx") = (long)(arg1); \ 484 register long _arg2 asm("ecx") = (long)(arg2); \ 485 register long _arg3 asm("edx") = (long)(arg3); \ 486 \ 487 asm volatile ( \ 488 "int $0x80\n" \ 489 : "=a" (_ret) \ 490 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ 491 ""(_num) \ 492 : "memory", "cc" \ 493 ); \ 494 _ret; \ 495 }) 496 497 #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 498 ({ \ 499 long _ret; \ 500 register long _num asm("eax") = (num); \ 501 register long _arg1 asm("ebx") = (long)(arg1); \ 502 register long _arg2 asm("ecx") = (long)(arg2); \ 503 register long _arg3 asm("edx") = (long)(arg3); \ 504 register long _arg4 asm("esi") = (long)(arg4); \ 505 \ 506 asm volatile ( \ 507 "int $0x80\n" \ 508 : "=a" (_ret) \ 509 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 510 ""(_num) \ 511 : "memory", "cc" \ 512 ); \ 513 _ret; \ 514 }) 515 516 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 517 ({ \ 518 long _ret; \ 519 register long _num asm("eax") = (num); \ 520 register long _arg1 asm("ebx") = (long)(arg1); \ 521 register long _arg2 asm("ecx") = (long)(arg2); \ 522 register long _arg3 asm("edx") = (long)(arg3); \ 523 register long _arg4 asm("esi") = (long)(arg4); \ 524 register long _arg5 asm("edi") = (long)(arg5); \ 525 \ 526 asm volatile ( \ 527 "int $0x80\n" \ 528 : "=a" (_ret) \ 529 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 530 ""(_num) \ 531 : "memory", "cc" \ 532 ); \ 533 _ret; \ 534 }) 535 536 /* startup code */ 537 asm(".section .text\n" 538 ".global _start\n" 539 "_start:\n" 540 "pop %eax\n" // argc (first arg, %eax) 541 "mov %esp, %ebx\n" // argv[] (second arg, %ebx) 542 "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx) 543 "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned when 544 "push %ecx\n" // push all registers on the stack so that we 545 "push %ebx\n" // support both regparm and plain stack modes 546 "push %eax\n" 547 "call main\n" // main() returns the status code in %eax 548 "movzbl %al, %ebx\n" // retrieve exit code from lower 8 bits 549 "movl $1, %eax\n" // NR_exit == 1 550 "int $0x80\n" // exit now 551 "hlt\n" // ensure it does not 552 ""); 553 554 /* fcntl / open */ 555 #define O_RDONLY 0 556 #define O_WRONLY 1 557 #define O_RDWR 2 558 #define O_CREAT 0x40 559 #define O_EXCL 0x80 560 #define O_NOCTTY 0x100 561 #define O_TRUNC 0x200 562 #define O_APPEND 0x400 563 #define O_NONBLOCK 0x800 564 #define O_DIRECTORY 0x10000 565 566 /* The struct returned by the stat() syscall, 32-bit only, the syscall returns 567 * exactly 56 bytes (stops before the unused array). 568 */ 569 struct sys_stat_struct { 570 unsigned long st_dev; 571 unsigned long st_ino; 572 unsigned short st_mode; 573 unsigned short st_nlink; 574 unsigned short st_uid; 575 unsigned short st_gid; 576 577 unsigned long st_rdev; 578 unsigned long st_size; 579 unsigned long st_blksize; 580 unsigned long st_blocks; 581 582 unsigned long st_atime; 583 unsigned long st_atime_nsec; 584 unsigned long st_mtime; 585 unsigned long st_mtime_nsec; 586 587 unsigned long st_ctime; 588 unsigned long st_ctime_nsec; 589 unsigned long __unused[2]; 590 }; 591 592 #elif defined(__ARM_EABI__) 593 /* Syscalls for ARM in ARM or Thumb modes : 594 * - registers are 32-bit 595 * - stack is 8-byte aligned 596 * ( http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html) 597 * - syscall number is passed in r7 598 * - arguments are in r0, r1, r2, r3, r4, r5 599 * - the system call is performed by calling svc #0 600 * - syscall return comes in r0. 601 * - only lr is clobbered. 602 * - the arguments are cast to long and assigned into the target registers 603 * which are then simply passed as registers to the asm code, so that we 604 * don't have to experience issues with register constraints. 605 * - the syscall number is always specified last in order to allow to force 606 * some registers before (gcc refuses a %-register at the last position). 607 * 608 * Also, ARM supports the old_select syscall if newselect is not available 609 */ 610 #define __ARCH_WANT_SYS_OLD_SELECT 611 612 #define my_syscall0(num) \ 613 ({ \ 614 register long _num asm("r7") = (num); \ 615 register long _arg1 asm("r0"); \ 616 \ 617 asm volatile ( \ 618 "svc #0\n" \ 619 : "=r"(_arg1) \ 620 : "r"(_num) \ 621 : "memory", "cc", "lr" \ 622 ); \ 623 _arg1; \ 624 }) 625 626 #define my_syscall1(num, arg1) \ 627 ({ \ 628 register long _num asm("r7") = (num); \ 629 register long _arg1 asm("r0") = (long)(arg1); \ 630 \ 631 asm volatile ( \ 632 "svc #0\n" \ 633 : "=r"(_arg1) \ 634 : "r"(_arg1), \ 635 "r"(_num) \ 636 : "memory", "cc", "lr" \ 637 ); \ 638 _arg1; \ 639 }) 640 641 #define my_syscall2(num, arg1, arg2) \ 642 ({ \ 643 register long _num asm("r7") = (num); \ 644 register long _arg1 asm("r0") = (long)(arg1); \ 645 register long _arg2 asm("r1") = (long)(arg2); \ 646 \ 647 asm volatile ( \ 648 "svc #0\n" \ 649 : "=r"(_arg1) \ 650 : "r"(_arg1), "r"(_arg2), \ 651 "r"(_num) \ 652 : "memory", "cc", "lr" \ 653 ); \ 654 _arg1; \ 655 }) 656 657 #define my_syscall3(num, arg1, arg2, arg3) \ 658 ({ \ 659 register long _num asm("r7") = (num); \ 660 register long _arg1 asm("r0") = (long)(arg1); \ 661 register long _arg2 asm("r1") = (long)(arg2); \ 662 register long _arg3 asm("r2") = (long)(arg3); \ 663 \ 664 asm volatile ( \ 665 "svc #0\n" \ 666 : "=r"(_arg1) \ 667 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ 668 "r"(_num) \ 669 : "memory", "cc", "lr" \ 670 ); \ 671 _arg1; \ 672 }) 673 674 #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 675 ({ \ 676 register long _num asm("r7") = (num); \ 677 register long _arg1 asm("r0") = (long)(arg1); \ 678 register long _arg2 asm("r1") = (long)(arg2); \ 679 register long _arg3 asm("r2") = (long)(arg3); \ 680 register long _arg4 asm("r3") = (long)(arg4); \ 681 \ 682 asm volatile ( \ 683 "svc #0\n" \ 684 : "=r"(_arg1) \ 685 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 686 "r"(_num) \ 687 : "memory", "cc", "lr" \ 688 ); \ 689 _arg1; \ 690 }) 691 692 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 693 ({ \ 694 register long _num asm("r7") = (num); \ 695 register long _arg1 asm("r0") = (long)(arg1); \ 696 register long _arg2 asm("r1") = (long)(arg2); \ 697 register long _arg3 asm("r2") = (long)(arg3); \ 698 register long _arg4 asm("r3") = (long)(arg4); \ 699 register long _arg5 asm("r4") = (long)(arg5); \ 700 \ 701 asm volatile ( \ 702 "svc #0\n" \ 703 : "=r" (_arg1) \ 704 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 705 "r"(_num) \ 706 : "memory", "cc", "lr" \ 707 ); \ 708 _arg1; \ 709 }) 710 711 /* startup code */ 712 asm(".section .text\n" 713 ".global _start\n" 714 "_start:\n" 715 #if defined(__THUMBEB__) || defined(__THUMBEL__) 716 /* We enter here in 32-bit mode but if some previous functions were in 717 * 16-bit mode, the assembler cannot know, so we need to tell it we're in 718 * 32-bit now, then switch to 16-bit (is there a better way to do it than 719 * adding 1 by hand ?) and tell the asm we're now in 16-bit mode so that 720 * it generates correct instructions. Note that we do not support thumb1. 721 */ 722 ".code 32\n" 723 "add r0, pc, #1\n" 724 "bx r0\n" 725 ".code 16\n" 726 #endif 727 "pop {%r0}\n" // argc was in the stack 728 "mov %r1, %sp\n" // argv = sp 729 "add %r2, %r1, %r0, lsl #2\n" // envp = argv + 4*argc ... 730 "add %r2, %r2, $4\n" // ... + 4 731 "and %r3, %r1, $-8\n" // AAPCS : sp must be 8-byte aligned in the 732 "mov %sp, %r3\n" // callee, an bl doesn't push (lr=pc) 733 "bl main\n" // main() returns the status code, we'll exit with it. 734 "and %r0, %r0, $0xff\n" // limit exit code to 8 bits 735 "movs r7, $1\n" // NR_exit == 1 736 "svc $0x00\n" 737 ""); 738 739 /* fcntl / open */ 740 #define O_RDONLY 0 741 #define O_WRONLY 1 742 #define O_RDWR 2 743 #define O_CREAT 0x40 744 #define O_EXCL 0x80 745 #define O_NOCTTY 0x100 746 #define O_TRUNC 0x200 747 #define O_APPEND 0x400 748 #define O_NONBLOCK 0x800 749 #define O_DIRECTORY 0x4000 750 751 /* The struct returned by the stat() syscall, 32-bit only, the syscall returns 752 * exactly 56 bytes (stops before the unused array). In big endian, the format 753 * differs as devices are returned as short only. 754 */ 755 struct sys_stat_struct { 756 #if defined(__ARMEB__) 757 unsigned short st_dev; 758 unsigned short __pad1; 759 #else 760 unsigned long st_dev; 761 #endif 762 unsigned long st_ino; 763 unsigned short st_mode; 764 unsigned short st_nlink; 765 unsigned short st_uid; 766 unsigned short st_gid; 767 #if defined(__ARMEB__) 768 unsigned short st_rdev; 769 unsigned short __pad2; 770 #else 771 unsigned long st_rdev; 772 #endif 773 unsigned long st_size; 774 unsigned long st_blksize; 775 unsigned long st_blocks; 776 unsigned long st_atime; 777 unsigned long st_atime_nsec; 778 unsigned long st_mtime; 779 unsigned long st_mtime_nsec; 780 unsigned long st_ctime; 781 unsigned long st_ctime_nsec; 782 unsigned long __unused[2]; 783 }; 784 785 #elif defined(__aarch64__) 786 /* Syscalls for AARCH64 : 787 * - registers are 64-bit 788 * - stack is 16-byte aligned 789 * - syscall number is passed in x8 790 * - arguments are in x0, x1, x2, x3, x4, x5 791 * - the system call is performed by calling svc 0 792 * - syscall return comes in x0. 793 * - the arguments are cast to long and assigned into the target registers 794 * which are then simply passed as registers to the asm code, so that we 795 * don't have to experience issues with register constraints. 796 * 797 * On aarch64, select() is not implemented so we have to use pselect6(). 798 */ 799 #define __ARCH_WANT_SYS_PSELECT6 800 801 #define my_syscall0(num) \ 802 ({ \ 803 register long _num asm("x8") = (num); \ 804 register long _arg1 asm("x0"); \ 805 \ 806 asm volatile ( \ 807 "svc #0\n" \ 808 : "=r"(_arg1) \ 809 : "r"(_num) \ 810 : "memory", "cc" \ 811 ); \ 812 _arg1; \ 813 }) 814 815 #define my_syscall1(num, arg1) \ 816 ({ \ 817 register long _num asm("x8") = (num); \ 818 register long _arg1 asm("x0") = (long)(arg1); \ 819 \ 820 asm volatile ( \ 821 "svc #0\n" \ 822 : "=r"(_arg1) \ 823 : "r"(_arg1), \ 824 "r"(_num) \ 825 : "memory", "cc" \ 826 ); \ 827 _arg1; \ 828 }) 829 830 #define my_syscall2(num, arg1, arg2) \ 831 ({ \ 832 register long _num asm("x8") = (num); \ 833 register long _arg1 asm("x0") = (long)(arg1); \ 834 register long _arg2 asm("x1") = (long)(arg2); \ 835 \ 836 asm volatile ( \ 837 "svc #0\n" \ 838 : "=r"(_arg1) \ 839 : "r"(_arg1), "r"(_arg2), \ 840 "r"(_num) \ 841 : "memory", "cc" \ 842 ); \ 843 _arg1; \ 844 }) 845 846 #define my_syscall3(num, arg1, arg2, arg3) \ 847 ({ \ 848 register long _num asm("x8") = (num); \ 849 register long _arg1 asm("x0") = (long)(arg1); \ 850 register long _arg2 asm("x1") = (long)(arg2); \ 851 register long _arg3 asm("x2") = (long)(arg3); \ 852 \ 853 asm volatile ( \ 854 "svc #0\n" \ 855 : "=r"(_arg1) \ 856 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ 857 "r"(_num) \ 858 : "memory", "cc" \ 859 ); \ 860 _arg1; \ 861 }) 862 863 #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 864 ({ \ 865 register long _num asm("x8") = (num); \ 866 register long _arg1 asm("x0") = (long)(arg1); \ 867 register long _arg2 asm("x1") = (long)(arg2); \ 868 register long _arg3 asm("x2") = (long)(arg3); \ 869 register long _arg4 asm("x3") = (long)(arg4); \ 870 \ 871 asm volatile ( \ 872 "svc #0\n" \ 873 : "=r"(_arg1) \ 874 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 875 "r"(_num) \ 876 : "memory", "cc" \ 877 ); \ 878 _arg1; \ 879 }) 880 881 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 882 ({ \ 883 register long _num asm("x8") = (num); \ 884 register long _arg1 asm("x0") = (long)(arg1); \ 885 register long _arg2 asm("x1") = (long)(arg2); \ 886 register long _arg3 asm("x2") = (long)(arg3); \ 887 register long _arg4 asm("x3") = (long)(arg4); \ 888 register long _arg5 asm("x4") = (long)(arg5); \ 889 \ 890 asm volatile ( \ 891 "svc #0\n" \ 892 : "=r" (_arg1) \ 893 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 894 "r"(_num) \ 895 : "memory", "cc" \ 896 ); \ 897 _arg1; \ 898 }) 899 900 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 901 ({ \ 902 register long _num asm("x8") = (num); \ 903 register long _arg1 asm("x0") = (long)(arg1); \ 904 register long _arg2 asm("x1") = (long)(arg2); \ 905 register long _arg3 asm("x2") = (long)(arg3); \ 906 register long _arg4 asm("x3") = (long)(arg4); \ 907 register long _arg5 asm("x4") = (long)(arg5); \ 908 register long _arg6 asm("x5") = (long)(arg6); \ 909 \ 910 asm volatile ( \ 911 "svc #0\n" \ 912 : "=r" (_arg1) \ 913 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 914 "r"(_arg6), "r"(_num) \ 915 : "memory", "cc" \ 916 ); \ 917 _arg1; \ 918 }) 919 920 /* startup code */ 921 asm(".section .text\n" 922 ".global _start\n" 923 "_start:\n" 924 "ldr x0, [sp]\n" // argc (x0) was in the stack 925 "add x1, sp, 8\n" // argv (x1) = sp 926 "lsl x2, x0, 3\n" // envp (x2) = 8*argc ... 927 "add x2, x2, 8\n" // + 8 (skip null) 928 "add x2, x2, x1\n" // + argv 929 "and sp, x1, -16\n" // sp must be 16-byte aligned in the callee 930 "bl main\n" // main() returns the status code, we'll exit with it. 931 "and x0, x0, 0xff\n" // limit exit code to 8 bits 932 "mov x8, 93\n" // NR_exit == 93 933 "svc #0\n" 934 ""); 935 936 /* fcntl / open */ 937 #define O_RDONLY 0 938 #define O_WRONLY 1 939 #define O_RDWR 2 940 #define O_CREAT 0x40 941 #define O_EXCL 0x80 942 #define O_NOCTTY 0x100 943 #define O_TRUNC 0x200 944 #define O_APPEND 0x400 945 #define O_NONBLOCK 0x800 946 #define O_DIRECTORY 0x4000 947 948 /* The struct returned by the newfstatat() syscall. Differs slightly from the 949 * x86_64's stat one by field ordering, so be careful. 950 */ 951 struct sys_stat_struct { 952 unsigned long st_dev; 953 unsigned long st_ino; 954 unsigned int st_mode; 955 unsigned int st_nlink; 956 unsigned int st_uid; 957 unsigned int st_gid; 958 959 unsigned long st_rdev; 960 unsigned long __pad1; 961 long st_size; 962 int st_blksize; 963 int __pad2; 964 965 long st_blocks; 966 long st_atime; 967 unsigned long st_atime_nsec; 968 long st_mtime; 969 970 unsigned long st_mtime_nsec; 971 long st_ctime; 972 unsigned long st_ctime_nsec; 973 unsigned int __unused[2]; 974 }; 975 976 #elif defined(__mips__) && defined(_ABIO32) 977 /* Syscalls for MIPS ABI O32 : 978 * - WARNING! there's always a delayed slot! 979 * - WARNING again, the syntax is different, registers take a '$' and numbers 980 * do not. 981 * - registers are 32-bit 982 * - stack is 8-byte aligned 983 * - syscall number is passed in v0 (starts at 0xfa0). 984 * - arguments are in a0, a1, a2, a3, then the stack. The caller needs to 985 * leave some room in the stack for the callee to save a0..a3 if needed. 986 * - Many registers are clobbered, in fact only a0..a2 and s0..s8 are 987 * preserved. See: https://www.linux-mips.org/wiki/Syscall as well as 988 * scall32-o32.S in the kernel sources. 989 * - the system call is performed by calling "syscall" 990 * - syscall return comes in v0, and register a3 needs to be checked to know 991 * if an error occured, in which case errno is in v0. 992 * - the arguments are cast to long and assigned into the target registers 993 * which are then simply passed as registers to the asm code, so that we 994 * don't have to experience issues with register constraints. 995 */ 996 997 #define my_syscall0(num) \ 998 ({ \ 999 register long _num asm("v0") = (num); \ 1000 register long _arg4 asm("a3"); \ 1001 \ 1002 asm volatile ( \ 1003 "addiu $sp, $sp, -32\n" \ 1004 "syscall\n" \ 1005 "addiu $sp, $sp, 32\n" \ 1006 : "=r"(_num), "=r"(_arg4) \ 1007 : "r"(_num) \ 1008 : "memory", "cc", "at", "v1", "hi", "lo", \ 1009 \ 1010 ); \ 1011 _arg4 ? -_num : _num; \ 1012 }) 1013 1014 #define my_syscall1(num, arg1) \ 1015 ({ \ 1016 register long _num asm("v0") = (num); \ 1017 register long _arg1 asm("a0") = (long)(arg1); \ 1018 register long _arg4 asm("a3"); \ 1019 \ 1020 asm volatile ( \ 1021 "addiu $sp, $sp, -32\n" \ 1022 "syscall\n" \ 1023 "addiu $sp, $sp, 32\n" \ 1024 : "=r"(_num), "=r"(_arg4) \ 1025 : ""(_num), \ 1026 "r"(_arg1) \ 1027 : "memory", "cc", "at", "v1", "hi", "lo", \ 1028 \ 1029 ); \ 1030 _arg4 ? -_num : _num; \ 1031 }) 1032 1033 #define my_syscall2(num, arg1, arg2) \ 1034 ({ \ 1035 register long _num asm("v0") = (num); \ 1036 register long _arg1 asm("a0") = (long)(arg1); \ 1037 register long _arg2 asm("a1") = (long)(arg2); \ 1038 register long _arg4 asm("a3"); \ 1039 \ 1040 asm volatile ( \ 1041 "addiu $sp, $sp, -32\n" \ 1042 "syscall\n" \ 1043 "addiu $sp, $sp, 32\n" \ 1044 : "=r"(_num), "=r"(_arg4) \ 1045 : ""(_num), \ 1046 "r"(_arg1), "r"(_arg2) \ 1047 : "memory", "cc", "at", "v1", "hi", "lo", \ 1048 \ 1049 ); \ 1050 _arg4 ? -_num : _num; \ 1051 }) 1052 1053 #define my_syscall3(num, arg1, arg2, arg3) \ 1054 ({ \ 1055 register long _num asm("v0") = (num); \ 1056 register long _arg1 asm("a0") = (long)(arg1); \ 1057 register long _arg2 asm("a1") = (long)(arg2); \ 1058 register long _arg3 asm("a2") = (long)(arg3); \ 1059 register long _arg4 asm("a3"); \ 1060 \ 1061 asm volatile ( \ 1062 "addiu $sp, $sp, -32\n" \ 1063 "syscall\n" \ 1064 "addiu $sp, $sp, 32\n" \ 1065 : "=r"(_num), "=r"(_arg4) \ 1066 : ""(_num), \ 1067 "r"(_arg1), "r"(_arg2), "r"(_arg3) \ 1068 : "memory", "cc", "at", "v1", "hi", "lo", \ 1069 \ 1070 ); \ 1071 _arg4 ? -_num : _num; \ 1072 }) 1073 1074 #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 1075 ({ \ 1076 register long _num asm("v0") = (num); \ 1077 register long _arg1 asm("a0") = (long)(arg1); \ 1078 register long _arg2 asm("a1") = (long)(arg2); \ 1079 register long _arg3 asm("a2") = (long)(arg3); \ 1080 register long _arg4 asm("a3") = (long)(arg4); \ 1081 \ 1082 asm volatile ( \ 1083 "addiu $sp, $sp, -32\n" \ 1084 "syscall\n" \ 1085 "addiu $sp, $sp, 32\n" \ 1086 : "=r" (_num), "=r"(_arg4) \ 1087 : ""(_num), \ 1088 "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \ 1089 : "memory", "cc", "at", "v1", "hi", "lo", \ 1090 \ 1091 ); \ 1092 _arg4 ? -_num : _num; \ 1093 }) 1094 1095 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 1096 ({ \ 1097 register long _num asm("v0") = (num); \ 1098 register long _arg1 asm("a0") = (long)(arg1); \ 1099 register long _arg2 asm("a1") = (long)(arg2); \ 1100 register long _arg3 asm("a2") = (long)(arg3); \ 1101 register long _arg4 asm("a3") = (long)(arg4); \ 1102 register long _arg5 = (long)(arg5); \ 1103 \ 1104 asm volatile ( \ 1105 "addiu $sp, $sp, -32\n" \ 1106 "sw %7, 16($sp)\n" \ 1107 "syscall\n " \ 1108 "addiu $sp, $sp, 32\n" \ 1109 : "=r" (_num), "=r"(_arg4) \ 1110 : ""(_num), \ 1111 "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \ 1112 : "memory", "cc", "at", "v1", "hi", "lo", \ 1113 \ 1114 ); \ 1115 _arg4 ? -_num : _num; \ 1116 }) 1117 1118 /* startup code, note that it's called __start on MIPS */ 1119 asm(".section .text\n" 1120 ".set nomips16\n" 1121 ".global __start\n" 1122 ".set noreorder\n" 1123 ".option pic0\n" 1124 ".ent __start\n" 1125 "__start:\n" 1126 "lw $a0,($sp)\n" // argc was in the stack 1127 "addiu $a1, $sp, 4\n" // argv = sp + 4 1128 "sll $a2, $a0, 2\n" // a2 = argc * 4 1129 "add $a2, $a2, $a1\n" // envp = argv + 4*argc ... 1130 "addiu $a2, $a2, 4\n" // ... + 4 1131 "li $t0, -8\n" 1132 "and $sp, $sp, $t0\n" // sp must be 8-byte aligned 1133 "addiu $sp,$sp,-16\n" // the callee expects to save a0..a3 there! 1134 "jal main\n" // main() returns the status code, we'll exit with it. 1135 "nop\n" // delayed slot 1136 "and $a0, $v0, 0xff\n" // limit exit code to 8 bits 1137 "li $v0, 4001\n" // NR_exit == 4001 1138 "syscall\n" 1139 ".end __start\n" 1140 ""); 1141 1142 /* fcntl / open */ 1143 #define O_RDONLY 0 1144 #define O_WRONLY 1 1145 #define O_RDWR 2 1146 #define O_APPEND 0x0008 1147 #define O_NONBLOCK 0x0080 1148 #define O_CREAT 0x0100 1149 #define O_TRUNC 0x0200 1150 #define O_EXCL 0x0400 1151 #define O_NOCTTY 0x0800 1152 #define O_DIRECTORY 0x10000 1153 1154 /* The struct returned by the stat() syscall. 88 bytes are returned by the 1155 * syscall. 1156 */ 1157 struct sys_stat_struct { 1158 unsigned int st_dev; 1159 long st_pad1[3]; 1160 unsigned long st_ino; 1161 unsigned int st_mode; 1162 unsigned int st_nlink; 1163 unsigned int st_uid; 1164 unsigned int st_gid; 1165 unsigned int st_rdev; 1166 long st_pad2[2]; 1167 long st_size; 1168 long st_pad3; 1169 long st_atime; 1170 long st_atime_nsec; 1171 long st_mtime; 1172 long st_mtime_nsec; 1173 long st_ctime; 1174 long st_ctime_nsec; 1175 long st_blksize; 1176 long st_blocks; 1177 long st_pad4[14]; 1178 }; 1179 1180 #endif 1181 1182 1183 /* Below are the C functions used to declare the raw syscalls. They try to be 1184 * architecture-agnostic, and return either a success or -errno. Declaring them 1185 * static will lead to them being inlined in most cases, but it's still possible 1186 * to reference them by a pointer if needed. 1187 */ 1188 static __attribute__((unused)) 1189 void *sys_brk(void *addr) 1190 { 1191 return (void *)my_syscall1(__NR_brk, addr); 1192 } 1193 1194 static __attribute__((noreturn,unused)) 1195 void sys_exit(int status) 1196 { 1197 my_syscall1(__NR_exit, status & 255); 1198 while(1); // shut the "noreturn" warnings. 1199 } 1200 1201 static __attribute__((unused)) 1202 int sys_chdir(const char *path) 1203 { 1204 return my_syscall1(__NR_chdir, path); 1205 } 1206 1207 static __attribute__((unused)) 1208 int sys_chmod(const char *path, mode_t mode) 1209 { 1210 #ifdef __NR_fchmodat 1211 return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0); 1212 #else 1213 return my_syscall2(__NR_chmod, path, mode); 1214 #endif 1215 } 1216 1217 static __attribute__((unused)) 1218 int sys_chown(const char *path, uid_t owner, gid_t group) 1219 { 1220 #ifdef __NR_fchownat 1221 return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0); 1222 #else 1223 return my_syscall3(__NR_chown, path, owner, group); 1224 #endif 1225 } 1226 1227 static __attribute__((unused)) 1228 int sys_chroot(const char *path) 1229 { 1230 return my_syscall1(__NR_chroot, path); 1231 } 1232 1233 static __attribute__((unused)) 1234 int sys_close(int fd) 1235 { 1236 return my_syscall1(__NR_close, fd); 1237 } 1238 1239 static __attribute__((unused)) 1240 int sys_dup(int fd) 1241 { 1242 return my_syscall1(__NR_dup, fd); 1243 } 1244 1245 static __attribute__((unused)) 1246 int sys_dup2(int old, int new) 1247 { 1248 return my_syscall2(__NR_dup2, old, new); 1249 } 1250 1251 static __attribute__((unused)) 1252 int sys_execve(const char *filename, char *const argv[], char *const envp[]) 1253 { 1254 return my_syscall3(__NR_execve, filename, argv, envp); 1255 } 1256 1257 static __attribute__((unused)) 1258 pid_t sys_fork(void) 1259 { 1260 return my_syscall0(__NR_fork); 1261 } 1262 1263 static __attribute__((unused)) 1264 int sys_fsync(int fd) 1265 { 1266 return my_syscall1(__NR_fsync, fd); 1267 } 1268 1269 static __attribute__((unused)) 1270 int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count) 1271 { 1272 return my_syscall3(__NR_getdents64, fd, dirp, count); 1273 } 1274 1275 static __attribute__((unused)) 1276 pid_t sys_getpgrp(void) 1277 { 1278 return my_syscall0(__NR_getpgrp); 1279 } 1280 1281 static __attribute__((unused)) 1282 pid_t sys_getpid(void) 1283 { 1284 return my_syscall0(__NR_getpid); 1285 } 1286 1287 static __attribute__((unused)) 1288 int sys_gettimeofday(struct timeval *tv, struct timezone *tz) 1289 { 1290 return my_syscall2(__NR_gettimeofday, tv, tz); 1291 } 1292 1293 static __attribute__((unused)) 1294 int sys_ioctl(int fd, unsigned long req, void *value) 1295 { 1296 return my_syscall3(__NR_ioctl, fd, req, value); 1297 } 1298 1299 static __attribute__((unused)) 1300 int sys_kill(pid_t pid, int signal) 1301 { 1302 return my_syscall2(__NR_kill, pid, signal); 1303 } 1304 1305 static __attribute__((unused)) 1306 int sys_link(const char *old, const char *new) 1307 { 1308 #ifdef __NR_linkat 1309 return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); 1310 #else 1311 return my_syscall2(__NR_link, old, new); 1312 #endif 1313 } 1314 1315 static __attribute__((unused)) 1316 off_t sys_lseek(int fd, off_t offset, int whence) 1317 { 1318 return my_syscall3(__NR_lseek, fd, offset, whence); 1319 } 1320 1321 static __attribute__((unused)) 1322 int sys_mkdir(const char *path, mode_t mode) 1323 { 1324 #ifdef __NR_mkdirat 1325 return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); 1326 #else 1327 return my_syscall2(__NR_mkdir, path, mode); 1328 #endif 1329 } 1330 1331 static __attribute__((unused)) 1332 long sys_mknod(const char *path, mode_t mode, dev_t dev) 1333 { 1334 #ifdef __NR_mknodat 1335 return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); 1336 #else 1337 return my_syscall3(__NR_mknod, path, mode, dev); 1338 #endif 1339 } 1340 1341 static __attribute__((unused)) 1342 int sys_mount(const char *src, const char *tgt, const char *fst, 1343 unsigned long flags, const void *data) 1344 { 1345 return my_syscall5(__NR_mount, src, tgt, fst, flags, data); 1346 } 1347 1348 static __attribute__((unused)) 1349 int sys_open(const char *path, int flags, mode_t mode) 1350 { 1351 #ifdef __NR_openat 1352 return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode); 1353 #else 1354 return my_syscall3(__NR_open, path, flags, mode); 1355 #endif 1356 } 1357 1358 static __attribute__((unused)) 1359 int sys_pivot_root(const char *new, const char *old) 1360 { 1361 return my_syscall2(__NR_pivot_root, new, old); 1362 } 1363 1364 static __attribute__((unused)) 1365 int sys_poll(struct pollfd *fds, int nfds, int timeout) 1366 { 1367 return my_syscall3(__NR_poll, fds, nfds, timeout); 1368 } 1369 1370 static __attribute__((unused)) 1371 ssize_t sys_read(int fd, void *buf, size_t count) 1372 { 1373 return my_syscall3(__NR_read, fd, buf, count); 1374 } 1375 1376 static __attribute__((unused)) 1377 ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg) 1378 { 1379 return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg); 1380 } 1381 1382 static __attribute__((unused)) 1383 int sys_sched_yield(void) 1384 { 1385 return my_syscall0(__NR_sched_yield); 1386 } 1387 1388 static __attribute__((unused)) 1389 int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 1390 { 1391 #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect) 1392 struct sel_arg_struct { 1393 unsigned long n; 1394 fd_set *r, *w, *e; 1395 struct timeval *t; 1396 } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout }; 1397 return my_syscall1(__NR_select, &arg); 1398 #elif defined(__ARCH_WANT_SYS_PSELECT6) && defined(__NR_pselect6) 1399 struct timespec t; 1400 1401 if (timeout) { 1402 t.tv_sec = timeout->tv_sec; 1403 t.tv_nsec = timeout->tv_usec * 1000; 1404 } 1405 return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 1406 #else 1407 #ifndef __NR__newselect 1408 #define __NR__newselect __NR_select 1409 #endif 1410 return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); 1411 #endif 1412 } 1413 1414 static __attribute__((unused)) 1415 int sys_setpgid(pid_t pid, pid_t pgid) 1416 { 1417 return my_syscall2(__NR_setpgid, pid, pgid); 1418 } 1419 1420 static __attribute__((unused)) 1421 pid_t sys_setsid(void) 1422 { 1423 return my_syscall0(__NR_setsid); 1424 } 1425 1426 static __attribute__((unused)) 1427 int sys_stat(const char *path, struct stat *buf) 1428 { 1429 struct sys_stat_struct stat; 1430 long ret; 1431 1432 #ifdef __NR_newfstatat 1433 /* only solution for arm64 */ 1434 ret = my_syscall4(__NR_newfstatat, AT_FDCWD, path, &stat, 0); 1435 #else 1436 ret = my_syscall2(__NR_stat, path, &stat); 1437 #endif 1438 buf->st_dev = stat.st_dev; 1439 buf->st_ino = stat.st_ino; 1440 buf->st_mode = stat.st_mode; 1441 buf->st_nlink = stat.st_nlink; 1442 buf->st_uid = stat.st_uid; 1443 buf->st_gid = stat.st_gid; 1444 buf->st_rdev = stat.st_rdev; 1445 buf->st_size = stat.st_size; 1446 buf->st_blksize = stat.st_blksize; 1447 buf->st_blocks = stat.st_blocks; 1448 buf->st_atime = stat.st_atime; 1449 buf->st_mtime = stat.st_mtime; 1450 buf->st_ctime = stat.st_ctime; 1451 return ret; 1452 } 1453 1454 1455 static __attribute__((unused)) 1456 int sys_symlink(const char *old, const char *new) 1457 { 1458 #ifdef __NR_symlinkat 1459 return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); 1460 #else 1461 return my_syscall2(__NR_symlink, old, new); 1462 #endif 1463 } 1464 1465 static __attribute__((unused)) 1466 mode_t sys_umask(mode_t mode) 1467 { 1468 return my_syscall1(__NR_umask, mode); 1469 } 1470 1471 static __attribute__((unused)) 1472 int sys_umount2(const char *path, int flags) 1473 { 1474 return my_syscall2(__NR_umount2, path, flags); 1475 } 1476 1477 static __attribute__((unused)) 1478 int sys_unlink(const char *path) 1479 { 1480 #ifdef __NR_unlinkat 1481 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); 1482 #else 1483 return my_syscall1(__NR_unlink, path); 1484 #endif 1485 } 1486 1487 static __attribute__((unused)) 1488 pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage) 1489 { 1490 return my_syscall4(__NR_wait4, pid, status, options, rusage); 1491 } 1492 1493 static __attribute__((unused)) 1494 pid_t sys_waitpid(pid_t pid, int *status, int options) 1495 { 1496 return sys_wait4(pid, status, options, 0); 1497 } 1498 1499 static __attribute__((unused)) 1500 pid_t sys_wait(int *status) 1501 { 1502 return sys_waitpid(-1, status, 0); 1503 } 1504 1505 static __attribute__((unused)) 1506 ssize_t sys_write(int fd, const void *buf, size_t count) 1507 { 1508 return my_syscall3(__NR_write, fd, buf, count); 1509 } 1510 1511 1512 /* Below are the libc-compatible syscalls which return x or -1 and set errno. 1513 * They rely on the functions above. Similarly they're marked static so that it 1514 * is possible to assign pointers to them if needed. 1515 */ 1516 1517 static __attribute__((unused)) 1518 int brk(void *addr) 1519 { 1520 void *ret = sys_brk(addr); 1521 1522 if (!ret) { 1523 SET_ERRNO(ENOMEM); 1524 return -1; 1525 } 1526 return 0; 1527 } 1528 1529 static __attribute__((noreturn,unused)) 1530 void exit(int status) 1531 { 1532 sys_exit(status); 1533 } 1534 1535 static __attribute__((unused)) 1536 int chdir(const char *path) 1537 { 1538 int ret = sys_chdir(path); 1539 1540 if (ret < 0) { 1541 SET_ERRNO(-ret); 1542 ret = -1; 1543 } 1544 return ret; 1545 } 1546 1547 static __attribute__((unused)) 1548 int chmod(const char *path, mode_t mode) 1549 { 1550 int ret = sys_chmod(path, mode); 1551 1552 if (ret < 0) { 1553 SET_ERRNO(-ret); 1554 ret = -1; 1555 } 1556 return ret; 1557 } 1558 1559 static __attribute__((unused)) 1560 int chown(const char *path, uid_t owner, gid_t group) 1561 { 1562 int ret = sys_chown(path, owner, group); 1563 1564 if (ret < 0) { 1565 SET_ERRNO(-ret); 1566 ret = -1; 1567 } 1568 return ret; 1569 } 1570 1571 static __attribute__((unused)) 1572 int chroot(const char *path) 1573 { 1574 int ret = sys_chroot(path); 1575 1576 if (ret < 0) { 1577 SET_ERRNO(-ret); 1578 ret = -1; 1579 } 1580 return ret; 1581 } 1582 1583 static __attribute__((unused)) 1584 int close(int fd) 1585 { 1586 int ret = sys_close(fd); 1587 1588 if (ret < 0) { 1589 SET_ERRNO(-ret); 1590 ret = -1; 1591 } 1592 return ret; 1593 } 1594 1595 static __attribute__((unused)) 1596 int dup2(int old, int new) 1597 { 1598 int ret = sys_dup2(old, new); 1599 1600 if (ret < 0) { 1601 SET_ERRNO(-ret); 1602 ret = -1; 1603 } 1604 return ret; 1605 } 1606 1607 static __attribute__((unused)) 1608 int execve(const char *filename, char *const argv[], char *const envp[]) 1609 { 1610 int ret = sys_execve(filename, argv, envp); 1611 1612 if (ret < 0) { 1613 SET_ERRNO(-ret); 1614 ret = -1; 1615 } 1616 return ret; 1617 } 1618 1619 static __attribute__((unused)) 1620 pid_t fork(void) 1621 { 1622 pid_t ret = sys_fork(); 1623 1624 if (ret < 0) { 1625 SET_ERRNO(-ret); 1626 ret = -1; 1627 } 1628 return ret; 1629 } 1630 1631 static __attribute__((unused)) 1632 int fsync(int fd) 1633 { 1634 int ret = sys_fsync(fd); 1635 1636 if (ret < 0) { 1637 SET_ERRNO(-ret); 1638 ret = -1; 1639 } 1640 return ret; 1641 } 1642 1643 static __attribute__((unused)) 1644 int getdents64(int fd, struct linux_dirent64 *dirp, int count) 1645 { 1646 int ret = sys_getdents64(fd, dirp, count); 1647 1648 if (ret < 0) { 1649 SET_ERRNO(-ret); 1650 ret = -1; 1651 } 1652 return ret; 1653 } 1654 1655 static __attribute__((unused)) 1656 pid_t getpgrp(void) 1657 { 1658 pid_t ret = sys_getpgrp(); 1659 1660 if (ret < 0) { 1661 SET_ERRNO(-ret); 1662 ret = -1; 1663 } 1664 return ret; 1665 } 1666 1667 static __attribute__((unused)) 1668 pid_t getpid(void) 1669 { 1670 pid_t ret = sys_getpid(); 1671 1672 if (ret < 0) { 1673 SET_ERRNO(-ret); 1674 ret = -1; 1675 } 1676 return ret; 1677 } 1678 1679 static __attribute__((unused)) 1680 int gettimeofday(struct timeval *tv, struct timezone *tz) 1681 { 1682 int ret = sys_gettimeofday(tv, tz); 1683 1684 if (ret < 0) { 1685 SET_ERRNO(-ret); 1686 ret = -1; 1687 } 1688 return ret; 1689 } 1690 1691 static __attribute__((unused)) 1692 int ioctl(int fd, unsigned long req, void *value) 1693 { 1694 int ret = sys_ioctl(fd, req, value); 1695 1696 if (ret < 0) { 1697 SET_ERRNO(-ret); 1698 ret = -1; 1699 } 1700 return ret; 1701 } 1702 1703 static __attribute__((unused)) 1704 int kill(pid_t pid, int signal) 1705 { 1706 int ret = sys_kill(pid, signal); 1707 1708 if (ret < 0) { 1709 SET_ERRNO(-ret); 1710 ret = -1; 1711 } 1712 return ret; 1713 } 1714 1715 static __attribute__((unused)) 1716 int link(const char *old, const char *new) 1717 { 1718 int ret = sys_link(old, new); 1719 1720 if (ret < 0) { 1721 SET_ERRNO(-ret); 1722 ret = -1; 1723 } 1724 return ret; 1725 } 1726 1727 static __attribute__((unused)) 1728 off_t lseek(int fd, off_t offset, int whence) 1729 { 1730 off_t ret = sys_lseek(fd, offset, whence); 1731 1732 if (ret < 0) { 1733 SET_ERRNO(-ret); 1734 ret = -1; 1735 } 1736 return ret; 1737 } 1738 1739 static __attribute__((unused)) 1740 int mkdir(const char *path, mode_t mode) 1741 { 1742 int ret = sys_mkdir(path, mode); 1743 1744 if (ret < 0) { 1745 SET_ERRNO(-ret); 1746 ret = -1; 1747 } 1748 return ret; 1749 } 1750 1751 static __attribute__((unused)) 1752 int mknod(const char *path, mode_t mode, dev_t dev) 1753 { 1754 int ret = sys_mknod(path, mode, dev); 1755 1756 if (ret < 0) { 1757 SET_ERRNO(-ret); 1758 ret = -1; 1759 } 1760 return ret; 1761 } 1762 1763 static __attribute__((unused)) 1764 int mount(const char *src, const char *tgt, 1765 const char *fst, unsigned long flags, 1766 const void *data) 1767 { 1768 int ret = sys_mount(src, tgt, fst, flags, data); 1769 1770 if (ret < 0) { 1771 SET_ERRNO(-ret); 1772 ret = -1; 1773 } 1774 return ret; 1775 } 1776 1777 static __attribute__((unused)) 1778 int open(const char *path, int flags, mode_t mode) 1779 { 1780 int ret = sys_open(path, flags, mode); 1781 1782 if (ret < 0) { 1783 SET_ERRNO(-ret); 1784 ret = -1; 1785 } 1786 return ret; 1787 } 1788 1789 static __attribute__((unused)) 1790 int pivot_root(const char *new, const char *old) 1791 { 1792 int ret = sys_pivot_root(new, old); 1793 1794 if (ret < 0) { 1795 SET_ERRNO(-ret); 1796 ret = -1; 1797 } 1798 return ret; 1799 } 1800 1801 static __attribute__((unused)) 1802 int poll(struct pollfd *fds, int nfds, int timeout) 1803 { 1804 int ret = sys_poll(fds, nfds, timeout); 1805 1806 if (ret < 0) { 1807 SET_ERRNO(-ret); 1808 ret = -1; 1809 } 1810 return ret; 1811 } 1812 1813 static __attribute__((unused)) 1814 ssize_t read(int fd, void *buf, size_t count) 1815 { 1816 ssize_t ret = sys_read(fd, buf, count); 1817 1818 if (ret < 0) { 1819 SET_ERRNO(-ret); 1820 ret = -1; 1821 } 1822 return ret; 1823 } 1824 1825 static __attribute__((unused)) 1826 int reboot(int cmd) 1827 { 1828 int ret = sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0); 1829 1830 if (ret < 0) { 1831 SET_ERRNO(-ret); 1832 ret = -1; 1833 } 1834 return ret; 1835 } 1836 1837 static __attribute__((unused)) 1838 void *sbrk(intptr_t inc) 1839 { 1840 void *ret; 1841 1842 /* first call to find current end */ 1843 if ((ret = sys_brk(0)) && (sys_brk(ret + inc) == ret + inc)) 1844 return ret + inc; 1845 1846 SET_ERRNO(ENOMEM); 1847 return (void *)-1; 1848 } 1849 1850 static __attribute__((unused)) 1851 int sched_yield(void) 1852 { 1853 int ret = sys_sched_yield(); 1854 1855 if (ret < 0) { 1856 SET_ERRNO(-ret); 1857 ret = -1; 1858 } 1859 return ret; 1860 } 1861 1862 static __attribute__((unused)) 1863 int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 1864 { 1865 int ret = sys_select(nfds, rfds, wfds, efds, timeout); 1866 1867 if (ret < 0) { 1868 SET_ERRNO(-ret); 1869 ret = -1; 1870 } 1871 return ret; 1872 } 1873 1874 static __attribute__((unused)) 1875 int setpgid(pid_t pid, pid_t pgid) 1876 { 1877 int ret = sys_setpgid(pid, pgid); 1878 1879 if (ret < 0) { 1880 SET_ERRNO(-ret); 1881 ret = -1; 1882 } 1883 return ret; 1884 } 1885 1886 static __attribute__((unused)) 1887 pid_t setsid(void) 1888 { 1889 pid_t ret = sys_setsid(); 1890 1891 if (ret < 0) { 1892 SET_ERRNO(-ret); 1893 ret = -1; 1894 } 1895 return ret; 1896 } 1897 1898 static __attribute__((unused)) 1899 unsigned int sleep(unsigned int seconds) 1900 { 1901 struct timeval my_timeval = { seconds, 0 }; 1902 1903 if (sys_select(0, 0, 0, 0, &my_timeval) < 0) 1904 return my_timeval.tv_sec + !!my_timeval.tv_usec; 1905 else 1906 return 0; 1907 } 1908 1909 static __attribute__((unused)) 1910 int stat(const char *path, struct stat *buf) 1911 { 1912 int ret = sys_stat(path, buf); 1913 1914 if (ret < 0) { 1915 SET_ERRNO(-ret); 1916 ret = -1; 1917 } 1918 return ret; 1919 } 1920 1921 static __attribute__((unused)) 1922 int symlink(const char *old, const char *new) 1923 { 1924 int ret = sys_symlink(old, new); 1925 1926 if (ret < 0) { 1927 SET_ERRNO(-ret); 1928 ret = -1; 1929 } 1930 return ret; 1931 } 1932 1933 static __attribute__((unused)) 1934 int tcsetpgrp(int fd, pid_t pid) 1935 { 1936 return ioctl(fd, TIOCSPGRP, &pid); 1937 } 1938 1939 static __attribute__((unused)) 1940 mode_t umask(mode_t mode) 1941 { 1942 return sys_umask(mode); 1943 } 1944 1945 static __attribute__((unused)) 1946 int umount2(const char *path, int flags) 1947 { 1948 int ret = sys_umount2(path, flags); 1949 1950 if (ret < 0) { 1951 SET_ERRNO(-ret); 1952 ret = -1; 1953 } 1954 return ret; 1955 } 1956 1957 static __attribute__((unused)) 1958 int unlink(const char *path) 1959 { 1960 int ret = sys_unlink(path); 1961 1962 if (ret < 0) { 1963 SET_ERRNO(-ret); 1964 ret = -1; 1965 } 1966 return ret; 1967 } 1968 1969 static __attribute__((unused)) 1970 pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage) 1971 { 1972 pid_t ret = sys_wait4(pid, status, options, rusage); 1973 1974 if (ret < 0) { 1975 SET_ERRNO(-ret); 1976 ret = -1; 1977 } 1978 return ret; 1979 } 1980 1981 static __attribute__((unused)) 1982 pid_t waitpid(pid_t pid, int *status, int options) 1983 { 1984 pid_t ret = sys_waitpid(pid, status, options); 1985 1986 if (ret < 0) { 1987 SET_ERRNO(-ret); 1988 ret = -1; 1989 } 1990 return ret; 1991 } 1992 1993 static __attribute__((unused)) 1994 pid_t wait(int *status) 1995 { 1996 pid_t ret = sys_wait(status); 1997 1998 if (ret < 0) { 1999 SET_ERRNO(-ret); 2000 ret = -1; 2001 } 2002 return ret; 2003 } 2004 2005 static __attribute__((unused)) 2006 ssize_t write(int fd, const void *buf, size_t count) 2007 { 2008 ssize_t ret = sys_write(fd, buf, count); 2009 2010 if (ret < 0) { 2011 SET_ERRNO(-ret); 2012 ret = -1; 2013 } 2014 return ret; 2015 } 2016 2017 /* some size-optimized reimplementations of a few common str* and mem* 2018 * functions. They're marked static, except memcpy() and raise() which are used 2019 * by libgcc on ARM, so they are marked weak instead in order not to cause an 2020 * error when building a program made of multiple files (not recommended). 2021 */ 2022 2023 static __attribute__((unused)) 2024 void *memmove(void *dst, const void *src, size_t len) 2025 { 2026 ssize_t pos = (dst <= src) ? -1 : (long)len; 2027 void *ret = dst; 2028 2029 while (len--) { 2030 pos += (dst <= src) ? 1 : -1; 2031 ((char *)dst)[pos] = ((char *)src)[pos]; 2032 } 2033 return ret; 2034 } 2035 2036 static __attribute__((unused)) 2037 void *memset(void *dst, int b, size_t len) 2038 { 2039 char *p = dst; 2040 2041 while (len--) 2042 *(p++) = b; 2043 return dst; 2044 } 2045 2046 static __attribute__((unused)) 2047 int memcmp(const void *s1, const void *s2, size_t n) 2048 { 2049 size_t ofs = 0; 2050 char c1 = 0; 2051 2052 while (ofs < n && !(c1 = ((char *)s1)[ofs] - ((char *)s2)[ofs])) { 2053 ofs++; 2054 } 2055 return c1; 2056 } 2057 2058 static __attribute__((unused)) 2059 char *strcpy(char *dst, const char *src) 2060 { 2061 char *ret = dst; 2062 2063 while ((*dst++ = *src++)); 2064 return ret; 2065 } 2066 2067 static __attribute__((unused)) 2068 char *strchr(const char *s, int c) 2069 { 2070 while (*s) { 2071 if (*s == (char)c) 2072 return (char *)s; 2073 s++; 2074 } 2075 return NULL; 2076 } 2077 2078 static __attribute__((unused)) 2079 char *strrchr(const char *s, int c) 2080 { 2081 const char *ret = NULL; 2082 2083 while (*s) { 2084 if (*s == (char)c) 2085 ret = s; 2086 s++; 2087 } 2088 return (char *)ret; 2089 } 2090 2091 static __attribute__((unused)) 2092 size_t nolibc_strlen(const char *str) 2093 { 2094 size_t len; 2095 2096 for (len = 0; str[len]; len++); 2097 return len; 2098 } 2099 2100 #define strlen(str) ({ \ 2101 __builtin_constant_p((str)) ? \ 2102 __builtin_strlen((str)) : \ 2103 nolibc_strlen((str)); \ 2104 }) 2105 2106 static __attribute__((unused)) 2107 int isdigit(int c) 2108 { 2109 return (unsigned int)(c - '') <= 9; 2110 } 2111 2112 static __attribute__((unused)) 2113 long atol(const char *s) 2114 { 2115 unsigned long ret = 0; 2116 unsigned long d; 2117 int neg = 0; 2118 2119 if (*s == '-') { 2120 neg = 1; 2121 s++; 2122 } 2123 2124 while (1) { 2125 d = (*s++) - ''; 2126 if (d > 9) 2127 break; 2128 ret *= 10; 2129 ret += d; 2130 } 2131 2132 return neg ? -ret : ret; 2133 } 2134 2135 static __attribute__((unused)) 2136 int atoi(const char *s) 2137 { 2138 return atol(s); 2139 } 2140 2141 static __attribute__((unused)) 2142 const char *ltoa(long in) 2143 { 2144 /* large enough for -9223372036854775808 */ 2145 static char buffer[21]; 2146 char *pos = buffer + sizeof(buffer) - 1; 2147 int neg = in < 0; 2148 unsigned long n = neg ? -in : in; 2149 2150 *pos-- = '\0'; 2151 do { 2152 *pos-- = '' + n % 10; 2153 n /= 10; 2154 if (pos < buffer) 2155 return pos + 1; 2156 } while (n); 2157 2158 if (neg) 2159 *pos-- = '-'; 2160 return pos + 1; 2161 } 2162 2163 __attribute__((weak,unused)) 2164 void *memcpy(void *dst, const void *src, size_t len) 2165 { 2166 return memmove(dst, src, len); 2167 } 2168 2169 /* needed by libgcc for divide by zero */ 2170 __attribute__((weak,unused)) 2171 int raise(int signal) 2172 { 2173 return kill(getpid(), signal); 2174 } 2175 2176 /* Here come a few helper functions */ 2177 2178 static __attribute__((unused)) 2179 void FD_ZERO(fd_set *set) 2180 { 2181 memset(set, 0, sizeof(*set)); 2182 } 2183 2184 static __attribute__((unused)) 2185 void FD_SET(int fd, fd_set *set) 2186 { 2187 if (fd < 0 || fd >= FD_SETSIZE) 2188 return; 2189 set->fd32[fd / 32] |= 1 << (fd & 31); 2190 } 2191 2192 /* WARNING, it only deals with the 4096 first majors and 256 first minors */ 2193 static __attribute__((unused)) 2194 dev_t makedev(unsigned int major, unsigned int minor) 2195 { 2196 return ((major & 0xfff) << 8) | (minor & 0xff); 2197 } 2198
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.