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