├── 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 |
--------------------------------------------------------------------------------
|