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