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