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