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