├── Android.mk ├── README.md ├── bionic ├── abort.cpp ├── bionic_time_conversions.cpp ├── dirent.cpp ├── faccessat.cpp ├── fcntl.cpp ├── poll.cpp ├── private │ ├── ErrnoRestorer.h │ ├── SigSetConverter.h │ ├── bionic_asm.h │ ├── bionic_asm_arm.h │ ├── bionic_asm_arm64.h │ ├── bionic_asm_riscv64.h │ ├── bionic_asm_x86.h │ ├── bionic_asm_x86_64.h │ ├── bionic_constants.h │ ├── bionic_errdefs.h │ └── bionic_time_conversions.h ├── strerror.cpp ├── syscall-arm.S ├── syscall-arm64.S ├── syscall-riscv64.S ├── syscall-x86.S ├── syscall-x86_64.S ├── upstream-openbsd │ ├── getenv.c │ ├── openbsd-compat.h │ ├── setenv.c │ └── strlcpy.c └── usleep.cpp ├── crtbegin.c ├── fmt.c ├── linux_syscall_support.h ├── malloc.c ├── mem.c ├── misc.c ├── musl ├── floatscan.c ├── intscan.c ├── memmem.c ├── qsort.c ├── shgetc.h ├── strcasecmp.c ├── strspn.c ├── strtok_r.c ├── vfprintf.c └── vfscanf.c ├── printf ├── printf.c ├── printf.h └── printf_config.h ├── stdio.c ├── stdio_impl.h └── syscalls.c /Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | LOCAL_MODULE := crt0 5 | 6 | # -lc -lm is hardcoded in this variable, disable it 7 | TARGET_LDLIBS := 8 | 9 | # Manually link the compiler runtime library 10 | LOCAL_compiler_rt := $(shell $(TARGET_CC) -target $(LLVM_TRIPLE)$(TARGET_PLATFORM_LEVEL) --print-libgcc-file-name) 11 | 12 | LOCAL_EXPORT_LDFLAGS := -static -nostartfiles -nodefaultlibs \ 13 | "$(LOCAL_compiler_rt)" -Wl,-wrap,abort_message 14 | LOCAL_CFLAGS := -Wno-c99-designator -Wno-shift-op-parentheses 15 | LOCAL_EXPORT_CFLAGS := -DUSE_CRT0 16 | 17 | LOCAL_SRC_FILES := \ 18 | crtbegin.c \ 19 | fmt.c \ 20 | malloc.c \ 21 | mem.c \ 22 | misc.c \ 23 | stdio.c \ 24 | syscalls.c \ 25 | printf/printf.c \ 26 | bionic/syscall-$(TARGET_ARCH).S \ 27 | $(wildcard $(LOCAL_PATH)/musl/*.c) \ 28 | $(wildcard $(LOCAL_PATH)/bionic/*/*.c) \ 29 | $(wildcard $(LOCAL_PATH)/bionic/*.cpp) 30 | 31 | LOCAL_SRC_FILES := $(LOCAL_SRC_FILES:$(LOCAL_PATH)/%=%) 32 | 33 | include $(BUILD_STATIC_LIBRARY) 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # crt0 2 | 3 | Part of the [Magisk](https://github.com/topjohnwu/Magisk) project. 4 | 5 | An extremely rudimentary libc with its sole purpose being to build the smallest possible executable for Magisk.
6 | A lot of code in this project is modified from various sources. 7 | 8 | - `bionic`: https://android.googlesource.com/platform/bionic.git/+/refs/heads/main/libc/ 9 | - `musl`: https://musl.libc.org/ 10 | - `tinystdio`: https://github.com/vladcebo/TinyStdio 11 | - `linux_syscall_support.h`: https://chromium.googlesource.com/linux-syscall-support 12 | - Other copied functions have its source commented above its code 13 | -------------------------------------------------------------------------------- /bionic/abort.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1985 Regents of the University of California. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the University nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | void abort() { 35 | // Since abort() must not return, there's no error checking in this function: 36 | // there's no way to report an error anyway. 37 | 38 | // Unblock SIGABRT to give any signal handler a chance. 39 | sigset_t mask; 40 | sigemptyset(&mask); 41 | sigaddset(&mask, SIGABRT); 42 | sigprocmask(SIG_UNBLOCK, &mask, nullptr); 43 | 44 | raise(SIGABRT); 45 | 46 | // If that signal was ignored or was caught and the handler returned, 47 | // remove the signal handler and raise SIGABRT again. 48 | signal(SIGABRT, SIG_DFL); 49 | raise(SIGABRT); 50 | 51 | // If we get this far, just exit. 52 | _exit(127); 53 | } 54 | -------------------------------------------------------------------------------- /bionic/bionic_time_conversions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include "private/bionic_time_conversions.h" 30 | 31 | #include "private/bionic_constants.h" 32 | 33 | bool timespec_from_timeval(timespec& ts, const timeval& tv) { 34 | // Whole seconds can just be copied. 35 | ts.tv_sec = tv.tv_sec; 36 | 37 | // But we might overflow when converting microseconds to nanoseconds. 38 | if (tv.tv_usec >= 1000000 || tv.tv_usec < 0) { 39 | return false; 40 | } 41 | ts.tv_nsec = tv.tv_usec * 1000; 42 | return true; 43 | } 44 | 45 | void timespec_from_ms(timespec& ts, const int ms) { 46 | ts.tv_sec = ms / 1000; 47 | ts.tv_nsec = (ms % 1000) * 1000000; 48 | } 49 | 50 | void timeval_from_timespec(timeval& tv, const timespec& ts) { 51 | tv.tv_sec = ts.tv_sec; 52 | tv.tv_usec = ts.tv_nsec / 1000; 53 | } 54 | 55 | static void convert_timespec_clocks(timespec& new_time, clockid_t new_clockbase, 56 | const timespec& old_time, clockid_t old_clockbase) { 57 | // get reference clocks 58 | timespec new_clock; 59 | clock_gettime(new_clockbase, &new_clock); 60 | timespec old_clock; 61 | clock_gettime(old_clockbase, &old_clock); 62 | 63 | // compute new time by moving old delta to the new clock. 64 | new_time.tv_sec = old_time.tv_sec - old_clock.tv_sec + new_clock.tv_sec; 65 | new_time.tv_nsec = old_time.tv_nsec - old_clock.tv_nsec + new_clock.tv_nsec; 66 | 67 | // correct nsec to second wrap. 68 | if (new_time.tv_nsec >= NS_PER_S) { 69 | new_time.tv_nsec -= NS_PER_S; 70 | new_time.tv_sec += 1; 71 | } else if (new_time.tv_nsec < 0) { 72 | new_time.tv_nsec += NS_PER_S; 73 | new_time.tv_sec -= 1; 74 | } 75 | } 76 | 77 | void monotonic_time_from_realtime_time(timespec& monotonic_time, const timespec& realtime_time) { 78 | convert_timespec_clocks(monotonic_time, CLOCK_MONOTONIC, realtime_time, CLOCK_REALTIME); 79 | } 80 | 81 | void realtime_time_from_monotonic_time(timespec& realtime_time, const timespec& monotonic_time) { 82 | convert_timespec_clocks(realtime_time, CLOCK_REALTIME, monotonic_time, CLOCK_MONOTONIC); 83 | } 84 | -------------------------------------------------------------------------------- /bionic/dirent.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include "private/ErrnoRestorer.h" 40 | 41 | extern "C" int sys_getdents64(unsigned int, dirent*, unsigned int); 42 | 43 | // Apportable decided to copy the data structure from this file 44 | // and use it in their own code, but they also call into readdir. 45 | // In order to avoid a lockup, the structure must be maintained in 46 | // the exact same order as in L and below. New structure members 47 | // need to be added to the end of this structure. 48 | // See b/21037208 for more details. 49 | struct DIR { 50 | int fd_; 51 | size_t available_bytes_; 52 | dirent* next_; 53 | dirent buff_[15]; 54 | long current_pos_; 55 | }; 56 | 57 | static DIR* __allocate_DIR(int fd) { 58 | DIR* d = reinterpret_cast(malloc(sizeof(DIR))); 59 | if (d == nullptr) { 60 | return nullptr; 61 | } 62 | d->fd_ = fd; 63 | d->available_bytes_ = 0; 64 | d->next_ = nullptr; 65 | d->current_pos_ = 0L; 66 | return d; 67 | } 68 | 69 | int dirfd(DIR* d) { 70 | return d->fd_; 71 | } 72 | 73 | DIR* fdopendir(int fd) { 74 | // Is 'fd' actually a directory? 75 | struct stat sb; 76 | if (fstat(fd, &sb) == -1) { 77 | return nullptr; 78 | } 79 | if (!S_ISDIR(sb.st_mode)) { 80 | errno = ENOTDIR; 81 | return nullptr; 82 | } 83 | 84 | return __allocate_DIR(fd); 85 | } 86 | 87 | DIR* opendir(const char* path) { 88 | int fd = open(path, O_CLOEXEC | O_DIRECTORY | O_RDONLY); 89 | return (fd != -1) ? __allocate_DIR(fd) : nullptr; 90 | } 91 | 92 | static bool __fill_DIR(DIR* d) { 93 | int rc = TEMP_FAILURE_RETRY(sys_getdents64(d->fd_, d->buff_, sizeof(d->buff_))); 94 | if (rc <= 0) { 95 | return false; 96 | } 97 | d->available_bytes_ = rc; 98 | d->next_ = d->buff_; 99 | return true; 100 | } 101 | 102 | static dirent* __readdir_locked(DIR* d) { 103 | if (d->available_bytes_ == 0 && !__fill_DIR(d)) { 104 | return nullptr; 105 | } 106 | 107 | dirent* entry = d->next_; 108 | d->next_ = reinterpret_cast(reinterpret_cast(entry) + entry->d_reclen); 109 | d->available_bytes_ -= entry->d_reclen; 110 | // The directory entry offset uses 0, 1, 2 instead of real file offset, 111 | // so the value range of long type is enough. 112 | d->current_pos_ = static_cast(entry->d_off); 113 | return entry; 114 | } 115 | 116 | dirent* readdir(DIR* d) { 117 | return __readdir_locked(d); 118 | } 119 | __strong_alias(readdir64, readdir); 120 | 121 | int readdir_r(DIR* d, dirent* entry, dirent** result) { 122 | ErrnoRestorer errno_restorer; 123 | 124 | *result = nullptr; 125 | errno = 0; 126 | 127 | dirent* next = __readdir_locked(d); 128 | if (errno != 0 && next == nullptr) { 129 | return errno; 130 | } 131 | 132 | if (next != nullptr) { 133 | memcpy(entry, next, next->d_reclen); 134 | *result = entry; 135 | } 136 | return 0; 137 | } 138 | __strong_alias(readdir64_r, readdir_r); 139 | 140 | int closedir(DIR* d) { 141 | if (d == nullptr) { 142 | errno = EINVAL; 143 | return -1; 144 | } 145 | 146 | int fd = d->fd_; 147 | int rc = close(fd); 148 | free(d); 149 | return rc; 150 | } 151 | 152 | void rewinddir(DIR* d) { 153 | lseek(d->fd_, 0, SEEK_SET); 154 | d->available_bytes_ = 0; 155 | d->current_pos_ = 0L; 156 | } 157 | 158 | void seekdir(DIR* d, long offset) { 159 | off_t ret = lseek(d->fd_, offset, SEEK_SET); 160 | if (ret != -1L) { 161 | d->available_bytes_ = 0; 162 | d->current_pos_ = ret; 163 | } 164 | } 165 | 166 | long telldir(DIR* d) { 167 | return d->current_pos_; 168 | } 169 | -------------------------------------------------------------------------------- /bionic/faccessat.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | extern "C" int sys_faccessat(int, const char*, int); 34 | 35 | int faccessat(int dirfd, const char* pathname, int mode, int flags) { 36 | // "The mode specifies the accessibility check(s) to be performed, 37 | // and is either the value F_OK, or a mask consisting of the 38 | // bitwise OR of one or more of R_OK, W_OK, and X_OK." 39 | if ((mode != F_OK) && ((mode & ~(R_OK | W_OK | X_OK)) != 0) && 40 | ((mode & (R_OK | W_OK | X_OK)) == 0)) { 41 | errno = EINVAL; 42 | return -1; 43 | } 44 | 45 | if (flags != 0) { 46 | // We deliberately don't support AT_SYMLINK_NOFOLLOW, a glibc 47 | // only feature which is error prone and dangerous. 48 | // More details at http://permalink.gmane.org/gmane.linux.lib.musl.general/6952 49 | // 50 | // AT_EACCESS isn't supported either. Android doesn't have setuid 51 | // programs, and never runs code with euid!=uid. 52 | // 53 | // We could use faccessat2(2) from Linux 5.8, but since we don't want the 54 | // first feature and don't need the second, we just reject such requests. 55 | errno = EINVAL; 56 | return -1; 57 | } 58 | 59 | return sys_faccessat(dirfd, pathname, mode); 60 | } 61 | -------------------------------------------------------------------------------- /bionic/fcntl.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | #include 31 | 32 | extern "C" int sys_fcntl(int fd, int cmd, ...); 33 | extern "C" int sys_fcntl64(int, int, ...); 34 | 35 | int fcntl(int fd, int cmd, ...) { 36 | va_list args; 37 | va_start(args, cmd); 38 | // This is a bit sketchy for LP64, especially because arg can be an int, 39 | // but all of our supported 64-bit ABIs pass the argument in a register. 40 | void* arg = va_arg(args, void*); 41 | va_end(args); 42 | 43 | if (cmd == F_SETFD && (reinterpret_cast(arg) & ~FD_CLOEXEC) != 0) { 44 | return -1; 45 | } 46 | 47 | #if defined(__LP64__) 48 | return sys_fcntl(fd, cmd, arg); 49 | #else 50 | // For LP32 we use the fcntl64 system call to signal that we're using struct flock64. 51 | return sys_fcntl64(fd, cmd, arg); 52 | #endif 53 | } 54 | -------------------------------------------------------------------------------- /bionic/poll.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #undef __BIONIC_AVAILABILITY_GUARD 30 | #define __BIONIC_AVAILABILITY_GUARD(api_level) 1 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #include "private/bionic_time_conversions.h" 37 | #include "private/SigSetConverter.h" 38 | 39 | extern "C" int sys_ppoll(pollfd*, unsigned int, timespec*, const sigset64_t*, size_t); 40 | extern "C" int sys_pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*); 41 | 42 | int poll(pollfd* fds, nfds_t fd_count, int ms) { 43 | timespec ts; 44 | timespec* ts_ptr = nullptr; 45 | if (ms >= 0) { 46 | timespec_from_ms(ts, ms); 47 | ts_ptr = &ts; 48 | } 49 | return sys_ppoll(fds, fd_count, ts_ptr, nullptr, 0); 50 | } 51 | 52 | int ppoll64(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset64_t* ss) { 53 | // The underlying sys_ppoll system call modifies its `struct timespec` argument. 54 | timespec mutable_ts; 55 | timespec* mutable_ts_ptr = nullptr; 56 | if (ts != nullptr) { 57 | mutable_ts = *ts; 58 | mutable_ts_ptr = &mutable_ts; 59 | } 60 | 61 | sigset64_t mutable_ss; 62 | sigset64_t* mutable_ss_ptr = nullptr; 63 | if (ss != nullptr) { 64 | mutable_ss = *ss; 65 | mutable_ss_ptr = &mutable_ss; 66 | } 67 | 68 | return sys_ppoll(fds, fd_count, mutable_ts_ptr, mutable_ss_ptr, sizeof(*mutable_ss_ptr)); 69 | } 70 | 71 | // The underlying ppoll(2) system call only takes `sigset64_t`. 72 | #if defined(__LP64__) 73 | // That's fine for LP64 where `sigset_t` and `sigset64_t` are the same. 74 | __strong_alias(ppoll, ppoll64); 75 | #else 76 | // ILP32 needs a shim. 77 | int ppoll(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset_t* ss) { 78 | SigSetConverter set{ss}; 79 | return ppoll64(fds, fd_count, ts, set.ptr); 80 | } 81 | #endif 82 | 83 | int select(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds, timeval* tv) { 84 | timespec ts; 85 | timespec* ts_ptr = nullptr; 86 | if (tv != nullptr) { 87 | if (!timespec_from_timeval(ts, *tv)) { 88 | errno = EINVAL; 89 | return -1; 90 | } 91 | ts_ptr = &ts; 92 | } 93 | int result = sys_pselect6(fd_count, read_fds, write_fds, error_fds, ts_ptr, nullptr); 94 | if (tv != nullptr) { 95 | timeval_from_timespec(*tv, ts); 96 | } 97 | return result; 98 | } 99 | 100 | int pselect64(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds, 101 | const timespec* ts, const sigset64_t* ss) { 102 | // The underlying sys_pselect6 system call modifies its `struct timespec` argument. 103 | timespec mutable_ts; 104 | timespec* mutable_ts_ptr = nullptr; 105 | if (ts != nullptr) { 106 | mutable_ts = *ts; 107 | mutable_ts_ptr = &mutable_ts; 108 | } 109 | 110 | sigset64_t mutable_ss; 111 | sigset64_t* mutable_ss_ptr = nullptr; 112 | if (ss != nullptr) { 113 | mutable_ss = *ss; 114 | mutable_ss_ptr = &mutable_ss; 115 | } 116 | 117 | // The Linux kernel only handles 6 arguments and this system call really needs 7, 118 | // so the last argument is a void* pointing to: 119 | struct pselect6_extra_data_t { 120 | uintptr_t ss_addr; 121 | size_t ss_len; 122 | }; 123 | pselect6_extra_data_t extra_data; 124 | extra_data.ss_addr = reinterpret_cast(mutable_ss_ptr); 125 | extra_data.ss_len = sizeof(*mutable_ss_ptr); 126 | 127 | return sys_pselect6(fd_count, read_fds, write_fds, error_fds, mutable_ts_ptr, &extra_data); 128 | } 129 | 130 | // The underlying pselect6(2) system call only takes `sigset64_t`. 131 | #if defined(__LP64__) 132 | // That's fine for LP64 where `sigset_t` and `sigset64_t` are the same. 133 | __strong_alias(pselect, pselect64); 134 | #else 135 | // ILP32 needs a shim. 136 | int pselect(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds, 137 | const timespec* ts, const sigset_t* ss) { 138 | // The underlying `sys_pselect6` system call only takes `sigset64_t`. 139 | SigSetConverter set{ss}; 140 | return pselect64(fd_count, read_fds, write_fds, error_fds, ts, set.ptr); 141 | } 142 | #endif 143 | -------------------------------------------------------------------------------- /bionic/private/ErrnoRestorer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | 21 | class ErrnoRestorer { 22 | public: 23 | explicit ErrnoRestorer() : saved_errno_(errno) { 24 | } 25 | 26 | ~ErrnoRestorer() { 27 | errno = saved_errno_; 28 | } 29 | 30 | void override(int new_errno) { 31 | saved_errno_ = new_errno; 32 | } 33 | 34 | private: 35 | int saved_errno_; 36 | }; 37 | -------------------------------------------------------------------------------- /bionic/private/SigSetConverter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | // Android's 32-bit ABI shipped with a sigset_t too small to include any 32 | // of the realtime signals, so we have both sigset_t and sigset64_t. Many 33 | // new system calls only accept a sigset64_t, so this helps paper over 34 | // the difference at zero cost to LP64 in most cases after the optimizer 35 | // removes the unnecessary temporary `ptr`. 36 | struct SigSetConverter { 37 | public: 38 | SigSetConverter(const sigset_t* s) : SigSetConverter(const_cast(s)) {} 39 | 40 | SigSetConverter(sigset_t* s) { 41 | #if defined(__LP64__) 42 | // sigset_t == sigset64_t on LP64. 43 | ptr = s; 44 | #else 45 | sigset64 = {}; 46 | if (s != nullptr) { 47 | original_ptr = s; 48 | sigset = *s; 49 | ptr = &sigset64; 50 | } else { 51 | ptr = nullptr; 52 | } 53 | #endif 54 | } 55 | 56 | void copy_out() { 57 | #if defined(__LP64__) 58 | // We used the original pointer directly, so no copy needed. 59 | #else 60 | *original_ptr = sigset; 61 | #endif 62 | } 63 | 64 | sigset64_t* ptr; 65 | 66 | private: 67 | [[maybe_unused]] sigset_t* original_ptr; 68 | union { 69 | sigset_t sigset; 70 | sigset64_t sigset64; 71 | }; 72 | }; 73 | -------------------------------------------------------------------------------- /bionic/private/bionic_asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #define __ASSEMBLY__ 32 | 33 | /* https://github.com/android/ndk/issues/1422 */ 34 | #include 35 | 36 | #include /* For system call numbers. */ 37 | #define MAX_ERRNO 4095 /* For recognizing system call error returns. */ 38 | 39 | #define __bionic_asm_custom_entry(f) 40 | #define __bionic_asm_custom_end(f) 41 | #define __bionic_asm_function_type @function 42 | #define __bionic_asm_custom_note_gnu_section() 43 | 44 | #if defined(__aarch64__) 45 | #include "bionic_asm_arm64.h" 46 | #elif defined(__arm__) 47 | #include "bionic_asm_arm.h" 48 | #elif defined(__i386__) 49 | #include "bionic_asm_x86.h" 50 | #elif defined(__riscv) 51 | #include "bionic_asm_riscv64.h" 52 | #elif defined(__x86_64__) 53 | #include "bionic_asm_x86_64.h" 54 | #endif 55 | 56 | // Starts a normal assembler routine. 57 | #define ENTRY(__f) __ENTRY_WITH_BINDING(__f, .globl) 58 | 59 | // Starts an assembler routine with hidden visibility. 60 | #define ENTRY_PRIVATE(__f) \ 61 | __ENTRY_WITH_BINDING(__f, .globl); \ 62 | .hidden __f; 63 | 64 | // Starts an assembler routine that's weak so native bridges can override it. 65 | #define ENTRY_WEAK_FOR_NATIVE_BRIDGE(__f) __ENTRY_WITH_BINDING(__f, .weak) 66 | 67 | // Starts an assembler routine with hidden visibility and no DWARF information. 68 | // Only used for internal functions passed via sa_restorer. 69 | // TODO: can't we just delete all those and let the kernel do its thing? 70 | #define ENTRY_NO_DWARF_PRIVATE(__f) \ 71 | __ENTRY_NO_DWARF(__f, .globl); \ 72 | .hidden __f; 73 | 74 | // (Implementation detail.) 75 | #define __ENTRY_NO_DWARF(__f, __binding) \ 76 | .text; \ 77 | __binding __f; \ 78 | .balign __bionic_asm_align; \ 79 | .type __f, __bionic_asm_function_type; \ 80 | __f: \ 81 | __bionic_asm_custom_entry(__f); 82 | 83 | // (Implementation detail.) 84 | #define __ENTRY_WITH_BINDING(__f, __binding) \ 85 | __ENTRY_NO_DWARF(__f, __binding); \ 86 | .cfi_startproc; 87 | 88 | // Ends a normal assembler routine. 89 | #define END(__f) \ 90 | .cfi_endproc; \ 91 | END_NO_DWARF(__f) 92 | 93 | // Ends an assembler routine with no DWARF information. 94 | // Only used for internal functions passed via sa_restorer. 95 | // TODO: can't we just delete all those and let the kernel do its thing? 96 | #define END_NO_DWARF(__f) \ 97 | .size __f, .- __f; \ 98 | __bionic_asm_custom_end(__f) 99 | 100 | // Creates an alias `alias` for the symbol `original`. 101 | #define ALIAS_SYMBOL(alias, original) \ 102 | .globl alias; \ 103 | .equ alias, original 104 | 105 | // Creates an alias `alias` for the symbol `original` that's weak so it can be 106 | // separately overridden by native bridges. 107 | #define ALIAS_SYMBOL_WEAK_FOR_NATIVE_BRIDGE(alias, original) \ 108 | .weak alias; \ 109 | .equ alias, original 110 | 111 | // Adds a GNU property ELF note. Important on arm64 to declare PAC/BTI support. 112 | #define NOTE_GNU_PROPERTY() __bionic_asm_custom_note_gnu_section() 113 | 114 | // Gives local labels a more convenient and readable syntax. 115 | #define L(__label) .L##__label 116 | -------------------------------------------------------------------------------- /bionic/private/bionic_asm_arm.h: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: asm.h,v 1.1 2004/02/01 05:09:49 drahn Exp $ */ 2 | /* $NetBSD: asm.h,v 1.4 2001/07/16 05:43:32 matt Exp $ */ 3 | 4 | /* 5 | * Copyright (c) 1990 The Regents of the University of California. 6 | * All rights reserved. 7 | * 8 | * This code is derived from software contributed to Berkeley by 9 | * William Jolitz. 10 | * 11 | * Redistribution and use in source and binary forms, with or without 12 | * modification, are permitted provided that the following conditions 13 | * are met: 14 | * 1. Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 3. Neither the name of the University nor the names of its contributors 20 | * may be used to endorse or promote products derived from this software 21 | * without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 | * SUCH DAMAGE. 34 | * 35 | * from: @(#)asm.h 5.5 (Berkeley) 5/7/91 36 | */ 37 | 38 | #pragma once 39 | 40 | #define __bionic_asm_align 0 41 | 42 | #undef __bionic_asm_custom_entry 43 | #undef __bionic_asm_custom_end 44 | #define __bionic_asm_custom_entry(f) .fnstart 45 | #define __bionic_asm_custom_end(f) .fnend 46 | 47 | #undef __bionic_asm_function_type 48 | #define __bionic_asm_function_type #function 49 | -------------------------------------------------------------------------------- /bionic/private/bionic_asm_arm64.h: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: asm.h,v 1.1 2004/02/01 05:09:49 drahn Exp $ */ 2 | /* $NetBSD: asm.h,v 1.4 2001/07/16 05:43:32 matt Exp $ */ 3 | 4 | /* 5 | * Copyright (c) 1990 The Regents of the University of California. 6 | * All rights reserved. 7 | * 8 | * This code is derived from software contributed to Berkeley by 9 | * William Jolitz. 10 | * 11 | * Redistribution and use in source and binary forms, with or without 12 | * modification, are permitted provided that the following conditions 13 | * are met: 14 | * 1. Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 3. Neither the name of the University nor the names of its contributors 20 | * may be used to endorse or promote products derived from this software 21 | * without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 | * SUCH DAMAGE. 34 | * 35 | * from: @(#)asm.h 5.5 (Berkeley) 5/7/91 36 | */ 37 | 38 | #pragma once 39 | 40 | #define __bionic_asm_align 16 41 | 42 | #undef __bionic_asm_function_type 43 | #define __bionic_asm_function_type %function 44 | 45 | #if defined(__ARM_FEATURE_BTI_DEFAULT) 46 | #define __bionic_asm_aarch64_feature_bti (1 << 0) 47 | #undef __bionic_asm_custom_entry 48 | #define __bionic_asm_custom_entry(f) bti c 49 | #else 50 | #define __bionic_asm_aarch64_feature_bti 0 51 | #endif 52 | 53 | #if defined(__ARM_FEATURE_PAC_DEFAULT) 54 | #define __bionic_asm_aarch64_feature_pac (1 << 1) 55 | #else 56 | #define __bionic_asm_aarch64_feature_pac 0 57 | #endif 58 | 59 | #undef __bionic_asm_custom_note_gnu_section 60 | #define __bionic_asm_custom_note_gnu_section() \ 61 | .pushsection .note.gnu.property, "a"; \ 62 | .balign 8; \ 63 | .long 4; \ 64 | .long 0x10; \ 65 | .long 0x5; /* NT_GNU_PROPERTY_TYPE_0 */ \ 66 | .asciz "GNU"; \ 67 | .long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ \ 68 | .long 4; \ 69 | .long (__bionic_asm_aarch64_feature_pac | \ 70 | __bionic_asm_aarch64_feature_bti); \ 71 | .long 0; \ 72 | .popsection; 73 | 74 | #define NT_MEMTAG_LEVEL_MASK 3 75 | #define NT_MEMTAG_LEVEL_NONE 0 76 | #define NT_MEMTAG_LEVEL_ASYNC 1 77 | #define NT_MEMTAG_LEVEL_SYNC 2 78 | #define NT_MEMTAG_HEAP 4 79 | #define NT_MEMTAG_STACK 8 80 | -------------------------------------------------------------------------------- /bionic/private/bionic_asm_riscv64.h: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: asm.h,v 1.1 2004/02/01 05:09:49 drahn Exp $ */ 2 | /* $NetBSD: asm.h,v 1.4 2001/07/16 05:43:32 matt Exp $ */ 3 | 4 | /* 5 | * Copyright (c) 1990 The Regents of the University of California. 6 | * All rights reserved. 7 | * 8 | * This code is derived from software contributed to Berkeley by 9 | * William Jolitz. 10 | * 11 | * Redistribution and use in source and binary forms, with or without 12 | * modification, are permitted provided that the following conditions 13 | * are met: 14 | * 1. Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 3. Neither the name of the University nor the names of its contributors 20 | * may be used to endorse or promote products derived from this software 21 | * without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 | * SUCH DAMAGE. 34 | * 35 | * from: @(#)asm.h 5.5 (Berkeley) 5/7/91 36 | */ 37 | 38 | #pragma once 39 | 40 | #define __bionic_asm_align 16 41 | 42 | #undef __bionic_asm_function_type 43 | #define __bionic_asm_function_type %function 44 | -------------------------------------------------------------------------------- /bionic/private/bionic_asm_x86.h: -------------------------------------------------------------------------------- 1 | /* $NetBSD: asm.h,v 1.40 2011/06/16 13:16:20 joerg Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1990 The Regents of the University of California. 5 | * All rights reserved. 6 | * 7 | * This code is derived from software contributed to Berkeley by 8 | * William Jolitz. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the University nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 | * SUCH DAMAGE. 33 | * 34 | * @(#)asm.h 5.5 (Berkeley) 5/7/91 35 | */ 36 | 37 | #pragma once 38 | 39 | #define PIC_PROLOGUE \ 40 | pushl %ebx; \ 41 | call 666f; \ 42 | 666: \ 43 | popl %ebx; \ 44 | addl $_GLOBAL_OFFSET_TABLE_+[.-666b], %ebx 45 | #define PIC_EPILOGUE \ 46 | popl %ebx 47 | #define PIC_PLT(x) x@PLT 48 | #define PIC_GOT(x) x@GOT(%ebx) 49 | #define PIC_GOTOFF(x) x@GOTOFF(%ebx) 50 | 51 | #define __bionic_asm_align 16 52 | -------------------------------------------------------------------------------- /bionic/private/bionic_asm_x86_64.h: -------------------------------------------------------------------------------- 1 | /* $NetBSD: asm.h,v 1.18 2013/09/12 15:36:17 joerg Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1990 The Regents of the University of California. 5 | * All rights reserved. 6 | * 7 | * This code is derived from software contributed to Berkeley by 8 | * William Jolitz. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the University nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 | * SUCH DAMAGE. 33 | * 34 | * @(#)asm.h 5.5 (Berkeley) 5/7/91 35 | */ 36 | 37 | #pragma once 38 | 39 | #define PIC_PLT(x) x@PLT 40 | #define PIC_GOT(x) x@GOTPCREL(%rip) 41 | 42 | #define __bionic_asm_align 16 43 | -------------------------------------------------------------------------------- /bionic/private/bionic_constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #define US_PER_S 1'000'000LL 20 | #define NS_PER_S 1'000'000'000LL 21 | 22 | // Size of the shadow call stack. This can be small because these stacks only 23 | // contain return addresses. This must be a power of 2 so the mask trick works. 24 | // See the SCS commentary in pthread_internal.h for more detail. 25 | // SCS_SIZE must be a multiple of page size. 26 | // We used 8KiB until V but switched to 16KiB in V to experiment with 16KiB pages. 27 | #define SCS_SIZE (16 * 1024) 28 | #define SCS_MASK (SCS_SIZE - 1) 29 | 30 | // The shadow call stack is allocated at an aligned address within a guard region of this size. The 31 | // guard region must be large enough that we can allocate an SCS_SIZE-aligned SCS while ensuring 32 | // that there is at least one guard page after the SCS so that a stack overflow results in a SIGSEGV 33 | // instead of corrupting the allocation that comes after it. 34 | #define SCS_GUARD_REGION_SIZE (16 * 1024 * 1024) 35 | -------------------------------------------------------------------------------- /bionic/private/bionic_errdefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | /* 30 | * This header is used to define error constants and names; 31 | * it might be included several times. 32 | */ 33 | 34 | #ifndef __BIONIC_ERRDEF 35 | #error __BIONIC_ERRDEF not defined 36 | #endif 37 | 38 | __BIONIC_ERRDEF(0, "Success") 39 | __BIONIC_ERRDEF(EPERM, "Operation not permitted") 40 | __BIONIC_ERRDEF(ENOENT, "No such file or directory") 41 | __BIONIC_ERRDEF(ESRCH, "No such process") 42 | __BIONIC_ERRDEF(EINTR, "Interrupted system call") 43 | __BIONIC_ERRDEF(EIO, "I/O error") 44 | __BIONIC_ERRDEF(ENXIO, "No such device or address") 45 | __BIONIC_ERRDEF(E2BIG, "Argument list too long") 46 | __BIONIC_ERRDEF(ENOEXEC, "Exec format error") 47 | __BIONIC_ERRDEF(EBADF, "Bad file descriptor") 48 | __BIONIC_ERRDEF(ECHILD, "No child processes") 49 | __BIONIC_ERRDEF(EAGAIN, "Try again") 50 | __BIONIC_ERRDEF(ENOMEM, "Out of memory") 51 | __BIONIC_ERRDEF(EACCES, "Permission denied") 52 | __BIONIC_ERRDEF(EFAULT, "Bad address") 53 | __BIONIC_ERRDEF(ENOTBLK, "Block device required") 54 | __BIONIC_ERRDEF(EBUSY, "Device or resource busy") 55 | __BIONIC_ERRDEF(EEXIST, "File exists") 56 | __BIONIC_ERRDEF(EXDEV, "Cross-device link") 57 | __BIONIC_ERRDEF(ENODEV, "No such device") 58 | __BIONIC_ERRDEF(ENOTDIR, "Not a directory") 59 | __BIONIC_ERRDEF(EISDIR, "Is a directory") 60 | __BIONIC_ERRDEF(EINVAL, "Invalid argument") 61 | __BIONIC_ERRDEF(ENFILE, "File table overflow") 62 | __BIONIC_ERRDEF(EMFILE, "Too many open files") 63 | __BIONIC_ERRDEF(ENOTTY, "Inappropriate ioctl for device") 64 | __BIONIC_ERRDEF(ETXTBSY, "Text file busy") 65 | __BIONIC_ERRDEF(EFBIG, "File too large") 66 | __BIONIC_ERRDEF(ENOSPC, "No space left on device") 67 | __BIONIC_ERRDEF(ESPIPE, "Illegal seek") 68 | __BIONIC_ERRDEF(EROFS, "Read-only file system") 69 | __BIONIC_ERRDEF(EMLINK, "Too many links") 70 | __BIONIC_ERRDEF(EPIPE, "Broken pipe") 71 | __BIONIC_ERRDEF(EDOM, "Math argument out of domain of func") 72 | __BIONIC_ERRDEF(ERANGE, "Math result not representable") 73 | __BIONIC_ERRDEF(EDEADLK, "Resource deadlock would occur") 74 | __BIONIC_ERRDEF(ENAMETOOLONG, "File name too long") 75 | __BIONIC_ERRDEF(ENOLCK, "No record locks available") 76 | __BIONIC_ERRDEF(ENOSYS, "Function not implemented") 77 | __BIONIC_ERRDEF(ENOTEMPTY, "Directory not empty") 78 | __BIONIC_ERRDEF(ELOOP, "Too many symbolic links encountered") 79 | __BIONIC_ERRDEF(ENOMSG, "No message of desired type") 80 | __BIONIC_ERRDEF(EIDRM, "Identifier removed") 81 | __BIONIC_ERRDEF(ECHRNG, "Channel number out of range") 82 | __BIONIC_ERRDEF(EL2NSYNC, "Level 2 not synchronized") 83 | __BIONIC_ERRDEF(EL3HLT, "Level 3 halted") 84 | __BIONIC_ERRDEF(EL3RST, "Level 3 reset") 85 | __BIONIC_ERRDEF(ELNRNG, "Link number out of range") 86 | __BIONIC_ERRDEF(EUNATCH, "Protocol driver not attached") 87 | __BIONIC_ERRDEF(ENOCSI, "No CSI structure available") 88 | __BIONIC_ERRDEF(EL2HLT, "Level 2 halted") 89 | __BIONIC_ERRDEF(EBADE, "Invalid exchange") 90 | __BIONIC_ERRDEF(EBADR, "Invalid request descriptor") 91 | __BIONIC_ERRDEF(EXFULL, "Exchange full") 92 | __BIONIC_ERRDEF(ENOANO, "No anode") 93 | __BIONIC_ERRDEF(EBADRQC, "Invalid request code") 94 | __BIONIC_ERRDEF(EBADSLT, "Invalid slot") 95 | __BIONIC_ERRDEF(EBFONT, "Bad font file format") 96 | __BIONIC_ERRDEF(ENOSTR, "Device not a stream") 97 | __BIONIC_ERRDEF(ENODATA, "No data available") 98 | __BIONIC_ERRDEF(ETIME, "Timer expired") 99 | __BIONIC_ERRDEF(ENOSR, "Out of streams resources") 100 | __BIONIC_ERRDEF(ENONET, "Machine is not on the network") 101 | __BIONIC_ERRDEF(ENOPKG, "Package not installed") 102 | __BIONIC_ERRDEF(EREMOTE, "Object is remote") 103 | __BIONIC_ERRDEF(ENOLINK, "Link has been severed") 104 | __BIONIC_ERRDEF(EADV, "Advertise error") 105 | __BIONIC_ERRDEF(ESRMNT, "Srmount error") 106 | __BIONIC_ERRDEF(ECOMM, "Communication error on send") 107 | __BIONIC_ERRDEF(EPROTO, "Protocol error") 108 | __BIONIC_ERRDEF(EMULTIHOP, "Multihop attempted") 109 | __BIONIC_ERRDEF(EDOTDOT, "RFS specific error") 110 | __BIONIC_ERRDEF(EBADMSG, "Not a data message") 111 | __BIONIC_ERRDEF(EOVERFLOW, "Value too large for defined data type") 112 | __BIONIC_ERRDEF(ENOTUNIQ, "Name not unique on network") 113 | __BIONIC_ERRDEF(EBADFD, "File descriptor in bad state") 114 | __BIONIC_ERRDEF(EREMCHG, "Remote address changed") 115 | __BIONIC_ERRDEF(ELIBACC, "Can not access a needed shared library") 116 | __BIONIC_ERRDEF(ELIBBAD, "Accessing a corrupted shared library") 117 | __BIONIC_ERRDEF(ELIBSCN, ".lib section in a.out corrupted") 118 | __BIONIC_ERRDEF(ELIBMAX, "Attempting to link in too many shared libraries") 119 | __BIONIC_ERRDEF(ELIBEXEC, "Cannot exec a shared library directly") 120 | __BIONIC_ERRDEF(EILSEQ, "Illegal byte sequence") 121 | __BIONIC_ERRDEF(ERESTART, "Interrupted system call should be restarted") 122 | __BIONIC_ERRDEF(ESTRPIPE, "Streams pipe error") 123 | __BIONIC_ERRDEF(EUSERS, "Too many users") 124 | __BIONIC_ERRDEF(ENOTSOCK, "Socket operation on non-socket") 125 | __BIONIC_ERRDEF(EDESTADDRREQ, "Destination address required") 126 | __BIONIC_ERRDEF(EMSGSIZE, "Message too long") 127 | __BIONIC_ERRDEF(EPROTOTYPE, "Protocol wrong type for socket") 128 | __BIONIC_ERRDEF(ENOPROTOOPT, "Protocol not available") 129 | __BIONIC_ERRDEF(EPROTONOSUPPORT, "Protocol not supported") 130 | __BIONIC_ERRDEF(ESOCKTNOSUPPORT, "Socket type not supported") 131 | __BIONIC_ERRDEF(EOPNOTSUPP, "Operation not supported on transport endpoint") 132 | __BIONIC_ERRDEF(EPFNOSUPPORT, "Protocol family not supported") 133 | __BIONIC_ERRDEF(EAFNOSUPPORT, "Address family not supported by protocol") 134 | __BIONIC_ERRDEF(EADDRINUSE, "Address already in use") 135 | __BIONIC_ERRDEF(EADDRNOTAVAIL, "Cannot assign requested address") 136 | __BIONIC_ERRDEF(ENETDOWN, "Network is down") 137 | __BIONIC_ERRDEF(ENETUNREACH, "Network is unreachable") 138 | __BIONIC_ERRDEF(ENETRESET, "Network dropped connection because of reset") 139 | __BIONIC_ERRDEF(ECONNABORTED, "Software caused connection abort") 140 | __BIONIC_ERRDEF(ECONNRESET, "Connection reset by peer") 141 | __BIONIC_ERRDEF(ENOBUFS, "No buffer space available") 142 | __BIONIC_ERRDEF(EISCONN, "Transport endpoint is already connected") 143 | __BIONIC_ERRDEF(ENOTCONN, "Transport endpoint is not connected") 144 | __BIONIC_ERRDEF(ESHUTDOWN, "Cannot send after transport endpoint shutdown") 145 | __BIONIC_ERRDEF(ETOOMANYREFS, "Too many references: cannot splice") 146 | __BIONIC_ERRDEF(ETIMEDOUT, "Connection timed out") 147 | __BIONIC_ERRDEF(ECONNREFUSED, "Connection refused") 148 | __BIONIC_ERRDEF(EHOSTDOWN, "Host is down") 149 | __BIONIC_ERRDEF(EHOSTUNREACH, "No route to host") 150 | __BIONIC_ERRDEF(EALREADY, "Operation already in progress") 151 | __BIONIC_ERRDEF(EINPROGRESS, "Operation now in progress") 152 | __BIONIC_ERRDEF(ESTALE, "Stale NFS file handle") 153 | __BIONIC_ERRDEF(EUCLEAN, "Structure needs cleaning") 154 | __BIONIC_ERRDEF(ENOTNAM, "Not a XENIX named type file") 155 | __BIONIC_ERRDEF(ENAVAIL, "No XENIX semaphores available") 156 | __BIONIC_ERRDEF(EISNAM, "Is a named type file") 157 | __BIONIC_ERRDEF(EREMOTEIO, "Remote I/O error") 158 | __BIONIC_ERRDEF(EDQUOT, "Quota exceeded") 159 | __BIONIC_ERRDEF(ENOMEDIUM, "No medium found") 160 | __BIONIC_ERRDEF(EMEDIUMTYPE, "Wrong medium type") 161 | __BIONIC_ERRDEF(ECANCELED, "Operation Canceled") 162 | __BIONIC_ERRDEF(ENOKEY, "Required key not available") 163 | __BIONIC_ERRDEF(EKEYEXPIRED, "Key has expired") 164 | __BIONIC_ERRDEF(EKEYREVOKED, "Key has been revoked") 165 | __BIONIC_ERRDEF(EKEYREJECTED, "Key was rejected by service") 166 | __BIONIC_ERRDEF(EOWNERDEAD, "Owner died") 167 | __BIONIC_ERRDEF(ENOTRECOVERABLE, "State not recoverable") 168 | __BIONIC_ERRDEF(ERFKILL, "Operation not possible due to RF-kill") 169 | __BIONIC_ERRDEF(EHWPOISON, "Memory page has hardware error") 170 | 171 | #undef __BIONIC_ERRDEF 172 | -------------------------------------------------------------------------------- /bionic/private/bionic_time_conversions.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #include "bionic_constants.h" 36 | 37 | bool timespec_from_timeval(timespec& ts, const timeval& tv); 38 | void timespec_from_ms(timespec& ts, const int ms); 39 | 40 | void timeval_from_timespec(timeval& tv, const timespec& ts); 41 | 42 | void monotonic_time_from_realtime_time(timespec& monotonic_time, const timespec& realtime_time); 43 | void realtime_time_from_monotonic_time(timespec& realtime_time, const timespec& monotonic_time); 44 | 45 | static inline int64_t to_ns(const timespec& ts) { 46 | return ts.tv_sec * NS_PER_S + ts.tv_nsec; 47 | } 48 | 49 | static inline int64_t to_us(const timeval& tv) { 50 | return tv.tv_sec * US_PER_S + tv.tv_usec; 51 | } 52 | 53 | static inline int check_timespec(const timespec* ts, bool null_allowed) { 54 | if (null_allowed && ts == nullptr) { 55 | return 0; 56 | } 57 | // glibc just segfaults if you pass a null timespec. 58 | // That seems a lot more likely to catch bad code than returning EINVAL. 59 | if (ts->tv_nsec < 0 || ts->tv_nsec >= NS_PER_S) { 60 | return EINVAL; 61 | } 62 | if (ts->tv_sec < 0) { 63 | return ETIMEDOUT; 64 | } 65 | return 0; 66 | } 67 | 68 | #if !defined(__LP64__) 69 | static inline void absolute_timespec_from_timespec(timespec& abs_ts, const timespec& ts, clockid_t clock) { 70 | clock_gettime(clock, &abs_ts); 71 | abs_ts.tv_sec += ts.tv_sec; 72 | abs_ts.tv_nsec += ts.tv_nsec; 73 | if (abs_ts.tv_nsec >= NS_PER_S) { 74 | abs_ts.tv_nsec -= NS_PER_S; 75 | abs_ts.tv_sec++; 76 | } 77 | } 78 | #endif 79 | -------------------------------------------------------------------------------- /bionic/strerror.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | // -std=gnu++XX automatically defines _GNU_SOURCE, which then means that 30 | // gives us the GNU variant, which is not what we're defining here. 31 | #undef _GNU_SOURCE 32 | 33 | #include 34 | 35 | #include 36 | #include 37 | 38 | #include "private/ErrnoRestorer.h" 39 | 40 | #include 41 | #include 42 | 43 | // The arraysize(arr) macro returns the # of elements in an array arr. 44 | // The expression is a compile-time constant, and therefore can be 45 | // used in defining new arrays, for example. If you use arraysize on 46 | // a pointer by mistake, you will get a compile-time error. 47 | // 48 | // One caveat is that arraysize() doesn't accept any array of an 49 | // anonymous type or a type defined inside a function. 50 | // 51 | // This template function declaration is used in defining arraysize. 52 | // Note that the function doesn't need an implementation, as we only 53 | // use its type. 54 | template 55 | char (&ArraySizeHelper(T (&array)[N]))[N]; // NOLINT(readability/casting) 56 | 57 | #define arraysize(array) (sizeof(ArraySizeHelper(array))) 58 | 59 | static const char* __sys_error_descriptions[] = { 60 | #define __BIONIC_ERRDEF(error_number, error_description) [error_number] = error_description, 61 | #include "private/bionic_errdefs.h" 62 | }; 63 | 64 | static inline const char* __strerror_lookup(int error_number) { 65 | if (error_number < 0 || error_number >= static_cast(arraysize(__sys_error_descriptions))) { 66 | return nullptr; 67 | } 68 | return __sys_error_descriptions[error_number]; 69 | } 70 | 71 | int strerror_r(int error_number, char* buf, size_t buf_len) { 72 | ErrnoRestorer errno_restorer; 73 | size_t length; 74 | 75 | const char* error_name = __strerror_lookup(error_number); 76 | if (error_name != nullptr) { 77 | length = strlcpy(buf, error_name, buf_len); 78 | } else { 79 | length = snprintf(buf, buf_len, "Unknown error %d", error_number); 80 | } 81 | if (length >= buf_len) { 82 | return ERANGE; 83 | } 84 | 85 | return 0; 86 | } 87 | 88 | char* strerror(int error_number) { 89 | static char strerror_buf[NL_TEXTMAX]; 90 | 91 | // Just return the original constant in the easy cases. 92 | char* result = const_cast(__strerror_lookup(error_number)); 93 | if (result != nullptr) { 94 | return result; 95 | } 96 | 97 | result = strerror_buf; 98 | strerror_r(error_number, result, sizeof(strerror_buf)); 99 | return result; 100 | } 101 | -------------------------------------------------------------------------------- /bionic/syscall-arm.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include "private/bionic_asm.h" 30 | 31 | ENTRY(syscall) 32 | mov ip, sp 33 | stmfd sp!, {r4, r5, r6, r7} 34 | .cfi_def_cfa_offset 16 35 | .cfi_rel_offset r4, 0 36 | .cfi_rel_offset r5, 4 37 | .cfi_rel_offset r6, 8 38 | .cfi_rel_offset r7, 12 39 | mov r7, r0 40 | mov r0, r1 41 | mov r1, r2 42 | mov r2, r3 43 | ldmfd ip, {r3, r4, r5, r6} 44 | swi #0 45 | ldmfd sp!, {r4, r5, r6, r7} 46 | .cfi_def_cfa_offset 0 47 | cmn r0, #(MAX_ERRNO + 1) 48 | bxls lr 49 | neg r0, r0 50 | b __set_errno_internal 51 | END(syscall) 52 | -------------------------------------------------------------------------------- /bionic/syscall-arm64.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include "private/bionic_asm.h" 30 | 31 | ENTRY(syscall) 32 | /* Move syscall No. from x0 to x8 */ 33 | mov x8, x0 34 | /* Move syscall parameters from x1 thru x6 to x0 thru x5 */ 35 | mov x0, x1 36 | mov x1, x2 37 | mov x2, x3 38 | mov x3, x4 39 | mov x4, x5 40 | mov x5, x6 41 | svc #0 42 | 43 | /* check if syscall returned successfully */ 44 | cmn x0, #(MAX_ERRNO + 1) 45 | cneg x0, x0, hi 46 | b.hi __set_errno_internal 47 | 48 | ret 49 | END(syscall) 50 | 51 | NOTE_GNU_PROPERTY() 52 | -------------------------------------------------------------------------------- /bionic/syscall-riscv64.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include "private/bionic_asm.h" 30 | 31 | ENTRY(syscall) 32 | // Move the syscall number up. 33 | mv a7, a0 34 | 35 | // Shuffle the arguments down. 36 | mv a0, a1 37 | mv a1, a2 38 | mv a2, a3 39 | mv a3, a4 40 | mv a4, a5 41 | mv a5, a6 42 | 43 | ecall 44 | 45 | // Did it fail? 46 | li a7, -MAX_ERRNO 47 | bgtu a0, a7, 1f 48 | 49 | ret 50 | 1: 51 | neg a0, a0 52 | tail __set_errno_internal 53 | END(syscall) 54 | -------------------------------------------------------------------------------- /bionic/syscall-x86.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Generic syscall call. 3 | * Upon entry: 4 | * %eax: system call number - caller save 5 | * %ebx: arg0 to system call - callee save 6 | * %ecx: arg1 - caller save 7 | * %edx: arg2 - caller save 8 | * %esi: arg3 - callee save 9 | * %edi: arg4 - callee save 10 | * %ebp: arg5 - callee save 11 | */ 12 | 13 | #include "private/bionic_asm.h" 14 | 15 | ENTRY(syscall) 16 | # Push the callee save registers. 17 | push %ebx 18 | .cfi_adjust_cfa_offset 4 19 | .cfi_rel_offset ebx, 0 20 | push %esi 21 | .cfi_adjust_cfa_offset 4 22 | .cfi_rel_offset esi, 0 23 | push %edi 24 | .cfi_adjust_cfa_offset 4 25 | .cfi_rel_offset edi, 0 26 | push %ebp 27 | .cfi_adjust_cfa_offset 4 28 | .cfi_rel_offset ebp, 0 29 | 30 | # Load all the arguments from the calling frame. 31 | # (Not all will be valid, depending on the syscall.) 32 | mov 20(%esp),%eax 33 | mov 24(%esp),%ebx 34 | mov 28(%esp),%ecx 35 | mov 32(%esp),%edx 36 | mov 36(%esp),%esi 37 | mov 40(%esp),%edi 38 | mov 44(%esp),%ebp 39 | 40 | # Make the system call. 41 | int $0x80 42 | 43 | # Error? 44 | cmpl $-MAX_ERRNO, %eax 45 | jb 1f 46 | # Yes, so set errno. 47 | negl %eax 48 | pushl %eax 49 | call __set_errno_internal 50 | addl $4, %esp 51 | 1: 52 | # Restore the callee save registers. 53 | pop %ebp 54 | .cfi_adjust_cfa_offset -4 55 | .cfi_restore ebp 56 | pop %edi 57 | .cfi_adjust_cfa_offset -4 58 | .cfi_restore edi 59 | pop %esi 60 | .cfi_adjust_cfa_offset -4 61 | .cfi_restore esi 62 | pop %ebx 63 | .cfi_adjust_cfa_offset -4 64 | .cfi_restore ebx 65 | ret 66 | END(syscall) 67 | -------------------------------------------------------------------------------- /bionic/syscall-x86_64.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | /* 30 | * Generic syscall call. 31 | * Upon entry: 32 | * %rax: system call number 33 | * %rdi: arg0 to system call 34 | * %rsi: arg1 35 | * %rdx: arg2 36 | * %rcx: arg3 - syscall expects it at %r10 37 | * %r8: arg4 38 | * %r9: arg5 39 | */ 40 | 41 | #include "private/bionic_asm.h" 42 | 43 | ENTRY(syscall) 44 | # All arguments are passed via registers. 45 | # (Not all will be valid, depending on the syscall.) 46 | mov %edi, %eax 47 | mov %rsi, %rdi 48 | mov %rdx, %rsi 49 | mov %rcx, %rdx 50 | mov %r8, %r10 51 | mov %r9, %r8 52 | mov 8(%rsp), %r9 53 | 54 | # Make the system call. 55 | syscall 56 | cmpq $-MAX_ERRNO, %rax 57 | jb 1f 58 | negl %eax 59 | movl %eax, %edi 60 | call __set_errno_internal 61 | 1: 62 | ret 63 | END(syscall) 64 | -------------------------------------------------------------------------------- /bionic/upstream-openbsd/getenv.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: getenv.c,v 1.12 2016/03/13 18:34:21 guenther Exp $ */ 2 | /* 3 | * Copyright (c) 1987, 1993 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 3. Neither the name of the University nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 | * SUCH DAMAGE. 29 | */ 30 | 31 | #include 32 | #include 33 | 34 | #include "openbsd-compat.h" 35 | 36 | 37 | /* 38 | * __findenv -- 39 | * Returns pointer to value associated with name, if any, else NULL. 40 | * Starts searching within the environmental array at offset. 41 | * Sets offset to be the offset of the name/value combination in the 42 | * environmental array, for use by putenv(3), setenv(3) and unsetenv(3). 43 | * Explicitly removes '=' in argument name. 44 | * 45 | * This routine *should* be a static; don't use it. 46 | */ 47 | char * 48 | __findenv(const char *name, int len, int *offset) 49 | { 50 | int i; 51 | const char *np; 52 | char **p, *cp; 53 | 54 | if (name == NULL || environ == NULL) 55 | return (NULL); 56 | for (p = environ + *offset; (cp = *p) != NULL; ++p) { 57 | for (np = name, i = len; i && *cp; i--) 58 | if (*cp++ != *np++) 59 | break; 60 | if (i == 0 && *cp++ == '=') { 61 | *offset = p - environ; 62 | return (cp); 63 | } 64 | } 65 | return (NULL); 66 | } 67 | 68 | /* 69 | * getenv -- 70 | * Returns ptr to value associated with name, if any, else NULL. 71 | */ 72 | char * 73 | getenv(const char *name) 74 | { 75 | int offset = 0; 76 | const char *np; 77 | 78 | for (np = name; *np && *np != '='; ++np) 79 | ; 80 | return (__findenv(name, (int)(np - name), &offset)); 81 | } 82 | DEF_STRONG(getenv); 83 | -------------------------------------------------------------------------------- /bionic/upstream-openbsd/openbsd-compat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #define _BSD_SOURCE 20 | #include 21 | 22 | #include // For environ. 23 | 24 | #include // For size_t. 25 | 26 | #include // For getentropy. 27 | 28 | #define __BEGIN_HIDDEN_DECLS _Pragma("GCC visibility push(hidden)") 29 | #define __END_HIDDEN_DECLS _Pragma("GCC visibility pop") 30 | 31 | extern const char* __progname; 32 | 33 | /* Ignore all DEF_STRONG/DEF_WEAK in OpenBSD. */ 34 | #define DEF_STRONG(sym) 35 | #define DEF_WEAK(sym) 36 | #define __weak_alias __strong_alias 37 | 38 | /* Ignore all __warn_references in OpenBSD. */ 39 | #define __warn_references(sym,msg) 40 | 41 | #define PROTO_NORMAL(x) 42 | 43 | /* OpenBSD's uses these names, which conflicted with stlport. 44 | * Additionally, we changed the numeric/digit type from N to D for libcxx. 45 | */ 46 | #define _U _CTYPE_U 47 | #define _L _CTYPE_L 48 | #define _N _CTYPE_D 49 | #define _S _CTYPE_S 50 | #define _P _CTYPE_P 51 | #define _C _CTYPE_C 52 | #define _X _CTYPE_X 53 | #define _B _CTYPE_B 54 | 55 | /* OpenBSD has this, but we can't really implement it correctly on Linux. */ 56 | #define issetugid() 0 57 | 58 | #define explicit_bzero(p, s) memset(p, 0, s) 59 | 60 | /* OpenBSD has this in paths.h. But this directory doesn't normally exist. 61 | * Even when it does exist, only the 'shell' user has permissions. 62 | */ 63 | #define _PATH_TMP "/data/local/tmp/" 64 | 65 | /* Use appropriate shell depending on process's executable. */ 66 | __LIBC_HIDDEN__ extern const char* __bionic_get_shell_path(); 67 | #define _PATH_BSHELL __bionic_get_shell_path() 68 | 69 | __LIBC_HIDDEN__ extern char* __findenv(const char*, int, int*); 70 | __LIBC_HIDDEN__ extern char* _mktemp(char*); 71 | 72 | // Only OpenBSD has this at the moment, and we're more likely to just say 73 | // "malloc is always calloc", so we don't expose this as libc API. 74 | __LIBC_HIDDEN__ void* recallocarray(void*, size_t, size_t, size_t); 75 | 76 | void *reallocarray(void *ptr, size_t, size_t); 77 | -------------------------------------------------------------------------------- /bionic/upstream-openbsd/setenv.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: setenv.c,v 1.20 2022/08/08 22:40:03 millert Exp $ */ 2 | /* 3 | * Copyright (c) 1987 Regents of the University of California. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 3. Neither the name of the University nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 | * SUCH DAMAGE. 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #include "openbsd-compat.h" 36 | 37 | static char **lastenv; /* last value of environ */ 38 | 39 | /* 40 | * putenv -- 41 | * Add a name=value string directly to the environmental, replacing 42 | * any current value. 43 | */ 44 | int 45 | putenv(char *str) 46 | { 47 | char **P, *cp; 48 | size_t cnt = 0; 49 | int offset = 0; 50 | 51 | for (cp = str; *cp && *cp != '='; ++cp) 52 | ; 53 | if (cp == str || *cp != '=') { 54 | /* '=' is the first character of string or is missing. */ 55 | errno = EINVAL; 56 | return (-1); 57 | } 58 | 59 | if (__findenv(str, (int)(cp - str), &offset) != NULL) { 60 | environ[offset++] = str; 61 | /* could be set multiple times */ 62 | while (__findenv(str, (int)(cp - str), &offset)) { 63 | for (P = &environ[offset];; ++P) 64 | if (!(*P = *(P + 1))) 65 | break; 66 | } 67 | return (0); 68 | } 69 | 70 | /* create new slot for string */ 71 | if (environ != NULL) { 72 | for (P = environ; *P != NULL; P++) 73 | ; 74 | cnt = P - environ; 75 | } 76 | P = reallocarray(lastenv, cnt + 2, sizeof(char *)); 77 | if (!P) 78 | return (-1); 79 | if (lastenv != environ && environ != NULL) 80 | memcpy(P, environ, cnt * sizeof(char *)); 81 | lastenv = environ = P; 82 | environ[cnt] = str; 83 | environ[cnt + 1] = NULL; 84 | return (0); 85 | } 86 | DEF_WEAK(putenv); 87 | 88 | /* 89 | * setenv -- 90 | * Set the value of the environmental variable "name" to be 91 | * "value". If rewrite is set, replace any current value. 92 | */ 93 | int 94 | setenv(const char *name, const char *value, int rewrite) 95 | { 96 | char *C, **P; 97 | const char *np; 98 | int l_value, offset = 0; 99 | 100 | if (!name || !*name) { 101 | errno = EINVAL; 102 | return (-1); 103 | } 104 | for (np = name; *np && *np != '='; ++np) 105 | ; 106 | if (*np) { 107 | errno = EINVAL; 108 | return (-1); /* has `=' in name */ 109 | } 110 | 111 | l_value = strlen(value); 112 | if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) { 113 | int tmpoff = offset + 1; 114 | if (!rewrite) 115 | return (0); 116 | #if 0 /* XXX - existing entry may not be writable */ 117 | if (strlen(C) >= l_value) { /* old larger; copy over */ 118 | while ((*C++ = *value++)) 119 | ; 120 | return (0); 121 | } 122 | #endif 123 | /* could be set multiple times */ 124 | while (__findenv(name, (int)(np - name), &tmpoff)) { 125 | for (P = &environ[tmpoff];; ++P) 126 | if (!(*P = *(P + 1))) 127 | break; 128 | } 129 | } else { /* create new slot */ 130 | size_t cnt = 0; 131 | 132 | if (environ != NULL) { 133 | for (P = environ; *P != NULL; P++) 134 | ; 135 | cnt = P - environ; 136 | } 137 | P = reallocarray(lastenv, cnt + 2, sizeof(char *)); 138 | if (!P) 139 | return (-1); 140 | if (lastenv != environ && environ != NULL) 141 | memcpy(P, environ, cnt * sizeof(char *)); 142 | lastenv = environ = P; 143 | offset = cnt; 144 | environ[cnt + 1] = NULL; 145 | } 146 | if (!(environ[offset] = /* name + `=' + value */ 147 | malloc((int)(np - name) + l_value + 2))) 148 | return (-1); 149 | for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) 150 | ; 151 | for (*C++ = '='; (*C++ = *value++); ) 152 | ; 153 | return (0); 154 | } 155 | DEF_WEAK(setenv); 156 | 157 | /* 158 | * unsetenv(name) -- 159 | * Delete environmental variable "name". 160 | */ 161 | int 162 | unsetenv(const char *name) 163 | { 164 | char **P; 165 | const char *np; 166 | int offset = 0; 167 | 168 | if (!name || !*name) { 169 | errno = EINVAL; 170 | return (-1); 171 | } 172 | for (np = name; *np && *np != '='; ++np) 173 | ; 174 | if (*np) { 175 | errno = EINVAL; 176 | return (-1); /* has `=' in name */ 177 | } 178 | 179 | /* could be set multiple times */ 180 | while (__findenv(name, (int)(np - name), &offset)) { 181 | for (P = &environ[offset];; ++P) 182 | if (!(*P = *(P + 1))) 183 | break; 184 | } 185 | return (0); 186 | } 187 | DEF_WEAK(unsetenv); 188 | -------------------------------------------------------------------------------- /bionic/upstream-openbsd/strlcpy.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $ */ 2 | 3 | /* 4 | * Copyright (c) 1998, 2015 Todd C. Miller 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "openbsd-compat.h" 23 | 24 | /* 25 | * Copy string src to buffer dst of size dsize. At most dsize-1 26 | * chars will be copied. Always NUL terminates (unless dsize == 0). 27 | * Returns strlen(src); if retval >= dsize, truncation occurred. 28 | */ 29 | size_t 30 | strlcpy(char *dst, const char *src, size_t dsize) 31 | { 32 | const char *osrc = src; 33 | size_t nleft = dsize; 34 | 35 | /* Copy as many bytes as will fit. */ 36 | if (nleft != 0) { 37 | while (--nleft != 0) { 38 | if ((*dst++ = *src++) == '\0') 39 | break; 40 | } 41 | } 42 | 43 | /* Not enough room in dst, add NUL and traverse rest of src. */ 44 | if (nleft == 0) { 45 | if (dsize != 0) 46 | *dst = '\0'; /* NUL-terminate dst */ 47 | while (*src++) 48 | ; 49 | } 50 | 51 | return(src - osrc - 1); /* count does not include NUL */ 52 | } 53 | DEF_WEAK(strlcpy); 54 | -------------------------------------------------------------------------------- /bionic/usleep.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | 31 | #include 32 | 33 | int usleep(useconds_t us) { 34 | timespec ts; 35 | ts.tv_sec = us / 1000000; 36 | ts.tv_nsec = (us % 1000000) * 1000; 37 | return nanosleep(&ts, nullptr); 38 | } 39 | -------------------------------------------------------------------------------- /crtbegin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | char **environ; 5 | 6 | extern void exit(int); 7 | extern void __init_stdio(void); 8 | 9 | typedef void init_func_t(int, char*[], char*[]); 10 | 11 | extern init_func_t *__preinit_array_start[]; 12 | extern init_func_t *__preinit_array_end[]; 13 | extern init_func_t *__init_array_start[]; 14 | extern init_func_t *__init_array_end[]; 15 | 16 | static void call_array(init_func_t **start, init_func_t **end, int argc, char *argv[], char *envp[]) { 17 | unsigned long count = end - start; 18 | while (count-- > 0) { 19 | init_func_t* function = *start++; 20 | (*function)(argc, argv, envp); 21 | } 22 | } 23 | 24 | typedef struct auxv_t { 25 | unsigned long type; 26 | unsigned long value; 27 | } auxv_t; 28 | 29 | static auxv_t *_auxv; 30 | 31 | // Inspired from Linux nolibc 32 | void _start_c(long *sp) { 33 | long argc; 34 | char **argv; 35 | char **envp; 36 | void **auxv; 37 | /* silence potential warning: conflicting types for 'main' */ 38 | int __real_main(int, char **, char **) __asm__ ("main"); 39 | 40 | /* 41 | * sp : argc <-- argument count, required by main() 42 | * argv: argv[0] <-- argument vector, required by main() 43 | * argv[1] 44 | * ... 45 | * argv[argc-1] 46 | * null 47 | * environ: environ[0] <-- environment variables, required by main() and getenv() 48 | * environ[1] 49 | * ... 50 | * null 51 | * auxv: auxv[0] <-- auxiliary vector, required by getauxval() 52 | * auxv[1] 53 | * ... 54 | * null 55 | */ 56 | 57 | /* assign argc and argv */ 58 | argc = *sp; 59 | argv = (void *)(sp + 1); 60 | 61 | /* find environ */ 62 | environ = envp = argv + argc + 1; 63 | 64 | /* find auxv */ 65 | for (auxv = (void *)envp; *auxv++;) 66 | ; 67 | _auxv = (void *) auxv; 68 | 69 | /* call preinit and init */ 70 | __init_stdio(); 71 | call_array(__preinit_array_start, __preinit_array_end, argc, argv, envp); 72 | call_array(__init_array_start, __init_array_end, argc, argv, envp); 73 | 74 | /* go to application */ 75 | exit(__real_main(argc, argv, envp)); 76 | } 77 | 78 | unsigned long getauxval(unsigned long type) { 79 | for (auxv_t *v = _auxv; v->type != AT_NULL; ++v) { 80 | if (v->type == type) { 81 | return v->value; 82 | } 83 | } 84 | errno = ENOENT; 85 | return 0; 86 | } 87 | 88 | // Assembly source: bionic/libc/arch-common/bionic/crtbegin.c 89 | 90 | #define PRE ".text; .global _start; .type _start,%function; _start:" 91 | #define POST "; .size _start, .-_start" 92 | 93 | #if defined(__aarch64__) 94 | __asm__(PRE "bti j; mov x29,#0; mov x30,#0; mov x0,sp; b _start_c" POST); 95 | #elif defined(__arm__) 96 | __asm__(PRE "mov fp,#0; mov lr,#0; mov r0,sp; b _start_c" POST); 97 | #elif defined(__i386__) 98 | __asm__(PRE 99 | "xorl %ebp,%ebp; movl %esp,%eax; andl $~0xf,%esp; subl $12,%esp; pushl %eax;" 100 | "call _start_c" POST); 101 | #elif defined(__riscv) 102 | __asm__(PRE "li fp,0; li ra,0; mv a0,sp; tail _start_c" POST); 103 | #elif defined(__x86_64__) 104 | __asm__(PRE "xorl %ebp, %ebp; movq %rsp,%rdi; andq $~0xf,%rsp; callq _start_c" POST); 105 | #else 106 | #error unsupported architecture 107 | #endif 108 | 109 | #undef PRE 110 | #undef POST 111 | -------------------------------------------------------------------------------- /fmt.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "stdio_impl.h" 4 | #include "printf/printf.h" 5 | 6 | // tiny_vfprintf implementation 7 | 8 | static void fct_putchar(char ch, void *p) { 9 | fputc(ch, (FILE *) p); 10 | } 11 | 12 | int tiny_vfprintf(FILE *stream, const char *format, va_list arg) { 13 | return vfctprintf(fct_putchar, stream, format, arg); 14 | } 15 | 16 | // {s,f}printf family wrappers 17 | 18 | int vasprintf(char **strp, const char *fmt, va_list ap) { 19 | int size = vsnprintf(NULL, 0, fmt, ap); 20 | if (size >= 0) { 21 | *strp = malloc(size + 1); 22 | vsnprintf(*strp, size, fmt, ap); 23 | } 24 | return size; 25 | } 26 | 27 | int vsprintf(char *str, const char *fmt, va_list ap) { 28 | file_impl file; 29 | buf_holder h; 30 | h.begin = str; 31 | h.end = NULL; 32 | setup_buf_fp(&file, &h); 33 | 34 | int retval = vfprintf((FILE *) &file, fmt, ap); 35 | if (retval > 0) { 36 | str[retval] = '\0'; 37 | } 38 | return retval; 39 | } 40 | 41 | int sprintf(char *str, const char *format, ...) { 42 | va_list ap; 43 | int retval; 44 | 45 | va_start(ap, format); 46 | retval = vsprintf(str, format, ap); 47 | va_end(ap); 48 | return retval; 49 | } 50 | 51 | int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) { 52 | file_impl file; 53 | buf_holder h; 54 | h.begin = str; 55 | h.end = str + size; 56 | setup_buf_fp(&file, &h); 57 | 58 | int retval = vfprintf((FILE *) &file, fmt, ap); 59 | if (retval > 0) { 60 | str[MIN(size - 1, retval)] = '\0'; 61 | } 62 | return retval; 63 | } 64 | 65 | int snprintf(char *str, size_t size, const char *format, ...) { 66 | va_list ap; 67 | int retval; 68 | 69 | va_start(ap, format); 70 | retval = vsnprintf(str, size, format, ap); 71 | va_end(ap); 72 | return retval; 73 | } 74 | 75 | int vprintf(const char *fmt, va_list args) { 76 | return vfprintf(stdout, fmt, args); 77 | } 78 | 79 | int fprintf(FILE *stream, const char *fmt, ...) { 80 | va_list args; 81 | int ret; 82 | 83 | va_start(args, fmt); 84 | ret = vfprintf(stream, fmt, args); 85 | va_end(args); 86 | return ret; 87 | } 88 | 89 | int printf(const char *fmt, ...) { 90 | va_list args; 91 | int ret; 92 | 93 | va_start(args, fmt); 94 | ret = vfprintf(stdout, fmt, args); 95 | va_end(args); 96 | return ret; 97 | } 98 | 99 | // sscanf family 100 | 101 | int musl_vfscanf(FILE *f, const char *fmt, va_list ap); 102 | 103 | int vsscanf(const char *s, const char *fmt, va_list args) { 104 | file_impl file; 105 | buf_holder h; 106 | h.begin = (void *) s; 107 | h.end = NULL; 108 | setup_buf_fp(&file, &h); 109 | return musl_vfscanf((FILE *) &file, fmt, args); 110 | } 111 | 112 | int sscanf(const char *str, const char *format, ...) { 113 | va_list ap; 114 | int retval; 115 | 116 | va_start(ap, format); 117 | retval = vsscanf(str, format, ap); 118 | va_end(ap); 119 | return retval; 120 | } 121 | -------------------------------------------------------------------------------- /malloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define BLOCK_SIZE (1 << 22) /* 4M */ 8 | #define MMAP_THRESHOLD (1 << 18) /* 256k */ 9 | #define WORD_SZ (sizeof(void*)) 10 | #define MIN_ALIGNMENT (2 * WORD_SZ) 11 | 12 | #define CHUNK_START(p) *((void **)(p - WORD_SZ)) 13 | #define CHUNK_SIZE(p) *((size_t *) CHUNK_START(p)) 14 | 15 | #define sys_alloc(s) mmap(NULL, s, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) 16 | 17 | /* 18 | * Allocated memory chunk layout 19 | * 20 | * +-------------+ <----------- chunk_start 21 | * | chunk_size | size_t 22 | * +-------------+ 23 | * | padding | n words (n can be 0) 24 | * +-------------+ 25 | * | chunk_start | void * 26 | * +-------------+ <----------- data_start 27 | * | data | chunk_size 28 | * +-------------+ 29 | * 30 | */ 31 | 32 | static inline size_t align(size_t l, size_t align) { 33 | return (l + align - 1) / align * align; 34 | } 35 | 36 | // Prefix is chunk_size + padding + chunk_start 37 | static size_t calculate_prefix(size_t start, size_t alignment) { 38 | size_t p = start; 39 | // Reserve 2 words, one for chunk_size, one for chunk_start 40 | p += 2 * WORD_SZ; 41 | p = align(p, alignment); 42 | return p - start; 43 | } 44 | 45 | void *memalign(size_t alignment, size_t size) { 46 | static struct { 47 | void *curr; 48 | void *end; 49 | } block = { NULL, NULL }; 50 | 51 | if (alignment < MIN_ALIGNMENT) alignment = MIN_ALIGNMENT; 52 | if (alignment > getpagesize()) alignment = getpagesize(); 53 | size = align(size, MIN_ALIGNMENT); 54 | 55 | if (size >= MMAP_THRESHOLD) { 56 | size_t prefix = calculate_prefix(0, alignment); 57 | void *chunk = sys_alloc(size + prefix); 58 | if (chunk == MAP_FAILED) { 59 | errno = ENOMEM; 60 | return NULL; 61 | } 62 | void *p = chunk + prefix; 63 | CHUNK_START(p) = chunk; 64 | CHUNK_SIZE(p) = size; 65 | return p; 66 | } 67 | 68 | size_t prefix = calculate_prefix((size_t) block.curr, alignment); 69 | if (block.curr == NULL || block.curr + prefix + size > block.end) { 70 | void *b = sys_alloc(BLOCK_SIZE); 71 | if (b == MAP_FAILED) { 72 | errno = ENOMEM; 73 | return NULL; 74 | } 75 | block.curr = b; 76 | block.end = b + BLOCK_SIZE; 77 | prefix = calculate_prefix((size_t) b, alignment); 78 | } 79 | 80 | void *p = block.curr + prefix; 81 | CHUNK_START(p) = block.curr; 82 | CHUNK_SIZE(p) = size; 83 | block.curr += prefix + size; 84 | return p; 85 | } 86 | 87 | int posix_memalign(void **memptr, size_t alignment, size_t size) { 88 | void *ptr = memalign(alignment, size); 89 | if (ptr) { 90 | *memptr = ptr; 91 | return 0; 92 | } else { 93 | return ENOMEM; 94 | } 95 | } 96 | 97 | void *malloc(size_t size) { 98 | return memalign(MIN_ALIGNMENT, size); 99 | } 100 | 101 | void free(void *ptr) { 102 | if (ptr == NULL) return; 103 | size_t size = CHUNK_SIZE(ptr); 104 | if (size >= MMAP_THRESHOLD) { 105 | munmap(CHUNK_START(ptr), size); 106 | } 107 | } 108 | 109 | void *crt0_calloc(size_t nmemb, size_t size) { 110 | size_t sz; 111 | if (__builtin_mul_overflow(nmemb, size, &sz)) { 112 | errno = ENOMEM; 113 | return NULL; 114 | } 115 | return malloc(sz); 116 | } 117 | 118 | // For some reason calloc does not export properly 119 | __asm__(".global calloc \n calloc = crt0_calloc"); 120 | 121 | void *realloc(void *ptr, size_t size) { 122 | if (ptr) { 123 | size_t old_sz = CHUNK_SIZE(ptr); 124 | if (old_sz >= size) 125 | return ptr; 126 | void *p = malloc(size); 127 | memcpy(p, ptr, old_sz); 128 | free(ptr); 129 | return p; 130 | } else { 131 | return malloc(size); 132 | } 133 | } 134 | 135 | void *reallocarray(void *ptr, size_t nmemb, size_t size) { 136 | size_t sz; 137 | if (__builtin_mul_overflow(nmemb, size, &sz)) { 138 | errno = ENOMEM; 139 | return NULL; 140 | } 141 | return realloc(ptr, sz); 142 | } 143 | -------------------------------------------------------------------------------- /mem.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void *memset(void *dst, int ch, size_t n) { 5 | uint8_t *d = dst; 6 | uint8_t c = ch; 7 | while (n--) 8 | (*d++) = c; 9 | return dst; 10 | } 11 | 12 | void *memmove(void *dst, const void *src, size_t n) { 13 | if (dst < src) { 14 | return memcpy(dst, src, n); 15 | } 16 | // Copy backwards 17 | uint8_t *d = dst + n; 18 | const uint8_t *s = src + n; 19 | while (n--) 20 | *--d = *--s; 21 | return dst; 22 | } 23 | 24 | void *memcpy(void * restrict dst, const void * restrict src, size_t n) { 25 | uint8_t *d = dst; 26 | const uint8_t *s = src; 27 | while (n--) 28 | *d++ = *s++; 29 | return dst; 30 | } 31 | 32 | int memcmp(const void *lhs, const void *rhs, size_t n) { 33 | const uint8_t *l = lhs; 34 | const uint8_t *r = rhs; 35 | while (n--) { 36 | if (*l != *r) { 37 | return *l - *r; 38 | } else { 39 | l++; 40 | r++; 41 | } 42 | } 43 | return 0; 44 | } 45 | 46 | void *memchr(const void *ptr, int ch, size_t n) { 47 | const uint8_t *p = ptr; 48 | uint8_t c = ch; 49 | while (n--) { 50 | if (*p != c) 51 | ++p; 52 | else 53 | return (void *) p; 54 | } 55 | return NULL; 56 | } 57 | 58 | char *strchr(const char *s, int ch) { 59 | char c = ch; 60 | while (*s != c) 61 | if (!*s++) 62 | return NULL; 63 | return (char *) s; 64 | } 65 | 66 | char *strrchr(const char *s, int ch) { 67 | char c = ch; 68 | const char *ret = NULL; 69 | do { 70 | if(*s == c) 71 | ret = s; 72 | } while(*s++); 73 | return (char *) ret; 74 | } 75 | 76 | int strcmp(const char *lhs, const char *rhs) { 77 | while (*lhs && (*lhs == *rhs)) { 78 | ++lhs; 79 | ++rhs; 80 | } 81 | return *(uint8_t *)lhs - *(uint8_t *)rhs; 82 | } 83 | 84 | size_t strlen(const char *str) { 85 | size_t l = 0; 86 | while (str[l]) 87 | ++l; 88 | return l; 89 | } 90 | 91 | size_t strnlen(const char *s, size_t maxlen) { 92 | size_t l = 0; 93 | while (l < maxlen && s[l]) 94 | ++l; 95 | return l; 96 | } 97 | 98 | char *strcpy(char *restrict dest, const char *restrict src) { 99 | char *ret = dest; 100 | while ((*dest++ = *src++)) {} 101 | return ret; 102 | } 103 | 104 | char *strdup(const char *str) { 105 | size_t siz; 106 | char *copy; 107 | siz = strlen(str) + 1; 108 | if ((copy = malloc(siz)) == NULL) 109 | return NULL; 110 | memcpy(copy, str, siz); 111 | return copy; 112 | } 113 | -------------------------------------------------------------------------------- /misc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // errno 10 | 11 | static int g_errno = 0; 12 | 13 | int *__errno(void) { 14 | return &g_errno; 15 | } 16 | 17 | long __set_errno_internal(int n) { 18 | g_errno = n; 19 | return -1; 20 | } 21 | 22 | // Source: bionic/libc/bionic/libgen.cpp 23 | static int __basename_r(const char *path, char* buffer, size_t buffer_size) { 24 | const char *startp = NULL; 25 | const char *endp = NULL; 26 | int len; 27 | int result; 28 | 29 | // Empty or NULL string gets treated as ".". 30 | if (path == NULL || *path == '\0') { 31 | startp = "."; 32 | len = 1; 33 | goto Exit; 34 | } 35 | 36 | // Strip trailing slashes. 37 | endp = path + strlen(path) - 1; 38 | while (endp > path && *endp == '/') { 39 | endp--; 40 | } 41 | 42 | // All slashes becomes "/". 43 | if (endp == path && *endp == '/') { 44 | startp = "/"; 45 | len = 1; 46 | goto Exit; 47 | } 48 | 49 | // Find the start of the base. 50 | startp = endp; 51 | while (startp > path && *(startp - 1) != '/') { 52 | startp--; 53 | } 54 | 55 | len = endp - startp +1; 56 | 57 | Exit: 58 | result = len; 59 | if (buffer == NULL) { 60 | return result; 61 | } 62 | if (len > (int) buffer_size - 1) { 63 | len = buffer_size - 1; 64 | result = -1; 65 | errno = ERANGE; 66 | } 67 | 68 | if (len >= 0) { 69 | memcpy(buffer, startp, len); 70 | buffer[len] = 0; 71 | } 72 | return result; 73 | } 74 | 75 | char *basename(const char *path) { 76 | static char buf[4069]; 77 | int rc = __basename_r(path, buf, sizeof(buf)); 78 | return (rc < 0) ? NULL : buf; 79 | } 80 | 81 | // Simply just abort when abort_message is called 82 | void __wrap_abort_message(const char* format, ...) { 83 | abort(); 84 | } 85 | 86 | typedef struct at_exit_func { 87 | void *arg; 88 | void (*func)(void*); 89 | } at_exit_func; 90 | 91 | static int at_exit_cap = 0; 92 | static int at_exit_sz = 0; 93 | static at_exit_func *at_exit_list = NULL; 94 | 95 | int __cxa_atexit(void (*func)(void *), void *arg, void *dso_handle) { 96 | if (at_exit_sz == at_exit_cap) { 97 | at_exit_cap = at_exit_cap ? at_exit_sz * 2 : 16; 98 | at_exit_list = realloc(at_exit_list, at_exit_cap * sizeof(at_exit_func)); 99 | } 100 | at_exit_list[at_exit_sz].func = func; 101 | at_exit_list[at_exit_sz].arg = arg; 102 | ++at_exit_sz; 103 | return 0; 104 | } 105 | 106 | typedef void fini_func_t(void); 107 | 108 | extern fini_func_t *__fini_array_start[]; 109 | extern fini_func_t *__fini_array_end[]; 110 | 111 | void exit(int status) { 112 | // Call registered at_exit functions in reverse 113 | for (int i = at_exit_sz - 1; i >= 0; --i) { 114 | at_exit_list[i].func(at_exit_list[i].arg); 115 | } 116 | 117 | fini_func_t** array = __fini_array_start; 118 | size_t count = __fini_array_end - __fini_array_start; 119 | // Call fini functions in reverse order 120 | while (count-- > 0) { 121 | fini_func_t* function = array[count]; 122 | (*function)(); 123 | } 124 | 125 | _exit(status); 126 | } 127 | 128 | // Emulate pthread functions 129 | 130 | typedef struct key_data { 131 | void *data; 132 | void (*dtor)(void*); 133 | int used; 134 | } key_data; 135 | 136 | static pthread_key_t key_list_sz = 0; 137 | static key_data *key_list; 138 | 139 | int pthread_key_create(pthread_key_t *key_ptr, void (*dtor)(void*)) { 140 | if (key_list_sz == 0) { 141 | key_list_sz = 16; 142 | key_list = calloc(key_list_sz, sizeof(key_data)); 143 | } 144 | 145 | pthread_key_t k = 0; 146 | 147 | // Find an empty slot 148 | for (; k < key_list_sz; ++k) { 149 | if (!key_list[k].used) { 150 | goto set_key; 151 | } 152 | } 153 | // Expand list 154 | key_list_sz *= 2; 155 | key_list = realloc(key_list, key_list_sz * sizeof(key_data)); 156 | memset(&key_list[k], 0, k * sizeof(key_data)); 157 | 158 | set_key: 159 | *key_ptr = k; 160 | key_list[k].used = 1; 161 | key_list[k].dtor = dtor; 162 | return 0; 163 | } 164 | 165 | int pthread_key_delete(pthread_key_t key) { 166 | if (key < key_list_sz) { 167 | if (key_list[key].dtor && key_list[key].data) { 168 | key_list[key].dtor(key_list[key].data); 169 | } 170 | key_list[key].data = NULL; 171 | key_list[key].dtor = NULL; 172 | key_list[key].used = 0; 173 | } 174 | return 0; 175 | } 176 | 177 | void *pthread_getspecific(pthread_key_t key) { 178 | if (key >= key_list_sz || !key_list[key].used) { 179 | return NULL; 180 | } 181 | return key_list[key].data; 182 | } 183 | 184 | int pthread_setspecific(pthread_key_t key, const void *value) { 185 | if (key >= key_list_sz || !key_list[key].used) { 186 | errno = EINVAL; 187 | return 1; 188 | } 189 | key_list[key].data = (void *) value; 190 | return 0; 191 | } 192 | 193 | int getpagesize() { 194 | static int sz = 0; 195 | if (sz == 0) { 196 | sz = getauxval(AT_PAGESZ); 197 | } 198 | return sz; 199 | } 200 | 201 | // Stack protector support 202 | 203 | uintptr_t __stack_chk_guard = 0; 204 | 205 | void __stack_chk_fail() { 206 | abort(); 207 | } 208 | -------------------------------------------------------------------------------- /musl/floatscan.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "shgetc.h" 10 | 11 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 12 | 13 | #define LD_B1B_DIG 2 14 | #define LD_B1B_MAX 9007199, 254740991 15 | #define KMAX 128 16 | 17 | #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 18 | 19 | #define LD_B1B_DIG 3 20 | #define LD_B1B_MAX 18, 446744073, 709551615 21 | #define KMAX 2048 22 | 23 | #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 24 | 25 | #define LD_B1B_DIG 4 26 | #define LD_B1B_MAX 10384593, 717069655, 257060992, 658440191 27 | #define KMAX 2048 28 | 29 | #else 30 | #error Unsupported long double representation 31 | #endif 32 | 33 | #define MASK (KMAX-1) 34 | 35 | static long long scanexp(FILE *f, int pok) 36 | { 37 | int c; 38 | int x; 39 | long long y; 40 | int neg = 0; 41 | 42 | c = shgetc(f); 43 | if (c=='+' || c=='-') { 44 | neg = (c=='-'); 45 | c = shgetc(f); 46 | if (c-'0'>=10U && pok) shunget(f); 47 | } 48 | if (c-'0'>=10U) { 49 | shunget(f); 50 | return LLONG_MIN; 51 | } 52 | for (x=0; c-'0'<10U && x=0) { 130 | shunget(f); 131 | } 132 | if (!gotdig) { 133 | errno = EINVAL; 134 | shlim(f, 0); 135 | return 0; 136 | } 137 | 138 | /* Handle zero specially to avoid nasty special cases later */ 139 | if (!x[0]) return sign * 0.0; 140 | 141 | /* Optimize small integers (w/no exponent) and over/under-flow */ 142 | if (lrp==dc && dc<10 && (bits>30 || x[0]>>bits==0)) 143 | return sign * (long double)x[0]; 144 | if (lrp > -emin/2) { 145 | errno = ERANGE; 146 | return sign * LDBL_MAX * LDBL_MAX; 147 | } 148 | if (lrp < emin-2*LDBL_MANT_DIG) { 149 | errno = ERANGE; 150 | return sign * LDBL_MIN * LDBL_MIN; 151 | } 152 | 153 | /* Align incomplete final B1B digit */ 154 | if (j) { 155 | for (; j<9; j++) x[k]*=10; 156 | k++; 157 | j=0; 158 | } 159 | 160 | a = 0; 161 | z = k; 162 | e2 = 0; 163 | rp = lrp; 164 | 165 | /* Optimize small to mid-size integers (even in exp. notation) */ 166 | if (lnz<9 && lnz<=rp && rp < 18) { 167 | if (rp == 9) return sign * (long double)x[0]; 168 | if (rp < 9) return sign * (long double)x[0] / p10s[8-rp]; 169 | int bitlim = bits-3*(int)(rp-9); 170 | if (bitlim>30 || x[0]>>bitlim==0) 171 | return sign * (long double)x[0] * p10s[rp-10]; 172 | } 173 | 174 | /* Drop trailing zeros */ 175 | for (; !x[z-1]; z--); 176 | 177 | /* Align radix point to B1B digit boundary */ 178 | if (rp % 9) { 179 | int rpm9 = rp>=0 ? rp%9 : rp%9+9; 180 | int p10 = p10s[8-rpm9]; 181 | uint32_t carry = 0; 182 | for (k=a; k!=z; k++) { 183 | uint32_t tmp = x[k] % p10; 184 | x[k] = x[k]/p10 + carry; 185 | carry = 1000000000/p10 * tmp; 186 | if (k==a && !x[k]) { 187 | a = (a+1 & MASK); 188 | rp -= 9; 189 | } 190 | } 191 | if (carry) x[z++] = carry; 192 | rp += 9-rpm9; 193 | } 194 | 195 | /* Upscale until desired number of bits are left of radix point */ 196 | while (rp < 9*LD_B1B_DIG || (rp == 9*LD_B1B_DIG && x[a] 1000000000) { 202 | carry = tmp / 1000000000; 203 | x[k] = tmp % 1000000000; 204 | } else { 205 | carry = 0; 206 | x[k] = tmp; 207 | } 208 | if (k==(z-1 & MASK) && k!=a && !x[k]) z = k; 209 | if (k==a) break; 210 | } 211 | if (carry) { 212 | rp += 9; 213 | a = (a-1 & MASK); 214 | if (a == z) { 215 | z = (z-1 & MASK); 216 | x[z-1 & MASK] |= x[z]; 217 | } 218 | x[a] = carry; 219 | } 220 | } 221 | 222 | /* Downscale until exactly number of bits are left of radix point */ 223 | for (;;) { 224 | uint32_t carry = 0; 225 | int sh = 1; 226 | for (i=0; i th[i]) break; 233 | } 234 | if (i==LD_B1B_DIG && rp==9*LD_B1B_DIG) break; 235 | /* FIXME: find a way to compute optimal sh */ 236 | if (rp > 9+9*LD_B1B_DIG) sh = 9; 237 | e2 += sh; 238 | for (k=a; k!=z; k=(k+1 & MASK)) { 239 | uint32_t tmp = x[k] & (1<>sh) + carry; 241 | carry = (1000000000>>sh) * tmp; 242 | if (k==a && !x[k]) { 243 | a = (a+1 & MASK); 244 | i--; 245 | rp -= 9; 246 | } 247 | } 248 | if (carry) { 249 | if ((z+1 & MASK) != a) { 250 | x[z] = carry; 251 | z = (z+1 & MASK); 252 | } else x[z-1 & MASK] |= 1; 253 | } 254 | } 255 | 256 | /* Assemble desired bits into floating point variable */ 257 | for (y=i=0; i LDBL_MANT_DIG+e2-emin) { 266 | bits = LDBL_MANT_DIG+e2-emin; 267 | if (bits<0) bits=0; 268 | denormal = 1; 269 | } 270 | 271 | /* Calculate bias term to force rounding, move out lower bits */ 272 | if (bits < LDBL_MANT_DIG) { 273 | bias = copysignl(scalbn(1, 2*LDBL_MANT_DIG-bits-1), y); 274 | frac = fmodl(y, scalbn(1, LDBL_MANT_DIG-bits)); 275 | y -= frac; 276 | y += bias; 277 | } 278 | 279 | /* Process tail of decimal input so it can affect rounding */ 280 | if ((a+i & MASK) != z) { 281 | uint32_t t = x[a+i & MASK]; 282 | if (t < 500000000 && (t || (a+i+1 & MASK) != z)) 283 | frac += 0.25*sign; 284 | else if (t > 500000000) 285 | frac += 0.75*sign; 286 | else if (t == 500000000) { 287 | if ((a+i+1 & MASK) == z) 288 | frac += 0.5*sign; 289 | else 290 | frac += 0.75*sign; 291 | } 292 | if (LDBL_MANT_DIG-bits >= 2 && !fmodl(frac, 1)) 293 | frac++; 294 | } 295 | 296 | y += frac; 297 | y -= bias; 298 | 299 | if ((e2+LDBL_MANT_DIG & INT_MAX) > emax-5) { 300 | if (fabsl(y) >= 2/LDBL_EPSILON) { 301 | if (denormal && bits==LDBL_MANT_DIG+e2-emin) 302 | denormal = 0; 303 | y *= 0.5; 304 | e2++; 305 | } 306 | if (e2+LDBL_MANT_DIG>emax || (denormal && frac)) 307 | errno = ERANGE; 308 | } 309 | 310 | return scalbnl(y, e2); 311 | } 312 | 313 | static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok) 314 | { 315 | uint32_t x = 0; 316 | long double y = 0; 317 | long double scale = 1; 318 | long double bias = 0; 319 | int gottail = 0, gotrad = 0, gotdig = 0; 320 | long long rp = 0; 321 | long long dc = 0; 322 | long long e2 = 0; 323 | int d; 324 | int c; 325 | 326 | c = shgetc(f); 327 | 328 | /* Skip leading zeros */ 329 | for (; c=='0'; c = shgetc(f)) gotdig = 1; 330 | 331 | if (c=='.') { 332 | gotrad = 1; 333 | c = shgetc(f); 334 | /* Count zeros after the radix point before significand */ 335 | for (rp=0; c=='0'; c = shgetc(f), rp--) gotdig = 1; 336 | } 337 | 338 | for (; c-'0'<10U || (c|32)-'a'<6U || c=='.'; c = shgetc(f)) { 339 | if (c=='.') { 340 | if (gotrad) break; 341 | rp = dc; 342 | gotrad = 1; 343 | } else { 344 | gotdig = 1; 345 | if (c > '9') d = (c|32)+10-'a'; 346 | else d = c-'0'; 347 | if (dc<8) { 348 | x = x*16 + d; 349 | } else if (dc < LDBL_MANT_DIG/4+1) { 350 | y += d*(scale/=16); 351 | } else if (d && !gottail) { 352 | y += 0.5*scale; 353 | gottail = 1; 354 | } 355 | dc++; 356 | } 357 | } 358 | if (!gotdig) { 359 | shunget(f); 360 | if (pok) { 361 | shunget(f); 362 | if (gotrad) shunget(f); 363 | } else { 364 | shlim(f, 0); 365 | } 366 | return sign * 0.0; 367 | } 368 | if (!gotrad) rp = dc; 369 | while (dc<8) x *= 16, dc++; 370 | if ((c|32)=='p') { 371 | e2 = scanexp(f, pok); 372 | if (e2 == LLONG_MIN) { 373 | if (pok) { 374 | shunget(f); 375 | } else { 376 | shlim(f, 0); 377 | return 0; 378 | } 379 | e2 = 0; 380 | } 381 | } else { 382 | shunget(f); 383 | } 384 | e2 += 4*rp - 32; 385 | 386 | if (!x) return sign * 0.0; 387 | if (e2 > -emin) { 388 | errno = ERANGE; 389 | return sign * LDBL_MAX * LDBL_MAX; 390 | } 391 | if (e2 < emin-2*LDBL_MANT_DIG) { 392 | errno = ERANGE; 393 | return sign * LDBL_MIN * LDBL_MIN; 394 | } 395 | 396 | while (x < 0x80000000) { 397 | if (y>=0.5) { 398 | x += x + 1; 399 | y += y - 1; 400 | } else { 401 | x += x; 402 | y += y; 403 | } 404 | e2--; 405 | } 406 | 407 | if (bits > 32+e2-emin) { 408 | bits = 32+e2-emin; 409 | if (bits<0) bits=0; 410 | } 411 | 412 | if (bits < LDBL_MANT_DIG) 413 | bias = copysignl(scalbn(1, 32+LDBL_MANT_DIG-bits-1), sign); 414 | 415 | if (bits<32 && y && !(x&1)) x++, y=0; 416 | 417 | y = bias + sign*(long double)x + sign*y; 418 | y -= bias; 419 | 420 | if (!y) errno = ERANGE; 421 | 422 | return scalbnl(y, e2); 423 | } 424 | 425 | long double __floatscan(FILE *f, int prec, int pok) 426 | { 427 | int sign = 1; 428 | size_t i; 429 | int bits; 430 | int emin; 431 | int c; 432 | 433 | switch (prec) { 434 | case 0: 435 | bits = FLT_MANT_DIG; 436 | emin = FLT_MIN_EXP-bits; 437 | break; 438 | case 1: 439 | bits = DBL_MANT_DIG; 440 | emin = DBL_MIN_EXP-bits; 441 | break; 442 | case 2: 443 | bits = LDBL_MANT_DIG; 444 | emin = LDBL_MIN_EXP-bits; 445 | break; 446 | default: 447 | return 0; 448 | } 449 | 450 | while (isspace((c=shgetc(f)))); 451 | 452 | if (c=='+' || c=='-') { 453 | sign -= 2*(c=='-'); 454 | c = shgetc(f); 455 | } 456 | 457 | for (i=0; i<8 && (c|32)=="infinity"[i]; i++) 458 | if (i<7) c = shgetc(f); 459 | if (i==3 || i==8 || (i>3 && pok)) { 460 | if (i!=8) { 461 | shunget(f); 462 | if (pok) for (; i>3; i--) shunget(f); 463 | } 464 | return sign * INFINITY; 465 | } 466 | if (!i) for (i=0; i<3 && (c|32)=="nan"[i]; i++) 467 | if (i<2) c = shgetc(f); 468 | if (i==3) { 469 | if (shgetc(f) != '(') { 470 | shunget(f); 471 | return NAN; 472 | } 473 | for (i=1; ; i++) { 474 | c = shgetc(f); 475 | if (c-'0'<10U || c-'A'<26U || c-'a'<26U || c=='_') 476 | continue; 477 | if (c==')') return NAN; 478 | shunget(f); 479 | if (!pok) { 480 | errno = EINVAL; 481 | shlim(f, 0); 482 | return 0; 483 | } 484 | while (i--) shunget(f); 485 | return NAN; 486 | } 487 | return NAN; 488 | } 489 | 490 | if (i) { 491 | shunget(f); 492 | errno = EINVAL; 493 | shlim(f, 0); 494 | return 0; 495 | } 496 | 497 | if (c=='0') { 498 | c = shgetc(f); 499 | if ((c|32) == 'x') 500 | return hexfloat(f, bits, emin, sign, pok); 501 | shunget(f); 502 | c = '0'; 503 | } 504 | 505 | return decfloat(f, c, bits, emin, sign, pok); 506 | } 507 | -------------------------------------------------------------------------------- /musl/intscan.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "shgetc.h" 7 | 8 | /* Lookup table for digit values. -1==255>=36 -> invalid */ 9 | static const unsigned char table[] = { -1, 10 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 11 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 12 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 13 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, 14 | -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 15 | 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, 16 | -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 17 | 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, 18 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 20 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 21 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 22 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 23 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 24 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 25 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 26 | }; 27 | 28 | unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long lim) 29 | { 30 | const unsigned char *val = table+1; 31 | int c, neg=0; 32 | unsigned x; 33 | unsigned long long y; 34 | if (base > 36 || base == 1) { 35 | errno = EINVAL; 36 | return 0; 37 | } 38 | while (isspace((c=shgetc(f)))); 39 | if (c=='+' || c=='-') { 40 | neg = -(c=='-'); 41 | c = shgetc(f); 42 | } 43 | if ((base == 0 || base == 16) && c=='0') { 44 | c = shgetc(f); 45 | if ((c|32)=='x') { 46 | c = shgetc(f); 47 | if (val[c]>=16) { 48 | shunget(f); 49 | if (pok) shunget(f); 50 | else shlim(f, 0); 51 | return 0; 52 | } 53 | base = 16; 54 | } else if (base == 0) { 55 | base = 8; 56 | } 57 | } else { 58 | if (base == 0) base = 10; 59 | if (val[c] >= base) { 60 | shunget(f); 61 | shlim(f, 0); 62 | errno = EINVAL; 63 | return 0; 64 | } 65 | } 66 | if (base == 10) { 67 | for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f)) 68 | x = x*10 + (c-'0'); 69 | for (y=x; c-'0'<10U && y<=ULLONG_MAX/10 && 10*y<=ULLONG_MAX-(c-'0'); c=shgetc(f)) 70 | y = y*10 + (c-'0'); 71 | if (c-'0'>=10U) goto done; 72 | } else if (!(base & base-1)) { 73 | int bs = "\0\1\2\4\7\3\6\5"[(0x17*base)>>5&7]; 74 | for (x=0; val[c]>bs; c=shgetc(f)) 77 | y = y<=lim) { 93 | if (!(lim&1) && !neg) { 94 | errno = ERANGE; 95 | return lim-1; 96 | } else if (y>lim) { 97 | errno = ERANGE; 98 | return lim; 99 | } 100 | } 101 | return (y^neg)-neg; 102 | } 103 | -------------------------------------------------------------------------------- /musl/memmem.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | 5 | static char *twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) 6 | { 7 | uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1]; 8 | for (h+=2, k-=2; k; k--, hw = hw<<8 | *h++) 9 | if (hw == nw) return (char *)h-2; 10 | return hw == nw ? (char *)h-2 : 0; 11 | } 12 | 13 | static char *threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) 14 | { 15 | uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8; 16 | uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8; 17 | for (h+=3, k-=3; k; k--, hw = (hw|*h++)<<8) 18 | if (hw == nw) return (char *)h-3; 19 | return hw == nw ? (char *)h-3 : 0; 20 | } 21 | 22 | static char *fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) 23 | { 24 | uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3]; 25 | uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3]; 26 | for (h+=4, k-=4; k; k--, hw = hw<<8 | *h++) 27 | if (hw == nw) return (char *)h-4; 28 | return hw == nw ? (char *)h-4 : 0; 29 | } 30 | 31 | #define MAX(a,b) ((a)>(b)?(a):(b)) 32 | #define MIN(a,b) ((a)<(b)?(a):(b)) 33 | 34 | #define BITOP(a,b,op) \ 35 | ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) 36 | 37 | static char *twoway_memmem(const unsigned char *h, const unsigned char *z, const unsigned char *n, size_t l) 38 | { 39 | size_t i, ip, jp, k, p, ms, p0, mem, mem0; 40 | size_t byteset[32 / sizeof(size_t)] = { 0 }; 41 | size_t shift[256]; 42 | 43 | /* Computing length of needle and fill shift table */ 44 | for (i=0; i n[jp+k]) { 56 | jp += k; 57 | k = 1; 58 | p = jp - ip; 59 | } else { 60 | ip = jp++; 61 | k = p = 1; 62 | } 63 | } 64 | ms = ip; 65 | p0 = p; 66 | 67 | /* And with the opposite comparison */ 68 | ip = -1; jp = 0; k = p = 1; 69 | while (jp+k ms+1) ms = ip; 85 | else p = p0; 86 | 87 | /* Periodic needle? */ 88 | if (memcmp(n, n+p, ms+1)) { 89 | mem0 = 0; 90 | p = MAX(ms, l-ms-1) + 1; 91 | } else mem0 = l-p; 92 | mem = 0; 93 | 94 | /* Search loop */ 95 | for (;;) { 96 | /* If remainder of haystack is shorter than needle, done */ 97 | if (z-h < l) return 0; 98 | 99 | /* Check last byte first; advance by shift on mismatch */ 100 | if (BITOP(byteset, h[l-1], &)) { 101 | k = l-shift[h[l-1]]; 102 | if (k) { 103 | if (k < mem) k = mem; 104 | h += k; 105 | mem = 0; 106 | continue; 107 | } 108 | } else { 109 | h += l; 110 | mem = 0; 111 | continue; 112 | } 113 | 114 | /* Compare right half */ 115 | for (k=MAX(ms+1,mem); kmem && n[k-1] == h[k-1]; k--); 123 | if (k <= mem) return (char *)h; 124 | h += p; 125 | mem = mem0; 126 | } 127 | } 128 | 129 | void *memmem(const void *h0, size_t k, const void *n0, size_t l) 130 | { 131 | const unsigned char *h = h0, *n = n0; 132 | 133 | /* Return immediately on empty needle */ 134 | if (!l) return (void *)h; 135 | 136 | /* Return immediately when needle is longer than haystack */ 137 | if (k 29 | #include 30 | #include 31 | 32 | #ifndef a_ctz_32 33 | #define a_ctz_32 a_ctz_32 34 | static inline int a_ctz_32(uint32_t x) 35 | { 36 | #ifdef a_clz_32 37 | return 31-a_clz_32(x&-x); 38 | #else 39 | static const char debruijn32[32] = { 40 | 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, 41 | 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14 42 | }; 43 | return debruijn32[(x&-x)*0x076be629 >> 27]; 44 | #endif 45 | } 46 | #endif 47 | 48 | #ifndef a_ctz_64 49 | #define a_ctz_64 a_ctz_64 50 | static inline int a_ctz_64(uint64_t x) 51 | { 52 | static const char debruijn64[64] = { 53 | 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, 54 | 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, 55 | 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10, 56 | 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12 57 | }; 58 | if (sizeof(long) < 8) { 59 | uint32_t y = x; 60 | if (!y) { 61 | y = x>>32; 62 | return 32 + a_ctz_32(y); 63 | } 64 | return a_ctz_32(y); 65 | } 66 | return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58]; 67 | } 68 | #endif 69 | 70 | static inline int a_ctz_l(unsigned long x) 71 | { 72 | return (sizeof(long) < 8) ? a_ctz_32(x) : a_ctz_64(x); 73 | } 74 | 75 | #define ntz(x) a_ctz_l((x)) 76 | 77 | typedef int (*cmpfun)(const void *, const void *, void *); 78 | 79 | static inline int pntz(size_t p[2]) { 80 | int r = ntz(p[0] - 1); 81 | if(r != 0 || (r = 8*sizeof(size_t) + ntz(p[1])) != 8*sizeof(size_t)) { 82 | return r; 83 | } 84 | return 0; 85 | } 86 | 87 | static void cycle(size_t width, unsigned char* ar[], int n) 88 | { 89 | unsigned char tmp[256]; 90 | size_t l; 91 | int i; 92 | 93 | if(n < 2) { 94 | return; 95 | } 96 | 97 | ar[n] = tmp; 98 | while(width) { 99 | l = sizeof(tmp) < width ? sizeof(tmp) : width; 100 | memcpy(ar[n], ar[0], l); 101 | for(i = 0; i < n; i++) { 102 | memcpy(ar[i], ar[i + 1], l); 103 | ar[i] += l; 104 | } 105 | width -= l; 106 | } 107 | } 108 | 109 | /* shl() and shr() need n > 0 */ 110 | static inline void shl(size_t p[2], int n) 111 | { 112 | if(n >= 8 * sizeof(size_t)) { 113 | n -= 8 * sizeof(size_t); 114 | p[1] = p[0]; 115 | p[0] = 0; 116 | } 117 | p[1] <<= n; 118 | p[1] |= p[0] >> (sizeof(size_t) * 8 - n); 119 | p[0] <<= n; 120 | } 121 | 122 | static inline void shr(size_t p[2], int n) 123 | { 124 | if(n >= 8 * sizeof(size_t)) { 125 | n -= 8 * sizeof(size_t); 126 | p[0] = p[1]; 127 | p[1] = 0; 128 | } 129 | p[0] >>= n; 130 | p[0] |= p[1] << (sizeof(size_t) * 8 - n); 131 | p[1] >>= n; 132 | } 133 | 134 | static void sift(unsigned char *head, size_t width, cmpfun cmp, void *arg, int pshift, size_t lp[]) 135 | { 136 | unsigned char *rt, *lf; 137 | unsigned char *ar[14 * sizeof(size_t) + 1]; 138 | int i = 1; 139 | 140 | ar[0] = head; 141 | while(pshift > 1) { 142 | rt = head - width; 143 | lf = head - width - lp[pshift - 2]; 144 | 145 | if(cmp(ar[0], lf, arg) >= 0 && cmp(ar[0], rt, arg) >= 0) { 146 | break; 147 | } 148 | if(cmp(lf, rt, arg) >= 0) { 149 | ar[i++] = lf; 150 | head = lf; 151 | pshift -= 1; 152 | } else { 153 | ar[i++] = rt; 154 | head = rt; 155 | pshift -= 2; 156 | } 157 | } 158 | cycle(width, ar, i); 159 | } 160 | 161 | static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, size_t pp[2], int pshift, int trusty, size_t lp[]) 162 | { 163 | unsigned char *stepson, 164 | *rt, *lf; 165 | size_t p[2]; 166 | unsigned char *ar[14 * sizeof(size_t) + 1]; 167 | int i = 1; 168 | int trail; 169 | 170 | p[0] = pp[0]; 171 | p[1] = pp[1]; 172 | 173 | ar[0] = head; 174 | while(p[0] != 1 || p[1] != 0) { 175 | stepson = head - lp[pshift]; 176 | if(cmp(stepson, ar[0], arg) <= 0) { 177 | break; 178 | } 179 | if(!trusty && pshift > 1) { 180 | rt = head - width; 181 | lf = head - width - lp[pshift - 2]; 182 | if(cmp(rt, stepson, arg) >= 0 || cmp(lf, stepson, arg) >= 0) { 183 | break; 184 | } 185 | } 186 | 187 | ar[i++] = stepson; 188 | head = stepson; 189 | trail = pntz(p); 190 | shr(p, trail); 191 | pshift += trail; 192 | trusty = 0; 193 | } 194 | if(!trusty) { 195 | cycle(width, ar, i); 196 | sift(head, width, cmp, arg, pshift, lp); 197 | } 198 | } 199 | 200 | void qsort_r(void *base, size_t nel, size_t width, cmpfun cmp, void *arg) 201 | { 202 | size_t lp[12*sizeof(size_t)]; 203 | size_t i, size = width * nel; 204 | unsigned char *head, *high; 205 | size_t p[2] = {1, 0}; 206 | int pshift = 1; 207 | int trail; 208 | 209 | if (!size) return; 210 | 211 | head = base; 212 | high = head + size - width; 213 | 214 | /* Precompute Leonardo numbers, scaled by element width */ 215 | for(lp[0]=lp[1]=width, i=2; (lp[i]=lp[i-2]+lp[i-1]+width) < size; i++); 216 | 217 | while(head < high) { 218 | if((p[0] & 3) == 3) { 219 | sift(head, width, cmp, arg, pshift, lp); 220 | shr(p, 2); 221 | pshift += 2; 222 | } else { 223 | if(lp[pshift - 1] >= high - head) { 224 | trinkle(head, width, cmp, arg, p, pshift, 0, lp); 225 | } else { 226 | sift(head, width, cmp, arg, pshift, lp); 227 | } 228 | 229 | if(pshift == 1) { 230 | shl(p, 1); 231 | pshift = 0; 232 | } else { 233 | shl(p, pshift - 1); 234 | pshift = 1; 235 | } 236 | } 237 | 238 | p[0] |= 1; 239 | head += width; 240 | } 241 | 242 | trinkle(head, width, cmp, arg, p, pshift, 0, lp); 243 | 244 | while(pshift != 1 || p[0] != 1 || p[1] != 0) { 245 | if(pshift <= 1) { 246 | trail = pntz(p); 247 | shr(p, trail); 248 | pshift += trail; 249 | } else { 250 | shl(p, 2); 251 | pshift -= 2; 252 | p[0] ^= 7; 253 | shr(p, 1); 254 | trinkle(head - lp[pshift] - width, width, cmp, arg, p, pshift + 1, 1, lp); 255 | shl(p, 1); 256 | p[0] |= 1; 257 | trinkle(head - width, width, cmp, arg, p, pshift, 1, lp); 258 | } 259 | head -= width; 260 | } 261 | } 262 | 263 | typedef int (*q_cmpfun)(const void *, const void *); 264 | 265 | static int wrapper_cmp(const void *v1, const void *v2, void *cmp) 266 | { 267 | return ((q_cmpfun)cmp)(v1, v2); 268 | } 269 | 270 | void qsort(void *base, size_t nel, size_t width, q_cmpfun cmp) 271 | { 272 | qsort_r(base, nel, width, wrapper_cmp, (void *)cmp); 273 | } 274 | -------------------------------------------------------------------------------- /musl/shgetc.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Scan helper "stdio" functions for use by scanf-family and strto*-family 4 | * functions. These accept either a valid stdio FILE, or a minimal pseudo 5 | * FILE whose buffer pointers point into a null-terminated string. In the 6 | * latter case, the sh_fromstring macro should be used to setup the FILE; 7 | * the rest of the structure can be left uninitialized. 8 | * 9 | * To begin using these functions, shlim must first be called on the FILE 10 | * to set a field width limit, or 0 for no limit. For string pseudo-FILEs, 11 | * a nonzero limit is not valid and produces undefined behavior. After that, 12 | * shgetc, shunget, and shcnt are valid as long as no other stdio functions 13 | * are called on the stream. 14 | * 15 | * When used with a real FILE object, shunget has only one byte of pushback 16 | * available. Further shunget (up to a limit of the stdio UNGET buffer size) 17 | * will adjust the position but will not restore the data to be read again. 18 | * This functionality is needed for the wcsto*-family functions, where it's 19 | * okay because the FILE will be discarded immediately anyway. When used 20 | * with string pseudo-FILEs, shunget has unlimited pushback, back to the 21 | * beginning of the string. */ 22 | 23 | void shlim(FILE *, off_t); 24 | int shgetc(FILE *); 25 | size_t shcnt(FILE *); 26 | void shunget(FILE *); 27 | -------------------------------------------------------------------------------- /musl/strcasecmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int strcasecmp(const char *_l, const char *_r) 5 | { 6 | const unsigned char *l=(void *)_l, *r=(void *)_r; 7 | for (; *l && *r && (*l == *r || tolower(*l) == tolower(*r)); l++, r++); 8 | return tolower(*l) - tolower(*r); 9 | } 10 | -------------------------------------------------------------------------------- /musl/strspn.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define BITOP(a,b,op) \ 4 | ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) 5 | 6 | size_t strspn(const char *s, const char *c) 7 | { 8 | const char *a = s; 9 | size_t byteset[32/sizeof(size_t)] = { 0 }; 10 | 11 | if (!c[0]) return 0; 12 | if (!c[1]) { 13 | for (; *s == *c; s++); 14 | return s-a; 15 | } 16 | 17 | for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++); 18 | for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++); 19 | return s-a; 20 | } 21 | -------------------------------------------------------------------------------- /musl/strtok_r.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char *strtok_r(char *restrict s, const char *restrict sep, char **restrict p) 4 | { 5 | if (!s && !(s = *p)) return NULL; 6 | s += strspn(s, sep); 7 | if (!*s) return *p = 0; 8 | *p = s + strcspn(s, sep); 9 | if (**p) *(*p)++ = 0; 10 | else *p = 0; 11 | return s; 12 | } 13 | -------------------------------------------------------------------------------- /musl/vfprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* Some useful macros */ 14 | 15 | #define MAX(a,b) ((a)>(b) ? (a) : (b)) 16 | #define MIN(a,b) ((a)<(b) ? (a) : (b)) 17 | 18 | /* Convenient bit representation for modifier flags, which all fall 19 | * within 31 codepoints of the space character. */ 20 | 21 | #define ALT_FORM (1U<<'#'-' ') 22 | #define ZERO_PAD (1U<<'0'-' ') 23 | #define LEFT_ADJ (1U<<'-'-' ') 24 | #define PAD_POS (1U<<' '-' ') 25 | #define MARK_POS (1U<<'+'-' ') 26 | #define GROUPED (1U<<'\''-' ') 27 | 28 | #define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS|GROUPED) 29 | 30 | /* State machine to accept length modifiers + conversion specifiers. 31 | * Result is 0 on failure, or an argument type to pop on success. */ 32 | 33 | enum { 34 | BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE, 35 | ZTPRE, JPRE, 36 | STOP, 37 | PTR, INT, UINT, ULLONG, 38 | LONG, ULONG, 39 | SHORT, USHORT, CHAR, UCHAR, 40 | LLONG, SIZET, IMAX, UMAX, PDIFF, UIPTR, 41 | DBL, LDBL, 42 | NOARG, 43 | MAXSTATE 44 | }; 45 | 46 | #define S(x) [(x)-'A'] 47 | 48 | static const unsigned char states[]['z'-'A'+1] = { 49 | { /* 0: bare types */ 50 | S('d') = INT, S('i') = INT, 51 | S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT, 52 | S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL, 53 | S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL, 54 | S('c') = INT, S('C') = UINT, 55 | S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR, 56 | S('m') = NOARG, 57 | S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE, 58 | S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE, 59 | }, { /* 1: l-prefixed */ 60 | S('d') = LONG, S('i') = LONG, 61 | S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG, 62 | S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL, 63 | S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL, 64 | S('c') = UINT, S('s') = PTR, S('n') = PTR, 65 | S('l') = LLPRE, 66 | }, { /* 2: ll-prefixed */ 67 | S('d') = LLONG, S('i') = LLONG, 68 | S('o') = ULLONG, S('u') = ULLONG, 69 | S('x') = ULLONG, S('X') = ULLONG, 70 | S('n') = PTR, 71 | }, { /* 3: h-prefixed */ 72 | S('d') = SHORT, S('i') = SHORT, 73 | S('o') = USHORT, S('u') = USHORT, 74 | S('x') = USHORT, S('X') = USHORT, 75 | S('n') = PTR, 76 | S('h') = HHPRE, 77 | }, { /* 4: hh-prefixed */ 78 | S('d') = CHAR, S('i') = CHAR, 79 | S('o') = UCHAR, S('u') = UCHAR, 80 | S('x') = UCHAR, S('X') = UCHAR, 81 | S('n') = PTR, 82 | }, { /* 5: L-prefixed */ 83 | S('e') = LDBL, S('f') = LDBL, S('g') = LDBL, S('a') = LDBL, 84 | S('E') = LDBL, S('F') = LDBL, S('G') = LDBL, S('A') = LDBL, 85 | S('n') = PTR, 86 | }, { /* 6: z- or t-prefixed (assumed to be same size) */ 87 | S('d') = PDIFF, S('i') = PDIFF, 88 | S('o') = SIZET, S('u') = SIZET, 89 | S('x') = SIZET, S('X') = SIZET, 90 | S('n') = PTR, 91 | }, { /* 7: j-prefixed */ 92 | S('d') = IMAX, S('i') = IMAX, 93 | S('o') = UMAX, S('u') = UMAX, 94 | S('x') = UMAX, S('X') = UMAX, 95 | S('n') = PTR, 96 | } 97 | }; 98 | 99 | #define OOB(x) ((unsigned)(x)-'A' > 'z'-'A') 100 | 101 | union arg 102 | { 103 | uintmax_t i; 104 | long double f; 105 | void *p; 106 | }; 107 | 108 | static void pop_arg(union arg *arg, int type, va_list *ap) 109 | { 110 | switch (type) { 111 | case PTR: arg->p = va_arg(*ap, void *); 112 | break; case INT: arg->i = va_arg(*ap, int); 113 | break; case UINT: arg->i = va_arg(*ap, unsigned int); 114 | break; case LONG: arg->i = va_arg(*ap, long); 115 | break; case ULONG: arg->i = va_arg(*ap, unsigned long); 116 | break; case ULLONG: arg->i = va_arg(*ap, unsigned long long); 117 | break; case SHORT: arg->i = (short)va_arg(*ap, int); 118 | break; case USHORT: arg->i = (unsigned short)va_arg(*ap, int); 119 | break; case CHAR: arg->i = (signed char)va_arg(*ap, int); 120 | break; case UCHAR: arg->i = (unsigned char)va_arg(*ap, int); 121 | break; case LLONG: arg->i = va_arg(*ap, long long); 122 | break; case SIZET: arg->i = va_arg(*ap, size_t); 123 | break; case IMAX: arg->i = va_arg(*ap, intmax_t); 124 | break; case UMAX: arg->i = va_arg(*ap, uintmax_t); 125 | break; case PDIFF: arg->i = va_arg(*ap, ptrdiff_t); 126 | break; case UIPTR: arg->i = (uintptr_t)va_arg(*ap, void *); 127 | break; case DBL: arg->f = va_arg(*ap, double); 128 | break; case LDBL: arg->f = va_arg(*ap, long double); 129 | } 130 | } 131 | 132 | static void out(FILE *f, const char *s, size_t l) 133 | { 134 | if (!ferror(f)) fwrite((void *)s, 1, l, f); 135 | } 136 | 137 | static void pad(FILE *f, char c, int w, int l, int fl) 138 | { 139 | char pad[256]; 140 | if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return; 141 | l = w - l; 142 | memset(pad, c, l>sizeof pad ? sizeof pad : l); 143 | for (; l >= sizeof pad; l -= sizeof pad) 144 | out(f, pad, sizeof pad); 145 | out(f, pad, l); 146 | } 147 | 148 | static const char xdigits[16] = { 149 | "0123456789ABCDEF" 150 | }; 151 | 152 | static char *fmt_x(uintmax_t x, char *s, int lower) 153 | { 154 | for (; x; x>>=4) *--s = xdigits[(x&15)]|lower; 155 | return s; 156 | } 157 | 158 | static char *fmt_o(uintmax_t x, char *s) 159 | { 160 | for (; x; x>>=3) *--s = '0' + (x&7); 161 | return s; 162 | } 163 | 164 | static char *fmt_u(uintmax_t x, char *s) 165 | { 166 | unsigned long y; 167 | for ( ; x>ULONG_MAX; x/=10) *--s = '0' + x%10; 168 | for (y=x; y; y/=10) *--s = '0' + y%10; 169 | return s; 170 | } 171 | 172 | /* Do not override this check. The floating point printing code below 173 | * depends on the float.h constants being right. If they are wrong, it 174 | * may overflow the stack. */ 175 | #if LDBL_MANT_DIG == 53 176 | typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)]; 177 | #endif 178 | 179 | static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) 180 | { 181 | uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion 182 | + (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion 183 | uint32_t *a, *d, *r, *z; 184 | int e2=0, e, i, j, l; 185 | char buf[9+LDBL_MANT_DIG/4], *s; 186 | const char *prefix="-0X+0X 0X-0x+0x 0x"; 187 | int pl; 188 | char ebuf0[3*sizeof(int)], *ebuf=&ebuf0[3*sizeof(int)], *estr; 189 | 190 | pl=1; 191 | if (signbit(y)) { 192 | y=-y; 193 | } else if (fl & MARK_POS) { 194 | prefix+=3; 195 | } else if (fl & PAD_POS) { 196 | prefix+=6; 197 | } else prefix++, pl=0; 198 | 199 | if (!isfinite(y)) { 200 | char *s = (t&32)?"inf":"INF"; 201 | if (y!=y) s=(t&32)?"nan":"NAN"; 202 | pad(f, ' ', w, 3+pl, fl&~ZERO_PAD); 203 | out(f, prefix, pl); 204 | out(f, s, 3); 205 | pad(f, ' ', w, 3+pl, fl^LEFT_ADJ); 206 | return MAX(w, 3+pl); 207 | } 208 | 209 | y = frexpl(y, &e2) * 2; 210 | if (y) e2--; 211 | 212 | if ((t|32)=='a') { 213 | long double round = 8.0; 214 | int re; 215 | 216 | if (t&32) prefix += 9; 217 | pl += 2; 218 | 219 | if (p<0 || p>=LDBL_MANT_DIG/4-1) re=0; 220 | else re=LDBL_MANT_DIG/4-1-p; 221 | 222 | if (re) { 223 | round *= 1<<(LDBL_MANT_DIG%4); 224 | while (re--) round*=16; 225 | if (*prefix=='-') { 226 | y=-y; 227 | y-=round; 228 | y+=round; 229 | y=-y; 230 | } else { 231 | y+=round; 232 | y-=round; 233 | } 234 | } 235 | 236 | estr=fmt_u(e2<0 ? -e2 : e2, ebuf); 237 | if (estr==ebuf) *--estr='0'; 238 | *--estr = (e2<0 ? '-' : '+'); 239 | *--estr = t+('p'-'a'); 240 | 241 | s=buf; 242 | do { 243 | int x=y; 244 | *s++=xdigits[x]|(t&32); 245 | y=16*(y-x); 246 | if (s-buf==1 && (y||p>0||(fl&ALT_FORM))) *s++='.'; 247 | } while (y); 248 | 249 | if (p > INT_MAX-2-(ebuf-estr)-pl) 250 | return -1; 251 | if (p && s-buf-2 < p) 252 | l = (p+2) + (ebuf-estr); 253 | else 254 | l = (s-buf) + (ebuf-estr); 255 | 256 | pad(f, ' ', w, pl+l, fl); 257 | out(f, prefix, pl); 258 | pad(f, '0', w, pl+l, fl^ZERO_PAD); 259 | out(f, buf, s-buf); 260 | pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0); 261 | out(f, estr, ebuf-estr); 262 | pad(f, ' ', w, pl+l, fl^LEFT_ADJ); 263 | return MAX(w, pl+l); 264 | } 265 | if (p<0) p=6; 266 | 267 | if (y) y *= 0x1p28, e2-=28; 268 | 269 | if (e2<0) a=r=z=big; 270 | else a=r=z=big+sizeof(big)/sizeof(*big) - LDBL_MANT_DIG - 1; 271 | 272 | do { 273 | *z = y; 274 | y = 1000000000*(y-*z++); 275 | } while (y); 276 | 277 | while (e2>0) { 278 | uint32_t carry=0; 279 | int sh=MIN(29,e2); 280 | for (d=z-1; d>=a; d--) { 281 | uint64_t x = ((uint64_t)*d<a && !z[-1]) z--; 287 | e2-=sh; 288 | } 289 | while (e2<0) { 290 | uint32_t carry=0, *b; 291 | int sh=MIN(9,-e2), need=1+(p+LDBL_MANT_DIG/3U+8)/9; 292 | for (d=a; d>sh) + carry; 295 | carry = (1000000000>>sh) * rm; 296 | } 297 | if (!*a) a++; 298 | if (carry) *z++ = carry; 299 | /* Avoid (slow!) computation past requested precision */ 300 | b = (t|32)=='f' ? r : a; 301 | if (z-b > need) z = b+need; 302 | e2+=sh; 303 | } 304 | 305 | if (a=i; i*=10, e++); 306 | else e=0; 307 | 308 | /* Perform rounding: j is precision after the radix (possibly neg) */ 309 | j = p - ((t|32)!='f')*e - ((t|32)=='g' && p); 310 | if (j < 9*(z-r-1)) { 311 | uint32_t x; 312 | /* We avoid C's broken division of negative numbers */ 313 | d = r + 1 + ((j+9*LDBL_MAX_EXP)/9 - LDBL_MAX_EXP); 314 | j += 9*LDBL_MAX_EXP; 315 | j %= 9; 316 | for (i=10, j++; j<9; i*=10, j++); 317 | x = *d % i; 318 | /* Are there any significant digits past j? */ 319 | if (x || d+1!=z) { 320 | long double round = 2/LDBL_EPSILON; 321 | long double small; 322 | if ((*d/i & 1) || (i==1000000000 && d>a && (d[-1]&1))) 323 | round += 2; 324 | if (x 999999999) { 333 | *d--=0; 334 | if (d=i; i*=10, e++); 338 | } 339 | } 340 | if (z>d+1) z=d+1; 341 | } 342 | for (; z>a && !z[-1]; z--); 343 | 344 | if ((t|32)=='g') { 345 | if (!p) p++; 346 | if (p>e && e>=-4) { 347 | t--; 348 | p-=e+1; 349 | } else { 350 | t-=2; 351 | p--; 352 | } 353 | if (!(fl&ALT_FORM)) { 354 | /* Count trailing zeros in last place */ 355 | if (z>a && z[-1]) for (i=10, j=0; z[-1]%i==0; i*=10, j++); 356 | else j=9; 357 | if ((t|32)=='f') 358 | p = MIN(p,MAX(0,9*(z-r-1)-j)); 359 | else 360 | p = MIN(p,MAX(0,9*(z-r-1)+e-j)); 361 | } 362 | } 363 | if (p > INT_MAX-1-(p || (fl&ALT_FORM))) 364 | return -1; 365 | l = 1 + p + (p || (fl&ALT_FORM)); 366 | if ((t|32)=='f') { 367 | if (e > INT_MAX-l) return -1; 368 | if (e>0) l+=e; 369 | } else { 370 | estr=fmt_u(e<0 ? -e : e, ebuf); 371 | while(ebuf-estr<2) *--estr='0'; 372 | *--estr = (e<0 ? '-' : '+'); 373 | *--estr = t; 374 | if (ebuf-estr > INT_MAX-l) return -1; 375 | l += ebuf-estr; 376 | } 377 | 378 | if (l > INT_MAX-pl) return -1; 379 | pad(f, ' ', w, pl+l, fl); 380 | out(f, prefix, pl); 381 | pad(f, '0', w, pl+l, fl^ZERO_PAD); 382 | 383 | if ((t|32)=='f') { 384 | if (a>r) a=r; 385 | for (d=a; d<=r; d++) { 386 | char *s = fmt_u(*d, buf+9); 387 | if (d!=a) while (s>buf) *--s='0'; 388 | else if (s==buf+9) *--s='0'; 389 | out(f, s, buf+9-s); 390 | } 391 | if (p || (fl&ALT_FORM)) out(f, ".", 1); 392 | for (; d0; d++, p-=9) { 393 | char *s = fmt_u(*d, buf+9); 394 | while (s>buf) *--s='0'; 395 | out(f, s, MIN(9,p)); 396 | } 397 | pad(f, '0', p+9, 9, 0); 398 | } else { 399 | if (z<=a) z=a+1; 400 | for (d=a; d=0; d++) { 401 | char *s = fmt_u(*d, buf+9); 402 | if (s==buf+9) *--s='0'; 403 | if (d!=a) while (s>buf) *--s='0'; 404 | else { 405 | out(f, s++, 1); 406 | if (p>0||(fl&ALT_FORM)) out(f, ".", 1); 407 | } 408 | out(f, s, MIN(buf+9-s, p)); 409 | p -= buf+9-s; 410 | } 411 | pad(f, '0', p+18, 18, 0); 412 | out(f, estr, ebuf-estr); 413 | } 414 | 415 | pad(f, ' ', w, pl+l, fl^LEFT_ADJ); 416 | 417 | return MAX(w, pl+l); 418 | } 419 | 420 | static int getint(char **s) { 421 | int i; 422 | for (i=0; isdigit(**s); (*s)++) { 423 | if (i > INT_MAX/10U || **s-'0' > INT_MAX-10*i) i = -1; 424 | else i = 10*i + (**s-'0'); 425 | } 426 | return i; 427 | } 428 | 429 | static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, int *nl_type) 430 | { 431 | char *a, *z, *s=(char *)fmt; 432 | unsigned l10n=0, fl; 433 | int w, p, xp; 434 | union arg arg; 435 | int argpos; 436 | unsigned st, ps; 437 | int cnt=0, l=0; 438 | size_t i; 439 | char buf[sizeof(uintmax_t)*3]; 440 | const char *prefix; 441 | int t, pl; 442 | 443 | for (;;) { 444 | /* This error is only specified for snprintf, but since it's 445 | * unspecified for other forms, do the same. Stop immediately 446 | * on overflow; otherwise %n could produce wrong results. */ 447 | if (l > INT_MAX - cnt) goto overflow; 448 | 449 | /* Update output count, end loop when fmt is exhausted */ 450 | cnt += l; 451 | if (!*s) break; 452 | 453 | /* Handle literal text and %% format specifiers */ 454 | for (a=s; *s && *s!='%'; s++); 455 | for (z=s; s[0]=='%' && s[1]=='%'; z++, s+=2); 456 | if (z-a > INT_MAX-cnt) goto overflow; 457 | l = z-a; 458 | if (f) out(f, a, l); 459 | if (l) continue; 460 | 461 | if (isdigit(s[1]) && s[2]=='$') { 462 | l10n=1; 463 | argpos = s[1]-'0'; 464 | s+=3; 465 | } else { 466 | argpos = -1; 467 | s++; 468 | } 469 | 470 | /* Read modifier flags */ 471 | for (fl=0; (unsigned)*s-' '<32 && (FLAGMASK&(1U<<*s-' ')); s++) 472 | fl |= 1U<<*s-' '; 473 | 474 | /* Read field width */ 475 | if (*s=='*') { 476 | if (isdigit(s[1]) && s[2]=='$') { 477 | l10n=1; 478 | if (!f) nl_type[s[1]-'0'] = INT, w = 0; 479 | else w = nl_arg[s[1]-'0'].i; 480 | s+=3; 481 | } else if (!l10n) { 482 | w = f ? va_arg(*ap, int) : 0; 483 | s++; 484 | } else goto inval; 485 | if (w<0) fl|=LEFT_ADJ, w=-w; 486 | } else if ((w=getint(&s))<0) goto overflow; 487 | 488 | /* Read precision */ 489 | if (*s=='.' && s[1]=='*') { 490 | if (isdigit(s[2]) && s[3]=='$') { 491 | if (!f) nl_type[s[2]-'0'] = INT, p = 0; 492 | else p = nl_arg[s[2]-'0'].i; 493 | s+=4; 494 | } else if (!l10n) { 495 | p = f ? va_arg(*ap, int) : 0; 496 | s+=2; 497 | } else goto inval; 498 | xp = (p>=0); 499 | } else if (*s=='.') { 500 | s++; 501 | p = getint(&s); 502 | xp = 1; 503 | } else { 504 | p = -1; 505 | xp = 0; 506 | } 507 | 508 | /* Format specifier state machine */ 509 | st=0; 510 | do { 511 | if (OOB(*s)) goto inval; 512 | ps=st; 513 | st=states[st]S(*s++); 514 | } while (st-1=0) goto inval; 520 | } else { 521 | if (argpos>=0) { 522 | if (!f) nl_type[argpos]=st; 523 | else arg=nl_arg[argpos]; 524 | } else if (f) pop_arg(&arg, st, ap); 525 | else return 0; 526 | } 527 | 528 | if (!f) continue; 529 | 530 | /* Do not process any new directives once in error state. */ 531 | if (ferror(f)) return -1; 532 | 533 | z = buf + sizeof(buf); 534 | prefix = "-+ 0X0x"; 535 | pl = 0; 536 | t = s[-1]; 537 | 538 | /* Transform ls,lc -> S,C */ 539 | if (ps && (t&15)==3) t&=~32; 540 | 541 | /* - and 0 flags are mutually exclusive */ 542 | if (fl & LEFT_ADJ) fl &= ~ZERO_PAD; 543 | 544 | switch(t) { 545 | case 'n': 546 | switch(ps) { 547 | case BARE: *(int *)arg.p = cnt; break; 548 | case LPRE: *(long *)arg.p = cnt; break; 549 | case LLPRE: *(long long *)arg.p = cnt; break; 550 | case HPRE: *(unsigned short *)arg.p = cnt; break; 551 | case HHPRE: *(unsigned char *)arg.p = cnt; break; 552 | case ZTPRE: *(size_t *)arg.p = cnt; break; 553 | case JPRE: *(uintmax_t *)arg.p = cnt; break; 554 | } 555 | continue; 556 | case 'p': 557 | p = MAX(p, 2*sizeof(void*)); 558 | t = 'x'; 559 | fl |= ALT_FORM; 560 | case 'x': case 'X': 561 | a = fmt_x(arg.i, z, t&32); 562 | if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2; 563 | if (0) { 564 | case 'o': 565 | a = fmt_o(arg.i, z); 566 | if ((fl&ALT_FORM) && pINTMAX_MAX) { 571 | arg.i=-arg.i; 572 | } else if (fl & MARK_POS) { 573 | prefix++; 574 | } else if (fl & PAD_POS) { 575 | prefix+=2; 576 | } else pl=0; 577 | case 'u': 578 | a = fmt_u(arg.i, z); 579 | } 580 | if (xp && p<0) goto overflow; 581 | if (xp) fl &= ~ZERO_PAD; 582 | if (!arg.i && !p) { 583 | a=z; 584 | break; 585 | } 586 | p = MAX(p, z-a + !arg.i); 587 | break; 588 | case 'c': 589 | *(a=z-(p=1))=arg.i; 590 | fl &= ~ZERO_PAD; 591 | break; 592 | case 'm': 593 | if (1) a = strerror(errno); else 594 | case 's': 595 | a = arg.p ? arg.p : "(null)"; 596 | z = a + strnlen(a, p<0 ? INT_MAX : p); 597 | if (p<0 && *z) goto overflow; 598 | p = z-a; 599 | fl &= ~ZERO_PAD; 600 | break; 601 | case 'e': case 'f': case 'g': case 'a': 602 | case 'E': case 'F': case 'G': case 'A': 603 | if (xp && p<0) goto overflow; 604 | l = fmt_fp(f, arg.f, w, p, fl, t); 605 | if (l<0) goto overflow; 606 | continue; 607 | } 608 | 609 | if (p < z-a) p = z-a; 610 | if (p > INT_MAX-pl) goto overflow; 611 | if (w < pl+p) w = pl+p; 612 | if (w > INT_MAX-cnt) goto overflow; 613 | 614 | pad(f, ' ', w, pl+p, fl); 615 | out(f, prefix, pl); 616 | pad(f, '0', w, pl+p, fl^ZERO_PAD); 617 | pad(f, '0', p, z-a, 0); 618 | out(f, a, z-a); 619 | pad(f, ' ', w, pl+p, fl^LEFT_ADJ); 620 | 621 | l = w; 622 | } 623 | 624 | if (f) return cnt; 625 | if (!l10n) return 0; 626 | 627 | for (i=1; i<=NL_ARGMAX && nl_type[i]; i++) 628 | pop_arg(nl_arg+i, nl_type[i], ap); 629 | for (; i<=NL_ARGMAX && !nl_type[i]; i++); 630 | if (i<=NL_ARGMAX) goto inval; 631 | return 1; 632 | 633 | inval: 634 | errno = EINVAL; 635 | return -1; 636 | overflow: 637 | errno = EOVERFLOW; 638 | return -1; 639 | } 640 | 641 | int musl_vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) 642 | { 643 | va_list ap2; 644 | int nl_type[NL_ARGMAX+1] = {0}; 645 | union arg nl_arg[NL_ARGMAX+1]; 646 | int ret; 647 | 648 | /* the copy allows passing va_list* even if va_list is an array */ 649 | va_copy(ap2, ap); 650 | if (printf_core(0, fmt, &ap2, nl_arg, nl_type) < 0) { 651 | va_end(ap2); 652 | return -1; 653 | } 654 | 655 | ret = printf_core(f, fmt, &ap2, nl_arg, nl_type); 656 | if (ferror(f)) ret = -1; 657 | va_end(ap2); 658 | return ret; 659 | } 660 | -------------------------------------------------------------------------------- /musl/vfscanf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "shgetc.h" 11 | 12 | #define SIZE_hh -2 13 | #define SIZE_h -1 14 | #define SIZE_def 0 15 | #define SIZE_l 1 16 | #define SIZE_L 2 17 | #define SIZE_ll 3 18 | 19 | extern unsigned long long __intscan(FILE *, unsigned, int, unsigned long long); 20 | extern long double __floatscan(FILE *, int, int); 21 | 22 | static void store_int(void *dest, int size, unsigned long long i) 23 | { 24 | if (!dest) return; 25 | switch (size) { 26 | case SIZE_hh: 27 | *(char *)dest = i; 28 | break; 29 | case SIZE_h: 30 | *(short *)dest = i; 31 | break; 32 | case SIZE_def: 33 | *(int *)dest = i; 34 | break; 35 | case SIZE_l: 36 | *(long *)dest = i; 37 | break; 38 | case SIZE_ll: 39 | *(long long *)dest = i; 40 | break; 41 | } 42 | } 43 | 44 | static void *arg_n(va_list ap, unsigned int n) 45 | { 46 | void *p; 47 | unsigned int i; 48 | va_list ap2; 49 | va_copy(ap2, ap); 50 | for (i=n; i>1; i--) va_arg(ap2, void *); 51 | p = va_arg(ap2, void *); 52 | va_end(ap2); 53 | return p; 54 | } 55 | 56 | int musl_vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap) 57 | { 58 | int width; 59 | int size; 60 | int alloc = 0; 61 | int base; 62 | const unsigned char *p; 63 | int c, t; 64 | char *s; 65 | void *dest=NULL; 66 | int invert; 67 | int matches=0; 68 | unsigned long long x; 69 | long double y; 70 | off_t pos = 0; 71 | unsigned char scanset[257]; 72 | size_t i, k; 73 | wchar_t *wcs; 74 | #if 0 75 | wchar_t wc; 76 | mbstate_t st; 77 | #endif 78 | 79 | for (p=(const unsigned char *)fmt; *p; p++) { 80 | 81 | alloc = 0; 82 | 83 | if (isspace(*p)) { 84 | while (isspace(p[1])) p++; 85 | shlim(f, 0); 86 | while (isspace(shgetc(f))); 87 | shunget(f); 88 | pos += shcnt(f); 89 | continue; 90 | } 91 | if (*p != '%' || p[1] == '%') { 92 | shlim(f, 0); 93 | if (*p == '%') { 94 | p++; 95 | while (isspace((c=shgetc(f)))); 96 | } else { 97 | c = shgetc(f); 98 | } 99 | if (c!=*p) { 100 | shunget(f); 101 | if (c<0) goto input_fail; 102 | goto match_fail; 103 | } 104 | pos += shcnt(f); 105 | continue; 106 | } 107 | 108 | p++; 109 | if (*p=='*') { 110 | dest = 0; p++; 111 | } else if (isdigit(*p) && p[1]=='$') { 112 | dest = arg_n(ap, *p-'0'); p+=2; 113 | } else { 114 | dest = va_arg(ap, void *); 115 | } 116 | 117 | for (width=0; isdigit(*p); p++) { 118 | width = 10*width + *p - '0'; 119 | } 120 | 121 | if (*p=='m') { 122 | wcs = 0; 123 | s = 0; 124 | alloc = !!dest; 125 | p++; 126 | } else { 127 | alloc = 0; 128 | } 129 | 130 | size = SIZE_def; 131 | switch (*p++) { 132 | case 'h': 133 | if (*p == 'h') p++, size = SIZE_hh; 134 | else size = SIZE_h; 135 | break; 136 | case 'l': 137 | if (*p == 'l') p++, size = SIZE_ll; 138 | else size = SIZE_l; 139 | break; 140 | case 'j': 141 | size = SIZE_ll; 142 | break; 143 | case 'z': 144 | case 't': 145 | size = SIZE_l; 146 | break; 147 | case 'L': 148 | size = SIZE_L; 149 | break; 150 | case 'd': case 'i': case 'o': case 'u': case 'x': 151 | case 'a': case 'e': case 'f': case 'g': 152 | case 'A': case 'E': case 'F': case 'G': case 'X': 153 | case 's': case 'c': case '[': 154 | case 'S': case 'C': 155 | case 'p': case 'n': 156 | p--; 157 | break; 158 | default: 159 | goto fmt_fail; 160 | } 161 | 162 | t = *p; 163 | 164 | /* C or S */ 165 | if ((t&0x2f) == 3) { 166 | t |= 32; 167 | size = SIZE_l; 168 | } 169 | 170 | switch (t) { 171 | case 'c': 172 | if (width < 1) width = 1; 173 | case '[': 174 | break; 175 | case 'n': 176 | store_int(dest, size, pos); 177 | /* do not increment match count, etc! */ 178 | continue; 179 | default: 180 | shlim(f, 0); 181 | while (isspace(shgetc(f))); 182 | shunget(f); 183 | pos += shcnt(f); 184 | } 185 | 186 | shlim(f, width); 187 | if (shgetc(f) < 0) goto input_fail; 188 | shunget(f); 189 | 190 | switch (t) { 191 | case 's': 192 | case 'c': 193 | case '[': 194 | if (t == 'c' || t == 's') { 195 | memset(scanset, -1, sizeof scanset); 196 | scanset[0] = 0; 197 | if (t == 's') { 198 | scanset[1+'\t'] = 0; 199 | scanset[1+'\n'] = 0; 200 | scanset[1+'\v'] = 0; 201 | scanset[1+'\f'] = 0; 202 | scanset[1+'\r'] = 0; 203 | scanset[1+' '] = 0; 204 | } 205 | } else { 206 | if (*++p == '^') p++, invert = 1; 207 | else invert = 0; 208 | memset(scanset, invert, sizeof scanset); 209 | scanset[0] = 0; 210 | if (*p == '-') p++, scanset[1+'-'] = 1-invert; 211 | else if (*p == ']') p++, scanset[1+']'] = 1-invert; 212 | for (; *p != ']'; p++) { 213 | if (!*p) goto fmt_fail; 214 | if (*p=='-' && p[1] && p[1] != ']') 215 | for (c=p++[-1]; c<*p; c++) 216 | scanset[1+c] = 1-invert; 217 | scanset[1+*p] = 1-invert; 218 | } 219 | } 220 | wcs = 0; 221 | s = 0; 222 | i = 0; 223 | k = t=='c' ? width+1U : 31; 224 | if (size == SIZE_l) { 225 | abort(); 226 | #if 0 227 | if (alloc) { 228 | wcs = malloc(k*sizeof(wchar_t)); 229 | if (!wcs) goto alloc_fail; 230 | } else { 231 | wcs = dest; 232 | } 233 | st = (mbstate_t){0}; 234 | while (scanset[(c=shgetc(f))+1]) { 235 | switch (mbrtowc(&wc, &(char){c}, 1, &st)) { 236 | case -1: 237 | goto input_fail; 238 | case -2: 239 | continue; 240 | } 241 | if (wcs) wcs[i++] = wc; 242 | if (alloc && i==k) { 243 | k+=k+1; 244 | wchar_t *tmp = realloc(wcs, k*sizeof(wchar_t)); 245 | if (!tmp) goto alloc_fail; 246 | wcs = tmp; 247 | } 248 | } 249 | if (!mbsinit(&st)) goto input_fail; 250 | #endif 251 | } else if (alloc) { 252 | s = malloc(k); 253 | if (!s) goto alloc_fail; 254 | while (scanset[(c=shgetc(f))+1]) { 255 | s[i++] = c; 256 | if (i==k) { 257 | k+=k+1; 258 | char *tmp = realloc(s, k); 259 | if (!tmp) goto alloc_fail; 260 | s = tmp; 261 | } 262 | } 263 | } else if ((s = dest)) { 264 | while (scanset[(c=shgetc(f))+1]) 265 | s[i++] = c; 266 | } else { 267 | while (scanset[(c=shgetc(f))+1]); 268 | } 269 | shunget(f); 270 | if (!shcnt(f)) goto match_fail; 271 | if (t == 'c' && shcnt(f) != width) goto match_fail; 272 | if (alloc) { 273 | if (size == SIZE_l) *(wchar_t **)dest = wcs; 274 | else *(char **)dest = s; 275 | } 276 | if (t != 'c') { 277 | if (wcs) wcs[i] = 0; 278 | if (s) s[i] = 0; 279 | } 280 | break; 281 | case 'p': 282 | case 'X': 283 | case 'x': 284 | base = 16; 285 | goto int_common; 286 | case 'o': 287 | base = 8; 288 | goto int_common; 289 | case 'd': 290 | case 'u': 291 | base = 10; 292 | goto int_common; 293 | case 'i': 294 | base = 0; 295 | int_common: 296 | x = __intscan(f, base, 0, ULLONG_MAX); 297 | if (!shcnt(f)) goto match_fail; 298 | if (t=='p' && dest) *(void **)dest = (void *)(uintptr_t)x; 299 | else store_int(dest, size, x); 300 | break; 301 | case 'a': case 'A': 302 | case 'e': case 'E': 303 | case 'f': case 'F': 304 | case 'g': case 'G': 305 | y = __floatscan(f, size, 0); 306 | if (!shcnt(f)) goto match_fail; 307 | if (dest) switch (size) { 308 | case SIZE_def: 309 | *(float *)dest = y; 310 | break; 311 | case SIZE_l: 312 | *(double *)dest = y; 313 | break; 314 | case SIZE_L: 315 | *(long double *)dest = y; 316 | break; 317 | } 318 | break; 319 | } 320 | 321 | pos += shcnt(f); 322 | if (dest) matches++; 323 | } 324 | if (0) { 325 | fmt_fail: 326 | alloc_fail: 327 | input_fail: 328 | if (!matches) matches--; 329 | match_fail: 330 | if (alloc) { 331 | free(s); 332 | free(wcs); 333 | } 334 | } 335 | return matches; 336 | } 337 | -------------------------------------------------------------------------------- /printf/printf.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @author (c) Eyal Rozenberg 3 | * 2021-2023, Haifa, Palestine/Israel 4 | * @author (c) Marco Paland (info@paland.com) 5 | * 2014-2019, PALANDesign Hannover, Germany 6 | * 7 | * @note Others have made smaller contributions to this file: see the 8 | * contributors page at https://github.com/eyalroz/printf/graphs/contributors 9 | * or ask one of the authors. 10 | * 11 | * @brief Small stand-alone implementation of the printf family of functions 12 | * (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems 13 | * with a very limited resources. 14 | * 15 | * @note the implementations are thread-safe; re-entrant; use no functions from 16 | * the standard library; and do not dynamically allocate any memory. 17 | * 18 | * @license The MIT License (MIT) 19 | * 20 | * Permission is hereby granted, free of charge, to any person obtaining a copy 21 | * of this software and associated documentation files (the "Software"), to deal 22 | * in the Software without restriction, including without limitation the rights 23 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 24 | * copies of the Software, and to permit persons to whom the Software is 25 | * furnished to do so, subject to the following conditions: 26 | * 27 | * The above copyright notice and this permission notice shall be included in 28 | * all copies or substantial portions of the Software. 29 | * 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 36 | * THE SOFTWARE. 37 | */ 38 | 39 | #ifndef PRINTF_H_ 40 | #define PRINTF_H_ 41 | 42 | #ifdef __cplusplus 43 | # include 44 | # include 45 | extern "C" { 46 | #else 47 | # include 48 | # include 49 | #endif 50 | 51 | #ifdef __GNUC__ 52 | # if ((__GNUC__ == 4 && __GNUC_MINOR__>= 4) || __GNUC__ > 4) 53 | # define ATTR_PRINTF(one_based_format_index, first_arg) \ 54 | __attribute__((format(gnu_printf, (one_based_format_index), (first_arg)))) 55 | # else 56 | # define ATTR_PRINTF(one_based_format_index, first_arg) \ 57 | __attribute__((format(printf, (one_based_format_index), (first_arg)))) 58 | # endif 59 | # define ATTR_VPRINTF(one_based_format_index) \ 60 | ATTR_PRINTF((one_based_format_index), 0) 61 | #else 62 | # define ATTR_PRINTF(one_based_format_index, first_arg) 63 | # define ATTR_VPRINTF(one_based_format_index) 64 | #endif 65 | 66 | // If you want to include this implementation file directly rather than 67 | // link against it, this will let you control the functions' visibility, 68 | // e.g. make them static so as not to clash with other objects also 69 | // using them. 70 | #ifndef PRINTF_VISIBILITY 71 | #define PRINTF_VISIBILITY 72 | #endif 73 | 74 | /** 75 | * printf/vprintf with user-specified output function 76 | * 77 | * An alternative to @ref printf_, in which the output function is specified 78 | * dynamically (rather than @ref putchar_ being used) 79 | * 80 | * @param out An output function which takes one character and a type-erased 81 | * additional parameters 82 | * @param extra_arg The type-erased argument to pass to the output function @p 83 | * out with each call 84 | * @param format A string specifying the format of the output, with %-marked 85 | * specifiers of how to interpret additional arguments. 86 | * @param arg Additional arguments to the function, one for each specifier in 87 | * @p format 88 | * @return The number of characters for which the output f unction was invoked, 89 | * not counting the terminating null character 90 | * 91 | */ 92 | PRINTF_VISIBILITY 93 | int vfctprintf(void (*out)(char c, void* extra_arg), void* extra_arg, const char* format, va_list arg) ATTR_VPRINTF(3); 94 | 95 | #ifdef __cplusplus 96 | } // extern "C" 97 | #endif 98 | 99 | #endif // PRINTF_H_ 100 | -------------------------------------------------------------------------------- /printf/printf_config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define PRINTF_SUPPORT_DECIMAL_SPECIFIERS 0 4 | #define PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS 0 5 | #define PRINTF_CHECK_FOR_NUL_IN_FORMAT_SPECIFIER 0 6 | -------------------------------------------------------------------------------- /stdio.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "stdio_impl.h" 8 | 9 | // Hand-rolled base FILE operations 10 | 11 | static int fp_read_fn(void *p, char *buf, int sz) { 12 | intptr_t fd = (intptr_t) p; 13 | return read(fd, buf, sz); 14 | } 15 | 16 | static int fp_write_fn(void *p, const char *buf, int sz) { 17 | intptr_t fd = (intptr_t) p; 18 | return write(fd, buf, sz); 19 | } 20 | 21 | static int fp_close_fn(void *p) { 22 | intptr_t fd = (intptr_t) p; 23 | return close(fd); 24 | } 25 | 26 | static int buf_read_fn(void *p, char *buf, int sz) { 27 | buf_holder *h = (buf_holder *) p; 28 | size_t len; 29 | if (h->end) { 30 | len = MIN(h->begin + sz, h->end) - h->begin; 31 | } else { 32 | len = sz; 33 | } 34 | if (len) { 35 | memcpy(buf, h->begin, len); 36 | h->begin += len; 37 | } 38 | return sz; 39 | } 40 | 41 | static int buf_write_fn(void *p, const char *buf, int sz) { 42 | buf_holder *h = (buf_holder *) p; 43 | size_t len; 44 | if (h->end) { 45 | len = MIN(h->begin + sz, h->end) - h->begin; 46 | } else { 47 | len = sz; 48 | } 49 | if (len) { 50 | memcpy(h->begin, buf, len); 51 | h->begin += len; 52 | } 53 | return sz; 54 | } 55 | 56 | void setup_fd_fp(file_impl *fp, int fd) { 57 | fp->fd = fd; 58 | fp->cookie = NULL; 59 | fp->read_fn = fp_read_fn; 60 | fp->write_fn = fp_write_fn; 61 | fp->close_fn = fp_close_fn; 62 | } 63 | 64 | void setup_buf_fp(file_impl *fp, buf_holder *h) { 65 | fp->fd = -1; 66 | fp->buf = h; 67 | fp->read_fn = buf_read_fn; 68 | fp->write_fn = buf_write_fn; 69 | fp->close_fn = NULL; 70 | } 71 | 72 | static file_impl __stdio_fp[3]; 73 | 74 | FILE* stdin = (FILE *) &__stdio_fp[0]; 75 | FILE* stdout = (FILE *) &__stdio_fp[1]; 76 | FILE* stderr = (FILE *) &__stdio_fp[2]; 77 | 78 | void __init_stdio(void) { 79 | setup_fd_fp(&__stdio_fp[0], 0); 80 | setup_fd_fp(&__stdio_fp[1], 1); 81 | setup_fd_fp(&__stdio_fp[2], 2); 82 | } 83 | 84 | FILE *fopen(const char *path, const char *mode) { 85 | int flag = 0; 86 | int mode_flg = 0; 87 | if (*mode == 'r') { 88 | flag |= O_RDONLY; 89 | } else if (*mode == 'w') { 90 | flag |= O_WRONLY | O_CREAT | O_TRUNC; 91 | } else if (*mode == 'a') { 92 | flag |= O_WRONLY | O_CREAT | O_APPEND; 93 | } 94 | if (strchr(mode, 'e')) flag |= O_CLOEXEC; 95 | if (strchr(mode, '+')) { 96 | flag &= ~O_ACCMODE; 97 | flag |= O_RDWR; 98 | } 99 | if (flag & O_CREAT) mode_flg = 0644; 100 | 101 | int fd = open(path, flag, mode_flg); 102 | if (fd >= 0) { 103 | return fdopen(fd, mode); 104 | } 105 | return NULL; 106 | } 107 | 108 | FILE *fdopen(int fd, const char *mode __attribute__((unused))) { 109 | file_impl *fp = malloc(sizeof(file_impl)); 110 | setup_fd_fp(fp, fd); 111 | return (FILE *) fp; 112 | } 113 | 114 | FILE *funopen(const void* cookie, 115 | int (*read_fn)(void*, char*, int), 116 | int (*write_fn)(void*, const char*, int), 117 | fpos_t (*seek_fn)(void*, fpos_t, int), 118 | int (*close_fn)(void*)) { 119 | file_impl *fp = malloc(sizeof(file_impl)); 120 | fp->fd = -1; 121 | fp->cookie = (void *) cookie; 122 | fp->read_fn = read_fn; 123 | fp->write_fn = write_fn; 124 | fp->close_fn = close_fn; 125 | return (FILE *) fp; 126 | } 127 | 128 | int ferror(FILE *stream) { 129 | // We don't report any errors 130 | return 0; 131 | } 132 | 133 | #define fn_arg (fp->fd < 0 ? fp->cookie : ((void*)(intptr_t) fp->fd)) 134 | 135 | int fclose(FILE *stream) { 136 | file_impl *fp = (file_impl *) stream; 137 | int ret = 0; 138 | if (fp->close_fn) 139 | fp->close_fn(fn_arg); 140 | free(fp); 141 | return ret; 142 | } 143 | 144 | int fileno(FILE *stream) { 145 | file_impl *fp = (file_impl *) stream; 146 | return fp->fd; 147 | } 148 | 149 | int fputc(int ch, FILE *stream) { 150 | char c = ch; 151 | file_impl *fp = (file_impl *) stream; 152 | return fp->write_fn(fn_arg, &c, 1) >= 0 ? 0 : EOF; 153 | } 154 | 155 | int putchar(int ch) { 156 | return fputc(ch, stdout); 157 | } 158 | 159 | size_t fwrite(const void* buf, size_t size, size_t count, FILE* stream) { 160 | file_impl *fp = (file_impl *) stream; 161 | int len = size * count; 162 | int ret = fp->write_fn(fn_arg, buf, len); 163 | return ret == len ? count : 0; 164 | } 165 | 166 | int fputs(const char* s, FILE* stream) { 167 | file_impl *fp = (file_impl *) stream; 168 | size_t length = strlen(s); 169 | return fp->write_fn(fn_arg, s, length) == length ? 0 : EOF; 170 | } 171 | 172 | int fgetc(FILE *stream) { 173 | char ch; 174 | file_impl *fp = (file_impl *) stream; 175 | if (fp->read_fn(fn_arg, &ch, 1) == 1) { 176 | return ch; 177 | } 178 | return -1; 179 | } 180 | 181 | size_t fread(void *buf, size_t size, size_t count, FILE* stream) { 182 | file_impl *fp = (file_impl *) stream; 183 | int len = size * count; 184 | int ret = fp->read_fn(fn_arg, buf, len); 185 | return ret == len ? count : 0; 186 | } 187 | 188 | void setbuf(FILE* fp, char* buf) {} 189 | 190 | // Internal functions for musl_vfscanf 191 | // For now we only support buffer FILE pointers 192 | 193 | void shlim(FILE *f, off_t lim) { 194 | file_impl *fp = (file_impl *) f; 195 | fp->buf->cnt = 0; 196 | } 197 | 198 | int shgetc(FILE *f) { 199 | file_impl *fp = (file_impl *) f; 200 | ++fp->buf->cnt; 201 | return *(const uint8_t *)(fp->buf->begin++); 202 | } 203 | 204 | size_t shcnt(FILE *f) { 205 | file_impl *fp = (file_impl *) f; 206 | return fp->buf->cnt; 207 | } 208 | 209 | void shunget(FILE *f) { 210 | file_impl *fp = (file_impl *) f; 211 | --fp->buf->begin; 212 | } 213 | 214 | // Original source: https://github.com/freebsd/freebsd/blob/master/contrib/file/src/getline.c 215 | // License: BSD, full copyright notice please check original source 216 | ssize_t getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) { 217 | char *ptr, *eptr; 218 | 219 | if (*buf == NULL || *bufsiz == 0) { 220 | *bufsiz = BUFSIZ; 221 | if ((*buf = (char *) malloc(*bufsiz)) == NULL) 222 | return -1; 223 | } 224 | 225 | for (ptr = *buf, eptr = *buf + *bufsiz;;) { 226 | int c = fgetc(fp); 227 | if (c == -1) { 228 | return ptr == *buf ? -1 : ptr - *buf; 229 | } 230 | *ptr++ = c; 231 | if (c == delimiter) { 232 | *ptr = '\0'; 233 | return ptr - *buf; 234 | } 235 | if (ptr + 2 >= eptr) { 236 | char *nbuf; 237 | size_t nbufsiz = *bufsiz * 2; 238 | ssize_t d = ptr - *buf; 239 | if ((nbuf = (char *) realloc(*buf, nbufsiz)) == NULL) 240 | return -1; 241 | *buf = nbuf; 242 | *bufsiz = nbufsiz; 243 | eptr = nbuf + nbufsiz; 244 | ptr = nbuf + d; 245 | } 246 | } 247 | } 248 | 249 | ssize_t getline(char **buf, size_t *bufsiz, FILE *fp) { 250 | return getdelim(buf, bufsiz, '\n', fp); 251 | } 252 | -------------------------------------------------------------------------------- /stdio_impl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define MIN(a,b) ((a)<(b) ? (a) : (b)) 6 | 7 | typedef struct buf_holder { 8 | void *begin; 9 | void *end; 10 | size_t cnt; 11 | } buf_holder; 12 | 13 | typedef struct file_impl { 14 | int fd; 15 | union { 16 | void *cookie; 17 | buf_holder *buf; 18 | }; 19 | int (*read_fn)(void*, char*, int); 20 | int (*write_fn)(void*, const char*, int); 21 | int (*close_fn)(void*); 22 | } file_impl; 23 | 24 | void setup_fd_fp(file_impl *fp, int fd); 25 | void setup_buf_fp(file_impl *fp, buf_holder *h); 26 | -------------------------------------------------------------------------------- /syscalls.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SYS_INLINE 5 | #include "linux_syscall_support.h" 6 | 7 | // Some missing declarations 8 | _syscall3(int, faccessat, int, f, const char *, p, int, m) 9 | _syscall2(int, umount2, const char *, t, int, f) 10 | #ifdef __NR_renameat 11 | _syscall4(int, renameat, int, o, const char *, op, int, n, const char *, np) 12 | #else 13 | _syscall5(int, renameat2, int, o, const char *, op, int, n, const char *, np, int, flag) 14 | #endif 15 | _syscall1(mode_t, umask, mode_t, mask) 16 | _syscall1(int, chroot, const char *, path) 17 | _syscall2(int, nanosleep, const struct kernel_timespec *, req, struct kernel_timespec *, rem) 18 | _syscall5(int, mount, const char *, s, const char *, t, 19 | const char *, fs, unsigned long, f, const void *, d) 20 | _syscall3(int, symlinkat, const char *, t, int, fd, const char *, l) 21 | _syscall3(int, mkdirat, int, dirfd, const char *, pathname, mode_t, mode) 22 | _syscall4(ssize_t, sendfile, int, out_fd, int, in_fd, off_t *, offset, size_t, count) 23 | _syscall5(int, linkat, int, o, const char *, op, int, n, const char *, np, int, f) 24 | _syscall4(int, mknodat, int, dirfd, const char *, pathname, mode_t, mode, dev_t, dev) 25 | _syscall2(int, fchmod, int, fd, mode_t, mode) 26 | _syscall4(int, fchmodat, int, dirfd, const char *, pathname, mode_t, mode, int, flags) 27 | _syscall5(int, fchownat, int, dirfd, const char *, p, uid_t, owner, gid_t, group, int, flags) 28 | _syscall3(ssize_t, readv, int, fd, const struct kernel_iovec*, v, size_t, c) 29 | _syscall5(int, pselect6, fd_set*, s1, fd_set*, s2, fd_set*, s3, struct kernel_timespec*, ts, void*, p) 30 | _syscall4(ssize_t, fgetxattr, int, fd, const char *, n, void *, v, size_t, s) 31 | _syscall4(ssize_t, fsetxattr, int, fd, const char *, n, void *, v, size_t, s) 32 | 33 | #define SYMBOL_ALIAS(from, to) \ 34 | __asm__(".global " #from " \n " #from " = " #to) 35 | 36 | #define EXPORT_SYMBOL(name) \ 37 | SYMBOL_ALIAS(name, sys_##name) 38 | 39 | EXPORT_SYMBOL(openat); 40 | EXPORT_SYMBOL(close); 41 | EXPORT_SYMBOL(read); 42 | EXPORT_SYMBOL(symlink); 43 | EXPORT_SYMBOL(write); 44 | EXPORT_SYMBOL(writev); 45 | EXPORT_SYMBOL(unlink); 46 | EXPORT_SYMBOL(munmap); 47 | EXPORT_SYMBOL(mremap); 48 | EXPORT_SYMBOL(readlink); 49 | EXPORT_SYMBOL(unlinkat); 50 | EXPORT_SYMBOL(getpid); 51 | EXPORT_SYMBOL(chdir); 52 | EXPORT_SYMBOL(umount2); 53 | EXPORT_SYMBOL(readlinkat); 54 | EXPORT_SYMBOL(umask); 55 | EXPORT_SYMBOL(chroot); 56 | EXPORT_SYMBOL(mount); 57 | EXPORT_SYMBOL(symlinkat); 58 | EXPORT_SYMBOL(statfs); 59 | EXPORT_SYMBOL(mkdirat); 60 | EXPORT_SYMBOL(ioctl); 61 | EXPORT_SYMBOL(fork); 62 | EXPORT_SYMBOL(sendfile); 63 | EXPORT_SYMBOL(ftruncate); 64 | EXPORT_SYMBOL(linkat); 65 | EXPORT_SYMBOL(mknodat); 66 | EXPORT_SYMBOL(fchmod); 67 | EXPORT_SYMBOL(fchmodat); 68 | EXPORT_SYMBOL(fchownat); 69 | EXPORT_SYMBOL(readv); 70 | EXPORT_SYMBOL(lseek); 71 | EXPORT_SYMBOL(execve); 72 | EXPORT_SYMBOL(getdents64); 73 | EXPORT_SYMBOL(clock_gettime); 74 | EXPORT_SYMBOL(nanosleep); 75 | EXPORT_SYMBOL(sigemptyset); 76 | EXPORT_SYMBOL(sigaddset); 77 | EXPORT_SYMBOL(sigprocmask); 78 | EXPORT_SYMBOL(raise); 79 | EXPORT_SYMBOL(getxattr); 80 | EXPORT_SYMBOL(setxattr); 81 | EXPORT_SYMBOL(lgetxattr); 82 | EXPORT_SYMBOL(lsetxattr); 83 | EXPORT_SYMBOL(fgetxattr); 84 | EXPORT_SYMBOL(fsetxattr); 85 | 86 | SYMBOL_ALIAS(_exit, sys_exit_group); 87 | SYMBOL_ALIAS(openat64, openat); 88 | SYMBOL_ALIAS(stat64, stat); 89 | SYMBOL_ALIAS(lstat64, lstat); 90 | 91 | #if defined(__LP64__) 92 | 93 | _syscall3(int, fchown, int, i, uid_t, u, gid_t, g) 94 | EXPORT_SYMBOL(fchown); 95 | EXPORT_SYMBOL(fstat); 96 | EXPORT_SYMBOL(mmap); 97 | SYMBOL_ALIAS(fstatat, sys_newfstatat); 98 | SYMBOL_ALIAS(lseek64, lseek); 99 | SYMBOL_ALIAS(ftruncate64, ftruncate); 100 | SYMBOL_ALIAS(mmap64, mmap); 101 | 102 | #else 103 | 104 | _syscall3(int, fchown32, int, i, uid_t, u, gid_t, g) 105 | _syscall2(int, ftruncate64, int, i, off64_t, off) 106 | _syscall3(int, fcntl64, int, fd, int, op, long, arg) 107 | EXPORT_SYMBOL(ftruncate64); 108 | EXPORT_SYMBOL(fstat64); 109 | EXPORT_SYMBOL(fstatat64); 110 | SYMBOL_ALIAS(fstat, fstat64); 111 | SYMBOL_ALIAS(fstatat, fstatat64); 112 | SYMBOL_ALIAS(fchown, sys_fchown32); 113 | 114 | // Source: bionic/libc/bionic/legacy_32_bit_support.cpp 115 | off64_t lseek64(int fd, off64_t off, int whence) { 116 | off64_t result; 117 | unsigned long off_hi = (unsigned long) (off >> 32); 118 | unsigned long off_lo = (unsigned long) off; 119 | if (sys__llseek(fd, off_hi, off_lo, &result, whence) < 0) { 120 | return -1; 121 | } 122 | return result; 123 | } 124 | 125 | // Source: bionic/libc/bionic/legacy_32_bit_support.cpp 126 | #define MMAP2_SHIFT 12 // 2**12 == 4096 127 | 128 | void *mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offset) { 129 | if (offset < 0 || (offset & ((1UL << MMAP2_SHIFT)-1)) != 0) { 130 | errno = EINVAL; 131 | return MAP_FAILED; 132 | } 133 | 134 | // Prevent allocations large enough for `end - start` to overflow. 135 | size_t rounded = __BIONIC_ALIGN(size, getpagesize()); 136 | if (rounded < size || rounded > PTRDIFF_MAX) { 137 | errno = ENOMEM; 138 | return MAP_FAILED; 139 | } 140 | 141 | return sys__mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT); 142 | } 143 | 144 | void *mmap(void *addr, size_t size, int prot, int flags, int fd, off_t offset) { 145 | return mmap64(addr, size, prot, flags, fd, (off64_t) offset); 146 | } 147 | 148 | #endif 149 | 150 | int lstat(const char* path, struct stat *st) { 151 | return fstatat(AT_FDCWD, path, st, AT_SYMLINK_NOFOLLOW); 152 | } 153 | 154 | int stat(const char* path, struct stat *st) { 155 | return fstatat(AT_FDCWD, path, st, 0); 156 | } 157 | 158 | int lchown(const char* path, uid_t uid, gid_t gid) { 159 | return fchownat(AT_FDCWD, path, uid, gid, AT_SYMLINK_NOFOLLOW); 160 | } 161 | 162 | int chown(const char* path, uid_t uid, gid_t gid) { 163 | return fchownat(AT_FDCWD, path, uid, gid, 0); 164 | } 165 | 166 | int chmod(const char* path, mode_t mode) { 167 | return sys_fchmodat(AT_FDCWD, path, mode, 0); 168 | } 169 | 170 | int mkfifoat(int fd, const char* path, mode_t mode) { 171 | return sys_mknodat(fd, path, (mode & ~S_IFMT) | S_IFIFO, 0); 172 | } 173 | 174 | int mkfifo(const char* path, mode_t mode) { 175 | return mkfifoat(AT_FDCWD, path, mode); 176 | } 177 | 178 | int mknod(const char* path, mode_t mode, dev_t dev) { 179 | return sys_mknodat(AT_FDCWD, path, mode, dev); 180 | } 181 | 182 | int link(const char *oldpath, const char *newpath) { 183 | return sys_linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0); 184 | } 185 | 186 | int rmdir(const char *path) { 187 | return sys_unlinkat(AT_FDCWD, path, AT_REMOVEDIR); 188 | } 189 | 190 | int mkdir(const char *pathname, mode_t mode) { 191 | return sys_mkdirat(AT_FDCWD, pathname, mode); 192 | } 193 | 194 | int symlink(const char *target, const char *linkpath) { 195 | return sys_symlinkat(target, AT_FDCWD, linkpath); 196 | } 197 | 198 | int rename(const char *oldpath, const char *newpath) { 199 | #ifdef __NR_renameat 200 | return sys_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath); 201 | #else 202 | return sys_renameat2(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0); 203 | #endif 204 | } 205 | 206 | #ifdef __NR_renameat 207 | EXPORT_SYMBOL(renameat); 208 | #else 209 | int renameat(int o, const char * op, int n, const char * np) { 210 | return sys_renameat2(o, op, n, np, 0); 211 | } 212 | #endif 213 | 214 | int access(const char* path, int mode) { 215 | return faccessat(AT_FDCWD, path, mode, 0); 216 | } 217 | 218 | int remove(const char *path) { 219 | int r = sys_unlinkat(AT_FDCWD, path, 0); 220 | if (r < 0 && errno == EISDIR) { 221 | r = sys_unlinkat(AT_FDCWD, path, AT_REMOVEDIR); 222 | } 223 | return r; 224 | } 225 | 226 | int creat(const char *path, mode_t mode) { 227 | return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); 228 | } 229 | 230 | sighandler_t signal(int sig, sighandler_t handler) { 231 | struct kernel_sigaction sa = { .sa_handler_ = handler, .sa_flags = SA_RESTART }; 232 | return (sys_sigaction(sig, &sa, &sa) == -1) ? SIG_ERR : sa.sa_handler_; 233 | } 234 | 235 | int open(const char *pathname, int flags, ...) { 236 | int mode = 0; 237 | 238 | if (((flags & O_CREAT) == O_CREAT) || ((flags & O_TMPFILE) == O_TMPFILE)) { 239 | va_list args; 240 | va_start(args, flags); 241 | mode = va_arg(args, int); 242 | va_end(args); 243 | } 244 | 245 | #if !defined(__LP64__) 246 | flags |= O_LARGEFILE; 247 | #endif 248 | 249 | return sys_openat(AT_FDCWD, pathname, flags, mode); 250 | } 251 | --------------------------------------------------------------------------------