Merge "Fix-up for change in pwd/grp ids for PRNG seeder daemon" into android13-tests-dev am: d06e75b7e3
Original change: https://android-review.googlesource.com/c/platform/bionic/+/2273426
Change-Id: I4d17c2c68d9661530371c53d109410397edbe7c5
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/README.md b/README.md
index f397fee..85c8190 100644
--- a/README.md
+++ b/README.md
@@ -158,30 +158,63 @@
Adding a system call usually involves:
- 1. Add entries to SYSCALLS.TXT.
+ 1. Add an entry (or entries, in some cases) to SYSCALLS.TXT.
See SYSCALLS.TXT itself for documentation on the format.
- 2. Add constants (and perhaps types) to the appropriate header file.
+ See also the notes below for how to deal with tricky cases like `off_t`.
+ 2. Find the right header file to work in by looking up your system call
+ on [man7.org](https://man7.org/linux/man-pages/dir_section_2.html).
+ (If there's no header file given, see the points above about whether we
+ should really be adding this or not!)
+ 3. Add constants (and perhaps types) to the appropriate header file.
Note that you should check to see whether the constants are already in
kernel uapi header files, in which case you just need to make sure that
- the appropriate POSIX header file in libc/include/ includes the
- relevant file or files.
- 3. Add function declarations to the appropriate header file. Don't forget
- to include the appropriate `__INTRODUCED_IN()`. If you need to create a new
- header file, libc/include/sys/sysinfo.h is a good short example to copy and
- paste from.
- 4. Add basic documentation to the header file. libc/include/sys/sysinfo.h is a
- good short example that shows the expected style. Most of the detail
- should actually be left to the man7.org page, with only a brief
- one-sentence explanation in our documentation. Alway include the return
- value/error reporting details. Explicitly say which version of Android the
- function was added to. Explicitly call out any Android-specific
- changes/additions/limitations because they won't be on the man7.org page.
- 5. Add the function name to the correct section in libc/libc.map.txt.
- 6. Add a basic test. Don't try to test everything; concentrate on just testing
+ the appropriate header file in libc/include/ `#include`s the relevant
+ `linux/` file or files.
+ 4. Add function declarations to the appropriate header file. Don't forget
+ to include the appropriate `__INTRODUCED_IN()`, with the right API level
+ for the first release your system call wrapper will be in. See
+ libc/include/android/api_level.h for the API levels.
+ If the header file doesn't exist, copy all of libc/include/sys/sysinfo.h
+ into your new file --- it's a good short example to start from.
+
+ Note also our style for naming arguments: always use two leading
+ underscores (so developers are free to use any of the unadorned names as
+ macros without breaking things), avoid abbreviations, and ideally try to
+ use the same name as an existing system call (to reduce the amount of
+ English vocabulary required by people who just want to use the function
+ signatures). If there's a similar function already in the C library,
+ check what names it's used. Finally, prefer the `void*` orthography we
+ use over the `void *` you'll see on man7.org.)
+ 5. Add basic documentation to the header file. Again, the existing
+ libc/include/sys/sysinfo.h is a good short example that shows the
+ expected style.
+
+ Most of the detail should actually be left to the man7.org page, with
+ only a brief one-sentence explanation (usually based on the description
+ in the NAME section of the man page) in our documentation. Always
+ include the return value/error reporting details (you can find out
+ what the system call returns from the RETURN VALUE of the man page),
+ but try to match the wording and style wording from _our_ existing
+ documentation; we're trying to minimize the amount of English readers
+ need to understand by using the exact same wording where possible).
+ Explicitly say which version of Android the function was added to in
+ the documentation because the documentation generation tool doesn't yet
+ understand `__INTRODUCED_IN()`.
+
+ Explicitly call out any Android-specific changes/additions/limitations
+ because they won't be on the man7.org page.
+ 6. Add the function name to the correct section in libc/libc.map.txt; it'll
+ be near the end of the file. You may need to add a new section if you're
+ the first to add a system call to this version of Android.
+ 7. Add a basic test. Don't try to test everything; concentrate on just testing
the code that's actually in *bionic*, not all the functionality that's
implemented in the kernel. For simple syscalls, that's just the
auto-generated argument and return value marshalling.
+ Add a test in the right file in tests/. We have one file per header, so if
+ your system call is exposed in <unistd.h>, for example, your test would go
+ in tests/unistd_test.cpp.
+
A trivial test that deliberately supplies an invalid argument helps check
that we're generating the right symbol and have the right declaration in
the header file, and that the change to libc.map.txt from step 5 is
@@ -208,6 +241,39 @@
than 2GiB, say -- so you may end up just writing a "meaningless" program whose
only purpose is to give you patterns to look for when run under strace(1).)
+A general example of adding a system call:
+https://android-review.googlesource.com/c/platform/bionic/+/2073827
+
+### Debugging tips
+1. Key error for a new codename in libc/libc.map.txt
+e.g. what you add in libc/libc.map.txt is:
+
+```
+LIBC_V { # introduced=Vanilla
+ global:
+ xxx; // the new system call you add
+} LIBC_U;
+```
+
+The error output is:
+
+```
+Traceback (most recent call last):
+ File "/path/tp/out/soong/.temp/Soong.python_qucjwd7g/symbolfile/__init__.py", line 171,
+ in decode_api_level_tag
+ decoded = str(decode_api_level(value, api_map))
+ File "/path/to/out/soong/.temp/Soong.python_qucjwd7g/symbolfile/__init__.py", line 157,
+ in decode_api_level
+ return api_map[api]
+KeyError: 'Vanilla'
+```
+
+Solution: Ask in the team and wait for the update.
+
+2. Use of undeclared identifier of the new system call in the test
+Possible Solution: Check everything ready in the files mentioned above first.
+Maybe glibc matters. Follow the example and try #if defined(__GLIBC__).
+
## Updating kernel header files
As mentioned above, this is currently a two-step process:
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 2db0efe..18e8bbc 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -38,6 +38,9 @@
},
{
"name": "memunreachable_unit_test"
+ },
+ {
+ "name": "toybox-tests"
}
],
"hwasan-presubmit": [
@@ -73,6 +76,12 @@
},
{
"name": "malloc_hooks_system_tests"
+ },
+ {
+ "name": "memunreachable_unit_test"
+ },
+ {
+ "name": "toybox-tests"
}
]
}
diff --git a/benchmarks/spawn/AndroidTest.xml b/benchmarks/spawn/AndroidTest.xml
index 466dc7f..5232aa0 100644
--- a/benchmarks/spawn/AndroidTest.xml
+++ b/benchmarks/spawn/AndroidTest.xml
@@ -4,18 +4,18 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
- <option name="push" value="bionic-spawn-benchmarks->/data/local/tmp/bionic-spawn-benchmarks" />
+ <option name="push" value="bionic-spawn-benchmarks->/data/local/tests/unrestricted/bionic-spawn-benchmarks" />
</target_preparer>
<!-- TODO(b/120549168): This seems necessary for consistent results on a walleye, but it's not working with atest
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="push" value="perf-setup.sh->/data/local/tmp/perf-setup.sh" />
- <option name="post-push" value="chmod 755 /data/local/tmp/perf-setup.sh;/data/local/tmp/perf-setup.sh" />
+ <option name="push" value="perf-setup.sh->/data/local/tests/unrestricted/perf-setup.sh" />
+ <option name="post-push" value="chmod 755 /data/local/tests/unrestricted/perf-setup.sh;/data/local/tests/unrestricted/perf-setup.sh" />
</target_preparer>
-->
<test class="com.android.tradefed.testtype.GoogleBenchmarkTest" >
- <option name="native-benchmark-device-path" value="/data/local/tmp" />
+ <option name="native-benchmark-device-path" value="/data/local/tests/unrestricted" />
<option name="benchmark-module-name" value="bionic-spawn-benchmarks" />
<!-- The GoogleBenchmarkTest class ordinarily expects every file in the benchmark's
diff --git a/docs/clang_fortify_anatomy.md b/docs/clang_fortify_anatomy.md
new file mode 100644
index 0000000..4b95fdc
--- /dev/null
+++ b/docs/clang_fortify_anatomy.md
@@ -0,0 +1,841 @@
+*This document was originally written for a broad audience, and it was*
+*determined that it'd be good to hold in Bionic's docs, too. Due to the*
+*ever-changing nature of code, it tries to link to a stable tag of*
+*Bionic's libc, rather than the live code in Bionic. Same for Clang.*
+*Reader beware. :)*
+
+# The Anatomy of Clang FORTIFY
+
+## Objective
+
+The intent of this document is to run through the minutiae of how Clang FORTIFY
+actually works in Bionic at the time of writing. Other FORTIFY implementations
+that target Clang should use very similar mechanics. This document exists in part
+because many Clang-specific features serve multiple purposes simultaneously, so
+getting up-to-speed on how things function can be quite difficult.
+
+## Background
+
+FORTIFY is a broad suite of extensions to libc aimed at catching misuses of
+common library functions. Textually, these extensions exist purely in libc, but
+all implementations of FORTIFY rely heavily on C language extensions in order
+to function at all.
+
+Broadly, FORTIFY implementations try to guard against many misuses of C
+standard(-ish) libraries:
+- Buffer overruns in functions where pointers+sizes are passed (e.g., `memcpy`,
+ `poll`), or where sizes exist implicitly (e.g., `strcpy`).
+- Arguments with incorrect values passed to libc functions (e.g.,
+ out-of-bounds bits in `umask`).
+- Missing arguments to functions (e.g., `open()` with `O_CREAT`, but no mode
+ bits).
+
+FORTIFY is traditionally enabled by passing `-D_FORTIFY_SOURCE=N` to your
+compiler. `N==0` disables FORTIFY, whereas `N==1`, `N==2`, and `N==3` enable
+increasingly strict versions of it. In general, FORTIFY doesn't require user
+code changes; that said, some code patterns
+are [incompatible with stricter versions of FORTIFY checking]. This is largely
+because FORTIFY has significant flexibility in what it considers to be an
+"out-of-bounds" access.
+
+FORTIFY implementations use a mix of compiler diagnostics and runtime checks to
+flag and/or mitigate the impacts of the misuses mentioned above.
+
+Further, given FORTIFY's design, the effectiveness of FORTIFY is a function of
+-- among other things -- the optimization level you're compiling your code at.
+Many FORTIFY implementations are implicitly disabled when building with `-O0`,
+since FORTIFY's design for both Clang and GCC relies on optimizations in order
+to provide useful run-time checks. For the purpose of this document, all
+analysis of FORTIFY functions and commentary on builtins assume that code is
+being built with some optimization level > `-O0`.
+
+### A note on GCC
+
+This document talks specifically about Bionic's FORTIFY implementation targeted
+at Clang. While GCC also provides a set of language extensions necessary to
+implement FORTIFY, these tools are different from what Clang offers. This
+divergence is an artifact of Clang and GCC's differing architecture as
+compilers.
+
+Textually, quite a bit can be shared between a FORTIFY implementation for GCC
+and one for Clang (e.g., see [ChromeOS' Glibc patch]), but this kind of sharing
+requires things like macros that expand to unbalanced braces depending on your
+compiler:
+
+```c
+/*
+ * Highly simplified; if you're interested in FORTIFY's actual implementation,
+ * please see the patch linked above.
+ */
+#ifdef __clang__
+# define FORTIFY_PRECONDITIONS
+# define FORTIFY_FUNCTION_END
+#else
+# define FORTIFY_PRECONDITIONS {
+# define FORTIFY_FUNCTION_END }
+#endif
+
+/*
+ * FORTIFY_WARNING_ONLY_IF_SIZE_OF_BUF_LESS_THAN is not defined, due to its
+ * complexity and irrelevance. It turns into a compile-time warning if the
+ * compiler can determine `*buf` has fewer than `size` bytes available.
+ */
+
+char *getcwd(char *buf, size_t size)
+FORTIFY_PRECONDITIONS
+ FORTIFY_WARNING_ONLY_IF_SIZE_OF_BUF_LESS_THAN(buf, size, "`buf` is too smol.")
+{
+ // Actual shared function implementation goes here.
+}
+FORTIFY_FUNCTION_END
+```
+
+All talk of GCC-focused implementations and how to merge Clang and GCC
+implementations is out-of-scope for this doc, however.
+
+## The Life of a Clang FORTIFY Function
+
+As referenced in the Background section, FORTIFY performs many different checks
+for many functions. This section intends to go through real-world examples of
+FORTIFY functions in Bionic, breaking down how each part of these functions
+work, and how the pieces fit together to provide FORTIFY-like functionality.
+
+While FORTIFY implementations may differ between stdlibs, they broadly follow
+the same patterns when implementing their checks for Clang, and they try to
+make similar promises with respect to FORTIFY compiling to be zero-overhead in
+some cases, etc. Moreover, while this document specifically examines Bionic,
+many stdlibs will operate _very similarly_ to Bionic in their Clang FORTIFY
+implementations.
+
+**In general, when reading the below, be prepared for exceptions, subtlety, and
+corner cases. The individual function breakdowns below try to not offer
+redundant information. Each one focuses on different aspects of FORTIFY.**
+
+### Terminology
+
+Because FORTIFY should be mostly transparent to developers, there are inherent
+naming collisions here: `memcpy(x, y, z)` turns into fundamentally different
+generated code depending on the value of `_FORTIFY_SOURCE`. Further, said
+`memcpy` call with `_FORTIFY_SOURCE` enabled needs to be able to refer to the
+`memcpy` that would have been called, had `_FORTIFY_SOURCE` been disabled.
+Hence, the following convention is followed in the subsections below for all
+prose (namely, multiline code blocks are exempted from this):
+
+- Standard library function names preceded by `__builtin_` refer to the use of
+ the function with `_FORTIFY_SOURCE` disabled.
+- Standard library function names without a prefix refer to the use of the
+ function with `_FORTIFY_SOURCE` enabled.
+
+This convention also applies in `clang`. `__builtin_memcpy` will always call
+`memcpy` as though `_FORTIFY_SOURCE` were disabled.
+
+## Breakdown of `mempcpy`
+
+The [FORTIFY'ed version of `mempcpy`] is a full, featureful example of a
+FORTIFY'ed function from Bionic. From the user's perspective, it supports a few
+things:
+- Producing a compile-time error if the number of bytes to copy trivially
+ exceeds the number of bytes available at the destination pointer.
+- If the `mempcpy` has the potential to write to more bytes than what is
+ available at the destination, a run-time check is inserted to crash the
+ program if more bytes are written than what is allowed.
+- Compiling away to be zero overhead when none of the buffer sizes can be
+ determined at compile-time[^1].
+
+The declaration in Bionic's headers for `__builtin_mempcpy` is:
+```c
+void* mempcpy(void* __dst, const void* __src, size_t __n) __INTRODUCED_IN(23);
+```
+
+Which is annotated with nothing special, except for Bionic's versioner, which
+is Android-specific (and orthogonal to FORTIFY anyway), so it will be ignored.
+
+The [source for `mempcpy`] in Bionic's headers for is:
+```c
+__BIONIC_FORTIFY_INLINE
+void* mempcpy(void* const dst __pass_object_size0, const void* src, size_t copy_amount)
+ __overloadable
+ __clang_error_if(__bos_unevaluated_lt(__bos0(dst), copy_amount),
+ "'mempcpy' called with size bigger than buffer") {
+#if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
+ size_t bos_dst = __bos0(dst);
+ if (!__bos_trivially_ge(bos_dst, copy_amount)) {
+ return __builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);
+ }
+#endif
+ return __builtin_mempcpy(dst, src, copy_amount);
+}
+```
+
+Expanding some of the important macros here, this function expands to roughly:
+```c
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+void* mempcpy(
+ void* const dst __attribute__((pass_object_size(0))),
+ const void* src,
+ size_t copy_amount)
+ __attribute__((overloadable))
+ __attribute__((diagnose_if(
+ __builtin_object_size(dst, 0) != -1 && __builtin_object_size(dst, 0) <= copy_amount),
+ "'mempcpy' called with size bigger than buffer"))) {
+#if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
+ size_t bos_dst = __builtin_object_size(dst, 0);
+ if (!(__bos_trivially_ge(bos_dst, copy_amount))) {
+ return __builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);
+ }
+#endif
+ return __builtin_mempcpy(dst, src, copy_amount);
+}
+```
+
+So let's walk through this step by step, to see how FORTIFY does what it says on
+the tin here.
+
+[^1]: "Zero overhead" in a way [similar to C++11's `std::unique_ptr`]: this will
+turn into a direct call `__builtin_mempcpy` (or an optimized form thereof) with
+no other surrounding checks at runtime. However, the additional complexity may
+hinder optimizations that are performed before the optimizer can prove that the
+`if (...) { ... }` can be optimized out. Depending on how late this happens,
+the additional complexity may skew inlining costs, hide opportunities for e.g.,
+`memcpy` coalescing, etc etc.
+
+### How does Clang select `mempcpy`?
+
+First, it's critical to notice that `mempcpy` is marked `overloadable`. This
+function is a `static inline __attribute__((always_inline))` overload of
+`__builtin_mempcpy`:
+- `__attribute__((overloadable))` allows us to perform overloading in C.
+- `__attribute__((overloadable))` mangles all calls to functions marked with
+ `__attribute__((overloadable))`.
+- `__attribute__((overloadable))` allows exactly one function signature with a
+ given name to not be marked with `__attribute__((overloadable))`. Calls to
+ this overload will not be mangled.
+
+Second, one might note that this `mempcpy` implementation has the same C-level
+signature as `__builtin_mempcpy`. `pass_object_size` is a Clang attribute that
+is generally needed by FORTIFY, but it carries the side-effect that functions
+may be overloaded simply on the presence (or lack of presence) of
+`pass_object_size` attributes. Given two overloads of a function that only
+differ on the presence of `pass_object_size` attributes, the candidate with
+`pass_object_size` attributes is preferred.
+
+Finally, the prior paragraph gets thrown out if one tries to take the address of
+`mempcpy`. It is impossible to take the address of a function with one or more
+parameters that are annotated with `pass_object_size`. Hence,
+`&__builtin_mempcpy == &mempcpy`. Further, because this is an issue of overload
+resolution, `(&mempcpy)(x, y, z);` is functionally identical to
+`__builtin_mempcpy(x, y, z);`.
+
+All of this accomplishes the following:
+- Direct calls to `mempcpy` should call the FORTIFY-protected `mempcpy`.
+- Indirect calls to `&mempcpy` should call `__builtin_mempcpy`.
+
+### How does Clang offer compile-time diagnostics?
+
+Once one is convinced that the FORTIFY-enabled overload of `mempcpy` will be
+selected for direct calls, Clang's `diagnose_if` and `__builtin_object_size` do
+all of the work from there.
+
+Subtleties here primarily fall out of the discussion in the above section about
+`&__builtin_mempcpy == &mempcpy`:
+```c
+#define _FORTIFY_SOURCE 2
+#include <string.h>
+void example_code() {
+ char buf[4]; // ...Assume sizeof(char) == 1.
+ const char input_buf[] = "Hello, World";
+ mempcpy(buf, input_buf, 4); // Valid, no diagnostic issued.
+
+ mempcpy(buf, input_buf, 5); // Emits a compile-time error since sizeof(buf) < 5.
+ __builtin_mempcpy(buf, input_buf, 5); // No compile-time error.
+ (&mempcpy)(buf, input_buf, 5); // No compile-time error, since __builtin_mempcpy is selected.
+}
+```
+
+Otherwise, the rest of this subsection is dedicated to preliminary discussion
+about `__builtin_object_size`.
+
+Clang's frontend can do one of two things with `__builtin_object_size(p, n)`:
+- Evaluate it as a constant.
+ - This can either mean declaring that the number of bytes at `p` is definitely
+ impossible to know, so the default value is used, or the number of bytes at
+ `p` can be known without optimizations.
+- Declare that the expression cannot form a constant, and lower it to
+ `@llvm.objectsize`, which is discussed in depth later.
+
+In the examples above, since `diagnose_if` is evaluated with context from the
+caller, Clang should be able to trivially determine that `buf` refers to a
+`char` array with 4 elements.
+
+The primary consequence of the above is that diagnostics can only be emitted if
+no optimizations are required to detect a broken code pattern. To be specific,
+clang's constexpr evaluator must be able to determine the logical object that
+any given pointer points to in order to fold `__builtin_object_size` to a
+constant, non-default answer:
+
+```c
+#define _FORTIFY_SOURCE 2
+#include <string.h>
+void example_code() {
+ char buf[4]; // ...Assume sizeof(char) == 1.
+ const char input_buf[] = "Hello, World";
+ mempcpy(buf, input_buf, 4); // Valid, no diagnostic issued.
+ mempcpy(buf, input_buf, 5); // Emits a compile-time error since sizeof(buf) < 5.
+ char *buf_ptr = buf;
+ mempcpy(buf_ptr, input_buf, 5); // No compile-time error; `buf_ptr`'s target can't be determined.
+}
+```
+
+### How does Clang insert run-time checks?
+
+This section expands on the following statement: FORTIFY has zero runtime cost
+in instances where there is no chance of catching a bug at run-time. Otherwise,
+it introduces a tiny additional run-time cost to ensure that functions aren't
+misused.
+
+In prior sections, the following was established:
+- `overloadable` and `pass_object_size` prompt Clang to always select this
+ overload of `mempcpy` over `__builtin_mempcpy` for direct calls.
+- If a call to `mempcpy` was trivially broken, Clang would produce a
+ compile-time error, rather than producing a binary.
+
+Hence, the case we're interested in here is one where Clang's frontend selected
+a FORTIFY'ed function's implementation for a function call, but was unable to
+find anything seriously wrong with said function call. Since the frontend is
+powerless to detect bugs at this point, our focus shifts to the mechanisms that
+LLVM uses to support FORTIFY.
+
+Going back to Bionic's `mempcpy` implementation, we have the following (ignoring
+diagnose_if and assuming run-time checks are enabled):
+```c
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+void* mempcpy(
+ void* const dst __attribute__((pass_object_size(0))),
+ const void* src,
+ size_t copy_amount)
+ __attribute__((overloadable)) {
+ size_t bos_dst = __builtin_object_size(dst, 0);
+ if (bos_dst != -1 &&
+ !(__builtin_constant_p(copy_amount) && bos_dst >= copy_amount)) {
+ return __builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);
+ }
+ return __builtin_mempcpy(dst, src, copy_amount);
+}
+```
+
+In other words, we have a `static`, `always_inline` function which:
+- If `__builtin_object_size(dst, 0)` cannot be determined (in which case, it
+ returns -1), calls `__builtin_mempcpy`.
+- Otherwise, if `copy_amount` can be folded to a constant, and if
+ `__builtin_object_size(dst, 0) >= copy_amount`, calls `__builtin_mempcpy`.
+- Otherwise, calls `__builtin___mempcpy_chk`.
+
+
+How can this be "zero overhead"? Let's focus on the following part of the
+function:
+
+```c
+ size_t bos_dst = __builtin_object_size(dst, 0);
+ if (bos_dst != -1 &&
+ !(__builtin_constant_p(copy_amount) && bos_dst >= copy_amount)) {
+```
+
+If Clang's frontend cannot determine a value for `__builtin_object_size`, Clang
+lowers it to LLVM's `@llvm.objectsize` intrinsic. The `@llvm.objectsize`
+invocation corresponding to `__builtin_object_size(p, 0)` is guaranteed to
+always fold to a constant value by the time LLVM emits machine code.
+
+Hence, `bos_dst` is guaranteed to be a constant; if it's -1, the above branch
+can be eliminated entirely, since it folds to `if (false && ...)`. Further, the
+RHS of the `&&` in this branch has us call `__builtin_mempcpy` if `copy_amount`
+is a known value less than `bos_dst` (yet another constant value). Therefore,
+the entire condition is always knowable when LLVM is done with LLVM IR-level
+optimizations, so no condition is ever emitted to machine code in practice.
+
+#### Why is "zero overhead" in quotes? Why is `unique_ptr` relevant?
+
+`__builtin_object_size` and `__builtin_constant_p` are forced to be constants
+after most optimizations take place. Until LLVM replaces both of these with
+constants and optimizes them out, we have additional branches and function calls
+in our IR. This can have negative effects, such as distorting inlining costs and
+inhibiting optimizations that are conservative around branches in control-flow.
+
+So FORTIFY is free in these cases _in isolation of any of the code around it_.
+Due to its implementation, it may impact the optimizations that occur on code
+around the literal call to the FORTIFY-hardened libc function.
+
+`unique_ptr` was just the first thing that came to the author's mind for "the
+type should be zero cost with any level of optimization enabled, but edge-cases
+might make it only-mostly-free to use."
+
+### How is checking actually performed?
+
+In cases where checking can be performed (e.g., where we call
+`__builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);`), Bionic provides [an
+implementation for `__mempcpy_chk`]. This is:
+
+```c
+extern "C" void* __mempcpy_chk(void* dst, const void* src, size_t count, size_t dst_len) {
+ __check_count("mempcpy", "count", count);
+ __check_buffer_access("mempcpy", "write into", count, dst_len);
+ return mempcpy(dst, src, count);
+}
+```
+This function itself boils down to a few small branches which abort the program
+if they fail, and a direct call to `__builtin_mempcpy`.
+
+### Wrapping up
+
+In the above breakdown, it was shown how Clang and Bionic work together to:
+- represent FORTIFY-hardened overloads of functions,
+- report misuses of stdlib functions at compile-time, and
+- insert run-time checks for uses of functions that might be incorrect, but only
+ if we have the potential of proving the incorrectness of these.
+
+## Breakdown of open
+
+In Bionic, the [FORTIFY'ed implementation of `open`] is quite large. Much like
+`mempcpy`, the `__builtin_open` declaration is simple:
+
+```c
+int open(const char* __path, int __flags, ...);
+```
+
+With some macros expanded, the FORTIFY-hardened header implementation is:
+```c
+int __open_2(const char*, int);
+int __open_real(const char*, int, ...) __asm__(open);
+
+#define __open_modes_useful(flags) (((flags) & O_CREAT) || ((flags) & O_TMPFILE) == O_TMPFILE)
+
+static
+int open(const char* pathname, int flags, mode_t modes, ...) __overloadable
+ __attribute__((diagnose_if(1, "error", "too many arguments")));
+
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+int open(const char* const __attribute__((pass_object_size(1))) pathname, int flags)
+ __attribute__((overloadable))
+ __attribute__((diagnose_if(
+ __open_modes_useful(flags),
+ "error",
+ "'open' called with O_CREAT or O_TMPFILE, but missing mode"))) {
+#if __ANDROID_API__ >= 17 && __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
+ return __open_2(pathname, flags);
+#else
+ return __open_real(pathname, flags);
+#endif
+}
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+int open(const char* const __attribute__((pass_object_size(1))) pathname, int flags, mode_t modes)
+ __attribute__((overloadable))
+ __clang_warning_if(!__open_modes_useful(flags) && modes,
+ "'open' has superfluous mode bits; missing O_CREAT?") {
+ return __open_real(pathname, flags, modes);
+}
+```
+
+Which may be a lot to take in.
+
+Before diving too deeply, please note that the remainder of these subsections
+assume that the programmer didn't make any egregious typos. Moreover, there's no
+real way that Bionic tries to prevent calls to `open` like
+`open("foo", 0, "how do you convert a const char[N] to mode_t?");`. The only
+real C-compatible solution the author can think of is "stamp out many overloads
+to catch sort-of-common instances of this very uncommon typo." This isn't great.
+
+More directly, no effort is made below to recognize calls that, due to
+incompatible argument types, cannot go to any `open` implementation other than
+`__builtin_open`, since it's recognized right here. :)
+
+### Implementation breakdown
+
+This `open` implementation does a few things:
+- Turns calls to `open` with too many arguments into a compile-time error.
+- Diagnoses calls to `open` with missing modes at compile-time and run-time
+ (both cases turn into errors).
+- Emits warnings on calls to `open` with useless mode bits, unless the mode bits
+ are all 0.
+
+One common bit of code not explained below is the `__open_real` declaration above:
+```c
+int __open_real(const char*, int, ...) __asm__(open);
+```
+
+This exists as a way for us to call `__builtin_open` without needing clang to
+have a pre-defined `__builtin_open` function.
+
+#### Compile-time error on too many arguments
+
+```c
+static
+int open(const char* pathname, int flags, mode_t modes, ...) __overloadable
+ __attribute__((diagnose_if(1, "error", "too many arguments")));
+```
+
+Which matches most calls to open that supply too many arguments, since
+`int(const char *, int, ...)` matches less strongly than
+`int(const char *, int, mode_t, ...)` for calls where the 3rd arg can be
+converted to `mode_t` without too much effort. Because of the `diagnose_if`
+attribute, all of these calls turn into compile-time errors.
+
+#### Compile-time or run-time error on missing arguments
+The following overload handles all two-argument calls to `open`.
+```c
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+int open(const char* const __attribute__((pass_object_size(1))) pathname, int flags)
+ __attribute__((overloadable))
+ __attribute__((diagnose_if(
+ __open_modes_useful(flags),
+ "error",
+ "'open' called with O_CREAT or O_TMPFILE, but missing mode"))) {
+#if __ANDROID_API__ >= 17 && __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
+ return __open_2(pathname, flags);
+#else
+ return __open_real(pathname, flags);
+#endif
+}
+```
+
+Like `mempcpy`, `diagnose_if` handles emitting a compile-time error if the call
+to `open` is broken in a way that's visible to Clang's frontend. This
+essentially boils down to "`open` is being called with a `flags` value that
+requires mode bits to be set."
+
+If that fails to catch a bug, we [unconditionally call `__open_2`], which
+performs a run-time check:
+```c
+int __open_2(const char* pathname, int flags) {
+ if (needs_mode(flags)) __fortify_fatal("open: called with O_CREAT/O_TMPFILE but no mode");
+ return FDTRACK_CREATE_NAME("open", __openat(AT_FDCWD, pathname, force_O_LARGEFILE(flags), 0));
+}
+```
+
+#### Compile-time warning if modes are pointless
+
+Finally, we have the following `open` call:
+```c
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+int open(const char* const __attribute__((pass_object_size(1))) pathname, int flags, mode_t modes)
+ __attribute__((overloadable))
+ __clang_warning_if(!__open_modes_useful(flags) && modes,
+ "'open' has superfluous mode bits; missing O_CREAT?") {
+ return __open_real(pathname, flags, modes);
+}
+```
+
+This simply issues a warning if Clang's frontend can determine that `flags`
+isn't necessary. Due to conventions in existing code, a `modes` value of `0` is
+not diagnosed.
+
+#### What about `&open`?
+One yet-unaddressed aspect of the above is how `&open` works. This is thankfully
+a short answer:
+- It happens that `open` takes a parameter of type `const char*`.
+- It happens that `pass_object_size` -- an attribute only applicable to
+ parameters of type `T*` -- makes it impossible to take the address of a
+ function.
+
+Since clang doesn't support a "this function should never have its address
+taken," attribute, Bionic uses the next best thing: `pass_object_size`. :)
+
+## Breakdown of poll
+
+(Preemptively: at the time of writing, Clang has no literal `__builtin_poll`
+builtin. `__builtin_poll` is referenced below to remain consistent with the
+convention established in the Terminology section.)
+
+Bionic's `poll` implementation is closest to `mempcpy` above, though it has a
+few interesting aspects worth examining.
+
+The [full header implementation of `poll`] is, with some macros expanded:
+```c
+#define __bos_fd_count_trivially_safe(bos_val, fds, fd_count) \
+ ((bos_val) == -1) || \
+ (__builtin_constant_p(fd_count) && \
+ (bos_val) >= sizeof(*fds) * (fd_count)))
+
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+int poll(struct pollfd* const fds __attribute__((pass_object_size(1))), nfds_t fd_count, int timeout)
+ __attribute__((overloadable))
+ __attriubte__((diagnose_if(
+ __builtin_object_size(fds, 1) != -1 && __builtin_object_size(fds, 1) < sizeof(*fds) * fd_count,
+ "error",
+ "in call to 'poll', fd_count is larger than the given buffer"))) {
+ size_t bos_fds = __builtin_object_size(fds, 1);
+ if (!__bos_fd_count_trivially_safe(bos_fds, fds, fd_count)) {
+ return __poll_chk(fds, fd_count, timeout, bos_fds);
+ }
+ return (&poll)(fds, fd_count, timeout);
+}
+```
+
+To get the commonality with `mempcpy` and `open` out of the way:
+- This function is an overload with `__builtin_poll`.
+- The signature is the same, modulo the presence of a `pass_object_size`
+ attribute. Hence, for direct calls, overload resolution will always prefer it
+ over `__builtin_poll`. Taking the address of `poll` is forbidden, so all
+ references to `&poll` actually reference `__builtin_poll`.
+- When `fds` is too small to hold `fd_count` `pollfd`s, Clang will emit a
+ compile-time error if possible using `diagnose_if`.
+- If this can't be observed until run-time, `__poll_chk` verifies this.
+- When `fds` is a constant according to `__builtin_constant_p`, this always
+ compiles into `__poll_chk` for always-broken calls to `poll`, or
+ `__builtin_poll` for always-safe calls to `poll`.
+
+The critical bits to highlight here are on this line:
+```c
+int poll(struct pollfd* const fds __attribute__((pass_object_size(1))), nfds_t fd_count, int timeout)
+```
+
+And this line:
+```c
+ return (&poll)(fds, fd_count, timeout);
+```
+
+Starting with the simplest, we call `__builtin_poll` with `(&poll)(...);`. As
+referenced above, taking the address of an overloaded function where all but one
+overload has a `pass_object_size` attribute on one or more parameters always
+resolves to the function without any `pass_object_size` attributes.
+
+The other line deserves a section. The subtlety of it is almost entirely in the
+use of `pass_object_size(1)` instead of `pass_object_size(0)`. on the `fds`
+parameter, and the corresponding use of `__builtin_object_size(fds, 1);` in the
+body of `poll`.
+
+### Subtleties of __builtin_object_size(p, N)
+
+Earlier in this document, it was said that a full description of each
+attribute/builtin necessary to power FORTIFY was out of scope. This is... only
+somewhat the case when we talk about `__builtin_object_size` and
+`pass_object_size`, especially when their second argument is `1`.
+
+#### tl;dr
+`__builtin_object_size(p, N)` and `pass_object_size(N)`, where `(N & 1) == 1`,
+can only be accurately determined by Clang. LLVM's `@llvm.objectsize` intrinsic
+ignores the value of `N & 1`, since handling `(N & 1) == 1` accurately requires
+data that's currently entirely inaccessible to LLVM, and that is difficult to
+preserve through LLVM's optimization passes.
+
+`pass_object_size`'s "lifting" of the evaluation of
+`__builtin_object_size(p, N)` to the caller is critical, since it allows Clang
+full visibility into the expression passed to e.g., `poll(&foo->bar, baz, qux)`.
+It's not a perfect solution, but it allows `N == 1` to be fully accurate in at
+least some cases.
+
+#### Background
+Clang's implementation of `__builtin_object_size` aims to be compatible with
+GCC's, which has [a decent bit of documentation]. Put simply,
+`__builtin_object_size(p, N)` is intended to evaluate at compile-time how many
+bytes can be accessed after `p` in a well-defined way. Straightforward examples
+of this are:
+```c
+char buf[8];
+assert(__builtin_object_size(buf, N) == 8);
+assert(__builtin_object_size(buf + 1, N) == 7);
+```
+
+This should hold for all values of N that are valid to pass to
+`__builtin_object_size`. The `N` value of `__builtin_object_size` is a mask of
+settings.
+
+##### (N & 2) == ?
+
+This is mostly for completeness sake; in Bionic's FORTIFY implementation, N is
+always either 0 or 1.
+
+If there are multiple possible values of `p` in a call to
+`__builtin_object_size(p, N)`, the second bit in `N` determines the behavior of
+the compiler. If `(N & 2) == 0`, `__builtin_object_size` should return the
+greatest possible size for each possible value of `p`. Otherwise, it should
+return the least possible value. For example:
+
+```c
+char smol_buf[7];
+char buf[8];
+char *p = rand() ? smol_buf : buf;
+assert(__builtin_object_size(p, 0) == 8);
+assert(__builtin_object_size(p, 2) == 7);
+```
+
+##### (N & 1) == 0
+
+`__builtin_object_size(p, 0)` is more or less as simple as the example in the
+Background section directly above. When Clang attempts to evaluate
+`__builtin_object_size(p, 0);` and when LLVM tries to determine the result of a
+corresponding `@llvm.objectsize` call to, they search for the storage underlying
+the pointer in question. If that can be determined, Clang or LLVM can provide an
+answer; otherwise, they cannot.
+
+##### (N & 1) == 1, and the true magic of pass_object_size
+
+`__builtin_object_size(p, 1)` has a less uniform implementation between LLVM and
+Clang. According to GCC's documentation, "If the least significant bit [of
+__builtin_object_size's second argument] is clear, objects are whole variables,
+if it is set, a closest surrounding subobject is considered the object a pointer
+points to."
+
+The "closest surrounding subobject," means that `(N & 1) == 1` depends on type
+information in order to operate in many cases. Consider the following examples:
+```c
+struct Foo {
+ int a;
+ int b;
+};
+
+struct Foo foo;
+assert(__builtin_object_size(&foo, 0) == sizeof(foo));
+assert(__builtin_object_size(&foo, 1) == sizeof(foo));
+assert(__builtin_object_size(&foo->a, 0) == sizeof(foo));
+assert(__builtin_object_size(&foo->a, 1) == sizeof(int));
+
+struct Foo foos[2];
+assert(__builtin_object_size(&foos[0], 0) == 2 * sizeof(foo));
+assert(__builtin_object_size(&foos[0], 1) == sizeof(foo));
+assert(__builtin_object_size(&foos[0]->a, 0) == 2 * sizeof(foo));
+assert(__builtin_object_size(&foos[0]->a, 1) == sizeof(int));
+```
+
+...And perhaps somewhat surprisingly:
+```c
+void example(struct Foo *foo) {
+ // (As a reminder, `-1` is "I don't know" when `(N & 2) == 0`.)
+ assert(__builtin_object_size(foo, 0) == -1);
+ assert(__builtin_object_size(foo, 1) == -1);
+ assert(__builtin_object_size(foo->a, 0) == -1);
+ assert(__builtin_object_size(foo->a, 1) == sizeof(int));
+}
+```
+
+In Clang, [this type-aware requirement poses problems for us]: Clang's frontend
+knows everything we could possibly want about the types of variables, but
+optimizations are only performed by LLVM. LLVM has no reliable source for C or
+C++ data types, so calls to `__builtin_object_size(p, N)` that cannot be
+resolved by clang are lowered to the equivalent of
+`__builtin_object_size(p, N & ~1)` in LLVM IR.
+
+Moreover, Clang's frontend is the best-equipped part of the compiler to
+accurately determine the answer for `__builtin_object_size(p, N)`, given we know
+what `p` is. LLVM is the best-equipped part of the compiler to determine the
+value of `p`. This ordering issue is unfortunate.
+
+This is where `pass_object_size(N)` comes in. To summarize [the docs for
+`pass_object_size`], it evaluates `__builtin_object_size(p, N)` within the
+context of the caller of the function annotated with `pass_object_size`, and
+passes the value of that into the callee as an invisible parameter. All calls to
+`__builtin_object_size(parameter, N)` are substituted with references to this
+invisible parameter.
+
+Putting this plainly, Clang's frontend struggles to evaluate the following:
+```c
+int foo(void *p) {
+ return __builtin_object_size(p, 1);
+}
+
+void bar() {
+ struct { int i, j } k;
+ // The frontend can't figure this interprocedural objectsize out, so it gets lowered to
+ // LLVM, which determines that the answer here is sizeof(k).
+ int baz = foo(&k.i);
+}
+```
+
+However, with the magic of `pass_object_size`, we get one level of inlining to
+look through:
+```c
+int foo(void *const __attribute__((pass_object_size(1))) p) {
+ return __builtin_object_size(p, 1);
+}
+
+void bar() {
+ struct { int i, j } k;
+ // Due to pass_object_size, this is equivalent to:
+ // int baz = foo(&k.i, __builtin_object_size(&k.i, 1));
+ // ...and `int foo(void *)` is actually equivalent to:
+ // int foo(void *const, size_t size) {
+ // return size;
+ // }
+ int baz = foo(&k.i);
+}
+```
+
+So we can obtain an accurate result in this case.
+
+##### What about pass_object_size(0)?
+It's sort of tangential, but if you find yourself wondering about the utility of
+`pass_object_size(0)` ... it's somewhat split. `pass_object_size(0)` in Bionic's
+FORTIFY exists mostly for visual consistency, simplicity, and as a useful way to
+have e.g., `&mempcpy` == `&__builtin_mempcpy`.
+
+Outside of these fringe benefits, all of the functions with
+`pass_object_size(0)` on parameters are marked with `always_inline`, so
+"lifting" the `__builtin_object_size` call isn't ultimately very helpful. In
+theory, users can always have something like:
+
+```c
+// In some_header.h
+// This function does cool and interesting things with the `__builtin_object_size` of its parameter,
+// and is able to work with that as though the function were defined inline.
+void out_of_line_function(void *__attribute__((pass_object_size(0))));
+```
+
+Though the author isn't aware of uses like this in practice, beyond a few folks
+on LLVM's mailing list seeming interested in trying it someday.
+
+#### Wrapping up
+In the (long) section above, two things were covered:
+- The use of `(&poll)(...);` is a convenient shorthand for calling
+ `__builtin_poll`.
+- `__builtin_object_size(p, N)` with `(N & 1) == 1` is not easy for Clang to
+ answer accurately, since it relies on type info only available in the
+ frontend, and it sometimes relies on optimizations only available in the
+ middle-end. `pass_object_size` helps mitigate this.
+
+## Miscellaneous Notes
+The above should be a roughly comprehensive view of how FORTIFY works in the
+real world. The main thing it fails to mention is the use of [the `diagnose_as_builtin` attribute] in Clang.
+
+As time has moved on, Clang has increasingly gained support for emitting
+warnings that were previously emitted by FORTIFY machinery.
+`diagnose_as_builtin` allows us to remove the `diagnose_if`s from some of the
+`static inline` overloads of stdlib functions above, so Clang may diagnose them
+instead.
+
+Clang's built-in diagnostics are often better than `diagnose_if` diagnostics,
+since Clang can format its diagnostics to include e.g., information about the
+sizes of buffers in a suspect call to a function. `diagnose_if` can only have
+the compiler output constant strings.
+
+[ChromeOS' Glibc patch]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/90fa9b27731db10a6010c7f7c25b24028145b091/sys-libs/glibc/files/local/glibc-2.33/0007-glibc-add-clang-style-FORTIFY.patch
+[FORTIFY'ed implementation of `open`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/include/bits/fortify/fcntl.h#41
+[FORTIFY'ed version of `mempcpy`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/include/bits/fortify/string.h#45
+[a decent bit of documentation]: https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+[an implementation for `__mempcpy_chk`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/bionic/fortify.cpp#501
+[full header implementation of `poll`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/include/bits/fortify/poll.h#43
+[incompatible with stricter versions of FORTIFY checking]: https://godbolt.org/z/fGfEYxfnf
+[similar to C++11's `std::unique_ptr`]: https://stackoverflow.com/questions/58339165/why-can-a-t-be-passed-in-register-but-a-unique-ptrt-cannot
+[source for `mempcpy`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/include/string.h#55
+[the `diagnose_as_builtin` attribute]: https://releases.llvm.org/14.0.0/tools/clang/docs/AttributeReference.html#diagnose-as-builtin
+[the docs for `pass_object_size`]: https://releases.llvm.org/14.0.0/tools/clang/docs/AttributeReference.html#pass-object-size-pass-dynamic-object-size
+[this type-aware requirement poses problems for us]: https://github.com/llvm/llvm-project/issues/55742
+[unconditionally call `__open_2`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/bionic/open.cpp#70
diff --git a/docs/status.md b/docs/status.md
index bf246a6..20a1309 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -29,6 +29,7 @@
* `gethostid`
* `shm_open`/`shm_unlink`
* `sockatmark`
+ * `ualarm`
Missing functionality:
* `<aio.h>`
@@ -50,6 +51,16 @@
Current libc symbols: https://android.googlesource.com/platform/bionic/+/master/libc/libc.map.txt
+New libc functions in U (API level 34):
+ * `close_range` and `copy_file_range` (Linux-specific GNU extensions).
+ * `memset_explicit` in <string.h> (C23 addition).
+ * `__freadahead` in <stdio_ext.h> (in musl but not glibc).
+
+New libc behavior in U (API level 34):
+ * Support for `%b` and `%B` in the printf/wprintf family, `%b` in the
+ scanf/wscanf family, and `0b` prefixes with base 0 in the strtol/wcstol
+ family.
+
New libc functions in T (API level 33):
* `backtrace`, `backtrace_symbols`, `backtrace_symbols_fd` (`<execinfo.h>`).
* New system call wrappers: `preadv2`, `preadv64v2`, `pwritev2`,
diff --git a/libc/Android.bp b/libc/Android.bp
index 97146aa..6042929 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -35,7 +35,7 @@
"stdio/stdio.cpp",
"stdio/stdio_ext.cpp",
"stdio/vfscanf.cpp",
- "stdio/vfwscanf.c",
+ "stdio/vfwscanf.cpp",
]
// off64_t/time64_t support on LP32.
@@ -95,7 +95,6 @@
header_libs: [
"libc_headers",
- "gwp_asan_headers",
"liblog_headers", // needed by bionic/libc/async_safe/include
],
export_header_lib_headers: [
@@ -198,6 +197,9 @@
arm64: {
srcs: ["arch-arm64/bionic/__set_tls.c"],
},
+ riscv64: {
+ srcs: ["arch-riscv64/bionic/__set_tls.c"],
+ },
x86: {
srcs: [
"arch-x86/bionic/__libc_init_sysinfo.cpp",
@@ -259,18 +261,22 @@
// Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
"-DSTD_INSPIRED",
// Obviously, we want to be thread-safe.
- "-DTHREAD_SAFE",
+ "-DTHREAD_SAFE=1",
// The name of the tm_gmtoff field in our struct tm.
"-DTM_GMTOFF=tm_gmtoff",
+ // TZDEFAULT is not applicable to Android as there is no one file per time zone mapping
+ "-DTZDEFAULT=NULL",
// Where we store our tzdata.
"-DTZDIR=\"/system/usr/share/zoneinfo\"",
// Include `tzname`, `timezone`, and `daylight` globals.
"-DHAVE_POSIX_DECLS=0",
- "-DUSG_COMPAT=1",
+ "-DUSG_COMPAT=2",
+ "-DHAVE_TZNAME=2",
+ // stdbool.h is available
+ "-DHAVE_STDBOOL_H",
// Use the empty string (instead of " ") as the timezone abbreviation
// fallback.
"-DWILDABBR=\"\"",
- "-DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU",
"-Dlint",
],
@@ -372,7 +378,6 @@
"upstream-freebsd/lib/libc/string/wcscat.c",
"upstream-freebsd/lib/libc/string/wcscpy.c",
"upstream-freebsd/lib/libc/string/wmemcmp.c",
- "upstream-freebsd/lib/libc/string/wmemset.c",
],
},
},
@@ -497,13 +502,7 @@
"upstream-openbsd/lib/libc/locale/mbstowcs.c",
"upstream-openbsd/lib/libc/locale/mbtowc.c",
"upstream-openbsd/lib/libc/locale/wcscoll.c",
- "upstream-openbsd/lib/libc/locale/wcstoimax.c",
- "upstream-openbsd/lib/libc/locale/wcstol.c",
- "upstream-openbsd/lib/libc/locale/wcstoll.c",
"upstream-openbsd/lib/libc/locale/wcstombs.c",
- "upstream-openbsd/lib/libc/locale/wcstoul.c",
- "upstream-openbsd/lib/libc/locale/wcstoull.c",
- "upstream-openbsd/lib/libc/locale/wcstoumax.c",
"upstream-openbsd/lib/libc/locale/wcsxfrm.c",
"upstream-openbsd/lib/libc/locale/wctob.c",
"upstream-openbsd/lib/libc/locale/wctomb.c",
@@ -665,6 +664,17 @@
"upstream-openbsd/lib/libc/string/strncmp.c",
],
},
+ riscv64: {
+ srcs: [
+ "arch-riscv64/string/memset_chk.c",
+ "upstream-freebsd/lib/libc/string/memcmp.c",
+ "upstream-freebsd/lib/libc/string/memcpy.c",
+ "upstream-freebsd/lib/libc/string/memmove.c",
+ "upstream-freebsd/lib/libc/string/memset.c",
+ "upstream-openbsd/lib/libc/string/strcmp.c",
+ "upstream-openbsd/lib/libc/string/strlen.c",
+ ],
+ },
x86: {
exclude_srcs: [
"upstream-openbsd/lib/libc/string/memchr.c",
@@ -910,6 +920,16 @@
],
},
+ riscv64: {
+ srcs: [
+ "arch-riscv64/bionic/__bionic_clone.S",
+ "arch-riscv64/bionic/_exit_with_stack_teardown.S",
+ "arch-riscv64/bionic/setjmp.S",
+ "arch-riscv64/bionic/syscall.S",
+ "arch-riscv64/bionic/vfork.S",
+ ],
+ },
+
x86: {
srcs: [
"arch-x86/generic/string/memcmp.S",
@@ -923,24 +943,42 @@
"arch-x86/generic/string/wcscat.c",
"arch-x86/generic/string/wcscpy.c",
"arch-x86/generic/string/wmemcmp.c",
- "arch-x86/generic/string/wmemset.c",
- "arch-x86/atom/string/sse2-memchr-atom.S",
- "arch-x86/atom/string/sse2-memrchr-atom.S",
- "arch-x86/atom/string/sse2-strchr-atom.S",
- "arch-x86/atom/string/sse2-strnlen-atom.S",
- "arch-x86/atom/string/sse2-strrchr-atom.S",
- "arch-x86/atom/string/sse2-wcschr-atom.S",
- "arch-x86/atom/string/sse2-wcsrchr-atom.S",
- "arch-x86/atom/string/sse2-wcslen-atom.S",
- "arch-x86/atom/string/sse2-wcscmp-atom.S",
- "arch-x86/silvermont/string/sse2-memmove-slm.S",
- "arch-x86/silvermont/string/sse2-memset-slm.S",
- "arch-x86/silvermont/string/sse2-stpcpy-slm.S",
- "arch-x86/silvermont/string/sse2-stpncpy-slm.S",
- "arch-x86/silvermont/string/sse2-strcpy-slm.S",
- "arch-x86/silvermont/string/sse2-strlen-slm.S",
- "arch-x86/silvermont/string/sse2-strncpy-slm.S",
+ "arch-x86/string/sse2-memchr-atom.S",
+ "arch-x86/string/sse2-memmove-slm.S",
+ "arch-x86/string/sse2-memrchr-atom.S",
+ "arch-x86/string/sse2-memset-atom.S",
+ "arch-x86/string/sse2-memset-slm.S",
+ "arch-x86/string/sse2-stpcpy-slm.S",
+ "arch-x86/string/sse2-stpncpy-slm.S",
+ "arch-x86/string/sse2-strchr-atom.S",
+ "arch-x86/string/sse2-strcpy-slm.S",
+ "arch-x86/string/sse2-strlen-slm.S",
+ "arch-x86/string/sse2-strncpy-slm.S",
+ "arch-x86/string/sse2-strnlen-atom.S",
+ "arch-x86/string/sse2-strrchr-atom.S",
+ "arch-x86/string/sse2-wcschr-atom.S",
+ "arch-x86/string/sse2-wcsrchr-atom.S",
+ "arch-x86/string/sse2-wcslen-atom.S",
+ "arch-x86/string/sse2-wcscmp-atom.S",
+ "arch-x86/string/sse2-strlen-atom.S",
+
+ "arch-x86/string/ssse3-memcmp-atom.S",
+ "arch-x86/string/ssse3-memmove-atom.S",
+ "arch-x86/string/ssse3-strcat-atom.S",
+ "arch-x86/string/ssse3-strcmp-atom.S",
+ "arch-x86/string/ssse3-strcpy-atom.S",
+ "arch-x86/string/ssse3-strlcat-atom.S",
+ "arch-x86/string/ssse3-strlcpy-atom.S",
+ "arch-x86/string/ssse3-strncat-atom.S",
+ "arch-x86/string/ssse3-strncmp-atom.S",
+ "arch-x86/string/ssse3-strncpy-atom.S",
+ "arch-x86/string/ssse3-wcscat-atom.S",
+ "arch-x86/string/ssse3-wcscpy-atom.S",
+ "arch-x86/string/ssse3-wmemcmp-atom.S",
+
+ "arch-x86/string/sse4-memcmp-slm.S",
+ "arch-x86/string/sse4-wmemcmp-slm.S",
"arch-x86/bionic/__bionic_clone.S",
"arch-x86/bionic/_exit_with_stack_teardown.S",
@@ -950,32 +988,6 @@
"arch-x86/bionic/syscall.S",
"arch-x86/bionic/vfork.S",
"arch-x86/bionic/__x86.get_pc_thunk.S",
-
- // ssse3 functions
- "arch-x86/atom/string/ssse3-strcat-atom.S",
- "arch-x86/atom/string/ssse3-strcmp-atom.S",
- "arch-x86/atom/string/ssse3-strlcat-atom.S",
- "arch-x86/atom/string/ssse3-strlcpy-atom.S",
- "arch-x86/atom/string/ssse3-strncat-atom.S",
- "arch-x86/atom/string/ssse3-strncmp-atom.S",
- "arch-x86/atom/string/ssse3-wcscat-atom.S",
- "arch-x86/atom/string/ssse3-wcscpy-atom.S",
-
- // sse4 functions
- "arch-x86/silvermont/string/sse4-memcmp-slm.S",
- "arch-x86/silvermont/string/sse4-wmemcmp-slm.S",
-
- // atom functions
- "arch-x86/atom/string/sse2-memset-atom.S",
- "arch-x86/atom/string/sse2-strlen-atom.S",
- "arch-x86/atom/string/ssse3-memcmp-atom.S",
- "arch-x86/atom/string/ssse3-memmove-atom.S",
- "arch-x86/atom/string/ssse3-strcpy-atom.S",
- "arch-x86/atom/string/ssse3-strncpy-atom.S",
- "arch-x86/atom/string/ssse3-wmemcmp-atom.S",
-
- // avx2 functions
- "arch-x86/kabylake/string/avx2-wmemset-kbl.S",
],
exclude_srcs: [
@@ -986,6 +998,7 @@
},
x86_64: {
srcs: [
+ "arch-x86_64/string/avx2-memset-kbl.S",
"arch-x86_64/string/sse2-memmove-slm.S",
"arch-x86_64/string/sse2-memset-slm.S",
"arch-x86_64/string/sse2-stpcpy-slm.S",
@@ -998,7 +1011,6 @@
"arch-x86_64/string/sse4-memcmp-slm.S",
"arch-x86_64/string/ssse3-strcmp-slm.S",
"arch-x86_64/string/ssse3-strncmp-slm.S",
- "arch-x86_64/string/avx2-wmemset-kbl.S",
"arch-x86_64/bionic/__bionic_clone.S",
"arch-x86_64/bionic/_exit_with_stack_teardown.S",
@@ -1115,6 +1127,7 @@
"bionic/mbrtoc16.cpp",
"bionic/mbrtoc32.cpp",
"bionic/mempcpy.cpp",
+ "bionic/memset_explicit.cpp",
"bionic/mkdir.cpp",
"bionic/mkfifo.cpp",
"bionic/mknod.cpp",
@@ -1303,44 +1316,40 @@
name: "syscalls-arm.S",
out: ["syscalls-arm.S"],
srcs: ["SYSCALLS.TXT"],
- tool_files: [":bionic-gensyscalls"],
- cmd: "$(location :bionic-gensyscalls) arm $(in) > $(out)",
- bazel_module: {
- bp2build_available: true,
- }
+ tools: ["gensyscalls"],
+ cmd: "$(location gensyscalls) arm $(in) > $(out)",
}
genrule {
name: "syscalls-arm64.S",
out: ["syscalls-arm64.S"],
srcs: ["SYSCALLS.TXT"],
- tool_files: [":bionic-gensyscalls"],
- cmd: "$(location :bionic-gensyscalls) arm64 $(in) > $(out)",
- bazel_module: {
- bp2build_available: true,
- },
+ tools: ["gensyscalls"],
+ cmd: "$(location gensyscalls) arm64 $(in) > $(out)",
+}
+
+genrule {
+ name: "syscalls-riscv64.S",
+ out: ["syscalls-riscv64.S"],
+ srcs: ["SYSCALLS.TXT"],
+ tools: ["gensyscalls"],
+ cmd: "$(location gensyscalls) riscv64 $(in) > $(out)",
}
genrule {
name: "syscalls-x86.S",
out: ["syscalls-x86.S"],
srcs: ["SYSCALLS.TXT"],
- tool_files: [":bionic-gensyscalls"],
- cmd: "$(location :bionic-gensyscalls) x86 $(in) > $(out)",
- bazel_module: {
- bp2build_available: true,
- },
+ tools: ["gensyscalls"],
+ cmd: "$(location gensyscalls) x86 $(in) > $(out)",
}
genrule {
name: "syscalls-x86_64.S",
out: ["syscalls-x86_64.S"],
srcs: ["SYSCALLS.TXT"],
- tool_files: [":bionic-gensyscalls"],
- cmd: "$(location :bionic-gensyscalls) x86_64 $(in) > $(out)",
- bazel_module: {
- bp2build_available: true,
- },
+ tools: ["gensyscalls"],
+ cmd: "$(location gensyscalls) x86_64 $(in) > $(out)",
}
cc_library_static {
@@ -1353,6 +1362,9 @@
arm64: {
srcs: [":syscalls-arm64.S"],
},
+ riscv64: {
+ srcs: [":syscalls-riscv64.S"],
+ },
x86: {
srcs: [":syscalls-x86.S"],
},
@@ -1511,6 +1523,9 @@
name: "libc_static_dispatch",
arch: {
+ x86_64: {
+ srcs: ["arch-x86_64/static_function_dispatch.S"],
+ },
x86: {
srcs: ["arch-x86/static_function_dispatch.S"],
},
@@ -1536,6 +1551,9 @@
"-fno-jump-tables",
],
arch: {
+ x86_64: {
+ srcs: ["arch-x86_64/dynamic_function_dispatch.cpp"],
+ },
x86: {
srcs: ["arch-x86/dynamic_function_dispatch.cpp"],
},
@@ -1627,7 +1645,6 @@
"bionic/NetdClient.cpp",
"arch-common/bionic/crtend_so.S",
],
- bazel_module: { bp2build_available: true },
}
filegroup {
@@ -1638,7 +1655,6 @@
"bionic/malloc_common.cpp",
"bionic/malloc_limit.cpp",
],
- bazel_module: { bp2build_available: true },
}
filegroup {
@@ -1647,7 +1663,6 @@
"arch-arm/bionic/exidx_dynamic.c",
"arch-arm/bionic/atexit_legacy.c",
],
- bazel_module: { bp2build_available: true },
}
// ========================================================
@@ -1686,8 +1701,8 @@
},
required: [
- "tzdata",
- "tz_version", // Version metadata for tzdata to help debugging.
+ "tzdata_prebuilt",
+ "tz_version_prebuilt", // Version metadata for tzdata to help debugging.
],
// Do not pack libc.so relocations; see http://b/20645321 for details.
@@ -1745,6 +1760,15 @@
keep_symbols: true,
},
},
+ riscv64: {
+ version_script: ":libc.riscv64.map",
+
+ // Leave the symbols in the shared library so that stack unwinders can produce
+ // meaningful name resolution.
+ strip: {
+ keep_symbols: true,
+ },
+ },
x86: {
// TODO: This is to work around b/24465209. Remove after root cause is fixed.
pack_relocations: false,
@@ -1807,36 +1831,40 @@
name: "libc.arm.map",
out: ["libc.arm.map"],
srcs: ["libc.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) arm $(in) $(out)",
- bazel_module: { bp2build_available: true },
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) arm $(in) $(out)",
}
genrule {
name: "libc.arm64.map",
out: ["libc.arm64.map"],
srcs: ["libc.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) arm64 $(in) $(out)",
- bazel_module: { bp2build_available: true },
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) arm64 $(in) $(out)",
+}
+
+genrule {
+ name: "libc.riscv64.map",
+ out: ["libc.riscv64.map"],
+ srcs: ["libc.map.txt"],
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) riscv64 $(in) $(out)",
}
genrule {
name: "libc.x86.map",
out: ["libc.x86.map"],
srcs: ["libc.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) x86 $(in) $(out)",
- bazel_module: { bp2build_available: true },
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) x86 $(in) $(out)",
}
genrule {
name: "libc.x86_64.map",
out: ["libc.x86_64.map"],
srcs: ["libc.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) x86_64 $(in) $(out)",
- bazel_module: { bp2build_available: true },
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) x86_64 $(in) $(out)",
}
// Headers that only other parts of the platform can include.
@@ -1852,6 +1880,7 @@
"//external/perfetto:__subpackages__",
"//external/scudo:__subpackages__",
"//system/core/debuggerd:__subpackages__",
+ "//system/core/init:__subpackages__",
"//system/core/libcutils:__subpackages__",
"//system/memory/libmemunreachable:__subpackages__",
"//system/unwinding/libunwindstack:__subpackages__",
@@ -1875,7 +1904,6 @@
"//apex_available:platform",
"//apex_available:anyapex",
],
- bazel_module: { bp2build_available: true },
}
cc_library_headers {
@@ -1925,6 +1953,9 @@
arm64: {
export_system_include_dirs: ["kernel/uapi/asm-arm64"],
},
+ riscv64: {
+ export_system_include_dirs: ["kernel/uapi/asm-riscv"],
+ },
x86: {
export_system_include_dirs: ["kernel/uapi/asm-x86"],
},
@@ -1932,7 +1963,6 @@
export_system_include_dirs: ["kernel/uapi/asm-x86"],
},
},
- bazel_module: { bp2build_available: true },
}
cc_library_headers {
@@ -1980,7 +2010,6 @@
export_header_lib_headers: ["libc_llndk_headers"],
},
},
- bazel_module: { bp2build_available: true },
}
// ========================================================
@@ -2021,6 +2050,9 @@
arm64: {
version_script: ":libstdc++.arm64.map",
},
+ riscv64: {
+ version_script: ":libstdc++.riscv64.map",
+ },
x86: {
pack_relocations: false,
ldflags: ["-Wl,--hash-style=both"],
@@ -2036,32 +2068,40 @@
name: "libstdc++.arm.map",
out: ["libstdc++.arm.map"],
srcs: ["libstdc++.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) arm $(in) $(out)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) arm $(in) $(out)",
}
genrule {
name: "libstdc++.arm64.map",
out: ["libstdc++.arm64.map"],
srcs: ["libstdc++.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) arm64 $(in) $(out)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) arm64 $(in) $(out)",
+}
+
+genrule {
+ name: "libstdc++.riscv64.map",
+ out: ["libstdc++.riscv64.map"],
+ srcs: ["libstdc++.map.txt"],
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) riscv64 $(in) $(out)",
}
genrule {
name: "libstdc++.x86.map",
out: ["libstdc++.x86.map"],
srcs: ["libstdc++.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) x86 $(in) $(out)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) x86 $(in) $(out)",
}
genrule {
name: "libstdc++.x86_64.map",
out: ["libstdc++.x86_64.map"],
srcs: ["libstdc++.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) x86_64 $(in) $(out)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) x86_64 $(in) $(out)",
}
// ========================================================
@@ -2131,8 +2171,6 @@
srcs: ["arch-common/bionic/crtbrand.S"],
defaults: ["crt_so_defaults"],
-
- bazel_module: { bp2build_available: true },
}
cc_object {
@@ -2144,8 +2182,6 @@
objs: [
"crtbrand",
],
-
- bazel_module: { bp2build_available: true },
}
cc_object {
@@ -2157,8 +2193,6 @@
srcs: ["arch-common/bionic/crtend_so.S"],
defaults: ["crt_so_defaults"],
-
- bazel_module: { bp2build_available: true },
}
cc_object {
@@ -2176,8 +2210,6 @@
defaults: ["crt_defaults"],
// When using libc.a, we're using the latest library regardless of target API level.
min_sdk_version: "current",
-
- bazel_module: { bp2build_available: true },
}
cc_object {
@@ -2200,8 +2232,6 @@
},
},
defaults: ["crt_defaults"],
-
- bazel_module: { bp2build_available: true },
}
cc_object {
@@ -2215,8 +2245,6 @@
srcs: ["arch-common/bionic/crtend.S"],
defaults: ["crt_defaults"],
-
- bazel_module: { bp2build_available: true },
}
cc_library_static {
@@ -2306,6 +2334,14 @@
}
ndk_headers {
+ name: "libc_asm_riscv64",
+ from: "kernel/uapi/asm-riscv",
+ to: "riscv64-linux-android",
+ srcs: ["kernel/uapi/asm-riscv/**/*.h"],
+ license: "NOTICE",
+}
+
+ndk_headers {
name: "libc_asm_x86",
from: "kernel/uapi/asm-x86",
to: "i686-linux-android",
@@ -2327,6 +2363,17 @@
first_version: "9",
// APIs implemented in asm don't have debug info: http://b/190554910.
allow_untyped_symbols: true,
+ export_header_libs: [
+ "common_libc",
+ "libc_uapi",
+ "libc_kernel_android_uapi_linux",
+ "libc_kernel_android_scsi",
+ "libc_asm_arm",
+ "libc_asm_arm64",
+ "libc_asm_riscv64",
+ "libc_asm_x86",
+ "libc_asm_x86_64",
+ ],
}
ndk_library {
@@ -2342,7 +2389,6 @@
"kernel/uapi/linux/input.h",
"kernel/uapi/linux/input-event-codes.h",
],
- bazel_module: { bp2build_available: true },
}
// Generate a syscall name / number mapping. These objects are text files
@@ -2368,8 +2414,6 @@
"kernel/uapi/asm-arm",
"kernel/uapi",
],
-
- bazel_module: { bp2build_available: true },
}
cc_object {
@@ -2379,8 +2423,15 @@
"kernel/uapi/asm-arm64",
"kernel/uapi",
],
+}
- bazel_module: { bp2build_available: true },
+cc_object {
+ name: "libseccomp_gen_syscall_nrs_riscv64",
+ defaults: ["libseccomp_gen_syscall_nrs_defaults"],
+ local_include_dirs: [
+ "kernel/uapi/asm-riscv",
+ "kernel/uapi",
+ ],
}
cc_object {
@@ -2392,8 +2443,6 @@
"kernel/uapi/asm-x86",
"kernel/uapi",
],
-
- bazel_module: { bp2build_available: true },
}
cc_object {
@@ -2405,14 +2454,11 @@
"kernel/uapi/asm-x86",
"kernel/uapi",
],
-
- bazel_module: { bp2build_available: true },
}
filegroup {
name: "all_kernel_uapi_headers",
srcs: ["kernel/uapi/**/*.h"],
- bazel_module: { bp2build_available: true },
}
@@ -2425,12 +2471,38 @@
srcs: [
"SYSCALLS.TXT",
- ":libseccomp_gen_syscall_nrs_arm",
- ":libseccomp_gen_syscall_nrs_arm64",
- ":libseccomp_gen_syscall_nrs_x86",
- ":libseccomp_gen_syscall_nrs_x86_64",
],
+ arch: {
+ arm: {
+ srcs: [
+ ":libseccomp_gen_syscall_nrs_arm",
+ ":libseccomp_gen_syscall_nrs_arm64",
+ ],
+ },
+ arm64: {
+ srcs: [
+ ":libseccomp_gen_syscall_nrs_arm",
+ ":libseccomp_gen_syscall_nrs_arm64",
+ ],
+ },
+ riscv64: {
+ srcs: [":libseccomp_gen_syscall_nrs_riscv64"],
+ },
+ x86: {
+ srcs: [
+ ":libseccomp_gen_syscall_nrs_x86",
+ ":libseccomp_gen_syscall_nrs_x86_64",
+ ],
+ },
+ x86_64: {
+ srcs: [
+ ":libseccomp_gen_syscall_nrs_x86",
+ ":libseccomp_gen_syscall_nrs_x86_64",
+ ],
+ },
+ },
+
out: [
"func_to_syscall_nrs.h",
],
@@ -2444,13 +2516,8 @@
cmd: "grep -v '^int[ \t]*setresgid' $(in) > $(out)",
}
-cc_genrule {
- name: "libseccomp_policy_app_zygote_sources",
- recovery_available: true,
- cmd: "$(location genseccomp) --out-dir=$(genDir) --name-modifier=app_zygote $(in)",
-
- tools: [ "genseccomp" ],
-
+filegroup {
+ name: "seccomp_syscalls_sources_zygote",
srcs: [
"SYSCALLS.TXT",
"SECCOMP_ALLOWLIST_COMMON.TXT",
@@ -2458,27 +2525,11 @@
"SECCOMP_BLOCKLIST_COMMON.TXT",
"SECCOMP_PRIORITY.TXT",
":generate_app_zygote_blocklist",
- ":libseccomp_gen_syscall_nrs_arm",
- ":libseccomp_gen_syscall_nrs_arm64",
- ":libseccomp_gen_syscall_nrs_x86",
- ":libseccomp_gen_syscall_nrs_x86_64",
- ],
-
- out: [
- "arm64_app_zygote_policy.cpp",
- "arm_app_zygote_policy.cpp",
- "x86_64_app_zygote_policy.cpp",
- "x86_app_zygote_policy.cpp",
],
}
-cc_genrule {
- name: "libseccomp_policy_app_sources",
- recovery_available: true,
- cmd: "$(location genseccomp) --out-dir=$(genDir) --name-modifier=app $(in)",
-
- tools: [ "genseccomp" ],
-
+filegroup {
+ name: "seccomp_syscalls_sources_app",
srcs: [
"SYSCALLS.TXT",
"SECCOMP_ALLOWLIST_COMMON.TXT",
@@ -2486,56 +2537,242 @@
"SECCOMP_BLOCKLIST_COMMON.TXT",
"SECCOMP_BLOCKLIST_APP.TXT",
"SECCOMP_PRIORITY.TXT",
- ":libseccomp_gen_syscall_nrs_arm",
- ":libseccomp_gen_syscall_nrs_arm64",
- ":libseccomp_gen_syscall_nrs_x86",
- ":libseccomp_gen_syscall_nrs_x86_64",
- ],
-
- out: [
- "arm64_app_policy.cpp",
- "arm_app_policy.cpp",
- "x86_64_app_policy.cpp",
- "x86_app_policy.cpp",
],
}
-cc_genrule {
- name: "libseccomp_policy_system_sources",
- recovery_available: true,
- cmd: "$(location genseccomp) --out-dir=$(genDir) --name-modifier=system $(in)",
-
- tools: [ "genseccomp" ],
-
+filegroup {
+ name: "seccomp_syscalls_sources_system",
srcs: [
"SYSCALLS.TXT",
"SECCOMP_ALLOWLIST_COMMON.TXT",
"SECCOMP_ALLOWLIST_SYSTEM.TXT",
"SECCOMP_BLOCKLIST_COMMON.TXT",
"SECCOMP_PRIORITY.TXT",
- ":libseccomp_gen_syscall_nrs_arm",
- ":libseccomp_gen_syscall_nrs_arm64",
+ ],
+}
+
+cc_genrule {
+ name: "libseccomp_policy_app_zygote_sources_x86",
+ recovery_available: true,
+ cmd: "$(location genseccomp) --out-dir=$(genDir) --name-modifier=app_zygote $(in)",
+ tools: [ "genseccomp" ],
+ srcs: [
+ ":seccomp_syscalls_sources_zygote",
":libseccomp_gen_syscall_nrs_x86",
":libseccomp_gen_syscall_nrs_x86_64",
],
-
out: [
- "arm64_system_policy.cpp",
- "arm_system_policy.cpp",
- "x86_64_system_policy.cpp",
- "x86_system_policy.cpp",
+ "x86_app_zygote_policy.cpp",
+ "x86_64_app_zygote_policy.cpp",
],
+ enabled: false,
+ arch: {
+ x86: { enabled: true },
+ x86_64: { enabled: true },
+ },
+}
+
+cc_genrule {
+ name: "libseccomp_policy_app_zygote_sources_arm",
+ recovery_available: true,
+ cmd: "$(location genseccomp) --out-dir=$(genDir) --name-modifier=app_zygote $(in)",
+ tools: [ "genseccomp" ],
+ srcs: [
+ ":seccomp_syscalls_sources_zygote",
+ ":libseccomp_gen_syscall_nrs_arm",
+ ":libseccomp_gen_syscall_nrs_arm64",
+ ],
+ out: [
+ "arm_app_zygote_policy.cpp",
+ "arm64_app_zygote_policy.cpp",
+ ],
+ enabled: false,
+ arch: {
+ arm: { enabled: true },
+ arm64: { enabled: true },
+ },
+}
+
+cc_genrule {
+ name: "libseccomp_policy_app_zygote_sources_riscv64",
+ recovery_available: true,
+ cmd: "$(location genseccomp) --out-dir=$(genDir) --name-modifier=app_zygote $(in)",
+ tools: [ "genseccomp" ],
+ srcs: [
+ ":seccomp_syscalls_sources_zygote",
+ ":libseccomp_gen_syscall_nrs_riscv64",
+ ],
+ out: [
+ "riscv64_app_zygote_policy.cpp",
+ ],
+ enabled: false,
+ arch: {
+ riscv64: { enabled: true },
+ },
+}
+
+cc_genrule {
+ name: "libseccomp_policy_app_sources_x86",
+ recovery_available: true,
+ cmd: "$(location genseccomp) --out-dir=$(genDir) --name-modifier=app $(in)",
+ tools: [ "genseccomp" ],
+ srcs: [
+ ":seccomp_syscalls_sources_app",
+ ":libseccomp_gen_syscall_nrs_x86",
+ ":libseccomp_gen_syscall_nrs_x86_64",
+ ],
+ out: [
+ "x86_app_policy.cpp",
+ "x86_64_app_policy.cpp",
+ ],
+ enabled: false,
+ arch: {
+ x86: { enabled: true },
+ x86_64: { enabled: true },
+ },
+}
+
+cc_genrule {
+ name: "libseccomp_policy_app_sources_arm",
+ recovery_available: true,
+ cmd: "$(location genseccomp) --out-dir=$(genDir) --name-modifier=app $(in)",
+ tools: [ "genseccomp" ],
+ srcs: [
+ ":seccomp_syscalls_sources_app",
+ ":libseccomp_gen_syscall_nrs_arm",
+ ":libseccomp_gen_syscall_nrs_arm64",
+ ],
+ out: [
+ "arm_app_policy.cpp",
+ "arm64_app_policy.cpp",
+ ],
+ enabled: false,
+ arch: {
+ arm: { enabled: true },
+ arm64: { enabled: true },
+ },
+}
+
+cc_genrule {
+ name: "libseccomp_policy_app_sources_riscv64",
+ recovery_available: true,
+ cmd: "$(location genseccomp) --out-dir=$(genDir) --name-modifier=app $(in)",
+ tools: [ "genseccomp" ],
+ srcs: [
+ ":seccomp_syscalls_sources_app",
+ ":libseccomp_gen_syscall_nrs_riscv64",
+ ],
+ out: [
+ "riscv64_app_policy.cpp",
+ ],
+ enabled: false,
+ arch: {
+ riscv64: { enabled: true },
+ },
+}
+
+cc_genrule {
+ name: "libseccomp_policy_system_sources_x86",
+ recovery_available: true,
+ cmd: "$(location genseccomp) --out-dir=$(genDir) --name-modifier=system $(in)",
+ tools: [ "genseccomp" ],
+ srcs: [
+ ":seccomp_syscalls_sources_system",
+ ":libseccomp_gen_syscall_nrs_x86",
+ ":libseccomp_gen_syscall_nrs_x86_64",
+ ],
+ out: [
+ "x86_system_policy.cpp",
+ "x86_64_system_policy.cpp",
+ ],
+ enabled: false,
+ arch: {
+ x86: { enabled: true },
+ x86_64: { enabled: true },
+ },
+}
+
+cc_genrule {
+ name: "libseccomp_policy_system_sources_arm",
+ recovery_available: true,
+ cmd: "$(location genseccomp) --out-dir=$(genDir) --name-modifier=system $(in)",
+ tools: [ "genseccomp" ],
+ srcs: [
+ ":seccomp_syscalls_sources_system",
+ ":libseccomp_gen_syscall_nrs_arm",
+ ":libseccomp_gen_syscall_nrs_arm64",
+ ],
+ out: [
+ "arm_system_policy.cpp",
+ "arm64_system_policy.cpp",
+ ],
+ enabled: false,
+ arch: {
+ arm: { enabled: true },
+ arm64: { enabled: true },
+ },
+}
+
+cc_genrule {
+ name: "libseccomp_policy_system_sources_riscv64",
+ recovery_available: true,
+ cmd: "$(location genseccomp) --out-dir=$(genDir) --name-modifier=system $(in)",
+ tools: [ "genseccomp" ],
+ srcs: [
+ ":seccomp_syscalls_sources_system",
+ ":libseccomp_gen_syscall_nrs_riscv64",
+ ],
+ out: [
+ "riscv64_system_policy.cpp",
+ ],
+ enabled: false,
+ arch: {
+ riscv64: { enabled: true },
+ },
}
cc_library {
name: "libseccomp_policy",
recovery_available: true,
generated_headers: ["func_to_syscall_nrs"],
- generated_sources: [
- "libseccomp_policy_app_sources",
- "libseccomp_policy_app_zygote_sources",
- "libseccomp_policy_system_sources",
- ],
+
+ arch: {
+ arm: {
+ generated_sources: [
+ "libseccomp_policy_app_sources_arm",
+ "libseccomp_policy_app_zygote_sources_arm",
+ "libseccomp_policy_system_sources_arm",
+ ],
+ },
+ arm64: {
+ generated_sources: [
+ "libseccomp_policy_app_sources_arm",
+ "libseccomp_policy_app_zygote_sources_arm",
+ "libseccomp_policy_system_sources_arm",
+ ],
+ },
+ riscv64: {
+ generated_sources: [
+ "libseccomp_policy_app_sources_riscv64",
+ "libseccomp_policy_app_zygote_sources_riscv64",
+ "libseccomp_policy_system_sources_riscv64",
+ ],
+ },
+ x86: {
+ generated_sources: [
+ "libseccomp_policy_app_sources_x86",
+ "libseccomp_policy_app_zygote_sources_x86",
+ "libseccomp_policy_system_sources_x86",
+ ],
+ },
+ x86_64: {
+ generated_sources: [
+ "libseccomp_policy_app_sources_x86",
+ "libseccomp_policy_app_zygote_sources_x86",
+ "libseccomp_policy_system_sources_x86",
+ ],
+ },
+ },
srcs: [
"seccomp/seccomp_policy.cpp",
@@ -2666,6 +2903,7 @@
" -D $${BIONIC_LIBC_DIR}/b64/include " +
" && " +
"$(location zip2zip) -i $(genDir)/sysroot.zip -o $(genDir)/sysroot-renamed.zip " +
+ " -x **/BUILD " +
" include/**/*:include/ " +
" NOTICE:NOTICE.bionic " +
" && " +
@@ -2705,3 +2943,53 @@
tools: ["soong_zip"],
cmd: "includes=($(in)) && $(location soong_zip) -o $(out) -P include/asm -j -D $$(dirname $${includes[0]})",
}
+
+cc_genrule {
+ name: "bionic_sysroot_crt_objects",
+ visibility: ["//visibility:private"],
+ out: ["bionic_sysroot_crt_objects.zip"],
+ tools: ["soong_zip"],
+ srcs: [
+ ":crtbegin_dynamic",
+ ":crtbegin_so",
+ ":crtbegin_static",
+ ":crtend_android",
+ ":crtend_so",
+ ],
+ cmd: "$(location soong_zip) -o $(out) -j " +
+ "-f $(location :crtbegin_dynamic) " +
+ "-f $(location :crtbegin_so) " +
+ "-f $(location :crtbegin_static) " +
+ "-f $(location :crtend_android) " +
+ "-f $(location :crtend_so)",
+ dist: {
+ targets: ["bionic_sysroot_crt_objects"],
+ },
+ arch: {
+ arm: {
+ dist: {
+ suffix: "_arm",
+ },
+ },
+ arm64: {
+ dist: {
+ suffix: "_arm64",
+ },
+ },
+ riscv64: {
+ dist: {
+ suffix: "_riscv64",
+ },
+ },
+ x86: {
+ dist: {
+ suffix: "_x86",
+ },
+ },
+ x86_64: {
+ dist: {
+ suffix: "_x86_64",
+ },
+ },
+ },
+}
diff --git a/libc/BUILD b/libc/BUILD
new file mode 100644
index 0000000..1777ae9
--- /dev/null
+++ b/libc/BUILD
@@ -0,0 +1,42 @@
+# Copyright (C) 2022 The Android Open Source Project
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+load("//build/bazel/rules/apis:cc_api_contribution.bzl", "cc_api_contribution")
+
+cc_api_contribution(
+ name = "libc_contributions",
+ hdrs = [
+ "//bionic/libc/kernel/android:libc_kernel_android_scsi_headers",
+ "//bionic/libc/kernel/android:libc_kernel_android_uapi_headers",
+ "//bionic/libc/kernel/uapi:libc_kernel_uapi_asm_arm64_headers", #arm64
+ "//bionic/libc/kernel/uapi:libc_kernel_uapi_asm_arm_headers", #arm
+ "//bionic/libc/kernel/uapi:libc_kernel_uapi_asm_x86_64_headers", #x86_64
+ "//bionic/libc/kernel/uapi:libc_kernel_uapi_asm_x86_headers", #x86
+ "//bionic/libc/kernel/uapi:libc_kernel_uapi_headers",
+ ],
+ api = ":libc.map.txt",
+ library_name = "libc",
+)
diff --git a/libc/NOTICE b/libc/NOTICE
index 9cbbde2..51f43f1 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -783,22 +783,6 @@
-------------------------------------------------------------------
Copyright (C) 2019 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
--------------------------------------------------------------------
-
-Copyright (C) 2019 The Android Open Source Project
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -826,34 +810,6 @@
-------------------------------------------------------------------
-Copyright (C) 2019 The Android Open Source Project
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
--------------------------------------------------------------------
-
Copyright (C) 2020 The Android Open Source Project
All rights reserved.
@@ -2096,6 +2052,38 @@
Copyright (c) 1990, 1993
The Regents of the University of California. All rights reserved.
+
+This code is derived from software contributed to Berkeley by
+Mike Hibler and Chris Torek.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1990, 1993
+ The Regents of the University of California. All rights reserved.
(c) UNIX System Laboratories, Inc.
All or some portions of this file are derived from material licensed
to the University of California by American Telephone and Telegraph
@@ -4605,6 +4593,34 @@
-------------------------------------------------------------------
+Copyright (c) 2017, 2018 Dell EMC
+Copyright (c) 2000, 2001, 2008, 2011, David E. O'Brien
+Copyright (c) 1998 John D. Polstra.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
Copyright (c)1999 Citrus Project,
All rights reserved.
diff --git a/libc/SECCOMP_ALLOWLIST_APP.TXT b/libc/SECCOMP_ALLOWLIST_APP.TXT
index ba40b60..39c6c53 100644
--- a/libc/SECCOMP_ALLOWLIST_APP.TXT
+++ b/libc/SECCOMP_ALLOWLIST_APP.TXT
@@ -56,3 +56,7 @@
# b/62090571
int mkdir(const char *pathname, mode_t mode) lp32
+
+# Not used by bionic in U because riscv64 doesn't have it, but still
+# used by legacy apps (http://b/254179267).
+int renameat(int, const char*, int, const char*) arm,x86,arm64,x86-64
diff --git a/libc/SECCOMP_ALLOWLIST_COMMON.TXT b/libc/SECCOMP_ALLOWLIST_COMMON.TXT
index 0366fdf..a4218ee 100644
--- a/libc/SECCOMP_ALLOWLIST_COMMON.TXT
+++ b/libc/SECCOMP_ALLOWLIST_COMMON.TXT
@@ -76,5 +76,3 @@
int sched_rr_get_interval_time64(pid_t, timespec64*) lp32
# Since Linux 5.4, not in glibc. Probed for and conditionally used by ART.
int userfaultfd(int) all
-# Since Linux 5.9, used by POSIX_SPAWN_CLOEXEC_DEFAULT
-int close_range(unsigned int, unsigned int, int) all
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index a09c614..1b9054b 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -7,7 +7,7 @@
# where:
# arch_list ::= "all" | arches
# arches ::= arch | arch "," arches
-# arch ::= "arm" | "arm64" | "x86" | "x86_64" | "lp32" | "lp64"
+# arch ::= "arm" | "arm64" | "riscv64" | "x86" | "x86_64" | "lp32" | "lp64"
#
# Note:
# - syscall_name corresponds to the name of the syscall, which may differ from
@@ -26,7 +26,7 @@
# This file is processed by a python script named gensyscalls.py, run via
# genrules in Android.bp.
-int execve(const char*, char* const*, char* const*) all
+int __execve:execve(const char*, char* const*, char* const*) all
uid_t getuid:getuid32() lp32
uid_t getuid:getuid() lp64
@@ -107,6 +107,8 @@
ssize_t __pwritev64v2:pwritev2(int, const struct iovec*, int, long, long, int) all
int __close:close(int) all
+int close_range(unsigned int, unsigned int, int) all
+ssize_t copy_file_range(int, off64_t*, int, off64_t*, size_t, unsigned int) all
pid_t __getpid:getpid() all
int memfd_create(const char*, unsigned) all
int munmap(void*, size_t) all
@@ -154,7 +156,6 @@
int mkdirat(int, const char*, mode_t) all
int mknodat(int, const char*, mode_t, dev_t) all
int readlinkat(int, const char*, char*, size_t) all
-int renameat(int, const char*, int, const char*) all
int renameat2(int, const char*, int, const char*, unsigned) all
int symlinkat(const char*, int, const char*) all
int unlinkat(int, const char*, int) all
@@ -318,7 +319,7 @@
int __eventfd:eventfd2(unsigned int, int) all
-void _exit|_Exit:exit_group(int) all
+void __exit_group:exit_group(int) all
void __exit:exit(int) all
int inotify_init1(int) all
@@ -351,6 +352,9 @@
int __set_tls:__ARM_NR_set_tls(void*) arm
int cacheflush:__ARM_NR_cacheflush(long start, long end, long flags) arm
+# riscv64-specific
+int _flush_icache:riscv_flush_icache(void*, void*, unsigned long) riscv64
+
# x86-specific
int __set_thread_area:set_thread_area(void*) x86
diff --git a/libc/arch-arm64/bionic/setjmp.S b/libc/arch-arm64/bionic/setjmp.S
index d2fafdb..8e00b56 100644
--- a/libc/arch-arm64/bionic/setjmp.S
+++ b/libc/arch-arm64/bionic/setjmp.S
@@ -194,7 +194,7 @@
cmp x2, x12
bne __bionic_setjmp_checksum_mismatch
-#if __has_feature(hwaddress_sanitizer)
+ // Update stack memory tags (MTE + hwasan).
stp x0, x30, [sp, #-16]!
.cfi_adjust_cfa_offset 16
.cfi_rel_offset x0, 0
@@ -206,7 +206,7 @@
bic x2, x2, #1
ldr x0, [x0, #(_JB_X30_SP * 8 + 8)]
eor x0, x0, x2
- bl __hwasan_handle_longjmp
+ bl memtag_handle_longjmp
mov x1, x19 // Restore 'value'.
// Restore original x0 and lr.
@@ -214,7 +214,6 @@
.cfi_adjust_cfa_offset -16
.cfi_restore x0
.cfi_restore x30
-#endif
// Do we need to restore the signal mask?
ldr x2, [x0, #(_JB_SIGFLAG * 8)]
diff --git a/libc/arch-arm64/bionic/vfork.S b/libc/arch-arm64/bionic/vfork.S
index df7b063..9eb82d8 100644
--- a/libc/arch-arm64/bionic/vfork.S
+++ b/libc/arch-arm64/bionic/vfork.S
@@ -29,10 +29,7 @@
#include <platform/bionic/tls_defines.h>
#include <private/bionic_asm.h>
#include <asm/signal.h>
-
-// Must match the defines in linux/sched.h
-#define CLONE_VM 0x00000100
-#define CLONE_VFORK 0x00004000
+#include <linux/sched.h>
ENTRY(vfork)
__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(vfork)
@@ -45,6 +42,9 @@
ldr w10, [x9, #20]
str w0, [x9, #20]
+ // Clear vfork_child_stack_bottom_.
+ str xzr, [x9, #776]
+
mov x0, #(CLONE_VM | CLONE_VFORK | SIGCHLD)
mov x1, xzr
mov x2, xzr
@@ -62,9 +62,6 @@
cneg x0, x0, hi
b.hi __set_errno_internal
-#if __has_feature(hwaddress_sanitizer)
- cbz x0, .L_exit
-
// Clean up stack shadow in the parent process.
// https://github.com/google/sanitizers/issues/925
paciasp
@@ -75,7 +72,7 @@
.cfi_rel_offset x30, 8
add x0, sp, #16
- bl __hwasan_handle_vfork
+ bl memtag_handle_vfork
ldp x0, x30, [sp], #16
.cfi_adjust_cfa_offset -16
@@ -84,8 +81,6 @@
autiasp
.cfi_negate_ra_state
-#endif
-
.L_exit:
ret
END(vfork)
diff --git a/libc/arch-common/bionic/crtbegin.c b/libc/arch-common/bionic/crtbegin.c
index 9b8ad4e..b87db64 100644
--- a/libc/arch-common/bionic/crtbegin.c
+++ b/libc/arch-common/bionic/crtbegin.c
@@ -56,6 +56,8 @@
__asm__(PRE
"xorl %ebp,%ebp; movl %esp,%eax; andl $~0xf,%esp; subl $12,%esp; pushl %eax;"
"call _start_main" POST);
+#elif defined(__riscv)
+__asm__(PRE "li fp,0; li ra,0; mv a0,sp; tail _start_main" POST);
#elif defined(__x86_64__)
__asm__(PRE "xorl %ebp, %ebp; movq %rsp,%rdi; andq $~0xf,%rsp; callq _start_main" POST);
#else
diff --git a/libc/arch-riscv64/bionic/__bionic_clone.S b/libc/arch-riscv64/bionic/__bionic_clone.S
new file mode 100644
index 0000000..d535095
--- /dev/null
+++ b/libc/arch-riscv64/bionic/__bionic_clone.S
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+
+// pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
+
+ENTRY_PRIVATE(__bionic_clone)
+ # Push 'fn' and 'arg' onto the child stack.
+ addi a1, a1, -16
+ sd a5, 0(a1)
+ sd a6, 8(a1)
+
+ # Make the system call.
+ li a7, __NR_clone
+ ecall
+
+ # Are we the child?
+ beqz a0, .L_bc_child
+
+ # Did the clone(2) fail?
+ bltz a0, .L_bc_failure
+ # Nope, we're the parent, and our work here is done.
+ ret
+
+.L_bc_failure:
+ # Set errno if something went wrong.
+ neg a0, a0
+ j __set_errno_internal
+
+.L_bc_child:
+ # We're in the child now. Set the end of the frame record chain.
+ li fp, 0
+ # Setting ra to 0 will make the unwinder stop at __start_thread.
+ li ra, 0
+ # Call __start_thread with the 'fn' and 'arg' we stored on the child stack.
+ ld a0, 0(sp)
+ ld a1, 8(sp)
+ addi sp, sp, 16
+ j __start_thread
+END(__bionic_clone)
diff --git a/libc/arch-riscv64/bionic/__set_tls.c b/libc/arch-riscv64/bionic/__set_tls.c
new file mode 100644
index 0000000..57383ab
--- /dev/null
+++ b/libc/arch-riscv64/bionic/__set_tls.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__LIBC_HIDDEN__ void __set_tls(void* tls) {
+ asm("mv tp, %0" : : "r"(tls));
+}
diff --git a/libc/arch-riscv64/bionic/_exit_with_stack_teardown.S b/libc/arch-riscv64/bionic/_exit_with_stack_teardown.S
new file mode 100644
index 0000000..f7bf58b
--- /dev/null
+++ b/libc/arch-riscv64/bionic/_exit_with_stack_teardown.S
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+
+// void _exit_with_stack_teardown(void* stackBase, size_t stackSize)
+ENTRY_PRIVATE(_exit_with_stack_teardown)
+ li a7, __NR_munmap
+ ecall
+ // If munmap failed, we ignore the failure and exit anyway.
+
+ li a0, 0
+ li a7, __NR_exit
+ ecall
+ // The exit syscall does not return.
+END(_exit_with_stack_teardown)
diff --git a/libc/arch-riscv64/bionic/setjmp.S b/libc/arch-riscv64/bionic/setjmp.S
new file mode 100644
index 0000000..eea2978
--- /dev/null
+++ b/libc/arch-riscv64/bionic/setjmp.S
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+#include <private/bionic_constants.h>
+
+// The internal structure of a jmp_buf is totally private.
+// Current layout (changes from release to release):
+//
+// word name description
+// 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit
+// 1 sigmask 64-bit signal mask
+// 2 ra
+// 3 s0
+// ......
+// 14 s11
+// 15 sp
+// 16 fs0
+// ......
+// 27 fs11
+// 28 checksum
+// _JBLEN: defined in bionic/libc/include/setjmp.h
+
+#define _JB_SIGFLAG 0
+#define _JB_SIGMASK 1 * 8
+#define _JB_RA 2 * 8
+#define _JB_S0 3 * 8
+#define _JB_S1 4 * 8
+#define _JB_S2 5 * 8
+#define _JB_S3 6 * 8
+#define _JB_S4 7 * 8
+#define _JB_S5 8 * 8
+#define _JB_S6 9 * 8
+#define _JB_S7 10 * 8
+#define _JB_S8 11 * 8
+#define _JB_S9 12 * 8
+#define _JB_S10 13 * 8
+#define _JB_S11 14 * 8
+#define _JB_SP 15 * 8
+#define _JB_FS0 16 * 8
+#define _JB_FS1 17 * 8
+#define _JB_FS2 18 * 8
+#define _JB_FS3 19 * 8
+#define _JB_FS4 20 * 8
+#define _JB_FS5 21 * 8
+#define _JB_FS6 22 * 8
+#define _JB_FS7 23 * 8
+#define _JB_FS8 24 * 8
+#define _JB_FS9 25 * 8
+#define _JB_FS10 26 * 8
+#define _JB_FS11 27 * 8
+#define _JB_CHECKSUM 28 * 8
+
+.macro m_mangle_registers reg, sp_reg
+ xor s0, s0, \reg
+ xor s1, s1, \reg
+ xor s2, s2, \reg
+ xor s3, s3, \reg
+ xor s4, s4, \reg
+ xor s5, s5, \reg
+ xor s6, s6, \reg
+ xor s7, s7, \reg
+ xor s8, s8, \reg
+ xor s9, s9, \reg
+ xor s10, s10, \reg
+ xor s11, s11, \reg
+ xor \sp_reg, \sp_reg, \reg
+.endm
+
+.macro m_calculate_checksum dst, src, scratch
+ li \dst, 0
+ .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27
+ ld \scratch, (\i * 8)(\src)
+ xor \dst, \dst, \scratch
+ .endr
+.endm
+
+.macro m_unmangle_registers reg, sp_reg
+ m_mangle_registers \reg, sp_reg=\sp_reg
+.endm
+
+ENTRY(setjmp)
+__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp)
+ li a1, 1
+ tail sigsetjmp
+END(setjmp)
+
+ENTRY(_setjmp)
+__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp)
+ li a1, 0
+ tail sigsetjmp
+END(_setjmp)
+
+// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
+ENTRY(sigsetjmp)
+__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
+ addi sp, sp, -24
+ sd a0, 0(sp)
+ sd a1, 8(sp)
+ sd ra, 16(sp)
+
+ // Get the cookie and store it along with the signal flag.
+ mv a0, a1
+ call __bionic_setjmp_cookie_get
+ mv a1, a0
+ ld a0, 0(sp)
+ sd a1, _JB_SIGFLAG(a0)
+
+ // Do we need to save the signal mask?
+ andi a1, a1, 1
+ beqz a1, 1f
+
+ // Save current signal mask.
+ // The 'how'/a0 argument is ignored if set is NULL.
+ li a1, 0 // NULL
+ addi a2, a0, _JB_SIGMASK // old_mask.
+ call sigprocmask
+
+1:
+ // Restore original a0/ra.
+ ld a0, 0(sp)
+ ld ra, 16(sp)
+ addi sp, sp, 24
+
+ // Get the cookie.
+ ld a1, _JB_SIGFLAG(a0)
+ andi a1, a1, -2
+
+ // Save core registers.
+ mv a2, sp
+ m_mangle_registers a1, sp_reg=a2
+ sd ra, _JB_RA(a0)
+ sd s0, _JB_S0(a0)
+ sd s1, _JB_S1(a0)
+ sd s2, _JB_S2(a0)
+ sd s3, _JB_S3(a0)
+ sd s4, _JB_S4(a0)
+ sd s5, _JB_S5(a0)
+ sd s6, _JB_S6(a0)
+ sd s7, _JB_S7(a0)
+ sd s8, _JB_S8(a0)
+ sd s9, _JB_S9(a0)
+ sd s10, _JB_S10(a0)
+ sd s11, _JB_S11(a0)
+ sd a2, _JB_SP(a0)
+ m_unmangle_registers a1, sp_reg=a2
+
+ // Save floating point registers.
+ fsd fs0, _JB_FS0(a0)
+ fsd fs1, _JB_FS1(a0)
+ fsd fs2, _JB_FS2(a0)
+ fsd fs3, _JB_FS3(a0)
+ fsd fs4, _JB_FS4(a0)
+ fsd fs5, _JB_FS5(a0)
+ fsd fs6, _JB_FS6(a0)
+ fsd fs7, _JB_FS7(a0)
+ fsd fs8, _JB_FS8(a0)
+ fsd fs9, _JB_FS9(a0)
+ fsd fs10, _JB_FS10(a0)
+ fsd fs11, _JB_FS11(a0)
+
+ // Calculate the checksum and save it.
+ m_calculate_checksum t0, a0, t1
+ sd t0, _JB_CHECKSUM(a0)
+
+ li a0, 0
+ ret
+END(sigsetjmp)
+
+// void siglongjmp(sigjmp_buf env, int value);
+ENTRY(siglongjmp)
+__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
+ // Check the checksum before doing anything.
+ m_calculate_checksum t0, a0, t1
+ ld t1, _JB_CHECKSUM(a0)
+ bne t0, t1, 3f
+
+ // Do we need to restore the signal mask?
+ ld a2, _JB_SIGFLAG(a0)
+ andi a3, a2, 1
+ beqz a3, 1f
+
+ addi sp, sp, -16
+ sd a0, 0(sp)
+ sd ra, 8(sp)
+
+ // Restore the signal mask.
+ mv t0, a1 // Save 'value'.
+
+ mv a2, a0
+ li a0, 2 // SIG_SETMASK
+ addi a1, a2, _JB_SIGMASK // new_mask
+ li a2, 0 // NULL
+ call sigprocmask
+ mv a1, t0 // Restore 'value'.
+
+ // Restore original a0 and ra.
+ ld a0, 0(sp)
+ ld ra, 8(sp)
+ addi sp, sp, 16
+
+ ld a2, _JB_SIGFLAG(a0)
+1:
+ // Restore core registers.
+ andi a2, a2, -2
+ ld ra, _JB_RA(a0)
+ ld s0, _JB_S0(a0)
+ ld s1, _JB_S1(a0)
+ ld s2, _JB_S2(a0)
+ ld s3, _JB_S3(a0)
+ ld s4, _JB_S4(a0)
+ ld s5, _JB_S5(a0)
+ ld s6, _JB_S6(a0)
+ ld s7, _JB_S7(a0)
+ ld s8, _JB_S8(a0)
+ ld s9, _JB_S9(a0)
+ ld s10, _JB_S10(a0)
+ ld s11, _JB_S11(a0)
+ ld a3, _JB_SP(a0)
+ m_unmangle_registers a2, sp_reg=a3
+ mv sp, a3
+
+ addi sp, sp, -24
+ sd ra, 0(sp)
+ sd a0, 8(sp)
+ sd a1, 16(sp)
+ ld a0, _JB_SIGFLAG(a0)
+ call __bionic_setjmp_cookie_check
+ ld ra, 0(sp)
+ ld a0, 8(sp)
+ ld a1, 16(sp)
+ addi sp, sp, 24
+
+ // Restore floating point registers.
+ fld fs0, _JB_FS0(a0)
+ fld fs1, _JB_FS1(a0)
+ fld fs2, _JB_FS2(a0)
+ fld fs3, _JB_FS3(a0)
+ fld fs4, _JB_FS4(a0)
+ fld fs5, _JB_FS5(a0)
+ fld fs6, _JB_FS6(a0)
+ fld fs7, _JB_FS7(a0)
+ fld fs8, _JB_FS8(a0)
+ fld fs9, _JB_FS9(a0)
+ fld fs10, _JB_FS10(a0)
+ fld fs11, _JB_FS11(a0)
+
+ // Set return value.
+ beqz a1, 2f
+ li a0, 1
+2:
+ mv a0, a1
+ ret
+
+3:
+ call __bionic_setjmp_checksum_mismatch
+END(siglongjmp)
+
+ALIAS_SYMBOL(longjmp, siglongjmp)
+__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
+ALIAS_SYMBOL(_longjmp, siglongjmp)
+__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)
diff --git a/libc/arch-riscv64/bionic/syscall.S b/libc/arch-riscv64/bionic/syscall.S
new file mode 100644
index 0000000..7b9d3ca
--- /dev/null
+++ b/libc/arch-riscv64/bionic/syscall.S
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+
+ENTRY(syscall)
+ // Move the syscall number up.
+ mv a7, a0
+
+ // Shuffle the arguments down.
+ mv a0, a1
+ mv a1, a2
+ mv a2, a3
+ mv a3, a4
+ mv a4, a5
+ mv a5, a6
+
+ ecall
+
+ // Did it fail?
+ li a7, -MAX_ERRNO
+ bgtu a0, a7, 1f
+
+ ret
+1:
+ neg a0, a0
+ j __set_errno_internal
+END(syscall)
diff --git a/libc/arch-riscv64/bionic/vfork.S b/libc/arch-riscv64/bionic/vfork.S
new file mode 100644
index 0000000..0eff9e9
--- /dev/null
+++ b/libc/arch-riscv64/bionic/vfork.S
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <platform/bionic/tls_defines.h>
+#include <private/bionic_asm.h>
+#include <asm/signal.h>
+#include <linux/sched.h>
+
+ENTRY(vfork)
+ // t0 = __get_tls()[TLS_SLOT_THREAD_ID]
+ mv t0, tp
+ ld t0, TLS_SLOT_THREAD_ID * 8(t0)
+
+ // Set cached_pid_ to 0, vforked_ to 1, and stash the previous value.
+ li t1, 0x80000000
+ lw t2, 20(t0)
+ sw t1, 20(t0)
+
+ li a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
+ li a1, 0 //uses a duplicate of the parent's stack
+ li a2, 0
+ li a3, 0
+ li a4, 0
+
+ li a7, __NR_clone
+ ecall
+
+ // if (rc == 0) we're the child, and finished...
+ beqz a0, .L_success
+
+ // else if (rc != 0): reset cached_pid_ and vforked_...
+ sw t2, 20(t0)
+ // ...and work out whether we succeeded or failed.
+ bltz a0, .L_failure
+.L_success:
+ ret
+
+.L_failure:
+ neg a0, a0
+ j __set_errno_internal
+END(vfork)
diff --git a/libc/arch-riscv64/string/memset_chk.c b/libc/arch-riscv64/string/memset_chk.c
new file mode 100644
index 0000000..bdd15a5
--- /dev/null
+++ b/libc/arch-riscv64/string/memset_chk.c
@@ -0,0 +1,9 @@
+#include <stdint.h>
+
+extern void* memset(void*, int, size_t);
+extern void* __memset_chk_fail(void*, int, size_t, size_t);
+
+void* __memset_chk(void* dst, int c, size_t n, size_t dst_len) {
+ if (dst_len < n) __memset_chk_fail(dst, c, n, dst_len);
+ return memset(dst, c, n);
+}
diff --git a/libc/arch-x86/atom/string/cache.h b/libc/arch-x86/atom/string/cache.h
deleted file mode 100644
index 823bb1e..0000000
--- a/libc/arch-x86/atom/string/cache.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-Copyright (c) 2010, Intel Corporation
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
-
- * Neither the name of Intel Corporation nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* Values are optimized for Atom */
-#define SHARED_CACHE_SIZE (512*1024) /* Atom L2 Cache */
-#define DATA_CACHE_SIZE (24*1024) /* Atom L1 Data Cache */
-
-#define SHARED_CACHE_SIZE_HALF (SHARED_CACHE_SIZE / 2)
-#define DATA_CACHE_SIZE_HALF (DATA_CACHE_SIZE / 2)
diff --git a/libc/arch-x86/dynamic_function_dispatch.cpp b/libc/arch-x86/dynamic_function_dispatch.cpp
index e94fa1f..38d8a0a 100644
--- a/libc/arch-x86/dynamic_function_dispatch.cpp
+++ b/libc/arch-x86/dynamic_function_dispatch.cpp
@@ -95,13 +95,6 @@
RETURN_FUNC(wmemcmp_func, wmemcmp_freebsd);
}
-typedef int wmemset_func(const wchar_t* __lhs, const wchar_t* __rhs, size_t __n);
-DEFINE_IFUNC_FOR(wmemset) {
- __builtin_cpu_init();
- if (__builtin_cpu_supports("avx2")) RETURN_FUNC(wmemset_func, wmemset_avx2);
- RETURN_FUNC(wmemset_func, wmemset_freebsd);
-}
-
typedef int strcmp_func(const char* __lhs, const char* __rhs);
DEFINE_IFUNC_FOR(strcmp) {
__builtin_cpu_init();
diff --git a/libc/arch-x86/generic/string/wmemset.c b/libc/arch-x86/generic/string/wmemset.c
deleted file mode 100644
index 35d489f..0000000
--- a/libc/arch-x86/generic/string/wmemset.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-
-#define wmemset wmemset_freebsd
-
-#include <upstream-freebsd/lib/libc/string/wmemset.c>
diff --git a/libc/arch-x86/kabylake/string/avx2-wmemset-kbl.S b/libc/arch-x86/kabylake/string/avx2-wmemset-kbl.S
deleted file mode 100644
index 69b66c7..0000000
--- a/libc/arch-x86/kabylake/string/avx2-wmemset-kbl.S
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
-Copyright (C) 2019 The Android Open Source Project
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-*/
-
-#include <private/bionic_asm.h>
-
-#ifndef WMEMSET
- #define WMEMSET wmemset_avx2
-#endif
-
-ENTRY(WMEMSET)
-# BB#0:
- pushl %ebp
- pushl %ebx
- pushl %edi
- pushl %esi
- pushl %eax
- movl 32(%esp), %ecx
- movl 24(%esp), %eax
- testl %ecx, %ecx
- je .LBB0_12
-# BB#1:
- movl 28(%esp), %edx
- xorl %edi, %edi
- movl %eax, %esi
- cmpl $32, %ecx
- jb .LBB0_10
-# BB#2:
- movl %ecx, %eax
- andl $-32, %eax
- vmovd %edx, %xmm0
- vpbroadcastd %xmm0, %ymm0
- movl %eax, (%esp) # 4-byte Spill
- leal -32(%eax), %esi
- movl %esi, %eax
- shrl $5, %eax
- leal 1(%eax), %edi
- andl $7, %edi
- xorl %ebx, %ebx
- cmpl $224, %esi
- jb .LBB0_5
-# BB#3:
- movl 24(%esp), %esi
- leal 992(%esi), %ebp
- leal -1(%edi), %esi
- subl %eax, %esi
- xorl %ebx, %ebx
- .p2align 4, 0x90
-.LBB0_4: # =>This Inner Loop Header: Depth=1
- vmovdqu %ymm0, -992(%ebp,%ebx,4)
- vmovdqu %ymm0, -960(%ebp,%ebx,4)
- vmovdqu %ymm0, -928(%ebp,%ebx,4)
- vmovdqu %ymm0, -896(%ebp,%ebx,4)
- vmovdqu %ymm0, -864(%ebp,%ebx,4)
- vmovdqu %ymm0, -832(%ebp,%ebx,4)
- vmovdqu %ymm0, -800(%ebp,%ebx,4)
- vmovdqu %ymm0, -768(%ebp,%ebx,4)
- vmovdqu %ymm0, -736(%ebp,%ebx,4)
- vmovdqu %ymm0, -704(%ebp,%ebx,4)
- vmovdqu %ymm0, -672(%ebp,%ebx,4)
- vmovdqu %ymm0, -640(%ebp,%ebx,4)
- vmovdqu %ymm0, -608(%ebp,%ebx,4)
- vmovdqu %ymm0, -576(%ebp,%ebx,4)
- vmovdqu %ymm0, -544(%ebp,%ebx,4)
- vmovdqu %ymm0, -512(%ebp,%ebx,4)
- vmovdqu %ymm0, -480(%ebp,%ebx,4)
- vmovdqu %ymm0, -448(%ebp,%ebx,4)
- vmovdqu %ymm0, -416(%ebp,%ebx,4)
- vmovdqu %ymm0, -384(%ebp,%ebx,4)
- vmovdqu %ymm0, -352(%ebp,%ebx,4)
- vmovdqu %ymm0, -320(%ebp,%ebx,4)
- vmovdqu %ymm0, -288(%ebp,%ebx,4)
- vmovdqu %ymm0, -256(%ebp,%ebx,4)
- vmovdqu %ymm0, -224(%ebp,%ebx,4)
- vmovdqu %ymm0, -192(%ebp,%ebx,4)
- vmovdqu %ymm0, -160(%ebp,%ebx,4)
- vmovdqu %ymm0, -128(%ebp,%ebx,4)
- vmovdqu %ymm0, -96(%ebp,%ebx,4)
- vmovdqu %ymm0, -64(%ebp,%ebx,4)
- vmovdqu %ymm0, -32(%ebp,%ebx,4)
- vmovdqu %ymm0, (%ebp,%ebx,4)
- addl $256, %ebx # imm = 0x100
- addl $8, %esi
- jne .LBB0_4
-.LBB0_5:
- testl %edi, %edi
- movl 24(%esp), %eax
- je .LBB0_8
-# BB#6:
- leal (%eax,%ebx,4), %esi
- addl $96, %esi
- negl %edi
- .p2align 4, 0x90
-.LBB0_7: # =>This Inner Loop Header: Depth=1
- vmovdqu %ymm0, -96(%esi)
- vmovdqu %ymm0, -64(%esi)
- vmovdqu %ymm0, -32(%esi)
- vmovdqu %ymm0, (%esi)
- subl $-128, %esi
- addl $1, %edi
- jne .LBB0_7
-.LBB0_8:
- movl (%esp), %edi # 4-byte Reload
- cmpl %ecx, %edi
- je .LBB0_12
-# BB#9:
- leal (%eax,%edi,4), %esi
-.LBB0_10:
- subl %edi, %ecx
- .p2align 4, 0x90
-.LBB0_11: # =>This Inner Loop Header: Depth=1
- movl %edx, (%esi)
- addl $4, %esi
- addl $-1, %ecx
- jne .LBB0_11
-.LBB0_12:
- addl $4, %esp
- popl %esi
- popl %edi
- popl %ebx
- popl %ebp
- vzeroupper
- retl
-END(WMEMSET)
diff --git a/libc/arch-x86/static_function_dispatch.S b/libc/arch-x86/static_function_dispatch.S
index 1560c04..7e8e63d 100644
--- a/libc/arch-x86/static_function_dispatch.S
+++ b/libc/arch-x86/static_function_dispatch.S
@@ -45,7 +45,6 @@
FUNCTION_DELEGATE(strncmp, strncmp_generic)
FUNCTION_DELEGATE(strcat, strcat_generic)
FUNCTION_DELEGATE(wmemcmp, wmemcmp_freebsd)
-FUNCTION_DELEGATE(wmemset, wmemset_freebsd)
FUNCTION_DELEGATE(wcscat, wcscat_freebsd)
FUNCTION_DELEGATE(strncat, strncat_openbsd)
FUNCTION_DELEGATE(strlcat, strlcat_openbsd)
diff --git a/libc/arch-x86/silvermont/string/cache.h b/libc/arch-x86/string/cache.h
similarity index 80%
rename from libc/arch-x86/silvermont/string/cache.h
rename to libc/arch-x86/string/cache.h
index c342b1c..33719a0 100644
--- a/libc/arch-x86/silvermont/string/cache.h
+++ b/libc/arch-x86/string/cache.h
@@ -28,9 +28,14 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* Values are optimized for Silvermont */
-#define SHARED_CACHE_SIZE (1024*1024) /* Silvermont L2 Cache */
-#define DATA_CACHE_SIZE (24*1024) /* Silvermont L1 Data Cache */
+#ifdef FOR_ATOM
+#define SHARED_CACHE_SIZE (512 * 1024) /* Atom L2 Cache */
+#endif
+#ifdef FOR_SILVERMONT
+#define SHARED_CACHE_SIZE (1024 * 1024) /* Silvermont L2 Cache */
+#endif
-#define SHARED_CACHE_SIZE_HALF (SHARED_CACHE_SIZE / 2)
-#define DATA_CACHE_SIZE_HALF (DATA_CACHE_SIZE / 2)
+#define DATA_CACHE_SIZE (24 * 1024) /* Atom and Silvermont L1 Data Cache */
+
+#define SHARED_CACHE_SIZE_HALF (SHARED_CACHE_SIZE / 2)
+#define DATA_CACHE_SIZE_HALF (DATA_CACHE_SIZE / 2)
diff --git a/libc/arch-x86/atom/string/sse2-memchr-atom.S b/libc/arch-x86/string/sse2-memchr-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-memchr-atom.S
rename to libc/arch-x86/string/sse2-memchr-atom.S
diff --git a/libc/arch-x86/silvermont/string/sse2-memmove-slm.S b/libc/arch-x86/string/sse2-memmove-slm.S
similarity index 99%
rename from libc/arch-x86/silvermont/string/sse2-memmove-slm.S
rename to libc/arch-x86/string/sse2-memmove-slm.S
index da6456c..79b5d1b 100644
--- a/libc/arch-x86/silvermont/string/sse2-memmove-slm.S
+++ b/libc/arch-x86/string/sse2-memmove-slm.S
@@ -28,6 +28,7 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#define FOR_SILVERMONT
#include "cache.h"
#ifndef MEMMOVE
diff --git a/libc/arch-x86/atom/string/sse2-memrchr-atom.S b/libc/arch-x86/string/sse2-memrchr-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-memrchr-atom.S
rename to libc/arch-x86/string/sse2-memrchr-atom.S
diff --git a/libc/arch-x86/atom/string/sse2-memset-atom.S b/libc/arch-x86/string/sse2-memset-atom.S
similarity index 99%
rename from libc/arch-x86/atom/string/sse2-memset-atom.S
rename to libc/arch-x86/string/sse2-memset-atom.S
index e4cd038..320afec 100644
--- a/libc/arch-x86/atom/string/sse2-memset-atom.S
+++ b/libc/arch-x86/string/sse2-memset-atom.S
@@ -30,6 +30,7 @@
#include <private/bionic_asm.h>
+#define FOR_ATOM
#include "cache.h"
#ifndef L
diff --git a/libc/arch-x86/silvermont/string/sse2-memset-slm.S b/libc/arch-x86/string/sse2-memset-slm.S
similarity index 99%
rename from libc/arch-x86/silvermont/string/sse2-memset-slm.S
rename to libc/arch-x86/string/sse2-memset-slm.S
index b7633f5..5cff141 100644
--- a/libc/arch-x86/silvermont/string/sse2-memset-slm.S
+++ b/libc/arch-x86/string/sse2-memset-slm.S
@@ -30,6 +30,7 @@
#include <private/bionic_asm.h>
+#define FOR_SILVERMONT
#include "cache.h"
#ifndef L
diff --git a/libc/arch-x86/silvermont/string/sse2-stpcpy-slm.S b/libc/arch-x86/string/sse2-stpcpy-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse2-stpcpy-slm.S
rename to libc/arch-x86/string/sse2-stpcpy-slm.S
diff --git a/libc/arch-x86/silvermont/string/sse2-stpncpy-slm.S b/libc/arch-x86/string/sse2-stpncpy-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse2-stpncpy-slm.S
rename to libc/arch-x86/string/sse2-stpncpy-slm.S
diff --git a/libc/arch-x86/atom/string/sse2-strchr-atom.S b/libc/arch-x86/string/sse2-strchr-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-strchr-atom.S
rename to libc/arch-x86/string/sse2-strchr-atom.S
diff --git a/libc/arch-x86/silvermont/string/sse2-strcpy-slm.S b/libc/arch-x86/string/sse2-strcpy-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse2-strcpy-slm.S
rename to libc/arch-x86/string/sse2-strcpy-slm.S
diff --git a/libc/arch-x86/atom/string/sse2-strlen-atom.S b/libc/arch-x86/string/sse2-strlen-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-strlen-atom.S
rename to libc/arch-x86/string/sse2-strlen-atom.S
diff --git a/libc/arch-x86/silvermont/string/sse2-strlen-slm.S b/libc/arch-x86/string/sse2-strlen-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse2-strlen-slm.S
rename to libc/arch-x86/string/sse2-strlen-slm.S
diff --git a/libc/arch-x86/silvermont/string/sse2-strncpy-slm.S b/libc/arch-x86/string/sse2-strncpy-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse2-strncpy-slm.S
rename to libc/arch-x86/string/sse2-strncpy-slm.S
diff --git a/libc/arch-x86/atom/string/sse2-strnlen-atom.S b/libc/arch-x86/string/sse2-strnlen-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-strnlen-atom.S
rename to libc/arch-x86/string/sse2-strnlen-atom.S
diff --git a/libc/arch-x86/atom/string/sse2-strrchr-atom.S b/libc/arch-x86/string/sse2-strrchr-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-strrchr-atom.S
rename to libc/arch-x86/string/sse2-strrchr-atom.S
diff --git a/libc/arch-x86/atom/string/sse2-wcschr-atom.S b/libc/arch-x86/string/sse2-wcschr-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-wcschr-atom.S
rename to libc/arch-x86/string/sse2-wcschr-atom.S
diff --git a/libc/arch-x86/atom/string/sse2-wcscmp-atom.S b/libc/arch-x86/string/sse2-wcscmp-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-wcscmp-atom.S
rename to libc/arch-x86/string/sse2-wcscmp-atom.S
diff --git a/libc/arch-x86/atom/string/sse2-wcslen-atom.S b/libc/arch-x86/string/sse2-wcslen-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-wcslen-atom.S
rename to libc/arch-x86/string/sse2-wcslen-atom.S
diff --git a/libc/arch-x86/atom/string/sse2-wcsrchr-atom.S b/libc/arch-x86/string/sse2-wcsrchr-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-wcsrchr-atom.S
rename to libc/arch-x86/string/sse2-wcsrchr-atom.S
diff --git a/libc/arch-x86/silvermont/string/sse4-memcmp-slm.S b/libc/arch-x86/string/sse4-memcmp-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse4-memcmp-slm.S
rename to libc/arch-x86/string/sse4-memcmp-slm.S
diff --git a/libc/arch-x86/silvermont/string/sse4-wmemcmp-slm.S b/libc/arch-x86/string/sse4-wmemcmp-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse4-wmemcmp-slm.S
rename to libc/arch-x86/string/sse4-wmemcmp-slm.S
diff --git a/libc/arch-x86/atom/string/ssse3-memcmp-atom.S b/libc/arch-x86/string/ssse3-memcmp-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-memcmp-atom.S
rename to libc/arch-x86/string/ssse3-memcmp-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-memcpy-atom.S b/libc/arch-x86/string/ssse3-memcpy-atom.S
similarity index 99%
rename from libc/arch-x86/atom/string/ssse3-memcpy-atom.S
rename to libc/arch-x86/string/ssse3-memcpy-atom.S
index 5532e2e..fe3082e 100644
--- a/libc/arch-x86/atom/string/ssse3-memcpy-atom.S
+++ b/libc/arch-x86/string/ssse3-memcpy-atom.S
@@ -28,6 +28,7 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#define FOR_ATOM
#include "cache.h"
#ifndef MEMCPY
diff --git a/libc/arch-x86/atom/string/ssse3-memmove-atom.S b/libc/arch-x86/string/ssse3-memmove-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-memmove-atom.S
rename to libc/arch-x86/string/ssse3-memmove-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strcat-atom.S b/libc/arch-x86/string/ssse3-strcat-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strcat-atom.S
rename to libc/arch-x86/string/ssse3-strcat-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strcmp-atom.S b/libc/arch-x86/string/ssse3-strcmp-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strcmp-atom.S
rename to libc/arch-x86/string/ssse3-strcmp-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strcpy-atom.S b/libc/arch-x86/string/ssse3-strcpy-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strcpy-atom.S
rename to libc/arch-x86/string/ssse3-strcpy-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strlcat-atom.S b/libc/arch-x86/string/ssse3-strlcat-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strlcat-atom.S
rename to libc/arch-x86/string/ssse3-strlcat-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strlcpy-atom.S b/libc/arch-x86/string/ssse3-strlcpy-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strlcpy-atom.S
rename to libc/arch-x86/string/ssse3-strlcpy-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strncat-atom.S b/libc/arch-x86/string/ssse3-strncat-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strncat-atom.S
rename to libc/arch-x86/string/ssse3-strncat-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strncmp-atom.S b/libc/arch-x86/string/ssse3-strncmp-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strncmp-atom.S
rename to libc/arch-x86/string/ssse3-strncmp-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strncpy-atom.S b/libc/arch-x86/string/ssse3-strncpy-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strncpy-atom.S
rename to libc/arch-x86/string/ssse3-strncpy-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-wcscat-atom.S b/libc/arch-x86/string/ssse3-wcscat-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-wcscat-atom.S
rename to libc/arch-x86/string/ssse3-wcscat-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-wcscpy-atom.S b/libc/arch-x86/string/ssse3-wcscpy-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-wcscpy-atom.S
rename to libc/arch-x86/string/ssse3-wcscpy-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-wmemcmp-atom.S b/libc/arch-x86/string/ssse3-wmemcmp-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-wmemcmp-atom.S
rename to libc/arch-x86/string/ssse3-wmemcmp-atom.S
diff --git a/libc/arch-x86_64/dynamic_function_dispatch.cpp b/libc/arch-x86_64/dynamic_function_dispatch.cpp
new file mode 100644
index 0000000..c846ded
--- /dev/null
+++ b/libc/arch-x86_64/dynamic_function_dispatch.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+
+#include <private/bionic_ifuncs.h>
+
+extern "C" {
+
+typedef int memset_func(void* __dst, int __ch, size_t __n);
+DEFINE_IFUNC_FOR(memset) {
+ __builtin_cpu_init();
+ if (__builtin_cpu_supports("avx2")) RETURN_FUNC(memset_func, memset_avx2);
+ RETURN_FUNC(memset_func, memset_generic);
+}
+
+typedef void* __memset_chk_func(void* s, int c, size_t n, size_t n2);
+DEFINE_IFUNC_FOR(__memset_chk) {
+ __builtin_cpu_init();
+ if (__builtin_cpu_supports("avx2")) RETURN_FUNC(__memset_chk_func, __memset_chk_avx2);
+ RETURN_FUNC(__memset_chk_func, __memset_chk_generic);
+}
+
+} // extern "C"
diff --git a/libc/arch-x86_64/static_function_dispatch.S b/libc/arch-x86_64/static_function_dispatch.S
new file mode 100644
index 0000000..93ff5f2
--- /dev/null
+++ b/libc/arch-x86_64/static_function_dispatch.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+
+#define FUNCTION_DELEGATE(name, impl) \
+ENTRY(name); \
+ jmp impl; \
+END(name)
+
+FUNCTION_DELEGATE(memset, memset_generic)
+FUNCTION_DELEGATE(__memset_chk, __memset_chk_generic)
diff --git a/libc/arch-x86_64/string/avx2-memset-kbl.S b/libc/arch-x86_64/string/avx2-memset-kbl.S
new file mode 100644
index 0000000..09dd07d
--- /dev/null
+++ b/libc/arch-x86_64/string/avx2-memset-kbl.S
@@ -0,0 +1,160 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <private/bionic_asm.h>
+
+#include "cache.h"
+
+#ifndef L
+# define L(label) .L##label
+#endif
+
+#ifndef ALIGN
+# define ALIGN(n) .p2align n
+#endif
+
+ .section .text.avx2,"ax",@progbits
+
+ENTRY(__memset_chk_avx2)
+ # %rdi = dst, %rsi = byte, %rdx = n, %rcx = dst_len
+ cmp %rcx, %rdx
+ ja __memset_chk_fail
+ // Fall through to memset...
+END(__memset_chk_avx2)
+
+ENTRY(memset_avx2)
+ movq %rdi, %rax
+ and $0xff, %rsi
+ mov $0x0101010101010101, %rcx
+ imul %rsi, %rcx
+ cmpq $16, %rdx
+ jae L(16bytesormore)
+ testb $8, %dl
+ jnz L(8_15bytes)
+ testb $4, %dl
+ jnz L(4_7bytes)
+ testb $2, %dl
+ jnz L(2_3bytes)
+ testb $1, %dl
+ jz L(return)
+ movb %cl, (%rdi)
+L(return):
+ ret
+
+L(8_15bytes):
+ movq %rcx, (%rdi)
+ movq %rcx, -8(%rdi, %rdx)
+ ret
+
+L(4_7bytes):
+ movl %ecx, (%rdi)
+ movl %ecx, -4(%rdi, %rdx)
+ ret
+
+L(2_3bytes):
+ movw %cx, (%rdi)
+ movw %cx, -2(%rdi, %rdx)
+ ret
+
+ ALIGN (4)
+L(16bytesormore):
+ movd %rcx, %xmm0
+ pshufd $0, %xmm0, %xmm0
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm0, -16(%rdi, %rdx)
+ cmpq $32, %rdx
+ jbe L(32bytesless)
+ movdqu %xmm0, 16(%rdi)
+ movdqu %xmm0, -32(%rdi, %rdx)
+ cmpq $64, %rdx
+ jbe L(64bytesless)
+ movdqu %xmm0, 32(%rdi)
+ movdqu %xmm0, 48(%rdi)
+ movdqu %xmm0, -64(%rdi, %rdx)
+ movdqu %xmm0, -48(%rdi, %rdx)
+ cmpq $128, %rdx
+ jbe L(128bytesless)
+ vpbroadcastb %xmm0, %ymm0
+ vmovdqu %ymm0, 64(%rdi)
+ vmovdqu %ymm0, 96(%rdi)
+ vmovdqu %ymm0, -128(%rdi, %rdx)
+ vmovdqu %ymm0, -96(%rdi, %rdx)
+ cmpq $256, %rdx
+ ja L(256bytesmore)
+L(32bytesless):
+L(64bytesless):
+L(128bytesless):
+ ret
+
+ ALIGN (4)
+L(256bytesmore):
+ leaq 128(%rdi), %rcx
+ andq $-128, %rcx
+ movq %rdx, %r8
+ addq %rdi, %rdx
+ andq $-128, %rdx
+ cmpq %rcx, %rdx
+ je L(return)
+
+#ifdef SHARED_CACHE_SIZE
+ cmp $SHARED_CACHE_SIZE, %r8
+#else
+ cmp __x86_64_shared_cache_size(%rip), %r8
+#endif
+ ja L(256bytesmore_nt)
+
+ ALIGN (4)
+L(256bytesmore_normal):
+ vmovdqa %ymm0, (%rcx)
+ vmovdqa %ymm0, 32(%rcx)
+ vmovdqa %ymm0, 64(%rcx)
+ vmovdqa %ymm0, 96(%rcx)
+ addq $128, %rcx
+ cmpq %rcx, %rdx
+ jne L(256bytesmore_normal)
+ ret
+
+ ALIGN (4)
+L(256bytesmore_nt):
+ movntdq %xmm0, (%rcx)
+ movntdq %xmm0, 16(%rcx)
+ movntdq %xmm0, 32(%rcx)
+ movntdq %xmm0, 48(%rcx)
+ movntdq %xmm0, 64(%rcx)
+ movntdq %xmm0, 80(%rcx)
+ movntdq %xmm0, 96(%rcx)
+ movntdq %xmm0, 112(%rcx)
+ leaq 128(%rcx), %rcx
+ cmpq %rcx, %rdx
+ jne L(256bytesmore_nt)
+ sfence
+ ret
+
+END(memset_avx2)
diff --git a/libc/arch-x86_64/string/avx2-wmemset-kbl.S b/libc/arch-x86_64/string/avx2-wmemset-kbl.S
deleted file mode 100644
index 7c485cf..0000000
--- a/libc/arch-x86_64/string/avx2-wmemset-kbl.S
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
-Copyright (C) 2019 The Android Open Source Project
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-*/
-
-#include <private/bionic_asm.h>
-
-#ifndef WMEMSET
- #define WMEMSET wmemset_avx2
-#endif
-
- .section .text.avx2,"ax",@progbits
-
-ENTRY (WMEMSET)
-# BB#0:
- testq %rdx, %rdx
- je .LBB0_14
-# BB#1:
- cmpq $32, %rdx
- jae .LBB0_3
-# BB#2:
- xorl %r8d, %r8d
- movq %rdi, %rax
- jmp .LBB0_12
-.LBB0_3:
- movq %rdx, %r8
- andq $-32, %r8
- vmovd %esi, %xmm0
- vpbroadcastd %xmm0, %ymm0
- leaq -32(%r8), %rcx
- movq %rcx, %rax
- shrq $5, %rax
- leal 1(%rax), %r9d
- andl $7, %r9d
- cmpq $224, %rcx
- jae .LBB0_5
-# BB#4:
- xorl %eax, %eax
- testq %r9, %r9
- jne .LBB0_8
- jmp .LBB0_10
-.LBB0_5:
- leaq 992(%rdi), %rcx
- leaq -1(%r9), %r10
- subq %rax, %r10
- xorl %eax, %eax
- .p2align 4, 0x90
-.LBB0_6: # =>This Inner Loop Header: Depth=1
- vmovdqu %ymm0, -992(%rcx,%rax,4)
- vmovdqu %ymm0, -960(%rcx,%rax,4)
- vmovdqu %ymm0, -928(%rcx,%rax,4)
- vmovdqu %ymm0, -896(%rcx,%rax,4)
- vmovdqu %ymm0, -864(%rcx,%rax,4)
- vmovdqu %ymm0, -832(%rcx,%rax,4)
- vmovdqu %ymm0, -800(%rcx,%rax,4)
- vmovdqu %ymm0, -768(%rcx,%rax,4)
- vmovdqu %ymm0, -736(%rcx,%rax,4)
- vmovdqu %ymm0, -704(%rcx,%rax,4)
- vmovdqu %ymm0, -672(%rcx,%rax,4)
- vmovdqu %ymm0, -640(%rcx,%rax,4)
- vmovdqu %ymm0, -608(%rcx,%rax,4)
- vmovdqu %ymm0, -576(%rcx,%rax,4)
- vmovdqu %ymm0, -544(%rcx,%rax,4)
- vmovdqu %ymm0, -512(%rcx,%rax,4)
- vmovdqu %ymm0, -480(%rcx,%rax,4)
- vmovdqu %ymm0, -448(%rcx,%rax,4)
- vmovdqu %ymm0, -416(%rcx,%rax,4)
- vmovdqu %ymm0, -384(%rcx,%rax,4)
- vmovdqu %ymm0, -352(%rcx,%rax,4)
- vmovdqu %ymm0, -320(%rcx,%rax,4)
- vmovdqu %ymm0, -288(%rcx,%rax,4)
- vmovdqu %ymm0, -256(%rcx,%rax,4)
- vmovdqu %ymm0, -224(%rcx,%rax,4)
- vmovdqu %ymm0, -192(%rcx,%rax,4)
- vmovdqu %ymm0, -160(%rcx,%rax,4)
- vmovdqu %ymm0, -128(%rcx,%rax,4)
- vmovdqu %ymm0, -96(%rcx,%rax,4)
- vmovdqu %ymm0, -64(%rcx,%rax,4)
- vmovdqu %ymm0, -32(%rcx,%rax,4)
- vmovdqu %ymm0, (%rcx,%rax,4)
- addq $256, %rax # imm = 0x100
- addq $8, %r10
- jne .LBB0_6
-# BB#7:
- testq %r9, %r9
- je .LBB0_10
-.LBB0_8:
- leaq (%rdi,%rax,4), %rax
- addq $96, %rax
- negq %r9
- .p2align 4, 0x90
-.LBB0_9: # =>This Inner Loop Header: Depth=1
- vmovdqu %ymm0, -96(%rax)
- vmovdqu %ymm0, -64(%rax)
- vmovdqu %ymm0, -32(%rax)
- vmovdqu %ymm0, (%rax)
- subq $-128, %rax
- addq $1, %r9
- jne .LBB0_9
-.LBB0_10:
- cmpq %rdx, %r8
- je .LBB0_14
-# BB#11:
- leaq (%rdi,%r8,4), %rax
-.LBB0_12:
- subq %r8, %rdx
- .p2align 4, 0x90
-.LBB0_13: # =>This Inner Loop Header: Depth=1
- movl %esi, (%rax)
- addq $4, %rax
- addq $-1, %rdx
- jne .LBB0_13
-.LBB0_14:
- movq %rdi, %rax
- vzeroupper
- retq
-END(WMEMSET)
diff --git a/libc/arch-x86_64/string/sse2-memset-slm.S b/libc/arch-x86_64/string/sse2-memset-slm.S
index fc502c0..cceadd2 100644
--- a/libc/arch-x86_64/string/sse2-memset-slm.S
+++ b/libc/arch-x86_64/string/sse2-memset-slm.S
@@ -41,16 +41,16 @@
#endif
-ENTRY(__memset_chk)
+ENTRY(__memset_chk_generic)
# %rdi = dst, %rsi = byte, %rdx = n, %rcx = dst_len
cmp %rcx, %rdx
ja __memset_chk_fail
// Fall through to memset...
-END(__memset_chk)
+END(__memset_chk_generic)
.section .text.sse2,"ax",@progbits
-ENTRY(memset)
+ENTRY(memset_generic)
movq %rdi, %rax
and $0xff, %rsi
mov $0x0101010101010101, %rcx
@@ -146,4 +146,4 @@
sfence
ret
-END(memset)
+END(memset_generic)
diff --git a/libc/async_safe/Android.bp b/libc/async_safe/Android.bp
index 531317d..eb690dd 100644
--- a/libc/async_safe/Android.bp
+++ b/libc/async_safe/Android.bp
@@ -30,13 +30,8 @@
stl: "none",
apex_available: [
+ "//apex_available:anyapex",
"//apex_available:platform",
- "com.android.runtime",
- "com.android.art",
- "com.android.art.debug",
- "com.android.media",
- "com.android.media.swcodec",
- "com.android.virt",
],
min_sdk_version: "apex_inherit",
}
diff --git a/libc/bionic/android_profiling_dynamic.cpp b/libc/bionic/android_profiling_dynamic.cpp
index 3460a6d..8c9127e 100644
--- a/libc/bionic/android_profiling_dynamic.cpp
+++ b/libc/bionic/android_profiling_dynamic.cpp
@@ -204,12 +204,14 @@
auto ret = -ENOSYS;
ucontext_t* ctx = reinterpret_cast<ucontext_t*>(void_context);
-#if defined(__arm__)
+#if defined(__aarch64__)
+ ctx->uc_mcontext.regs[0] = ret;
+#elif defined(__arm__)
ctx->uc_mcontext.arm_r0 = ret;
-#elif defined(__aarch64__)
- ctx->uc_mcontext.regs[0] = ret; // x0
#elif defined(__i386__)
ctx->uc_mcontext.gregs[REG_EAX] = ret;
+#elif defined(__riscv)
+ ctx->uc_mcontext.__gregs[REG_A0] = ret;
#elif defined(__x86_64__)
ctx->uc_mcontext.gregs[REG_RAX] = ret;
#else
diff --git a/libc/bionic/bionic_elf_tls.cpp b/libc/bionic/bionic_elf_tls.cpp
index d5fb05a..79893e3 100644
--- a/libc/bionic/bionic_elf_tls.cpp
+++ b/libc/bionic/bionic_elf_tls.cpp
@@ -137,6 +137,15 @@
offset_bionic_tcb_ = reserve(sizeof(bionic_tcb), max_align);
return offset_bionic_tcb_ - exe_size;
+#elif defined(__riscv)
+
+ // First reserve enough space for the TCB before the executable segment.
+ offset_bionic_tcb_ = reserve(sizeof(bionic_tcb), 1);
+
+ // Then reserve the segment itself.
+ const size_t exe_size = round_up_with_overflow_check(exe_segment->size, exe_segment->alignment);
+ return reserve(exe_size, 1);
+
#else
#error "Unrecognized architecture"
#endif
@@ -312,7 +321,7 @@
}
}
- return static_cast<char*>(mod_ptr) + ti->offset;
+ return static_cast<char*>(mod_ptr) + ti->offset + TLS_DTV_OFFSET;
}
// Returns the address of a thread's TLS memory given a module ID and an offset
@@ -332,7 +341,7 @@
if (__predict_true(generation == dtv->generation)) {
void* mod_ptr = dtv->modules[__tls_module_id_to_idx(ti->module_id)];
if (__predict_true(mod_ptr != nullptr)) {
- return static_cast<char*>(mod_ptr) + ti->offset;
+ return static_cast<char*>(mod_ptr) + ti->offset + TLS_DTV_OFFSET;
}
}
diff --git a/libc/bionic/exec.cpp b/libc/bionic/exec.cpp
index fd2c401..40612e7 100644
--- a/libc/bionic/exec.cpp
+++ b/libc/bionic/exec.cpp
@@ -39,10 +39,12 @@
#include <string.h>
#include <unistd.h>
-#include "private/__bionic_get_shell_path.h"
#include "private/FdPath.h"
+#include "private/__bionic_get_shell_path.h"
+#include "pthread_internal.h"
extern "C" char** environ;
+extern "C" int __execve(const char* pathname, char* const* argv, char* const* envp);
enum { ExecL, ExecLE, ExecLP };
@@ -181,3 +183,9 @@
if (errno == ENOENT) errno = EBADF;
return -1;
}
+
+__attribute__((no_sanitize("memtag"))) int execve(const char* pathname, char* const* argv,
+ char* const* envp) {
+ __get_thread()->vfork_child_stack_bottom = __builtin_frame_address(0);
+ return __execve(pathname, argv, envp);
+}
diff --git a/libc/bionic/exit.cpp b/libc/bionic/exit.cpp
index a5aed78..52fd193 100644
--- a/libc/bionic/exit.cpp
+++ b/libc/bionic/exit.cpp
@@ -30,9 +30,18 @@
#include <unistd.h>
#include "private/bionic_defs.h"
+#include "pthread_internal.h"
extern "C" void __cxa_finalize(void* dso_handle);
extern "C" void __cxa_thread_finalize();
+extern "C" __noreturn void __exit_group(int status);
+
+__attribute__((no_sanitize("memtag"))) void _exit(int status) {
+ __get_thread()->vfork_child_stack_bottom = __builtin_frame_address(0);
+ __exit_group(status);
+}
+
+__strong_alias(_Exit, _exit);
__BIONIC_WEAK_FOR_NATIVE_BRIDGE
void exit(int status) {
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index 48e8674..6433b59 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -101,7 +101,7 @@
}
size_t offset = idx - inline_fds;
- if (local_overflow->len < offset) {
+ if (local_overflow->len <= offset) {
return nullptr;
}
return &local_overflow->entries[offset];
@@ -216,6 +216,8 @@
return "SocketImpl";
case ANDROID_FDSAN_OWNER_TYPE_ZIPARCHIVE:
return "ZipArchive";
+ case ANDROID_FDSAN_OWNER_TYPE_NATIVE_HANDLE:
+ return "native_handle_t";
case ANDROID_FDSAN_OWNER_TYPE_GENERIC_00:
default:
diff --git a/libc/bionic/gwp_asan_wrappers.cpp b/libc/bionic/gwp_asan_wrappers.cpp
index 7e19b31..fc59c88 100644
--- a/libc/bionic/gwp_asan_wrappers.cpp
+++ b/libc/bionic/gwp_asan_wrappers.cpp
@@ -41,6 +41,7 @@
#include "gwp_asan_wrappers.h"
#include "malloc_common.h"
#include "platform/bionic/android_unsafe_frame_pointer_chase.h"
+#include "platform/bionic/macros.h"
#include "platform/bionic/malloc.h"
#include "private/bionic_arc4random.h"
#include "private/bionic_globals.h"
@@ -221,6 +222,8 @@
static const char* kMaxAllocsTargetedSyspropPrefix = "libc.debug.gwp_asan.max_allocs.";
static const char* kMaxAllocsEnvVar = "GWP_ASAN_MAX_ALLOCS";
+static const char kPersistPrefix[] = "persist.";
+
void SetDefaultGwpAsanOptions(Options* options, unsigned* process_sample_rate,
const android_mallopt_gwp_asan_options_t& mallopt_options) {
options->Enabled = true;
@@ -244,26 +247,40 @@
const char* basename = "";
if (mallopt_options.program_name) basename = __gnu_basename(mallopt_options.program_name);
- size_t program_specific_sysprop_size = strlen(targeted_sysprop_prefix) + strlen(basename) + 1;
- char* program_specific_sysprop_name = static_cast<char*>(alloca(program_specific_sysprop_size));
- async_safe_format_buffer(program_specific_sysprop_name, program_specific_sysprop_size, "%s%s",
- targeted_sysprop_prefix, basename);
-
- const char* sysprop_names[2] = {nullptr, nullptr};
+ constexpr size_t kSyspropMaxLen = 512;
+ char program_specific_sysprop[kSyspropMaxLen] = {};
+ char persist_program_specific_sysprop[kSyspropMaxLen] = {};
+ char persist_default_sysprop[kSyspropMaxLen] = {};
+ const char* sysprop_names[4] = {};
// Tests use a blank program name to specify that system properties should not
// be used. Tests still continue to use the environment variable though.
if (*basename != '\0') {
- sysprop_names[0] = program_specific_sysprop_name;
+ const char* default_sysprop = system_sysprop;
if (mallopt_options.desire == Action::TURN_ON_FOR_APP) {
- sysprop_names[1] = app_sysprop;
- } else {
- sysprop_names[1] = system_sysprop;
+ default_sysprop = app_sysprop;
}
+ async_safe_format_buffer(&program_specific_sysprop[0], kSyspropMaxLen, "%s%s",
+ targeted_sysprop_prefix, basename);
+ async_safe_format_buffer(&persist_program_specific_sysprop[0], kSyspropMaxLen, "%s%s",
+ kPersistPrefix, program_specific_sysprop);
+ async_safe_format_buffer(&persist_default_sysprop[0], kSyspropMaxLen, "%s%s", kPersistPrefix,
+ default_sysprop);
+
+ // In order of precedence, always take the program-specific sysprop (e.g.
+ // '[persist.]libc.debug.gwp_asan.sample_rate.cameraserver') over the
+ // generic sysprop (e.g.
+ // '[persist.]libc.debug.gwp_asan.(system_default|app_default)'). In
+ // addition, always take the non-persistent option over the persistent
+ // option.
+ sysprop_names[0] = program_specific_sysprop;
+ sysprop_names[1] = persist_program_specific_sysprop;
+ sysprop_names[2] = default_sysprop;
+ sysprop_names[3] = persist_default_sysprop;
}
char settings_buf[PROP_VALUE_MAX];
- if (!get_config_from_env_or_sysprops(env_var, sysprop_names,
- /* sys_prop_names_size */ 2, settings_buf, PROP_VALUE_MAX)) {
+ if (!get_config_from_env_or_sysprops(env_var, sysprop_names, arraysize(sysprop_names),
+ settings_buf, PROP_VALUE_MAX)) {
return false;
}
diff --git a/libc/bionic/heap_tagging.cpp b/libc/bionic/heap_tagging.cpp
index 41aa205..78d21b0 100644
--- a/libc/bionic/heap_tagging.cpp
+++ b/libc/bionic/heap_tagging.cpp
@@ -32,6 +32,8 @@
#include <bionic/pthread_internal.h>
#include <platform/bionic/malloc.h>
+#include <sanitizer/hwasan_interface.h>
+#include <sys/auxv.h>
extern "C" void scudo_malloc_disable_memory_tagging();
extern "C" void scudo_malloc_set_track_allocation_stacks(int);
@@ -44,61 +46,61 @@
#if !__has_feature(hwaddress_sanitizer)
heap_tagging_level = __libc_shared_globals()->initial_heap_tagging_level;
#endif
- switch (heap_tagging_level) {
- case M_HEAP_TAGGING_LEVEL_TBI:
- __libc_globals.mutate([](libc_globals* globals) {
+
+ __libc_globals.mutate([](libc_globals* globals) {
+ switch (heap_tagging_level) {
+ case M_HEAP_TAGGING_LEVEL_TBI:
// Arrange for us to set pointer tags to POINTER_TAG, check tags on
// deallocation and untag when passing pointers to the allocator.
globals->heap_pointer_tag = (reinterpret_cast<uintptr_t>(POINTER_TAG) << TAG_SHIFT) |
(0xffull << CHECK_SHIFT) | (0xffull << UNTAG_SHIFT);
- });
-#if defined(USE_SCUDO)
- scudo_malloc_disable_memory_tagging();
-#endif // USE_SCUDO
- break;
-#if defined(USE_SCUDO)
- case M_HEAP_TAGGING_LEVEL_SYNC:
- scudo_malloc_set_track_allocation_stacks(1);
- break;
+ break;
+ case M_HEAP_TAGGING_LEVEL_SYNC:
+ case M_HEAP_TAGGING_LEVEL_ASYNC:
+ atomic_store(&globals->memtag_stack, __libc_shared_globals()->initial_memtag_stack);
+ break;
+ default:
+ break;
+ };
+ });
+#if defined(USE_SCUDO)
+ switch (heap_tagging_level) {
+ case M_HEAP_TAGGING_LEVEL_TBI:
case M_HEAP_TAGGING_LEVEL_NONE:
scudo_malloc_disable_memory_tagging();
break;
-#endif // USE_SCUDO
+ case M_HEAP_TAGGING_LEVEL_SYNC:
+ scudo_malloc_set_track_allocation_stacks(1);
+ break;
default:
break;
}
+#endif // USE_SCUDO
#endif // aarch64
}
static bool set_tcf_on_all_threads(int tcf) {
- static int g_tcf;
- g_tcf = tcf;
-
return android_run_on_all_threads(
- [](void*) {
+ [](void* arg) {
+ int tcf = *reinterpret_cast<int*>(arg);
int tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
if (tagged_addr_ctrl < 0) {
return false;
}
- tagged_addr_ctrl = (tagged_addr_ctrl & ~PR_MTE_TCF_MASK) | g_tcf;
+ tagged_addr_ctrl = (tagged_addr_ctrl & ~PR_MTE_TCF_MASK) | tcf;
if (prctl(PR_SET_TAGGED_ADDR_CTRL, tagged_addr_ctrl, 0, 0, 0) < 0) {
return false;
}
return true;
},
- nullptr);
+ &tcf);
}
pthread_mutex_t g_heap_tagging_lock = PTHREAD_MUTEX_INITIALIZER;
// Requires `g_heap_tagging_lock` to be held.
-HeapTaggingLevel GetHeapTaggingLevel() {
- return heap_tagging_level;
-}
-
-// Requires `g_heap_tagging_lock` to be held.
bool SetHeapTaggingLevel(HeapTaggingLevel tag_level) {
if (tag_level == heap_tagging_level) {
return true;
@@ -106,16 +108,21 @@
switch (tag_level) {
case M_HEAP_TAGGING_LEVEL_NONE:
- if (heap_tagging_level == M_HEAP_TAGGING_LEVEL_TBI) {
- __libc_globals.mutate([](libc_globals* globals) {
+ __libc_globals.mutate([](libc_globals* globals) {
+ if (heap_tagging_level == M_HEAP_TAGGING_LEVEL_TBI) {
// Preserve the untag mask (we still want to untag pointers when passing them to the
// allocator), but clear the fixed tag and the check mask, so that pointers are no longer
// tagged and checks no longer happen.
globals->heap_pointer_tag = static_cast<uintptr_t>(0xffull << UNTAG_SHIFT);
- });
- } else if (!set_tcf_on_all_threads(PR_MTE_TCF_NONE)) {
- error_log("SetHeapTaggingLevel: set_tcf_on_all_threads failed");
- return false;
+ }
+ atomic_store(&globals->memtag_stack, false);
+ });
+
+ if (heap_tagging_level != M_HEAP_TAGGING_LEVEL_TBI) {
+ if (!set_tcf_on_all_threads(PR_MTE_TCF_NONE)) {
+ error_log("SetHeapTaggingLevel: set_tcf_on_all_threads failed");
+ return false;
+ }
}
#if defined(USE_SCUDO)
scudo_malloc_disable_memory_tagging();
@@ -165,3 +172,69 @@
return true;
}
+
+#ifdef __aarch64__
+static inline __attribute__((no_sanitize("memtag"))) void untag_memory(void* from, void* to) {
+ __asm__ __volatile__(
+ ".arch_extension mte\n"
+ "1:\n"
+ "stg %[Ptr], [%[Ptr]], #16\n"
+ "cmp %[Ptr], %[End]\n"
+ "b.lt 1b\n"
+ : [Ptr] "+&r"(from)
+ : [End] "r"(to)
+ : "memory");
+}
+#endif
+
+#ifdef __aarch64__
+// 128Mb of stack should be enough for anybody.
+static constexpr size_t kUntagLimit = 128 * 1024 * 1024;
+#endif // __aarch64__
+
+extern "C" __LIBC_HIDDEN__ __attribute__((no_sanitize("memtag"))) void memtag_handle_longjmp(
+ void* sp_dst __unused) {
+#ifdef __aarch64__
+ if (__libc_globals->memtag_stack) {
+ void* sp = __builtin_frame_address(0);
+ size_t distance = reinterpret_cast<uintptr_t>(sp_dst) - reinterpret_cast<uintptr_t>(sp);
+ if (distance > kUntagLimit) {
+ async_safe_fatal(
+ "memtag_handle_longjmp: stack adjustment too large! %p -> %p, distance %zx > %zx\n", sp,
+ sp_dst, distance, kUntagLimit);
+ } else {
+ untag_memory(sp, sp_dst);
+ }
+ }
+#endif // __aarch64__
+
+#if __has_feature(hwaddress_sanitizer)
+ __hwasan_handle_longjmp(sp_dst);
+#endif // __has_feature(hwaddress_sanitizer)
+}
+
+extern "C" __LIBC_HIDDEN__ __attribute__((no_sanitize("memtag"), no_sanitize("hwaddress"))) void
+memtag_handle_vfork(void* sp __unused) {
+#ifdef __aarch64__
+ if (__libc_globals->memtag_stack) {
+ void* child_sp = __get_thread()->vfork_child_stack_bottom;
+ __get_thread()->vfork_child_stack_bottom = nullptr;
+ if (child_sp) {
+ size_t distance = reinterpret_cast<uintptr_t>(sp) - reinterpret_cast<uintptr_t>(child_sp);
+ if (distance > kUntagLimit) {
+ async_safe_fatal(
+ "memtag_handle_vfork: stack adjustment too large! %p -> %p, distance %zx > %zx\n",
+ child_sp, sp, distance, kUntagLimit);
+ } else {
+ untag_memory(child_sp, sp);
+ }
+ } else {
+ async_safe_fatal("memtag_handle_vfork: child SP unknown\n");
+ }
+ }
+#endif // __aarch64__
+
+#if __has_feature(hwaddress_sanitizer)
+ __hwasan_handle_vfork(sp);
+#endif // __has_feature(hwaddress_sanitizer)
+}
diff --git a/libc/bionic/heap_tagging.h b/libc/bionic/heap_tagging.h
index 110b6ed..5bc1da0 100644
--- a/libc/bionic/heap_tagging.h
+++ b/libc/bionic/heap_tagging.h
@@ -40,7 +40,22 @@
// useful for RAII on this lock.
extern pthread_mutex_t g_heap_tagging_lock;
-// These functions can be called in a multithreaded context, and thus should
+// This function can be called in a multithreaded context, and thus should
// only be called when holding the `g_heap_tagging_lock`.
bool SetHeapTaggingLevel(HeapTaggingLevel level);
-HeapTaggingLevel GetHeapTaggingLevel();
+
+// This is static because libc_nomalloc uses this but does not need to link the
+// cpp file.
+__attribute__((unused)) static inline const char* DescribeTaggingLevel(
+ HeapTaggingLevel level) {
+ switch (level) {
+ case M_HEAP_TAGGING_LEVEL_NONE:
+ return "none";
+ case M_HEAP_TAGGING_LEVEL_TBI:
+ return "tbi";
+ case M_HEAP_TAGGING_LEVEL_ASYNC:
+ return "async";
+ case M_HEAP_TAGGING_LEVEL_SYNC:
+ return "sync";
+ }
+}
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 8084e73..5d5ecac 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -27,11 +27,12 @@
*/
#include "libc_init_common.h"
-#include "heap_tagging.h"
+#include <async_safe/log.h>
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
@@ -42,8 +43,8 @@
#include <sys/time.h>
#include <unistd.h>
-#include <async_safe/log.h>
-
+#include "heap_tagging.h"
+#include "private/ScopedPthreadMutexLocker.h"
#include "private/WriteProtected.h"
#include "private/bionic_defs.h"
#include "private/bionic_globals.h"
@@ -104,6 +105,51 @@
}
__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+__attribute__((no_sanitize("hwaddress", "memtag"))) void
+__libc_init_mte_late() {
+#if defined(__aarch64__)
+ if (!__libc_shared_globals()->heap_tagging_upgrade_timer_sec) {
+ return;
+ }
+ struct sigevent event = {};
+ static timer_t timer;
+ event.sigev_notify = SIGEV_THREAD;
+ event.sigev_notify_function = [](union sigval) {
+ async_safe_format_log(ANDROID_LOG_INFO, "libc",
+ "Downgrading MTE to async.");
+ ScopedPthreadMutexLocker l(&g_heap_tagging_lock);
+ SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC);
+ timer_delete(timer);
+ };
+
+ if (timer_create(CLOCK_REALTIME, &event, &timer) == -1) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+ "Failed to create MTE downgrade timer: %m");
+ // Revert back to ASYNC. If we fail to create or arm the timer, otherwise
+ // the process would be indefinitely stuck in SYNC.
+ SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC);
+ return;
+ }
+
+ struct itimerspec timerspec = {};
+ timerspec.it_value.tv_sec =
+ __libc_shared_globals()->heap_tagging_upgrade_timer_sec;
+ if (timer_settime(timer, /* flags= */ 0, &timerspec, nullptr) == -1) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+ "Failed to arm MTE downgrade timer: %m");
+ // Revert back to ASYNC. If we fail to create or arm the timer, otherwise
+ // the process would be indefinitely stuck in SYNC.
+ SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC);
+ timer_delete(timer);
+ return;
+ }
+ async_safe_format_log(
+ ANDROID_LOG_INFO, "libc", "Armed MTE downgrade timer for %" PRId64 " s",
+ __libc_shared_globals()->heap_tagging_upgrade_timer_sec);
+#endif
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
void __libc_add_main_thread() {
// Get the main thread from TLS and add it to the thread list.
pthread_internal_t* main_thread = __get_thread();
diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h
index 15c747e..6b39d6d 100644
--- a/libc/bionic/libc_init_common.h
+++ b/libc/bionic/libc_init_common.h
@@ -60,6 +60,8 @@
__LIBC_HIDDEN__ void __libc_init_scudo();
+__LIBC_HIDDEN__ void __libc_init_mte_late();
+
__LIBC_HIDDEN__ void __libc_init_AT_SECURE(char** envp);
// The fork handler must be initialised after __libc_init_malloc, as
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 24efbf5..c61810e 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -154,6 +154,8 @@
__cxa_atexit(__libc_fini,structors->fini_array,nullptr);
}
+ __libc_init_mte_late();
+
exit(slingshot(args.argc - __libc_shared_globals()->initial_linker_arg_count,
args.argv + __libc_shared_globals()->initial_linker_arg_count,
args.envp));
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 575da62..d64d402 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -29,6 +29,7 @@
#include <android/api-level.h>
#include <elf.h>
#include <errno.h>
+#include <malloc.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
@@ -36,10 +37,9 @@
#include <sys/auxv.h>
#include <sys/mman.h>
+#include "async_safe/log.h"
+#include "heap_tagging.h"
#include "libc_init_common.h"
-#include "pthread_internal.h"
-#include "sysprop_helpers.h"
-
#include "platform/bionic/macros.h"
#include "platform/bionic/mte.h"
#include "platform/bionic/page.h"
@@ -51,7 +51,9 @@
#include "private/bionic_elf_tls.h"
#include "private/bionic_globals.h"
#include "private/bionic_tls.h"
+#include "pthread_internal.h"
#include "sys/system_properties.h"
+#include "sysprop_helpers.h"
#if __has_feature(hwaddress_sanitizer)
#include <sanitizer/hwasan_interface.h>
@@ -74,33 +76,12 @@
}
}
-#if defined(__aarch64__) || defined(__x86_64__)
-extern __LIBC_HIDDEN__ __attribute__((weak)) ElfW(Rela) __rela_iplt_start[], __rela_iplt_end[];
-
-static void call_ifunc_resolvers() {
- if (__rela_iplt_start == nullptr || __rela_iplt_end == nullptr) {
- // These symbols are not emitted by gold. Gold has code to do so, but for
- // whatever reason it is not being run. In these cases ifuncs cannot be
- // resolved, so we do not support using ifuncs in static executables linked
- // with gold.
- //
- // Since they are weak, they will be non-null when linked with bfd/lld and
- // null when linked with gold.
- return;
- }
-
- for (ElfW(Rela) *r = __rela_iplt_start; r != __rela_iplt_end; ++r) {
- ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset);
- ElfW(Addr) resolver = r->r_addend;
- *offset = __bionic_call_ifunc_resolver(resolver);
- }
-}
-#else
+#if defined(__arm__) || defined(__i386__) // Legacy architectures used REL...
extern __LIBC_HIDDEN__ __attribute__((weak)) ElfW(Rel) __rel_iplt_start[], __rel_iplt_end[];
static void call_ifunc_resolvers() {
if (__rel_iplt_start == nullptr || __rel_iplt_end == nullptr) {
- // These symbols are not emitted by gold. Gold has code to do so, but for
+ // These symbols were not emitted by gold. Gold has code to do so, but for
// whatever reason it is not being run. In these cases ifuncs cannot be
// resolved, so we do not support using ifuncs in static executables linked
// with gold.
@@ -110,12 +91,33 @@
return;
}
- for (ElfW(Rel) *r = __rel_iplt_start; r != __rel_iplt_end; ++r) {
+ for (ElfW(Rel)* r = __rel_iplt_start; r != __rel_iplt_end; ++r) {
ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset);
ElfW(Addr) resolver = *offset;
*offset = __bionic_call_ifunc_resolver(resolver);
}
}
+#else // ...but modern architectures use RELA instead.
+extern __LIBC_HIDDEN__ __attribute__((weak)) ElfW(Rela) __rela_iplt_start[], __rela_iplt_end[];
+
+static void call_ifunc_resolvers() {
+ if (__rela_iplt_start == nullptr || __rela_iplt_end == nullptr) {
+ // These symbols were not emitted by gold. Gold has code to do so, but for
+ // whatever reason it is not being run. In these cases ifuncs cannot be
+ // resolved, so we do not support using ifuncs in static executables linked
+ // with gold.
+ //
+ // Since they are weak, they will be non-null when linked with bfd/lld and
+ // null when linked with gold.
+ return;
+ }
+
+ for (ElfW(Rela)* r = __rela_iplt_start; r != __rela_iplt_end; ++r) {
+ ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset);
+ ElfW(Addr) resolver = r->r_addend;
+ *offset = __bionic_call_ifunc_resolver(resolver);
+ }
+}
#endif
static void apply_gnu_relro() {
@@ -218,23 +220,25 @@
static bool get_environment_memtag_setting(HeapTaggingLevel* level) {
static const char kMemtagPrognameSyspropPrefix[] = "arm64.memtag.process.";
static const char kMemtagGlobalSysprop[] = "persist.arm64.memtag.default";
+ static const char kMemtagOverrideSyspropPrefix[] =
+ "persist.device_config.memory_safety_native.mode_override.process.";
const char* progname = __libc_shared_globals()->init_progname;
if (progname == nullptr) return false;
const char* basename = __gnu_basename(progname);
- static constexpr size_t kOptionsSize = PROP_VALUE_MAX;
- char options_str[kOptionsSize];
- size_t sysprop_size = strlen(basename) + strlen(kMemtagPrognameSyspropPrefix) + 1;
- char* sysprop_name = static_cast<char*>(alloca(sysprop_size));
-
- async_safe_format_buffer(sysprop_name, sysprop_size, "%s%s", kMemtagPrognameSyspropPrefix,
+ char options_str[PROP_VALUE_MAX];
+ char sysprop_name[512];
+ async_safe_format_buffer(sysprop_name, sizeof(sysprop_name), "%s%s", kMemtagPrognameSyspropPrefix,
basename);
- const char* sys_prop_names[] = {sysprop_name, kMemtagGlobalSysprop};
+ char remote_sysprop_name[512];
+ async_safe_format_buffer(remote_sysprop_name, sizeof(remote_sysprop_name), "%s%s",
+ kMemtagOverrideSyspropPrefix, basename);
+ const char* sys_prop_names[] = {sysprop_name, remote_sysprop_name, kMemtagGlobalSysprop};
if (!get_config_from_env_or_sysprops("MEMTAG_OPTIONS", sys_prop_names, arraysize(sys_prop_names),
- options_str, kOptionsSize)) {
+ options_str, sizeof(options_str))) {
return false;
}
@@ -259,17 +263,18 @@
// M_HEAP_TAGGING_LEVEL_NONE, if MTE isn't enabled for this process we enable
// M_HEAP_TAGGING_LEVEL_TBI.
static HeapTaggingLevel __get_heap_tagging_level(const void* phdr_start, size_t phdr_ct,
- uintptr_t load_bias) {
+ uintptr_t load_bias, bool* stack) {
+ unsigned note_val =
+ __get_memtag_note(reinterpret_cast<const ElfW(Phdr)*>(phdr_start), phdr_ct, load_bias);
+ *stack = note_val & NT_MEMTAG_STACK;
+
HeapTaggingLevel level;
if (get_environment_memtag_setting(&level)) return level;
- unsigned note_val =
- __get_memtag_note(reinterpret_cast<const ElfW(Phdr)*>(phdr_start), phdr_ct, load_bias);
-
// Note, previously (in Android 12), any value outside of bits [0..3] resulted
// in a check-fail. In order to be permissive of further extensions, we
- // relaxed this restriction. For now, we still only support MTE heap.
- if (!(note_val & NT_MEMTAG_HEAP)) return M_HEAP_TAGGING_LEVEL_TBI;
+ // relaxed this restriction.
+ if (!(note_val & (NT_MEMTAG_HEAP | NT_MEMTAG_STACK))) return M_HEAP_TAGGING_LEVEL_TBI;
unsigned mode = note_val & NT_MEMTAG_LEVEL_MASK;
switch (mode) {
@@ -295,9 +300,47 @@
// This function is called from the linker before the main executable is relocated.
__attribute__((no_sanitize("hwaddress", "memtag"))) void __libc_init_mte(const void* phdr_start,
size_t phdr_ct,
- uintptr_t load_bias) {
- HeapTaggingLevel level = __get_heap_tagging_level(phdr_start, phdr_ct, load_bias);
-
+ uintptr_t load_bias,
+ void* stack_top) {
+ bool memtag_stack;
+ HeapTaggingLevel level = __get_heap_tagging_level(phdr_start, phdr_ct, load_bias, &memtag_stack);
+ char* env = getenv("BIONIC_MEMTAG_UPGRADE_SECS");
+ static const char kAppProcessName[] = "app_process64";
+ const char* progname = __libc_shared_globals()->init_progname;
+ progname = progname ? __gnu_basename(progname) : nullptr;
+ if (progname &&
+ strncmp(progname, kAppProcessName, sizeof(kAppProcessName)) == 0) {
+ // disable timed upgrade for zygote, as the thread spawned will violate the requirement
+ // that it be single-threaded.
+ env = nullptr;
+ }
+ int64_t timed_upgrade = 0;
+ if (env) {
+ char* endptr;
+ timed_upgrade = strtoll(env, &endptr, 10);
+ if (*endptr != '\0' || timed_upgrade < 0) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+ "Invalid value for BIONIC_MEMTAG_UPGRADE_SECS: %s",
+ env);
+ timed_upgrade = 0;
+ }
+ // Make sure that this does not get passed to potential processes inheriting
+ // this environment.
+ unsetenv("BIONIC_MEMTAG_UPGRADE_SECS");
+ }
+ if (timed_upgrade) {
+ if (level == M_HEAP_TAGGING_LEVEL_ASYNC) {
+ async_safe_format_log(ANDROID_LOG_INFO, "libc",
+ "Attempting timed MTE upgrade from async to sync.");
+ __libc_shared_globals()->heap_tagging_upgrade_timer_sec = timed_upgrade;
+ level = M_HEAP_TAGGING_LEVEL_SYNC;
+ } else if (level != M_HEAP_TAGGING_LEVEL_SYNC) {
+ async_safe_format_log(
+ ANDROID_LOG_ERROR, "libc",
+ "Requested timed MTE upgrade from invalid %s to sync. Ignoring.",
+ DescribeTaggingLevel(level));
+ }
+ }
if (level == M_HEAP_TAGGING_LEVEL_SYNC || level == M_HEAP_TAGGING_LEVEL_ASYNC) {
unsigned long prctl_arg = PR_TAGGED_ADDR_ENABLE | PR_MTE_TAG_SET_NONZERO;
prctl_arg |= (level == M_HEAP_TAGGING_LEVEL_SYNC) ? PR_MTE_TCF_SYNC : PR_MTE_TCF_ASYNC;
@@ -308,6 +351,17 @@
if (prctl(PR_SET_TAGGED_ADDR_CTRL, prctl_arg | PR_MTE_TCF_SYNC, 0, 0, 0) == 0 ||
prctl(PR_SET_TAGGED_ADDR_CTRL, prctl_arg, 0, 0, 0) == 0) {
__libc_shared_globals()->initial_heap_tagging_level = level;
+ __libc_shared_globals()->initial_memtag_stack = memtag_stack;
+
+ if (memtag_stack) {
+ void* page_start =
+ reinterpret_cast<void*>(PAGE_START(reinterpret_cast<uintptr_t>(stack_top)));
+ if (mprotect(page_start, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_MTE | PROT_GROWSDOWN)) {
+ async_safe_fatal("error: failed to set PROT_MTE on main thread stack: %s\n",
+ strerror(errno));
+ }
+ }
+
return;
}
}
@@ -317,9 +371,11 @@
if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == 0) {
__libc_shared_globals()->initial_heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI;
}
+ // We did not enable MTE, so we do not need to arm the upgrade timer.
+ __libc_shared_globals()->heap_tagging_upgrade_timer_sec = 0;
}
#else // __aarch64__
-void __libc_init_mte(const void*, size_t, uintptr_t) {}
+void __libc_init_mte(const void*, size_t, uintptr_t, void*) {}
#endif // __aarch64__
void __libc_init_profiling_handlers() {
@@ -331,11 +387,9 @@
signal(BIONIC_SIGNAL_ART_PROFILER, SIG_IGN);
}
-__noreturn static void __real_libc_init(void *raw_args,
- void (*onexit)(void) __unused,
- int (*slingshot)(int, char**, char**),
- structors_array_t const * const structors,
- bionic_tcb* temp_tcb) {
+__attribute__((no_sanitize("memtag"))) __noreturn static void __real_libc_init(
+ void* raw_args, void (*onexit)(void) __unused, int (*slingshot)(int, char**, char**),
+ structors_array_t const* const structors, bionic_tcb* temp_tcb) {
BIONIC_STOP_UNWIND;
// Initialize TLS early so system calls and errno work.
@@ -349,7 +403,7 @@
__libc_init_main_thread_final();
__libc_init_common();
__libc_init_mte(reinterpret_cast<ElfW(Phdr)*>(getauxval(AT_PHDR)), getauxval(AT_PHNUM),
- /*load_bias = */ 0);
+ /*load_bias = */ 0, /*stack_top = */ raw_args);
__libc_init_scudo();
__libc_init_profiling_handlers();
__libc_init_fork_handler();
@@ -370,6 +424,8 @@
__cxa_atexit(__libc_fini,structors->fini_array,nullptr);
}
+ __libc_init_mte_late();
+
exit(slingshot(args.argc, args.argv, args.envp));
}
@@ -379,11 +435,9 @@
//
// The 'structors' parameter contains pointers to various initializer
// arrays that must be run before the program's 'main' routine is launched.
-__attribute__((no_sanitize("hwaddress")))
-__noreturn void __libc_init(void* raw_args,
- void (*onexit)(void) __unused,
- int (*slingshot)(int, char**, char**),
- structors_array_t const * const structors) {
+__attribute__((no_sanitize("hwaddress", "memtag"))) __noreturn void __libc_init(
+ void* raw_args, void (*onexit)(void) __unused, int (*slingshot)(int, char**, char**),
+ structors_array_t const* const structors) {
bionic_tcb temp_tcb = {};
#if __has_feature(hwaddress_sanitizer)
// Install main thread TLS early. It will be initialized later in __libc_init_main_thread. For now
diff --git a/libc/bionic/locale.cpp b/libc/bionic/locale.cpp
index 0b7037a..2f4d206 100644
--- a/libc/bionic/locale.cpp
+++ b/libc/bionic/locale.cpp
@@ -54,23 +54,23 @@
struct __locale_t {
size_t mb_cur_max;
-
- explicit __locale_t(size_t mb_cur_max) : mb_cur_max(mb_cur_max) {
- }
-
- explicit __locale_t(const __locale_t* other) {
- if (other == LC_GLOBAL_LOCALE) {
- mb_cur_max = __bionic_current_locale_is_utf8 ? 4 : 1;
- } else {
- mb_cur_max = other->mb_cur_max;
- }
- }
-
- BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(__locale_t);
};
-size_t __ctype_get_mb_cur_max() {
- locale_t l = uselocale(nullptr);
+// Avoid using new/delete in this file, because a user may have overridden
+// new/delete, and we want to avoid making extraneous calls to them. This isn't
+// an issue for libc.so in the platform, but this file is also compiled into the
+// NDK's libandroid_support.a, and there are libc++ tests that count the number
+// of calls to new/delete.
+#pragma clang poison new delete
+
+static inline locale_t __alloc_locale(size_t mb_cur_max) {
+ auto result = static_cast<__locale_t*>(malloc(sizeof(__locale_t)));
+ if (result == nullptr) return nullptr;
+ result->mb_cur_max = mb_cur_max;
+ return result;
+}
+
+static inline size_t get_locale_mb_cur_max(locale_t l) {
if (l == LC_GLOBAL_LOCALE) {
return __bionic_current_locale_is_utf8 ? 4 : 1;
} else {
@@ -78,6 +78,10 @@
}
}
+size_t __ctype_get_mb_cur_max() {
+ return get_locale_mb_cur_max(uselocale(nullptr));
+}
+
#if !USE_TLS_SLOT
static thread_local locale_t g_current_locale;
#endif
@@ -133,11 +137,11 @@
}
locale_t duplocale(locale_t l) {
- return new __locale_t(l);
+ return __alloc_locale(get_locale_mb_cur_max(l));
}
void freelocale(locale_t l) {
- delete l;
+ free(l);
}
locale_t newlocale(int category_mask, const char* locale_name, locale_t /*base*/) {
@@ -152,7 +156,7 @@
return nullptr;
}
- return new __locale_t(__is_utf8_locale(locale_name) ? 4 : 1);
+ return __alloc_locale(__is_utf8_locale(locale_name) ? 4 : 1);
}
char* setlocale(int category, const char* locale_name) {
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 9744968..e159fdc 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -333,6 +333,14 @@
return EnableGwpAsan(*reinterpret_cast<android_mallopt_gwp_asan_options_t*>(arg));
}
+ if (opcode == M_MEMTAG_STACK_IS_ON) {
+ if (arg == nullptr || arg_size != sizeof(bool)) {
+ errno = EINVAL;
+ return false;
+ }
+ *reinterpret_cast<bool*>(arg) = atomic_load(&__libc_globals->memtag_stack);
+ return true;
+ }
errno = ENOTSUP;
return false;
}
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 6c2f4d9..97e8d15 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -533,6 +533,14 @@
return EnableGwpAsan(*reinterpret_cast<android_mallopt_gwp_asan_options_t*>(arg));
}
+ if (opcode == M_MEMTAG_STACK_IS_ON) {
+ if (arg == nullptr || arg_size != sizeof(bool)) {
+ errno = EINVAL;
+ return false;
+ }
+ *reinterpret_cast<bool*>(arg) = atomic_load(&__libc_globals->memtag_stack);
+ return true;
+ }
// Try heapprofd's mallopt, as it handles options not covered here.
return HeapprofdMallopt(opcode, arg, arg_size);
}
diff --git a/libc/bionic/memset_explicit.cpp b/libc/bionic/memset_explicit.cpp
new file mode 100644
index 0000000..2bcc20c
--- /dev/null
+++ b/libc/bionic/memset_explicit.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+void* memset_explicit(void* __dst, int __ch, size_t __n) {
+ void* result = memset(__dst, __ch, __n);
+ // https://bugs.llvm.org/show_bug.cgi?id=15495
+ __asm__ __volatile__("" : : "r"(__dst) : "memory");
+ return result;
+}
diff --git a/libc/bionic/mmap.cpp b/libc/bionic/mmap.cpp
index 9aad0b3..ed6b9c6 100644
--- a/libc/bionic/mmap.cpp
+++ b/libc/bionic/mmap.cpp
@@ -39,37 +39,20 @@
#define MMAP2_SHIFT 12 // 2**12 == 4096
-static bool kernel_has_MADV_MERGEABLE = true;
-
void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offset) {
if (offset < 0 || (offset & ((1UL << MMAP2_SHIFT)-1)) != 0) {
errno = EINVAL;
return MAP_FAILED;
}
- // prevent allocations large enough for `end - start` to overflow
+ // Prevent allocations large enough for `end - start` to overflow.
size_t rounded = __BIONIC_ALIGN(size, PAGE_SIZE);
if (rounded < size || rounded > PTRDIFF_MAX) {
errno = ENOMEM;
return MAP_FAILED;
}
- bool is_private_anonymous =
- (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) == (MAP_PRIVATE | MAP_ANONYMOUS);
- bool is_stack_or_grows_down = (flags & (MAP_STACK | MAP_GROWSDOWN)) != 0;
-
- void* result = __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
-
- if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE &&
- is_private_anonymous && !is_stack_or_grows_down) {
- ErrnoRestorer errno_restorer;
- int rc = madvise(result, size, MADV_MERGEABLE);
- if (rc == -1 && errno == EINVAL) {
- kernel_has_MADV_MERGEABLE = false;
- }
- }
-
- return result;
+ return __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
}
void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset) {
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 121b26f..417ce76 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -40,15 +40,16 @@
#include <async_safe/log.h>
+#include "platform/bionic/macros.h"
+#include "platform/bionic/mte.h"
+#include "private/ErrnoRestorer.h"
#include "private/ScopedRWLock.h"
#include "private/bionic_constants.h"
#include "private/bionic_defs.h"
#include "private/bionic_globals.h"
-#include "platform/bionic/macros.h"
#include "private/bionic_ssp.h"
#include "private/bionic_systrace.h"
#include "private/bionic_tls.h"
-#include "private/ErrnoRestorer.h"
// x86 uses segment descriptors rather than a direct pointer to TLS.
#if defined(__i386__)
@@ -88,7 +89,13 @@
static void __init_alternate_signal_stack(pthread_internal_t* thread) {
// Create and set an alternate signal stack.
- void* stack_base = mmap(nullptr, SIGNAL_STACK_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ int prot = PROT_READ | PROT_WRITE;
+#ifdef __aarch64__
+ if (atomic_load(&__libc_globals->memtag_stack)) {
+ prot |= PROT_MTE;
+ }
+#endif
+ void* stack_base = mmap(nullptr, SIGNAL_STACK_SIZE, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (stack_base != MAP_FAILED) {
// Create a guard to catch stack overflows in signal handlers.
if (mprotect(stack_base, PTHREAD_GUARD_SIZE, PROT_NONE) == -1) {
@@ -224,12 +231,19 @@
return {};
}
const size_t writable_size = mmap_size - stack_guard_size - PTHREAD_GUARD_SIZE;
- if (mprotect(space + stack_guard_size,
- writable_size,
- PROT_READ | PROT_WRITE) != 0) {
- async_safe_format_log(ANDROID_LOG_WARN, "libc",
- "pthread_create failed: couldn't mprotect R+W %zu-byte thread mapping region: %s",
- writable_size, strerror(errno));
+ int prot = PROT_READ | PROT_WRITE;
+ const char* prot_str = "R+W";
+#ifdef __aarch64__
+ if (atomic_load(&__libc_globals->memtag_stack)) {
+ prot |= PROT_MTE;
+ prot_str = "R+W+MTE";
+ }
+#endif
+ if (mprotect(space + stack_guard_size, writable_size, prot) != 0) {
+ async_safe_format_log(
+ ANDROID_LOG_WARN, "libc",
+ "pthread_create failed: couldn't mprotect %s %zu-byte thread mapping region: %s", prot_str,
+ writable_size, strerror(errno));
munmap(space, mmap_size);
return {};
}
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 071a5bc..7222b62 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -160,6 +160,13 @@
bionic_tls* bionic_tls;
int errno_value;
+
+ // The last observed value of SP in a vfork child process.
+ // The part of the stack between this address and the value of SP when the vfork parent process
+ // regains control may have stale MTE tags and needs cleanup. This field is only meaningful while
+ // the parent is waiting for the vfork child to return control by calling either exec*() or
+ // exit().
+ void* vfork_child_stack_bottom;
};
struct ThreadMapping {
diff --git a/libc/bionic/rename.cpp b/libc/bionic/rename.cpp
index 8295559..89786f7 100644
--- a/libc/bionic/rename.cpp
+++ b/libc/bionic/rename.cpp
@@ -30,5 +30,9 @@
#include <stdio.h>
int rename(const char* old_path, const char* new_path) {
- return renameat(AT_FDCWD, old_path, AT_FDCWD, new_path);
+ return renameat2(AT_FDCWD, old_path, AT_FDCWD, new_path, 0);
+}
+
+int renameat(int old_dir_fd, const char* old_path, int new_dir_fd, const char* new_path) {
+ return renameat2(old_dir_fd, old_path, new_dir_fd, new_path, 0);
}
diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp
index 59f7631..7e80ef6 100644
--- a/libc/bionic/spawn.cpp
+++ b/libc/bionic/spawn.cpp
@@ -52,7 +52,7 @@
// mark all open fds except stdin/out/err as close-on-exec
static int cloexec_except_stdioe() {
// requires 5.11+ or ACK 5.10-T kernel, otherwise returns ENOSYS or EINVAL
- if (!syscall(SYS_close_range, 3, ~0U, CLOSE_RANGE_CLOEXEC)) return 0;
+ if (!close_range(3, ~0U, CLOSE_RANGE_CLOEXEC)) return 0;
// unfortunately getrlimit can lie:
// - both soft and hard limits can be lowered to 0, with fds still open, so it can underestimate
diff --git a/libc/bionic/strtol.cpp b/libc/bionic/strtol.cpp
index 77f1d92..ec72b09 100644
--- a/libc/bionic/strtol.cpp
+++ b/libc/bionic/strtol.cpp
@@ -32,11 +32,13 @@
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
+#include <wchar.h>
-template <typename T, T Min, T Max> T StrToI(const char* nptr, char** endptr, int base) {
+template <typename T, T Min, T Max, typename CharT>
+T StrToI(const CharT* nptr, CharT** endptr, int base) {
// Ensure that base is between 2 and 36 inclusive, or the special value of 0.
if (base < 0 || base == 1 || base > 36) {
- if (endptr != nullptr) *endptr = const_cast<char*>(nptr);
+ if (endptr != nullptr) *endptr = const_cast<CharT*>(nptr);
errno = EINVAL;
return 0;
}
@@ -44,7 +46,7 @@
// Skip white space and pick up leading +/- sign if any.
// If base is 0, allow 0x for hex and 0 for octal, else
// assume decimal; if base is already 16, allow 0x.
- const char* s = nptr;
+ const CharT* s = nptr;
int c;
do {
c = *s++;
@@ -62,6 +64,11 @@
s += 2;
base = 16;
}
+ if ((base == 0 || base == 2) && c == '0' && (*s == 'b' || *s == 'B') && isdigit(s[1])) {
+ c = s[1];
+ s += 2;
+ base = 2;
+ }
if (base == 0) base = (c == '0') ? 8 : 10;
// We always work in the negative space because the most negative value has a
@@ -91,7 +98,7 @@
acc -= c;
}
}
- if (endptr != nullptr) *endptr = const_cast<char*>(any ? s - 1 : nptr);
+ if (endptr != nullptr) *endptr = const_cast<CharT*>(any ? s - 1 : nptr);
if (!neg) {
if (acc == Min) {
errno = ERANGE;
@@ -103,14 +110,15 @@
return acc;
}
-template <typename T, T Max> T StrToU(const char* nptr, char** endptr, int base) {
+template <typename T, T Max, typename CharT>
+T StrToU(const CharT* nptr, CharT** endptr, int base) {
if (base < 0 || base == 1 || base > 36) {
- if (endptr != nullptr) *endptr = const_cast<char*>(nptr);
+ if (endptr != nullptr) *endptr = const_cast<CharT*>(nptr);
errno = EINVAL;
return 0;
}
- const char* s = nptr;
+ const CharT* s = nptr;
int c;
do {
c = *s++;
@@ -128,6 +136,11 @@
s += 2;
base = 16;
}
+ if ((base == 0 || base == 2) && c == '0' && (*s == 'b' || *s == 'B') && isdigit(s[1])) {
+ c = s[1];
+ s += 2;
+ base = 2;
+ }
if (base == 0) base = (c == '0') ? 8 : 10;
T cutoff = Max / static_cast<T>(base);
@@ -155,7 +168,7 @@
}
}
if (neg && any > 0) acc = -acc;
- if (endptr != nullptr) *endptr = const_cast<char*>(any ? s - 1 : nptr);
+ if (endptr != nullptr) *endptr = const_cast<CharT*>(any ? s - 1 : nptr);
return acc;
}
@@ -172,30 +185,54 @@
}
intmax_t strtoimax(const char* s, char** end, int base) {
- return StrToI<intmax_t, INTMAX_MIN, INTMAX_MAX>(s, end, base);
+ return StrToI<intmax_t, INTMAX_MIN, INTMAX_MAX, char>(s, end, base);
+}
+
+intmax_t wcstoimax(const wchar_t* s, wchar_t** end, int base) {
+ return StrToI<intmax_t, INTMAX_MIN, INTMAX_MAX, wchar_t>(s, end, base);
}
long strtol(const char* s, char** end, int base) {
- return StrToI<long, LONG_MIN, LONG_MAX>(s, end, base);
+ return StrToI<long, LONG_MIN, LONG_MAX, char>(s, end, base);
+}
+
+long wcstol(const wchar_t* s, wchar_t** end, int base) {
+ return StrToI<long, LONG_MIN, LONG_MAX, wchar_t>(s, end, base);
}
long long strtoll(const char* s, char** end, int base) {
- return StrToI<long long, LLONG_MIN, LLONG_MAX>(s, end, base);
+ return StrToI<long long, LLONG_MIN, LLONG_MAX, char>(s, end, base);
+}
+
+long long wcstoll(const wchar_t* s, wchar_t** end, int base) {
+ return StrToI<long long, LLONG_MIN, LLONG_MAX, wchar_t>(s, end, base);
}
// Public API since L, but not in any header.
__strong_alias(strtoq, strtoll);
unsigned long strtoul(const char* s, char** end, int base) {
- return StrToU<unsigned long, ULONG_MAX>(s, end, base);
+ return StrToU<unsigned long, ULONG_MAX, char>(s, end, base);
+}
+
+unsigned long wcstoul(const wchar_t* s, wchar_t** end, int base) {
+ return StrToU<unsigned long, ULONG_MAX, wchar_t>(s, end, base);
}
unsigned long long strtoull(const char* s, char** end, int base) {
- return StrToU<unsigned long long, ULLONG_MAX>(s, end, base);
+ return StrToU<unsigned long long, ULLONG_MAX, char>(s, end, base);
+}
+
+unsigned long long wcstoull(const wchar_t* s, wchar_t** end, int base) {
+ return StrToU<unsigned long long, ULLONG_MAX, wchar_t>(s, end, base);
}
uintmax_t strtoumax(const char* s, char** end, int base) {
- return StrToU<uintmax_t, UINTMAX_MAX>(s, end, base);
+ return StrToU<uintmax_t, UINTMAX_MAX, char>(s, end, base);
+}
+
+uintmax_t wcstoumax(const wchar_t* s, wchar_t** end, int base) {
+ return StrToU<uintmax_t, UINTMAX_MAX, wchar_t>(s, end, base);
}
// Public API since L, but not in any header.
diff --git a/libc/bionic/sysinfo.cpp b/libc/bionic/sysinfo.cpp
index 7ab8e9e..1e4a0e8 100644
--- a/libc/bionic/sysinfo.cpp
+++ b/libc/bionic/sysinfo.cpp
@@ -36,47 +36,31 @@
#include "private/get_cpu_count_from_string.h"
#include "private/ScopedReaddir.h"
-static bool __matches_cpuN(const char* s) {
- // The %c trick is to ensure that we have the anchored match "^cpu[0-9]+$".
- // We can't use %*c because the return value is how many were *assigned*.
- unsigned cpu;
- char unused;
- return (sscanf(s, "cpu%u%c", &cpu, &unused) == 1);
-}
-
-int get_nprocs_conf() {
- // On x86 kernels you can use /proc/cpuinfo for this, but on ARM kernels offline CPUs disappear
- // from there. This method works on both.
- ScopedReaddir reader("/sys/devices/system/cpu");
- if (reader.IsBad()) {
- return 1;
- }
-
- int result = 0;
- dirent* entry;
- while ((entry = reader.ReadEntry()) != nullptr) {
- if (entry->d_type == DT_DIR && __matches_cpuN(entry->d_name)) {
- ++result;
- }
- }
- return result;
-}
-
-int get_nprocs() {
+int __get_cpu_count(const char* sys_file) {
int cpu_count = 1;
- FILE* fp = fopen("/sys/devices/system/cpu/online", "re");
+ FILE* fp = fopen(sys_file, "re");
if (fp != nullptr) {
char* line = nullptr;
- size_t len = 0;
- if (getline(&line, &len, fp) != -1) {
+ size_t allocated_size = 0;
+ if (getline(&line, &allocated_size, fp) != -1) {
cpu_count = GetCpuCountFromString(line);
- free(line);
}
+ free(line);
fclose(fp);
}
return cpu_count;
}
+int get_nprocs_conf() {
+ // It's unclear to me whether this is intended to be "possible" or "present",
+ // but on mobile they're unlikely to differ.
+ return __get_cpu_count("/sys/devices/system/cpu/possible");
+}
+
+int get_nprocs() {
+ return __get_cpu_count("/sys/devices/system/cpu/online");
+}
+
long get_phys_pages() {
struct sysinfo si;
sysinfo(&si);
diff --git a/libc/bionic/sysprop_helpers.cpp b/libc/bionic/sysprop_helpers.cpp
index edae6cc..5627034 100644
--- a/libc/bionic/sysprop_helpers.cpp
+++ b/libc/bionic/sysprop_helpers.cpp
@@ -53,9 +53,7 @@
strncpy(cb_cookie->dest, value, cb_cookie->size);
},
&cb_cookie);
- if (*dest != '\0' && *dest != '0') return true;
-
- return false;
+ return *dest != '\0';
}
bool get_config_from_env_or_sysprops(const char* env_var_name, const char* const* sys_prop_names,
diff --git a/libc/bionic/time64.c b/libc/bionic/time64.c
index da38bf3..73f24ab 100644
--- a/libc/bionic/time64.c
+++ b/libc/bionic/time64.c
@@ -483,6 +483,11 @@
}
+/* This implementation violates mktime specification, according to which
+ tm_yday, tm_wday, and tm_isdst fields should be updated. This function
+ leaves input_date unmodified. Given that there were no bug reports, fixing
+ it might cause more troubles than just leaving it as it is.
+ */
Time64_T mktime64(const struct TM *input_date) {
struct tm safe_date;
struct TM date;
diff --git a/libc/dns/resolv/res_send.c b/libc/dns/resolv/res_send.c
index fa81e6d..a95997d 100644
--- a/libc/dns/resolv/res_send.c
+++ b/libc/dns/resolv/res_send.c
@@ -680,8 +680,7 @@
/* Private */
static int
-get_salen(sa)
- const struct sockaddr *sa;
+get_salen(const struct sockaddr *sa)
{
#ifdef HAVE_SA_LEN
@@ -702,9 +701,7 @@
* pick appropriate nsaddr_list for use. see res_init() for initialization.
*/
static struct sockaddr *
-get_nsaddr(statp, n)
- res_state statp;
- size_t n;
+get_nsaddr(res_state statp, size_t n)
{
if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
diff --git a/libc/include/android/api-level.h b/libc/include/android/api-level.h
index ecf318d..79085d1 100644
--- a/libc/include/android/api-level.h
+++ b/libc/include/android/api-level.h
@@ -139,21 +139,32 @@
#define __ANDROID_API_P__ 28
/**
- * Names the "Q" API level (29), for comparison against `__ANDROID_API__`.
- * This release was called Android 10 publicly, not to be (but sure to be)
- * confused with API level 10.
+ * Names the Android 10 (aka "Q" or "Quince Tart") API level (29), for
+ * comparison against `__ANDROID_API__`.
*/
#define __ANDROID_API_Q__ 29
-/** Names the "R" API level (30), for comparison against `__ANDROID_API__`. */
+/**
+ * Names the Android 11 (aka "R" or "Red Velvet Cake") API level (30), for
+ * comparison against `__ANDROID_API__`.
+ */
#define __ANDROID_API_R__ 30
-/** Names the "S" API level (31), for comparison against `__ANDROID_API__`. */
+/**
+ * Names the Android 12 (aka "S" or "Snowcone") API level (31), for
+ * comparison against `__ANDROID_API__`.
+ */
#define __ANDROID_API_S__ 31
-/** Names the "T" API level (33), for comparison against `__ANDROID_API__`. */
+/**
+ * Names the Android 13 (aka "T" or "Tiramisu") API level (33), for
+ * comparison against `__ANDROID_API__`.
+ */
#define __ANDROID_API_T__ 33
+/** Names the "U" API level (34), for comparison against `__ANDROID_API__`. */
+#define __ANDROID_API_U__ 34
+
/* This file is included in <features.h>, and might be used from .S files. */
#if !defined(__ASSEMBLY__)
diff --git a/libc/include/android/fdsan.h b/libc/include/android/fdsan.h
index e23de85..59ce133 100644
--- a/libc/include/android/fdsan.h
+++ b/libc/include/android/fdsan.h
@@ -123,6 +123,9 @@
/* libziparchive's ZipArchive */
ANDROID_FDSAN_OWNER_TYPE_ZIPARCHIVE = 12,
+
+ /* native_handle_t */
+ ANDROID_FDSAN_OWNER_TYPE_NATIVE_HANDLE = 13,
};
/*
diff --git a/libc/include/android/legacy_stdlib_inlines.h b/libc/include/android/legacy_stdlib_inlines.h
index aeb1575..6903536 100644
--- a/libc/include/android/legacy_stdlib_inlines.h
+++ b/libc/include/android/legacy_stdlib_inlines.h
@@ -57,13 +57,11 @@
__BEGIN_DECLS
static __inline float strtof(const char* nptr, char** endptr) {
+ // N.B. Double-rounding makes this function incorrect for some inputs.
double d = strtod(nptr, endptr);
- if (d > FLT_MAX) {
+ if (__builtin_isfinite(d) && __builtin_fabs(d) > FLT_MAX) {
errno = ERANGE;
- return __builtin_huge_valf();
- } else if (d < -FLT_MAX) {
- errno = ERANGE;
- return -__builtin_huge_valf();
+ return __builtin_copysign(__builtin_huge_valf(), d);
}
return __BIONIC_CAST(static_cast, float, d);
}
diff --git a/libc/include/bits/elf_arm.h b/libc/include/bits/elf_arm.h
deleted file mode 100644
index 08fe1d5..0000000
--- a/libc/include/bits/elf_arm.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/* $NetBSD: elf_machdep.h,v 1.17 2014/02/25 19:20:09 matt Exp $ */
-
-#ifndef _ARM_ELF_MACHDEP_H_
-#define _ARM_ELF_MACHDEP_H_
-
-/* Android-added. */
-#define R_ARM_IRELATIVE 160
-
-/* Processor specific flags for the ELF header e_flags field. */
-#define EF_ARM_RELEXEC 0x00000001
-#define EF_ARM_HASENTRY 0x00000002
-#define EF_ARM_INTERWORK 0x00000004 /* GNU binutils 000413 */
-#define EF_ARM_SYMSARESORTED 0x00000004 /* ARM ELF A08 */
-#define EF_ARM_APCS_26 0x00000008 /* GNU binutils 000413 */
-#define EF_ARM_DYNSYMSUSESEGIDX 0x00000008 /* ARM ELF B01 */
-#define EF_ARM_APCS_FLOAT 0x00000010 /* GNU binutils 000413 */
-#define EF_ARM_MAPSYMSFIRST 0x00000010 /* ARM ELF B01 */
-#define EF_ARM_PIC 0x00000020
-#define EF_ARM_ALIGN8 0x00000040 /* 8-bit structure alignment. */
-#define EF_ARM_NEW_ABI 0x00000080
-#define EF_ARM_OLD_ABI 0x00000100
-#define EF_ARM_SOFT_FLOAT 0x00000200
-#define EF_ARM_BE8 0x00800000
-#define EF_ARM_EABIMASK 0xff000000
-#define EF_ARM_EABI_VER1 0x01000000
-#define EF_ARM_EABI_VER2 0x02000000
-#define EF_ARM_EABI_VER3 0x03000000
-#define EF_ARM_EABI_VER4 0x04000000
-#define EF_ARM_EABI_VER5 0x05000000
-
-/* Processor specific relocation types */
-
-#define R_ARM_NONE 0
-#define R_ARM_PC24 1
-#define R_ARM_ABS32 2
-#define R_ARM_REL32 3
-#define R_ARM_PC13 4
-#define R_ARM_ABS16 5
-#define R_ARM_ABS12 6
-#define R_ARM_THM_ABS5 7
-#define R_ARM_ABS8 8
-#define R_ARM_SBREL32 9
-#define R_ARM_THM_PC22 10
-#define R_ARM_THM_PC8 11
-#define R_ARM_AMP_VCALL9 12
-#define R_ARM_SWI24 13 /* obsolete static relocation */
-#define R_ARM_TLS_DESC 13 /* dynamic relocation */
-#define R_ARM_THM_SWI8 14
-#define R_ARM_XPC25 15
-#define R_ARM_THM_XPC22 16
-
-/* TLS relocations */
-#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */
-#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */
-#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */
-
-/* 20-31 are reserved for ARM Linux. */
-#define R_ARM_COPY 20
-#define R_ARM_GLOB_DAT 21
-#define R_ARM_JUMP_SLOT 22
-#define R_ARM_RELATIVE 23
-#define R_ARM_GOTOFF 24
-#define R_ARM_GOTPC 25
-#define R_ARM_GOT32 26
-#define R_ARM_PLT32 27
-#define R_ARM_CALL 28
-#define R_ARM_JUMP24 29
-#define R_ARM_THM_JUMP24 30
-#define R_ARM_BASE_ABS 31
-#define R_ARM_ALU_PCREL_7_0 32
-#define R_ARM_ALU_PCREL_15_8 33
-#define R_ARM_ALU_PCREL_23_15 34
-#define R_ARM_ALU_SBREL_11_0 35
-#define R_ARM_ALU_SBREL_19_12 36
-#define R_ARM_ALU_SBREL_27_20 37 // depcreated
-#define R_ARM_TARGET1 38
-#define R_ARM_SBREL31 39 // deprecated
-#define R_ARM_V4BX 40
-#define R_ARM_TARGET2 41
-#define R_ARM_PREL31 42
-#define R_ARM_MOVW_ABS_NC 43
-#define R_ARM_MOVT_ABS 44
-#define R_ARM_MOVW_PREL_NC 45
-#define R_ARM_MOVT_PREL 46
-#define R_ARM_THM_MOVW_ABS_NC 47
-#define R_ARM_THM_MOVT_ABS 48
-#define R_ARM_THM_MOVW_PREL_NC 49
-#define R_ARM_THM_MOVT_PREL 50
-
-/* 96-111 are reserved to G++. */
-#define R_ARM_GNU_VTENTRY 100
-#define R_ARM_GNU_VTINHERIT 101
-#define R_ARM_THM_PC11 102
-#define R_ARM_THM_PC9 103
-
-/* More TLS relocations */
-#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic */
-#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic */
-#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS */
-#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of */
-#define R_ARM_TLS_LE32 108
-#define R_ARM_TLS_LDO12 109
-#define R_ARM_TLS_LE12 110
-#define R_ARM_TLS_IE12GP 111
-
-/* 112-127 are reserved for private experiments. */
-
-#define R_ARM_RXPC25 249
-#define R_ARM_RSBREL32 250
-#define R_ARM_THM_RPC22 251
-#define R_ARM_RREL32 252
-#define R_ARM_RABS32 253
-#define R_ARM_RPC24 254
-#define R_ARM_RBASE 255
-
-/* Processor specific program header flags */
-#define PF_ARM_SB 0x10000000
-#define PF_ARM_PI 0x20000000
-#define PF_ARM_ENTRY 0x80000000
-
-/* Processor specific program header types */
-#define PT_ARM_EXIDX (PT_LOPROC + 1)
-
-/* Processor specific section header flags */
-#define SHF_ENTRYSECT 0x10000000
-#define SHF_COMDEF 0x80000000
-
-/* Processor specific symbol types */
-#define STT_ARM_TFUNC STT_LOPROC
-
-#endif /* _ARM_ELF_MACHDEP_H_ */
diff --git a/libc/include/bits/elf_arm64.h b/libc/include/bits/elf_arm64.h
deleted file mode 100644
index 9330d7b..0000000
--- a/libc/include/bits/elf_arm64.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _AARCH64_ELF_MACHDEP_H_
-#define _AARCH64_ELF_MACHDEP_H_
-
-/* Null relocations */
-#define R_ARM_NONE 0
-#define R_AARCH64_NONE 256
-
-/* Static Data relocations */
-#define R_AARCH64_ABS64 257
-#define R_AARCH64_ABS32 258
-#define R_AARCH64_ABS16 259
-#define R_AARCH64_PREL64 260
-#define R_AARCH64_PREL32 261
-#define R_AARCH64_PREL16 262
-
-#define R_AARCH64_MOVW_UABS_G0 263
-#define R_AARCH64_MOVW_UABS_G0_NC 264
-#define R_AARCH64_MOVW_UABS_G1 265
-#define R_AARCH64_MOVW_UABS_G1_NC 266
-#define R_AARCH64_MOVW_UABS_G2 267
-#define R_AARCH64_MOVW_UABS_G2_NC 268
-#define R_AARCH64_MOVW_UABS_G3 269
-#define R_AARCH64_MOVW_SABS_G0 270
-#define R_AARCH64_MOVW_SABS_G1 271
-#define R_AARCH64_MOVW_SABS_G2 272
-
-/* PC-relative addresses */
-#define R_AARCH64_LD_PREL_LO19 273
-#define R_AARCH64_ADR_PREL_LO21 274
-#define R_AARCH64_ADR_PREL_PG_HI21 275
-#define R_AARCH64_ADR_PREL_PG_HI21_NC 276
-#define R_AARCH64_ADD_ABS_LO12_NC 277
-#define R_AARCH64_LDST8_ABS_LO12_NC 278
-
-/* Control-flow relocations */
-#define R_AARCH64_TSTBR14 279
-#define R_AARCH64_CONDBR19 280
-#define R_AARCH64_JUMP26 282
-#define R_AARCH64_CALL26 283
-#define R_AARCH64_LDST16_ABS_LO12_NC 284
-#define R_AARCH64_LDST32_ABS_LO12_NC 285
-#define R_AARCH64_LDST64_ABS_LO12_NC 286
-#define R_AARCH64_LDST128_ABS_LO12_NC 299
-
-#define R_AARCH64_MOVW_PREL_G0 287
-#define R_AARCH64_MOVW_PREL_G0_NC 288
-#define R_AARCH64_MOVW_PREL_G1 289
-#define R_AARCH64_MOVW_PREL_G1_NC 290
-#define R_AARCH64_MOVW_PREL_G2 291
-#define R_AARCH64_MOVW_PREL_G2_NC 292
-#define R_AARCH64_MOVW_PREL_G3 293
-
-/* Dynamic relocations */
-#define R_AARCH64_COPY 1024
-#define R_AARCH64_GLOB_DAT 1025 /* Create GOT entry. */
-#define R_AARCH64_JUMP_SLOT 1026 /* Create PLT entry. */
-#define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */
-#define R_AARCH64_TLS_DTPMOD 1028 /* Module index. */
-#define R_AARCH64_TLS_DTPREL 1029 /* Module-relative offset. */
-#define R_AARCH64_TLS_TPREL 1030 /* TP-relative offset. */
-#define R_AARCH64_TLSDESC 1031 /* 16-byte descriptor: resolver func + arg. */
-#define R_AARCH64_IRELATIVE 1032
-
-/* Dynamic array tags */
-#define DT_AARCH64_BTI_PLT 0x70000001
-#define DT_AARCH64_PAC_PLT 0x70000003
-#define DT_AARCH64_VARIANT_PCS 0x70000005
-
-#endif /* _AARCH64_ELF_MACHDEP_H_ */
diff --git a/libc/include/bits/elf_common.h b/libc/include/bits/elf_common.h
new file mode 100644
index 0000000..ea833f4
--- /dev/null
+++ b/libc/include/bits/elf_common.h
@@ -0,0 +1,1430 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2017, 2018 Dell EMC
+ * Copyright (c) 2000, 2001, 2008, 2011, David E. O'Brien
+ * Copyright (c) 1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_ELF_COMMON_H_
+#define _SYS_ELF_COMMON_H_ 1
+
+/*
+ * ELF definitions that are independent of architecture or word size.
+ */
+
+/*
+ * Option kinds.
+ */
+#define ODK_NULL 0 /* undefined */
+#define ODK_REGINFO 1 /* register usage info */
+#define ODK_EXCEPTIONS 2 /* exception processing info */
+#define ODK_PAD 3 /* section padding */
+#define ODK_HWPATCH 4 /* hardware patch applied */
+#define ODK_FILL 5 /* fill value used by the linker */
+#define ODK_TAGS 6 /* reserved space for tools */
+#define ODK_HWAND 7 /* hardware AND patch applied */
+#define ODK_HWOR 8 /* hardware OR patch applied */
+#define ODK_GP_GROUP 9 /* GP group for text/data sections */
+#define ODK_IDENT 10 /* ID information */
+#define ODK_PAGESIZE 11 /* page size information */
+
+/*
+ * ODK_EXCEPTIONS info field masks.
+ */
+#define OEX_FPU_MIN 0x0000001f /* min FPU exception required */
+#define OEX_FPU_MAX 0x00001f00 /* max FPU exception allowed */
+#define OEX_PAGE0 0x00010000 /* page zero must be mapped */
+#define OEX_SMM 0x00020000 /* run in sequential memory mode */
+#define OEX_PRECISEFP 0x00040000 /* run in precise FP exception mode */
+#define OEX_DISMISS 0x00080000 /* dismiss invalid address traps */
+
+/*
+ * ODK_PAD info field masks.
+ */
+#define OPAD_PREFIX 0x0001
+#define OPAD_POSTFIX 0x0002
+#define OPAD_SYMBOL 0x0004
+
+/*
+ * ODK_HWPATCH info field masks.
+ */
+#define OHW_R4KEOP 0x00000001 /* patch for R4000 branch at end-of-page bug */
+#define OHW_R8KPFETCH 0x00000002 /* R8000 prefetch bug may occur */
+#define OHW_R5KEOP 0x00000004 /* patch for R5000 branch at end-of-page bug */
+#define OHW_R5KCVTL 0x00000008 /* R5000 cvt.[ds].l bug: clean == 1 */
+#define OHW_R10KLDL 0x00000010UL /* need patch for R10000 misaligned load */
+
+/*
+ * ODK_HWAND/ODK_HWOR info field and hwp_flags[12] masks.
+ */
+#define OHWA0_R4KEOP_CHECKED 0x00000001 /* object checked for R4000 end-of-page bug */
+#define OHWA0_R4KEOP_CLEAN 0x00000002 /* object verified clean for R4000 end-of-page bug */
+#define OHWO0_FIXADE 0x00000001 /* object requires call to fixade */
+
+/*
+ * ODK_IDENT/ODK_GP_GROUP info field masks.
+ */
+#define OGP_GROUP 0x0000ffff /* GP group number */
+#define OGP_SELF 0x00010000 /* GP group is self-contained */
+
+/* Indexes into the e_ident array. Keep synced with
+ http://www.sco.com/developers/gabi/latest/ch4.eheader.html */
+#define EI_MAG0 0 /* Magic number, byte 0. */
+#define EI_MAG1 1 /* Magic number, byte 1. */
+#define EI_MAG2 2 /* Magic number, byte 2. */
+#define EI_MAG3 3 /* Magic number, byte 3. */
+#define EI_CLASS 4 /* Class of machine. */
+#define EI_DATA 5 /* Data format. */
+#define EI_VERSION 6 /* ELF format version. */
+#define EI_OSABI 7 /* Operating system / ABI identification */
+#define EI_ABIVERSION 8 /* ABI version */
+#define OLD_EI_BRAND 8 /* Start of architecture identification. */
+#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */
+#define EI_NIDENT 16 /* Size of e_ident array. */
+
+/* Values for the magic number bytes. */
+#define ELFMAG0 0x7f
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF" /* magic string */
+#define SELFMAG 4 /* magic string size */
+
+/* Values for e_ident[EI_VERSION] and e_version. */
+#define EV_NONE 0
+#define EV_CURRENT 1
+
+/* Values for e_ident[EI_CLASS]. */
+#define ELFCLASSNONE 0 /* Unknown class. */
+#define ELFCLASS32 1 /* 32-bit architecture. */
+#define ELFCLASS64 2 /* 64-bit architecture. */
+
+/* Values for e_ident[EI_DATA]. */
+#define ELFDATANONE 0 /* Unknown data format. */
+#define ELFDATA2LSB 1 /* 2's complement little-endian. */
+#define ELFDATA2MSB 2 /* 2's complement big-endian. */
+
+/* Values for e_ident[EI_OSABI]. */
+#define ELFOSABI_NONE 0 /* UNIX System V ABI */
+#define ELFOSABI_HPUX 1 /* HP-UX operating system */
+#define ELFOSABI_NETBSD 2 /* NetBSD */
+#define ELFOSABI_LINUX 3 /* GNU/Linux */
+#define ELFOSABI_HURD 4 /* GNU/Hurd */
+#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */
+#define ELFOSABI_SOLARIS 6 /* Solaris */
+#define ELFOSABI_AIX 7 /* AIX */
+#define ELFOSABI_IRIX 8 /* IRIX */
+#define ELFOSABI_FREEBSD 9 /* FreeBSD */
+#define ELFOSABI_TRU64 10 /* TRU64 UNIX */
+#define ELFOSABI_MODESTO 11 /* Novell Modesto */
+#define ELFOSABI_OPENBSD 12 /* OpenBSD */
+#define ELFOSABI_OPENVMS 13 /* Open VMS */
+#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */
+#define ELFOSABI_AROS 15 /* Amiga Research OS */
+#define ELFOSABI_FENIXOS 16 /* FenixOS */
+#define ELFOSABI_CLOUDABI 17 /* Nuxi CloudABI */
+#define ELFOSABI_OPENVOS 18 /* Stratus Technologies OpenVOS */
+#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */
+#define ELFOSABI_ARM 97 /* ARM */
+#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
+
+#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */
+
+/* e_ident */
+#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
+ (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
+ (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
+ (ehdr).e_ident[EI_MAG3] == ELFMAG3)
+
+/* Values for e_type. */
+#define ET_NONE 0 /* Unknown type. */
+#define ET_REL 1 /* Relocatable. */
+#define ET_EXEC 2 /* Executable. */
+#define ET_DYN 3 /* Shared object. */
+#define ET_CORE 4 /* Core file. */
+#define ET_LOOS 0xfe00 /* First operating system specific. */
+#define ET_HIOS 0xfeff /* Last operating system-specific. */
+#define ET_LOPROC 0xff00 /* First processor-specific. */
+#define ET_HIPROC 0xffff /* Last processor-specific. */
+
+/* Values for e_machine. */
+#define EM_NONE 0 /* Unknown machine. */
+#define EM_M32 1 /* AT&T WE32100. */
+#define EM_SPARC 2 /* Sun SPARC. */
+#define EM_386 3 /* Intel i386. */
+#define EM_68K 4 /* Motorola 68000. */
+#define EM_88K 5 /* Motorola 88000. */
+#define EM_IAMCU 6 /* Intel MCU. */
+#define EM_860 7 /* Intel i860. */
+#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */
+#define EM_S370 9 /* IBM System/370. */
+#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */
+#define EM_PARISC 15 /* HP PA-RISC. */
+#define EM_VPP500 17 /* Fujitsu VPP500. */
+#define EM_SPARC32PLUS 18 /* SPARC v8plus. */
+#define EM_960 19 /* Intel 80960. */
+#define EM_PPC 20 /* PowerPC 32-bit. */
+#define EM_PPC64 21 /* PowerPC 64-bit. */
+#define EM_S390 22 /* IBM System/390. */
+#define EM_V800 36 /* NEC V800. */
+#define EM_FR20 37 /* Fujitsu FR20. */
+#define EM_RH32 38 /* TRW RH-32. */
+#define EM_RCE 39 /* Motorola RCE. */
+#define EM_ARM 40 /* ARM. */
+#define EM_SH 42 /* Hitachi SH. */
+#define EM_SPARCV9 43 /* SPARC v9 64-bit. */
+#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */
+#define EM_ARC 45 /* Argonaut RISC Core. */
+#define EM_H8_300 46 /* Hitachi H8/300. */
+#define EM_H8_300H 47 /* Hitachi H8/300H. */
+#define EM_H8S 48 /* Hitachi H8S. */
+#define EM_H8_500 49 /* Hitachi H8/500. */
+#define EM_IA_64 50 /* Intel IA-64 Processor. */
+#define EM_MIPS_X 51 /* Stanford MIPS-X. */
+#define EM_COLDFIRE 52 /* Motorola ColdFire. */
+#define EM_68HC12 53 /* Motorola M68HC12. */
+#define EM_MMA 54 /* Fujitsu MMA. */
+#define EM_PCP 55 /* Siemens PCP. */
+#define EM_NCPU 56 /* Sony nCPU. */
+#define EM_NDR1 57 /* Denso NDR1 microprocessor. */
+#define EM_STARCORE 58 /* Motorola Star*Core processor. */
+#define EM_ME16 59 /* Toyota ME16 processor. */
+#define EM_ST100 60 /* STMicroelectronics ST100 processor. */
+#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */
+#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */
+#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */
+#define EM_PDSP 63 /* Sony DSP Processor. */
+#define EM_FX66 66 /* Siemens FX66 microcontroller. */
+#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16
+ microcontroller. */
+#define EM_ST7 68 /* STmicroelectronics ST7 8-bit
+ microcontroller. */
+#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller. */
+#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller. */
+#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller. */
+#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller. */
+#define EM_SVX 73 /* Silicon Graphics SVx. */
+#define EM_ST19 74 /* STMicroelectronics ST19 8-bit mc. */
+#define EM_VAX 75 /* Digital VAX. */
+#define EM_CRIS 76 /* Axis Communications 32-bit embedded
+ processor. */
+#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded
+ processor. */
+#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor. */
+#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor. */
+#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc. */
+#define EM_HUANY 81 /* Harvard University machine-independent
+ object files. */
+#define EM_PRISM 82 /* SiTera Prism. */
+#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller. */
+#define EM_FR30 84 /* Fujitsu FR30. */
+#define EM_D10V 85 /* Mitsubishi D10V. */
+#define EM_D30V 86 /* Mitsubishi D30V. */
+#define EM_V850 87 /* NEC v850. */
+#define EM_M32R 88 /* Mitsubishi M32R. */
+#define EM_MN10300 89 /* Matsushita MN10300. */
+#define EM_MN10200 90 /* Matsushita MN10200. */
+#define EM_PJ 91 /* picoJava. */
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor. */
+#define EM_ARC_A5 93 /* ARC Cores Tangent-A5. */
+#define EM_XTENSA 94 /* Tensilica Xtensa Architecture. */
+#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor. */
+#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose
+ Processor. */
+#define EM_NS32K 97 /* National Semiconductor 32000 series. */
+#define EM_TPC 98 /* Tenor Network TPC processor. */
+#define EM_SNP1K 99 /* Trebia SNP 1000 processor. */
+#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller. */
+#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family. */
+#define EM_MAX 102 /* MAX Processor. */
+#define EM_CR 103 /* National Semiconductor CompactRISC
+ microprocessor. */
+#define EM_F2MC16 104 /* Fujitsu F2MC16. */
+#define EM_MSP430 105 /* Texas Instruments embedded microcontroller
+ msp430. */
+#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor. */
+#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors. */
+#define EM_SEP 108 /* Sharp embedded microprocessor. */
+#define EM_ARCA 109 /* Arca RISC Microprocessor. */
+#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd.
+ and MPRC of Peking University */
+#define EM_AARCH64 183 /* AArch64 (64-bit ARM) */
+#define EM_RISCV 243 /* RISC-V */
+
+/* Non-standard or deprecated. */
+#define EM_486 6 /* Intel i486. */
+#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
+#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */
+#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */
+
+/**
+ * e_flags
+ */
+#define EF_ARM_RELEXEC 0x1
+#define EF_ARM_HASENTRY 0x2
+#define EF_ARM_SYMSARESORTED 0x4
+#define EF_ARM_DYNSYMSUSESEGIDX 0x8
+#define EF_ARM_MAPSYMSFIRST 0x10
+#define EF_ARM_LE8 0x00400000
+#define EF_ARM_BE8 0x00800000
+#define EF_ARM_EABIMASK 0xFF000000
+#define EF_ARM_EABI_UNKNOWN 0x00000000
+#define EF_ARM_EABI_VER1 0x01000000
+#define EF_ARM_EABI_VER2 0x02000000
+#define EF_ARM_EABI_VER3 0x03000000
+#define EF_ARM_EABI_VER4 0x04000000
+#define EF_ARM_EABI_VER5 0x05000000
+#define EF_ARM_INTERWORK 0x00000004
+#define EF_ARM_APCS_26 0x00000008
+#define EF_ARM_APCS_FLOAT 0x00000010
+#define EF_ARM_PIC 0x00000020
+#define EF_ARM_ALIGN8 0x00000040
+#define EF_ARM_NEW_ABI 0x00000080
+#define EF_ARM_OLD_ABI 0x00000100
+#define EF_ARM_ABI_FLOAT_SOFT 0x00000200
+#define EF_ARM_SOFT_FLOAT EF_ARM_ABI_FLOAT_SOFT /* Pre-V5 ABI name */
+#define EF_ARM_ABI_FLOAT_HARD 0x00000400
+#define EF_ARM_VFP_FLOAT EF_ARM_ABI_FLOAT_HARD /* Pre-V5 ABI name */
+#define EF_ARM_MAVERICK_FLOAT 0x00000800
+
+#define EF_MIPS_NOREORDER 0x00000001
+#define EF_MIPS_PIC 0x00000002 /* Contains PIC code */
+#define EF_MIPS_CPIC 0x00000004 /* STD PIC calling sequence */
+#define EF_MIPS_UCODE 0x00000010
+#define EF_MIPS_ABI2 0x00000020 /* N32 */
+#define EF_MIPS_OPTIONS_FIRST 0x00000080
+#define EF_MIPS_ABI 0x0000F000
+#define EF_MIPS_ABI_O32 0x00001000
+#define EF_MIPS_ABI_O64 0x00002000
+#define EF_MIPS_ABI_EABI32 0x00003000
+#define EF_MIPS_ABI_EABI64 0x00004000
+#define EF_MIPS_ARCH_ASE 0x0F000000 /* Architectural extensions */
+#define EF_MIPS_ARCH_ASE_MDMX 0x08000000 /* MDMX multimedia extension */
+#define EF_MIPS_ARCH_ASE_M16 0x04000000 /* MIPS-16 ISA extensions */
+#define EF_MIPS_ARCH 0xF0000000 /* Architecture field */
+#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code */
+#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code */
+#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code */
+#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code */
+#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code */
+#define EF_MIPS_ARCH_32 0x50000000 /* -mips32 code */
+#define EF_MIPS_ARCH_64 0x60000000 /* -mips64 code */
+#define EF_MIPS_ARCH_32R2 0x70000000 /* -mips32r2 code */
+#define EF_MIPS_ARCH_64R2 0x80000000 /* -mips64r2 code */
+
+#define EF_PPC_EMB 0x80000000
+#define EF_PPC_RELOCATABLE 0x00010000
+#define EF_PPC_RELOCATABLE_LIB 0x00008000
+
+#define EF_RISCV_RVC 0x00000001
+#define EF_RISCV_FLOAT_ABI_MASK 0x00000006
+#define EF_RISCV_FLOAT_ABI_SOFT 0x00000000
+#define EF_RISCV_FLOAT_ABI_SINGLE 0x000002
+#define EF_RISCV_FLOAT_ABI_DOUBLE 0x000004
+#define EF_RISCV_FLOAT_ABI_QUAD 0x00000006
+#define EF_RISCV_RVE 0x00000008
+#define EF_RISCV_TSO 0x00000010
+
+#define EF_SPARC_EXT_MASK 0x00ffff00
+#define EF_SPARC_32PLUS 0x00000100
+#define EF_SPARC_SUN_US1 0x00000200
+#define EF_SPARC_HAL_R1 0x00000200
+#define EF_SPARC_SUN_US3 0x00000800
+
+#define EF_SPARCV9_MM 0x00000003
+#define EF_SPARCV9_TSO 0x00000000
+#define EF_SPARCV9_PSO 0x00000001
+#define EF_SPARCV9_RMO 0x00000002
+
+/* Special section indexes. */
+#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */
+#define SHN_LORESERVE 0xff00 /* First of reserved range. */
+#define SHN_LOPROC 0xff00 /* First processor-specific. */
+#define SHN_HIPROC 0xff1f /* Last processor-specific. */
+#define SHN_LOOS 0xff20 /* First operating system-specific. */
+#define SHN_FBSD_CACHED SHN_LOOS /* Transient, for sys/kern/link_elf_obj
+ linker only: Cached global in local
+ symtab. */
+#define SHN_HIOS 0xff3f /* Last operating system-specific. */
+#define SHN_ABS 0xfff1 /* Absolute values. */
+#define SHN_COMMON 0xfff2 /* Common data. */
+#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */
+#define SHN_HIRESERVE 0xffff /* Last of reserved range. */
+
+/* sh_type */
+#define SHT_NULL 0 /* inactive */
+#define SHT_PROGBITS 1 /* program defined information */
+#define SHT_SYMTAB 2 /* symbol table section */
+#define SHT_STRTAB 3 /* string table section */
+#define SHT_RELA 4 /* relocation section with addends */
+#define SHT_HASH 5 /* symbol hash table section */
+#define SHT_DYNAMIC 6 /* dynamic section */
+#define SHT_NOTE 7 /* note section */
+#define SHT_NOBITS 8 /* no space section */
+#define SHT_REL 9 /* relocation section - no addends */
+#define SHT_SHLIB 10 /* reserved - purpose unknown */
+#define SHT_DYNSYM 11 /* dynamic symbol table section */
+#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */
+#define SHT_FINI_ARRAY 15 /* Termination function pointers. */
+#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */
+#define SHT_GROUP 17 /* Section group. */
+#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */
+#define SHT_LOOS 0x60000000 /* First of OS specific semantics */
+#define SHT_LOSUNW 0x6ffffff4
+#define SHT_SUNW_dof 0x6ffffff4
+#define SHT_SUNW_cap 0x6ffffff5
+#define SHT_GNU_ATTRIBUTES 0x6ffffff5
+#define SHT_SUNW_SIGNATURE 0x6ffffff6
+#define SHT_GNU_HASH 0x6ffffff6
+#define SHT_GNU_LIBLIST 0x6ffffff7
+#define SHT_SUNW_ANNOTATE 0x6ffffff7
+#define SHT_SUNW_DEBUGSTR 0x6ffffff8
+#define SHT_SUNW_DEBUG 0x6ffffff9
+#define SHT_SUNW_move 0x6ffffffa
+#define SHT_SUNW_COMDAT 0x6ffffffb
+#define SHT_SUNW_syminfo 0x6ffffffc
+#define SHT_SUNW_verdef 0x6ffffffd
+#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */
+#define SHT_SUNW_verneed 0x6ffffffe
+#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */
+#define SHT_SUNW_versym 0x6fffffff
+#define SHT_GNU_versym 0x6fffffff /* Symbol version table */
+#define SHT_HISUNW 0x6fffffff
+#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */
+#define SHT_LOPROC 0x70000000 /* reserved range for processor */
+#define SHT_X86_64_UNWIND 0x70000001 /* unwind information */
+#define SHT_AMD64_UNWIND SHT_X86_64_UNWIND
+
+#define SHT_ARM_EXIDX 0x70000001 /* Exception index table. */
+#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking
+ pre-emption map. */
+#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility
+ attributes. */
+#define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details. */
+#define SHT_ARM_OVERLAYSECTION 0x70000005 /* See DBGOVL for details. */
+#define SHT_MIPS_LIBLIST 0x70000000
+#define SHT_MIPS_MSYM 0x70000001
+#define SHT_MIPS_CONFLICT 0x70000002
+#define SHT_MIPS_GPTAB 0x70000003
+#define SHT_MIPS_UCODE 0x70000004
+#define SHT_MIPS_DEBUG 0x70000005
+#define SHT_MIPS_REGINFO 0x70000006
+#define SHT_MIPS_PACKAGE 0x70000007
+#define SHT_MIPS_PACKSYM 0x70000008
+#define SHT_MIPS_RELD 0x70000009
+#define SHT_MIPS_IFACE 0x7000000b
+#define SHT_MIPS_CONTENT 0x7000000c
+#define SHT_MIPS_OPTIONS 0x7000000d
+#define SHT_MIPS_DELTASYM 0x7000001b
+#define SHT_MIPS_DELTAINST 0x7000001c
+#define SHT_MIPS_DELTACLASS 0x7000001d
+#define SHT_MIPS_DWARF 0x7000001e /* MIPS gcc uses MIPS_DWARF */
+#define SHT_MIPS_DELTADECL 0x7000001f
+#define SHT_MIPS_SYMBOL_LIB 0x70000020
+#define SHT_MIPS_EVENTS 0x70000021
+#define SHT_MIPS_TRANSLATE 0x70000022
+#define SHT_MIPS_PIXIE 0x70000023
+#define SHT_MIPS_XLATE 0x70000024
+#define SHT_MIPS_XLATE_DEBUG 0x70000025
+#define SHT_MIPS_WHIRL 0x70000026
+#define SHT_MIPS_EH_REGION 0x70000027
+#define SHT_MIPS_XLATE_OLD 0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+#define SHT_MIPS_ABIFLAGS 0x7000002a
+
+#define SHT_SPARC_GOTDATA 0x70000000
+
+#define SHTORDERED
+#define SHT_HIPROC 0x7fffffff /* specific section header types */
+#define SHT_LOUSER 0x80000000 /* reserved range for application */
+#define SHT_HIUSER 0xffffffff /* specific indexes */
+
+/* Flags for sh_flags. */
+#define SHF_WRITE 0x1 /* Section contains writable data. */
+#define SHF_ALLOC 0x2 /* Section occupies memory. */
+#define SHF_EXECINSTR 0x4 /* Section contains instructions. */
+#define SHF_MERGE 0x10 /* Section may be merged. */
+#define SHF_STRINGS 0x20 /* Section contains strings. */
+#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */
+#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */
+#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */
+#define SHF_GROUP 0x200 /* Member of section group. */
+#define SHF_TLS 0x400 /* Section contains TLS data. */
+#define SHF_COMPRESSED 0x800 /* Section contains compressed data. */
+#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */
+#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */
+
+/* Flags for section groups. */
+#define GRP_COMDAT 0x1 /* COMDAT semantics. */
+
+/*
+ * Flags / mask for .gnu.versym sections.
+ */
+#define VERSYM_VERSION 0x7fff
+#define VERSYM_HIDDEN 0x8000
+
+/* Values for p_type. */
+#define PT_NULL 0 /* Unused entry. */
+#define PT_LOAD 1 /* Loadable segment. */
+#define PT_DYNAMIC 2 /* Dynamic linking information segment. */
+#define PT_INTERP 3 /* Pathname of interpreter. */
+#define PT_NOTE 4 /* Auxiliary information. */
+#define PT_SHLIB 5 /* Reserved (not used). */
+#define PT_PHDR 6 /* Location of program header itself. */
+#define PT_TLS 7 /* Thread local storage segment */
+#define PT_LOOS 0x60000000 /* First OS-specific. */
+#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */
+#define PT_DUMP_DELTA 0x6fb5d000 /* va->pa map for kernel dumps
+ (currently arm). */
+#define PT_LOSUNW 0x6ffffffa
+#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
+#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */
+#define PT_SUNWDTRACE 0x6ffffffc /* private */
+#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */
+#define PT_HISUNW 0x6fffffff
+#define PT_HIOS 0x6fffffff /* Last OS-specific. */
+#define PT_LOPROC 0x70000000 /* First processor-specific type. */
+#define PT_ARM_ARCHEXT 0x70000000 /* ARM arch compat information. */
+#define PT_ARM_EXIDX 0x70000001 /* ARM exception unwind tables. */
+#define PT_MIPS_REGINFO 0x70000000 /* MIPS register usage info */
+#define PT_MIPS_RTPROC 0x70000001 /* MIPS runtime procedure tbl */
+#define PT_MIPS_OPTIONS 0x70000002 /* MIPS e_flags value*/
+#define PT_MIPS_ABIFLAGS 0x70000003 /* MIPS fp mode */
+#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */
+
+#define PT_OPENBSD_RANDOMIZE 0x65A3DBE6 /* OpenBSD random data segment */
+#define PT_OPENBSD_WXNEEDED 0x65A3DBE7 /* OpenBSD EXEC/WRITE pages needed */
+#define PT_OPENBSD_BOOTDATA 0x65A41BE6 /* OpenBSD section for boot args */
+
+/* Values for p_flags. */
+#define PF_X 0x1 /* Executable. */
+#define PF_W 0x2 /* Writable. */
+#define PF_R 0x4 /* Readable. */
+#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */
+#define PF_MASKPROC 0xf0000000 /* Processor-specific. */
+
+/* Extended program header index. */
+#define PN_XNUM 0xffff
+
+/* Values for d_tag. */
+#define DT_NULL 0 /* Terminating entry. */
+#define DT_NEEDED 1 /* String table offset of a needed shared
+ library. */
+#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */
+#define DT_PLTGOT 3 /* Processor-dependent address. */
+#define DT_HASH 4 /* Address of symbol hash table. */
+#define DT_STRTAB 5 /* Address of string table. */
+#define DT_SYMTAB 6 /* Address of symbol table. */
+#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */
+#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */
+#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */
+#define DT_STRSZ 10 /* Size of string table. */
+#define DT_SYMENT 11 /* Size of each symbol table entry. */
+#define DT_INIT 12 /* Address of initialization function. */
+#define DT_FINI 13 /* Address of finalization function. */
+#define DT_SONAME 14 /* String table offset of shared object
+ name. */
+#define DT_RPATH 15 /* String table offset of library path. [sup] */
+#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */
+#define DT_REL 17 /* Address of ElfNN_Rel relocations. */
+#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */
+#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */
+#define DT_PLTREL 20 /* Type of relocation used for PLT. */
+#define DT_DEBUG 21 /* Reserved (not used). */
+#define DT_TEXTREL 22 /* Indicates there may be relocations in
+ non-writable segments. [sup] */
+#define DT_JMPREL 23 /* Address of PLT relocations. */
+#define DT_BIND_NOW 24 /* [sup] */
+#define DT_INIT_ARRAY 25 /* Address of the array of pointers to
+ initialization functions */
+#define DT_FINI_ARRAY 26 /* Address of the array of pointers to
+ termination functions */
+#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of
+ initialization functions. */
+#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of
+ termination functions. */
+#define DT_RUNPATH 29 /* String table offset of a null-terminated
+ library search path string. */
+#define DT_FLAGS 30 /* Object specific flag values. */
+#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING
+ and less than DT_LOOS follow the rules for
+ the interpretation of the d_un union
+ as follows: even == 'd_ptr', odd == 'd_val'
+ or none */
+#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to
+ pre-initialization functions. */
+#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of
+ pre-initialization functions. */
+#define DT_MAXPOSTAGS 34 /* number of positive tags */
+#define DT_RELRSZ 35 /* Total size of ElfNN_Relr relocations. */
+#define DT_RELR 36 /* Address of ElfNN_Relr relocations. */
+#define DT_RELRENT 37 /* Size of each ElfNN_Relr relocation. */
+#define DT_LOOS 0x6000000d /* First OS-specific */
+#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */
+#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */
+#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */
+#define DT_SUNW_CAP 0x60000010 /* hardware/software */
+#define DT_SUNW_ASLR 0x60000023 /* ASLR control */
+#define DT_HIOS 0x6ffff000 /* Last OS-specific */
+
+/*
+ * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+ * Dyn.d_un.d_val field of the Elf*_Dyn structure.
+ */
+#define DT_VALRNGLO 0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5 /* prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* size of library list */
+#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */
+#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */
+#define DT_MOVEENT 0x6ffffdfa /* move table entry size */
+#define DT_MOVESZ 0x6ffffdfb /* move table size */
+#define DT_FEATURE 0x6ffffdfc /* feature holder */
+#define DT_FEATURE_1 DT_FEATURE
+#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */
+ /* the following DT_* entry. */
+ /* See DF_P1_* definitions */
+#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */
+#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */
+#define DT_VALRNGHI 0x6ffffdff
+
+/*
+ * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+ * Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+ *
+ * If any adjustment is made to the ELF object after it has been
+ * built, these entries will need to be adjusted.
+ */
+#define DT_ADDRRNGLO 0x6ffffe00
+#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */
+#define DT_TLSDESC_PLT 0x6ffffef6 /* loc. of PLT for tlsdesc resolver */
+#define DT_TLSDESC_GOT 0x6ffffef7 /* loc. of GOT for tlsdesc resolver */
+#define DT_GNU_CONFLICT 0x6ffffef8 /* address of conflict section */
+#define DT_GNU_LIBLIST 0x6ffffef9 /* address of library list */
+#define DT_CONFIG 0x6ffffefa /* configuration information */
+#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */
+#define DT_AUDIT 0x6ffffefc /* object auditing */
+#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */
+#define DT_MOVETAB 0x6ffffefe /* move table */
+#define DT_SYMINFO 0x6ffffeff /* syminfo table */
+#define DT_ADDRRNGHI 0x6ffffeff
+
+#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */
+#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */
+#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */
+#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */
+#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */
+#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */
+#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */
+#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */
+
+#define DT_LOPROC 0x70000000 /* First processor-specific type. */
+
+#define DT_AARCH64_BTI_PLT 0x70000001
+#define DT_AARCH64_PAC_PLT 0x70000003
+#define DT_AARCH64_VARIANT_PCS 0x70000005
+
+#define DT_ARM_SYMTABSZ 0x70000001
+#define DT_ARM_PREEMPTMAP 0x70000002
+
+#define DT_SPARC_REGISTER 0x70000001
+#define DT_DEPRECATED_SPARC_REGISTER 0x7000001
+
+#define DT_MIPS_RLD_VERSION 0x70000001
+#define DT_MIPS_TIME_STAMP 0x70000002
+#define DT_MIPS_ICHECKSUM 0x70000003
+#define DT_MIPS_IVERSION 0x70000004
+#define DT_MIPS_FLAGS 0x70000005
+#define DT_MIPS_BASE_ADDRESS 0x70000006
+#define DT_MIPS_CONFLICT 0x70000008
+#define DT_MIPS_LIBLIST 0x70000009
+#define DT_MIPS_LOCAL_GOTNO 0x7000000a
+#define DT_MIPS_CONFLICTNO 0x7000000b
+#define DT_MIPS_LIBLISTNO 0x70000010
+#define DT_MIPS_SYMTABNO 0x70000011
+#define DT_MIPS_UNREFEXTNO 0x70000012
+#define DT_MIPS_GOTSYM 0x70000013
+#define DT_MIPS_HIPAGENO 0x70000014
+#define DT_MIPS_RLD_MAP 0x70000016
+#define DT_MIPS_DELTA_CLASS 0x70000017
+#define DT_MIPS_DELTA_CLASS_NO 0x70000018
+#define DT_MIPS_DELTA_INSTANCE 0x70000019
+#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001A
+#define DT_MIPS_DELTA_RELOC 0x7000001B
+#define DT_MIPS_DELTA_RELOC_NO 0x7000001C
+#define DT_MIPS_DELTA_SYM 0x7000001D
+#define DT_MIPS_DELTA_SYM_NO 0x7000001E
+#define DT_MIPS_DELTA_CLASSSYM 0x70000020
+#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021
+#define DT_MIPS_CXX_FLAGS 0x70000022
+#define DT_MIPS_PIXIE_INIT 0x70000023
+#define DT_MIPS_SYMBOL_LIB 0x70000024
+#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
+#define DT_MIPS_LOCAL_GOTIDX 0x70000026
+#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
+#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
+#define DT_MIPS_OPTIONS 0x70000029
+#define DT_MIPS_INTERFACE 0x7000002A
+#define DT_MIPS_DYNSTR_ALIGN 0x7000002B
+#define DT_MIPS_INTERFACE_SIZE 0x7000002C
+#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002D
+#define DT_MIPS_PERF_SUFFIX 0x7000002E
+#define DT_MIPS_COMPACT_SIZE 0x7000002F
+#define DT_MIPS_GP_VALUE 0x70000030
+#define DT_MIPS_AUX_DYNAMIC 0x70000031
+#define DT_MIPS_PLTGOT 0x70000032
+#define DT_MIPS_RLD_OBJ_UPDATE 0x70000033
+#define DT_MIPS_RWPLT 0x70000034
+#define DT_MIPS_RLD_MAP_REL 0x70000035
+
+#define DT_PPC_GOT 0x70000000
+#define DT_PPC_TLSOPT 0x70000001
+
+#define DT_PPC64_GLINK 0x70000000
+#define DT_PPC64_OPD 0x70000001
+#define DT_PPC64_OPDSZ 0x70000002
+#define DT_PPC64_TLSOPT 0x70000003
+
+#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */
+#define DT_USED 0x7ffffffe /* ignored - same as needed */
+#define DT_FILTER 0x7fffffff /* shared library filter name */
+#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */
+
+/* Values for DT_FLAGS */
+#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may
+ make reference to the $ORIGIN substitution
+ string */
+#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */
+#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in
+ non-writable segments. */
+#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should
+ process all relocations for the object
+ containing this entry before transferring
+ control to the program. */
+#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or
+ executable contains code using a static
+ thread-local storage scheme. */
+
+/* Values for DT_FLAGS_1 */
+#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */
+#define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */
+#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */
+#define DF_1_LOADFLTR 0x00000010 /* Immediate loading of filtees */
+#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */
+#define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */
+#define DF_1_INTERPOSE 0x00000400 /* Interpose all objects but main */
+#define DF_1_NODEFLIB 0x00000800 /* Do not search default paths */
+#define DF_1_PIE 0x08000000 /* Is position-independent executable */
+
+/* Values for l_flags. */
+#define LL_NONE 0x0 /* no flags */
+#define LL_EXACT_MATCH 0x1 /* require an exact match */
+#define LL_IGNORE_INT_VER 0x2 /* ignore version incompatibilities */
+#define LL_REQUIRE_MINOR 0x4
+#define LL_EXPORTS 0x8
+#define LL_DELAY_LOAD 0x10
+#define LL_DELTA 0x20
+
+/* Note section names */
+#define ELF_NOTE_FREEBSD "FreeBSD"
+#define ELF_NOTE_NETBSD "NetBSD"
+#define ELF_NOTE_SOLARIS "SUNW Solaris"
+#define ELF_NOTE_GNU "GNU"
+
+/* Values for n_type used in executables. */
+#define NT_FREEBSD_ABI_TAG 1
+#define NT_FREEBSD_NOINIT_TAG 2
+#define NT_FREEBSD_ARCH_TAG 3
+#define NT_FREEBSD_FEATURE_CTL 4
+
+/* NT_FREEBSD_FEATURE_CTL desc[0] bits */
+#define NT_FREEBSD_FCTL_ASLR_DISABLE 0x00000001
+#define NT_FREEBSD_FCTL_PROTMAX_DISABLE 0x00000002
+#define NT_FREEBSD_FCTL_STKGAP_DISABLE 0x00000004
+#define NT_FREEBSD_FCTL_WXNEEDED 0x00000008
+#define NT_FREEBSD_FCTL_LA48 0x00000010
+/* was ASG_DISABLE, do not reuse 0x00000020 */
+
+/* Values for n_type. Used in core files. */
+#define NT_PRSTATUS 1 /* Process status. */
+#define NT_FPREGSET 2 /* Floating point registers. */
+#define NT_PRPSINFO 3 /* Process state info. */
+#define NT_THRMISC 7 /* Thread miscellaneous info. */
+#define NT_PROCSTAT_PROC 8 /* Procstat proc data. */
+#define NT_PROCSTAT_FILES 9 /* Procstat files data. */
+#define NT_PROCSTAT_VMMAP 10 /* Procstat vmmap data. */
+#define NT_PROCSTAT_GROUPS 11 /* Procstat groups data. */
+#define NT_PROCSTAT_UMASK 12 /* Procstat umask data. */
+#define NT_PROCSTAT_RLIMIT 13 /* Procstat rlimit data. */
+#define NT_PROCSTAT_OSREL 14 /* Procstat osreldate data. */
+#define NT_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */
+#define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */
+#define NT_PTLWPINFO 17 /* Thread ptrace miscellaneous info. */
+#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
+#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */
+#define NT_X86_SEGBASES 0x200 /* x86 FS/GS base addresses. */
+#define NT_X86_XSTATE 0x202 /* x86 XSAVE extended state. */
+#define NT_ARM_VFP 0x400 /* ARM VFP registers */
+#define NT_ARM_TLS 0x401 /* ARM TLS register */
+#define NT_ARM_ADDR_MASK 0x406 /* arm64 address mask (e.g. for TBI) */
+
+/* GNU note types. */
+#define NT_GNU_ABI_TAG 1
+#define NT_GNU_HWCAP 2
+#define NT_GNU_BUILD_ID 3
+#define NT_GNU_GOLD_VERSION 4
+#define NT_GNU_PROPERTY_TYPE_0 5
+
+#define GNU_PROPERTY_LOPROC 0xc0000000
+#define GNU_PROPERTY_HIPROC 0xdfffffff
+
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
+
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 0x00000002
+
+#define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002
+
+#define GNU_PROPERTY_X86_FEATURE_1_IBT 0x00000001
+#define GNU_PROPERTY_X86_FEATURE_1_SHSTK 0x00000002
+
+/* Symbol Binding - ELFNN_ST_BIND - st_info */
+#define STB_LOCAL 0 /* Local symbol */
+#define STB_GLOBAL 1 /* Global symbol */
+#define STB_WEAK 2 /* like global - lower precedence */
+#define STB_LOOS 10 /* Start of operating system reserved range. */
+#define STB_GNU_UNIQUE 10 /* Unique symbol (GNU) */
+#define STB_HIOS 12 /* End of operating system reserved range. */
+#define STB_LOPROC 13 /* reserved range for processor */
+#define STB_HIPROC 15 /* specific semantics. */
+
+/* Symbol type - ELFNN_ST_TYPE - st_info */
+#define STT_NOTYPE 0 /* Unspecified type. */
+#define STT_OBJECT 1 /* Data object. */
+#define STT_FUNC 2 /* Function. */
+#define STT_SECTION 3 /* Section. */
+#define STT_FILE 4 /* Source file. */
+#define STT_COMMON 5 /* Uninitialized common block. */
+#define STT_TLS 6 /* TLS object. */
+#define STT_NUM 7
+#define STT_LOOS 10 /* Reserved range for operating system */
+#define STT_GNU_IFUNC 10
+#define STT_HIOS 12 /* specific semantics. */
+#define STT_LOPROC 13 /* Start of processor reserved range. */
+#define STT_SPARC_REGISTER 13 /* SPARC register information. */
+#define STT_HIPROC 15 /* End of processor reserved range. */
+
+/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */
+#define STV_DEFAULT 0x0 /* Default visibility (see binding). */
+#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */
+#define STV_HIDDEN 0x2 /* Not visible. */
+#define STV_PROTECTED 0x3 /* Visible but not preemptible. */
+#define STV_EXPORTED 0x4
+#define STV_SINGLETON 0x5
+#define STV_ELIMINATE 0x6
+
+/* Special symbol table indexes. */
+#define STN_UNDEF 0 /* Undefined symbol index. */
+
+/* Symbol versioning flags. */
+#define VER_DEF_CURRENT 1
+#define VER_DEF_IDX(x) VER_NDX(x)
+
+#define VER_FLG_BASE 0x01
+#define VER_FLG_WEAK 0x02
+
+#define VER_NEED_CURRENT 1
+#define VER_NEED_WEAK (1u << 15)
+#define VER_NEED_HIDDEN VER_NDX_HIDDEN
+#define VER_NEED_IDX(x) VER_NDX(x)
+
+#define VER_NDX_LOCAL 0
+#define VER_NDX_GLOBAL 1
+#define VER_NDX_GIVEN 2
+
+#define VER_NDX_HIDDEN (1u << 15)
+#define VER_NDX(x) ((x) & ~(1u << 15))
+
+#define CA_SUNW_NULL 0
+#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */
+#define CA_SUNW_SF_1 2 /* first software capabilities entry */
+
+/*
+ * Syminfo flag values
+ */
+#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */
+ /* to object containing defn. */
+#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */
+#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */
+ /* lazily-loaded */
+#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */
+ /* object containing defn. */
+#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */
+ /* directly bind to this symbol */
+#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */
+#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */
+
+/*
+ * Syminfo.si_boundto values.
+ */
+#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */
+#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */
+#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */
+#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */
+#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */
+
+/*
+ * Syminfo version values.
+ */
+#define SYMINFO_NONE 0 /* Syminfo version */
+#define SYMINFO_CURRENT 1
+#define SYMINFO_NUM 2
+
+/* Values for ch_type (compressed section headers). */
+#define ELFCOMPRESS_ZLIB 1 /* ZLIB/DEFLATE */
+#define ELFCOMPRESS_ZSTD 2 /* Zstandard */
+#define ELFCOMPRESS_LOOS 0x60000000 /* OS-specific */
+#define ELFCOMPRESS_HIOS 0x6fffffff
+#define ELFCOMPRESS_LOPROC 0x70000000 /* Processor-specific */
+#define ELFCOMPRESS_HIPROC 0x7fffffff
+
+/*
+ * Relocation types.
+ *
+ * All machine architectures are defined here to allow tools on one to
+ * handle others.
+ */
+
+#define R_386_NONE 0 /* No relocation. */
+#define R_386_32 1 /* Add symbol value. */
+#define R_386_PC32 2 /* Add PC-relative symbol value. */
+#define R_386_GOT32 3 /* Add PC-relative GOT offset. */
+#define R_386_PLT32 4 /* Add PC-relative PLT offset. */
+#define R_386_COPY 5 /* Copy data from shared object. */
+#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */
+#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */
+#define R_386_RELATIVE 8 /* Add load address of shared object. */
+#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */
+#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */
+#define R_386_32PLT 11
+#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */
+#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */
+#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */
+#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */
+#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */
+#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */
+#define R_386_16 20
+#define R_386_PC16 21
+#define R_386_8 22
+#define R_386_PC8 23
+#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */
+#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */
+#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */
+#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */
+#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */
+#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */
+#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */
+#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */
+#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */
+#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */
+#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */
+#define R_386_SIZE32 38
+#define R_386_TLS_GOTDESC 39
+#define R_386_TLS_DESC_CALL 40
+#define R_386_TLS_DESC 41
+#define R_386_IRELATIVE 42 /* PLT entry resolved indirectly at runtime */
+#define R_386_GOT32X 43
+
+#define R_AARCH64_NONE 0 /* No relocation */
+#define R_AARCH64_ABS64 257 /* Absolute offset */
+#define R_AARCH64_ABS32 258 /* Absolute, 32-bit overflow check */
+#define R_AARCH64_ABS16 259 /* Absolute, 16-bit overflow check */
+#define R_AARCH64_PREL64 260 /* PC relative */
+#define R_AARCH64_PREL32 261 /* PC relative, 32-bit overflow check */
+#define R_AARCH64_PREL16 262 /* PC relative, 16-bit overflow check */
+#define R_AARCH64_TSTBR14 279 /* TBZ/TBNZ immediate */
+#define R_AARCH64_CONDBR19 280 /* Conditional branch immediate */
+#define R_AARCH64_JUMP26 282 /* Branch immediate */
+#define R_AARCH64_CALL26 283 /* Call immediate */
+#define R_AARCH64_COPY 1024 /* Copy data from shared object */
+#define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address */
+#define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address */
+#define R_AARCH64_RELATIVE 1027 /* Add load address of shared object */
+#define R_AARCH64_TLS_DTPREL64 1028
+#define R_AARCH64_TLS_DTPMOD64 1029
+#define R_AARCH64_TLS_TPREL64 1030
+#define R_AARCH64_TLSDESC 1031 /* Identify the TLS descriptor */
+#define R_AARCH64_IRELATIVE 1032
+
+#define R_ARM_NONE 0 /* No relocation. */
+#define R_ARM_PC24 1
+#define R_ARM_ABS32 2
+#define R_ARM_REL32 3
+#define R_ARM_PC13 4
+#define R_ARM_ABS16 5
+#define R_ARM_ABS12 6
+#define R_ARM_THM_ABS5 7
+#define R_ARM_ABS8 8
+#define R_ARM_SBREL32 9
+#define R_ARM_THM_PC22 10
+#define R_ARM_THM_PC8 11
+#define R_ARM_AMP_VCALL9 12
+#define R_ARM_SWI24 13
+#define R_ARM_THM_SWI8 14
+#define R_ARM_XPC25 15
+#define R_ARM_THM_XPC22 16
+/* TLS relocations */
+#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */
+#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */
+#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */
+#define R_ARM_COPY 20 /* Copy data from shared object. */
+#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */
+#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */
+#define R_ARM_RELATIVE 23 /* Add load address of shared object. */
+#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */
+#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */
+#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */
+#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */
+#define R_ARM_GNU_VTENTRY 100
+#define R_ARM_GNU_VTINHERIT 101
+#define R_ARM_RSBREL32 250
+#define R_ARM_THM_RPC22 251
+#define R_ARM_RREL32 252
+#define R_ARM_RABS32 253
+#define R_ARM_RPC24 254
+#define R_ARM_RBASE 255
+
+/* Name Value Field Calculation */
+#define R_IA_64_NONE 0 /* None */
+#define R_IA_64_IMM14 0x21 /* immediate14 S + A */
+#define R_IA_64_IMM22 0x22 /* immediate22 S + A */
+#define R_IA_64_IMM64 0x23 /* immediate64 S + A */
+#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */
+#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */
+#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */
+#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */
+#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */
+#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */
+#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */
+#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */
+#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */
+#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */
+#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */
+#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */
+#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */
+#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */
+#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */
+#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */
+#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */
+#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */
+#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */
+#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */
+#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */
+#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */
+#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */
+#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */
+#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */
+#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */
+#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */
+#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */
+#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */
+#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */
+#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */
+#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */
+#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */
+#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */
+#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */
+#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */
+#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */
+#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */
+#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */
+#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */
+#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */
+#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */
+#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */
+#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */
+#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */
+#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */
+#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */
+#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */
+#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */
+#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */
+#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */
+#define R_IA_64_SUB 0x85 /* immediate64 A - S */
+#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */
+#define R_IA_64_LDXMOV 0x87 /* immediate22 special */
+#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */
+#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */
+#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */
+#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */
+#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */
+#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */
+#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */
+#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */
+#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */
+#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */
+#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */
+#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */
+#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */
+#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */
+#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */
+#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */
+#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */
+
+#define R_MIPS_NONE 0 /* No reloc */
+#define R_MIPS_16 1 /* Direct 16 bit */
+#define R_MIPS_32 2 /* Direct 32 bit */
+#define R_MIPS_REL32 3 /* PC relative 32 bit */
+#define R_MIPS_26 4 /* Direct 26 bit shifted */
+#define R_MIPS_HI16 5 /* High 16 bit */
+#define R_MIPS_LO16 6 /* Low 16 bit */
+#define R_MIPS_GPREL16 7 /* GP relative 16 bit */
+#define R_MIPS_LITERAL 8 /* 16 bit literal entry */
+#define R_MIPS_GOT16 9 /* 16 bit GOT entry */
+#define R_MIPS_PC16 10 /* PC relative 16 bit */
+#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */
+#define R_MIPS_GPREL32 12 /* GP relative 32 bit */
+#define R_MIPS_64 18 /* Direct 64 bit */
+#define R_MIPS_GOT_DISP 19
+#define R_MIPS_GOT_PAGE 20
+#define R_MIPS_GOT_OFST 21
+#define R_MIPS_GOT_HI16 22 /* GOT HI 16 bit */
+#define R_MIPS_GOT_LO16 23 /* GOT LO 16 bit */
+#define R_MIPS_SUB 24
+#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */
+#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */
+#define R_MIPS_JALR 37
+#define R_MIPS_TLS_GD 42
+#define R_MIPS_COPY 126
+#define R_MIPS_JUMP_SLOT 127
+
+#define R_PPC_NONE 0 /* No relocation. */
+#define R_PPC_ADDR32 1
+#define R_PPC_ADDR24 2
+#define R_PPC_ADDR16 3
+#define R_PPC_ADDR16_LO 4
+#define R_PPC_ADDR16_HI 5
+#define R_PPC_ADDR16_HA 6
+#define R_PPC_ADDR14 7
+#define R_PPC_ADDR14_BRTAKEN 8
+#define R_PPC_ADDR14_BRNTAKEN 9
+#define R_PPC_REL24 10
+#define R_PPC_REL14 11
+#define R_PPC_REL14_BRTAKEN 12
+#define R_PPC_REL14_BRNTAKEN 13
+#define R_PPC_GOT16 14
+#define R_PPC_GOT16_LO 15
+#define R_PPC_GOT16_HI 16
+#define R_PPC_GOT16_HA 17
+#define R_PPC_PLTREL24 18
+#define R_PPC_COPY 19
+#define R_PPC_GLOB_DAT 20
+#define R_PPC_JMP_SLOT 21
+#define R_PPC_RELATIVE 22
+#define R_PPC_LOCAL24PC 23
+#define R_PPC_UADDR32 24
+#define R_PPC_UADDR16 25
+#define R_PPC_REL32 26
+#define R_PPC_PLT32 27
+#define R_PPC_PLTREL32 28
+#define R_PPC_PLT16_LO 29
+#define R_PPC_PLT16_HI 30
+#define R_PPC_PLT16_HA 31
+#define R_PPC_SDAREL16 32
+#define R_PPC_SECTOFF 33
+#define R_PPC_SECTOFF_LO 34
+#define R_PPC_SECTOFF_HI 35
+#define R_PPC_SECTOFF_HA 36
+#define R_PPC_IRELATIVE 248
+
+/*
+ * 64-bit relocations
+ */
+#define R_PPC64_ADDR64 38
+#define R_PPC64_ADDR16_HIGHER 39
+#define R_PPC64_ADDR16_HIGHERA 40
+#define R_PPC64_ADDR16_HIGHEST 41
+#define R_PPC64_ADDR16_HIGHESTA 42
+#define R_PPC64_UADDR64 43
+#define R_PPC64_REL64 44
+#define R_PPC64_PLT64 45
+#define R_PPC64_PLTREL64 46
+#define R_PPC64_TOC16 47
+#define R_PPC64_TOC16_LO 48
+#define R_PPC64_TOC16_HI 49
+#define R_PPC64_TOC16_HA 50
+#define R_PPC64_TOC 51
+#define R_PPC64_DTPMOD64 68
+#define R_PPC64_TPREL64 73
+#define R_PPC64_DTPREL64 78
+
+/*
+ * TLS relocations
+ */
+#define R_PPC_TLS 67
+#define R_PPC_DTPMOD32 68
+#define R_PPC_TPREL16 69
+#define R_PPC_TPREL16_LO 70
+#define R_PPC_TPREL16_HI 71
+#define R_PPC_TPREL16_HA 72
+#define R_PPC_TPREL32 73
+#define R_PPC_DTPREL16 74
+#define R_PPC_DTPREL16_LO 75
+#define R_PPC_DTPREL16_HI 76
+#define R_PPC_DTPREL16_HA 77
+#define R_PPC_DTPREL32 78
+#define R_PPC_GOT_TLSGD16 79
+#define R_PPC_GOT_TLSGD16_LO 80
+#define R_PPC_GOT_TLSGD16_HI 81
+#define R_PPC_GOT_TLSGD16_HA 82
+#define R_PPC_GOT_TLSLD16 83
+#define R_PPC_GOT_TLSLD16_LO 84
+#define R_PPC_GOT_TLSLD16_HI 85
+#define R_PPC_GOT_TLSLD16_HA 86
+#define R_PPC_GOT_TPREL16 87
+#define R_PPC_GOT_TPREL16_LO 88
+#define R_PPC_GOT_TPREL16_HI 89
+#define R_PPC_GOT_TPREL16_HA 90
+
+/*
+ * The remaining relocs are from the Embedded ELF ABI, and are not in the
+ * SVR4 ELF ABI.
+ */
+
+#define R_PPC_EMB_NADDR32 101
+#define R_PPC_EMB_NADDR16 102
+#define R_PPC_EMB_NADDR16_LO 103
+#define R_PPC_EMB_NADDR16_HI 104
+#define R_PPC_EMB_NADDR16_HA 105
+#define R_PPC_EMB_SDAI16 106
+#define R_PPC_EMB_SDA2I16 107
+#define R_PPC_EMB_SDA2REL 108
+#define R_PPC_EMB_SDA21 109
+#define R_PPC_EMB_MRKREF 110
+#define R_PPC_EMB_RELSEC16 111
+#define R_PPC_EMB_RELST_LO 112
+#define R_PPC_EMB_RELST_HI 113
+#define R_PPC_EMB_RELST_HA 114
+#define R_PPC_EMB_BIT_FLD 115
+#define R_PPC_EMB_RELSDA 116
+
+/*
+ * RISC-V relocation types.
+ */
+
+/* Relocation types used by the dynamic linker. */
+#define R_RISCV_NONE 0
+#define R_RISCV_32 1
+#define R_RISCV_64 2
+#define R_RISCV_RELATIVE 3
+#define R_RISCV_COPY 4
+#define R_RISCV_JUMP_SLOT 5
+#define R_RISCV_TLS_DTPMOD32 6
+#define R_RISCV_TLS_DTPMOD64 7
+#define R_RISCV_TLS_DTPREL32 8
+#define R_RISCV_TLS_DTPREL64 9
+#define R_RISCV_TLS_TPREL32 10
+#define R_RISCV_TLS_TPREL64 11
+
+/* Relocation types not used by the dynamic linker. */
+#define R_RISCV_BRANCH 16
+#define R_RISCV_JAL 17
+#define R_RISCV_CALL 18
+#define R_RISCV_CALL_PLT 19
+#define R_RISCV_GOT_HI20 20
+#define R_RISCV_TLS_GOT_HI20 21
+#define R_RISCV_TLS_GD_HI20 22
+#define R_RISCV_PCREL_HI20 23
+#define R_RISCV_PCREL_LO12_I 24
+#define R_RISCV_PCREL_LO12_S 25
+#define R_RISCV_HI20 26
+#define R_RISCV_LO12_I 27
+#define R_RISCV_LO12_S 28
+#define R_RISCV_TPREL_HI20 29
+#define R_RISCV_TPREL_LO12_I 30
+#define R_RISCV_TPREL_LO12_S 31
+#define R_RISCV_TPREL_ADD 32
+#define R_RISCV_ADD8 33
+#define R_RISCV_ADD16 34
+#define R_RISCV_ADD32 35
+#define R_RISCV_ADD64 36
+#define R_RISCV_SUB8 37
+#define R_RISCV_SUB16 38
+#define R_RISCV_SUB32 39
+#define R_RISCV_SUB64 40
+#define R_RISCV_GNU_VTINHERIT 41
+#define R_RISCV_GNU_VTENTRY 42
+#define R_RISCV_ALIGN 43
+#define R_RISCV_RVC_BRANCH 44
+#define R_RISCV_RVC_JUMP 45
+#define R_RISCV_RVC_LUI 46
+#define R_RISCV_RELAX 51
+#define R_RISCV_SUB6 52
+#define R_RISCV_SET6 53
+#define R_RISCV_SET8 54
+#define R_RISCV_SET16 55
+#define R_RISCV_SET32 56
+#define R_RISCV_32_PCREL 57
+#define R_RISCV_IRELATIVE 58
+
+#define R_SPARC_NONE 0
+#define R_SPARC_8 1
+#define R_SPARC_16 2
+#define R_SPARC_32 3
+#define R_SPARC_DISP8 4
+#define R_SPARC_DISP16 5
+#define R_SPARC_DISP32 6
+#define R_SPARC_WDISP30 7
+#define R_SPARC_WDISP22 8
+#define R_SPARC_HI22 9
+#define R_SPARC_22 10
+#define R_SPARC_13 11
+#define R_SPARC_LO10 12
+#define R_SPARC_GOT10 13
+#define R_SPARC_GOT13 14
+#define R_SPARC_GOT22 15
+#define R_SPARC_PC10 16
+#define R_SPARC_PC22 17
+#define R_SPARC_WPLT30 18
+#define R_SPARC_COPY 19
+#define R_SPARC_GLOB_DAT 20
+#define R_SPARC_JMP_SLOT 21
+#define R_SPARC_RELATIVE 22
+#define R_SPARC_UA32 23
+#define R_SPARC_PLT32 24
+#define R_SPARC_HIPLT22 25
+#define R_SPARC_LOPLT10 26
+#define R_SPARC_PCPLT32 27
+#define R_SPARC_PCPLT22 28
+#define R_SPARC_PCPLT10 29
+#define R_SPARC_10 30
+#define R_SPARC_11 31
+#define R_SPARC_64 32
+#define R_SPARC_OLO10 33
+#define R_SPARC_HH22 34
+#define R_SPARC_HM10 35
+#define R_SPARC_LM22 36
+#define R_SPARC_PC_HH22 37
+#define R_SPARC_PC_HM10 38
+#define R_SPARC_PC_LM22 39
+#define R_SPARC_WDISP16 40
+#define R_SPARC_WDISP19 41
+#define R_SPARC_GLOB_JMP 42
+#define R_SPARC_7 43
+#define R_SPARC_5 44
+#define R_SPARC_6 45
+#define R_SPARC_DISP64 46
+#define R_SPARC_PLT64 47
+#define R_SPARC_HIX22 48
+#define R_SPARC_LOX10 49
+#define R_SPARC_H44 50
+#define R_SPARC_M44 51
+#define R_SPARC_L44 52
+#define R_SPARC_REGISTER 53
+#define R_SPARC_UA64 54
+#define R_SPARC_UA16 55
+#define R_SPARC_TLS_GD_HI22 56
+#define R_SPARC_TLS_GD_LO10 57
+#define R_SPARC_TLS_GD_ADD 58
+#define R_SPARC_TLS_GD_CALL 59
+#define R_SPARC_TLS_LDM_HI22 60
+#define R_SPARC_TLS_LDM_LO10 61
+#define R_SPARC_TLS_LDM_ADD 62
+#define R_SPARC_TLS_LDM_CALL 63
+#define R_SPARC_TLS_LDO_HIX22 64
+#define R_SPARC_TLS_LDO_LOX10 65
+#define R_SPARC_TLS_LDO_ADD 66
+#define R_SPARC_TLS_IE_HI22 67
+#define R_SPARC_TLS_IE_LO10 68
+#define R_SPARC_TLS_IE_LD 69
+#define R_SPARC_TLS_IE_LDX 70
+#define R_SPARC_TLS_IE_ADD 71
+#define R_SPARC_TLS_LE_HIX22 72
+#define R_SPARC_TLS_LE_LOX10 73
+#define R_SPARC_TLS_DTPMOD32 74
+#define R_SPARC_TLS_DTPMOD64 75
+#define R_SPARC_TLS_DTPOFF32 76
+#define R_SPARC_TLS_DTPOFF64 77
+#define R_SPARC_TLS_TPOFF32 78
+#define R_SPARC_TLS_TPOFF64 79
+
+#define R_X86_64_NONE 0 /* No relocation. */
+#define R_X86_64_64 1 /* Add 64 bit symbol value. */
+#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */
+#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */
+#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */
+#define R_X86_64_COPY 5 /* Copy data from shared object. */
+#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */
+#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */
+#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */
+#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */
+#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */
+#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */
+#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */
+#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */
+#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */
+#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */
+#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
+#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */
+#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */
+#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */
+#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */
+#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
+#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */
+#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */
+#define R_X86_64_PC64 24 /* PC-relative 64 bit signed sym value. */
+#define R_X86_64_GOTOFF64 25
+#define R_X86_64_GOTPC32 26
+#define R_X86_64_GOT64 27
+#define R_X86_64_GOTPCREL64 28
+#define R_X86_64_GOTPC64 29
+#define R_X86_64_GOTPLT64 30
+#define R_X86_64_PLTOFF64 31
+#define R_X86_64_SIZE32 32
+#define R_X86_64_SIZE64 33
+#define R_X86_64_GOTPC32_TLSDESC 34
+#define R_X86_64_TLSDESC_CALL 35
+#define R_X86_64_TLSDESC 36
+#define R_X86_64_IRELATIVE 37
+#define R_X86_64_RELATIVE64 38
+/* 39 and 40 were BND-related, already decomissioned */
+#define R_X86_64_GOTPCRELX 41
+#define R_X86_64_REX_GOTPCRELX 42
+
+#define ELF_BSDF_SIGFASTBLK 0x0001 /* Kernel supports fast sigblock */
+#define ELF_BSDF_VMNOOVERCOMMIT 0x0002
+
+#endif /* !_SYS_ELF_COMMON_H_ */
diff --git a/libc/include/bits/elf_x86.h b/libc/include/bits/elf_x86.h
deleted file mode 100644
index dfbaba0..0000000
--- a/libc/include/bits/elf_x86.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* $NetBSD: elf_machdep.h,v 1.12 2016/02/02 20:16:59 christos Exp $ */
-
-#ifndef _X86_ELF_MACHDEP_H_
-#define _X86_ELF_MACHDEP_H_
-
-/* i386 relocations */
-#define R_386_NONE 0
-#define R_386_32 1
-#define R_386_PC32 2
-#define R_386_GOT32 3
-#define R_386_PLT32 4
-#define R_386_COPY 5
-#define R_386_GLOB_DAT 6
-#define R_386_JMP_SLOT 7
-#define R_386_RELATIVE 8
-#define R_386_GOTOFF 9
-#define R_386_GOTPC 10
-#define R_386_32PLT 11
-
-/* TLS relocations */
-#define R_386_TLS_TPOFF 14
-#define R_386_TLS_IE 15
-#define R_386_TLS_GOTIE 16
-#define R_386_TLS_LE 17
-#define R_386_TLS_GD 18
-#define R_386_TLS_LDM 19
-
-/* The following relocations are GNU extensions. */
-#define R_386_16 20
-#define R_386_PC16 21
-#define R_386_8 22
-#define R_386_PC8 23
-
-/* More TLS relocations */
-#define R_386_TLS_GD_32 24
-#define R_386_TLS_GD_PUSH 25
-#define R_386_TLS_GD_CALL 26
-#define R_386_TLS_GD_POP 27
-#define R_386_TLS_LDM_32 28
-#define R_386_TLS_LDM_PUSH 29
-#define R_386_TLS_LDM_CALL 30
-#define R_386_TLS_LDM_POP 31
-#define R_386_TLS_LDO_32 32
-#define R_386_TLS_IE_32 33
-#define R_386_TLS_LE_32 34
-#define R_386_TLS_DTPMOD32 35
-#define R_386_TLS_DTPOFF32 36
-#define R_386_TLS_TPOFF32 37
-
-#define R_386_SIZE32 38
-
-/* More TLS relocations */
-#define R_386_TLS_GOTDESC 39
-#define R_386_TLS_DESC_CALL 40
-#define R_386_TLS_DESC 41
-
-#define R_386_IRELATIVE 42
-#define R_386_GOT32X 43
-
-#endif
diff --git a/libc/include/bits/elf_x86_64.h b/libc/include/bits/elf_x86_64.h
deleted file mode 100644
index 30062af..0000000
--- a/libc/include/bits/elf_x86_64.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* $NetBSD: elf_machdep.h,v 1.5 2016/02/02 20:13:59 christos Exp $ */
-
-#ifndef _X86_64_ELF_MACHDEP_H_
-#define _X86_64_ELF_MACHDEP_H_
-
-/* x86-64 relocations */
-
-#define R_X86_64_NONE 0
-#define R_X86_64_64 1
-#define R_X86_64_PC32 2
-#define R_X86_64_GOT32 3
-#define R_X86_64_PLT32 4
-#define R_X86_64_COPY 5
-#define R_X86_64_GLOB_DAT 6
-#define R_X86_64_JUMP_SLOT 7
-#define R_X86_64_RELATIVE 8
-#define R_X86_64_GOTPCREL 9
-#define R_X86_64_32 10
-#define R_X86_64_32S 11
-#define R_X86_64_16 12
-#define R_X86_64_PC16 13
-#define R_X86_64_8 14
-#define R_X86_64_PC8 15
-
-/* TLS relocations */
-#define R_X86_64_DTPMOD64 16
-#define R_X86_64_DTPOFF64 17
-#define R_X86_64_TPOFF64 18
-#define R_X86_64_TLSGD 19
-#define R_X86_64_TLSLD 20
-#define R_X86_64_DTPOFF32 21
-#define R_X86_64_GOTTPOFF 22
-#define R_X86_64_TPOFF32 23
-
-#define R_X86_64_PC64 24
-#define R_X86_64_GOTOFF64 25
-#define R_X86_64_GOTPC32 26
-#define R_X86_64_GOT64 27
-#define R_X86_64_GOTPCREL64 28
-#define R_X86_64_GOTPC64 29
-#define R_X86_64_GOTPLT64 30
-#define R_X86_64_PLTOFF64 31
-#define R_X86_64_SIZE32 32
-#define R_X86_64_SIZE64 33
-#define R_X86_64_GOTPC32_TLSDESC 34
-#define R_X86_64_TLSDESC_CALL 35
-#define R_X86_64_TLSDESC 36
-#define R_X86_64_IRELATIVE 37
-#define R_X86_64_RELATIVE64 38
-#define R_X86_64_PC32_BND 39
-#define R_X86_64_PLT32_BND 40
-#define R_X86_64_GOTPCRELX 41
-#define R_X86_64_REX_GOTPCRELX 42
-
-#endif
diff --git a/libc/include/bits/fenv_riscv64.h b/libc/include/bits/fenv_riscv64.h
new file mode 100644
index 0000000..e1e43b6
--- /dev/null
+++ b/libc/include/bits/fenv_riscv64.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+typedef __uint32_t fenv_t;
+typedef __uint32_t fexcept_t;
+
+/* Exception flags. No FE_DENORMAL for riscv64. */
+#define FE_INEXACT 0x01
+#define FE_UNDERFLOW 0x02
+#define FE_OVERFLOW 0x04
+#define FE_DIVBYZERO 0x08
+#define FE_INVALID 0x10
+#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+
+/* Rounding modes. */
+#define FE_TONEAREST 0x0
+#define FE_TOWARDZERO 0x1
+#define FE_DOWNWARD 0x2
+#define FE_UPWARD 0x3
+
+__END_DECLS
diff --git a/libc/include/bits/fortify/fcntl.h b/libc/include/bits/fortify/fcntl.h
index 7063541..7fe60f4 100644
--- a/libc/include/bits/fortify/fcntl.h
+++ b/libc/include/bits/fortify/fcntl.h
@@ -41,7 +41,7 @@
#if defined(__BIONIC_FORTIFY)
#define __open_too_many_args_error "too many arguments"
#define __open_too_few_args_error "called with O_CREAT or O_TMPFILE, but missing mode"
-#define __open_useless_modes_warning "has superfluous mode bits; missing O_CREAT?"
+#define __open_useless_modes_warning "has superfluous mode bits; missing O_CREAT or O_TMPFILE?"
/* O_TMPFILE shares bits with O_DIRECTORY. */
#define __open_modes_useful(flags) (((flags) & O_CREAT) || ((flags) & O_TMPFILE) == O_TMPFILE)
diff --git a/libc/include/elf.h b/libc/include/elf.h
index 4739bbd..1dfc008 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -30,13 +30,12 @@
#include <sys/cdefs.h>
-#include <bits/auxvec.h>
-#include <bits/elf_arm.h>
-#include <bits/elf_arm64.h>
-#include <bits/elf_x86.h>
-#include <bits/elf_x86_64.h>
#include <linux/elf.h>
#include <linux/elf-em.h>
+#undef EI_PAD
+
+#include <bits/auxvec.h>
+#include <bits/elf_common.h>
/* http://www.sco.com/developers/gabi/latest/ch4.intro.html */
typedef __u64 Elf32_Xword;
@@ -83,14 +82,6 @@
Elf64_Word l_version;
Elf64_Word l_flags;
} Elf64_Lib;
-/* ElfW(Lib)::l_flags values. */
-#define LL_NONE 0x0
-#define LL_EXACT_MATCH 0x1
-#define LL_IGNORE_INT_VER 0x2
-#define LL_REQUIRE_MINOR 0x4
-#define LL_EXPORTS 0x8
-#define LL_DELAY_LOAD 0x10
-#define LL_DELTA 0x20
typedef struct {
Elf32_Xword m_value;
@@ -118,14 +109,6 @@
Elf64_Half si_boundto;
Elf64_Half si_flags;
} Elf64_Syminfo;
-/* ElfW(Syminfo)::si_boundto values. */
-#define SYMINFO_BT_SELF 0xffff
-#define SYMINFO_BT_PARENT 0xfffe
-/* ElfW(Syminfo)::si_flags values. */
-#define SYMINFO_FLG_DIRECT 0x1
-#define SYMINFO_FLG_PASSTHRU 0x2
-#define SYMINFO_FLG_COPY 0x4
-#define SYMINFO_FLG_LAZYLOAD 0x8
typedef Elf32_Half Elf32_Versym;
typedef Elf64_Half Elf64_Versym;
@@ -197,24 +180,12 @@
typedef Elf64_Xword Elf64_Relr;
/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html */
-#define DF_ORIGIN 0x00000001
-#define DF_SYMBOLIC 0x00000002
-#define DF_TEXTREL 0x00000004
-#define DF_BIND_NOW 0x00000008
-#define DF_STATIC_TLS 0x00000010
#define DF_1_NOW 0x00000001 /* Perform complete relocation processing. */
-#define DF_1_GLOBAL 0x00000002 /* implies RTLD_GLOBAL */
#define DF_1_GROUP 0x00000004
-#define DF_1_NODELETE 0x00000008 /* implies RTLD_NODELETE */
-#define DF_1_LOADFLTR 0x00000010
#define DF_1_INITFIRST 0x00000020
-#define DF_1_NOOPEN 0x00000040 /* Object can not be used with dlopen(3) */
-#define DF_1_ORIGIN 0x00000080
#define DF_1_DIRECT 0x00000100
#define DF_1_TRANS 0x00000200
-#define DF_1_INTERPOSE 0x00000400
-#define DF_1_NODEFLIB 0x00000800
#define DF_1_NODUMP 0x00001000 /* Object cannot be dumped with dldump(3) */
#define DF_1_CONFALT 0x00002000
#define DF_1_ENDFILTEE 0x00004000
@@ -230,58 +201,10 @@
#define DF_1_GLOBAUDIT 0x01000000
#define DF_1_SINGLETON 0x02000000
#define DF_1_STUB 0x04000000
-#define DF_1_PIE 0x08000000
-
-/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html */
-#define DT_BIND_NOW 24
-#define DT_INIT_ARRAY 25
-#define DT_FINI_ARRAY 26
-#define DT_INIT_ARRAYSZ 27
-#define DT_FINI_ARRAYSZ 28
-#define DT_RUNPATH 29
-#define DT_FLAGS 30
-/* glibc and BSD disagree for DT_ENCODING; glibc looks wrong. */
-#define DT_PREINIT_ARRAY 32
-#define DT_PREINIT_ARRAYSZ 33
-#define DT_RELRSZ 35
-#define DT_RELR 36
-#define DT_RELRENT 37
-
-#define DT_GNU_HASH 0x6ffffef5
-#define DT_TLSDESC_PLT 0x6ffffef6
-#define DT_TLSDESC_GOT 0x6ffffef7
-
-/* http://www.sco.com/developers/gabi/latest/ch4.eheader.html */
-#define EI_ABIVERSION 8
-#undef EI_PAD
-#define EI_PAD 9
-
-/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html */
-#define ELFCOMPRESS_ZLIB 1
-#define ELFCOMPRESS_LOOS 0x60000000
-#define ELFCOMPRESS_HIOS 0x6fffffff
-#define ELFCOMPRESS_LOPROC 0x70000000
-#define ELFCOMPRESS_HIPROC 0x7fffffff
/* http://www.sco.com/developers/gabi/latest/ch4.eheader.html */
#define ELFOSABI_SYSV 0 /* Synonym for ELFOSABI_NONE used by valgrind. */
-#define ELFOSABI_HPUX 1
-#define ELFOSABI_NETBSD 2
#define ELFOSABI_GNU 3 /* Synonym for ELFOSABI_LINUX. */
-#define ELFOSABI_SOLARIS 6
-#define ELFOSABI_AIX 7
-#define ELFOSABI_IRIX 8
-#define ELFOSABI_FREEBSD 9
-#define ELFOSABI_TRU64 10
-#define ELFOSABI_MODESTO 11
-#define ELFOSABI_OPENBSD 12
-#define ELFOSABI_OPENVMS 13
-#define ELFOSABI_NSK 14
-#define ELFOSABI_AROS 15
-#define ELFOSABI_FENIXOS 16
-#define ELFOSABI_CLOUDABI 17
-#define ELFOSABI_OPENVOS 18
-#define ELFOSABI_ARM_AEABI 64
/* http://www.sco.com/developers/gabi/latest/ch4.reloc.html */
#define ELF32_R_INFO(sym, type) ((((Elf32_Word)sym) << 8) | ((type) & 0xff))
@@ -294,236 +217,17 @@
#define ELF32_ST_INFO(b,t) ELF_ST_INFO(b,t)
#define ELF64_ST_INFO(b,t) ELF_ST_INFO(b,t)
-/* http://www.sco.com/developers/gabi/latest/ch4.eheader.html */
-#define EM_S370 9
-#define EM_VPP500 17
-#define EM_960 19
-#define EM_V800 36
-#define EM_FR20 37
-#define EM_RH32 38
-#define EM_RCE 39
-#define EM_FAKE_ALPHA 41
-#define EM_TRICORE 44
-#define EM_ARC 45
-#define EM_H8_300H 47
-#define EM_H8S 48
-#define EM_H8_500 49
-#define EM_MIPS_X 51
-#define EM_COLDFIRE 52
-#define EM_68HC12 53
-#define EM_MMA 54
-#define EM_PCP 55
-#define EM_NCPU 56
-#define EM_NDR1 57
-#define EM_STARCORE 58
-#define EM_ME16 59
-#define EM_ST100 60
-#define EM_TINYJ 61
-#define EM_PDSP 63
-#define EM_PDP10 64
-#define EM_PDP11 65
-#define EM_FX66 66
-#define EM_ST9PLUS 67
-#define EM_ST7 68
-#define EM_68HC16 69
-#define EM_68HC11 70
-#define EM_68HC08 71
-#define EM_68HC05 72
-#define EM_SVX 73
-#define EM_ST19 74
-#define EM_VAX 75
-#define EM_JAVELIN 77
-#define EM_FIREPATH 78
-#define EM_ZSP 79
-#define EM_MMIX 80
-#define EM_HUANY 81
-#define EM_PRISM 82
-#define EM_AVR 83
-#define EM_FR30 84
-#define EM_D10V 85
-#define EM_D30V 86
-#define EM_V850 87
-#define EM_MN10200 90
-#define EM_PJ 91
-#define EM_ARC_COMPACT 93
-#define EM_XTENSA 94
-#define EM_VIDEOCORE 95
-#define EM_TMM_GPP 96
-#define EM_NS32K 97
-#define EM_TPC 98
-#define EM_SNP1K 99
-#define EM_ST200 100
-#define EM_IP2K 101
-#define EM_MAX 102
-#define EM_CR 103
-#define EM_F2MC16 104
-#define EM_MSP430 105
-#define EM_SE_C33 107
-#define EM_SEP 108
-#define EM_ARCA 109
-#define EM_UNICORE 110
-#define EM_EXCESS 111
-#define EM_DXP 112
-#define EM_CRX 114
-#define EM_XGATE 115
-#define EM_C166 116
-#define EM_M16C 117
-#define EM_DSPIC30F 118
-#define EM_CE 119
-#define EM_M32C 120
-#define EM_TSK3000 131
-#define EM_RS08 132
-#define EM_SHARC 133
-#define EM_ECOG2 134
-#define EM_SCORE7 135
-#define EM_DSP24 136
-#define EM_VIDEOCORE3 137
-#define EM_LATTICEMICO32 138
-#define EM_SE_C17 139
-#define EM_TI_C2000 141
-#define EM_TI_C5500 142
-#define EM_MMDSP_PLUS 160
-#define EM_CYPRESS_M8C 161
-#define EM_R32C 162
-#define EM_TRIMEDIA 163
-#define EM_QDSP6 164
-#define EM_8051 165
-#define EM_STXP7X 166
-#define EM_NDS32 167
-#define EM_ECOG1 168
-#define EM_ECOG1X 168
-#define EM_MAXQ30 169
-#define EM_XIMO16 170
-#define EM_MANIK 171
-#define EM_CRAYNV2 172
-#define EM_RX 173
-#define EM_METAG 174
-#define EM_MCST_ELBRUS 175
-#define EM_ECOG16 176
-#define EM_CR16 177
-#define EM_ETPU 178
-#define EM_SLE9X 179
-#define EM_L10M 180
-#define EM_K10M 181
-#define EM_AVR32 185
-#define EM_STM8 186
-#define EM_TILE64 187
-#define EM_CUDA 190
-#define EM_CLOUDSHIELD 192
-#define EM_COREA_1ST 193
-#define EM_COREA_2ND 194
-#define EM_ARC_COMPACT2 195
-#define EM_OPEN8 196
-#define EM_RL78 197
-#define EM_VIDEOCORE5 198
-#define EM_78KOR 199
-#define EM_56800EX 200
-#define EM_BA1 201
-#define EM_BA2 202
-#define EM_XCORE 203
-#define EM_MCHP_PIC 204
-#define EM_INTEL205 205
-#define EM_INTEL206 206
-#define EM_INTEL207 207
-#define EM_INTEL208 208
-#define EM_INTEL209 209
-#define EM_KM32 210
-#define EM_KMX32 211
-#define EM_KMX16 212
-#define EM_KMX8 213
-#define EM_KVARC 214
-#define EM_CDP 215
-#define EM_COGE 216
-#define EM_COOL 217
-#define EM_NORC 218
-#define EM_CSR_KALIMBA 219
-#define EM_Z80 220
-#define EM_VISIUM 221
-#define EM_FT32 222
-#define EM_MOXIE 223
-#define EM_AMDGPU 224
-#define EM_RISCV 243
-
-/* http://www.sco.com/developers/gabi/latest/ch4.eheader.html */
-#define ET_LOOS 0xfe00
-#define ET_HIOS 0xfeff
-
/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html */
-#define GRP_COMDAT 0x1
#define GRP_MASKOS 0x0ff00000
#define GRP_MASKPROC 0xf0000000
-/* http://www.sco.com/developers/gabi/latest/ch5.pheader.html */
-#define PF_X 0x1
-#define PF_W 0x2
-#define PF_R 0x4
-#define PF_MASKOS 0x0ff00000
-#define PF_MASKPROC 0xf0000000
-
-#define PT_GNU_RELRO 0x6474e552
-
-#define STB_LOOS 10
-#define STB_HIOS 12
-#define STB_LOPROC 13
-#define STB_HIPROC 15
-
/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html */
-#define SHF_MERGE 0x10
-#define SHF_STRINGS 0x20
-#define SHF_INFO_LINK 0x40
-#define SHF_LINK_ORDER 0x80
-#define SHF_OS_NONCONFORMING 0x100
-#define SHF_GROUP 0x200
-#define SHF_TLS 0x400
-#define SHF_COMPRESSED 0x800
-#define SHF_MASKOS 0x0ff00000
-#define SHF_MASKPROC 0xf0000000
-
-/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html */
-#define SHN_LOOS 0xff20
-#define SHN_HIOS 0xff3f
-#define SHN_XINDEX 0xffff
-
-/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html */
-#define SHT_INIT_ARRAY 14
-#define SHT_FINI_ARRAY 15
-#define SHT_PREINIT_ARRAY 16
-#define SHT_GROUP 17
-#define SHT_SYMTAB_SHNDX 18
+/*
+ * Standard replacement for SHT_ANDROID_RELR.
+ */
#define SHT_RELR 19
#undef SHT_NUM
#define SHT_NUM 20
-#define SHT_LOOS 0x60000000
-#define SHT_HIOS 0x6fffffff
-
-/* http://www.sco.com/developers/gabi/latest/ch4.symtab.html */
-#define STN_UNDEF 0
-
-/* http://www.sco.com/developers/gabi/latest/ch4.symtab.html */
-#define STT_GNU_IFUNC 10
-#define STT_LOOS 10
-#define STT_HIOS 12
-#define STT_LOPROC 13
-#define STT_HIPROC 15
-
-/* http://www.sco.com/developers/gabi/latest/ch4.symtab.html */
-#define STV_DEFAULT 0
-#define STV_INTERNAL 1
-#define STV_HIDDEN 2
-#define STV_PROTECTED 3
-
-/* The kernel uses NT_PRFPREG but glibc also offers NT_FPREGSET */
-#define NT_FPREGSET NT_PRFPREG
-
-#define ELF_NOTE_GNU "GNU"
-
-#define NT_GNU_BUILD_ID 3
-
-#define VER_FLG_BASE 0x1
-#define VER_FLG_WEAK 0x2
-
-#define VER_NDX_LOCAL 0
-#define VER_NDX_GLOBAL 1
/*
* Experimental support for SHT_RELR sections. For details, see proposal
@@ -553,3 +257,13 @@
#define DT_ANDROID_RELSZ 0x60000010 // DT_LOOS + 3
#define DT_ANDROID_RELA 0x60000011 // DT_LOOS + 4
#define DT_ANDROID_RELASZ 0x60000012 // DT_LOOS + 5
+
+/* Linux traditionally doesn't have the trailing 64 that BSD has on these. */
+#define R_AARCH64_TLS_DTPREL R_AARCH64_TLS_DTPREL64
+#define R_AARCH64_TLS_DTPMOD R_AARCH64_TLS_DTPMOD64
+#define R_AARCH64_TLS_TPREL R_AARCH64_TLS_TPREL64
+
+/* TODO: upstream these to FreeBSD? */
+#define R_ARM_TLS_DESC 13
+#define R_ARM_IRELATIVE 160
+#define R_X86_64_JUMP_SLOT 7
diff --git a/libc/include/fenv.h b/libc/include/fenv.h
index 7b775b6..3fd9852 100644
--- a/libc/include/fenv.h
+++ b/libc/include/fenv.h
@@ -35,6 +35,8 @@
#include <bits/fenv_arm.h>
#elif defined(__i386__)
#include <bits/fenv_x86.h>
+#elif defined(__riscv)
+#include <bits/fenv_riscv64.h>
#elif defined(__x86_64__)
#include <bits/fenv_x86_64.h>
#endif
diff --git a/libc/include/setjmp.h b/libc/include/setjmp.h
index 3a64b33..a3de9c7 100644
--- a/libc/include/setjmp.h
+++ b/libc/include/setjmp.h
@@ -37,8 +37,12 @@
* @(#)setjmp.h 8.2 (Berkeley) 1/21/94
*/
-#ifndef _SETJMP_H_
-#define _SETJMP_H_
+#pragma once
+
+/**
+ * @file setjmp.h
+ * @brief Non-local jumps.
+ */
#include <sys/cdefs.h>
@@ -48,28 +52,60 @@
#define _JBLEN 64
#elif defined(__i386__)
#define _JBLEN 10
+#elif defined(__riscv)
+#define _JBLEN 29
#elif defined(__x86_64__)
#define _JBLEN 11
#endif
+/** The type of the buffer used by sigsetjmp()/siglongjmp(). */
typedef long sigjmp_buf[_JBLEN + 1];
+
+/** The type of the buffer used by setjmp()/longjmp(). */
typedef long jmp_buf[_JBLEN];
#undef _JBLEN
__BEGIN_DECLS
+/**
+ * Equivalent to sigsetjmp() with the second argument 0, so that the signal
+ * mask is not saved.
+ */
int _setjmp(jmp_buf __env) __returns_twice;
+
+/** Equivalent to siglongjmp(). */
__noreturn void _longjmp(jmp_buf __env, int __value);
+/**
+ * Equivalent to sigsetjmp() with the second argument 1, so that the signal
+ * mask is saved.
+ */
int setjmp(jmp_buf __env) __returns_twice;
-__noreturn void longjmp(jmp_buf __env, int __value);
+/** C11 says setjmp() must be a macro, but Android already had a function. */
#define setjmp(__env) setjmp(__env)
-int sigsetjmp(sigjmp_buf __env, int __save_signal_mask);
+/** Equivalent to siglongjmp(). */
+__noreturn void longjmp(jmp_buf __env, int __value);
+
+/**
+ * [sigsetjmp(3)](http://man7.org/linux/man-pages/man3/sigsetjmp.3.html)
+ * sets the target of a future siglongjmp() call, saving or not saving the
+ * current signal mask based on the second argument.
+ *
+ * Returns 0 when first called, and returns the value passed to siglongjmp()
+ * when returning here as a result of a siglongjmp() call.
+ */
+int sigsetjmp(sigjmp_buf __env, int __save_signal_mask) __returns_twice;
+
+/**
+ * [siglongjmp(3)](http://man7.org/linux/man-pages/man3/siglongjmp.3.html)
+ * transfers control back to the site of the sigsetjmp() call that initialized
+ * the given jump buffer, returning the given value.
+ *
+ * Does not return.
+ */
__noreturn void siglongjmp(sigjmp_buf __env, int __value);
__END_DECLS
-
-#endif
diff --git a/libc/include/stdio_ext.h b/libc/include/stdio_ext.h
index 3aa183d..eda5919 100644
--- a/libc/include/stdio_ext.h
+++ b/libc/include/stdio_ext.h
@@ -96,13 +96,21 @@
/**
* [__fpending(3)](http://man7.org/linux/man-pages/man3/__fpending.3.html) returns the number of
- * bytes in the output buffer.
+ * bytes in the output buffer. See __freadahead() for the input buffer.
*
* Available since API level 23.
*/
size_t __fpending(FILE* __fp) __INTRODUCED_IN(23);
/**
+ * __freadahead(3) returns the number of bytes in the input buffer.
+ * See __fpending() for the output buffer.
+ *
+ * Available since API level 34.
+ */
+size_t __freadahead(FILE* __fp) __INTRODUCED_IN(34);
+
+/**
* [_flushlbf(3)](http://man7.org/linux/man-pages/man3/_flushlbf.3.html) flushes all
* line-buffered streams.
*
diff --git a/libc/include/string.h b/libc/include/string.h
index 0cc5611..59c4687 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -55,7 +55,24 @@
void* mempcpy(void* __dst, const void* __src, size_t __n) __INTRODUCED_IN(23);
#endif
void* memmove(void* __dst, const void* __src, size_t __n);
+
+/**
+ * [memset(3)](http://man7.org/linux/man-pages/man3/memset.3.html) writes the
+ * bottom 8 bits of the given int to the next `n` bytes of `dst`.
+ *
+ * Returns `dst`.
+ */
void* memset(void* __dst, int __ch, size_t __n);
+
+/**
+ * [memset_explicit(3)](http://man7.org/linux/man-pages/man3/memset_explicit.3.html)
+ * writes the bottom 8 bits of the given int to the next `n` bytes of `dst`,
+ * but won't be optimized out by the compiler.
+ *
+ * Returns `dst`.
+ */
+void* memset_explicit(void* __dst, int __ch, size_t __n) __INTRODUCED_IN(34);
+
void* memmem(const void* __haystack, size_t __haystack_size, const void* __needle, size_t __needle_size) __attribute_pure__;
char* strchr(const char* __s, int __ch) __attribute_pure__;
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index 6ef0c12..9e865a3 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -168,8 +168,13 @@
* PID file descriptor.
*
* Returns the number of bytes advised on success, and returns -1 and sets `errno` on failure.
+ *
+ * Available since API level 31. Its sibling process_mrelease() does not have a
+ * libc wrapper and should be called using syscall() instead. Given the lack of
+ * widespread applicability of this system call and the absence of wrappers in
+ * other libcs, it was probably a mistake to have added this wrapper to bionic.
*/
-ssize_t process_madvise(int __pid_fd, const struct iovec* __iov, size_t __count, int __advice, unsigned __flags);
+ssize_t process_madvise(int __pid_fd, const struct iovec* __iov, size_t __count, int __advice, unsigned __flags) __INTRODUCED_IN(31);
#if defined(__USE_GNU)
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index 4184f6c..623631e 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -40,7 +40,7 @@
__BEGIN_DECLS
-#if defined(__aarch64__)
+#if defined(__aarch64__) || defined(__riscv)
#define __STAT64_BODY \
dev_t st_dev; \
ino_t st_ino; \
diff --git a/libc/include/sys/ucontext.h b/libc/include/sys/ucontext.h
index 9c5801f..72b8adb 100644
--- a/libc/include/sys/ucontext.h
+++ b/libc/include/sys/ucontext.h
@@ -26,8 +26,7 @@
* SUCH DAMAGE.
*/
-#ifndef _SYS_UCONTEXT_H_
-#define _SYS_UCONTEXT_H_
+#pragma once
#include <sys/cdefs.h>
@@ -313,8 +312,66 @@
struct _libc_fpstate __fpregs_mem;
} ucontext_t;
+#elif defined(__riscv)
+
+#define NGREG 32
+
+#define REG_PC 0
+#define REG_RA 1
+#define REG_SP 2
+#define REG_TP 4
+#define REG_S0 8
+#define REG_A0 10
+
+typedef unsigned long __riscv_mc_gp_state[NGREG];
+
+typedef unsigned long greg_t;
+typedef unsigned long gregset_t[NGREG];
+typedef union __riscv_mc_fp_state fpregset_t;
+
+/* These match the kernel <asm/ptrace.h> types but with different names. */
+
+struct __riscv_mc_f_ext_state {
+ uint32_t __f[32];
+ uint32_t __fcsr;
+};
+
+struct __riscv_mc_d_ext_state {
+ uint64_t __f[32];
+ uint32_t __fcsr;
+};
+
+struct __riscv_mc_q_ext_state {
+ uint64_t __f[64] __attribute__((__aligned__(16)));
+ uint32_t __fcsr;
+ uint32_t __reserved[3];
+};
+
+union __riscv_mc_fp_state {
+ struct __riscv_mc_f_ext_state __f;
+ struct __riscv_mc_d_ext_state __d;
+ struct __riscv_mc_q_ext_state __q;
+};
+
+/* This matches the kernel <asm/sigcontext.h> but with different names. */
+
+typedef struct mcontext_t {
+ __riscv_mc_gp_state __gregs;
+ union __riscv_mc_fp_state __fpregs;
+} mcontext_t;
+
+/* This matches the kernel <asm/ucontext.h> but using mcontext_t. */
+
+typedef struct ucontext_t {
+ unsigned long uc_flags;
+ struct ucontext_t* uc_link;
+ stack_t uc_stack;
+ sigset_t uc_sigmask;
+ /* The kernel adds extra padding here to allow sigset_t to grow. */
+ char __padding[128 - sizeof(sigset_t)];
+ mcontext_t uc_mcontext;
+} ucontext_t;
+
#endif
__END_DECLS
-
-#endif /* _SYS_UCONTEXT_H_ */
diff --git a/libc/include/sys/user.h b/libc/include/sys/user.h
index 2392edd..432c7cb 100644
--- a/libc/include/sys/user.h
+++ b/libc/include/sys/user.h
@@ -26,8 +26,7 @@
* SUCH DAMAGE.
*/
-#ifndef _SYS_USER_H_
-#define _SYS_USER_H_
+#pragma once
#include <sys/cdefs.h>
#include <stddef.h> /* For size_t. */
@@ -233,6 +232,11 @@
uint32_t fpcr;
};
+#elif defined(__riscv)
+
+// This space deliberately left blank for now.
+// No other libcs have any riscv64-specific structs.
+
#else
#error "Unsupported architecture."
@@ -240,5 +244,3 @@
#endif
__END_DECLS
-
-#endif /* _SYS_USER_H_ */
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index e360421..b5694b8 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -313,10 +313,37 @@
int getdomainname(char* __buf, size_t __buf_size) __INTRODUCED_IN(26);
int setdomainname(const char* __name, size_t __n) __INTRODUCED_IN(26);
+/**
+ * [copy_file_range(2)](https://man7.org/linux/man-pages/man2/copy_file_range.2.html) copies
+ * a range of data from one file descriptor to another.
+ *
+ * Returns the number of bytes copied on success, and returns -1 and sets errno
+ * on failure.
+ *
+ * Available since API level 34.
+ */
+ssize_t copy_file_range(int __fd_in, off64_t* __off_in, int __fd_out, off64_t* __off_out, size_t __length, unsigned int __flags) __INTRODUCED_IN(34);
+
#if __ANDROID_API__ >= 28
void swab(const void* __src, void* __dst, ssize_t __byte_count) __INTRODUCED_IN(28);
#endif
+/**
+ * [close_range(2)](https://man7.org/linux/man-pages/man2/close_range.2.html)
+ * performs an action (which depends on value of flags) on an inclusive range
+ * of file descriptors.
+ *
+ * Available since API level 34.
+ *
+ * Note: there is no emulation on too old kernels, hence this will fail with
+ * -1/ENOSYS on pre-5.9 kernels, -1/EINVAL for unsupported flags. In particular
+ * CLOSE_RANGE_CLOEXEC requires 5.11, though support was backported to Android
+ * Common Kernel 5.10-T.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
+int close_range(unsigned int __min_fd, unsigned int __max_fd, int __flags) __INTRODUCED_IN(34);
+
#if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
#define _UNISTD_H_
#include <bits/fortify/unistd.h>
diff --git a/libc/kernel/README.md b/libc/kernel/README.md
index 5f1c81d..3846a4f 100644
--- a/libc/kernel/README.md
+++ b/libc/kernel/README.md
@@ -99,6 +99,7 @@
Run this command to automatically download the latest version of the headers
and import them if there is no checked out kernel source tree:
```
+ # For testing only, not for use in production!
bionic/libc/kernel/tools/generate_uapi_headers.sh --download-kernel
```
diff --git a/libc/kernel/android/BUILD b/libc/kernel/android/BUILD
new file mode 100644
index 0000000..b862a6d
--- /dev/null
+++ b/libc/kernel/android/BUILD
@@ -0,0 +1,43 @@
+# Copyright (C) 2022 The Android Open Source Project
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+load("//build/bazel/rules/apis:cc_api_contribution.bzl", "cc_api_headers")
+
+package(default_visibility = ["//bionic/libc:__pkg__"])
+
+cc_api_headers(
+ name="libc_kernel_android_uapi_headers",
+ include_dir="uapi",
+ hdrs=glob(["uapi/**/*.h"]),
+ system=True,
+)
+
+cc_api_headers(
+ name="libc_kernel_android_scsi_headers",
+ include_dir="scsi",
+ hdrs=glob(["scsi/**/*.h"]),
+ system=True,
+)
diff --git a/libc/kernel/android/scsi/scsi/scsi_proto.h b/libc/kernel/android/scsi/scsi/scsi_proto.h
index eea87a0..13ac4c8 100644
--- a/libc/kernel/android/scsi/scsi/scsi_proto.h
+++ b/libc/kernel/android/scsi/scsi/scsi_proto.h
@@ -183,6 +183,8 @@
ZBC_ZONE_TYPE_CONV = 0x1,
ZBC_ZONE_TYPE_SEQWRITE_REQ = 0x2,
ZBC_ZONE_TYPE_SEQWRITE_PREF = 0x3,
+ ZBC_ZONE_TYPE_SEQ_OR_BEFORE_REQ = 0x4,
+ ZBC_ZONE_TYPE_GAP = 0x5,
};
enum zbc_zone_cond {
ZBC_ZONE_COND_NO_WP = 0x0,
@@ -194,6 +196,10 @@
ZBC_ZONE_COND_FULL = 0xe,
ZBC_ZONE_COND_OFFLINE = 0xf,
};
+enum zbc_zone_alignment_method {
+ ZBC_CONSTANT_ZONE_LENGTH = 0x1,
+ ZBC_CONSTANT_ZONE_START_OFFSET = 0x8,
+};
enum scsi_version_descriptor {
SCSI_VERSION_DESCRIPTOR_FCP4 = 0x0a40,
SCSI_VERSION_DESCRIPTOR_ISCSI = 0x0960,
diff --git a/libc/kernel/tools/clean_header.py b/libc/kernel/tools/clean_header.py
index cfd301a..f15fab4 100755
--- a/libc/kernel/tools/clean_header.py
+++ b/libc/kernel/tools/clean_header.py
@@ -109,9 +109,6 @@
if arch and arch in kernel_default_arch_macros:
macros.update(kernel_default_arch_macros[arch])
- if arch and arch in kernel_arch_token_replacements:
- blocks.replaceTokens(kernel_arch_token_replacements[arch])
-
blocks.removeStructs(kernel_structs_to_remove)
blocks.optimizeMacros(macros)
blocks.optimizeIf01()
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index 26121ca..40e1f26 100755
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -14,7 +14,7 @@
utils.panic('ANDROID_BUILD_TOP not set.\n')
# Set up the env vars for libclang.
-site.addsitedir(os.path.join(top, 'prebuilts/clang/host/linux-x86/clang-stable/lib64/python3/site-packages/'))
+site.addsitedir(os.path.join(top, 'prebuilts/clang/host/linux-x86/clang-stable/lib/python3/site-packages/'))
import clang.cindex
from clang.cindex import conf
@@ -28,7 +28,7 @@
# Set up LD_LIBRARY_PATH to include libclang.so, libLLVM.so, and etc.
# Note that setting LD_LIBRARY_PATH with os.putenv() sometimes doesn't help.
-clang.cindex.Config.set_library_file(os.path.join(top, 'prebuilts/clang/host/linux-x86/clang-stable/lib64/libclang.so'))
+clang.cindex.Config.set_library_file(os.path.join(top, 'prebuilts/clang/host/linux-x86/clang-stable/lib/libclang.so'))
from defaults import *
@@ -155,6 +155,11 @@
pass
+class UnparseableStruct(Exception):
+ """An exception that will be raised for structs that cannot be parsed."""
+ pass
+
+
# The __contains__ function in libclang SourceRange class contains a bug. It
# gives wrong result when dealing with single line range.
# Bug filed with upstream:
@@ -1197,22 +1202,38 @@
def removeStructs(self, structs):
"""Remove structs."""
- for b in self.blocks:
+ extra_includes = []
+ block_num = 0
+ num_blocks = len(self.blocks)
+ while block_num < num_blocks:
+ b = self.blocks[block_num]
+ block_num += 1
# Have to look in each block for a top-level struct definition.
if b.directive:
continue
num_tokens = len(b.tokens)
- # A struct definition has at least 5 tokens:
+ # A struct definition usually looks like:
# struct
# ident
# {
# }
# ;
- if num_tokens < 5:
+ # However, the structure might be spread across multiple blocks
+ # if the structure looks like this:
+ # struct ident
+ # {
+ # #ifdef VARIABLE
+ # pid_t pid;
+ # #endif
+ # }:
+ # So the total number of tokens in the block might be less than
+ # five but assume at least three.
+ if num_tokens < 3:
continue
+
# This is a simple struct finder, it might fail if a top-level
# structure has an #if type directives that confuses the algorithm
- # for finding th end of the structure. Or if there is another
+ # for finding the end of the structure. Or if there is another
# structure definition embedded in the structure.
i = 0
while i < num_tokens - 2:
@@ -1223,24 +1244,58 @@
if (b.tokens[i + 1].kind == TokenKind.IDENTIFIER and
b.tokens[i + 2].kind == TokenKind.PUNCTUATION and
b.tokens[i + 2].id == "{" and b.tokens[i + 1].id in structs):
+ # Add an include for the structure to be removed of the form:
+ # #include <bits/STRUCT_NAME.h>
+ struct_token = b.tokens[i + 1]
+ if not structs[struct_token.id]:
+ extra_includes.append("<bits/%s.h>" % struct_token.id)
+
# Search forward for the end of the structure.
- # Very simple search, look for } and ; tokens. If something
- # more complicated is needed we can add it later.
+ # Very simple search, look for } and ; tokens.
+ # If we hit the end of the block, we'll need to start
+ # looking at the next block.
j = i + 3
- while j < num_tokens - 1:
- if (b.tokens[j].kind == TokenKind.PUNCTUATION and
- b.tokens[j].id == "}" and
- b.tokens[j + 1].kind == TokenKind.PUNCTUATION and
- b.tokens[j + 1].id == ";"):
- b.tokens = b.tokens[0:i] + b.tokens[j + 2:num_tokens]
+ depth = 1
+ struct_removed = False
+ while not struct_removed:
+ while j < num_tokens:
+ if b.tokens[j].kind == TokenKind.PUNCTUATION:
+ if b.tokens[j].id == '{':
+ depth += 1
+ elif b.tokens[j].id == '}':
+ depth -= 1
+ elif b.tokens[j].id == ';' and depth == 0:
+ b.tokens = b.tokens[0:i] + b.tokens[j + 1:num_tokens]
+ num_tokens = len(b.tokens)
+ struct_removed = True
+ break
+ j += 1
+ if not struct_removed:
+ b.tokens = b.tokens[0:i]
+
+ # Skip directive blocks.
+ start_block = block_num
+ while block_num < num_blocks:
+ if not self.blocks[block_num].directive:
+ break
+ block_num += 1
+ if block_num >= num_blocks:
+ # Unparsable struct, error out.
+ raise UnparseableStruct("Cannot remove struct %s: %s" % (struct_token.id, struct_token.location))
+ self.blocks = self.blocks[0:start_block] + self.blocks[block_num:num_blocks]
+ num_blocks = len(self.blocks)
+ b = self.blocks[start_block]
+ block_num = start_block + 1
num_tokens = len(b.tokens)
- j = i
- break
- j += 1
- i = j
+ i = 0
+ j = 0
continue
i += 1
+ for extra_include in extra_includes:
+ replacement = CppStringTokenizer(extra_include)
+ self.blocks.insert(2, Block(replacement.tokens, directive='include'))
+
def optimizeAll(self, macros):
self.optimizeMacros(macros)
self.optimizeIf01()
@@ -1404,35 +1459,12 @@
def replaceTokens(self, replacements):
"""Replace tokens according to the given dict."""
- extra_includes = []
for b in self.blocks:
made_change = False
if b.isInclude() is None:
i = 0
while i < len(b.tokens):
tok = b.tokens[i]
- if (tok.kind == TokenKind.KEYWORD and tok.id == 'struct'
- and (i + 2) < len(b.tokens) and b.tokens[i + 2].id == '{'):
- struct_name = b.tokens[i + 1].id
- if struct_name in kernel_struct_replacements:
- extra_includes.append("<bits/%s.h>" % struct_name)
- end = i + 2
- depth = 1
- while end < len(b.tokens) and depth > 0:
- if b.tokens[end].id == '}':
- depth -= 1
- elif b.tokens[end].id == '{':
- depth += 1
- end += 1
- end += 1 # Swallow last '}'
- while end < len(b.tokens) and b.tokens[end].id != ';':
- end += 1
- end += 1 # Swallow ';'
- # Remove these tokens. We'll replace them later with a #include block.
- b.tokens[i:end] = []
- made_change = True
- # We've just modified b.tokens, so revisit the current offset.
- continue
if tok.kind == TokenKind.IDENTIFIER:
if tok.id in replacements:
tok.id = replacements[tok.id]
@@ -1447,10 +1479,6 @@
# Keep 'expr' in sync with 'tokens'.
b.expr = CppExpr(b.tokens)
- for extra_include in extra_includes:
- replacement = CppStringTokenizer(extra_include)
- self.blocks.insert(2, Block(replacement.tokens, directive='include'))
-
def strip_space(s):
@@ -1647,7 +1675,7 @@
def get_blocks(self, lines):
blocks = BlockParser().parse(CppStringTokenizer('\n'.join(lines)))
- return map(lambda a: str(a), blocks)
+ return list(map(lambda a: str(a), blocks))
def test_hash(self):
self.assertEqual(self.get_blocks(["#error hello"]), ["#error hello"])
@@ -2020,7 +2048,7 @@
struct timeval val2;
};
"""
- self.assertEqual(self.parse(text, set(["remove"])), expected)
+ self.assertEqual(self.parse(text, {"remove": True}), expected)
def test_remove_struct_from_end(self):
text = """\
@@ -2039,7 +2067,7 @@
struct timeval val2;
};
"""
- self.assertEqual(self.parse(text, set(["remove"])), expected)
+ self.assertEqual(self.parse(text, {"remove": True}), expected)
def test_remove_minimal_struct(self):
text = """\
@@ -2047,7 +2075,7 @@
};
"""
expected = "";
- self.assertEqual(self.parse(text, set(["remove"])), expected)
+ self.assertEqual(self.parse(text, {"remove": True}), expected)
def test_remove_struct_with_struct_fields(self):
text = """\
@@ -2067,7 +2095,7 @@
struct remove val2;
};
"""
- self.assertEqual(self.parse(text, set(["remove"])), expected)
+ self.assertEqual(self.parse(text, {"remove": True}), expected)
def test_remove_consecutive_structs(self):
text = """\
@@ -2099,7 +2127,7 @@
struct timeval val2;
};
"""
- self.assertEqual(self.parse(text, set(["remove1", "remove2"])), expected)
+ self.assertEqual(self.parse(text, {"remove1": True, "remove2": True}), expected)
def test_remove_multiple_structs(self):
text = """\
@@ -2132,7 +2160,101 @@
int val;
};
"""
- self.assertEqual(self.parse(text, set(["remove1", "remove2"])), expected)
+ self.assertEqual(self.parse(text, {"remove1": True, "remove2": True}), expected)
+
+ def test_remove_struct_with_inline_structs(self):
+ text = """\
+struct remove {
+ int val1;
+ int val2;
+ struct {
+ int val1;
+ struct {
+ int val1;
+ } level2;
+ } level1;
+};
+struct something {
+ struct timeval val1;
+ struct timeval val2;
+};
+"""
+ expected = """\
+struct something {
+ struct timeval val1;
+ struct timeval val2;
+};
+"""
+ self.assertEqual(self.parse(text, {"remove": True}), expected)
+
+ def test_remove_struct_across_blocks(self):
+ text = """\
+struct remove {
+ int val1;
+ int val2;
+#ifdef PARAMETER1
+ PARAMETER1
+#endif
+#ifdef PARAMETER2
+ PARAMETER2
+#endif
+};
+struct something {
+ struct timeval val1;
+ struct timeval val2;
+};
+"""
+ expected = """\
+struct something {
+ struct timeval val1;
+ struct timeval val2;
+};
+"""
+ self.assertEqual(self.parse(text, {"remove": True}), expected)
+
+ def test_remove_struct_across_blocks_multiple_structs(self):
+ text = """\
+struct remove1 {
+ int val1;
+ int val2;
+#ifdef PARAMETER1
+ PARAMETER1
+#endif
+#ifdef PARAMETER2
+ PARAMETER2
+#endif
+};
+struct remove2 {
+};
+struct something {
+ struct timeval val1;
+ struct timeval val2;
+};
+"""
+ expected = """\
+struct something {
+ struct timeval val1;
+ struct timeval val2;
+};
+"""
+ self.assertEqual(self.parse(text, {"remove1": True, "remove2": True}), expected)
+
+ def test_remove_multiple_struct_and_add_includes(self):
+ text = """\
+struct remove1 {
+ int val1;
+ int val2;
+};
+struct remove2 {
+ struct timeval val1;
+ struct timeval val2;
+};
+"""
+ expected = """\
+#include <bits/remove1.h>
+#include <bits/remove2.h>
+"""
+ self.assertEqual(self.parse(text, {"remove1": False, "remove2": False}), expected)
class FullPathTest(unittest.TestCase):
diff --git a/libc/kernel/tools/defaults.py b/libc/kernel/tools/defaults.py
index 2089285..abb8f82 100644
--- a/libc/kernel/tools/defaults.py
+++ b/libc/kernel/tools/defaults.py
@@ -5,9 +5,6 @@
import time, os, sys
from utils import *
-# the list of supported architectures
-kernel_archs = [ 'arm', 'arm64', 'x86' ]
-
# the list of include directories that belong to the kernel
# tree. used when looking for sources...
kernel_dirs = [ "linux", "asm", "asm-generic", "mtd" ]
@@ -35,34 +32,34 @@
"__kernel_old_timeval": "1",
}
-# this is the set of known kernel data structures we want to remove from
-# the final headers
-kernel_structs_to_remove = set(
- [
- # Remove the structures since they are still the same as
- # timeval, itimerval.
- "__kernel_old_timeval",
- "__kernel_old_itimerval",
- ]
- )
+# This is the set of known kernel data structures we want to remove from
+# the final headers. If the map value is False, that means that in
+# addition to removing the structure, add an #include <bits/STRUCT.h>
+# to the file.
+kernel_structs_to_remove = {
+ # Remove the structures since they are still the same as
+ # timeval, itimerval.
+ "__kernel_old_timeval": True,
+ "__kernel_old_itimerval": True,
+ # Replace all of the below structures with #include <bits/STRUCT.h>
+ "epoll_event": False,
+ "flock": False,
+ "flock64": False,
+ "in_addr": False,
+ "ip_mreq_source": False,
+ "ip_msfilter": False,
+ }
# define to true if you want to remove all defined(CONFIG_FOO) tests
# from the clean headers. testing shows that this is not strictly necessary
# but just generates cleaner results
kernel_remove_config_macros = True
-# maps an architecture to a set of default macros that would be provided by
-# toolchain preprocessor
+# Maps an architecture to a set of default macros that would be provided by
+# the toolchain's preprocessor. Currently only used to remove confusing
+# big-endian junk from the 32-bit arm headers.
kernel_default_arch_macros = {
"arm": {"__ARMEB__": kCppUndefinedMacro, "__ARM_EABI__": "1"},
- "arm64": {},
- "x86": {},
- }
-
-kernel_arch_token_replacements = {
- "arm": {},
- "arm64": {},
- "x86": {},
}
# Replace tokens in the output according to this mapping.
@@ -100,20 +97,6 @@
}
-# This is the set of struct definitions that we want to replace with
-# a #include of <bits/struct.h> instead.
-kernel_struct_replacements = set(
- [
- "epoll_event",
- "flock",
- "flock64",
- "in_addr",
- "ip_mreq_source",
- "ip_msfilter",
- ]
- )
-
-
# This is the set of known static inline functions that we want to keep
# in the final kernel headers.
kernel_known_generic_statics = set(
diff --git a/libc/kernel/tools/generate_uapi_headers.sh b/libc/kernel/tools/generate_uapi_headers.sh
index 7e49cde..12f60e5 100755
--- a/libc/kernel/tools/generate_uapi_headers.sh
+++ b/libc/kernel/tools/generate_uapi_headers.sh
@@ -43,7 +43,7 @@
ANDROID_KERNEL_BRANCH="android-mainline"
KERNEL_DIR=""
KERNEL_DOWNLOAD=0
-ARCH_LIST=("arm" "arm64" "x86")
+ARCH_LIST=("arm" "arm64" "riscv" "x86")
ANDROID_KERNEL_DIR="external/kernel-headers/original"
SKIP_GENERATION=0
VERIFY_HEADERS_ONLY=0
diff --git a/libc/kernel/tools/update_all.py b/libc/kernel/tools/update_all.py
index f2e78da..abc72a4 100755
--- a/libc/kernel/tools/update_all.py
+++ b/libc/kernel/tools/update_all.py
@@ -27,8 +27,14 @@
def ProcessFiles(updater, original_dir, modified_dir, src_rel_dir, update_rel_dir):
# Delete the old headers before updating to the new headers.
update_dir = os.path.join(get_kernel_dir(), update_rel_dir)
- shutil.rmtree(update_dir)
- os.mkdir(update_dir, 0o755)
+ for root, dirs, files in os.walk(update_dir, topdown=True):
+ for entry in files:
+ # BUILD is a special file that needs to be preserved.
+ if entry == "BUILD":
+ continue
+ os.remove(os.path.join(root, entry))
+ for entry in dirs:
+ shutil.rmtree(os.path.join(root, entry))
src_dir = os.path.normpath(os.path.join(original_dir, src_rel_dir))
src_dir_len = len(src_dir) + 1
diff --git a/libc/kernel/uapi/BUILD b/libc/kernel/uapi/BUILD
new file mode 100644
index 0000000..3c9bb69
--- /dev/null
+++ b/libc/kernel/uapi/BUILD
@@ -0,0 +1,67 @@
+# Copyright (C) 2022 The Android Open Source Project
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+load("//build/bazel/rules/apis:cc_api_contribution.bzl", "cc_api_headers")
+
+package(default_visibility = ["//bionic/libc:__pkg__"])
+
+cc_api_headers(
+ name = "libc_kernel_uapi_headers",
+ hdrs = glob(["**/*.h"]),
+ system = True,
+)
+
+cc_api_headers(
+ name = "libc_kernel_uapi_asm_arm_headers",
+ hdrs = glob(["asm-arm/**/*.h"]),
+ arch = "arm",
+ include_dir = "asm-arm",
+ system = True,
+)
+
+cc_api_headers(
+ name = "libc_kernel_uapi_asm_arm64_headers",
+ hdrs = glob(["asm-arm64/**/*.h"]),
+ arch = "arm64",
+ include_dir = "asm-arm64",
+ system = True,
+)
+
+cc_api_headers(
+ name = "libc_kernel_uapi_asm_x86_headers",
+ hdrs = glob(["asm-x86/**/*.h"]),
+ arch = "x86",
+ include_dir = "asm-x86",
+ system = True,
+)
+
+cc_api_headers(
+ name = "libc_kernel_uapi_asm_x86_64_headers",
+ hdrs = glob(["asm-x86_64/**/*.h"]),
+ arch = "x86_64",
+ include_dir = "asm-x86_64",
+ system = True,
+)
diff --git a/libc/kernel/uapi/asm-arm/asm/signal.h b/libc/kernel/uapi/asm-arm/asm/signal.h
index 5f7e0c5..0424380 100644
--- a/libc/kernel/uapi/asm-arm/asm/signal.h
+++ b/libc/kernel/uapi/asm-arm/asm/signal.h
@@ -78,6 +78,6 @@
typedef struct sigaltstack {
void __user * ss_sp;
int ss_flags;
- size_t ss_size;
+ __kernel_size_t ss_size;
} stack_t;
#endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/hwcap.h b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
index 4316724..95d21aa 100644
--- a/libc/kernel/uapi/asm-arm64/asm/hwcap.h
+++ b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
@@ -72,4 +72,14 @@
#define HWCAP2_ECV (1 << 19)
#define HWCAP2_AFP (1 << 20)
#define HWCAP2_RPRES (1 << 21)
+#define HWCAP2_MTE3 (1 << 22)
+#define HWCAP2_SME (1 << 23)
+#define HWCAP2_SME_I16I64 (1 << 24)
+#define HWCAP2_SME_F64F64 (1 << 25)
+#define HWCAP2_SME_I8I32 (1 << 26)
+#define HWCAP2_SME_F16F32 (1 << 27)
+#define HWCAP2_SME_B16F32 (1 << 28)
+#define HWCAP2_SME_F32F32 (1 << 29)
+#define HWCAP2_SME_FA64 (1 << 30)
+#define HWCAP2_WFXT (1UL << 31)
#endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/kvm.h b/libc/kernel/uapi/asm-arm64/asm/kvm.h
index c53ee87..1f57fca 100644
--- a/libc/kernel/uapi/asm-arm64/asm/kvm.h
+++ b/libc/kernel/uapi/asm-arm64/asm/kvm.h
@@ -88,8 +88,10 @@
__u64 dbg_wcr[KVM_ARM_MAX_DBG_REGS];
__u64 dbg_wvr[KVM_ARM_MAX_DBG_REGS];
};
+#define KVM_DEBUG_ARCH_HSR_HIGH_VALID (1 << 0)
struct kvm_debug_exit_arch {
__u32 hsr;
+ __u32 hsr_high;
__u64 far;
};
#define KVM_GUESTDBG_USE_SW_BP (1 << 16)
@@ -185,6 +187,21 @@
#define KVM_ARM64_SVE_VQ_MAX __SVE_VQ_MAX
#define KVM_REG_ARM64_SVE_VLS (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | KVM_REG_SIZE_U512 | 0xffff)
#define KVM_ARM64_SVE_VLS_WORDS ((KVM_ARM64_SVE_VQ_MAX - KVM_ARM64_SVE_VQ_MIN) / 64 + 1)
+#define KVM_REG_ARM_FW_FEAT_BMAP (0x0016 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_FW_FEAT_BMAP_REG(r) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_FW_FEAT_BMAP | ((r) & 0xffff))
+#define KVM_REG_ARM_STD_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(0)
+enum {
+ KVM_REG_ARM_STD_BIT_TRNG_V1_0 = 0,
+};
+#define KVM_REG_ARM_STD_HYP_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(1)
+enum {
+ KVM_REG_ARM_STD_HYP_BIT_PV_TIME = 0,
+};
+#define KVM_REG_ARM_VENDOR_HYP_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(2)
+enum {
+ KVM_REG_ARM_VENDOR_HYP_BIT_FUNC_FEAT = 0,
+ KVM_REG_ARM_VENDOR_HYP_BIT_PTP = 1,
+};
#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
@@ -214,6 +231,7 @@
#define KVM_ARM_VCPU_PMU_V3_IRQ 0
#define KVM_ARM_VCPU_PMU_V3_INIT 1
#define KVM_ARM_VCPU_PMU_V3_FILTER 2
+#define KVM_ARM_VCPU_PMU_V3_SET_PMU 3
#define KVM_ARM_VCPU_TIMER_CTRL 1
#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
@@ -244,5 +262,7 @@
#define KVM_PSCI_RET_NI PSCI_RET_NOT_SUPPORTED
#define KVM_PSCI_RET_INVAL PSCI_RET_INVALID_PARAMS
#define KVM_PSCI_RET_DENIED PSCI_RET_DENIED
+#define KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2 (1ULL << 0)
+#define KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED (1ULL << 0)
#endif
#endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/ptrace.h b/libc/kernel/uapi/asm-arm64/asm/ptrace.h
index 480efcf..9540c3e 100644
--- a/libc/kernel/uapi/asm-arm64/asm/ptrace.h
+++ b/libc/kernel/uapi/asm-arm64/asm/ptrace.h
@@ -111,7 +111,7 @@
#define SVE_PT_SVE_FPSR_OFFSET(vq) ((SVE_PT_SVE_FFR_OFFSET(vq) + SVE_PT_SVE_FFR_SIZE(vq) + (__SVE_VQ_BYTES - 1)) / __SVE_VQ_BYTES * __SVE_VQ_BYTES)
#define SVE_PT_SVE_FPCR_OFFSET(vq) (SVE_PT_SVE_FPSR_OFFSET(vq) + SVE_PT_SVE_FPSR_SIZE)
#define SVE_PT_SVE_SIZE(vq,flags) ((SVE_PT_SVE_FPCR_OFFSET(vq) + SVE_PT_SVE_FPCR_SIZE - SVE_PT_SVE_OFFSET + (__SVE_VQ_BYTES - 1)) / __SVE_VQ_BYTES * __SVE_VQ_BYTES)
-#define SVE_PT_SIZE(vq,flags) (((flags) & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE ? SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags) : SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags))
+#define SVE_PT_SIZE(vq,flags) (((flags) & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE ? SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags) : ((((flags) & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD ? SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags) : SVE_PT_REGS_OFFSET)))
struct user_pac_mask {
__u64 data_mask;
__u64 insn_mask;
@@ -125,5 +125,19 @@
struct user_pac_generic_keys {
__uint128_t apgakey;
};
+struct user_za_header {
+ __u32 size;
+ __u32 max_size;
+ __u16 vl;
+ __u16 max_vl;
+ __u16 flags;
+ __u16 __reserved;
+};
+#define ZA_PT_VL_INHERIT ((1 << 17) >> 16)
+#define ZA_PT_VL_ONEXEC ((1 << 18) >> 16)
+#define ZA_PT_ZA_OFFSET ((sizeof(struct user_za_header) + (__SVE_VQ_BYTES - 1)) / __SVE_VQ_BYTES * __SVE_VQ_BYTES)
+#define ZA_PT_ZAV_OFFSET(vq,n) (ZA_PT_ZA_OFFSET + ((vq * __SVE_VQ_BYTES) * n))
+#define ZA_PT_ZA_SIZE(vq) ((vq * __SVE_VQ_BYTES) * (vq * __SVE_VQ_BYTES))
+#define ZA_PT_SIZE(vq) (ZA_PT_ZA_OFFSET + ZA_PT_ZA_SIZE(vq))
#endif
#endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/sigcontext.h b/libc/kernel/uapi/asm-arm64/asm/sigcontext.h
index 518079d..04aa593 100644
--- a/libc/kernel/uapi/asm-arm64/asm/sigcontext.h
+++ b/libc/kernel/uapi/asm-arm64/asm/sigcontext.h
@@ -55,6 +55,14 @@
struct sve_context {
struct _aarch64_ctx head;
__u16 vl;
+ __u16 flags;
+ __u16 __reserved[2];
+};
+#define SVE_SIG_FLAG_SM 0x1
+#define ZA_MAGIC 0x54366345
+struct za_context {
+ struct _aarch64_ctx head;
+ __u16 vl;
__u16 __reserved[3];
};
#endif
@@ -82,4 +90,8 @@
#define SVE_SIG_FFR_OFFSET(vq) (SVE_SIG_REGS_OFFSET + __SVE_FFR_OFFSET(vq))
#define SVE_SIG_REGS_SIZE(vq) (__SVE_FFR_OFFSET(vq) + __SVE_FFR_SIZE(vq))
#define SVE_SIG_CONTEXT_SIZE(vq) (SVE_SIG_REGS_OFFSET + SVE_SIG_REGS_SIZE(vq))
+#define ZA_SIG_REGS_OFFSET ((sizeof(struct za_context) + (__SVE_VQ_BYTES - 1)) / __SVE_VQ_BYTES * __SVE_VQ_BYTES)
+#define ZA_SIG_REGS_SIZE(vq) ((vq * __SVE_VQ_BYTES) * (vq * __SVE_VQ_BYTES))
+#define ZA_SIG_ZAV_OFFSET(vq,n) (ZA_SIG_REGS_OFFSET + (SVE_SIG_ZREG_SIZE(vq) * n))
+#define ZA_SIG_CONTEXT_SIZE(vq) (ZA_SIG_REGS_OFFSET + ZA_SIG_REGS_SIZE(vq))
#endif
diff --git a/libc/kernel/uapi/asm-generic/fcntl.h b/libc/kernel/uapi/asm-generic/fcntl.h
index a2cb5f4..ea8c108 100644
--- a/libc/kernel/uapi/asm-generic/fcntl.h
+++ b/libc/kernel/uapi/asm-generic/fcntl.h
@@ -100,7 +100,7 @@
#define F_SETSIG 10
#define F_GETSIG 11
#endif
-#ifndef __LP64__
+#if __BITS_PER_LONG == 32
#ifndef F_GETLK64
#define F_GETLK64 12
#define F_SETLK64 13
@@ -144,13 +144,5 @@
#define LOCK_RW 192
#define F_LINUX_SPECIFIC_BASE 1024
#ifndef HAVE_ARCH_STRUCT_FLOCK
-#ifndef __ARCH_FLOCK_PAD
-#define __ARCH_FLOCK_PAD
-#endif
-#endif
-#ifndef HAVE_ARCH_STRUCT_FLOCK64
-#ifndef __ARCH_FLOCK64_PAD
-#define __ARCH_FLOCK64_PAD
-#endif
#endif
#endif
diff --git a/libc/kernel/uapi/asm-generic/mman-common.h b/libc/kernel/uapi/asm-generic/mman-common.h
index 9440576..e96f4cc 100644
--- a/libc/kernel/uapi/asm-generic/mman-common.h
+++ b/libc/kernel/uapi/asm-generic/mman-common.h
@@ -62,6 +62,7 @@
#define MADV_PAGEOUT 21
#define MADV_POPULATE_READ 22
#define MADV_POPULATE_WRITE 23
+#define MADV_DONTNEED_LOCKED 24
#define MAP_FILE 0
#define PKEY_DISABLE_ACCESS 0x1
#define PKEY_DISABLE_WRITE 0x2
diff --git a/libc/kernel/uapi/asm-generic/shmbuf.h b/libc/kernel/uapi/asm-generic/shmbuf.h
index 067ffbc..11487f4 100644
--- a/libc/kernel/uapi/asm-generic/shmbuf.h
+++ b/libc/kernel/uapi/asm-generic/shmbuf.h
@@ -19,9 +19,11 @@
#ifndef __ASM_GENERIC_SHMBUF_H
#define __ASM_GENERIC_SHMBUF_H
#include <asm/bitsperlong.h>
+#include <asm/ipcbuf.h>
+#include <asm/posix_types.h>
struct shmid64_ds {
struct ipc64_perm shm_perm;
- size_t shm_segsz;
+ __kernel_size_t shm_segsz;
#if __BITS_PER_LONG == 64
long shm_atime;
long shm_dtime;
diff --git a/libc/kernel/uapi/asm-generic/siginfo.h b/libc/kernel/uapi/asm-generic/siginfo.h
index f9199e5..c5e4178 100644
--- a/libc/kernel/uapi/asm-generic/siginfo.h
+++ b/libc/kernel/uapi/asm-generic/siginfo.h
@@ -80,6 +80,7 @@
struct {
unsigned long _data;
__u32 _type;
+ __u32 _flags;
} _perf;
};
} _sigfault;
@@ -125,6 +126,7 @@
#define si_pkey _sifields._sigfault._addr_pkey._pkey
#define si_perf_data _sifields._sigfault._perf._data
#define si_perf_type _sifields._sigfault._perf._type
+#define si_perf_flags _sifields._sigfault._perf._flags
#define si_band _sifields._sigpoll._band
#define si_fd _sifields._sigpoll._fd
#define si_call_addr _sifields._sigsys._call_addr
@@ -197,6 +199,7 @@
#define TRAP_UNK 5
#define TRAP_PERF 6
#define NSIGTRAP 6
+#define TRAP_PERF_FLAG_ASYNC (1u << 0)
#define CLD_EXITED 1
#define CLD_KILLED 2
#define CLD_DUMPED 3
diff --git a/libc/kernel/uapi/asm-generic/signal.h b/libc/kernel/uapi/asm-generic/signal.h
index 874fece..5cb1dce 100644
--- a/libc/kernel/uapi/asm-generic/signal.h
+++ b/libc/kernel/uapi/asm-generic/signal.h
@@ -84,7 +84,7 @@
typedef struct sigaltstack {
void __user * ss_sp;
int ss_flags;
- size_t ss_size;
+ __kernel_size_t ss_size;
} stack_t;
#endif
#endif
diff --git a/libc/kernel/uapi/asm-generic/socket.h b/libc/kernel/uapi/asm-generic/socket.h
index 6767993..1a321bf 100644
--- a/libc/kernel/uapi/asm-generic/socket.h
+++ b/libc/kernel/uapi/asm-generic/socket.h
@@ -100,6 +100,8 @@
#define SO_NETNS_COOKIE 71
#define SO_BUF_LOCK 72
#define SO_RESERVE_MEM 73
+#define SO_TXREHASH 74
+#define SO_RCVMARK 75
#if __BITS_PER_LONG == 64 || defined(__x86_64__) && defined(__ILP32__)
#define SO_TIMESTAMP SO_TIMESTAMP_OLD
#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
diff --git a/libc/kernel/uapi/asm-generic/termbits-common.h b/libc/kernel/uapi/asm-generic/termbits-common.h
new file mode 100644
index 0000000..c67f21d
--- /dev/null
+++ b/libc/kernel/uapi/asm-generic/termbits-common.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __ASM_GENERIC_TERMBITS_COMMON_H
+#define __ASM_GENERIC_TERMBITS_COMMON_H
+typedef unsigned char cc_t;
+typedef unsigned int speed_t;
+#define IGNBRK 0x001
+#define BRKINT 0x002
+#define IGNPAR 0x004
+#define PARMRK 0x008
+#define INPCK 0x010
+#define ISTRIP 0x020
+#define INLCR 0x040
+#define IGNCR 0x080
+#define ICRNL 0x100
+#define IXANY 0x800
+#define OPOST 0x01
+#define OCRNL 0x08
+#define ONOCR 0x10
+#define ONLRET 0x20
+#define OFILL 0x40
+#define OFDEL 0x80
+#define B0 0x00000000
+#define B50 0x00000001
+#define B75 0x00000002
+#define B110 0x00000003
+#define B134 0x00000004
+#define B150 0x00000005
+#define B200 0x00000006
+#define B300 0x00000007
+#define B600 0x00000008
+#define B1200 0x00000009
+#define B1800 0x0000000a
+#define B2400 0x0000000b
+#define B4800 0x0000000c
+#define B9600 0x0000000d
+#define B19200 0x0000000e
+#define B38400 0x0000000f
+#define EXTA B19200
+#define EXTB B38400
+#define CMSPAR 0x40000000
+#define CRTSCTS 0x80000000
+#define IBSHIFT 16
+#define TCOOFF 0
+#define TCOON 1
+#define TCIOFF 2
+#define TCION 3
+#define TCIFLUSH 0
+#define TCOFLUSH 1
+#define TCIOFLUSH 2
+#endif
diff --git a/libc/kernel/uapi/asm-generic/termbits.h b/libc/kernel/uapi/asm-generic/termbits.h
index b592964..87d6c82 100644
--- a/libc/kernel/uapi/asm-generic/termbits.h
+++ b/libc/kernel/uapi/asm-generic/termbits.h
@@ -18,9 +18,7 @@
****************************************************************************/
#ifndef __ASM_GENERIC_TERMBITS_H
#define __ASM_GENERIC_TERMBITS_H
-#include <linux/posix_types.h>
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
+#include <asm-generic/termbits-common.h>
typedef unsigned int tcflag_t;
#define NCCS 19
struct termios {
@@ -68,126 +66,82 @@
#define VWERASE 14
#define VLNEXT 15
#define VEOL2 16
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK 0000020
-#define ISTRIP 0000040
-#define INLCR 0000100
-#define IGNCR 0000200
-#define ICRNL 0000400
-#define IUCLC 0001000
-#define IXON 0002000
-#define IXANY 0004000
-#define IXOFF 0010000
-#define IMAXBEL 0020000
-#define IUTF8 0040000
-#define OPOST 0000001
-#define OLCUC 0000002
-#define ONLCR 0000004
-#define OCRNL 0000010
-#define ONOCR 0000020
-#define ONLRET 0000040
-#define OFILL 0000100
-#define OFDEL 0000200
-#define NLDLY 0000400
-#define NL0 0000000
-#define NL1 0000400
-#define CRDLY 0003000
-#define CR0 0000000
-#define CR1 0001000
-#define CR2 0002000
-#define CR3 0003000
-#define TABDLY 0014000
-#define TAB0 0000000
-#define TAB1 0004000
-#define TAB2 0010000
-#define TAB3 0014000
-#define XTABS 0014000
-#define BSDLY 0020000
-#define BS0 0000000
-#define BS1 0020000
-#define VTDLY 0040000
-#define VT0 0000000
-#define VT1 0040000
-#define FFDLY 0100000
-#define FF0 0000000
-#define FF1 0100000
-#define CBAUD 0010017
-#define B0 0000000
-#define B50 0000001
-#define B75 0000002
-#define B110 0000003
-#define B134 0000004
-#define B150 0000005
-#define B200 0000006
-#define B300 0000007
-#define B600 0000010
-#define B1200 0000011
-#define B1800 0000012
-#define B2400 0000013
-#define B4800 0000014
-#define B9600 0000015
-#define B19200 0000016
-#define B38400 0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE 0000060
-#define CS5 0000000
-#define CS6 0000020
-#define CS7 0000040
-#define CS8 0000060
-#define CSTOPB 0000100
-#define CREAD 0000200
-#define PARENB 0000400
-#define PARODD 0001000
-#define HUPCL 0002000
-#define CLOCAL 0004000
-#define CBAUDEX 0010000
-#define BOTHER 0010000
-#define B57600 0010001
-#define B115200 0010002
-#define B230400 0010003
-#define B460800 0010004
-#define B500000 0010005
-#define B576000 0010006
-#define B921600 0010007
-#define B1000000 0010010
-#define B1152000 0010011
-#define B1500000 0010012
-#define B2000000 0010013
-#define B2500000 0010014
-#define B3000000 0010015
-#define B3500000 0010016
-#define B4000000 0010017
-#define CIBAUD 002003600000
-#define CMSPAR 010000000000
-#define CRTSCTS 020000000000
-#define IBSHIFT 16
-#define ISIG 0000001
-#define ICANON 0000002
-#define XCASE 0000004
-#define ECHO 0000010
-#define ECHOE 0000020
-#define ECHOK 0000040
-#define ECHONL 0000100
-#define NOFLSH 0000200
-#define TOSTOP 0000400
-#define ECHOCTL 0001000
-#define ECHOPRT 0002000
-#define ECHOKE 0004000
-#define FLUSHO 0010000
-#define PENDIN 0040000
-#define IEXTEN 0100000
-#define EXTPROC 0200000
-#define TCOOFF 0
-#define TCOON 1
-#define TCIOFF 2
-#define TCION 3
-#define TCIFLUSH 0
-#define TCOFLUSH 1
-#define TCIOFLUSH 2
+#define IUCLC 0x0200
+#define IXON 0x0400
+#define IXOFF 0x1000
+#define IMAXBEL 0x2000
+#define IUTF8 0x4000
+#define OLCUC 0x00002
+#define ONLCR 0x00004
+#define NLDLY 0x00100
+#define NL0 0x00000
+#define NL1 0x00100
+#define CRDLY 0x00600
+#define CR0 0x00000
+#define CR1 0x00200
+#define CR2 0x00400
+#define CR3 0x00600
+#define TABDLY 0x01800
+#define TAB0 0x00000
+#define TAB1 0x00800
+#define TAB2 0x01000
+#define TAB3 0x01800
+#define XTABS 0x01800
+#define BSDLY 0x02000
+#define BS0 0x00000
+#define BS1 0x02000
+#define VTDLY 0x04000
+#define VT0 0x00000
+#define VT1 0x04000
+#define FFDLY 0x08000
+#define FF0 0x00000
+#define FF1 0x08000
+#define CBAUD 0x0000100f
+#define CSIZE 0x00000030
+#define CS5 0x00000000
+#define CS6 0x00000010
+#define CS7 0x00000020
+#define CS8 0x00000030
+#define CSTOPB 0x00000040
+#define CREAD 0x00000080
+#define PARENB 0x00000100
+#define PARODD 0x00000200
+#define HUPCL 0x00000400
+#define CLOCAL 0x00000800
+#define CBAUDEX 0x00001000
+#define BOTHER 0x00001000
+#define B57600 0x00001001
+#define B115200 0x00001002
+#define B230400 0x00001003
+#define B460800 0x00001004
+#define B500000 0x00001005
+#define B576000 0x00001006
+#define B921600 0x00001007
+#define B1000000 0x00001008
+#define B1152000 0x00001009
+#define B1500000 0x0000100a
+#define B2000000 0x0000100b
+#define B2500000 0x0000100c
+#define B3000000 0x0000100d
+#define B3500000 0x0000100e
+#define B4000000 0x0000100f
+#define CIBAUD 0x100f0000
+#define ISIG 0x00001
+#define ICANON 0x00002
+#define XCASE 0x00004
+#define ECHO 0x00008
+#define ECHOE 0x00010
+#define ECHOK 0x00020
+#define ECHONL 0x00040
+#define NOFLSH 0x00080
+#define TOSTOP 0x00100
+#define ECHOCTL 0x00200
+#define ECHOPRT 0x00400
+#define ECHOKE 0x00800
+#define FLUSHO 0x01000
+#define PENDIN 0x04000
+#define IEXTEN 0x08000
+#define EXTPROC 0x10000
#define TCSANOW 0
#define TCSADRAIN 1
#define TCSAFLUSH 2
diff --git a/libc/kernel/uapi/asm-generic/unistd.h b/libc/kernel/uapi/asm-generic/unistd.h
index 4b9f174..d23958b 100644
--- a/libc/kernel/uapi/asm-generic/unistd.h
+++ b/libc/kernel/uapi/asm-generic/unistd.h
@@ -360,7 +360,7 @@
#endif
#define __NR_rseq 293
#define __NR_kexec_file_load 294
-#if __BITS_PER_LONG == 32
+#if defined(__SYSCALL_COMPAT) || __BITS_PER_LONG == 32
#define __NR_clock_gettime64 403
#define __NR_clock_settime64 404
#define __NR_clock_adjtime64 405
diff --git a/libc/kernel/uapi/asm-riscv/asm/auxvec.h b/libc/kernel/uapi/asm-riscv/asm/auxvec.h
new file mode 100644
index 0000000..b0e22af
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/auxvec.h
@@ -0,0 +1,29 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_ASM_RISCV_AUXVEC_H
+#define _UAPI_ASM_RISCV_AUXVEC_H
+#define AT_SYSINFO_EHDR 33
+#define AT_L1I_CACHESIZE 40
+#define AT_L1I_CACHEGEOMETRY 41
+#define AT_L1D_CACHESIZE 42
+#define AT_L1D_CACHEGEOMETRY 43
+#define AT_L2_CACHESIZE 44
+#define AT_L2_CACHEGEOMETRY 45
+#define AT_VECTOR_SIZE_ARCH 7
+#endif
diff --git a/libc/kernel/uapi/asm-riscv/asm/bitsperlong.h b/libc/kernel/uapi/asm-riscv/asm/bitsperlong.h
new file mode 100644
index 0000000..098b610
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/bitsperlong.h
@@ -0,0 +1,23 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_ASM_RISCV_BITSPERLONG_H
+#define _UAPI_ASM_RISCV_BITSPERLONG_H
+#define __BITS_PER_LONG (__SIZEOF_POINTER__ * 8)
+#include <asm-generic/bitsperlong.h>
+#endif
diff --git a/libc/kernel/uapi/asm-riscv/asm/bpf_perf_event.h b/libc/kernel/uapi/asm-riscv/asm/bpf_perf_event.h
new file mode 100644
index 0000000..47c09fd
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/bpf_perf_event.h
@@ -0,0 +1,23 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
+#define _UAPI__ASM_BPF_PERF_EVENT_H__
+#include <asm/ptrace.h>
+typedef struct user_regs_struct bpf_user_pt_regs_t;
+#endif
diff --git a/libc/kernel/uapi/asm-riscv/asm/byteorder.h b/libc/kernel/uapi/asm-riscv/asm/byteorder.h
new file mode 100644
index 0000000..42afc14
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/byteorder.h
@@ -0,0 +1,22 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_ASM_RISCV_BYTEORDER_H
+#define _UAPI_ASM_RISCV_BYTEORDER_H
+#include <linux/byteorder/little_endian.h>
+#endif
diff --git a/libc/kernel/uapi/asm-riscv/asm/elf.h b/libc/kernel/uapi/asm-riscv/asm/elf.h
new file mode 100644
index 0000000..07593d9
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/elf.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_ASM_RISCV_ELF_H
+#define _UAPI_ASM_RISCV_ELF_H
+#include <asm/ptrace.h>
+typedef unsigned long elf_greg_t;
+typedef struct user_regs_struct elf_gregset_t;
+#define ELF_NGREG (sizeof(elf_gregset_t) / sizeof(elf_greg_t))
+typedef __u64 elf_fpreg_t;
+typedef union __riscv_fp_state elf_fpregset_t;
+#define ELF_NFPREG (sizeof(struct __riscv_d_ext_state) / sizeof(elf_fpreg_t))
+#if __riscv_xlen == 64
+#define ELF_RISCV_R_SYM(r_info) ELF64_R_SYM(r_info)
+#define ELF_RISCV_R_TYPE(r_info) ELF64_R_TYPE(r_info)
+#else
+#define ELF_RISCV_R_SYM(r_info) ELF32_R_SYM(r_info)
+#define ELF_RISCV_R_TYPE(r_info) ELF32_R_TYPE(r_info)
+#endif
+#define R_RISCV_NONE 0
+#define R_RISCV_32 1
+#define R_RISCV_64 2
+#define R_RISCV_RELATIVE 3
+#define R_RISCV_COPY 4
+#define R_RISCV_JUMP_SLOT 5
+#define R_RISCV_TLS_DTPMOD32 6
+#define R_RISCV_TLS_DTPMOD64 7
+#define R_RISCV_TLS_DTPREL32 8
+#define R_RISCV_TLS_DTPREL64 9
+#define R_RISCV_TLS_TPREL32 10
+#define R_RISCV_TLS_TPREL64 11
+#define R_RISCV_BRANCH 16
+#define R_RISCV_JAL 17
+#define R_RISCV_CALL 18
+#define R_RISCV_CALL_PLT 19
+#define R_RISCV_GOT_HI20 20
+#define R_RISCV_TLS_GOT_HI20 21
+#define R_RISCV_TLS_GD_HI20 22
+#define R_RISCV_PCREL_HI20 23
+#define R_RISCV_PCREL_LO12_I 24
+#define R_RISCV_PCREL_LO12_S 25
+#define R_RISCV_HI20 26
+#define R_RISCV_LO12_I 27
+#define R_RISCV_LO12_S 28
+#define R_RISCV_TPREL_HI20 29
+#define R_RISCV_TPREL_LO12_I 30
+#define R_RISCV_TPREL_LO12_S 31
+#define R_RISCV_TPREL_ADD 32
+#define R_RISCV_ADD8 33
+#define R_RISCV_ADD16 34
+#define R_RISCV_ADD32 35
+#define R_RISCV_ADD64 36
+#define R_RISCV_SUB8 37
+#define R_RISCV_SUB16 38
+#define R_RISCV_SUB32 39
+#define R_RISCV_SUB64 40
+#define R_RISCV_GNU_VTINHERIT 41
+#define R_RISCV_GNU_VTENTRY 42
+#define R_RISCV_ALIGN 43
+#define R_RISCV_RVC_BRANCH 44
+#define R_RISCV_RVC_JUMP 45
+#define R_RISCV_LUI 46
+#define R_RISCV_GPREL_I 47
+#define R_RISCV_GPREL_S 48
+#define R_RISCV_TPREL_I 49
+#define R_RISCV_TPREL_S 50
+#define R_RISCV_RELAX 51
+#define R_RISCV_SUB6 52
+#define R_RISCV_SET6 53
+#define R_RISCV_SET8 54
+#define R_RISCV_SET16 55
+#define R_RISCV_SET32 56
+#define R_RISCV_32_PCREL 57
+#endif
diff --git a/libc/kernel/uapi/asm-riscv/asm/errno.h b/libc/kernel/uapi/asm-riscv/asm/errno.h
new file mode 100644
index 0000000..392cd94
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/errno.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/errno.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/fcntl.h b/libc/kernel/uapi/asm-riscv/asm/fcntl.h
new file mode 100644
index 0000000..518d3a7
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/fcntl.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/fcntl.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/hwcap.h b/libc/kernel/uapi/asm-riscv/asm/hwcap.h
new file mode 100644
index 0000000..d130cf7
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/hwcap.h
@@ -0,0 +1,27 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_ASM_RISCV_HWCAP_H
+#define _UAPI_ASM_RISCV_HWCAP_H
+#define COMPAT_HWCAP_ISA_I (1 << ('I' - 'A'))
+#define COMPAT_HWCAP_ISA_M (1 << ('M' - 'A'))
+#define COMPAT_HWCAP_ISA_A (1 << ('A' - 'A'))
+#define COMPAT_HWCAP_ISA_F (1 << ('F' - 'A'))
+#define COMPAT_HWCAP_ISA_D (1 << ('D' - 'A'))
+#define COMPAT_HWCAP_ISA_C (1 << ('C' - 'A'))
+#endif
diff --git a/libc/kernel/uapi/asm-riscv/asm/ioctl.h b/libc/kernel/uapi/asm-riscv/asm/ioctl.h
new file mode 100644
index 0000000..7b7bd37
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/ioctl.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/ioctl.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/ioctls.h b/libc/kernel/uapi/asm-riscv/asm/ioctls.h
new file mode 100644
index 0000000..0c66935
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/ioctls.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/ioctls.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/ipcbuf.h b/libc/kernel/uapi/asm-riscv/asm/ipcbuf.h
new file mode 100644
index 0000000..0021f14
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/ipcbuf.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/ipcbuf.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/kvm.h b/libc/kernel/uapi/asm-riscv/asm/kvm.h
new file mode 100644
index 0000000..8cb1cee
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/kvm.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __LINUX_KVM_RISCV_H
+#define __LINUX_KVM_RISCV_H
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#include <asm/ptrace.h>
+#define __KVM_HAVE_READONLY_MEM
+#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+#define KVM_INTERRUPT_SET - 1U
+#define KVM_INTERRUPT_UNSET - 2U
+struct kvm_regs {
+};
+struct kvm_fpu {
+};
+struct kvm_debug_exit_arch {
+};
+struct kvm_guest_debug_arch {
+};
+struct kvm_sync_regs {
+};
+struct kvm_sregs {
+};
+struct kvm_riscv_config {
+ unsigned long isa;
+};
+struct kvm_riscv_core {
+ struct user_regs_struct regs;
+ unsigned long mode;
+};
+#define KVM_RISCV_MODE_S 1
+#define KVM_RISCV_MODE_U 0
+struct kvm_riscv_csr {
+ unsigned long sstatus;
+ unsigned long sie;
+ unsigned long stvec;
+ unsigned long sscratch;
+ unsigned long sepc;
+ unsigned long scause;
+ unsigned long stval;
+ unsigned long sip;
+ unsigned long satp;
+ unsigned long scounteren;
+};
+struct kvm_riscv_timer {
+ __u64 frequency;
+ __u64 time;
+ __u64 compare;
+ __u64 state;
+};
+enum KVM_RISCV_ISA_EXT_ID {
+ KVM_RISCV_ISA_EXT_A = 0,
+ KVM_RISCV_ISA_EXT_C,
+ KVM_RISCV_ISA_EXT_D,
+ KVM_RISCV_ISA_EXT_F,
+ KVM_RISCV_ISA_EXT_H,
+ KVM_RISCV_ISA_EXT_I,
+ KVM_RISCV_ISA_EXT_M,
+ KVM_RISCV_ISA_EXT_MAX,
+};
+#define KVM_RISCV_TIMER_STATE_OFF 0
+#define KVM_RISCV_TIMER_STATE_ON 1
+#define KVM_REG_SIZE(id) (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
+#define KVM_REG_RISCV_TYPE_MASK 0x00000000FF000000
+#define KVM_REG_RISCV_TYPE_SHIFT 24
+#define KVM_REG_RISCV_CONFIG (0x01 << KVM_REG_RISCV_TYPE_SHIFT)
+#define KVM_REG_RISCV_CONFIG_REG(name) (offsetof(struct kvm_riscv_config, name) / sizeof(unsigned long))
+#define KVM_REG_RISCV_CORE (0x02 << KVM_REG_RISCV_TYPE_SHIFT)
+#define KVM_REG_RISCV_CORE_REG(name) (offsetof(struct kvm_riscv_core, name) / sizeof(unsigned long))
+#define KVM_REG_RISCV_CSR (0x03 << KVM_REG_RISCV_TYPE_SHIFT)
+#define KVM_REG_RISCV_CSR_REG(name) (offsetof(struct kvm_riscv_csr, name) / sizeof(unsigned long))
+#define KVM_REG_RISCV_TIMER (0x04 << KVM_REG_RISCV_TYPE_SHIFT)
+#define KVM_REG_RISCV_TIMER_REG(name) (offsetof(struct kvm_riscv_timer, name) / sizeof(__u64))
+#define KVM_REG_RISCV_FP_F (0x05 << KVM_REG_RISCV_TYPE_SHIFT)
+#define KVM_REG_RISCV_FP_F_REG(name) (offsetof(struct __riscv_f_ext_state, name) / sizeof(__u32))
+#define KVM_REG_RISCV_FP_D (0x06 << KVM_REG_RISCV_TYPE_SHIFT)
+#define KVM_REG_RISCV_FP_D_REG(name) (offsetof(struct __riscv_d_ext_state, name) / sizeof(__u64))
+#define KVM_REG_RISCV_ISA_EXT (0x07 << KVM_REG_RISCV_TYPE_SHIFT)
+#endif
+#endif
diff --git a/libc/kernel/uapi/asm-riscv/asm/mman.h b/libc/kernel/uapi/asm-riscv/asm/mman.h
new file mode 100644
index 0000000..6c23fb6
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/mman.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/mman.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/msgbuf.h b/libc/kernel/uapi/asm-riscv/asm/msgbuf.h
new file mode 100644
index 0000000..7809e3c
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/msgbuf.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/msgbuf.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/param.h b/libc/kernel/uapi/asm-riscv/asm/param.h
new file mode 100644
index 0000000..5ccf935
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/param.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/param.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/perf_regs.h b/libc/kernel/uapi/asm-riscv/asm/perf_regs.h
new file mode 100644
index 0000000..ceb0bbe
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/perf_regs.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _ASM_RISCV_PERF_REGS_H
+#define _ASM_RISCV_PERF_REGS_H
+enum perf_event_riscv_regs {
+ PERF_REG_RISCV_PC,
+ PERF_REG_RISCV_RA,
+ PERF_REG_RISCV_SP,
+ PERF_REG_RISCV_GP,
+ PERF_REG_RISCV_TP,
+ PERF_REG_RISCV_T0,
+ PERF_REG_RISCV_T1,
+ PERF_REG_RISCV_T2,
+ PERF_REG_RISCV_S0,
+ PERF_REG_RISCV_S1,
+ PERF_REG_RISCV_A0,
+ PERF_REG_RISCV_A1,
+ PERF_REG_RISCV_A2,
+ PERF_REG_RISCV_A3,
+ PERF_REG_RISCV_A4,
+ PERF_REG_RISCV_A5,
+ PERF_REG_RISCV_A6,
+ PERF_REG_RISCV_A7,
+ PERF_REG_RISCV_S2,
+ PERF_REG_RISCV_S3,
+ PERF_REG_RISCV_S4,
+ PERF_REG_RISCV_S5,
+ PERF_REG_RISCV_S6,
+ PERF_REG_RISCV_S7,
+ PERF_REG_RISCV_S8,
+ PERF_REG_RISCV_S9,
+ PERF_REG_RISCV_S10,
+ PERF_REG_RISCV_S11,
+ PERF_REG_RISCV_T3,
+ PERF_REG_RISCV_T4,
+ PERF_REG_RISCV_T5,
+ PERF_REG_RISCV_T6,
+ PERF_REG_RISCV_MAX,
+};
+#endif
diff --git a/libc/kernel/uapi/asm-riscv/asm/poll.h b/libc/kernel/uapi/asm-riscv/asm/poll.h
new file mode 100644
index 0000000..d7e8adc
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/poll.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/poll.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/posix_types.h b/libc/kernel/uapi/asm-riscv/asm/posix_types.h
new file mode 100644
index 0000000..1b89253
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/posix_types.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/posix_types.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/ptrace.h b/libc/kernel/uapi/asm-riscv/asm/ptrace.h
new file mode 100644
index 0000000..94e4ac9
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/ptrace.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_ASM_RISCV_PTRACE_H
+#define _UAPI_ASM_RISCV_PTRACE_H
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+struct user_regs_struct {
+ unsigned long pc;
+ unsigned long ra;
+ unsigned long sp;
+ unsigned long gp;
+ unsigned long tp;
+ unsigned long t0;
+ unsigned long t1;
+ unsigned long t2;
+ unsigned long s0;
+ unsigned long s1;
+ unsigned long a0;
+ unsigned long a1;
+ unsigned long a2;
+ unsigned long a3;
+ unsigned long a4;
+ unsigned long a5;
+ unsigned long a6;
+ unsigned long a7;
+ unsigned long s2;
+ unsigned long s3;
+ unsigned long s4;
+ unsigned long s5;
+ unsigned long s6;
+ unsigned long s7;
+ unsigned long s8;
+ unsigned long s9;
+ unsigned long s10;
+ unsigned long s11;
+ unsigned long t3;
+ unsigned long t4;
+ unsigned long t5;
+ unsigned long t6;
+};
+struct __riscv_f_ext_state {
+ __u32 f[32];
+ __u32 fcsr;
+};
+struct __riscv_d_ext_state {
+ __u64 f[32];
+ __u32 fcsr;
+};
+struct __riscv_q_ext_state {
+ __u64 f[64] __attribute__((aligned(16)));
+ __u32 fcsr;
+ __u32 reserved[3];
+};
+union __riscv_fp_state {
+ struct __riscv_f_ext_state f;
+ struct __riscv_d_ext_state d;
+ struct __riscv_q_ext_state q;
+};
+#endif
+#endif
diff --git a/libc/kernel/uapi/asm-riscv/asm/resource.h b/libc/kernel/uapi/asm-riscv/asm/resource.h
new file mode 100644
index 0000000..371adb5
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/resource.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/resource.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/sembuf.h b/libc/kernel/uapi/asm-riscv/asm/sembuf.h
new file mode 100644
index 0000000..6ce6549
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/sembuf.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/sembuf.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/setup.h b/libc/kernel/uapi/asm-riscv/asm/setup.h
new file mode 100644
index 0000000..940c4db
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/setup.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/setup.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/shmbuf.h b/libc/kernel/uapi/asm-riscv/asm/shmbuf.h
new file mode 100644
index 0000000..fe8b1be
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/shmbuf.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/shmbuf.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/sigcontext.h b/libc/kernel/uapi/asm-riscv/asm/sigcontext.h
new file mode 100644
index 0000000..0553b94
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/sigcontext.h
@@ -0,0 +1,26 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_ASM_RISCV_SIGCONTEXT_H
+#define _UAPI_ASM_RISCV_SIGCONTEXT_H
+#include <asm/ptrace.h>
+struct sigcontext {
+ struct user_regs_struct sc_regs;
+ union __riscv_fp_state sc_fpregs;
+};
+#endif
diff --git a/libc/kernel/uapi/asm-riscv/asm/siginfo.h b/libc/kernel/uapi/asm-riscv/asm/siginfo.h
new file mode 100644
index 0000000..a31ebb2
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/siginfo.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/siginfo.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/signal.h b/libc/kernel/uapi/asm-riscv/asm/signal.h
new file mode 100644
index 0000000..64373fe
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/signal.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/signal.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/socket.h b/libc/kernel/uapi/asm-riscv/asm/socket.h
new file mode 100644
index 0000000..50a9874
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/socket.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/socket.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/sockios.h b/libc/kernel/uapi/asm-riscv/asm/sockios.h
new file mode 100644
index 0000000..710db92
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/sockios.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/sockios.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/stat.h b/libc/kernel/uapi/asm-riscv/asm/stat.h
new file mode 100644
index 0000000..af7ebfc
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/stat.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/stat.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/statfs.h b/libc/kernel/uapi/asm-riscv/asm/statfs.h
new file mode 100644
index 0000000..93de275
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/statfs.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/statfs.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/swab.h b/libc/kernel/uapi/asm-riscv/asm/swab.h
new file mode 100644
index 0000000..0049f53
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/swab.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/swab.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/termbits.h b/libc/kernel/uapi/asm-riscv/asm/termbits.h
new file mode 100644
index 0000000..42af6fe
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/termbits.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/termbits.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/termios.h b/libc/kernel/uapi/asm-riscv/asm/termios.h
new file mode 100644
index 0000000..feca4c6
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/termios.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/termios.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/types.h b/libc/kernel/uapi/asm-riscv/asm/types.h
new file mode 100644
index 0000000..8250f43
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/types.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/types.h>
diff --git a/libc/kernel/uapi/asm-riscv/asm/ucontext.h b/libc/kernel/uapi/asm-riscv/asm/ucontext.h
new file mode 100644
index 0000000..8b72cc1
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/ucontext.h
@@ -0,0 +1,30 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_ASM_RISCV_UCONTEXT_H
+#define _UAPI_ASM_RISCV_UCONTEXT_H
+#include <linux/types.h>
+struct ucontext {
+ unsigned long uc_flags;
+ struct ucontext * uc_link;
+ stack_t uc_stack;
+ sigset_t uc_sigmask;
+ __u8 __linux_unused[1024 / 8 - sizeof(sigset_t)];
+ struct sigcontext uc_mcontext;
+};
+#endif
diff --git a/libc/kernel/uapi/asm-riscv/asm/unistd.h b/libc/kernel/uapi/asm-riscv/asm/unistd.h
new file mode 100644
index 0000000..665b820
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/unistd.h
@@ -0,0 +1,29 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#if defined(__LP64__) && !defined(__SYSCALL_COMPAT)
+#define __ARCH_WANT_NEW_STAT
+#define __ARCH_WANT_SET_GET_RLIMIT
+#endif
+#define __ARCH_WANT_SYS_CLONE3
+#define __ARCH_WANT_MEMFD_SECRET
+#include <asm-generic/unistd.h>
+#ifndef __NR_riscv_flush_icache
+#define __NR_riscv_flush_icache (__NR_arch_specific_syscall + 15)
+#endif
+__SYSCALL(__NR_riscv_flush_icache, sys_riscv_flush_icache)
diff --git a/libc/kernel/uapi/asm-x86/asm/amd_hsmp.h b/libc/kernel/uapi/asm-x86/asm/amd_hsmp.h
new file mode 100644
index 0000000..c026aac
--- /dev/null
+++ b/libc/kernel/uapi/asm-x86/asm/amd_hsmp.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_ASM_X86_AMD_HSMP_H_
+#define _UAPI_ASM_X86_AMD_HSMP_H_
+#include <linux/types.h>
+#pragma pack(4)
+#define HSMP_MAX_MSG_LEN 8
+enum hsmp_message_ids {
+ HSMP_TEST = 1,
+ HSMP_GET_SMU_VER,
+ HSMP_GET_PROTO_VER,
+ HSMP_GET_SOCKET_POWER,
+ HSMP_SET_SOCKET_POWER_LIMIT,
+ HSMP_GET_SOCKET_POWER_LIMIT,
+ HSMP_GET_SOCKET_POWER_LIMIT_MAX,
+ HSMP_SET_BOOST_LIMIT,
+ HSMP_SET_BOOST_LIMIT_SOCKET,
+ HSMP_GET_BOOST_LIMIT,
+ HSMP_GET_PROC_HOT,
+ HSMP_SET_XGMI_LINK_WIDTH,
+ HSMP_SET_DF_PSTATE,
+ HSMP_SET_AUTO_DF_PSTATE,
+ HSMP_GET_FCLK_MCLK,
+ HSMP_GET_CCLK_THROTTLE_LIMIT,
+ HSMP_GET_C0_PERCENT,
+ HSMP_SET_NBIO_DPM_LEVEL,
+ HSMP_GET_NBIO_DPM_LEVEL,
+ HSMP_GET_DDR_BANDWIDTH,
+ HSMP_GET_TEMP_MONITOR,
+ HSMP_GET_DIMM_TEMP_RANGE,
+ HSMP_GET_DIMM_POWER,
+ HSMP_GET_DIMM_THERMAL,
+ HSMP_GET_SOCKET_FREQ_LIMIT,
+ HSMP_GET_CCLK_CORE_LIMIT,
+ HSMP_GET_RAILS_SVI,
+ HSMP_GET_SOCKET_FMAX_FMIN,
+ HSMP_GET_IOLINK_BANDWITH,
+ HSMP_GET_XGMI_BANDWITH,
+ HSMP_SET_GMI3_WIDTH,
+ HSMP_SET_PCI_RATE,
+ HSMP_SET_POWER_MODE,
+ HSMP_SET_PSTATE_MAX_MIN,
+ HSMP_MSG_ID_MAX,
+};
+struct hsmp_message {
+ __u32 msg_id;
+ __u16 num_args;
+ __u16 response_sz;
+ __u32 args[HSMP_MAX_MSG_LEN];
+ __u16 sock_ind;
+};
+enum hsmp_msg_type {
+ HSMP_RSVD = - 1,
+ HSMP_SET = 0,
+ HSMP_GET = 1,
+};
+struct hsmp_msg_desc {
+ int num_args;
+ int response_sz;
+ enum hsmp_msg_type type;
+};
+static const struct hsmp_msg_desc hsmp_msg_desc_table[] = {
+ {
+ 0, 0, HSMP_RSVD
+ }
+ , {
+ 1, 1, HSMP_GET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 1, 0, HSMP_SET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 1, 0, HSMP_SET
+ }
+ , {
+ 1, 0, HSMP_SET
+ }
+ , {
+ 1, 1, HSMP_GET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 1, 0, HSMP_SET
+ }
+ , {
+ 1, 0, HSMP_SET
+ }
+ , {
+ 0, 0, HSMP_SET
+ }
+ , {
+ 0, 2, HSMP_GET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 1, 0, HSMP_SET
+ }
+ , {
+ 1, 1, HSMP_GET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 1, 1, HSMP_GET
+ }
+ , {
+ 1, 1, HSMP_GET
+ }
+ , {
+ 1, 1, HSMP_GET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 1, 1, HSMP_GET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 1, 1, HSMP_GET
+ }
+ , {
+ 1, 1, HSMP_GET
+ }
+ , {
+ 1, 0, HSMP_SET
+ }
+ , {
+ 1, 1, HSMP_SET
+ }
+ , {
+ 1, 0, HSMP_SET
+ }
+ , {
+ 1, 0, HSMP_SET
+ }
+ ,
+};
+#pragma pack()
+#define HSMP_BASE_IOCTL_NR 0xF8
+#define HSMP_IOCTL_CMD _IOWR(HSMP_BASE_IOCTL_NR, 0, struct hsmp_message)
+#endif
diff --git a/libc/kernel/uapi/asm-x86/asm/bootparam.h b/libc/kernel/uapi/asm-x86/asm/bootparam.h
index 7401135..ba1143b 100644
--- a/libc/kernel/uapi/asm-x86/asm/bootparam.h
+++ b/libc/kernel/uapi/asm-x86/asm/bootparam.h
@@ -25,8 +25,9 @@
#define SETUP_EFI 4
#define SETUP_APPLE_PROPERTIES 5
#define SETUP_JAILHOUSE 6
+#define SETUP_CC_BLOB 7
#define SETUP_INDIRECT (1 << 31)
-#define SETUP_TYPE_MAX (SETUP_INDIRECT | SETUP_JAILHOUSE)
+#define SETUP_TYPE_MAX (SETUP_INDIRECT | SETUP_CC_BLOB)
#define RAMDISK_IMAGE_START_MASK 0x07FF
#define RAMDISK_PROMPT_FLAG 0x8000
#define RAMDISK_LOAD_FLAG 0x4000
@@ -162,7 +163,8 @@
__u32 ext_ramdisk_image;
__u32 ext_ramdisk_size;
__u32 ext_cmd_line_ptr;
- __u8 _pad4[116];
+ __u8 _pad4[112];
+ __u32 cc_blob_address;
struct edid_info edid_info;
struct efi_info efi_info;
__u32 alt_mem_k;
diff --git a/libc/kernel/uapi/asm-x86/asm/kvm.h b/libc/kernel/uapi/asm-x86/asm/kvm.h
index caf8fc0..9a929ae 100644
--- a/libc/kernel/uapi/asm-x86/asm/kvm.h
+++ b/libc/kernel/uapi/asm-x86/asm/kvm.h
@@ -350,6 +350,7 @@
#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2)
#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3)
#define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4)
+#define KVM_X86_QUIRK_FIX_HYPERCALL_INSN (1 << 5)
#define KVM_STATE_NESTED_FORMAT_VMX 0
#define KVM_STATE_NESTED_FORMAT_SVM 1
#define KVM_STATE_NESTED_GUEST_MODE 0x00000001
diff --git a/libc/kernel/uapi/asm-x86/asm/processor-flags.h b/libc/kernel/uapi/asm-x86/asm/processor-flags.h
index 85f9d7e..0a95afd 100644
--- a/libc/kernel/uapi/asm-x86/asm/processor-flags.h
+++ b/libc/kernel/uapi/asm-x86/asm/processor-flags.h
@@ -127,6 +127,8 @@
#define X86_CR4_SMAP _BITUL(X86_CR4_SMAP_BIT)
#define X86_CR4_PKE_BIT 22
#define X86_CR4_PKE _BITUL(X86_CR4_PKE_BIT)
+#define X86_CR4_CET_BIT 23
+#define X86_CR4_CET _BITUL(X86_CR4_CET_BIT)
#define X86_CR8_TPR _AC(0x0000000f, UL)
#define CX86_PCR0 0x20
#define CX86_GCR 0xb8
diff --git a/libc/kernel/uapi/asm-x86/asm/shmbuf.h b/libc/kernel/uapi/asm-x86/asm/shmbuf.h
index 03e195e..2a0dcb5 100644
--- a/libc/kernel/uapi/asm-x86/asm/shmbuf.h
+++ b/libc/kernel/uapi/asm-x86/asm/shmbuf.h
@@ -21,9 +21,11 @@
#if !defined(__x86_64__) || !defined(__ILP32__)
#include <asm-generic/shmbuf.h>
#else
+#include <asm/ipcbuf.h>
+#include <asm/posix_types.h>
struct shmid64_ds {
struct ipc64_perm shm_perm;
- size_t shm_segsz;
+ __kernel_size_t shm_segsz;
__kernel_long_t shm_atime;
__kernel_long_t shm_dtime;
__kernel_long_t shm_ctime;
diff --git a/libc/kernel/uapi/asm-x86/asm/signal.h b/libc/kernel/uapi/asm-x86/asm/signal.h
index 8226da8..cbeeac4 100644
--- a/libc/kernel/uapi/asm-x86/asm/signal.h
+++ b/libc/kernel/uapi/asm-x86/asm/signal.h
@@ -90,7 +90,7 @@
typedef struct sigaltstack {
void __user * ss_sp;
int ss_flags;
- size_t ss_size;
+ __kernel_size_t ss_size;
} stack_t;
#endif
#endif
diff --git a/libc/kernel/uapi/asm-x86/asm/svm.h b/libc/kernel/uapi/asm-x86/asm/svm.h
index d051481..8bda2d5 100644
--- a/libc/kernel/uapi/asm-x86/asm/svm.h
+++ b/libc/kernel/uapi/asm-x86/asm/svm.h
@@ -122,8 +122,16 @@
#define SVM_VMGEXIT_AP_JUMP_TABLE 0x80000005
#define SVM_VMGEXIT_SET_AP_JUMP_TABLE 0
#define SVM_VMGEXIT_GET_AP_JUMP_TABLE 1
+#define SVM_VMGEXIT_PSC 0x80000010
+#define SVM_VMGEXIT_GUEST_REQUEST 0x80000011
+#define SVM_VMGEXIT_EXT_GUEST_REQUEST 0x80000012
+#define SVM_VMGEXIT_AP_CREATION 0x80000013
+#define SVM_VMGEXIT_AP_CREATE_ON_INIT 0
+#define SVM_VMGEXIT_AP_CREATE 1
+#define SVM_VMGEXIT_AP_DESTROY 2
+#define SVM_VMGEXIT_HV_FEATURES 0x8000fffd
#define SVM_VMGEXIT_UNSUPPORTED_EVENT 0x8000ffff
#define SVM_EXIT_SW 0xf0000000
#define SVM_EXIT_ERR - 1
-#define SVM_EXIT_REASONS { SVM_EXIT_READ_CR0, "read_cr0" }, { SVM_EXIT_READ_CR2, "read_cr2" }, { SVM_EXIT_READ_CR3, "read_cr3" }, { SVM_EXIT_READ_CR4, "read_cr4" }, { SVM_EXIT_READ_CR8, "read_cr8" }, { SVM_EXIT_WRITE_CR0, "write_cr0" }, { SVM_EXIT_WRITE_CR2, "write_cr2" }, { SVM_EXIT_WRITE_CR3, "write_cr3" }, { SVM_EXIT_WRITE_CR4, "write_cr4" }, { SVM_EXIT_WRITE_CR8, "write_cr8" }, { SVM_EXIT_READ_DR0, "read_dr0" }, { SVM_EXIT_READ_DR1, "read_dr1" }, { SVM_EXIT_READ_DR2, "read_dr2" }, { SVM_EXIT_READ_DR3, "read_dr3" }, { SVM_EXIT_READ_DR4, "read_dr4" }, { SVM_EXIT_READ_DR5, "read_dr5" }, { SVM_EXIT_READ_DR6, "read_dr6" }, { SVM_EXIT_READ_DR7, "read_dr7" }, { SVM_EXIT_WRITE_DR0, "write_dr0" }, { SVM_EXIT_WRITE_DR1, "write_dr1" }, { SVM_EXIT_WRITE_DR2, "write_dr2" }, { SVM_EXIT_WRITE_DR3, "write_dr3" }, { SVM_EXIT_WRITE_DR4, "write_dr4" }, { SVM_EXIT_WRITE_DR5, "write_dr5" }, { SVM_EXIT_WRITE_DR6, "write_dr6" }, { SVM_EXIT_WRITE_DR7, "write_dr7" }, { SVM_EXIT_EXCP_BASE + DE_VECTOR, "DE excp" }, { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, { SVM_EXIT_EXCP_BASE + OF_VECTOR, "OF excp" }, { SVM_EXIT_EXCP_BASE + BR_VECTOR, "BR excp" }, { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, { SVM_EXIT_EXCP_BASE + DF_VECTOR, "DF excp" }, { SVM_EXIT_EXCP_BASE + TS_VECTOR, "TS excp" }, { SVM_EXIT_EXCP_BASE + NP_VECTOR, "NP excp" }, { SVM_EXIT_EXCP_BASE + SS_VECTOR, "SS excp" }, { SVM_EXIT_EXCP_BASE + GP_VECTOR, "GP excp" }, { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, { SVM_EXIT_EXCP_BASE + MF_VECTOR, "MF excp" }, { SVM_EXIT_EXCP_BASE + AC_VECTOR, "AC excp" }, { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, { SVM_EXIT_EXCP_BASE + XM_VECTOR, "XF excp" }, { SVM_EXIT_INTR, "interrupt" }, { SVM_EXIT_NMI, "nmi" }, { SVM_EXIT_SMI, "smi" }, { SVM_EXIT_INIT, "init" }, { SVM_EXIT_VINTR, "vintr" }, { SVM_EXIT_CR0_SEL_WRITE, "cr0_sel_write" }, { SVM_EXIT_IDTR_READ, "read_idtr" }, { SVM_EXIT_GDTR_READ, "read_gdtr" }, { SVM_EXIT_LDTR_READ, "read_ldtr" }, { SVM_EXIT_TR_READ, "read_rt" }, { SVM_EXIT_IDTR_WRITE, "write_idtr" }, { SVM_EXIT_GDTR_WRITE, "write_gdtr" }, { SVM_EXIT_LDTR_WRITE, "write_ldtr" }, { SVM_EXIT_TR_WRITE, "write_rt" }, { SVM_EXIT_RDTSC, "rdtsc" }, { SVM_EXIT_RDPMC, "rdpmc" }, { SVM_EXIT_PUSHF, "pushf" }, { SVM_EXIT_POPF, "popf" }, { SVM_EXIT_CPUID, "cpuid" }, { SVM_EXIT_RSM, "rsm" }, { SVM_EXIT_IRET, "iret" }, { SVM_EXIT_SWINT, "swint" }, { SVM_EXIT_INVD, "invd" }, { SVM_EXIT_PAUSE, "pause" }, { SVM_EXIT_HLT, "hlt" }, { SVM_EXIT_INVLPG, "invlpg" }, { SVM_EXIT_INVLPGA, "invlpga" }, { SVM_EXIT_IOIO, "io" }, { SVM_EXIT_MSR, "msr" }, { SVM_EXIT_TASK_SWITCH, "task_switch" }, { SVM_EXIT_FERR_FREEZE, "ferr_freeze" }, { SVM_EXIT_SHUTDOWN, "shutdown" }, { SVM_EXIT_VMRUN, "vmrun" }, { SVM_EXIT_VMMCALL, "hypercall" }, { SVM_EXIT_VMLOAD, "vmload" }, { SVM_EXIT_VMSAVE, "vmsave" }, { SVM_EXIT_STGI, "stgi" }, { SVM_EXIT_CLGI, "clgi" }, { SVM_EXIT_SKINIT, "skinit" }, { SVM_EXIT_RDTSCP, "rdtscp" }, { SVM_EXIT_ICEBP, "icebp" }, { SVM_EXIT_WBINVD, "wbinvd" }, { SVM_EXIT_MONITOR, "monitor" }, { SVM_EXIT_MWAIT, "mwait" }, { SVM_EXIT_XSETBV, "xsetbv" }, { SVM_EXIT_EFER_WRITE_TRAP, "write_efer_trap" }, { SVM_EXIT_CR0_WRITE_TRAP, "write_cr0_trap" }, { SVM_EXIT_CR4_WRITE_TRAP, "write_cr4_trap" }, { SVM_EXIT_CR8_WRITE_TRAP, "write_cr8_trap" }, { SVM_EXIT_INVPCID, "invpcid" }, { SVM_EXIT_NPF, "npf" }, { SVM_EXIT_AVIC_INCOMPLETE_IPI, "avic_incomplete_ipi" }, { SVM_EXIT_AVIC_UNACCELERATED_ACCESS, "avic_unaccelerated_access" }, { SVM_EXIT_VMGEXIT, "vmgexit" }, { SVM_VMGEXIT_MMIO_READ, "vmgexit_mmio_read" }, { SVM_VMGEXIT_MMIO_WRITE, "vmgexit_mmio_write" }, { SVM_VMGEXIT_NMI_COMPLETE, "vmgexit_nmi_complete" }, { SVM_VMGEXIT_AP_HLT_LOOP, "vmgexit_ap_hlt_loop" }, { SVM_VMGEXIT_AP_JUMP_TABLE, "vmgexit_ap_jump_table" }, { SVM_EXIT_ERR, "invalid_guest_state" }
+#define SVM_EXIT_REASONS { SVM_EXIT_READ_CR0, "read_cr0" }, { SVM_EXIT_READ_CR2, "read_cr2" }, { SVM_EXIT_READ_CR3, "read_cr3" }, { SVM_EXIT_READ_CR4, "read_cr4" }, { SVM_EXIT_READ_CR8, "read_cr8" }, { SVM_EXIT_WRITE_CR0, "write_cr0" }, { SVM_EXIT_WRITE_CR2, "write_cr2" }, { SVM_EXIT_WRITE_CR3, "write_cr3" }, { SVM_EXIT_WRITE_CR4, "write_cr4" }, { SVM_EXIT_WRITE_CR8, "write_cr8" }, { SVM_EXIT_READ_DR0, "read_dr0" }, { SVM_EXIT_READ_DR1, "read_dr1" }, { SVM_EXIT_READ_DR2, "read_dr2" }, { SVM_EXIT_READ_DR3, "read_dr3" }, { SVM_EXIT_READ_DR4, "read_dr4" }, { SVM_EXIT_READ_DR5, "read_dr5" }, { SVM_EXIT_READ_DR6, "read_dr6" }, { SVM_EXIT_READ_DR7, "read_dr7" }, { SVM_EXIT_WRITE_DR0, "write_dr0" }, { SVM_EXIT_WRITE_DR1, "write_dr1" }, { SVM_EXIT_WRITE_DR2, "write_dr2" }, { SVM_EXIT_WRITE_DR3, "write_dr3" }, { SVM_EXIT_WRITE_DR4, "write_dr4" }, { SVM_EXIT_WRITE_DR5, "write_dr5" }, { SVM_EXIT_WRITE_DR6, "write_dr6" }, { SVM_EXIT_WRITE_DR7, "write_dr7" }, { SVM_EXIT_EXCP_BASE + DE_VECTOR, "DE excp" }, { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, { SVM_EXIT_EXCP_BASE + OF_VECTOR, "OF excp" }, { SVM_EXIT_EXCP_BASE + BR_VECTOR, "BR excp" }, { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, { SVM_EXIT_EXCP_BASE + DF_VECTOR, "DF excp" }, { SVM_EXIT_EXCP_BASE + TS_VECTOR, "TS excp" }, { SVM_EXIT_EXCP_BASE + NP_VECTOR, "NP excp" }, { SVM_EXIT_EXCP_BASE + SS_VECTOR, "SS excp" }, { SVM_EXIT_EXCP_BASE + GP_VECTOR, "GP excp" }, { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, { SVM_EXIT_EXCP_BASE + MF_VECTOR, "MF excp" }, { SVM_EXIT_EXCP_BASE + AC_VECTOR, "AC excp" }, { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, { SVM_EXIT_EXCP_BASE + XM_VECTOR, "XF excp" }, { SVM_EXIT_INTR, "interrupt" }, { SVM_EXIT_NMI, "nmi" }, { SVM_EXIT_SMI, "smi" }, { SVM_EXIT_INIT, "init" }, { SVM_EXIT_VINTR, "vintr" }, { SVM_EXIT_CR0_SEL_WRITE, "cr0_sel_write" }, { SVM_EXIT_IDTR_READ, "read_idtr" }, { SVM_EXIT_GDTR_READ, "read_gdtr" }, { SVM_EXIT_LDTR_READ, "read_ldtr" }, { SVM_EXIT_TR_READ, "read_rt" }, { SVM_EXIT_IDTR_WRITE, "write_idtr" }, { SVM_EXIT_GDTR_WRITE, "write_gdtr" }, { SVM_EXIT_LDTR_WRITE, "write_ldtr" }, { SVM_EXIT_TR_WRITE, "write_rt" }, { SVM_EXIT_RDTSC, "rdtsc" }, { SVM_EXIT_RDPMC, "rdpmc" }, { SVM_EXIT_PUSHF, "pushf" }, { SVM_EXIT_POPF, "popf" }, { SVM_EXIT_CPUID, "cpuid" }, { SVM_EXIT_RSM, "rsm" }, { SVM_EXIT_IRET, "iret" }, { SVM_EXIT_SWINT, "swint" }, { SVM_EXIT_INVD, "invd" }, { SVM_EXIT_PAUSE, "pause" }, { SVM_EXIT_HLT, "hlt" }, { SVM_EXIT_INVLPG, "invlpg" }, { SVM_EXIT_INVLPGA, "invlpga" }, { SVM_EXIT_IOIO, "io" }, { SVM_EXIT_MSR, "msr" }, { SVM_EXIT_TASK_SWITCH, "task_switch" }, { SVM_EXIT_FERR_FREEZE, "ferr_freeze" }, { SVM_EXIT_SHUTDOWN, "shutdown" }, { SVM_EXIT_VMRUN, "vmrun" }, { SVM_EXIT_VMMCALL, "hypercall" }, { SVM_EXIT_VMLOAD, "vmload" }, { SVM_EXIT_VMSAVE, "vmsave" }, { SVM_EXIT_STGI, "stgi" }, { SVM_EXIT_CLGI, "clgi" }, { SVM_EXIT_SKINIT, "skinit" }, { SVM_EXIT_RDTSCP, "rdtscp" }, { SVM_EXIT_ICEBP, "icebp" }, { SVM_EXIT_WBINVD, "wbinvd" }, { SVM_EXIT_MONITOR, "monitor" }, { SVM_EXIT_MWAIT, "mwait" }, { SVM_EXIT_XSETBV, "xsetbv" }, { SVM_EXIT_EFER_WRITE_TRAP, "write_efer_trap" }, { SVM_EXIT_CR0_WRITE_TRAP, "write_cr0_trap" }, { SVM_EXIT_CR4_WRITE_TRAP, "write_cr4_trap" }, { SVM_EXIT_CR8_WRITE_TRAP, "write_cr8_trap" }, { SVM_EXIT_INVPCID, "invpcid" }, { SVM_EXIT_NPF, "npf" }, { SVM_EXIT_AVIC_INCOMPLETE_IPI, "avic_incomplete_ipi" }, { SVM_EXIT_AVIC_UNACCELERATED_ACCESS, "avic_unaccelerated_access" }, { SVM_EXIT_VMGEXIT, "vmgexit" }, { SVM_VMGEXIT_MMIO_READ, "vmgexit_mmio_read" }, { SVM_VMGEXIT_MMIO_WRITE, "vmgexit_mmio_write" }, { SVM_VMGEXIT_NMI_COMPLETE, "vmgexit_nmi_complete" }, { SVM_VMGEXIT_AP_HLT_LOOP, "vmgexit_ap_hlt_loop" }, { SVM_VMGEXIT_AP_JUMP_TABLE, "vmgexit_ap_jump_table" }, { SVM_VMGEXIT_PSC, "vmgexit_page_state_change" }, { SVM_VMGEXIT_GUEST_REQUEST, "vmgexit_guest_request" }, { SVM_VMGEXIT_EXT_GUEST_REQUEST, "vmgexit_ext_guest_request" }, { SVM_VMGEXIT_AP_CREATION, "vmgexit_ap_creation" }, { SVM_VMGEXIT_HV_FEATURES, "vmgexit_hypervisor_feature" }, { SVM_EXIT_ERR, "invalid_guest_state" }
#endif
diff --git a/libc/kernel/uapi/drm/amdgpu_drm.h b/libc/kernel/uapi/drm/amdgpu_drm.h
index 3764d51..2d3afda 100644
--- a/libc/kernel/uapi/drm/amdgpu_drm.h
+++ b/libc/kernel/uapi/drm/amdgpu_drm.h
@@ -72,6 +72,7 @@
#define AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE (1 << 9)
#define AMDGPU_GEM_CREATE_ENCRYPTED (1 << 10)
#define AMDGPU_GEM_CREATE_PREEMPTIBLE (1 << 11)
+#define AMDGPU_GEM_CREATE_DISCARDABLE (1 << 12)
struct drm_amdgpu_gem_create_in {
__u64 bo_size;
__u64 alignment;
@@ -112,6 +113,8 @@
#define AMDGPU_CTX_OP_FREE_CTX 2
#define AMDGPU_CTX_OP_QUERY_STATE 3
#define AMDGPU_CTX_OP_QUERY_STATE2 4
+#define AMDGPU_CTX_OP_GET_STABLE_PSTATE 5
+#define AMDGPU_CTX_OP_SET_STABLE_PSTATE 6
#define AMDGPU_CTX_NO_RESET 0
#define AMDGPU_CTX_GUILTY_RESET 1
#define AMDGPU_CTX_INNOCENT_RESET 2
@@ -127,6 +130,12 @@
#define AMDGPU_CTX_PRIORITY_NORMAL 0
#define AMDGPU_CTX_PRIORITY_HIGH 512
#define AMDGPU_CTX_PRIORITY_VERY_HIGH 1023
+#define AMDGPU_CTX_STABLE_PSTATE_FLAGS_MASK 0xf
+#define AMDGPU_CTX_STABLE_PSTATE_NONE 0
+#define AMDGPU_CTX_STABLE_PSTATE_STANDARD 1
+#define AMDGPU_CTX_STABLE_PSTATE_MIN_SCLK 2
+#define AMDGPU_CTX_STABLE_PSTATE_MIN_MCLK 3
+#define AMDGPU_CTX_STABLE_PSTATE_PEAK 4
struct drm_amdgpu_ctx_in {
__u32 op;
__u32 flags;
@@ -143,6 +152,10 @@
__u32 hangs;
__u32 reset_status;
} state;
+ struct {
+ __u32 flags;
+ __u32 _pad;
+ } pstate;
};
union drm_amdgpu_ctx {
struct drm_amdgpu_ctx_in in;
@@ -307,6 +320,7 @@
#define AMDGPU_VM_MTYPE_CC (3 << 5)
#define AMDGPU_VM_MTYPE_UC (4 << 5)
#define AMDGPU_VM_MTYPE_RW (5 << 5)
+#define AMDGPU_VM_PAGE_NOALLOC (1 << 9)
struct drm_amdgpu_gem_va {
__u32 handle;
__u32 _pad;
@@ -438,6 +452,7 @@
#define AMDGPU_INFO_FW_TA 0x13
#define AMDGPU_INFO_FW_DMCUB 0x14
#define AMDGPU_INFO_FW_TOC 0x15
+#define AMDGPU_INFO_FW_CAP 0x16
#define AMDGPU_INFO_NUM_BYTES_MOVED 0x0f
#define AMDGPU_INFO_VRAM_USAGE 0x10
#define AMDGPU_INFO_GTT_USAGE 0x11
@@ -575,6 +590,8 @@
#define AMDGPU_VRAM_TYPE_DDR4 8
#define AMDGPU_VRAM_TYPE_GDDR6 9
#define AMDGPU_VRAM_TYPE_DDR5 10
+#define AMDGPU_VRAM_TYPE_LPDDR4 11
+#define AMDGPU_VRAM_TYPE_LPDDR5 12
struct drm_amdgpu_info_device {
__u32 device_id;
__u32 chip_rev;
@@ -681,7 +698,11 @@
#define AMDGPU_FAMILY_RV 142
#define AMDGPU_FAMILY_NV 143
#define AMDGPU_FAMILY_VGH 144
+#define AMDGPU_FAMILY_GC_11_0_0 145
#define AMDGPU_FAMILY_YC 146
+#define AMDGPU_FAMILY_GC_11_0_1 148
+#define AMDGPU_FAMILY_GC_10_3_6 149
+#define AMDGPU_FAMILY_GC_10_3_7 151
#ifdef __cplusplus
}
#endif
diff --git a/libc/kernel/uapi/drm/drm_fourcc.h b/libc/kernel/uapi/drm/drm_fourcc.h
index e845c8c..f032fa3 100644
--- a/libc/kernel/uapi/drm/drm_fourcc.h
+++ b/libc/kernel/uapi/drm/drm_fourcc.h
@@ -163,9 +163,15 @@
#define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS fourcc_mod_code(INTEL, 6)
#define I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS fourcc_mod_code(INTEL, 7)
#define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC fourcc_mod_code(INTEL, 8)
+#define I915_FORMAT_MOD_4_TILED fourcc_mod_code(INTEL, 9)
+#define I915_FORMAT_MOD_4_TILED_DG2_RC_CCS fourcc_mod_code(INTEL, 10)
+#define I915_FORMAT_MOD_4_TILED_DG2_MC_CCS fourcc_mod_code(INTEL, 11)
+#define I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC fourcc_mod_code(INTEL, 12)
#define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1)
#define DRM_FORMAT_MOD_SAMSUNG_16_16_TILE fourcc_mod_code(SAMSUNG, 2)
#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
+#define DRM_FORMAT_MOD_QCOM_TILED3 fourcc_mod_code(QCOM, 3)
+#define DRM_FORMAT_MOD_QCOM_TILED2 fourcc_mod_code(QCOM, 2)
#define DRM_FORMAT_MOD_VIVANTE_TILED fourcc_mod_code(VIVANTE, 1)
#define DRM_FORMAT_MOD_VIVANTE_SUPER_TILED fourcc_mod_code(VIVANTE, 2)
#define DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED fourcc_mod_code(VIVANTE, 3)
@@ -271,9 +277,9 @@
#define AMD_FMT_MOD_RB_MASK 0x7
#define AMD_FMT_MOD_PIPE_SHIFT 33
#define AMD_FMT_MOD_PIPE_MASK 0x7
-#define AMD_FMT_MOD_SET(field,value) ((uint64_t) (value) << AMD_FMT_MOD_ ##field ##_SHIFT)
+#define AMD_FMT_MOD_SET(field,value) ((__u64) (value) << AMD_FMT_MOD_ ##field ##_SHIFT)
#define AMD_FMT_MOD_GET(field,value) (((value) >> AMD_FMT_MOD_ ##field ##_SHIFT) & AMD_FMT_MOD_ ##field ##_MASK)
-#define AMD_FMT_MOD_CLEAR(field) (~((uint64_t) AMD_FMT_MOD_ ##field ##_MASK << AMD_FMT_MOD_ ##field ##_SHIFT))
+#define AMD_FMT_MOD_CLEAR(field) (~((__u64) AMD_FMT_MOD_ ##field ##_MASK << AMD_FMT_MOD_ ##field ##_SHIFT))
#ifdef __cplusplus
}
#endif
diff --git a/libc/kernel/uapi/drm/i915_drm.h b/libc/kernel/uapi/drm/i915_drm.h
index 52bfad2..1c79905 100644
--- a/libc/kernel/uapi/drm/i915_drm.h
+++ b/libc/kernel/uapi/drm/i915_drm.h
@@ -41,13 +41,14 @@
I915_ENGINE_CLASS_COPY = 1,
I915_ENGINE_CLASS_VIDEO = 2,
I915_ENGINE_CLASS_VIDEO_ENHANCE = 3,
+ I915_ENGINE_CLASS_COMPUTE = 4,
I915_ENGINE_CLASS_INVALID = - 1
};
struct i915_engine_class_instance {
__u16 engine_class;
- __u16 engine_instance;
#define I915_ENGINE_CLASS_INVALID_NONE - 1
#define I915_ENGINE_CLASS_INVALID_VIRTUAL - 2
+ __u16 engine_instance;
};
enum drm_i915_pmu_engine_sample {
I915_SAMPLE_BUSY = 0,
@@ -894,6 +895,8 @@
#define DRM_I915_QUERY_ENGINE_INFO 2
#define DRM_I915_QUERY_PERF_CONFIG 3
#define DRM_I915_QUERY_MEMORY_REGIONS 4
+#define DRM_I915_QUERY_HWCONFIG_BLOB 5
+#define DRM_I915_QUERY_GEOMETRY_SUBSLICES 6
__s32 length;
__u32 flags;
#define DRM_I915_QUERY_PERF_CONFIG_LIST 1
diff --git a/libc/kernel/uapi/drm/msm_drm.h b/libc/kernel/uapi/drm/msm_drm.h
index b4ba1d0..c2edefd 100644
--- a/libc/kernel/uapi/drm/msm_drm.h
+++ b/libc/kernel/uapi/drm/msm_drm.h
@@ -43,11 +43,18 @@
#define MSM_PARAM_PP_PGTABLE 0x08
#define MSM_PARAM_FAULTS 0x09
#define MSM_PARAM_SUSPENDS 0x0a
+#define MSM_PARAM_SYSPROF 0x0b
+#define MSM_PARAM_COMM 0x0c
+#define MSM_PARAM_CMDLINE 0x0d
+#define MSM_PARAM_VA_START 0x0e
+#define MSM_PARAM_VA_SIZE 0x0f
#define MSM_PARAM_NR_RINGS MSM_PARAM_PRIORITIES
struct drm_msm_param {
__u32 pipe;
__u32 param;
__u64 value;
+ __u32 len;
+ __u32 pad;
};
#define MSM_BO_SCANOUT 0x00000001
#define MSM_BO_GPU_READONLY 0x00000002
@@ -66,6 +73,7 @@
#define MSM_INFO_GET_IOVA 0x01
#define MSM_INFO_SET_NAME 0x02
#define MSM_INFO_GET_NAME 0x03
+#define MSM_INFO_SET_IOVA 0x04
struct drm_msm_gem_info {
__u32 handle;
__u32 info;
@@ -119,7 +127,8 @@
#define MSM_SUBMIT_SUDO 0x10000000
#define MSM_SUBMIT_SYNCOBJ_IN 0x08000000
#define MSM_SUBMIT_SYNCOBJ_OUT 0x04000000
-#define MSM_SUBMIT_FLAGS (MSM_SUBMIT_NO_IMPLICIT | MSM_SUBMIT_FENCE_FD_IN | MSM_SUBMIT_FENCE_FD_OUT | MSM_SUBMIT_SUDO | MSM_SUBMIT_SYNCOBJ_IN | MSM_SUBMIT_SYNCOBJ_OUT | 0)
+#define MSM_SUBMIT_FENCE_SN_IN 0x02000000
+#define MSM_SUBMIT_FLAGS (MSM_SUBMIT_NO_IMPLICIT | MSM_SUBMIT_FENCE_FD_IN | MSM_SUBMIT_FENCE_FD_OUT | MSM_SUBMIT_SUDO | MSM_SUBMIT_SYNCOBJ_IN | MSM_SUBMIT_SYNCOBJ_OUT | MSM_SUBMIT_FENCE_SN_IN | 0)
#define MSM_SUBMIT_SYNCOBJ_RESET 0x00000001
#define MSM_SUBMIT_SYNCOBJ_FLAGS (MSM_SUBMIT_SYNCOBJ_RESET | 0)
struct drm_msm_gem_submit_syncobj {
@@ -172,6 +181,7 @@
__u32 pad;
};
#define DRM_MSM_GET_PARAM 0x00
+#define DRM_MSM_SET_PARAM 0x01
#define DRM_MSM_GEM_NEW 0x02
#define DRM_MSM_GEM_INFO 0x03
#define DRM_MSM_GEM_CPU_PREP 0x04
@@ -183,6 +193,7 @@
#define DRM_MSM_SUBMITQUEUE_CLOSE 0x0B
#define DRM_MSM_SUBMITQUEUE_QUERY 0x0C
#define DRM_IOCTL_MSM_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GET_PARAM, struct drm_msm_param)
+#define DRM_IOCTL_MSM_SET_PARAM DRM_IOW(DRM_COMMAND_BASE + DRM_MSM_SET_PARAM, struct drm_msm_param)
#define DRM_IOCTL_MSM_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_NEW, struct drm_msm_gem_new)
#define DRM_IOCTL_MSM_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_INFO, struct drm_msm_gem_info)
#define DRM_IOCTL_MSM_GEM_CPU_PREP DRM_IOW(DRM_COMMAND_BASE + DRM_MSM_GEM_CPU_PREP, struct drm_msm_gem_cpu_prep)
diff --git a/libc/kernel/uapi/drm/vmwgfx_drm.h b/libc/kernel/uapi/drm/vmwgfx_drm.h
index 395743b..2f75589 100644
--- a/libc/kernel/uapi/drm/vmwgfx_drm.h
+++ b/libc/kernel/uapi/drm/vmwgfx_drm.h
@@ -76,6 +76,7 @@
#define DRM_VMW_PARAM_SM4_1 14
#define DRM_VMW_PARAM_SM5 15
#define DRM_VMW_PARAM_GL43 16
+#define DRM_VMW_PARAM_DEVICE_ID 17
enum drm_vmw_handle_type {
DRM_VMW_HANDLE_LEGACY = 0,
DRM_VMW_HANDLE_PRIME = 1
diff --git a/libc/kernel/uapi/linux/acct.h b/libc/kernel/uapi/linux/acct.h
index aecc9f6..ba9d25f 100644
--- a/libc/kernel/uapi/linux/acct.h
+++ b/libc/kernel/uapi/linux/acct.h
@@ -74,6 +74,7 @@
#define ACOMPAT 0x04
#define ACORE 0x08
#define AXSIG 0x10
+#define AGROUP 0x20
#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : defined(__BIG_ENDIAN)
#define ACCT_BYTEORDER 0x80
#elif defined(__BYTE_ORDER)?__BYTE_ORDER==__LITTLE_ENDIAN:defined(__LITTLE_ENDIAN)
diff --git a/libc/kernel/uapi/linux/agpgart.h b/libc/kernel/uapi/linux/agpgart.h
index 3b126f1..9dda7bf 100644
--- a/libc/kernel/uapi/linux/agpgart.h
+++ b/libc/kernel/uapi/linux/agpgart.h
@@ -38,7 +38,6 @@
#define FALSE 0
#endif
#include <linux/types.h>
-#include <stdlib.h>
struct agp_version {
__u16 major;
__u16 minor;
@@ -48,10 +47,10 @@
__u32 bridge_id;
__u32 agp_mode;
unsigned long aper_base;
- size_t aper_size;
- size_t pg_total;
- size_t pg_system;
- size_t pg_used;
+ __kernel_size_t aper_size;
+ __kernel_size_t pg_total;
+ __kernel_size_t pg_system;
+ __kernel_size_t pg_used;
} agp_info;
typedef struct _agp_setup {
__u32 agp_mode;
diff --git a/libc/kernel/uapi/linux/android/binder.h b/libc/kernel/uapi/linux/android/binder.h
index ded1756..2745972 100644
--- a/libc/kernel/uapi/linux/android/binder.h
+++ b/libc/kernel/uapi/linux/android/binder.h
@@ -127,6 +127,11 @@
__u32 sync_recv;
__u32 async_recv;
};
+struct binder_extended_error {
+ __u32 id;
+ __u32 command;
+ __s32 param;
+};
#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64)
#define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32)
@@ -140,6 +145,7 @@
#define BINDER_FREEZE _IOW('b', 14, struct binder_freeze_info)
#define BINDER_GET_FROZEN_INFO _IOWR('b', 15, struct binder_frozen_status_info)
#define BINDER_ENABLE_ONEWAY_SPAM_DETECTION _IOW('b', 16, __u32)
+#define BINDER_GET_EXTENDED_ERROR _IOWR('b', 17, struct binder_extended_error)
enum transaction_flags {
TF_ONE_WAY = 0x01,
TF_ROOT_OBJECT = 0x04,
@@ -155,8 +161,8 @@
binder_uintptr_t cookie;
__u32 code;
__u32 flags;
- pid_t sender_pid;
- uid_t sender_euid;
+ __kernel_pid_t sender_pid;
+ __kernel_uid32_t sender_euid;
binder_size_t data_size;
binder_size_t offsets_size;
union {
diff --git a/libc/kernel/uapi/linux/atm_zatm.h b/libc/kernel/uapi/linux/atm_zatm.h
deleted file mode 100644
index 1649b85..0000000
--- a/libc/kernel/uapi/linux/atm_zatm.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- *** This header was automatically generated from a Linux kernel header
- *** of the same name, to make information necessary for userspace to
- *** call into the kernel available to libc. It contains only constants,
- *** structures, and macros generated from the original header, and thus,
- *** contains no copyrightable information.
- ***
- *** To edit the content of this header, modify the corresponding
- *** source file (e.g. under external/kernel-headers/original/) then
- *** run bionic/libc/kernel/tools/update_all.py
- ***
- *** Any manual change here will be lost the next time this script will
- *** be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef LINUX_ATM_ZATM_H
-#define LINUX_ATM_ZATM_H
-#include <linux/atmapi.h>
-#include <linux/atmioc.h>
-#define ZATM_GETPOOL _IOW('a', ATMIOC_SARPRV + 1, struct atmif_sioc)
-#define ZATM_GETPOOLZ _IOW('a', ATMIOC_SARPRV + 2, struct atmif_sioc)
-#define ZATM_SETPOOL _IOW('a', ATMIOC_SARPRV + 3, struct atmif_sioc)
-struct zatm_pool_info {
- int ref_count;
- int low_water, high_water;
- int rqa_count, rqu_count;
- int offset, next_off;
- int next_cnt, next_thres;
-};
-struct zatm_pool_req {
- int pool_num;
- struct zatm_pool_info info;
-};
-#define ZATM_OAM_POOL 0
-#define ZATM_AAL0_POOL 1
-#define ZATM_AAL5_POOL_BASE 2
-#define ZATM_LAST_POOL ZATM_AAL5_POOL_BASE + 10
-#define ZATM_TIMER_HISTORY_SIZE 16
-#endif
diff --git a/libc/kernel/uapi/linux/audit.h b/libc/kernel/uapi/linux/audit.h
index 30a94af..2c37e2a 100644
--- a/libc/kernel/uapi/linux/audit.h
+++ b/libc/kernel/uapi/linux/audit.h
@@ -323,6 +323,8 @@
#define AUDIT_ARCH_UNICORE (EM_UNICORE | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_X86_64 (EM_X86_64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_XTENSA (EM_XTENSA)
+#define AUDIT_ARCH_LOONGARCH32 (EM_LOONGARCH | __AUDIT_ARCH_LE)
+#define AUDIT_ARCH_LOONGARCH64 (EM_LOONGARCH | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
#define AUDIT_PERM_EXEC 1
#define AUDIT_PERM_WRITE 2
#define AUDIT_PERM_READ 4
diff --git a/libc/kernel/uapi/linux/bpf.h b/libc/kernel/uapi/linux/bpf.h
index d363e81..dd10b34 100644
--- a/libc/kernel/uapi/linux/bpf.h
+++ b/libc/kernel/uapi/linux/bpf.h
@@ -228,6 +228,7 @@
BPF_SK_REUSEPORT_SELECT,
BPF_SK_REUSEPORT_SELECT_OR_MIGRATE,
BPF_PERF_EVENT,
+ BPF_TRACE_KPROBE_MULTI,
__MAX_BPF_ATTACH_TYPE
};
#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
@@ -240,6 +241,8 @@
BPF_LINK_TYPE_NETNS = 5,
BPF_LINK_TYPE_XDP = 6,
BPF_LINK_TYPE_PERF_EVENT = 7,
+ BPF_LINK_TYPE_KPROBE_MULTI = 8,
+ BPF_LINK_TYPE_STRUCT_OPS = 9,
MAX_BPF_LINK_TYPE,
};
#define BPF_F_ALLOW_OVERRIDE (1U << 0)
@@ -250,6 +253,8 @@
#define BPF_F_TEST_RND_HI32 (1U << 2)
#define BPF_F_TEST_STATE_FREQ (1U << 3)
#define BPF_F_SLEEPABLE (1U << 4)
+#define BPF_F_XDP_HAS_FRAGS (1U << 5)
+#define BPF_F_KPROBE_MULTI_RETURN (1U << 0)
#define BPF_PSEUDO_MAP_FD 1
#define BPF_PSEUDO_MAP_IDX 5
#define BPF_PSEUDO_MAP_VALUE 2
@@ -281,6 +286,7 @@
};
#define BPF_F_QUERY_EFFECTIVE (1U << 0)
#define BPF_F_TEST_RUN_ON_CPU (1U << 0)
+#define BPF_F_TEST_XDP_LIVE_FRAMES (1U << 1)
enum bpf_stats_type {
BPF_STATS_RUN_TIME = 0,
};
@@ -392,6 +398,7 @@
__aligned_u64 ctx_out;
__u32 flags;
__u32 cpu;
+ __u32 batch_size;
} test;
struct {
union {
@@ -456,6 +463,17 @@
struct {
__u64 bpf_cookie;
} perf_event;
+ struct {
+ __u32 flags;
+ __u32 cnt;
+ __aligned_u64 syms;
+ __aligned_u64 addrs;
+ __aligned_u64 cookies;
+ } kprobe_multi;
+ struct {
+ __u32 target_btf_id;
+ __u64 cookie;
+ } tracing;
};
} link_create;
struct {
@@ -480,7 +498,7 @@
__u32 flags;
} prog_bind_map;
} __attribute__((aligned(8)));
-#define __BPF_FUNC_MAPPER(FN) FN(unspec), FN(map_lookup_elem), FN(map_update_elem), FN(map_delete_elem), FN(probe_read), FN(ktime_get_ns), FN(trace_printk), FN(get_prandom_u32), FN(get_smp_processor_id), FN(skb_store_bytes), FN(l3_csum_replace), FN(l4_csum_replace), FN(tail_call), FN(clone_redirect), FN(get_current_pid_tgid), FN(get_current_uid_gid), FN(get_current_comm), FN(get_cgroup_classid), FN(skb_vlan_push), FN(skb_vlan_pop), FN(skb_get_tunnel_key), FN(skb_set_tunnel_key), FN(perf_event_read), FN(redirect), FN(get_route_realm), FN(perf_event_output), FN(skb_load_bytes), FN(get_stackid), FN(csum_diff), FN(skb_get_tunnel_opt), FN(skb_set_tunnel_opt), FN(skb_change_proto), FN(skb_change_type), FN(skb_under_cgroup), FN(get_hash_recalc), FN(get_current_task), FN(probe_write_user), FN(current_task_under_cgroup), FN(skb_change_tail), FN(skb_pull_data), FN(csum_update), FN(set_hash_invalid), FN(get_numa_node_id), FN(skb_change_head), FN(xdp_adjust_head), FN(probe_read_str), FN(get_socket_cookie), FN(get_socket_uid), FN(set_hash), FN(setsockopt), FN(skb_adjust_room), FN(redirect_map), FN(sk_redirect_map), FN(sock_map_update), FN(xdp_adjust_meta), FN(perf_event_read_value), FN(perf_prog_read_value), FN(getsockopt), FN(override_return), FN(sock_ops_cb_flags_set), FN(msg_redirect_map), FN(msg_apply_bytes), FN(msg_cork_bytes), FN(msg_pull_data), FN(bind), FN(xdp_adjust_tail), FN(skb_get_xfrm_state), FN(get_stack), FN(skb_load_bytes_relative), FN(fib_lookup), FN(sock_hash_update), FN(msg_redirect_hash), FN(sk_redirect_hash), FN(lwt_push_encap), FN(lwt_seg6_store_bytes), FN(lwt_seg6_adjust_srh), FN(lwt_seg6_action), FN(rc_repeat), FN(rc_keydown), FN(skb_cgroup_id), FN(get_current_cgroup_id), FN(get_local_storage), FN(sk_select_reuseport), FN(skb_ancestor_cgroup_id), FN(sk_lookup_tcp), FN(sk_lookup_udp), FN(sk_release), FN(map_push_elem), FN(map_pop_elem), FN(map_peek_elem), FN(msg_push_data), FN(msg_pop_data), FN(rc_pointer_rel), FN(spin_lock), FN(spin_unlock), FN(sk_fullsock), FN(tcp_sock), FN(skb_ecn_set_ce), FN(get_listener_sock), FN(skc_lookup_tcp), FN(tcp_check_syncookie), FN(sysctl_get_name), FN(sysctl_get_current_value), FN(sysctl_get_new_value), FN(sysctl_set_new_value), FN(strtol), FN(strtoul), FN(sk_storage_get), FN(sk_storage_delete), FN(send_signal), FN(tcp_gen_syncookie), FN(skb_output), FN(probe_read_user), FN(probe_read_kernel), FN(probe_read_user_str), FN(probe_read_kernel_str), FN(tcp_send_ack), FN(send_signal_thread), FN(jiffies64), FN(read_branch_records), FN(get_ns_current_pid_tgid), FN(xdp_output), FN(get_netns_cookie), FN(get_current_ancestor_cgroup_id), FN(sk_assign), FN(ktime_get_boot_ns), FN(seq_printf), FN(seq_write), FN(sk_cgroup_id), FN(sk_ancestor_cgroup_id), FN(ringbuf_output), FN(ringbuf_reserve), FN(ringbuf_submit), FN(ringbuf_discard), FN(ringbuf_query), FN(csum_level), FN(skc_to_tcp6_sock), FN(skc_to_tcp_sock), FN(skc_to_tcp_timewait_sock), FN(skc_to_tcp_request_sock), FN(skc_to_udp6_sock), FN(get_task_stack), FN(load_hdr_opt), FN(store_hdr_opt), FN(reserve_hdr_opt), FN(inode_storage_get), FN(inode_storage_delete), FN(d_path), FN(copy_from_user), FN(snprintf_btf), FN(seq_printf_btf), FN(skb_cgroup_classid), FN(redirect_neigh), FN(per_cpu_ptr), FN(this_cpu_ptr), FN(redirect_peer), FN(task_storage_get), FN(task_storage_delete), FN(get_current_task_btf), FN(bprm_opts_set), FN(ktime_get_coarse_ns), FN(ima_inode_hash), FN(sock_from_file), FN(check_mtu), FN(for_each_map_elem), FN(snprintf), FN(sys_bpf), FN(btf_find_by_name_kind), FN(sys_close), FN(timer_init), FN(timer_set_callback), FN(timer_start), FN(timer_cancel), FN(get_func_ip), FN(get_attach_cookie), FN(task_pt_regs), FN(get_branch_snapshot), FN(trace_vprintk), FN(skc_to_unix_sock), FN(kallsyms_lookup_name), FN(find_vma), FN(loop), FN(strncmp), FN(get_func_arg), FN(get_func_ret), FN(get_func_arg_cnt),
+#define __BPF_FUNC_MAPPER(FN) FN(unspec), FN(map_lookup_elem), FN(map_update_elem), FN(map_delete_elem), FN(probe_read), FN(ktime_get_ns), FN(trace_printk), FN(get_prandom_u32), FN(get_smp_processor_id), FN(skb_store_bytes), FN(l3_csum_replace), FN(l4_csum_replace), FN(tail_call), FN(clone_redirect), FN(get_current_pid_tgid), FN(get_current_uid_gid), FN(get_current_comm), FN(get_cgroup_classid), FN(skb_vlan_push), FN(skb_vlan_pop), FN(skb_get_tunnel_key), FN(skb_set_tunnel_key), FN(perf_event_read), FN(redirect), FN(get_route_realm), FN(perf_event_output), FN(skb_load_bytes), FN(get_stackid), FN(csum_diff), FN(skb_get_tunnel_opt), FN(skb_set_tunnel_opt), FN(skb_change_proto), FN(skb_change_type), FN(skb_under_cgroup), FN(get_hash_recalc), FN(get_current_task), FN(probe_write_user), FN(current_task_under_cgroup), FN(skb_change_tail), FN(skb_pull_data), FN(csum_update), FN(set_hash_invalid), FN(get_numa_node_id), FN(skb_change_head), FN(xdp_adjust_head), FN(probe_read_str), FN(get_socket_cookie), FN(get_socket_uid), FN(set_hash), FN(setsockopt), FN(skb_adjust_room), FN(redirect_map), FN(sk_redirect_map), FN(sock_map_update), FN(xdp_adjust_meta), FN(perf_event_read_value), FN(perf_prog_read_value), FN(getsockopt), FN(override_return), FN(sock_ops_cb_flags_set), FN(msg_redirect_map), FN(msg_apply_bytes), FN(msg_cork_bytes), FN(msg_pull_data), FN(bind), FN(xdp_adjust_tail), FN(skb_get_xfrm_state), FN(get_stack), FN(skb_load_bytes_relative), FN(fib_lookup), FN(sock_hash_update), FN(msg_redirect_hash), FN(sk_redirect_hash), FN(lwt_push_encap), FN(lwt_seg6_store_bytes), FN(lwt_seg6_adjust_srh), FN(lwt_seg6_action), FN(rc_repeat), FN(rc_keydown), FN(skb_cgroup_id), FN(get_current_cgroup_id), FN(get_local_storage), FN(sk_select_reuseport), FN(skb_ancestor_cgroup_id), FN(sk_lookup_tcp), FN(sk_lookup_udp), FN(sk_release), FN(map_push_elem), FN(map_pop_elem), FN(map_peek_elem), FN(msg_push_data), FN(msg_pop_data), FN(rc_pointer_rel), FN(spin_lock), FN(spin_unlock), FN(sk_fullsock), FN(tcp_sock), FN(skb_ecn_set_ce), FN(get_listener_sock), FN(skc_lookup_tcp), FN(tcp_check_syncookie), FN(sysctl_get_name), FN(sysctl_get_current_value), FN(sysctl_get_new_value), FN(sysctl_set_new_value), FN(strtol), FN(strtoul), FN(sk_storage_get), FN(sk_storage_delete), FN(send_signal), FN(tcp_gen_syncookie), FN(skb_output), FN(probe_read_user), FN(probe_read_kernel), FN(probe_read_user_str), FN(probe_read_kernel_str), FN(tcp_send_ack), FN(send_signal_thread), FN(jiffies64), FN(read_branch_records), FN(get_ns_current_pid_tgid), FN(xdp_output), FN(get_netns_cookie), FN(get_current_ancestor_cgroup_id), FN(sk_assign), FN(ktime_get_boot_ns), FN(seq_printf), FN(seq_write), FN(sk_cgroup_id), FN(sk_ancestor_cgroup_id), FN(ringbuf_output), FN(ringbuf_reserve), FN(ringbuf_submit), FN(ringbuf_discard), FN(ringbuf_query), FN(csum_level), FN(skc_to_tcp6_sock), FN(skc_to_tcp_sock), FN(skc_to_tcp_timewait_sock), FN(skc_to_tcp_request_sock), FN(skc_to_udp6_sock), FN(get_task_stack), FN(load_hdr_opt), FN(store_hdr_opt), FN(reserve_hdr_opt), FN(inode_storage_get), FN(inode_storage_delete), FN(d_path), FN(copy_from_user), FN(snprintf_btf), FN(seq_printf_btf), FN(skb_cgroup_classid), FN(redirect_neigh), FN(per_cpu_ptr), FN(this_cpu_ptr), FN(redirect_peer), FN(task_storage_get), FN(task_storage_delete), FN(get_current_task_btf), FN(bprm_opts_set), FN(ktime_get_coarse_ns), FN(ima_inode_hash), FN(sock_from_file), FN(check_mtu), FN(for_each_map_elem), FN(snprintf), FN(sys_bpf), FN(btf_find_by_name_kind), FN(sys_close), FN(timer_init), FN(timer_set_callback), FN(timer_start), FN(timer_cancel), FN(get_func_ip), FN(get_attach_cookie), FN(task_pt_regs), FN(get_branch_snapshot), FN(trace_vprintk), FN(skc_to_unix_sock), FN(kallsyms_lookup_name), FN(find_vma), FN(loop), FN(strncmp), FN(get_func_arg), FN(get_func_ret), FN(get_func_arg_cnt), FN(get_retval), FN(set_retval), FN(xdp_get_buff_len), FN(xdp_load_bytes), FN(xdp_store_bytes), FN(copy_from_user_task), FN(skb_set_tstamp), FN(ima_file_hash), FN(kptr_xchg), FN(map_lookup_percpu_elem), FN(skc_to_mptcp_sock), FN(dynptr_from_mem), FN(ringbuf_reserve_dynptr), FN(ringbuf_submit_dynptr), FN(ringbuf_discard_dynptr), FN(dynptr_read), FN(dynptr_write), FN(dynptr_data),
#define __BPF_ENUM_FN(x) BPF_FUNC_ ##x
enum bpf_func_id {
__BPF_FUNC_MAPPER(__BPF_ENUM_FN) __BPF_FUNC_MAX_ID,
@@ -595,6 +613,10 @@
};
#define __bpf_md_ptr(type,name) union { type name; __u64 : 64; \
} __attribute__((aligned(8)))
+enum {
+ BPF_SKB_TSTAMP_UNSPEC,
+ BPF_SKB_TSTAMP_DELIVERY_MONO,
+};
struct __sk_buff {
__u32 len;
__u32 pkt_type;
@@ -628,7 +650,8 @@
__u32 gso_segs;
__bpf_md_ptr(struct bpf_sock *, sk);
__u32 gso_size;
- __u32 : 32;
+ __u8 tstamp_type;
+ __u32 : 24;
__u64 hwtstamp;
};
struct bpf_tunnel_key {
@@ -641,6 +664,10 @@
__u8 tunnel_ttl;
__u16 tunnel_ext;
__u32 tunnel_label;
+ union {
+ __u32 local_ipv4;
+ __u32 local_ipv6[4];
+ };
};
struct bpf_xfrm_state {
__u32 reqid;
@@ -668,7 +695,8 @@
__u32 src_ip4;
__u32 src_ip6[4];
__u32 src_port;
- __u32 dst_port;
+ __be16 dst_port;
+ __u16 : 16;
__u32 dst_ip4;
__u32 dst_ip6[4];
__u32 state;
@@ -1134,6 +1162,10 @@
__u64 : 64;
__u64 : 64;
} __attribute__((aligned(8)));
+struct bpf_dynptr {
+ __u64 : 64;
+ __u64 : 64;
+} __attribute__((aligned(8)));
struct bpf_sysctl {
__u32 write;
__u32 file_pos;
@@ -1160,7 +1192,8 @@
__u32 protocol;
__u32 remote_ip4;
__u32 remote_ip6[4];
- __u32 remote_port;
+ __be16 remote_port;
+ __u16 : 16;
__u32 local_ip4;
__u32 local_ip6[4];
__u32 local_port;
diff --git a/libc/kernel/uapi/linux/btrfs.h b/libc/kernel/uapi/linux/btrfs.h
index 08b96a3..9f76d52 100644
--- a/libc/kernel/uapi/linux/btrfs.h
+++ b/libc/kernel/uapi/linux/btrfs.h
@@ -189,6 +189,7 @@
#define BTRFS_FEATURE_INCOMPAT_METADATA_UUID (1ULL << 10)
#define BTRFS_FEATURE_INCOMPAT_RAID1C34 (1ULL << 11)
#define BTRFS_FEATURE_INCOMPAT_ZONED (1ULL << 12)
+#define BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2 (1ULL << 13)
struct btrfs_ioctl_feature_flags {
__u64 compat_flags;
__u64 compat_ro_flags;
@@ -461,6 +462,29 @@
__u8 num_items;
__u8 align[7];
};
+struct btrfs_ioctl_encoded_io_args {
+ const struct iovec __user * iov;
+ unsigned long iovcnt;
+ __s64 offset;
+ __u64 flags;
+ __u64 len;
+ __u64 unencoded_len;
+ __u64 unencoded_offset;
+ __u32 compression;
+ __u32 encryption;
+ __u8 reserved[64];
+};
+#define BTRFS_ENCODED_IO_COMPRESSION_NONE 0
+#define BTRFS_ENCODED_IO_COMPRESSION_ZLIB 1
+#define BTRFS_ENCODED_IO_COMPRESSION_ZSTD 2
+#define BTRFS_ENCODED_IO_COMPRESSION_LZO_4K 3
+#define BTRFS_ENCODED_IO_COMPRESSION_LZO_8K 4
+#define BTRFS_ENCODED_IO_COMPRESSION_LZO_16K 5
+#define BTRFS_ENCODED_IO_COMPRESSION_LZO_32K 6
+#define BTRFS_ENCODED_IO_COMPRESSION_LZO_64K 7
+#define BTRFS_ENCODED_IO_COMPRESSION_TYPES 8
+#define BTRFS_ENCODED_IO_ENCRYPTION_NONE 0
+#define BTRFS_ENCODED_IO_ENCRYPTION_TYPES 1
enum btrfs_err_code {
BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET = 1,
BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET,
@@ -534,4 +558,6 @@
#define BTRFS_IOC_GET_SUBVOL_ROOTREF _IOWR(BTRFS_IOCTL_MAGIC, 61, struct btrfs_ioctl_get_subvol_rootref_args)
#define BTRFS_IOC_INO_LOOKUP_USER _IOWR(BTRFS_IOCTL_MAGIC, 62, struct btrfs_ioctl_ino_lookup_user_args)
#define BTRFS_IOC_SNAP_DESTROY_V2 _IOW(BTRFS_IOCTL_MAGIC, 63, struct btrfs_ioctl_vol_args_v2)
+#define BTRFS_IOC_ENCODED_READ _IOR(BTRFS_IOCTL_MAGIC, 64, struct btrfs_ioctl_encoded_io_args)
+#define BTRFS_IOC_ENCODED_WRITE _IOW(BTRFS_IOCTL_MAGIC, 64, struct btrfs_ioctl_encoded_io_args)
#endif
diff --git a/libc/kernel/uapi/linux/btrfs_tree.h b/libc/kernel/uapi/linux/btrfs_tree.h
index 0476733..02a9ae4 100644
--- a/libc/kernel/uapi/linux/btrfs_tree.h
+++ b/libc/kernel/uapi/linux/btrfs_tree.h
@@ -31,6 +31,7 @@
#define BTRFS_QUOTA_TREE_OBJECTID 8ULL
#define BTRFS_UUID_TREE_OBJECTID 9ULL
#define BTRFS_FREE_SPACE_TREE_OBJECTID 10ULL
+#define BTRFS_BLOCK_GROUP_TREE_OBJECTID 11ULL
#define BTRFS_DEV_STATS_OBJECTID 0ULL
#define BTRFS_BALANCE_OBJECTID - 4ULL
#define BTRFS_ORPHAN_OBJECTID - 5ULL
@@ -372,18 +373,6 @@
#define BTRFS_BLOCK_GROUP_RAID1C3 (1ULL << 9)
#define BTRFS_BLOCK_GROUP_RAID1C4 (1ULL << 10)
#define BTRFS_BLOCK_GROUP_RESERVED (BTRFS_AVAIL_ALLOC_BIT_SINGLE | BTRFS_SPACE_INFO_GLOBAL_RSV)
-enum btrfs_raid_types {
- BTRFS_RAID_RAID10,
- BTRFS_RAID_RAID1,
- BTRFS_RAID_DUP,
- BTRFS_RAID_RAID0,
- BTRFS_RAID_SINGLE,
- BTRFS_RAID_RAID5,
- BTRFS_RAID_RAID6,
- BTRFS_RAID_RAID1C3,
- BTRFS_RAID_RAID1C4,
- BTRFS_NR_RAID_TYPES
-};
#define BTRFS_BLOCK_GROUP_TYPE_MASK (BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_SYSTEM | BTRFS_BLOCK_GROUP_METADATA)
#define BTRFS_BLOCK_GROUP_PROFILE_MASK (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID1C3 | BTRFS_BLOCK_GROUP_RAID1C4 | BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6 | BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID10)
#define BTRFS_BLOCK_GROUP_RAID56_MASK (BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6)
diff --git a/libc/kernel/uapi/linux/cachefiles.h b/libc/kernel/uapi/linux/cachefiles.h
new file mode 100644
index 0000000..f5a58a5
--- /dev/null
+++ b/libc/kernel/uapi/linux/cachefiles.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_CACHEFILES_H
+#define _LINUX_CACHEFILES_H
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#define CACHEFILES_MSG_MAX_SIZE 1024
+enum cachefiles_opcode {
+ CACHEFILES_OP_OPEN,
+ CACHEFILES_OP_CLOSE,
+ CACHEFILES_OP_READ,
+};
+struct cachefiles_msg {
+ __u32 msg_id;
+ __u32 opcode;
+ __u32 len;
+ __u32 object_id;
+ __u8 data[];
+};
+struct cachefiles_open {
+ __u32 volume_key_size;
+ __u32 cookie_key_size;
+ __u32 fd;
+ __u32 flags;
+ __u8 data[];
+};
+struct cachefiles_read {
+ __u64 off;
+ __u64 len;
+};
+#define CACHEFILES_IOC_READ_COMPLETE _IOW(0x98, 1, int)
+#endif
diff --git a/libc/kernel/uapi/linux/can/isotp.h b/libc/kernel/uapi/linux/can/isotp.h
index dd5e4f5..f51aa59 100644
--- a/libc/kernel/uapi/linux/can/isotp.h
+++ b/libc/kernel/uapi/linux/can/isotp.h
@@ -44,26 +44,28 @@
__u8 tx_dl;
__u8 tx_flags;
};
-#define CAN_ISOTP_LISTEN_MODE 0x001
-#define CAN_ISOTP_EXTEND_ADDR 0x002
-#define CAN_ISOTP_TX_PADDING 0x004
-#define CAN_ISOTP_RX_PADDING 0x008
-#define CAN_ISOTP_CHK_PAD_LEN 0x010
-#define CAN_ISOTP_CHK_PAD_DATA 0x020
-#define CAN_ISOTP_HALF_DUPLEX 0x040
-#define CAN_ISOTP_FORCE_TXSTMIN 0x080
-#define CAN_ISOTP_FORCE_RXSTMIN 0x100
-#define CAN_ISOTP_RX_EXT_ADDR 0x200
-#define CAN_ISOTP_WAIT_TX_DONE 0x400
-#define CAN_ISOTP_SF_BROADCAST 0x800
+#define CAN_ISOTP_LISTEN_MODE 0x0001
+#define CAN_ISOTP_EXTEND_ADDR 0x0002
+#define CAN_ISOTP_TX_PADDING 0x0004
+#define CAN_ISOTP_RX_PADDING 0x0008
+#define CAN_ISOTP_CHK_PAD_LEN 0x0010
+#define CAN_ISOTP_CHK_PAD_DATA 0x0020
+#define CAN_ISOTP_HALF_DUPLEX 0x0040
+#define CAN_ISOTP_FORCE_TXSTMIN 0x0080
+#define CAN_ISOTP_FORCE_RXSTMIN 0x0100
+#define CAN_ISOTP_RX_EXT_ADDR 0x0200
+#define CAN_ISOTP_WAIT_TX_DONE 0x0400
+#define CAN_ISOTP_SF_BROADCAST 0x0800
+#define CAN_ISOTP_CF_BROADCAST 0x1000
#define CAN_ISOTP_DEFAULT_FLAGS 0
#define CAN_ISOTP_DEFAULT_EXT_ADDRESS 0x00
#define CAN_ISOTP_DEFAULT_PAD_CONTENT 0xCC
-#define CAN_ISOTP_DEFAULT_FRAME_TXTIME 0
+#define CAN_ISOTP_DEFAULT_FRAME_TXTIME 50000
#define CAN_ISOTP_DEFAULT_RECV_BS 0
#define CAN_ISOTP_DEFAULT_RECV_STMIN 0x00
#define CAN_ISOTP_DEFAULT_RECV_WFTMAX 0
#define CAN_ISOTP_DEFAULT_LL_MTU CAN_MTU
#define CAN_ISOTP_DEFAULT_LL_TX_DL CAN_MAX_DLEN
#define CAN_ISOTP_DEFAULT_LL_TX_FLAGS 0
+#define CAN_ISOTP_FRAME_TXTIME_ZERO 0xFFFFFFFF
#endif
diff --git a/libc/kernel/uapi/linux/counter.h b/libc/kernel/uapi/linux/counter.h
index 091e33d..4b86b28 100644
--- a/libc/kernel/uapi/linux/counter.h
+++ b/libc/kernel/uapi/linux/counter.h
@@ -45,6 +45,7 @@
COUNTER_EVENT_OVERFLOW_UNDERFLOW,
COUNTER_EVENT_THRESHOLD,
COUNTER_EVENT_INDEX,
+ COUNTER_EVENT_CHANGE_OF_STATE,
};
struct counter_watch {
struct counter_component component;
diff --git a/libc/kernel/uapi/linux/cxl_mem.h b/libc/kernel/uapi/linux/cxl_mem.h
index 15e9e29..578cefd 100644
--- a/libc/kernel/uapi/linux/cxl_mem.h
+++ b/libc/kernel/uapi/linux/cxl_mem.h
@@ -38,8 +38,8 @@
__u32 id;
__u32 flags;
#define CXL_MEM_COMMAND_FLAG_MASK GENMASK(0, 0)
- __s32 size_in;
- __s32 size_out;
+ __u32 size_in;
+ __u32 size_out;
};
struct cxl_mem_query_commands {
__u32 n_commands;
@@ -58,12 +58,12 @@
};
__u32 retval;
struct {
- __s32 size;
+ __u32 size;
__u32 rsvd;
__u64 payload;
} in;
struct {
- __s32 size;
+ __u32 size;
__u32 rsvd;
__u64 payload;
} out;
diff --git a/libc/kernel/uapi/linux/devlink.h b/libc/kernel/uapi/linux/devlink.h
index a809306..b45865e 100644
--- a/libc/kernel/uapi/linux/devlink.h
+++ b/libc/kernel/uapi/linux/devlink.h
@@ -103,6 +103,10 @@
DEVLINK_CMD_RATE_SET,
DEVLINK_CMD_RATE_NEW,
DEVLINK_CMD_RATE_DEL,
+ DEVLINK_CMD_LINECARD_GET,
+ DEVLINK_CMD_LINECARD_SET,
+ DEVLINK_CMD_LINECARD_NEW,
+ DEVLINK_CMD_LINECARD_DEL,
__DEVLINK_CMD_MAX,
DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1
};
@@ -212,6 +216,17 @@
DEVLINK_RELOAD_LIMIT_MAX = __DEVLINK_RELOAD_LIMIT_MAX - 1
};
#define DEVLINK_RELOAD_LIMITS_VALID_MASK (_BITUL(__DEVLINK_RELOAD_LIMIT_MAX) - 1)
+enum devlink_linecard_state {
+ DEVLINK_LINECARD_STATE_UNSPEC,
+ DEVLINK_LINECARD_STATE_UNPROVISIONED,
+ DEVLINK_LINECARD_STATE_UNPROVISIONING,
+ DEVLINK_LINECARD_STATE_PROVISIONING,
+ DEVLINK_LINECARD_STATE_PROVISIONING_FAILED,
+ DEVLINK_LINECARD_STATE_PROVISIONED,
+ DEVLINK_LINECARD_STATE_ACTIVE,
+ __DEVLINK_LINECARD_STATE_MAX,
+ DEVLINK_LINECARD_STATE_MAX = __DEVLINK_LINECARD_STATE_MAX - 1
+};
enum devlink_attr {
DEVLINK_ATTR_UNSPEC,
DEVLINK_ATTR_BUS_NAME,
@@ -384,6 +399,10 @@
DEVLINK_ATTR_RATE_NODE_NAME,
DEVLINK_ATTR_RATE_PARENT_NODE_NAME,
DEVLINK_ATTR_REGION_MAX_SNAPSHOTS,
+ DEVLINK_ATTR_LINECARD_INDEX,
+ DEVLINK_ATTR_LINECARD_STATE,
+ DEVLINK_ATTR_LINECARD_TYPE,
+ DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES,
__DEVLINK_ATTR_MAX,
DEVLINK_ATTR_MAX = __DEVLINK_ATTR_MAX - 1
};
diff --git a/libc/kernel/uapi/linux/dm-ioctl.h b/libc/kernel/uapi/linux/dm-ioctl.h
index 09f8a98..98cbc1f 100644
--- a/libc/kernel/uapi/linux/dm-ioctl.h
+++ b/libc/kernel/uapi/linux/dm-ioctl.h
@@ -106,9 +106,9 @@
#define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl)
#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 4
-#define DM_VERSION_MINOR 45
+#define DM_VERSION_MINOR 46
#define DM_VERSION_PATCHLEVEL 0
-#define DM_VERSION_EXTRA "-ioctl(2021-03-22)"
+#define DM_VERSION_EXTRA "-ioctl(2022-02-22)"
#define DM_READONLY_FLAG (1 << 0)
#define DM_SUSPEND_FLAG (1 << 1)
#define DM_PERSISTENT_DEV_FLAG (1 << 3)
diff --git a/libc/kernel/uapi/linux/dma-buf.h b/libc/kernel/uapi/linux/dma-buf.h
index 221c20f..4e31379 100644
--- a/libc/kernel/uapi/linux/dma-buf.h
+++ b/libc/kernel/uapi/linux/dma-buf.h
@@ -32,6 +32,6 @@
#define DMA_BUF_BASE 'b'
#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
#define DMA_BUF_SET_NAME _IOW(DMA_BUF_BASE, 1, const char *)
-#define DMA_BUF_SET_NAME_A _IOW(DMA_BUF_BASE, 1, u32)
-#define DMA_BUF_SET_NAME_B _IOW(DMA_BUF_BASE, 1, u64)
+#define DMA_BUF_SET_NAME_A _IOW(DMA_BUF_BASE, 1, __u32)
+#define DMA_BUF_SET_NAME_B _IOW(DMA_BUF_BASE, 1, __u64)
#endif
diff --git a/libc/kernel/uapi/linux/elf-em.h b/libc/kernel/uapi/linux/elf-em.h
index d1ed1f6..92da93d 100644
--- a/libc/kernel/uapi/linux/elf-em.h
+++ b/libc/kernel/uapi/linux/elf-em.h
@@ -61,6 +61,7 @@
#define EM_RISCV 243
#define EM_BPF 247
#define EM_CSKY 252
+#define EM_LOONGARCH 258
#define EM_FRV 0x5441
#define EM_ALPHA 0x9026
#define EM_CYGNUS_M32R 0x9041
diff --git a/libc/kernel/uapi/linux/elf.h b/libc/kernel/uapi/linux/elf.h
index 7655f12..35486fb 100644
--- a/libc/kernel/uapi/linux/elf.h
+++ b/libc/kernel/uapi/linux/elf.h
@@ -45,9 +45,11 @@
#define PT_HIOS 0x6fffffff
#define PT_LOPROC 0x70000000
#define PT_HIPROC 0x7fffffff
-#define PT_GNU_EH_FRAME 0x6474e550
-#define PT_GNU_PROPERTY 0x6474e553
+#define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550)
#define PT_GNU_STACK (PT_LOOS + 0x474e551)
+#define PT_GNU_RELRO (PT_LOOS + 0x474e552)
+#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
+#define PT_AARCH64_MEMTAG_MTE (PT_LOPROC + 0x2)
#define PN_XNUM 0xffff
#define ET_NONE 0
#define ET_REL 1
@@ -110,7 +112,7 @@
#define STT_COMMON 5
#define STT_TLS 6
#define ELF_ST_BIND(x) ((x) >> 4)
-#define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf)
+#define ELF_ST_TYPE(x) ((x) & 0xf)
#define ELF32_ST_BIND(x) ELF_ST_BIND(x)
#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x)
#define ELF64_ST_BIND(x) ELF_ST_BIND(x)
@@ -361,11 +363,18 @@
#define NT_ARM_PACG_KEYS 0x408
#define NT_ARM_TAGGED_ADDR_CTRL 0x409
#define NT_ARM_PAC_ENABLED_KEYS 0x40a
+#define NT_ARM_SSVE 0x40b
+#define NT_ARM_ZA 0x40c
#define NT_ARC_V2 0x600
#define NT_VMCOREDD 0x700
#define NT_MIPS_DSP 0x800
#define NT_MIPS_FP_MODE 0x801
#define NT_MIPS_MSA 0x802
+#define NT_LOONGARCH_CPUCFG 0xa00
+#define NT_LOONGARCH_CSR 0xa01
+#define NT_LOONGARCH_LSX 0xa02
+#define NT_LOONGARCH_LASX 0xa03
+#define NT_LOONGARCH_LBT 0xa04
#define NT_GNU_PROPERTY_TYPE_0 5
typedef struct elf32_note {
Elf32_Word n_namesz;
diff --git a/libc/kernel/uapi/linux/ethtool.h b/libc/kernel/uapi/linux/ethtool.h
index 741ea2a..c096f7f 100644
--- a/libc/kernel/uapi/linux/ethtool.h
+++ b/libc/kernel/uapi/linux/ethtool.h
@@ -704,6 +704,7 @@
ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT = 89,
ETHTOOL_LINK_MODE_100baseFX_Half_BIT = 90,
ETHTOOL_LINK_MODE_100baseFX_Full_BIT = 91,
+ ETHTOOL_LINK_MODE_10baseT1L_Full_BIT = 92,
__ETHTOOL_LINK_MODE_MASK_NBITS
};
#define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name) (1UL << (ETHTOOL_LINK_MODE_ ##base_name ##_BIT))
diff --git a/libc/kernel/uapi/linux/ethtool_netlink.h b/libc/kernel/uapi/linux/ethtool_netlink.h
index 7dcae22..85ce51b 100644
--- a/libc/kernel/uapi/linux/ethtool_netlink.h
+++ b/libc/kernel/uapi/linux/ethtool_netlink.h
@@ -240,6 +240,11 @@
ETHTOOL_A_PRIVFLAGS_MAX = __ETHTOOL_A_PRIVFLAGS_CNT - 1
};
enum {
+ ETHTOOL_TCP_DATA_SPLIT_UNKNOWN = 0,
+ ETHTOOL_TCP_DATA_SPLIT_DISABLED,
+ ETHTOOL_TCP_DATA_SPLIT_ENABLED,
+};
+enum {
ETHTOOL_A_RINGS_UNSPEC,
ETHTOOL_A_RINGS_HEADER,
ETHTOOL_A_RINGS_RX_MAX,
@@ -251,6 +256,9 @@
ETHTOOL_A_RINGS_RX_JUMBO,
ETHTOOL_A_RINGS_TX,
ETHTOOL_A_RINGS_RX_BUF_LEN,
+ ETHTOOL_A_RINGS_TCP_DATA_SPLIT,
+ ETHTOOL_A_RINGS_CQE_SIZE,
+ ETHTOOL_A_RINGS_TX_PUSH,
__ETHTOOL_A_RINGS_CNT,
ETHTOOL_A_RINGS_MAX = (__ETHTOOL_A_RINGS_CNT - 1)
};
diff --git a/libc/kernel/uapi/linux/fanotify.h b/libc/kernel/uapi/linux/fanotify.h
index 6249292..f4e2a2e 100644
--- a/libc/kernel/uapi/linux/fanotify.h
+++ b/libc/kernel/uapi/linux/fanotify.h
@@ -67,6 +67,7 @@
#define FAN_MARK_IGNORED_MASK 0x00000020
#define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040
#define FAN_MARK_FLUSH 0x00000080
+#define FAN_MARK_EVICTABLE 0x00000200
#define FAN_MARK_INODE 0x00000000
#define FAN_MARK_MOUNT 0x00000010
#define FAN_MARK_FILESYSTEM 0x00000100
diff --git a/libc/kernel/uapi/linux/fsi.h b/libc/kernel/uapi/linux/fsi.h
index fc88464..b080c21 100644
--- a/libc/kernel/uapi/linux/fsi.h
+++ b/libc/kernel/uapi/linux/fsi.h
@@ -48,4 +48,5 @@
#define FSI_SCOM_READ _IOWR('s', 0x01, struct scom_access)
#define FSI_SCOM_WRITE _IOWR('s', 0x02, struct scom_access)
#define FSI_SCOM_RESET _IOW('s', 0x03, __u32)
+#define FSI_SBEFIFO_READ_TIMEOUT_SECONDS _IOW('s', 0x00, __u32)
#endif
diff --git a/libc/kernel/uapi/linux/gpio.h b/libc/kernel/uapi/linux/gpio.h
index 7e010d9..e760321 100644
--- a/libc/kernel/uapi/linux/gpio.h
+++ b/libc/kernel/uapi/linux/gpio.h
@@ -42,6 +42,7 @@
GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN = _BITULL(9),
GPIO_V2_LINE_FLAG_BIAS_DISABLED = _BITULL(10),
GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME = _BITULL(11),
+ GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE = _BITULL(12),
};
struct gpio_v2_line_values {
__aligned_u64 bits;
diff --git a/libc/kernel/uapi/linux/gtp.h b/libc/kernel/uapi/linux/gtp.h
index 3b9416e..20bc3d6 100644
--- a/libc/kernel/uapi/linux/gtp.h
+++ b/libc/kernel/uapi/linux/gtp.h
@@ -23,6 +23,7 @@
GTP_CMD_NEWPDP,
GTP_CMD_DELPDP,
GTP_CMD_GETPDP,
+ GTP_CMD_ECHOREQ,
GTP_CMD_MAX,
};
enum gtp_version {
diff --git a/libc/kernel/uapi/linux/icmp.h b/libc/kernel/uapi/linux/icmp.h
index 8847a48..77cb328 100644
--- a/libc/kernel/uapi/linux/icmp.h
+++ b/libc/kernel/uapi/linux/icmp.h
@@ -84,7 +84,11 @@
} echo;
__be32 gateway;
struct {
+#ifdef __BIONIC__
__be16 __linux_unused;
+#else
+ __be16 __linux_unused;
+#endif
__be16 mtu;
} frag;
__u8 reserved[4];
diff --git a/libc/kernel/uapi/linux/idxd.h b/libc/kernel/uapi/linux/idxd.h
index ad9ed48..26f41ab 100644
--- a/libc/kernel/uapi/linux/idxd.h
+++ b/libc/kernel/uapi/linux/idxd.h
@@ -57,6 +57,11 @@
#define IDXD_OP_FLAG_DRDBK 0x4000
#define IDXD_OP_FLAG_DSTS 0x8000
#define IDXD_OP_FLAG_RD_SRC2_AECS 0x010000
+#define IDXD_OP_FLAG_RD_SRC2_2ND 0x020000
+#define IDXD_OP_FLAG_WR_SRC2_AECS_COMP 0x040000
+#define IDXD_OP_FLAG_WR_SRC2_AECS_OVFL 0x080000
+#define IDXD_OP_FLAG_SRC2_STS 0x100000
+#define IDXD_OP_FLAG_CRC_RFC3720 0x200000
enum dsa_opcode {
DSA_OPCODE_NOOP = 0,
DSA_OPCODE_BATCH,
@@ -82,6 +87,18 @@
IAX_OPCODE_MEMMOVE,
IAX_OPCODE_DECOMPRESS = 0x42,
IAX_OPCODE_COMPRESS,
+ IAX_OPCODE_CRC64,
+ IAX_OPCODE_ZERO_DECOMP_32 = 0x48,
+ IAX_OPCODE_ZERO_DECOMP_16,
+ IAX_OPCODE_DECOMP_32 = 0x4c,
+ IAX_OPCODE_DECOMP_16,
+ IAX_OPCODE_SCAN = 0x50,
+ IAX_OPCODE_SET_MEMBER,
+ IAX_OPCODE_EXTRACT,
+ IAX_OPCODE_SELECT,
+ IAX_OPCODE_RLE_BURST,
+ IAX_OPCDE_FIND_UNIQUE,
+ IAX_OPCODE_EXPAND,
};
enum dsa_completion_status {
DSA_COMP_NONE = 0,
@@ -118,6 +135,7 @@
IAX_COMP_NONE = 0,
IAX_COMP_SUCCESS,
IAX_COMP_PAGE_FAULT_IR = 0x04,
+ IAX_COMP_ANALYTICS_ERROR = 0x0a,
IAX_COMP_OUTBUF_OVERFLOW,
IAX_COMP_BAD_OPCODE = 0x10,
IAX_COMP_INVALID_FLAGS,
@@ -138,7 +156,10 @@
IAX_COMP_WATCHDOG,
IAX_COMP_INVALID_COMP_FLAG = 0x30,
IAX_COMP_INVALID_FILTER_FLAG,
- IAX_COMP_INVALID_NUM_ELEMS = 0x33,
+ IAX_COMP_INVALID_INPUT_SIZE,
+ IAX_COMP_INVALID_NUM_ELEMS,
+ IAX_COMP_INVALID_SRC1_WIDTH,
+ IAX_COMP_INVALID_INVERT_OUT,
};
#define DSA_COMP_STATUS_MASK 0x7f
#define DSA_COMP_STATUS_WRITE 0x80
@@ -291,8 +312,12 @@
uint32_t output_size;
uint8_t output_bits;
uint8_t rsvd3;
- uint16_t rsvd4;
- uint64_t rsvd5[4];
+ uint16_t xor_csum;
+ uint32_t crc;
+ uint32_t min;
+ uint32_t max;
+ uint32_t sum;
+ uint64_t rsvd4[2];
} __attribute__((packed));
struct iax_raw_completion_record {
uint64_t field[8];
diff --git a/libc/kernel/uapi/linux/if_addr.h b/libc/kernel/uapi/linux/if_addr.h
index 6a6b640..a225e69 100644
--- a/libc/kernel/uapi/linux/if_addr.h
+++ b/libc/kernel/uapi/linux/if_addr.h
@@ -39,6 +39,7 @@
IFA_FLAGS,
IFA_RT_PRIORITY,
IFA_TARGET_NETNSID,
+ IFA_PROTO,
__IFA_MAX,
};
#define IFA_MAX (__IFA_MAX - 1)
@@ -63,4 +64,8 @@
};
#define IFA_RTA(r) ((struct rtattr *) (((char *) (r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct ifaddrmsg))
+#define IFAPROT_UNSPEC 0
+#define IFAPROT_KERNEL_LO 1
+#define IFAPROT_KERNEL_RA 2
+#define IFAPROT_KERNEL_LL 3
#endif
diff --git a/libc/kernel/uapi/linux/if_bridge.h b/libc/kernel/uapi/linux/if_bridge.h
index 2054fb3..0f08866 100644
--- a/libc/kernel/uapi/linux/if_bridge.h
+++ b/libc/kernel/uapi/linux/if_bridge.h
@@ -108,6 +108,7 @@
IFLA_BRIDGE_VLAN_TUNNEL_INFO,
IFLA_BRIDGE_MRP,
IFLA_BRIDGE_CFM,
+ IFLA_BRIDGE_MST,
__IFLA_BRIDGE_MAX,
};
#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
@@ -384,6 +385,19 @@
__IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX,
};
#define IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX (__IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX - 1)
+enum {
+ IFLA_BRIDGE_MST_UNSPEC,
+ IFLA_BRIDGE_MST_ENTRY,
+ __IFLA_BRIDGE_MST_MAX,
+};
+#define IFLA_BRIDGE_MST_MAX (__IFLA_BRIDGE_MST_MAX - 1)
+enum {
+ IFLA_BRIDGE_MST_ENTRY_UNSPEC,
+ IFLA_BRIDGE_MST_ENTRY_MSTI,
+ IFLA_BRIDGE_MST_ENTRY_STATE,
+ __IFLA_BRIDGE_MST_ENTRY_MAX,
+};
+#define IFLA_BRIDGE_MST_ENTRY_MAX (__IFLA_BRIDGE_MST_ENTRY_MAX - 1)
struct bridge_stp_xstats {
__u64 transition_blk;
__u64 transition_fwd;
@@ -460,6 +474,7 @@
BRIDGE_VLANDB_GOPTS_MCAST_QUERIER,
BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS,
BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE,
+ BRIDGE_VLANDB_GOPTS_MSTI,
__BRIDGE_VLANDB_GOPTS_MAX
};
#define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1)
@@ -599,6 +614,7 @@
enum br_boolopt_id {
BR_BOOLOPT_NO_LL_LEARN,
BR_BOOLOPT_MCAST_VLAN_SNOOPING,
+ BR_BOOLOPT_MST_ENABLE,
BR_BOOLOPT_MAX
};
struct br_boolopt_multi {
diff --git a/libc/kernel/uapi/linux/if_ether.h b/libc/kernel/uapi/linux/if_ether.h
index 1f7f8f2..bd8e045 100644
--- a/libc/kernel/uapi/linux/if_ether.h
+++ b/libc/kernel/uapi/linux/if_ether.h
@@ -67,8 +67,10 @@
#define ETH_P_LINK_CTL 0x886c
#define ETH_P_ATMFATE 0x8884
#define ETH_P_PAE 0x888E
+#define ETH_P_PROFINET 0x8892
#define ETH_P_REALTEK 0x8899
#define ETH_P_AOE 0x88A2
+#define ETH_P_ETHERCAT 0x88A4
#define ETH_P_8021AD 0x88A8
#define ETH_P_802_EX1 0x88B5
#define ETH_P_PREAUTH 0x88C7
diff --git a/libc/kernel/uapi/linux/if_link.h b/libc/kernel/uapi/linux/if_link.h
index 7e413ae..fbe384e 100644
--- a/libc/kernel/uapi/linux/if_link.h
+++ b/libc/kernel/uapi/linux/if_link.h
@@ -71,6 +71,18 @@
__u64 rx_compressed;
__u64 tx_compressed;
__u64 rx_nohandler;
+ __u64 rx_otherhost_dropped;
+};
+struct rtnl_hw_stats64 {
+ __u64 rx_packets;
+ __u64 tx_packets;
+ __u64 rx_bytes;
+ __u64 tx_bytes;
+ __u64 rx_errors;
+ __u64 tx_errors;
+ __u64 rx_dropped;
+ __u64 tx_dropped;
+ __u64 multicast;
};
struct rtnl_link_ifmap {
__u64 mem_start;
@@ -151,6 +163,8 @@
IFLA_PARENT_DEV_NAME,
IFLA_PARENT_DEV_BUS_NAME,
IFLA_GRO_MAX_SIZE,
+ IFLA_TSO_MAX_SIZE,
+ IFLA_TSO_MAX_SEGS,
__IFLA_MAX
};
#define IFLA_MAX (__IFLA_MAX - 1)
@@ -289,6 +303,7 @@
IFLA_BRPORT_MRP_IN_OPEN,
IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT,
IFLA_BRPORT_MCAST_EHT_HOSTS_CNT,
+ IFLA_BRPORT_LOCKED,
__IFLA_BRPORT_MAX
};
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
@@ -428,6 +443,44 @@
};
#define IPVLAN_F_PRIVATE 0x01
#define IPVLAN_F_VEPA 0x02
+struct tunnel_msg {
+ __u8 family;
+ __u8 flags;
+ __u16 reserved2;
+ __u32 ifindex;
+};
+#define TUNNEL_MSG_FLAG_STATS 0x01
+#define TUNNEL_MSG_VALID_USER_FLAGS TUNNEL_MSG_FLAG_STATS
+enum {
+ VNIFILTER_ENTRY_STATS_UNSPEC,
+ VNIFILTER_ENTRY_STATS_RX_BYTES,
+ VNIFILTER_ENTRY_STATS_RX_PKTS,
+ VNIFILTER_ENTRY_STATS_RX_DROPS,
+ VNIFILTER_ENTRY_STATS_RX_ERRORS,
+ VNIFILTER_ENTRY_STATS_TX_BYTES,
+ VNIFILTER_ENTRY_STATS_TX_PKTS,
+ VNIFILTER_ENTRY_STATS_TX_DROPS,
+ VNIFILTER_ENTRY_STATS_TX_ERRORS,
+ VNIFILTER_ENTRY_STATS_PAD,
+ __VNIFILTER_ENTRY_STATS_MAX
+};
+#define VNIFILTER_ENTRY_STATS_MAX (__VNIFILTER_ENTRY_STATS_MAX - 1)
+enum {
+ VXLAN_VNIFILTER_ENTRY_UNSPEC,
+ VXLAN_VNIFILTER_ENTRY_START,
+ VXLAN_VNIFILTER_ENTRY_END,
+ VXLAN_VNIFILTER_ENTRY_GROUP,
+ VXLAN_VNIFILTER_ENTRY_GROUP6,
+ VXLAN_VNIFILTER_ENTRY_STATS,
+ __VXLAN_VNIFILTER_ENTRY_MAX
+};
+#define VXLAN_VNIFILTER_ENTRY_MAX (__VXLAN_VNIFILTER_ENTRY_MAX - 1)
+enum {
+ VXLAN_VNIFILTER_UNSPEC,
+ VXLAN_VNIFILTER_ENTRY,
+ __VXLAN_VNIFILTER_MAX
+};
+#define VXLAN_VNIFILTER_MAX (__VXLAN_VNIFILTER_MAX - 1)
enum {
IFLA_VXLAN_UNSPEC,
IFLA_VXLAN_ID,
@@ -459,6 +512,7 @@
IFLA_VXLAN_GPE,
IFLA_VXLAN_TTL_INHERIT,
IFLA_VXLAN_DF,
+ IFLA_VXLAN_VNIFILTER,
__IFLA_VXLAN_MAX
};
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
@@ -488,6 +542,7 @@
IFLA_GENEVE_LABEL,
IFLA_GENEVE_TTL_INHERIT,
IFLA_GENEVE_DF,
+ IFLA_GENEVE_INNER_PROTO_INHERIT,
__IFLA_GENEVE_MAX
};
#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
@@ -523,6 +578,8 @@
IFLA_GTP_FD1,
IFLA_GTP_PDP_HASHSIZE,
IFLA_GTP_ROLE,
+ IFLA_GTP_CREATE_SOCKETS,
+ IFLA_GTP_RESTART_COUNT,
__IFLA_GTP_MAX,
};
#define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)
@@ -558,6 +615,7 @@
IFLA_BOND_PEER_NOTIF_DELAY,
IFLA_BOND_AD_LACP_ACTIVE,
IFLA_BOND_MISSED_MAX,
+ IFLA_BOND_NS_IP6_TARGET,
__IFLA_BOND_MAX,
};
#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1)
@@ -777,6 +835,13 @@
#define IFLA_STATS_MAX (__IFLA_STATS_MAX - 1)
#define IFLA_STATS_FILTER_BIT(ATTR) (1 << (ATTR - 1))
enum {
+ IFLA_STATS_GETSET_UNSPEC,
+ IFLA_STATS_GET_FILTERS,
+ IFLA_STATS_SET_OFFLOAD_XSTATS_L3_STATS,
+ __IFLA_STATS_GETSET_MAX,
+};
+#define IFLA_STATS_GETSET_MAX (__IFLA_STATS_GETSET_MAX - 1)
+enum {
LINK_XSTATS_TYPE_UNSPEC,
LINK_XSTATS_TYPE_BRIDGE,
LINK_XSTATS_TYPE_BOND,
@@ -786,9 +851,18 @@
enum {
IFLA_OFFLOAD_XSTATS_UNSPEC,
IFLA_OFFLOAD_XSTATS_CPU_HIT,
+ IFLA_OFFLOAD_XSTATS_HW_S_INFO,
+ IFLA_OFFLOAD_XSTATS_L3_STATS,
__IFLA_OFFLOAD_XSTATS_MAX
};
#define IFLA_OFFLOAD_XSTATS_MAX (__IFLA_OFFLOAD_XSTATS_MAX - 1)
+enum {
+ IFLA_OFFLOAD_XSTATS_HW_S_INFO_UNSPEC,
+ IFLA_OFFLOAD_XSTATS_HW_S_INFO_REQUEST,
+ IFLA_OFFLOAD_XSTATS_HW_S_INFO_USED,
+ __IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX,
+};
+#define IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX (__IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX - 1)
#define XDP_FLAGS_UPDATE_IF_NOEXIST (1U << 0)
#define XDP_FLAGS_SKB_MODE (1U << 1)
#define XDP_FLAGS_DRV_MODE (1U << 2)
diff --git a/libc/kernel/uapi/linux/if_tunnel.h b/libc/kernel/uapi/linux/if_tunnel.h
index 8e1847f..01c2dc9 100644
--- a/libc/kernel/uapi/linux/if_tunnel.h
+++ b/libc/kernel/uapi/linux/if_tunnel.h
@@ -169,5 +169,6 @@
#define TUNNEL_VXLAN_OPT __cpu_to_be16(0x1000)
#define TUNNEL_NOCACHE __cpu_to_be16(0x2000)
#define TUNNEL_ERSPAN_OPT __cpu_to_be16(0x4000)
-#define TUNNEL_OPTIONS_PRESENT (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT | TUNNEL_ERSPAN_OPT)
+#define TUNNEL_GTP_OPT __cpu_to_be16(0x8000)
+#define TUNNEL_OPTIONS_PRESENT (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT | TUNNEL_ERSPAN_OPT | TUNNEL_GTP_OPT)
#endif
diff --git a/libc/kernel/uapi/linux/iio/types.h b/libc/kernel/uapi/linux/iio/types.h
index 22409a7..aa66d50 100644
--- a/libc/kernel/uapi/linux/iio/types.h
+++ b/libc/kernel/uapi/linux/iio/types.h
@@ -109,6 +109,7 @@
IIO_EV_TYPE_THRESH_ADAPTIVE,
IIO_EV_TYPE_MAG_ADAPTIVE,
IIO_EV_TYPE_CHANGE,
+ IIO_EV_TYPE_MAG_REFERENCED,
};
enum iio_event_direction {
IIO_EV_DIR_EITHER,
diff --git a/libc/kernel/uapi/linux/input-event-codes.h b/libc/kernel/uapi/linux/input-event-codes.h
index 34cd23c..4b251df 100644
--- a/libc/kernel/uapi/linux/input-event-codes.h
+++ b/libc/kernel/uapi/linux/input-event-codes.h
@@ -580,6 +580,21 @@
#define KEY_ONSCREEN_KEYBOARD 0x278
#define KEY_PRIVACY_SCREEN_TOGGLE 0x279
#define KEY_SELECTIVE_SCREENSHOT 0x27a
+#define KEY_NEXT_ELEMENT 0x27b
+#define KEY_PREVIOUS_ELEMENT 0x27c
+#define KEY_AUTOPILOT_ENGAGE_TOGGLE 0x27d
+#define KEY_MARK_WAYPOINT 0x27e
+#define KEY_SOS 0x27f
+#define KEY_NAV_CHART 0x280
+#define KEY_FISHING_CHART 0x281
+#define KEY_SINGLE_RANGE_RADAR 0x282
+#define KEY_DUAL_RANGE_RADAR 0x283
+#define KEY_RADAR_OVERLAY 0x284
+#define KEY_TRADITIONAL_SONAR 0x285
+#define KEY_CLEARVU_SONAR 0x286
+#define KEY_SIDEVU_SONAR 0x287
+#define KEY_NAV_INFO 0x288
+#define KEY_BRIGHTNESS_MENU 0x289
#define KEY_MACRO1 0x290
#define KEY_MACRO2 0x291
#define KEY_MACRO3 0x292
diff --git a/libc/kernel/uapi/linux/input.h b/libc/kernel/uapi/linux/input.h
index fe17226..4858c81 100644
--- a/libc/kernel/uapi/linux/input.h
+++ b/libc/kernel/uapi/linux/input.h
@@ -125,6 +125,7 @@
#define BUS_RMI 0x1D
#define BUS_CEC 0x1E
#define BUS_INTEL_ISHTP 0x1F
+#define BUS_AMD_SFH 0x20
#define MT_TOOL_FINGER 0x00
#define MT_TOOL_PEN 0x01
#define MT_TOOL_PALM 0x02
diff --git a/libc/kernel/uapi/linux/io_uring.h b/libc/kernel/uapi/linux/io_uring.h
index 96944f8..5dda702 100644
--- a/libc/kernel/uapi/linux/io_uring.h
+++ b/libc/kernel/uapi/linux/io_uring.h
@@ -28,6 +28,10 @@
union {
__u64 off;
__u64 addr2;
+ struct {
+ __u32 cmd_op;
+ __u32 __pad1;
+ };
};
union {
__u64 addr;
@@ -51,6 +55,7 @@
__u32 rename_flags;
__u32 unlink_flags;
__u32 hardlink_flags;
+ __u32 xattr_flags;
};
__u64 user_data;
union {
@@ -62,8 +67,15 @@
__s32 splice_fd_in;
__u32 file_index;
};
- __u64 __pad2[2];
+ union {
+ struct {
+ __u64 addr3;
+ __u64 __pad2[1];
+ };
+ __u8 cmd[0];
+ };
};
+#define IORING_FILE_INDEX_ALLOC (~0U)
enum {
IOSQE_FIXED_FILE_BIT,
IOSQE_IO_DRAIN_BIT,
@@ -87,7 +99,12 @@
#define IORING_SETUP_CLAMP (1U << 4)
#define IORING_SETUP_ATTACH_WQ (1U << 5)
#define IORING_SETUP_R_DISABLED (1U << 6)
-enum {
+#define IORING_SETUP_SUBMIT_ALL (1U << 7)
+#define IORING_SETUP_COOP_TASKRUN (1U << 8)
+#define IORING_SETUP_TASKRUN_FLAG (1U << 9)
+#define IORING_SETUP_SQE128 (1U << 10)
+#define IORING_SETUP_CQE32 (1U << 11)
+enum io_uring_op {
IORING_OP_NOP,
IORING_OP_READV,
IORING_OP_WRITEV,
@@ -128,6 +145,13 @@
IORING_OP_MKDIRAT,
IORING_OP_SYMLINKAT,
IORING_OP_LINKAT,
+ IORING_OP_MSG_RING,
+ IORING_OP_FSETXATTR,
+ IORING_OP_SETXATTR,
+ IORING_OP_FGETXATTR,
+ IORING_OP_GETXATTR,
+ IORING_OP_SOCKET,
+ IORING_OP_URING_CMD,
IORING_OP_LAST,
};
#define IORING_FSYNC_DATASYNC (1U << 0)
@@ -143,13 +167,20 @@
#define IORING_POLL_ADD_MULTI (1U << 0)
#define IORING_POLL_UPDATE_EVENTS (1U << 1)
#define IORING_POLL_UPDATE_USER_DATA (1U << 2)
+#define IORING_ASYNC_CANCEL_ALL (1U << 0)
+#define IORING_ASYNC_CANCEL_FD (1U << 1)
+#define IORING_ASYNC_CANCEL_ANY (1U << 2)
+#define IORING_RECVSEND_POLL_FIRST (1U << 0)
+#define IORING_ACCEPT_MULTISHOT (1U << 0)
struct io_uring_cqe {
__u64 user_data;
__s32 res;
__u32 flags;
+ __u64 big_cqe[];
};
#define IORING_CQE_F_BUFFER (1U << 0)
#define IORING_CQE_F_MORE (1U << 1)
+#define IORING_CQE_F_SOCK_NONEMPTY (1U << 2)
enum {
IORING_CQE_BUFFER_SHIFT = 16,
};
@@ -169,6 +200,7 @@
};
#define IORING_SQ_NEED_WAKEUP (1U << 0)
#define IORING_SQ_CQ_OVERFLOW (1U << 1)
+#define IORING_SQ_TASKRUN (1U << 2)
struct io_cqring_offsets {
__u32 head;
__u32 tail;
@@ -185,6 +217,7 @@
#define IORING_ENTER_SQ_WAKEUP (1U << 1)
#define IORING_ENTER_SQ_WAIT (1U << 2)
#define IORING_ENTER_EXT_ARG (1U << 3)
+#define IORING_ENTER_REGISTERED_RING (1U << 4)
struct io_uring_params {
__u32 sq_entries;
__u32 cq_entries;
@@ -209,6 +242,7 @@
#define IORING_FEAT_NATIVE_WORKERS (1U << 9)
#define IORING_FEAT_RSRC_TAGS (1U << 10)
#define IORING_FEAT_CQE_SKIP (1U << 11)
+#define IORING_FEAT_LINKED_FILE (1U << 12)
enum {
IORING_REGISTER_BUFFERS = 0,
IORING_UNREGISTER_BUFFERS = 1,
@@ -230,6 +264,10 @@
IORING_REGISTER_IOWQ_AFF = 17,
IORING_UNREGISTER_IOWQ_AFF = 18,
IORING_REGISTER_IOWQ_MAX_WORKERS = 19,
+ IORING_REGISTER_RING_FDS = 20,
+ IORING_UNREGISTER_RING_FDS = 21,
+ IORING_REGISTER_PBUF_RING = 22,
+ IORING_UNREGISTER_PBUF_RING = 23,
IORING_REGISTER_LAST
};
enum {
@@ -241,9 +279,10 @@
__u32 resv;
__aligned_u64 fds;
};
+#define IORING_RSRC_REGISTER_SPARSE (1U << 0)
struct io_uring_rsrc_register {
__u32 nr;
- __u32 resv;
+ __u32 flags;
__u64 resv2;
__aligned_u64 data;
__aligned_u64 tags;
@@ -286,6 +325,30 @@
__u8 resv;
__u32 resv2[3];
};
+struct io_uring_buf {
+ __u64 addr;
+ __u32 len;
+ __u16 bid;
+ __u16 resv;
+};
+struct io_uring_buf_ring {
+ union {
+ struct {
+ __u64 resv1;
+ __u32 resv2;
+ __u16 resv3;
+ __u16 tail;
+ };
+ struct io_uring_buf bufs[0];
+ };
+};
+struct io_uring_buf_reg {
+ __u64 ring_addr;
+ __u32 ring_entries;
+ __u16 bgid;
+ __u16 pad;
+ __u64 resv[3];
+};
enum {
IORING_RESTRICTION_REGISTER_OP = 0,
IORING_RESTRICTION_SQE_OP = 1,
diff --git a/libc/kernel/uapi/linux/ioam6_iptunnel.h b/libc/kernel/uapi/linux/ioam6_iptunnel.h
index 7426225..ec1a6a8 100644
--- a/libc/kernel/uapi/linux/ioam6_iptunnel.h
+++ b/libc/kernel/uapi/linux/ioam6_iptunnel.h
@@ -32,6 +32,10 @@
IOAM6_IPTUNNEL_MODE,
IOAM6_IPTUNNEL_DST,
IOAM6_IPTUNNEL_TRACE,
+#define IOAM6_IPTUNNEL_FREQ_MIN 1
+#define IOAM6_IPTUNNEL_FREQ_MAX 1000000
+ IOAM6_IPTUNNEL_FREQ_K,
+ IOAM6_IPTUNNEL_FREQ_N,
__IOAM6_IPTUNNEL_MAX,
};
#define IOAM6_IPTUNNEL_MAX (__IOAM6_IPTUNNEL_MAX - 1)
diff --git a/libc/kernel/uapi/linux/iommu.h b/libc/kernel/uapi/linux/iommu.h
index 0a0af92..0304a32 100644
--- a/libc/kernel/uapi/linux/iommu.h
+++ b/libc/kernel/uapi/linux/iommu.h
@@ -85,76 +85,4 @@
__u32 grpid;
__u32 code;
};
-enum iommu_inv_granularity {
- IOMMU_INV_GRANU_DOMAIN,
- IOMMU_INV_GRANU_PASID,
- IOMMU_INV_GRANU_ADDR,
- IOMMU_INV_GRANU_NR,
-};
-struct iommu_inv_addr_info {
-#define IOMMU_INV_ADDR_FLAGS_PASID (1 << 0)
-#define IOMMU_INV_ADDR_FLAGS_ARCHID (1 << 1)
-#define IOMMU_INV_ADDR_FLAGS_LEAF (1 << 2)
- __u32 flags;
- __u32 archid;
- __u64 pasid;
- __u64 addr;
- __u64 granule_size;
- __u64 nb_granules;
-};
-struct iommu_inv_pasid_info {
-#define IOMMU_INV_PASID_FLAGS_PASID (1 << 0)
-#define IOMMU_INV_PASID_FLAGS_ARCHID (1 << 1)
- __u32 flags;
- __u32 archid;
- __u64 pasid;
-};
-struct iommu_cache_invalidate_info {
- __u32 argsz;
-#define IOMMU_CACHE_INVALIDATE_INFO_VERSION_1 1
- __u32 version;
-#define IOMMU_CACHE_INV_TYPE_IOTLB (1 << 0)
-#define IOMMU_CACHE_INV_TYPE_DEV_IOTLB (1 << 1)
-#define IOMMU_CACHE_INV_TYPE_PASID (1 << 2)
-#define IOMMU_CACHE_INV_TYPE_NR (3)
- __u8 cache;
- __u8 granularity;
- __u8 padding[6];
- union {
- struct iommu_inv_pasid_info pasid_info;
- struct iommu_inv_addr_info addr_info;
- } granu;
-};
-struct iommu_gpasid_bind_data_vtd {
-#define IOMMU_SVA_VTD_GPASID_SRE (1 << 0)
-#define IOMMU_SVA_VTD_GPASID_EAFE (1 << 1)
-#define IOMMU_SVA_VTD_GPASID_PCD (1 << 2)
-#define IOMMU_SVA_VTD_GPASID_PWT (1 << 3)
-#define IOMMU_SVA_VTD_GPASID_EMTE (1 << 4)
-#define IOMMU_SVA_VTD_GPASID_CD (1 << 5)
-#define IOMMU_SVA_VTD_GPASID_WPE (1 << 6)
-#define IOMMU_SVA_VTD_GPASID_LAST (1 << 7)
- __u64 flags;
- __u32 pat;
- __u32 emt;
-};
-#define IOMMU_SVA_VTD_GPASID_MTS_MASK (IOMMU_SVA_VTD_GPASID_CD | IOMMU_SVA_VTD_GPASID_EMTE | IOMMU_SVA_VTD_GPASID_PCD | IOMMU_SVA_VTD_GPASID_PWT)
-struct iommu_gpasid_bind_data {
- __u32 argsz;
-#define IOMMU_GPASID_BIND_VERSION_1 1
- __u32 version;
-#define IOMMU_PASID_FORMAT_INTEL_VTD 1
-#define IOMMU_PASID_FORMAT_LAST 2
- __u32 format;
- __u32 addr_width;
-#define IOMMU_SVA_GPASID_VAL (1 << 0)
- __u64 flags;
- __u64 gpgd;
- __u64 hpasid;
- __u64 gpasid;
- __u8 padding[8];
- union {
- struct iommu_gpasid_bind_data_vtd vtd;
- } vendor;
-};
#endif
diff --git a/libc/kernel/uapi/linux/ipv6.h b/libc/kernel/uapi/linux/ipv6.h
index b3db9ce..757cbda 100644
--- a/libc/kernel/uapi/linux/ipv6.h
+++ b/libc/kernel/uapi/linux/ipv6.h
@@ -148,6 +148,7 @@
DEVCONF_IOAM6_ID,
DEVCONF_IOAM6_ID_WIDE,
DEVCONF_NDISC_EVICT_NOCARRIER,
+ DEVCONF_ACCEPT_UNTRACKED_NA,
DEVCONF_MAX
};
#endif
diff --git a/libc/kernel/uapi/linux/kexec.h b/libc/kernel/uapi/linux/kexec.h
index 2e3bd0c..438c07b 100644
--- a/libc/kernel/uapi/linux/kexec.h
+++ b/libc/kernel/uapi/linux/kexec.h
@@ -40,11 +40,12 @@
#define KEXEC_ARCH_MIPS (8 << 16)
#define KEXEC_ARCH_AARCH64 (183 << 16)
#define KEXEC_ARCH_RISCV (243 << 16)
+#define KEXEC_ARCH_LOONGARCH (258 << 16)
#define KEXEC_SEGMENT_MAX 16
struct kexec_segment {
const void * buf;
- size_t bufsz;
+ __kernel_size_t bufsz;
const void * mem;
- size_t memsz;
+ __kernel_size_t memsz;
};
#endif
diff --git a/libc/kernel/uapi/linux/kfd_ioctl.h b/libc/kernel/uapi/linux/kfd_ioctl.h
index c52ac64..8ec47f4 100644
--- a/libc/kernel/uapi/linux/kfd_ioctl.h
+++ b/libc/kernel/uapi/linux/kfd_ioctl.h
@@ -21,7 +21,7 @@
#include <drm/drm.h>
#include <linux/ioctl.h>
#define KFD_IOCTL_MAJOR_VERSION 1
-#define KFD_IOCTL_MINOR_VERSION 6
+#define KFD_IOCTL_MINOR_VERSION 8
struct kfd_ioctl_get_version_args {
__u32 major_version;
__u32 minor_version;
@@ -132,6 +132,7 @@
__u32 gpu_id;
__u32 buf_size_in_bytes;
};
+#define KFD_INVALID_FD 0xffffffff
#define KFD_IOC_EVENT_SIGNAL 0
#define KFD_IOC_EVENT_NODECHANGE 1
#define KFD_IOC_EVENT_DEVICESTATECHANGE 2
@@ -296,10 +297,45 @@
KFD_SMI_EVENT_GPU_POST_RESET = 4,
};
#define KFD_SMI_EVENT_MASK_FROM_INDEX(i) (1ULL << ((i) - 1))
+#define KFD_SMI_EVENT_MSG_SIZE 96
struct kfd_ioctl_smi_events_args {
__u32 gpuid;
__u32 anon_fd;
};
+enum kfd_criu_op {
+ KFD_CRIU_OP_PROCESS_INFO,
+ KFD_CRIU_OP_CHECKPOINT,
+ KFD_CRIU_OP_UNPAUSE,
+ KFD_CRIU_OP_RESTORE,
+ KFD_CRIU_OP_RESUME,
+};
+struct kfd_ioctl_criu_args {
+ __u64 devices;
+ __u64 bos;
+ __u64 priv_data;
+ __u64 priv_data_size;
+ __u32 num_devices;
+ __u32 num_bos;
+ __u32 num_objects;
+ __u32 pid;
+ __u32 op;
+};
+struct kfd_criu_device_bucket {
+ __u32 user_gpu_id;
+ __u32 actual_gpu_id;
+ __u32 drm_fd;
+ __u32 pad;
+};
+struct kfd_criu_bo_bucket {
+ __u64 addr;
+ __u64 size;
+ __u64 offset;
+ __u64 restored_offset;
+ __u32 gpu_id;
+ __u32 alloc_flags;
+ __u32 dmabuf_fd;
+ __u32 pad;
+};
enum kfd_mmio_remap {
KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL = 0,
KFD_MMIO_REMAP_HDP_REG_FLUSH_CNTL = 4,
@@ -337,7 +373,7 @@
__u64 size;
__u32 op;
__u32 nattr;
- struct kfd_ioctl_svm_attribute attrs[0];
+ struct kfd_ioctl_svm_attribute attrs[];
};
struct kfd_ioctl_set_xnack_mode_args {
__s32 xnack_enabled;
@@ -359,10 +395,10 @@
#define AMDKFD_IOC_SET_EVENT AMDKFD_IOW(0x0A, struct kfd_ioctl_set_event_args)
#define AMDKFD_IOC_RESET_EVENT AMDKFD_IOW(0x0B, struct kfd_ioctl_reset_event_args)
#define AMDKFD_IOC_WAIT_EVENTS AMDKFD_IOWR(0x0C, struct kfd_ioctl_wait_events_args)
-#define AMDKFD_IOC_DBG_REGISTER AMDKFD_IOW(0x0D, struct kfd_ioctl_dbg_register_args)
-#define AMDKFD_IOC_DBG_UNREGISTER AMDKFD_IOW(0x0E, struct kfd_ioctl_dbg_unregister_args)
-#define AMDKFD_IOC_DBG_ADDRESS_WATCH AMDKFD_IOW(0x0F, struct kfd_ioctl_dbg_address_watch_args)
-#define AMDKFD_IOC_DBG_WAVE_CONTROL AMDKFD_IOW(0x10, struct kfd_ioctl_dbg_wave_control_args)
+#define AMDKFD_IOC_DBG_REGISTER_DEPRECATED AMDKFD_IOW(0x0D, struct kfd_ioctl_dbg_register_args)
+#define AMDKFD_IOC_DBG_UNREGISTER_DEPRECATED AMDKFD_IOW(0x0E, struct kfd_ioctl_dbg_unregister_args)
+#define AMDKFD_IOC_DBG_ADDRESS_WATCH_DEPRECATED AMDKFD_IOW(0x0F, struct kfd_ioctl_dbg_address_watch_args)
+#define AMDKFD_IOC_DBG_WAVE_CONTROL_DEPRECATED AMDKFD_IOW(0x10, struct kfd_ioctl_dbg_wave_control_args)
#define AMDKFD_IOC_SET_SCRATCH_BACKING_VA AMDKFD_IOWR(0x11, struct kfd_ioctl_set_scratch_backing_va_args)
#define AMDKFD_IOC_GET_TILE_CONFIG AMDKFD_IOWR(0x12, struct kfd_ioctl_get_tile_config_args)
#define AMDKFD_IOC_SET_TRAP_HANDLER AMDKFD_IOW(0x13, struct kfd_ioctl_set_trap_handler_args)
@@ -380,6 +416,7 @@
#define AMDKFD_IOC_SMI_EVENTS AMDKFD_IOWR(0x1F, struct kfd_ioctl_smi_events_args)
#define AMDKFD_IOC_SVM AMDKFD_IOWR(0x20, struct kfd_ioctl_svm_args)
#define AMDKFD_IOC_SET_XNACK_MODE AMDKFD_IOWR(0x21, struct kfd_ioctl_set_xnack_mode_args)
+#define AMDKFD_IOC_CRIU_OP AMDKFD_IOWR(0x22, struct kfd_ioctl_criu_args)
#define AMDKFD_COMMAND_START 0x01
-#define AMDKFD_COMMAND_END 0x22
+#define AMDKFD_COMMAND_END 0x23
#endif
diff --git a/libc/kernel/uapi/linux/kvm.h b/libc/kernel/uapi/linux/kvm.h
index 1cf7182..cc5495d 100644
--- a/libc/kernel/uapi/linux/kvm.h
+++ b/libc/kernel/uapi/linux/kvm.h
@@ -336,8 +336,15 @@
#define KVM_SYSTEM_EVENT_SHUTDOWN 1
#define KVM_SYSTEM_EVENT_RESET 2
#define KVM_SYSTEM_EVENT_CRASH 3
+#define KVM_SYSTEM_EVENT_WAKEUP 4
+#define KVM_SYSTEM_EVENT_SUSPEND 5
+#define KVM_SYSTEM_EVENT_SEV_TERM 6
__u32 type;
- __u64 flags;
+ __u32 ndata;
+ union {
+ __u64 flags;
+ __u64 data[16];
+ };
} system_event;
struct {
__u64 addr;
@@ -419,7 +426,10 @@
__u32 op;
__u64 buf;
union {
- __u8 ar;
+ struct {
+ __u8 ar;
+ __u8 key;
+ };
__u32 sida_offset;
__u8 reserved[32];
};
@@ -428,8 +438,11 @@
#define KVM_S390_MEMOP_LOGICAL_WRITE 1
#define KVM_S390_MEMOP_SIDA_READ 2
#define KVM_S390_MEMOP_SIDA_WRITE 3
+#define KVM_S390_MEMOP_ABSOLUTE_READ 4
+#define KVM_S390_MEMOP_ABSOLUTE_WRITE 5
#define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0)
#define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1)
+#define KVM_S390_MEMOP_F_SKEY_PROTECTION (1ULL << 2)
struct kvm_interrupt {
__u32 irq;
};
@@ -472,6 +485,7 @@
#define KVM_MP_STATE_OPERATING 7
#define KVM_MP_STATE_LOAD 8
#define KVM_MP_STATE_AP_RESET_HOLD 9
+#define KVM_MP_STATE_SUSPENDED 10
struct kvm_mp_state {
__u32 mp_state;
};
@@ -890,6 +904,12 @@
#define KVM_CAP_XSAVE2 208
#define KVM_CAP_SYS_ATTRIBUTES 209
#define KVM_CAP_PPC_AIL_MODE_3 210
+#define KVM_CAP_S390_MEM_OP_EXTENSION 211
+#define KVM_CAP_PMU_CAPABILITY 212
+#define KVM_CAP_DISABLE_QUIRKS2 213
+#define KVM_CAP_VM_TSC_CONTROL 214
+#define KVM_CAP_SYSTEM_EVENT_DATA 215
+#define KVM_CAP_ARM_SYSTEM_SUSPEND 216
#ifdef KVM_CAP_IRQ_ROUTING
struct kvm_irq_routing_irqchip {
__u32 irqchip;
@@ -963,6 +983,7 @@
#define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2)
#define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 3)
#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL (1 << 4)
+#define KVM_XEN_HVM_CONFIG_EVTCHN_SEND (1 << 5)
struct kvm_xen_hvm_config {
__u32 flags;
__u32 msr;
@@ -1273,14 +1294,38 @@
struct {
__u64 gfn;
} shared_info;
+ struct {
+ __u32 send_port;
+ __u32 type;
+ __u32 flags;
+#define KVM_XEN_EVTCHN_DEASSIGN (1 << 0)
+#define KVM_XEN_EVTCHN_UPDATE (1 << 1)
+#define KVM_XEN_EVTCHN_RESET (1 << 2)
+ union {
+ struct {
+ __u32 port;
+ __u32 vcpu;
+ __u32 priority;
+ } port;
+ struct {
+ __u32 port;
+ __s32 fd;
+ } eventfd;
+ __u32 padding[4];
+ } deliver;
+ } evtchn;
+ __u32 xen_version;
__u64 pad[8];
} u;
};
#define KVM_XEN_ATTR_TYPE_LONG_MODE 0x0
#define KVM_XEN_ATTR_TYPE_SHARED_INFO 0x1
#define KVM_XEN_ATTR_TYPE_UPCALL_VECTOR 0x2
+#define KVM_XEN_ATTR_TYPE_EVTCHN 0x3
+#define KVM_XEN_ATTR_TYPE_XEN_VERSION 0x4
#define KVM_XEN_VCPU_GET_ATTR _IOWR(KVMIO, 0xca, struct kvm_xen_vcpu_attr)
#define KVM_XEN_VCPU_SET_ATTR _IOW(KVMIO, 0xcb, struct kvm_xen_vcpu_attr)
+#define KVM_XEN_HVM_EVTCHN_SEND _IOW(KVMIO, 0xd0, struct kvm_irq_routing_xen_evtchn)
#define KVM_GET_SREGS2 _IOR(KVMIO, 0xcc, struct kvm_sregs2)
#define KVM_SET_SREGS2 _IOW(KVMIO, 0xcd, struct kvm_sregs2)
struct kvm_xen_vcpu_attr {
@@ -1297,6 +1342,13 @@
__u64 time_blocked;
__u64 time_offline;
} runstate;
+ __u32 vcpu_id;
+ struct {
+ __u32 port;
+ __u32 priority;
+ __u64 expires_ns;
+ } timer;
+ __u8 vector;
} u;
};
#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO 0x0
@@ -1305,6 +1357,9 @@
#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT 0x3
#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA 0x4
#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5
+#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID 0x6
+#define KVM_XEN_VCPU_ATTR_TYPE_TIMER 0x7
+#define KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR 0x8
enum sev_cmd_id {
KVM_SEV_INIT = 0,
KVM_SEV_ES_INIT,
@@ -1480,6 +1535,7 @@
};
#define KVM_BUS_LOCK_DETECTION_OFF (1 << 0)
#define KVM_BUS_LOCK_DETECTION_EXIT (1 << 1)
+#define KVM_PMU_CAP_DISABLE (1 << 0)
struct kvm_stats_header {
__u32 flags;
__u32 name_size;
@@ -1502,7 +1558,8 @@
#define KVM_STATS_UNIT_BYTES (0x1 << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_SECONDS (0x2 << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_CYCLES (0x3 << KVM_STATS_UNIT_SHIFT)
-#define KVM_STATS_UNIT_MAX KVM_STATS_UNIT_CYCLES
+#define KVM_STATS_UNIT_BOOLEAN (0x4 << KVM_STATS_UNIT_SHIFT)
+#define KVM_STATS_UNIT_MAX KVM_STATS_UNIT_BOOLEAN
#define KVM_STATS_BASE_SHIFT 8
#define KVM_STATS_BASE_MASK (0xF << KVM_STATS_BASE_SHIFT)
#define KVM_STATS_BASE_POW10 (0x0 << KVM_STATS_BASE_SHIFT)
diff --git a/libc/kernel/uapi/linux/landlock.h b/libc/kernel/uapi/linux/landlock.h
index 50d79d8..ea2fd74 100644
--- a/libc/kernel/uapi/linux/landlock.h
+++ b/libc/kernel/uapi/linux/landlock.h
@@ -43,4 +43,5 @@
#define LANDLOCK_ACCESS_FS_MAKE_FIFO (1ULL << 10)
#define LANDLOCK_ACCESS_FS_MAKE_BLOCK (1ULL << 11)
#define LANDLOCK_ACCESS_FS_MAKE_SYM (1ULL << 12)
+#define LANDLOCK_ACCESS_FS_REFER (1ULL << 13)
#endif
diff --git a/libc/kernel/uapi/linux/lirc.h b/libc/kernel/uapi/linux/lirc.h
index a0ac24a..dff0b63 100644
--- a/libc/kernel/uapi/linux/lirc.h
+++ b/libc/kernel/uapi/linux/lirc.h
@@ -26,18 +26,21 @@
#define LIRC_MODE2_PULSE 0x01000000
#define LIRC_MODE2_FREQUENCY 0x02000000
#define LIRC_MODE2_TIMEOUT 0x03000000
+#define LIRC_MODE2_OVERFLOW 0x04000000
#define LIRC_VALUE_MASK 0x00FFFFFF
#define LIRC_MODE2_MASK 0xFF000000
#define LIRC_SPACE(val) (((val) & LIRC_VALUE_MASK) | LIRC_MODE2_SPACE)
#define LIRC_PULSE(val) (((val) & LIRC_VALUE_MASK) | LIRC_MODE2_PULSE)
#define LIRC_FREQUENCY(val) (((val) & LIRC_VALUE_MASK) | LIRC_MODE2_FREQUENCY)
#define LIRC_TIMEOUT(val) (((val) & LIRC_VALUE_MASK) | LIRC_MODE2_TIMEOUT)
+#define LIRC_OVERFLOW(val) (((val) & LIRC_VALUE_MASK) | LIRC_MODE2_OVERFLOW)
#define LIRC_VALUE(val) ((val) & LIRC_VALUE_MASK)
#define LIRC_MODE2(val) ((val) & LIRC_MODE2_MASK)
#define LIRC_IS_SPACE(val) (LIRC_MODE2(val) == LIRC_MODE2_SPACE)
#define LIRC_IS_PULSE(val) (LIRC_MODE2(val) == LIRC_MODE2_PULSE)
#define LIRC_IS_FREQUENCY(val) (LIRC_MODE2(val) == LIRC_MODE2_FREQUENCY)
#define LIRC_IS_TIMEOUT(val) (LIRC_MODE2(val) == LIRC_MODE2_TIMEOUT)
+#define LIRC_IS_OVERFLOW(val) (LIRC_MODE2(val) == LIRC_MODE2_OVERFLOW)
#define lirc_t int
#define LIRC_MODE2SEND(x) (x)
#define LIRC_SEND2MODE(x) (x)
@@ -63,17 +66,15 @@
#define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE)
#define LIRC_CAN_REC_MASK LIRC_MODE2REC(LIRC_CAN_SEND_MASK)
#define LIRC_CAN_SET_REC_CARRIER (LIRC_CAN_SET_SEND_CARRIER << 16)
-#define LIRC_CAN_SET_REC_DUTY_CYCLE (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16)
-#define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000
#define LIRC_CAN_SET_REC_CARRIER_RANGE 0x80000000
#define LIRC_CAN_GET_REC_RESOLUTION 0x20000000
#define LIRC_CAN_SET_REC_TIMEOUT 0x10000000
-#define LIRC_CAN_SET_REC_FILTER 0x08000000
#define LIRC_CAN_MEASURE_CARRIER 0x02000000
#define LIRC_CAN_USE_WIDEBAND_RECEIVER 0x04000000
#define LIRC_CAN_SEND(x) ((x) & LIRC_CAN_SEND_MASK)
#define LIRC_CAN_REC(x) ((x) & LIRC_CAN_REC_MASK)
-#define LIRC_CAN_NOTIFY_DECODE 0x01000000
+#define LIRC_CAN_SET_REC_FILTER 0
+#define LIRC_CAN_NOTIFY_DECODE 0
#define LIRC_GET_FEATURES _IOR('i', 0x00000000, __u32)
#define LIRC_GET_SEND_MODE _IOR('i', 0x00000001, __u32)
#define LIRC_GET_REC_MODE _IOR('i', 0x00000002, __u32)
diff --git a/libc/kernel/uapi/linux/mctp.h b/libc/kernel/uapi/linux/mctp.h
index 21a9a14..f02c12f 100644
--- a/libc/kernel/uapi/linux/mctp.h
+++ b/libc/kernel/uapi/linux/mctp.h
@@ -46,5 +46,13 @@
#define MCTP_ADDR_ANY 0xff
#define MCTP_TAG_MASK 0x07
#define MCTP_TAG_OWNER 0x08
+#define MCTP_TAG_PREALLOC 0x10
#define MCTP_OPT_ADDR_EXT 1
+#define SIOCMCTPALLOCTAG (SIOCPROTOPRIVATE + 0)
+#define SIOCMCTPDROPTAG (SIOCPROTOPRIVATE + 1)
+struct mctp_ioc_tag_ctl {
+ mctp_eid_t peer_addr;
+ __u8 tag;
+ __u16 flags;
+};
#endif
diff --git a/libc/kernel/uapi/linux/mdio.h b/libc/kernel/uapi/linux/mdio.h
index d5c9da8..7a2c9af 100644
--- a/libc/kernel/uapi/linux/mdio.h
+++ b/libc/kernel/uapi/linux/mdio.h
@@ -66,6 +66,19 @@
#define MDIO_PCS_10GBRT_STAT2 33
#define MDIO_AN_10GBT_CTRL 32
#define MDIO_AN_10GBT_STAT 33
+#define MDIO_B10L_PMA_CTRL 2294
+#define MDIO_PMA_10T1L_STAT 2295
+#define MDIO_PCS_10T1L_CTRL 2278
+#define MDIO_PMA_PMD_BT1 18
+#define MDIO_AN_T1_CTRL 512
+#define MDIO_AN_T1_STAT 513
+#define MDIO_AN_T1_ADV_L 514
+#define MDIO_AN_T1_ADV_M 515
+#define MDIO_AN_T1_ADV_H 516
+#define MDIO_AN_T1_LP_L 517
+#define MDIO_AN_T1_LP_M 518
+#define MDIO_AN_T1_LP_H 519
+#define MDIO_PMA_PMD_BT1_CTRL 2100
#define MDIO_PMA_LASI_RXCTRL 0x9000
#define MDIO_PMA_LASI_TXCTRL 0x9001
#define MDIO_PMA_LASI_CTRL 0x9002
@@ -139,6 +152,7 @@
#define MDIO_PMA_CTRL2_10BT 0x000f
#define MDIO_PMA_CTRL2_2_5GBT 0x0030
#define MDIO_PMA_CTRL2_5GBT 0x0031
+#define MDIO_PMA_CTRL2_BASET1 0x003D
#define MDIO_PCS_CTRL2_TYPE 0x0003
#define MDIO_PCS_CTRL2_10GBR 0x0000
#define MDIO_PCS_CTRL2_10GBX 0x0001
@@ -184,6 +198,7 @@
#define MDIO_PMA_EXTABLE_1000BKX 0x0040
#define MDIO_PMA_EXTABLE_100BTX 0x0080
#define MDIO_PMA_EXTABLE_10BT 0x0100
+#define MDIO_PMA_EXTABLE_BT1 0x0800
#define MDIO_PMA_EXTABLE_NBT 0x4000
#define MDIO_PHYXS_LNSTAT_SYNC0 0x0001
#define MDIO_PHYXS_LNSTAT_SYNC1 0x0002
@@ -218,6 +233,44 @@
#define MDIO_AN_10GBT_STAT_LOCOK 0x2000
#define MDIO_AN_10GBT_STAT_MS 0x4000
#define MDIO_AN_10GBT_STAT_MSFLT 0x8000
+#define MDIO_PMA_10T1L_CTRL_LB_EN 0x0001
+#define MDIO_PMA_10T1L_CTRL_EEE_EN 0x0400
+#define MDIO_PMA_10T1L_CTRL_LOW_POWER 0x0800
+#define MDIO_PMA_10T1L_CTRL_2V4_EN 0x1000
+#define MDIO_PMA_10T1L_CTRL_TX_DIS 0x4000
+#define MDIO_PMA_10T1L_CTRL_PMA_RST 0x8000
+#define MDIO_PMA_10T1L_STAT_LINK 0x0001
+#define MDIO_PMA_10T1L_STAT_FAULT 0x0002
+#define MDIO_PMA_10T1L_STAT_POLARITY 0x0004
+#define MDIO_PMA_10T1L_STAT_RECV_FAULT 0x0200
+#define MDIO_PMA_10T1L_STAT_EEE 0x0400
+#define MDIO_PMA_10T1L_STAT_LOW_POWER 0x0800
+#define MDIO_PMA_10T1L_STAT_2V4_ABLE 0x1000
+#define MDIO_PMA_10T1L_STAT_LB_ABLE 0x2000
+#define MDIO_PCS_10T1L_CTRL_LB 0x4000
+#define MDIO_PCS_10T1L_CTRL_RESET 0x8000
+#define MDIO_PMA_PMD_BT1_B10L_ABLE 0x0004
+#define MDIO_AN_T1_ADV_L_PAUSE_CAP ADVERTISE_PAUSE_CAP
+#define MDIO_AN_T1_ADV_L_PAUSE_ASYM ADVERTISE_PAUSE_ASYM
+#define MDIO_AN_T1_ADV_L_FORCE_MS 0x1000
+#define MDIO_AN_T1_ADV_L_REMOTE_FAULT ADVERTISE_RFAULT
+#define MDIO_AN_T1_ADV_L_ACK ADVERTISE_LPACK
+#define MDIO_AN_T1_ADV_L_NEXT_PAGE_REQ ADVERTISE_NPAGE
+#define MDIO_AN_T1_ADV_M_B10L 0x4000
+#define MDIO_AN_T1_ADV_M_MST 0x0010
+#define MDIO_AN_T1_ADV_H_10L_TX_HI_REQ 0x1000
+#define MDIO_AN_T1_ADV_H_10L_TX_HI 0x2000
+#define MDIO_AN_T1_LP_L_PAUSE_CAP LPA_PAUSE_CAP
+#define MDIO_AN_T1_LP_L_PAUSE_ASYM LPA_PAUSE_ASYM
+#define MDIO_AN_T1_LP_L_FORCE_MS 0x1000
+#define MDIO_AN_T1_LP_L_REMOTE_FAULT LPA_RFAULT
+#define MDIO_AN_T1_LP_L_ACK LPA_LPACK
+#define MDIO_AN_T1_LP_L_NEXT_PAGE_REQ LPA_NPAGE
+#define MDIO_AN_T1_LP_M_MST 0x0010
+#define MDIO_AN_T1_LP_M_B10L 0x4000
+#define MDIO_AN_T1_LP_H_10L_TX_HI_REQ 0x1000
+#define MDIO_AN_T1_LP_H_10L_TX_HI 0x2000
+#define MDIO_PMA_PMD_BT1_CTRL_CFG_MST 0x4000
#define MDIO_AN_EEE_ADV_100TX 0x0002
#define MDIO_AN_EEE_ADV_1000T 0x0004
#define MDIO_EEE_100TX MDIO_AN_EEE_ADV_100TX
diff --git a/libc/kernel/uapi/linux/media.h b/libc/kernel/uapi/linux/media.h
index 5c8efcd..869d47b 100644
--- a/libc/kernel/uapi/linux/media.h
+++ b/libc/kernel/uapi/linux/media.h
@@ -18,7 +18,6 @@
****************************************************************************/
#ifndef __LINUX_MEDIA_H
#define __LINUX_MEDIA_H
-#include <stdint.h>
#include <linux/ioctl.h>
#include <linux/types.h>
struct media_device_info {
@@ -117,6 +116,7 @@
#define MEDIA_LNK_FL_LINK_TYPE (0xf << 28)
#define MEDIA_LNK_FL_DATA_LINK (0 << 28)
#define MEDIA_LNK_FL_INTERFACE_LINK (1 << 28)
+#define MEDIA_LNK_FL_ANCILLARY_LINK (2 << 28)
struct media_link_desc {
struct media_pad_desc source;
struct media_pad_desc sink;
diff --git a/libc/kernel/uapi/linux/mptcp.h b/libc/kernel/uapi/linux/mptcp.h
index 67b0ce3..da1b5af 100644
--- a/libc/kernel/uapi/linux/mptcp.h
+++ b/libc/kernel/uapi/linux/mptcp.h
@@ -18,12 +18,13 @@
****************************************************************************/
#ifndef _UAPI_MPTCP_H
#define _UAPI_MPTCP_H
+#include <netinet/in.h>
+#include <sys/socket.h>
#include <linux/const.h>
#include <linux/types.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/socket.h>
-#include <sys/socket.h>
#define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0)
#define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1)
#define MPTCP_SUBFLOW_FLAG_JOIN_REM _BITUL(2)
@@ -58,6 +59,9 @@
MPTCP_PM_ATTR_ADDR,
MPTCP_PM_ATTR_RCV_ADD_ADDRS,
MPTCP_PM_ATTR_SUBFLOWS,
+ MPTCP_PM_ATTR_TOKEN,
+ MPTCP_PM_ATTR_LOC_ID,
+ MPTCP_PM_ATTR_ADDR_REMOTE,
__MPTCP_PM_ATTR_MAX
};
#define MPTCP_PM_ATTR_MAX (__MPTCP_PM_ATTR_MAX - 1)
@@ -77,6 +81,7 @@
#define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1)
#define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2)
#define MPTCP_PM_ADDR_FLAG_FULLMESH (1 << 3)
+#define MPTCP_PM_ADDR_FLAG_IMPLICIT (1 << 4)
enum {
MPTCP_PM_CMD_UNSPEC,
MPTCP_PM_CMD_ADD_ADDR,
@@ -86,6 +91,10 @@
MPTCP_PM_CMD_SET_LIMITS,
MPTCP_PM_CMD_GET_LIMITS,
MPTCP_PM_CMD_SET_FLAGS,
+ MPTCP_PM_CMD_ANNOUNCE,
+ MPTCP_PM_CMD_REMOVE,
+ MPTCP_PM_CMD_SUBFLOW_CREATE,
+ MPTCP_PM_CMD_SUBFLOW_DESTROY,
__MPTCP_PM_CMD_AFTER_LAST
};
#define MPTCP_INFO_FLAG_FALLBACK _BITUL(0)
@@ -136,6 +145,7 @@
MPTCP_ATTR_IF_IDX,
MPTCP_ATTR_RESET_REASON,
MPTCP_ATTR_RESET_FLAGS,
+ MPTCP_ATTR_SERVER_SIDE,
__MPTCP_ATTR_AFTER_LAST
};
#define MPTCP_ATTR_MAX (__MPTCP_ATTR_AFTER_LAST - 1)
diff --git a/libc/kernel/uapi/linux/mroute6.h b/libc/kernel/uapi/linux/mroute6.h
index c73765c..68480de 100644
--- a/libc/kernel/uapi/linux/mroute6.h
+++ b/libc/kernel/uapi/linux/mroute6.h
@@ -93,6 +93,7 @@
#define MRT6MSG_NOCACHE 1
#define MRT6MSG_WRONGMIF 2
#define MRT6MSG_WHOLEPKT 3
+#define MRT6MSG_WRMIFWHOLE 4
__u8 im6_mbz;
__u8 im6_msgtype;
__u16 im6_mif;
diff --git a/libc/kernel/uapi/linux/ndctl.h b/libc/kernel/uapi/linux/ndctl.h
index 53f8ba4..0fd3ac4 100644
--- a/libc/kernel/uapi/linux/ndctl.h
+++ b/libc/kernel/uapi/linux/ndctl.h
@@ -129,7 +129,6 @@
#define ND_DEVICE_REGION_BLK 3
#define ND_DEVICE_NAMESPACE_IO 4
#define ND_DEVICE_NAMESPACE_PMEM 5
-#define ND_DEVICE_NAMESPACE_BLK 6
#define ND_DEVICE_DAX_PMEM 7
enum nd_driver_flags {
ND_DRIVER_DIMM = 1 << ND_DEVICE_DIMM,
@@ -137,7 +136,6 @@
ND_DRIVER_REGION_BLK = 1 << ND_DEVICE_REGION_BLK,
ND_DRIVER_NAMESPACE_IO = 1 << ND_DEVICE_NAMESPACE_IO,
ND_DRIVER_NAMESPACE_PMEM = 1 << ND_DEVICE_NAMESPACE_PMEM,
- ND_DRIVER_NAMESPACE_BLK = 1 << ND_DEVICE_NAMESPACE_BLK,
ND_DRIVER_DAX_PMEM = 1 << ND_DEVICE_DAX_PMEM,
};
enum ars_masks {
diff --git a/libc/kernel/uapi/linux/neighbour.h b/libc/kernel/uapi/linux/neighbour.h
index 278f7d1..b5dcf2e 100644
--- a/libc/kernel/uapi/linux/neighbour.h
+++ b/libc/kernel/uapi/linux/neighbour.h
@@ -46,6 +46,8 @@
NDA_NH_ID,
NDA_FDB_EXT_ATTRS,
NDA_FLAGS_EXT,
+ NDA_NDM_STATE_MASK,
+ NDA_NDM_FLAGS_MASK,
__NDA_MAX
};
#define NDA_MAX (__NDA_MAX - 1)
diff --git a/libc/kernel/uapi/linux/net_dropmon.h b/libc/kernel/uapi/linux/net_dropmon.h
index 01b76cb..35f70a5 100644
--- a/libc/kernel/uapi/linux/net_dropmon.h
+++ b/libc/kernel/uapi/linux/net_dropmon.h
@@ -87,6 +87,7 @@
NET_DM_ATTR_SW_DROPS,
NET_DM_ATTR_HW_DROPS,
NET_DM_ATTR_FLOW_ACTION_COOKIE,
+ NET_DM_ATTR_REASON,
__NET_DM_ATTR_MAX,
NET_DM_ATTR_MAX = __NET_DM_ATTR_MAX - 1
};
diff --git a/libc/kernel/uapi/linux/netfilter/nfnetlink_queue.h b/libc/kernel/uapi/linux/netfilter/nfnetlink_queue.h
index 75fa359..d100dec 100644
--- a/libc/kernel/uapi/linux/netfilter/nfnetlink_queue.h
+++ b/libc/kernel/uapi/linux/netfilter/nfnetlink_queue.h
@@ -70,6 +70,7 @@
NFQA_SECCTX,
NFQA_VLAN,
NFQA_L2HDR,
+ NFQA_PRIORITY,
__NFQA_MAX
};
#define NFQA_MAX (__NFQA_MAX - 1)
diff --git a/libc/kernel/uapi/linux/netlink.h b/libc/kernel/uapi/linux/netlink.h
index 77825cc..bc3e749 100644
--- a/libc/kernel/uapi/linux/netlink.h
+++ b/libc/kernel/uapi/linux/netlink.h
@@ -73,6 +73,7 @@
#define NLM_F_CREATE 0x400
#define NLM_F_APPEND 0x800
#define NLM_F_NONREC 0x100
+#define NLM_F_BULK 0x200
#define NLM_F_CAPPED 0x100
#define NLM_F_ACK_TLVS 0x200
#define NLMSG_ALIGNTO 4U
diff --git a/libc/kernel/uapi/linux/nfs4.h b/libc/kernel/uapi/linux/nfs4.h
index 9d614ce..ef860e2 100644
--- a/libc/kernel/uapi/linux/nfs4.h
+++ b/libc/kernel/uapi/linux/nfs4.h
@@ -45,6 +45,7 @@
#define NFS4_FH_VOL_RENAME 0x0008
#define NFS4_OPEN_RESULT_CONFIRM 0x0002
#define NFS4_OPEN_RESULT_LOCKTYPE_POSIX 0x0004
+#define NFS4_OPEN_RESULT_PRESERVE_UNLINKED 0x0008
#define NFS4_OPEN_RESULT_MAY_NOTIFY_LOCK 0x0020
#define NFS4_SHARE_ACCESS_MASK 0x000F
#define NFS4_SHARE_ACCESS_READ 0x0001
diff --git a/libc/kernel/uapi/linux/nl80211.h b/libc/kernel/uapi/linux/nl80211.h
index e902178..8655d5f 100644
--- a/libc/kernel/uapi/linux/nl80211.h
+++ b/libc/kernel/uapi/linux/nl80211.h
@@ -511,6 +511,8 @@
NL80211_ATTR_MBSSID_ELEMS,
NL80211_ATTR_RADAR_BACKGROUND,
NL80211_ATTR_AP_SETTINGS_FLAGS,
+ NL80211_ATTR_EHT_CAPABILITY,
+ NL80211_ATTR_DISABLE_EHT,
__NL80211_ATTR_AFTER_LAST,
NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
@@ -555,6 +557,8 @@
#define NL80211_HE_MAX_CAPABILITY_LEN 54
#define NL80211_MAX_NR_CIPHER_SUITES 5
#define NL80211_MAX_NR_AKM_SUITES 2
+#define NL80211_EHT_MIN_CAPABILITY_LEN 13
+#define NL80211_EHT_MAX_CAPABILITY_LEN 51
#define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10
#define NL80211_SCAN_RSSI_THOLD_OFF - 300
#define NL80211_CQM_TXE_MAX_INTVL 1800
@@ -616,6 +620,29 @@
NL80211_RATE_INFO_HE_RU_ALLOC_996,
NL80211_RATE_INFO_HE_RU_ALLOC_2x996,
};
+enum nl80211_eht_gi {
+ NL80211_RATE_INFO_EHT_GI_0_8,
+ NL80211_RATE_INFO_EHT_GI_1_6,
+ NL80211_RATE_INFO_EHT_GI_3_2,
+};
+enum nl80211_eht_ru_alloc {
+ NL80211_RATE_INFO_EHT_RU_ALLOC_26,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_52,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_52P26,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_106,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_106P26,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_242,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_484,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_484P242,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_996,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_996P484,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_2x996,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_3x996,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484,
+ NL80211_RATE_INFO_EHT_RU_ALLOC_4x996,
+};
enum nl80211_rate_info {
__NL80211_RATE_INFO_INVALID,
NL80211_RATE_INFO_BITRATE,
@@ -635,6 +662,11 @@
NL80211_RATE_INFO_HE_GI,
NL80211_RATE_INFO_HE_DCM,
NL80211_RATE_INFO_HE_RU_ALLOC,
+ NL80211_RATE_INFO_320_MHZ_WIDTH,
+ NL80211_RATE_INFO_EHT_MCS,
+ NL80211_RATE_INFO_EHT_NSS,
+ NL80211_RATE_INFO_EHT_GI,
+ NL80211_RATE_INFO_EHT_RU_ALLOC,
__NL80211_RATE_INFO_AFTER_LAST,
NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
};
@@ -754,6 +786,10 @@
NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS,
+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC,
+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY,
+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET,
+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE,
__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST,
NL80211_BAND_IFTYPE_ATTR_MAX = __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST - 1
};
@@ -810,6 +846,8 @@
NL80211_FREQUENCY_ATTR_4MHZ,
NL80211_FREQUENCY_ATTR_8MHZ,
NL80211_FREQUENCY_ATTR_16MHZ,
+ NL80211_FREQUENCY_ATTR_NO_320MHZ,
+ NL80211_FREQUENCY_ATTR_NO_EHT,
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1
};
@@ -878,6 +916,7 @@
NL80211_RRF_NO_80MHZ = 1 << 15,
NL80211_RRF_NO_160MHZ = 1 << 16,
NL80211_RRF_NO_HE = 1 << 17,
+ NL80211_RRF_NO_320MHZ = 1 << 18,
};
#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
#define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR
@@ -1033,6 +1072,7 @@
NL80211_CHAN_WIDTH_4,
NL80211_CHAN_WIDTH_8,
NL80211_CHAN_WIDTH_16,
+ NL80211_CHAN_WIDTH_320,
};
enum nl80211_bss_scan_width {
NL80211_BSS_CHAN_WIDTH_20,
diff --git a/libc/kernel/uapi/linux/nvme_ioctl.h b/libc/kernel/uapi/linux/nvme_ioctl.h
index f2a328e..388e83f 100644
--- a/libc/kernel/uapi/linux/nvme_ioctl.h
+++ b/libc/kernel/uapi/linux/nvme_ioctl.h
@@ -63,7 +63,10 @@
__u64 metadata;
__u64 addr;
__u32 metadata_len;
- __u32 data_len;
+ union {
+ __u32 data_len;
+ __u32 vec_cnt;
+ };
__u32 cdw10;
__u32 cdw11;
__u32 cdw12;
@@ -74,6 +77,26 @@
__u32 rsvd2;
__u64 result;
};
+struct nvme_uring_cmd {
+ __u8 opcode;
+ __u8 flags;
+ __u16 rsvd1;
+ __u32 nsid;
+ __u32 cdw2;
+ __u32 cdw3;
+ __u64 metadata;
+ __u64 addr;
+ __u32 metadata_len;
+ __u32 data_len;
+ __u32 cdw10;
+ __u32 cdw11;
+ __u32 cdw12;
+ __u32 cdw13;
+ __u32 cdw14;
+ __u32 cdw15;
+ __u32 timeout_ms;
+ __u32 rsvd2;
+};
#define nvme_admin_cmd nvme_passthru_cmd
#define NVME_IOCTL_ID _IO('N', 0x40)
#define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct nvme_admin_cmd)
@@ -84,4 +107,9 @@
#define NVME_IOCTL_RESCAN _IO('N', 0x46)
#define NVME_IOCTL_ADMIN64_CMD _IOWR('N', 0x47, struct nvme_passthru_cmd64)
#define NVME_IOCTL_IO64_CMD _IOWR('N', 0x48, struct nvme_passthru_cmd64)
+#define NVME_IOCTL_IO64_CMD_VEC _IOWR('N', 0x49, struct nvme_passthru_cmd64)
+#define NVME_URING_CMD_IO _IOWR('N', 0x80, struct nvme_uring_cmd)
+#define NVME_URING_CMD_IO_VEC _IOWR('N', 0x81, struct nvme_uring_cmd)
+#define NVME_URING_CMD_ADMIN _IOWR('N', 0x82, struct nvme_uring_cmd)
+#define NVME_URING_CMD_ADMIN_VEC _IOWR('N', 0x83, struct nvme_uring_cmd)
#endif
diff --git a/libc/kernel/uapi/linux/omap3isp.h b/libc/kernel/uapi/linux/omap3isp.h
index d2eceb7..53345e3 100644
--- a/libc/kernel/uapi/linux/omap3isp.h
+++ b/libc/kernel/uapi/linux/omap3isp.h
@@ -89,10 +89,11 @@
struct omap3isp_stat_data {
struct timeval ts;
void __user * buf;
- __u32 buf_size;
+ __struct_group(, frame,, __u32 buf_size;
__u16 frame_number;
__u16 cur_frame;
__u16 config_counter;
+ );
};
#define OMAP3ISP_HIST_BINS_32 0
#define OMAP3ISP_HIST_BINS_64 1
diff --git a/libc/kernel/uapi/linux/openvswitch.h b/libc/kernel/uapi/linux/openvswitch.h
index 1f8ae17..c7d719c 100644
--- a/libc/kernel/uapi/linux/openvswitch.h
+++ b/libc/kernel/uapi/linux/openvswitch.h
@@ -190,6 +190,10 @@
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4,
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6,
OVS_KEY_ATTR_NSH,
+ OVS_KEY_ATTR_PACKET_TYPE,
+ OVS_KEY_ATTR_ND_EXTENSIONS,
+ OVS_KEY_ATTR_TUNNEL_INFO,
+ OVS_KEY_ATTR_IPV6_EXTHDRS,
__OVS_KEY_ATTR_MAX
};
#define OVS_KEY_ATTR_MAX (__OVS_KEY_ATTR_MAX - 1)
@@ -245,6 +249,9 @@
__u8 ipv6_hlimit;
__u8 ipv6_frag;
};
+struct ovs_key_ipv6_exthdrs {
+ __u16 hdrs;
+};
struct ovs_key_tcp {
__be16 tcp_src;
__be16 tcp_dst;
diff --git a/libc/kernel/uapi/linux/pci_regs.h b/libc/kernel/uapi/linux/pci_regs.h
index 46612da..e1a38a8 100644
--- a/libc/kernel/uapi/linux/pci_regs.h
+++ b/libc/kernel/uapi/linux/pci_regs.h
@@ -525,6 +525,7 @@
#define PCI_EXP_SLTCTL_PWR_OFF 0x0400
#define PCI_EXP_SLTCTL_EIC 0x0800
#define PCI_EXP_SLTCTL_DLLSCE 0x1000
+#define PCI_EXP_SLTCTL_ASPL_DISABLE 0x2000
#define PCI_EXP_SLTCTL_IBPD_DISABLE 0x4000
#define PCI_EXP_SLTSTA 0x1a
#define PCI_EXP_SLTSTA_ABP 0x0001
diff --git a/libc/kernel/uapi/linux/perf_event.h b/libc/kernel/uapi/linux/perf_event.h
index b022586..bcc4e97 100644
--- a/libc/kernel/uapi/linux/perf_event.h
+++ b/libc/kernel/uapi/linux/perf_event.h
@@ -165,6 +165,8 @@
PERF_BR_SYSRET = 8,
PERF_BR_COND_CALL = 9,
PERF_BR_COND_RET = 10,
+ PERF_BR_ERET = 11,
+ PERF_BR_IRQ = 12,
PERF_BR_MAX,
};
#define PERF_SAMPLE_BRANCH_PLM_ALL (PERF_SAMPLE_BRANCH_USER | PERF_SAMPLE_BRANCH_KERNEL | PERF_SAMPLE_BRANCH_HV)
diff --git a/libc/kernel/uapi/linux/pkt_cls.h b/libc/kernel/uapi/linux/pkt_cls.h
index 9fd89e0..1db5d32 100644
--- a/libc/kernel/uapi/linux/pkt_cls.h
+++ b/libc/kernel/uapi/linux/pkt_cls.h
@@ -459,6 +459,7 @@
TCA_FLOWER_KEY_MPLS_OPTS,
TCA_FLOWER_KEY_HASH,
TCA_FLOWER_KEY_HASH_MASK,
+ TCA_FLOWER_KEY_NUM_OF_VLANS,
__TCA_FLOWER_MAX,
};
#define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
@@ -476,6 +477,7 @@
TCA_FLOWER_KEY_ENC_OPTS_GENEVE,
TCA_FLOWER_KEY_ENC_OPTS_VXLAN,
TCA_FLOWER_KEY_ENC_OPTS_ERSPAN,
+ TCA_FLOWER_KEY_ENC_OPTS_GTP,
__TCA_FLOWER_KEY_ENC_OPTS_MAX,
};
#define TCA_FLOWER_KEY_ENC_OPTS_MAX (__TCA_FLOWER_KEY_ENC_OPTS_MAX - 1)
@@ -503,6 +505,13 @@
};
#define TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX (__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX - 1)
enum {
+ TCA_FLOWER_KEY_ENC_OPT_GTP_UNSPEC,
+ TCA_FLOWER_KEY_ENC_OPT_GTP_PDU_TYPE,
+ TCA_FLOWER_KEY_ENC_OPT_GTP_QFI,
+ __TCA_FLOWER_KEY_ENC_OPT_GTP_MAX,
+};
+#define TCA_FLOWER_KEY_ENC_OPT_GTP_MAX (__TCA_FLOWER_KEY_ENC_OPT_GTP_MAX - 1)
+enum {
TCA_FLOWER_KEY_MPLS_OPTS_UNSPEC,
TCA_FLOWER_KEY_MPLS_OPTS_LSE,
__TCA_FLOWER_KEY_MPLS_OPTS_MAX,
diff --git a/libc/kernel/uapi/linux/prctl.h b/libc/kernel/uapi/linux/prctl.h
index 9b4c695..1dac726 100644
--- a/libc/kernel/uapi/linux/prctl.h
+++ b/libc/kernel/uapi/linux/prctl.h
@@ -179,6 +179,11 @@
#define PR_SCHED_CORE_SCOPE_THREAD 0
#define PR_SCHED_CORE_SCOPE_THREAD_GROUP 1
#define PR_SCHED_CORE_SCOPE_PROCESS_GROUP 2
+#define PR_SME_SET_VL 63
+#define PR_SME_SET_VL_ONEXEC (1 << 18)
+#define PR_SME_GET_VL 64
+#define PR_SME_VL_LEN_MASK 0xffff
+#define PR_SME_VL_INHERIT (1 << 17)
#define PR_SET_VMA 0x53564d41
#define PR_SET_VMA_ANON_NAME 0
#endif
diff --git a/libc/kernel/uapi/linux/psci.h b/libc/kernel/uapi/linux/psci.h
index bc522e7..31e7465 100644
--- a/libc/kernel/uapi/linux/psci.h
+++ b/libc/kernel/uapi/linux/psci.h
@@ -60,6 +60,8 @@
#define PSCI_0_2_TOS_UP_MIGRATE 0
#define PSCI_0_2_TOS_UP_NO_MIGRATE 1
#define PSCI_0_2_TOS_MP 2
+#define PSCI_1_1_RESET_TYPE_SYSTEM_WARM_RESET 0
+#define PSCI_1_1_RESET_TYPE_VENDOR_START 0x80000000U
#define PSCI_VERSION_MAJOR_SHIFT 16
#define PSCI_VERSION_MINOR_MASK ((1U << PSCI_VERSION_MAJOR_SHIFT) - 1)
#define PSCI_VERSION_MAJOR_MASK ~PSCI_VERSION_MINOR_MASK
diff --git a/libc/kernel/uapi/linux/reiserfs_xattr.h b/libc/kernel/uapi/linux/reiserfs_xattr.h
index 36d31f6..16a7a08 100644
--- a/libc/kernel/uapi/linux/reiserfs_xattr.h
+++ b/libc/kernel/uapi/linux/reiserfs_xattr.h
@@ -27,6 +27,6 @@
struct reiserfs_security_handle {
const char * name;
void * value;
- size_t length;
+ __kernel_size_t length;
};
#endif
diff --git a/libc/kernel/uapi/linux/rfkill.h b/libc/kernel/uapi/linux/rfkill.h
index 6020baf..b90e67c 100644
--- a/libc/kernel/uapi/linux/rfkill.h
+++ b/libc/kernel/uapi/linux/rfkill.h
@@ -63,4 +63,6 @@
#define RFKILL_IOC_MAGIC 'R'
#define RFKILL_IOC_NOINPUT 1
#define RFKILL_IOCTL_NOINPUT _IO(RFKILL_IOC_MAGIC, RFKILL_IOC_NOINPUT)
+#define RFKILL_IOC_MAX_SIZE 2
+#define RFKILL_IOCTL_MAX_SIZE _IOW(RFKILL_IOC_MAGIC, RFKILL_IOC_MAX_SIZE, __u32)
#endif
diff --git a/libc/kernel/uapi/linux/rpmsg.h b/libc/kernel/uapi/linux/rpmsg.h
index c5b5a76..9ceccdd 100644
--- a/libc/kernel/uapi/linux/rpmsg.h
+++ b/libc/kernel/uapi/linux/rpmsg.h
@@ -28,4 +28,6 @@
};
#define RPMSG_CREATE_EPT_IOCTL _IOW(0xb5, 0x1, struct rpmsg_endpoint_info)
#define RPMSG_DESTROY_EPT_IOCTL _IO(0xb5, 0x2)
+#define RPMSG_CREATE_DEV_IOCTL _IOW(0xb5, 0x3, struct rpmsg_endpoint_info)
+#define RPMSG_RELEASE_DEV_IOCTL _IOW(0xb5, 0x4, struct rpmsg_endpoint_info)
#endif
diff --git a/libc/kernel/uapi/linux/rseq.h b/libc/kernel/uapi/linux/rseq.h
index ba0ceb1..29a9457 100644
--- a/libc/kernel/uapi/linux/rseq.h
+++ b/libc/kernel/uapi/linux/rseq.h
@@ -47,22 +47,7 @@
struct rseq {
__u32 cpu_id_start;
__u32 cpu_id;
- union {
- __u64 ptr64;
-#ifdef __LP64__
- __u64 ptr;
-#else
- struct {
-#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || defined(__BIG_ENDIAN)
- __u32 padding;
- __u32 ptr32;
-#else
- __u32 ptr32;
- __u32 padding;
-#endif
- } ptr;
-#endif
- } rseq_cs;
+ __u64 rseq_cs;
__u32 flags;
} __attribute__((aligned(4 * sizeof(__u64))));
#endif
diff --git a/libc/kernel/uapi/linux/rtc.h b/libc/kernel/uapi/linux/rtc.h
index cf5f22a..d75bc45 100644
--- a/libc/kernel/uapi/linux/rtc.h
+++ b/libc/kernel/uapi/linux/rtc.h
@@ -96,7 +96,8 @@
#define RTC_FEATURE_UPDATE_INTERRUPT 4
#define RTC_FEATURE_CORRECTION 5
#define RTC_FEATURE_BACKUP_SWITCH_MODE 6
-#define RTC_FEATURE_CNT 7
+#define RTC_FEATURE_ALARM_WAKEUP_ONLY 7
+#define RTC_FEATURE_CNT 8
#define RTC_PARAM_FEATURES 0
#define RTC_PARAM_CORRECTION 1
#define RTC_PARAM_BACKUP_SWITCH_MODE 2
diff --git a/libc/kernel/uapi/linux/rtnetlink.h b/libc/kernel/uapi/linux/rtnetlink.h
index 91c3ee4..321e487 100644
--- a/libc/kernel/uapi/linux/rtnetlink.h
+++ b/libc/kernel/uapi/linux/rtnetlink.h
@@ -131,6 +131,8 @@
#define RTM_NEWSTATS RTM_NEWSTATS
RTM_GETSTATS = 94,
#define RTM_GETSTATS RTM_GETSTATS
+ RTM_SETSTATS,
+#define RTM_SETSTATS RTM_SETSTATS
RTM_NEWCACHEREPORT = 96,
#define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT
RTM_NEWCHAIN = 100,
@@ -163,6 +165,12 @@
#define RTM_DELNEXTHOPBUCKET RTM_DELNEXTHOPBUCKET
RTM_GETNEXTHOPBUCKET,
#define RTM_GETNEXTHOPBUCKET RTM_GETNEXTHOPBUCKET
+ RTM_NEWTUNNEL = 120,
+#define RTM_NEWTUNNEL RTM_NEWTUNNEL
+ RTM_DELTUNNEL,
+#define RTM_DELTUNNEL RTM_DELTUNNEL
+ RTM_GETTUNNEL,
+#define RTM_GETTUNNEL RTM_GETTUNNEL
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
};
@@ -561,6 +569,10 @@
#define RTNLGRP_BRVLAN RTNLGRP_BRVLAN
RTNLGRP_MCTP_IFADDR,
#define RTNLGRP_MCTP_IFADDR RTNLGRP_MCTP_IFADDR
+ RTNLGRP_TUNNEL,
+#define RTNLGRP_TUNNEL RTNLGRP_TUNNEL
+ RTNLGRP_STATS,
+#define RTNLGRP_STATS RTNLGRP_STATS
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
@@ -592,4 +604,5 @@
#define RTEXT_FILTER_MRP (1 << 4)
#define RTEXT_FILTER_CFM_CONFIG (1 << 5)
#define RTEXT_FILTER_CFM_STATUS (1 << 6)
+#define RTEXT_FILTER_MST (1 << 7)
#endif
diff --git a/libc/kernel/uapi/linux/seccomp.h b/libc/kernel/uapi/linux/seccomp.h
index e58b421..cc506ae 100644
--- a/libc/kernel/uapi/linux/seccomp.h
+++ b/libc/kernel/uapi/linux/seccomp.h
@@ -32,6 +32,7 @@
#define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2)
#define SECCOMP_FILTER_FLAG_NEW_LISTENER (1UL << 3)
#define SECCOMP_FILTER_FLAG_TSYNC_ESRCH (1UL << 4)
+#define SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV (1UL << 5)
#define SECCOMP_RET_KILL_PROCESS 0x80000000U
#define SECCOMP_RET_KILL_THREAD 0x00000000U
#define SECCOMP_RET_KILL SECCOMP_RET_KILL_THREAD
diff --git a/libc/kernel/uapi/linux/serial_core.h b/libc/kernel/uapi/linux/serial_core.h
index 0caf698..b99c7d4 100644
--- a/libc/kernel/uapi/linux/serial_core.h
+++ b/libc/kernel/uapi/linux/serial_core.h
@@ -47,6 +47,7 @@
#define PORT_SUNSAB 39
#define PORT_NPCM 40
#define PORT_TEGRA_TCU 41
+#define PORT_ASPEED_VUART 42
#define PORT_PCH_8LINE 44
#define PORT_PCH_2LINE 45
#define PORT_DZ 46
@@ -122,4 +123,5 @@
#define PORT_SIFIVE_V0 120
#define PORT_SUNIX 121
#define PORT_LINFLEXUART 122
+#define PORT_SUNPLUS 123
#endif
diff --git a/libc/kernel/uapi/linux/sev-guest.h b/libc/kernel/uapi/linux/sev-guest.h
new file mode 100644
index 0000000..796479a
--- /dev/null
+++ b/libc/kernel/uapi/linux/sev-guest.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __UAPI_LINUX_SEV_GUEST_H_
+#define __UAPI_LINUX_SEV_GUEST_H_
+#include <linux/types.h>
+struct snp_report_req {
+ __u8 user_data[64];
+ __u32 vmpl;
+ __u8 rsvd[28];
+};
+struct snp_report_resp {
+ __u8 data[4000];
+};
+struct snp_derived_key_req {
+ __u32 root_key_select;
+ __u32 rsvd;
+ __u64 guest_field_select;
+ __u32 vmpl;
+ __u32 guest_svn;
+ __u64 tcb_version;
+};
+struct snp_derived_key_resp {
+ __u8 data[64];
+};
+struct snp_guest_request_ioctl {
+ __u8 msg_version;
+ __u64 req_data;
+ __u64 resp_data;
+ __u64 fw_err;
+};
+struct snp_ext_report_req {
+ struct snp_report_req data;
+ __u64 certs_address;
+ __u32 certs_len;
+};
+#define SNP_GUEST_REQ_IOC_TYPE 'S'
+#define SNP_GET_REPORT _IOWR(SNP_GUEST_REQ_IOC_TYPE, 0x0, struct snp_guest_request_ioctl)
+#define SNP_GET_DERIVED_KEY _IOWR(SNP_GUEST_REQ_IOC_TYPE, 0x1, struct snp_guest_request_ioctl)
+#define SNP_GET_EXT_REPORT _IOWR(SNP_GUEST_REQ_IOC_TYPE, 0x2, struct snp_guest_request_ioctl)
+#endif
diff --git a/libc/kernel/uapi/linux/smc.h b/libc/kernel/uapi/linux/smc.h
index 01494da..be6b71f 100644
--- a/libc/kernel/uapi/linux/smc.h
+++ b/libc/kernel/uapi/linux/smc.h
@@ -57,6 +57,9 @@
SMC_NETLINK_DUMP_SEID,
SMC_NETLINK_ENABLE_SEID,
SMC_NETLINK_DISABLE_SEID,
+ SMC_NETLINK_DUMP_HS_LIMITATION,
+ SMC_NETLINK_ENABLE_HS_LIMITATION,
+ SMC_NETLINK_DISABLE_HS_LIMITATION,
};
enum {
SMC_GEN_UNSPEC,
@@ -249,4 +252,11 @@
__SMC_NLA_SEID_TABLE_MAX,
SMC_NLA_SEID_TABLE_MAX = __SMC_NLA_SEID_TABLE_MAX - 1
};
+enum {
+ SMC_NLA_HS_LIMITATION_UNSPEC,
+ SMC_NLA_HS_LIMITATION_ENABLED,
+ __SMC_NLA_HS_LIMITATION_MAX,
+ SMC_NLA_HS_LIMITATION_MAX = __SMC_NLA_HS_LIMITATION_MAX - 1
+};
+#define SMC_LIMIT_HS 1
#endif
diff --git a/libc/kernel/uapi/linux/socket.h b/libc/kernel/uapi/linux/socket.h
index be16548..4a530a8 100644
--- a/libc/kernel/uapi/linux/socket.h
+++ b/libc/kernel/uapi/linux/socket.h
@@ -32,4 +32,7 @@
#define SOCK_SNDBUF_LOCK 1
#define SOCK_RCVBUF_LOCK 2
#define SOCK_BUF_LOCK_MASK (SOCK_SNDBUF_LOCK | SOCK_RCVBUF_LOCK)
+#define SOCK_TXREHASH_DEFAULT 255
+#define SOCK_TXREHASH_DISABLED 0
+#define SOCK_TXREHASH_ENABLED 1
#endif
diff --git a/libc/kernel/uapi/linux/spi/spi.h b/libc/kernel/uapi/linux/spi/spi.h
index 39267a2..693e752 100644
--- a/libc/kernel/uapi/linux/spi/spi.h
+++ b/libc/kernel/uapi/linux/spi/spi.h
@@ -40,5 +40,6 @@
#define SPI_TX_OCTAL _BITUL(13)
#define SPI_RX_OCTAL _BITUL(14)
#define SPI_3WIRE_HIZ _BITUL(15)
-#define SPI_MODE_USER_MASK (_BITUL(16) - 1)
+#define SPI_RX_CPHA_FLIP _BITUL(16)
+#define SPI_MODE_USER_MASK (_BITUL(17) - 1)
#endif
diff --git a/libc/kernel/uapi/linux/stddef.h b/libc/kernel/uapi/linux/stddef.h
index d5cdf80..6bc6925 100644
--- a/libc/kernel/uapi/linux/stddef.h
+++ b/libc/kernel/uapi/linux/stddef.h
@@ -16,9 +16,12 @@
***
****************************************************************************
****************************************************************************/
+#ifndef _UAPI_LINUX_STDDEF_H
+#define _UAPI_LINUX_STDDEF_H
#include <linux/compiler_types.h>
#ifndef __always_inline
#define __always_inline inline
#endif
#define __struct_group(TAG,NAME,ATTRS,MEMBERS...) union { struct { MEMBERS } ATTRS; struct TAG { MEMBERS } ATTRS NAME; }
#define __DECLARE_FLEX_ARRAY(TYPE,NAME) struct { struct { } __empty_ ##NAME; TYPE NAME[]; }
+#endif
diff --git a/libc/kernel/uapi/linux/taskstats.h b/libc/kernel/uapi/linux/taskstats.h
index efa5b4a..c1cda52 100644
--- a/libc/kernel/uapi/linux/taskstats.h
+++ b/libc/kernel/uapi/linux/taskstats.h
@@ -19,7 +19,7 @@
#ifndef _LINUX_TASKSTATS_H
#define _LINUX_TASKSTATS_H
#include <linux/types.h>
-#define TASKSTATS_VERSION 11
+#define TASKSTATS_VERSION 13
#define TS_COMM_LEN 32
struct taskstats {
__u16 version;
@@ -71,6 +71,12 @@
__u64 ac_btime64;
__u64 compact_count;
__u64 compact_delay_total;
+ __u32 ac_tgid;
+ __u64 ac_tgetime __attribute__((aligned(8)));
+ __u64 ac_exe_dev;
+ __u64 ac_exe_inode;
+ __u64 wpcopy_count;
+ __u64 wpcopy_delay_total;
};
enum {
TASKSTATS_CMD_UNSPEC = 0,
diff --git a/libc/kernel/uapi/linux/tc_act/tc_skbedit.h b/libc/kernel/uapi/linux/tc_act/tc_skbedit.h
index 5706d4d..b041a6a 100644
--- a/libc/kernel/uapi/linux/tc_act/tc_skbedit.h
+++ b/libc/kernel/uapi/linux/tc_act/tc_skbedit.h
@@ -25,6 +25,7 @@
#define SKBEDIT_F_PTYPE 0x8
#define SKBEDIT_F_MASK 0x10
#define SKBEDIT_F_INHERITDSFIELD 0x20
+#define SKBEDIT_F_TXQ_SKBHASH 0x40
struct tc_skbedit {
tc_gen;
};
@@ -39,6 +40,7 @@
TCA_SKBEDIT_PTYPE,
TCA_SKBEDIT_MASK,
TCA_SKBEDIT_FLAGS,
+ TCA_SKBEDIT_QUEUE_MAPPING_MAX,
__TCA_SKBEDIT_MAX
};
#define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
diff --git a/libc/kernel/uapi/linux/tee.h b/libc/kernel/uapi/linux/tee.h
index 5cfe713..404b7b2 100644
--- a/libc/kernel/uapi/linux/tee.h
+++ b/libc/kernel/uapi/linux/tee.h
@@ -22,8 +22,6 @@
#include <linux/types.h>
#define TEE_IOC_MAGIC 0xa4
#define TEE_IOC_BASE 0
-#define TEE_IOCTL_SHM_MAPPED 0x1
-#define TEE_IOCTL_SHM_DMA_BUF 0x2
#define TEE_MAX_ARG_SIZE 1024
#define TEE_GEN_CAP_GP (1 << 0)
#define TEE_GEN_CAP_PRIVILEGED (1 << 1)
diff --git a/libc/kernel/uapi/linux/thermal.h b/libc/kernel/uapi/linux/thermal.h
index 72ea378..2f9dccb 100644
--- a/libc/kernel/uapi/linux/thermal.h
+++ b/libc/kernel/uapi/linux/thermal.h
@@ -54,6 +54,10 @@
THERMAL_GENL_ATTR_CDEV_MAX_STATE,
THERMAL_GENL_ATTR_CDEV_NAME,
THERMAL_GENL_ATTR_GOV_NAME,
+ THERMAL_GENL_ATTR_CPU_CAPABILITY,
+ THERMAL_GENL_ATTR_CPU_CAPABILITY_ID,
+ THERMAL_GENL_ATTR_CPU_CAPABILITY_PERFORMANCE,
+ THERMAL_GENL_ATTR_CPU_CAPABILITY_EFFICIENCY,
__THERMAL_GENL_ATTR_MAX,
};
#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
@@ -77,6 +81,7 @@
THERMAL_GENL_EVENT_CDEV_DELETE,
THERMAL_GENL_EVENT_CDEV_STATE_UPDATE,
THERMAL_GENL_EVENT_TZ_GOV_CHANGE,
+ THERMAL_GENL_EVENT_CPU_CAPABILITY_CHANGE,
__THERMAL_GENL_EVENT_MAX,
};
#define THERMAL_GENL_EVENT_MAX (__THERMAL_GENL_EVENT_MAX - 1)
diff --git a/libc/kernel/uapi/linux/tipc_config.h b/libc/kernel/uapi/linux/tipc_config.h
index a371e37..c6ee1d1 100644
--- a/libc/kernel/uapi/linux/tipc_config.h
+++ b/libc/kernel/uapi/linux/tipc_config.h
@@ -22,7 +22,6 @@
#include <linux/string.h>
#include <linux/tipc.h>
#include <asm/byteorder.h>
-#include <arpa/inet.h>
#define TIPC_CMD_NOOP 0x0000
#define TIPC_CMD_GET_NODES 0x0001
#define TIPC_CMD_GET_MEDIA_NAMES 0x0002
diff --git a/libc/kernel/uapi/linux/tls.h b/libc/kernel/uapi/linux/tls.h
index c98ea0b..4501cda 100644
--- a/libc/kernel/uapi/linux/tls.h
+++ b/libc/kernel/uapi/linux/tls.h
@@ -21,6 +21,7 @@
#include <linux/types.h>
#define TLS_TX 1
#define TLS_RX 2
+#define TLS_TX_ZEROCOPY_RO 3
#define TLS_VERSION_MINOR(ver) ((ver) & 0xFF)
#define TLS_VERSION_MAJOR(ver) (((ver) >> 8) & 0xFF)
#define TLS_VERSION_NUMBER(id) ((((id ##_VERSION_MAJOR) & 0xFF) << 8) | ((id ##_VERSION_MINOR) & 0xFF))
@@ -120,6 +121,7 @@
TLS_INFO_CIPHER,
TLS_INFO_TXCONF,
TLS_INFO_RXCONF,
+ TLS_INFO_ZC_RO_TX,
__TLS_INFO_MAX,
};
#define TLS_INFO_MAX (__TLS_INFO_MAX - 1)
diff --git a/libc/kernel/uapi/linux/tty.h b/libc/kernel/uapi/linux/tty.h
index dcce572..a94e6e6 100644
--- a/libc/kernel/uapi/linux/tty.h
+++ b/libc/kernel/uapi/linux/tty.h
@@ -18,7 +18,6 @@
****************************************************************************/
#ifndef _UAPI_LINUX_TTY_H
#define _UAPI_LINUX_TTY_H
-#define NR_LDISCS 30
#define N_TTY 0
#define N_SLIP 1
#define N_MOUSE 2
@@ -48,4 +47,7 @@
#define N_SPEAKUP 26
#define N_NULL 27
#define N_MCTP 28
+#define N_DEVELOPMENT 29
+#define N_CAN327 30
+#define NR_LDISCS 31
#endif
diff --git a/libc/kernel/uapi/linux/types.h b/libc/kernel/uapi/linux/types.h
index 9145e66..f41d676 100644
--- a/libc/kernel/uapi/linux/types.h
+++ b/libc/kernel/uapi/linux/types.h
@@ -21,8 +21,8 @@
#include <asm/types.h>
#ifndef __ASSEMBLY__
#include <linux/posix_types.h>
-#define __bitwise__
-#define __bitwise __bitwise__
+#define __bitwise
+#define __bitwise__ __bitwise
typedef __u16 __bitwise __le16;
typedef __u16 __bitwise __be16;
typedef __u32 __bitwise __le32;
diff --git a/libc/kernel/uapi/linux/userfaultfd.h b/libc/kernel/uapi/linux/userfaultfd.h
index ca7b7a5..46d7472 100644
--- a/libc/kernel/uapi/linux/userfaultfd.h
+++ b/libc/kernel/uapi/linux/userfaultfd.h
@@ -21,10 +21,10 @@
#include <linux/types.h>
#define UFFD_API ((__u64) 0xAA)
#define UFFD_API_REGISTER_MODES (UFFDIO_REGISTER_MODE_MISSING | UFFDIO_REGISTER_MODE_WP | UFFDIO_REGISTER_MODE_MINOR)
-#define UFFD_API_FEATURES (UFFD_FEATURE_PAGEFAULT_FLAG_WP | UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_EVENT_REMAP | UFFD_FEATURE_EVENT_REMOVE | UFFD_FEATURE_EVENT_UNMAP | UFFD_FEATURE_MISSING_HUGETLBFS | UFFD_FEATURE_MISSING_SHMEM | UFFD_FEATURE_SIGBUS | UFFD_FEATURE_THREAD_ID | UFFD_FEATURE_MINOR_HUGETLBFS | UFFD_FEATURE_MINOR_SHMEM)
+#define UFFD_API_FEATURES (UFFD_FEATURE_PAGEFAULT_FLAG_WP | UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_EVENT_REMAP | UFFD_FEATURE_EVENT_REMOVE | UFFD_FEATURE_EVENT_UNMAP | UFFD_FEATURE_MISSING_HUGETLBFS | UFFD_FEATURE_MISSING_SHMEM | UFFD_FEATURE_SIGBUS | UFFD_FEATURE_THREAD_ID | UFFD_FEATURE_MINOR_HUGETLBFS | UFFD_FEATURE_MINOR_SHMEM | UFFD_FEATURE_EXACT_ADDRESS | UFFD_FEATURE_WP_HUGETLBFS_SHMEM)
#define UFFD_API_IOCTLS ((__u64) 1 << _UFFDIO_REGISTER | (__u64) 1 << _UFFDIO_UNREGISTER | (__u64) 1 << _UFFDIO_API)
#define UFFD_API_RANGE_IOCTLS ((__u64) 1 << _UFFDIO_WAKE | (__u64) 1 << _UFFDIO_COPY | (__u64) 1 << _UFFDIO_ZEROPAGE | (__u64) 1 << _UFFDIO_WRITEPROTECT | (__u64) 1 << _UFFDIO_CONTINUE)
-#define UFFD_API_RANGE_IOCTLS_BASIC ((__u64) 1 << _UFFDIO_WAKE | (__u64) 1 << _UFFDIO_COPY | (__u64) 1 << _UFFDIO_CONTINUE)
+#define UFFD_API_RANGE_IOCTLS_BASIC ((__u64) 1 << _UFFDIO_WAKE | (__u64) 1 << _UFFDIO_COPY | (__u64) 1 << _UFFDIO_CONTINUE | (__u64) 1 << _UFFDIO_WRITEPROTECT)
#define _UFFDIO_REGISTER (0x00)
#define _UFFDIO_UNREGISTER (0x01)
#define _UFFDIO_WAKE (0x02)
@@ -95,6 +95,8 @@
#define UFFD_FEATURE_THREAD_ID (1 << 8)
#define UFFD_FEATURE_MINOR_HUGETLBFS (1 << 9)
#define UFFD_FEATURE_MINOR_SHMEM (1 << 10)
+#define UFFD_FEATURE_EXACT_ADDRESS (1 << 11)
+#define UFFD_FEATURE_WP_HUGETLBFS_SHMEM (1 << 12)
__u64 features;
__u64 ioctls;
};
diff --git a/libc/kernel/uapi/linux/v4l2-controls.h b/libc/kernel/uapi/linux/v4l2-controls.h
index 1a11355..30a0553 100644
--- a/libc/kernel/uapi/linux/v4l2-controls.h
+++ b/libc/kernel/uapi/linux/v4l2-controls.h
@@ -119,6 +119,7 @@
#define V4L2_CID_USER_CODA_BASE (V4L2_CID_USER_BASE + 0x10e0)
#define V4L2_CID_USER_CCS_BASE (V4L2_CID_USER_BASE + 0x10f0)
#define V4L2_CID_USER_ALLEGRO_BASE (V4L2_CID_USER_BASE + 0x1170)
+#define V4L2_CID_USER_ISL7998X_BASE (V4L2_CID_USER_BASE + 0x1180)
#define V4L2_CID_CODEC_BASE (V4L2_CTRL_CLASS_CODEC | 0x900)
#define V4L2_CID_CODEC_CLASS (V4L2_CTRL_CLASS_CODEC | 1)
#define V4L2_CID_MPEG_STREAM_TYPE (V4L2_CID_CODEC_BASE + 0)
@@ -329,6 +330,11 @@
#define V4L2_CID_MPEG_VIDEO_USE_LTR_FRAMES (V4L2_CID_CODEC_BASE + 234)
#define V4L2_CID_MPEG_VIDEO_DEC_CONCEAL_COLOR (V4L2_CID_CODEC_BASE + 235)
#define V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD (V4L2_CID_CODEC_BASE + 236)
+#define V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE (V4L2_CID_CODEC_BASE + 237)
+enum v4l2_mpeg_video_intra_refresh_period_type {
+ V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM = 0,
+ V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC = 1,
+};
#define V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL (V4L2_CID_CODEC_BASE + 270)
enum v4l2_mpeg_video_mpeg2_level {
V4L2_MPEG_VIDEO_MPEG2_LEVEL_LOW = 0,
@@ -1153,6 +1159,8 @@
#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01
#define V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC 0x02
#define V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD 0x04
+#define V4L2_H264_DECODE_PARAM_FLAG_PFRAME 0x08
+#define V4L2_H264_DECODE_PARAM_FLAG_BFRAME 0x10
#define V4L2_CID_STATELESS_H264_DECODE_PARAMS (V4L2_CID_CODEC_STATELESS_BASE + 7)
struct v4l2_ctrl_h264_decode_params {
struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES];
diff --git a/libc/kernel/uapi/linux/vdpa.h b/libc/kernel/uapi/linux/vdpa.h
index b3e5d39..8b3be00 100644
--- a/libc/kernel/uapi/linux/vdpa.h
+++ b/libc/kernel/uapi/linux/vdpa.h
@@ -28,6 +28,7 @@
VDPA_CMD_DEV_DEL,
VDPA_CMD_DEV_GET,
VDPA_CMD_DEV_CONFIG_GET,
+ VDPA_CMD_DEV_VSTATS_GET,
};
enum vdpa_attr {
VDPA_ATTR_UNSPEC,
@@ -48,6 +49,9 @@
VDPA_ATTR_DEV_NEGOTIATED_FEATURES,
VDPA_ATTR_DEV_MGMTDEV_MAX_VQS,
VDPA_ATTR_DEV_SUPPORTED_FEATURES,
+ VDPA_ATTR_DEV_QUEUE_INDEX,
+ VDPA_ATTR_DEV_VENDOR_ATTR_NAME,
+ VDPA_ATTR_DEV_VENDOR_ATTR_VALUE,
VDPA_ATTR_MAX,
};
#endif
diff --git a/libc/kernel/uapi/linux/version.h b/libc/kernel/uapi/linux/version.h
index 2dfd696..62874da 100644
--- a/libc/kernel/uapi/linux/version.h
+++ b/libc/kernel/uapi/linux/version.h
@@ -16,8 +16,8 @@
***
****************************************************************************
****************************************************************************/
-#define LINUX_VERSION_CODE 332032
+#define LINUX_VERSION_CODE 332544
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
#define LINUX_VERSION_MAJOR 5
-#define LINUX_VERSION_PATCHLEVEL 17
+#define LINUX_VERSION_PATCHLEVEL 19
#define LINUX_VERSION_SUBLEVEL 0
diff --git a/libc/kernel/uapi/linux/vfio.h b/libc/kernel/uapi/linux/vfio.h
index e0f322b..8075408 100644
--- a/libc/kernel/uapi/linux/vfio.h
+++ b/libc/kernel/uapi/linux/vfio.h
@@ -110,7 +110,7 @@
#define VFIO_REGION_TYPE_PCI_VENDOR_MASK (0xffff)
#define VFIO_REGION_TYPE_GFX (1)
#define VFIO_REGION_TYPE_CCW (2)
-#define VFIO_REGION_TYPE_MIGRATION (3)
+#define VFIO_REGION_TYPE_MIGRATION_DEPRECATED (3)
#define VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION (1)
#define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2)
#define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3)
@@ -130,17 +130,17 @@
#define VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD (1)
#define VFIO_REGION_SUBTYPE_CCW_SCHIB (2)
#define VFIO_REGION_SUBTYPE_CCW_CRW (3)
-#define VFIO_REGION_SUBTYPE_MIGRATION (1)
+#define VFIO_REGION_SUBTYPE_MIGRATION_DEPRECATED (1)
struct vfio_device_migration_info {
__u32 device_state;
-#define VFIO_DEVICE_STATE_STOP (0)
-#define VFIO_DEVICE_STATE_RUNNING (1 << 0)
-#define VFIO_DEVICE_STATE_SAVING (1 << 1)
-#define VFIO_DEVICE_STATE_RESUMING (1 << 2)
-#define VFIO_DEVICE_STATE_MASK (VFIO_DEVICE_STATE_RUNNING | VFIO_DEVICE_STATE_SAVING | VFIO_DEVICE_STATE_RESUMING)
-#define VFIO_DEVICE_STATE_VALID(state) (state & VFIO_DEVICE_STATE_RESUMING ? (state & VFIO_DEVICE_STATE_MASK) == VFIO_DEVICE_STATE_RESUMING : 1)
-#define VFIO_DEVICE_STATE_IS_ERROR(state) ((state & VFIO_DEVICE_STATE_MASK) == (VFIO_DEVICE_STATE_SAVING | VFIO_DEVICE_STATE_RESUMING))
-#define VFIO_DEVICE_STATE_SET_ERROR(state) ((state & ~VFIO_DEVICE_STATE_MASK) | VFIO_DEVICE_SATE_SAVING | VFIO_DEVICE_STATE_RESUMING)
+#define VFIO_DEVICE_STATE_V1_STOP (0)
+#define VFIO_DEVICE_STATE_V1_RUNNING (1 << 0)
+#define VFIO_DEVICE_STATE_V1_SAVING (1 << 1)
+#define VFIO_DEVICE_STATE_V1_RESUMING (1 << 2)
+#define VFIO_DEVICE_STATE_MASK (VFIO_DEVICE_STATE_V1_RUNNING | VFIO_DEVICE_STATE_V1_SAVING | VFIO_DEVICE_STATE_V1_RESUMING)
+#define VFIO_DEVICE_STATE_VALID(state) (state & VFIO_DEVICE_STATE_V1_RESUMING ? (state & VFIO_DEVICE_STATE_MASK) == VFIO_DEVICE_STATE_V1_RESUMING : 1)
+#define VFIO_DEVICE_STATE_IS_ERROR(state) ((state & VFIO_DEVICE_STATE_MASK) == (VFIO_DEVICE_STATE_V1_SAVING | VFIO_DEVICE_STATE_V1_RESUMING))
+#define VFIO_DEVICE_STATE_SET_ERROR(state) ((state & ~VFIO_DEVICE_STATE_MASK) | VFIO_DEVICE_STATE_V1_SAVING | VFIO_DEVICE_STATE_V1_RESUMING)
__u32 reserved;
__u64 pending_bytes;
__u64 data_offset;
@@ -285,6 +285,25 @@
};
#define VFIO_DEVICE_FEATURE _IO(VFIO_TYPE, VFIO_BASE + 17)
#define VFIO_DEVICE_FEATURE_PCI_VF_TOKEN (0)
+struct vfio_device_feature_migration {
+ __aligned_u64 flags;
+#define VFIO_MIGRATION_STOP_COPY (1 << 0)
+#define VFIO_MIGRATION_P2P (1 << 1)
+};
+#define VFIO_DEVICE_FEATURE_MIGRATION 1
+struct vfio_device_feature_mig_state {
+ __u32 device_state;
+ __s32 data_fd;
+};
+#define VFIO_DEVICE_FEATURE_MIG_DEVICE_STATE 2
+enum vfio_device_mig_state {
+ VFIO_DEVICE_STATE_ERROR = 0,
+ VFIO_DEVICE_STATE_STOP = 1,
+ VFIO_DEVICE_STATE_RUNNING = 2,
+ VFIO_DEVICE_STATE_STOP_COPY = 3,
+ VFIO_DEVICE_STATE_RESUMING = 4,
+ VFIO_DEVICE_STATE_RUNNING_P2P = 5,
+};
struct vfio_iommu_type1_info {
__u32 argsz;
__u32 flags;
diff --git a/libc/kernel/uapi/linux/vhost.h b/libc/kernel/uapi/linux/vhost.h
index 53b01c4..3bf1372 100644
--- a/libc/kernel/uapi/linux/vhost.h
+++ b/libc/kernel/uapi/linux/vhost.h
@@ -43,8 +43,6 @@
#define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
#define VHOST_SET_VRING_BUSYLOOP_TIMEOUT _IOW(VHOST_VIRTIO, 0x23, struct vhost_vring_state)
#define VHOST_GET_VRING_BUSYLOOP_TIMEOUT _IOW(VHOST_VIRTIO, 0x24, struct vhost_vring_state)
-#define VHOST_BACKEND_F_IOTLB_MSG_V2 0x1
-#define VHOST_BACKEND_F_IOTLB_BATCH 0x2
#define VHOST_SET_BACKEND_FEATURES _IOW(VHOST_VIRTIO, 0x25, __u64)
#define VHOST_GET_BACKEND_FEATURES _IOR(VHOST_VIRTIO, 0x26, __u64)
#define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
@@ -64,4 +62,10 @@
#define VHOST_VDPA_GET_VRING_NUM _IOR(VHOST_VIRTIO, 0x76, __u16)
#define VHOST_VDPA_SET_CONFIG_CALL _IOW(VHOST_VIRTIO, 0x77, int)
#define VHOST_VDPA_GET_IOVA_RANGE _IOR(VHOST_VIRTIO, 0x78, struct vhost_vdpa_iova_range)
+#define VHOST_VDPA_GET_CONFIG_SIZE _IOR(VHOST_VIRTIO, 0x79, __u32)
+#define VHOST_VDPA_GET_VQS_COUNT _IOR(VHOST_VIRTIO, 0x80, __u32)
+#define VHOST_VDPA_GET_GROUP_NUM _IOR(VHOST_VIRTIO, 0x81, __u32)
+#define VHOST_VDPA_GET_AS_NUM _IOR(VHOST_VIRTIO, 0x7A, unsigned int)
+#define VHOST_VDPA_GET_VRING_GROUP _IOWR(VHOST_VIRTIO, 0x7B, struct vhost_vring_state)
+#define VHOST_VDPA_SET_GROUP_ASID _IOW(VHOST_VIRTIO, 0x7C, struct vhost_vring_state)
#endif
diff --git a/libc/kernel/uapi/linux/vhost_types.h b/libc/kernel/uapi/linux/vhost_types.h
index 6b4cc77..772a1cc 100644
--- a/libc/kernel/uapi/linux/vhost_types.h
+++ b/libc/kernel/uapi/linux/vhost_types.h
@@ -66,7 +66,7 @@
};
struct vhost_msg_v2 {
__u32 type;
- __u32 reserved;
+ __u32 asid;
union {
struct vhost_iotlb_msg iotlb;
__u8 padding[64];
@@ -102,4 +102,7 @@
};
#define VHOST_F_LOG_ALL 26
#define VHOST_NET_F_VIRTIO_NET_HDR 27
+#define VHOST_BACKEND_F_IOTLB_MSG_V2 0x1
+#define VHOST_BACKEND_F_IOTLB_BATCH 0x2
+#define VHOST_BACKEND_F_IOTLB_ASID 0x3
#endif
diff --git a/libc/kernel/uapi/linux/videodev2.h b/libc/kernel/uapi/linux/videodev2.h
index 74bd328..d4107bc 100644
--- a/libc/kernel/uapi/linux/videodev2.h
+++ b/libc/kernel/uapi/linux/videodev2.h
@@ -24,12 +24,7 @@
#include <linux/types.h>
#include <linux/v4l2-common.h>
#include <linux/v4l2-controls.h>
-/* ---------------------------------------------------
- * This value manually changed due to b/228783882.
- * Next kernel update should keep this value as is.
- */
#define VIDEO_MAX_FRAME 64
-/* --------------------------------------------------- */
#define VIDEO_MAX_PLANES 8
#define v4l2_fourcc(a,b,c,d) ((__u32) (a) | ((__u32) (b) << 8) | ((__u32) (c) << 16) | ((__u32) (d) << 24))
#define v4l2_fourcc_be(a,b,c,d) (v4l2_fourcc(a, b, c, d) | (1U << 31))
@@ -260,6 +255,7 @@
#define V4L2_PIX_FMT_Y16_BE v4l2_fourcc_be('Y', '1', '6', ' ')
#define V4L2_PIX_FMT_Y10BPACK v4l2_fourcc('Y', '1', '0', 'B')
#define V4L2_PIX_FMT_Y10P v4l2_fourcc('Y', '1', '0', 'P')
+#define V4L2_PIX_FMT_IPU3_Y10 v4l2_fourcc('i', 'p', '3', 'y')
#define V4L2_PIX_FMT_PAL8 v4l2_fourcc('P', 'A', 'L', '8')
#define V4L2_PIX_FMT_UV8 v4l2_fourcc('U', 'V', '8', ' ')
#define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y', 'U', 'Y', 'V')
@@ -305,6 +301,8 @@
#define V4L2_PIX_FMT_NV12_32L32 v4l2_fourcc('S', 'T', '1', '2')
#define V4L2_PIX_FMT_NV12MT v4l2_fourcc('T', 'M', '1', '2')
#define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2')
+#define V4L2_PIX_FMT_NV12M_8L128 v4l2_fourcc('N', 'A', '1', '2')
+#define V4L2_PIX_FMT_NV12M_10BE_8L128 v4l2_fourcc_be('N', 'T', '1', '2')
#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1')
#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G')
#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G')
@@ -404,6 +402,8 @@
#define V4L2_PIX_FMT_INZI v4l2_fourcc('I', 'N', 'Z', 'I')
#define V4L2_PIX_FMT_CNF4 v4l2_fourcc('C', 'N', 'F', '4')
#define V4L2_PIX_FMT_HI240 v4l2_fourcc('H', 'I', '2', '4')
+#define V4L2_PIX_FMT_QC08C v4l2_fourcc('Q', '0', '8', 'C')
+#define V4L2_PIX_FMT_QC10C v4l2_fourcc('Q', '1', '0', 'C')
#define V4L2_PIX_FMT_IPU3_SBGGR10 v4l2_fourcc('i', 'p', '3', 'b')
#define V4L2_PIX_FMT_IPU3_SGBRG10 v4l2_fourcc('i', 'p', '3', 'g')
#define V4L2_PIX_FMT_IPU3_SGRBG10 v4l2_fourcc('i', 'p', '3', 'G')
diff --git a/libc/kernel/uapi/linux/virtio_config.h b/libc/kernel/uapi/linux/virtio_config.h
index 6198fd1..30e552b 100644
--- a/libc/kernel/uapi/linux/virtio_config.h
+++ b/libc/kernel/uapi/linux/virtio_config.h
@@ -35,6 +35,7 @@
#define VIRTIO_F_ACCESS_PLATFORM 33
#define VIRTIO_F_IOMMU_PLATFORM VIRTIO_F_ACCESS_PLATFORM
#define VIRTIO_F_RING_PACKED 34
+#define VIRTIO_F_IN_ORDER 35
#define VIRTIO_F_ORDER_PLATFORM 36
#define VIRTIO_F_SR_IOV 37
#endif
diff --git a/libc/kernel/uapi/linux/virtio_crypto.h b/libc/kernel/uapi/linux/virtio_crypto.h
index 2ce760f..7d7561d 100644
--- a/libc/kernel/uapi/linux/virtio_crypto.h
+++ b/libc/kernel/uapi/linux/virtio_crypto.h
@@ -26,6 +26,7 @@
#define VIRTIO_CRYPTO_SERVICE_HASH 1
#define VIRTIO_CRYPTO_SERVICE_MAC 2
#define VIRTIO_CRYPTO_SERVICE_AEAD 3
+#define VIRTIO_CRYPTO_SERVICE_AKCIPHER 4
#define VIRTIO_CRYPTO_OPCODE(service,op) (((service) << 8) | (op))
struct virtio_crypto_ctrl_header {
#define VIRTIO_CRYPTO_CIPHER_CREATE_SESSION VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_CIPHER, 0x02)
@@ -36,6 +37,8 @@
#define VIRTIO_CRYPTO_MAC_DESTROY_SESSION VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_MAC, 0x03)
#define VIRTIO_CRYPTO_AEAD_CREATE_SESSION VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x02)
#define VIRTIO_CRYPTO_AEAD_DESTROY_SESSION VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x03)
+#define VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x04)
+#define VIRTIO_CRYPTO_AKCIPHER_DESTROY_SESSION VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x05)
__le32 opcode;
__le32 algo;
__le32 flag;
@@ -137,6 +140,51 @@
struct virtio_crypto_aead_session_para para;
__u8 padding[32];
};
+struct virtio_crypto_rsa_session_para {
+#define VIRTIO_CRYPTO_RSA_RAW_PADDING 0
+#define VIRTIO_CRYPTO_RSA_PKCS1_PADDING 1
+ __le32 padding_algo;
+#define VIRTIO_CRYPTO_RSA_NO_HASH 0
+#define VIRTIO_CRYPTO_RSA_MD2 1
+#define VIRTIO_CRYPTO_RSA_MD3 2
+#define VIRTIO_CRYPTO_RSA_MD4 3
+#define VIRTIO_CRYPTO_RSA_MD5 4
+#define VIRTIO_CRYPTO_RSA_SHA1 5
+#define VIRTIO_CRYPTO_RSA_SHA256 6
+#define VIRTIO_CRYPTO_RSA_SHA384 7
+#define VIRTIO_CRYPTO_RSA_SHA512 8
+#define VIRTIO_CRYPTO_RSA_SHA224 9
+ __le32 hash_algo;
+};
+struct virtio_crypto_ecdsa_session_para {
+#define VIRTIO_CRYPTO_CURVE_UNKNOWN 0
+#define VIRTIO_CRYPTO_CURVE_NIST_P192 1
+#define VIRTIO_CRYPTO_CURVE_NIST_P224 2
+#define VIRTIO_CRYPTO_CURVE_NIST_P256 3
+#define VIRTIO_CRYPTO_CURVE_NIST_P384 4
+#define VIRTIO_CRYPTO_CURVE_NIST_P521 5
+ __le32 curve_id;
+ __le32 padding;
+};
+struct virtio_crypto_akcipher_session_para {
+#define VIRTIO_CRYPTO_NO_AKCIPHER 0
+#define VIRTIO_CRYPTO_AKCIPHER_RSA 1
+#define VIRTIO_CRYPTO_AKCIPHER_DSA 2
+#define VIRTIO_CRYPTO_AKCIPHER_ECDSA 3
+ __le32 algo;
+#define VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC 1
+#define VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE 2
+ __le32 keytype;
+ __le32 keylen;
+ union {
+ struct virtio_crypto_rsa_session_para rsa;
+ struct virtio_crypto_ecdsa_session_para ecdsa;
+ } u;
+};
+struct virtio_crypto_akcipher_create_session_req {
+ struct virtio_crypto_akcipher_session_para para;
+ __u8 padding[36];
+};
struct virtio_crypto_alg_chain_session_para {
#define VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER 1
#define VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH 2
@@ -180,6 +228,7 @@
struct virtio_crypto_hash_create_session_req hash_create_session;
struct virtio_crypto_mac_create_session_req mac_create_session;
struct virtio_crypto_aead_create_session_req aead_create_session;
+ struct virtio_crypto_akcipher_create_session_req akcipher_create_session;
struct virtio_crypto_destroy_session_req destroy_session;
__u8 padding[56];
} u;
@@ -191,6 +240,10 @@
#define VIRTIO_CRYPTO_MAC VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_MAC, 0x00)
#define VIRTIO_CRYPTO_AEAD_ENCRYPT VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x00)
#define VIRTIO_CRYPTO_AEAD_DECRYPT VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x01)
+#define VIRTIO_CRYPTO_AKCIPHER_ENCRYPT VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x00)
+#define VIRTIO_CRYPTO_AKCIPHER_DECRYPT VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x01)
+#define VIRTIO_CRYPTO_AKCIPHER_SIGN VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x02)
+#define VIRTIO_CRYPTO_AKCIPHER_VERIFY VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x03)
__le32 opcode;
__le32 algo;
__le64 session_id;
@@ -256,6 +309,14 @@
struct virtio_crypto_aead_para para;
__u8 padding[32];
};
+struct virtio_crypto_akcipher_para {
+ __le32 src_data_len;
+ __le32 dst_data_len;
+};
+struct virtio_crypto_akcipher_data_req {
+ struct virtio_crypto_akcipher_para para;
+ __u8 padding[40];
+};
struct virtio_crypto_op_data_req {
struct virtio_crypto_op_header header;
union {
@@ -263,6 +324,7 @@
struct virtio_crypto_hash_data_req hash_req;
struct virtio_crypto_mac_data_req mac_req;
struct virtio_crypto_aead_data_req aead_req;
+ struct virtio_crypto_akcipher_data_req akcipher_req;
__u8 padding[48];
} u;
};
@@ -271,6 +333,8 @@
#define VIRTIO_CRYPTO_BADMSG 2
#define VIRTIO_CRYPTO_NOTSUPP 3
#define VIRTIO_CRYPTO_INVSESS 4
+#define VIRTIO_CRYPTO_NOSPC 5
+#define VIRTIO_CRYPTO_KEY_REJECTED 6
#define VIRTIO_CRYPTO_S_HW_READY (1 << 0)
struct virtio_crypto_config {
__le32 status;
@@ -284,7 +348,7 @@
__le32 aead_algo;
__le32 max_cipher_key_len;
__le32 max_auth_key_len;
- __le32 reserve;
+ __le32 akcipher_algo;
__le64 max_size;
};
struct virtio_crypto_inhdr {
diff --git a/libc/kernel/uapi/linux/virtio_ids.h b/libc/kernel/uapi/linux/virtio_ids.h
index 2894700..b31ed93 100644
--- a/libc/kernel/uapi/linux/virtio_ids.h
+++ b/libc/kernel/uapi/linux/virtio_ids.h
@@ -57,11 +57,11 @@
#define VIRTIO_ID_AUDIO_POLICY 39
#define VIRTIO_ID_BT 40
#define VIRTIO_ID_GPIO 41
-#define VIRTIO_TRANS_ID_NET 1000
-#define VIRTIO_TRANS_ID_BLOCK 1001
-#define VIRTIO_TRANS_ID_BALLOON 1002
-#define VIRTIO_TRANS_ID_CONSOLE 1003
-#define VIRTIO_TRANS_ID_SCSI 1004
-#define VIRTIO_TRANS_ID_RNG 1005
-#define VIRTIO_TRANS_ID_9P 1009
+#define VIRTIO_TRANS_ID_NET 0x1000
+#define VIRTIO_TRANS_ID_BLOCK 0x1001
+#define VIRTIO_TRANS_ID_BALLOON 0x1002
+#define VIRTIO_TRANS_ID_CONSOLE 0x1003
+#define VIRTIO_TRANS_ID_SCSI 0x1004
+#define VIRTIO_TRANS_ID_RNG 0x1005
+#define VIRTIO_TRANS_ID_9P 0x1009
#endif
diff --git a/libc/kernel/uapi/misc/fastrpc.h b/libc/kernel/uapi/misc/fastrpc.h
index 62955ec..e82b961 100644
--- a/libc/kernel/uapi/misc/fastrpc.h
+++ b/libc/kernel/uapi/misc/fastrpc.h
@@ -27,11 +27,32 @@
#define FASTRPC_IOCTL_MMAP _IOWR('R', 6, struct fastrpc_req_mmap)
#define FASTRPC_IOCTL_MUNMAP _IOWR('R', 7, struct fastrpc_req_munmap)
#define FASTRPC_IOCTL_INIT_ATTACH_SNS _IO('R', 8)
+#define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_mem_map)
+#define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_mem_unmap)
+#define FASTRPC_IOCTL_GET_DSP_INFO _IOWR('R', 13, struct fastrpc_ioctl_capability)
+enum fastrpc_map_flags {
+ FASTRPC_MAP_STATIC = 0,
+ FASTRPC_MAP_RESERVED,
+ FASTRPC_MAP_FD = 2,
+ FASTRPC_MAP_FD_DELAYED,
+ FASTRPC_MAP_FD_NOMAP = 16,
+ FASTRPC_MAP_MAX,
+};
+enum fastrpc_proc_attr {
+ FASTRPC_MODE_DEBUG = (1 << 0),
+ FASTRPC_MODE_PTRACE = (1 << 1),
+ FASTRPC_MODE_CRC = (1 << 2),
+ FASTRPC_MODE_UNSIGNED_MODULE = (1 << 3),
+ FASTRPC_MODE_ADAPTIVE_QOS = (1 << 4),
+ FASTRPC_MODE_SYSTEM_PROCESS = (1 << 5),
+ FASTRPC_MODE_PRIVILEGED = (1 << 6),
+};
+#define FASTRPC_ATTR_SECUREMAP (1)
struct fastrpc_invoke_args {
__u64 ptr;
__u64 length;
__s32 fd;
- __u32 reserved;
+ __u32 attr;
};
struct fastrpc_invoke {
__u32 handle;
@@ -57,8 +78,32 @@
__u64 size;
__u64 vaddrout;
};
+struct fastrpc_mem_map {
+ __s32 version;
+ __s32 fd;
+ __s32 offset;
+ __u32 flags;
+ __u64 vaddrin;
+ __u64 length;
+ __u64 vaddrout;
+ __s32 attrs;
+ __s32 reserved[4];
+};
struct fastrpc_req_munmap {
__u64 vaddrout;
__u64 size;
};
+struct fastrpc_mem_unmap {
+ __s32 vesion;
+ __s32 fd;
+ __u64 vaddr;
+ __u64 length;
+ __s32 reserved[5];
+};
+struct fastrpc_ioctl_capability {
+ __u32 domain;
+ __u32 attribute_id;
+ __u32 capability;
+ __u32 reserved[4];
+};
#endif
diff --git a/libc/kernel/uapi/misc/habanalabs.h b/libc/kernel/uapi/misc/habanalabs.h
index 6e3439a..2d18d7e 100644
--- a/libc/kernel/uapi/misc/habanalabs.h
+++ b/libc/kernel/uapi/misc/habanalabs.h
@@ -24,6 +24,7 @@
#define GAUDI_DRIVER_SRAM_RESERVED_SIZE_FROM_START 0x80
#define GAUDI_FIRST_AVAILABLE_W_S_SYNC_OBJECT 144
#define GAUDI_FIRST_AVAILABLE_W_S_MONITOR 72
+#define TS_MAX_ELEMENTS_NUM (1 << 20)
enum goya_queue_id {
GOYA_QUEUE_ID_DMA_0 = 0,
GOYA_QUEUE_ID_DMA_1 = 1,
@@ -269,6 +270,10 @@
#define HL_INFO_LAST_ERR_OPEN_DEV_TIME 23
#define HL_INFO_CS_TIMEOUT_EVENT 24
#define HL_INFO_RAZWI_EVENT 25
+#define HL_INFO_DEV_MEM_ALLOC_PAGE_SIZES 26
+#define HL_INFO_REGISTER_EVENTFD 28
+#define HL_INFO_UNREGISTER_EVENTFD 29
+#define HL_INFO_GET_EVENTS 30
#define HL_INFO_VERSION_MAX_LEN 128
#define HL_INFO_CARD_NAME_MAX_LEN 16
struct hl_info_hw_ip_info {
@@ -294,6 +299,11 @@
__u8 card_name[HL_INFO_CARD_NAME_MAX_LEN];
__u64 reserved2;
__u64 dram_page_size;
+ __u32 reserved3;
+ __u16 number_of_user_interrupts;
+ __u16 pad2;
+ __u64 reserved4;
+ __u64 device_mem_alloc_default_page_size;
};
struct hl_info_dram_usage {
__u64 dram_free_mem;
@@ -353,6 +363,9 @@
struct hl_open_stats_info {
__u64 open_counter;
__u64 last_open_period_ms;
+ __u8 is_compute_ctx_active;
+ __u8 compute_ctx_in_release;
+ __u8 pad[6];
};
struct hl_power_info {
__u64 power;
@@ -395,6 +408,9 @@
__u8 error_type;
__u8 pad[2];
};
+struct hl_info_dev_memalloc_page_sizes {
+ __u64 page_order_bitmask;
+};
enum gaudi_dcores {
HL_GAUDI_WS_DCORE,
HL_GAUDI_WN_DCORE,
@@ -410,6 +426,7 @@
__u32 ctx_id;
__u32 period_ms;
__u32 pll_index;
+ __u32 eventfd;
};
__u32 pad;
};
@@ -512,6 +529,7 @@
#define HL_WAIT_CS_FLAGS_INTERRUPT_MASK 0xFFF00000
#define HL_WAIT_CS_FLAGS_MULTI_CS 0x4
#define HL_WAIT_CS_FLAGS_INTERRUPT_KERNEL_CQ 0x10
+#define HL_WAIT_CS_FLAGS_REGISTER_INTERRUPT 0x20
#define HL_WAIT_MULTI_CS_LIST_MAX_LEN 32
struct hl_wait_cs_in {
union {
@@ -537,6 +555,8 @@
__u64 interrupt_timeout_us;
};
__u64 cq_counters_offset;
+ __u64 timestamp_handle;
+ __u64 timestamp_offset;
};
#define HL_WAIT_CS_STATUS_COMPLETED 0
#define HL_WAIT_CS_STATUS_BUSY 1
@@ -561,14 +581,17 @@
#define HL_MEM_OP_UNMAP 3
#define HL_MEM_OP_MAP_BLOCK 4
#define HL_MEM_OP_EXPORT_DMABUF_FD 5
+#define HL_MEM_OP_TS_ALLOC 6
#define HL_MEM_CONTIGUOUS 0x1
#define HL_MEM_SHARED 0x2
#define HL_MEM_USERPTR 0x4
#define HL_MEM_FORCE_HINT 0x8
+#define HL_MEM_PREFETCH 0x40
struct hl_mem_in {
union {
struct {
__u64 mem_size;
+ __u64 page_size;
} alloc;
struct {
__u64 handle;
@@ -596,7 +619,7 @@
__u32 op;
__u32 flags;
__u32 ctx_id;
- __u32 pad;
+ __u32 num_of_elements;
};
struct hl_mem_out {
union {
@@ -666,6 +689,7 @@
__u32 enable;
__u32 ctx_id;
};
+#define HL_NOTIFIER_EVENT_TPC_ASSERT (1 << 0)
#define HL_IOCTL_INFO _IOWR('H', 0x01, struct hl_info_args)
#define HL_IOCTL_CB _IOWR('H', 0x02, union hl_cb_args)
#define HL_IOCTL_CS _IOWR('H', 0x03, union hl_cs_args)
diff --git a/libc/kernel/uapi/rdma/ib_user_verbs.h b/libc/kernel/uapi/rdma/ib_user_verbs.h
index d9ac9e0..e24410e 100644
--- a/libc/kernel/uapi/rdma/ib_user_verbs.h
+++ b/libc/kernel/uapi/rdma/ib_user_verbs.h
@@ -1079,4 +1079,37 @@
__u32 reserved;
};
#define IB_DEVICE_NAME_MAX 64
+enum ib_uverbs_device_cap_flags {
+ IB_UVERBS_DEVICE_RESIZE_MAX_WR = 1 << 0,
+ IB_UVERBS_DEVICE_BAD_PKEY_CNTR = 1 << 1,
+ IB_UVERBS_DEVICE_BAD_QKEY_CNTR = 1 << 2,
+ IB_UVERBS_DEVICE_RAW_MULTI = 1 << 3,
+ IB_UVERBS_DEVICE_AUTO_PATH_MIG = 1 << 4,
+ IB_UVERBS_DEVICE_CHANGE_PHY_PORT = 1 << 5,
+ IB_UVERBS_DEVICE_UD_AV_PORT_ENFORCE = 1 << 6,
+ IB_UVERBS_DEVICE_CURR_QP_STATE_MOD = 1 << 7,
+ IB_UVERBS_DEVICE_SHUTDOWN_PORT = 1 << 8,
+ IB_UVERBS_DEVICE_PORT_ACTIVE_EVENT = 1 << 10,
+ IB_UVERBS_DEVICE_SYS_IMAGE_GUID = 1 << 11,
+ IB_UVERBS_DEVICE_RC_RNR_NAK_GEN = 1 << 12,
+ IB_UVERBS_DEVICE_SRQ_RESIZE = 1 << 13,
+ IB_UVERBS_DEVICE_N_NOTIFY_CQ = 1 << 14,
+ IB_UVERBS_DEVICE_MEM_WINDOW = 1 << 17,
+ IB_UVERBS_DEVICE_UD_IP_CSUM = 1 << 18,
+ IB_UVERBS_DEVICE_XRC = 1 << 20,
+ IB_UVERBS_DEVICE_MEM_MGT_EXTENSIONS = 1 << 21,
+ IB_UVERBS_DEVICE_MEM_WINDOW_TYPE_2A = 1 << 23,
+ IB_UVERBS_DEVICE_MEM_WINDOW_TYPE_2B = 1 << 24,
+ IB_UVERBS_DEVICE_RC_IP_CSUM = 1 << 25,
+ IB_UVERBS_DEVICE_RAW_IP_CSUM = 1 << 26,
+ IB_UVERBS_DEVICE_MANAGED_FLOW_STEERING = 1 << 29,
+ IB_UVERBS_DEVICE_RAW_SCATTER_FCS = 1ULL << 34,
+ IB_UVERBS_DEVICE_PCI_WRITE_END_PADDING = 1ULL << 36,
+};
+enum ib_uverbs_raw_packet_caps {
+ IB_UVERBS_RAW_PACKET_CAP_CVLAN_STRIPPING = 1 << 0,
+ IB_UVERBS_RAW_PACKET_CAP_SCATTER_FCS = 1 << 1,
+ IB_UVERBS_RAW_PACKET_CAP_IP_CSUM = 1 << 2,
+ IB_UVERBS_RAW_PACKET_CAP_DELAY_DROP = 1 << 3,
+};
#endif
diff --git a/libc/kernel/uapi/scsi/scsi_bsg_mpi3mr.h b/libc/kernel/uapi/scsi/scsi_bsg_mpi3mr.h
new file mode 100644
index 0000000..fcba8cd
--- /dev/null
+++ b/libc/kernel/uapi/scsi/scsi_bsg_mpi3mr.h
@@ -0,0 +1,333 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef SCSI_BSG_MPI3MR_H_INCLUDED
+#define SCSI_BSG_MPI3MR_H_INCLUDED
+#include <linux/types.h>
+#define MPI3MR_IOCTL_VERSION 0x06
+#define MPI3MR_APP_DEFAULT_TIMEOUT (60)
+#define MPI3MR_BSG_ADPTYPE_UNKNOWN 0
+#define MPI3MR_BSG_ADPTYPE_AVGFAMILY 1
+#define MPI3MR_BSG_ADPSTATE_UNKNOWN 0
+#define MPI3MR_BSG_ADPSTATE_OPERATIONAL 1
+#define MPI3MR_BSG_ADPSTATE_FAULT 2
+#define MPI3MR_BSG_ADPSTATE_IN_RESET 3
+#define MPI3MR_BSG_ADPSTATE_UNRECOVERABLE 4
+#define MPI3MR_BSG_ADPRESET_UNKNOWN 0
+#define MPI3MR_BSG_ADPRESET_SOFT 1
+#define MPI3MR_BSG_ADPRESET_DIAG_FAULT 2
+#define MPI3MR_BSG_LOGDATA_MAX_ENTRIES 400
+#define MPI3MR_BSG_LOGDATA_ENTRY_HEADER_SZ 4
+#define MPI3MR_DRVBSG_OPCODE_UNKNOWN 0
+#define MPI3MR_DRVBSG_OPCODE_ADPINFO 1
+#define MPI3MR_DRVBSG_OPCODE_ADPRESET 2
+#define MPI3MR_DRVBSG_OPCODE_ALLTGTDEVINFO 4
+#define MPI3MR_DRVBSG_OPCODE_GETCHGCNT 5
+#define MPI3MR_DRVBSG_OPCODE_LOGDATAENABLE 6
+#define MPI3MR_DRVBSG_OPCODE_PELENABLE 7
+#define MPI3MR_DRVBSG_OPCODE_GETLOGDATA 8
+#define MPI3MR_DRVBSG_OPCODE_QUERY_HDB 9
+#define MPI3MR_DRVBSG_OPCODE_REPOST_HDB 10
+#define MPI3MR_DRVBSG_OPCODE_UPLOAD_HDB 11
+#define MPI3MR_DRVBSG_OPCODE_REFRESH_HDB_TRIGGERS 12
+#define MPI3MR_BSG_BUFTYPE_UNKNOWN 0
+#define MPI3MR_BSG_BUFTYPE_RAIDMGMT_CMD 1
+#define MPI3MR_BSG_BUFTYPE_RAIDMGMT_RESP 2
+#define MPI3MR_BSG_BUFTYPE_DATA_IN 3
+#define MPI3MR_BSG_BUFTYPE_DATA_OUT 4
+#define MPI3MR_BSG_BUFTYPE_MPI_REPLY 5
+#define MPI3MR_BSG_BUFTYPE_ERR_RESPONSE 6
+#define MPI3MR_BSG_BUFTYPE_MPI_REQUEST 0xFE
+#define MPI3MR_BSG_MPI_REPLY_BUFTYPE_UNKNOWN 0
+#define MPI3MR_BSG_MPI_REPLY_BUFTYPE_STATUS 1
+#define MPI3MR_BSG_MPI_REPLY_BUFTYPE_ADDRESS 2
+#define MPI3MR_HDB_BUFTYPE_UNKNOWN 0
+#define MPI3MR_HDB_BUFTYPE_TRACE 1
+#define MPI3MR_HDB_BUFTYPE_FIRMWARE 2
+#define MPI3MR_HDB_BUFTYPE_RESERVED 3
+#define MPI3MR_HDB_BUFSTATUS_UNKNOWN 0
+#define MPI3MR_HDB_BUFSTATUS_NOT_ALLOCATED 1
+#define MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED 2
+#define MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED 3
+#define MPI3MR_HDB_BUFSTATUS_RELEASED 4
+#define MPI3MR_HDB_TRIGGER_TYPE_UNKNOWN 0
+#define MPI3MR_HDB_TRIGGER_TYPE_DIAGFAULT 1
+#define MPI3MR_HDB_TRIGGER_TYPE_ELEMENT 2
+#define MPI3MR_HDB_TRIGGER_TYPE_MASTER 3
+enum command {
+ MPI3MR_DRV_CMD = 1,
+ MPI3MR_MPT_CMD = 2,
+};
+struct mpi3_driver_info_layout {
+ __le32 information_length;
+ __u8 driver_signature[12];
+ __u8 os_name[16];
+ __u8 os_version[12];
+ __u8 driver_name[20];
+ __u8 driver_version[32];
+ __u8 driver_release_date[20];
+ __le32 driver_capabilities;
+};
+struct mpi3mr_bsg_in_adpinfo {
+ __u32 adp_type;
+ __u32 rsvd1;
+ __u32 pci_dev_id;
+ __u32 pci_dev_hw_rev;
+ __u32 pci_subsys_dev_id;
+ __u32 pci_subsys_ven_id;
+ __u32 pci_dev : 5;
+ __u32 pci_func : 3;
+ __u32 pci_bus : 8;
+ __u16 rsvd2;
+ __u32 pci_seg_id;
+ __u32 app_intfc_ver;
+ __u8 adp_state;
+ __u8 rsvd3;
+ __u16 rsvd4;
+ __u32 rsvd5[2];
+ struct mpi3_driver_info_layout driver_info;
+};
+struct mpi3mr_bsg_adp_reset {
+ __u8 reset_type;
+ __u8 rsvd1;
+ __u16 rsvd2;
+};
+struct mpi3mr_change_count {
+ __u16 change_count;
+ __u16 rsvd;
+};
+struct mpi3mr_device_map_info {
+ __u16 handle;
+ __u16 perst_id;
+ __u32 target_id;
+ __u8 bus_id;
+ __u8 rsvd1;
+ __u16 rsvd2;
+};
+struct mpi3mr_all_tgt_info {
+ __u16 num_devices;
+ __u16 rsvd1;
+ __u32 rsvd2;
+ struct mpi3mr_device_map_info dmi[1];
+};
+struct mpi3mr_logdata_enable {
+ __u16 max_entries;
+ __u16 rsvd;
+};
+struct mpi3mr_bsg_out_pel_enable {
+ __u16 pel_locale;
+ __u8 pel_class;
+ __u8 rsvd;
+};
+struct mpi3mr_logdata_entry {
+ __u8 valid_entry;
+ __u8 rsvd1;
+ __u16 rsvd2;
+ __u8 data[1];
+};
+struct mpi3mr_bsg_in_log_data {
+ struct mpi3mr_logdata_entry entry[1];
+};
+struct mpi3mr_hdb_entry {
+ __u8 buf_type;
+ __u8 status;
+ __u8 trigger_type;
+ __u8 rsvd1;
+ __u16 size;
+ __u16 rsvd2;
+ __u64 trigger_data;
+ __u32 rsvd3;
+ __u32 rsvd4;
+};
+struct mpi3mr_bsg_in_hdb_status {
+ __u8 num_hdb_types;
+ __u8 rsvd1;
+ __u16 rsvd2;
+ __u32 rsvd3;
+ struct mpi3mr_hdb_entry entry[1];
+};
+struct mpi3mr_bsg_out_repost_hdb {
+ __u8 buf_type;
+ __u8 rsvd1;
+ __u16 rsvd2;
+};
+struct mpi3mr_bsg_out_upload_hdb {
+ __u8 buf_type;
+ __u8 rsvd1;
+ __u16 rsvd2;
+ __u32 start_offset;
+ __u32 length;
+};
+struct mpi3mr_bsg_out_refresh_hdb_triggers {
+ __u8 page_type;
+ __u8 rsvd1;
+ __u16 rsvd2;
+};
+struct mpi3mr_bsg_drv_cmd {
+ __u8 mrioc_id;
+ __u8 opcode;
+ __u16 rsvd1;
+ __u32 rsvd2[4];
+};
+struct mpi3mr_bsg_in_reply_buf {
+ __u8 mpi_reply_type;
+ __u8 rsvd1;
+ __u16 rsvd2;
+ __u8 reply_buf[1];
+};
+struct mpi3mr_buf_entry {
+ __u8 buf_type;
+ __u8 rsvd1;
+ __u16 rsvd2;
+ __u32 buf_len;
+};
+struct mpi3mr_buf_entry_list {
+ __u8 num_of_entries;
+ __u8 rsvd1;
+ __u16 rsvd2;
+ __u32 rsvd3;
+ struct mpi3mr_buf_entry buf_entry[1];
+};
+struct mpi3mr_bsg_mptcmd {
+ __u8 mrioc_id;
+ __u8 rsvd1;
+ __u16 timeout;
+ __u32 rsvd2;
+ struct mpi3mr_buf_entry_list buf_entry_list;
+};
+struct mpi3mr_bsg_packet {
+ __u8 cmd_type;
+ __u8 rsvd1;
+ __u16 rsvd2;
+ __u32 rsvd3;
+ union {
+ struct mpi3mr_bsg_drv_cmd drvrcmd;
+ struct mpi3mr_bsg_mptcmd mptcmd;
+ } cmd;
+};
+#ifndef MPI3_NVME_ENCAP_CMD_MAX
+#define MPI3_NVME_ENCAP_CMD_MAX (1)
+#endif
+struct mpi3_nvme_encapsulated_request {
+ __le16 host_tag;
+ __u8 ioc_use_only02;
+ __u8 function;
+ __le16 ioc_use_only04;
+ __u8 ioc_use_only06;
+ __u8 msg_flags;
+ __le16 change_count;
+ __le16 dev_handle;
+ __le16 encapsulated_command_length;
+ __le16 flags;
+ __le32 data_length;
+ __le32 reserved14[3];
+ __le32 command[MPI3_NVME_ENCAP_CMD_MAX];
+};
+struct mpi3_nvme_encapsulated_error_reply {
+ __le16 host_tag;
+ __u8 ioc_use_only02;
+ __u8 function;
+ __le16 ioc_use_only04;
+ __u8 ioc_use_only06;
+ __u8 msg_flags;
+ __le16 ioc_use_only08;
+ __le16 ioc_status;
+ __le32 ioc_log_info;
+ __le32 nvme_completion_entry[4];
+};
+#define MPI3MR_NVME_PRP_SIZE 8
+#define MPI3MR_NVME_CMD_PRP1_OFFSET 24
+#define MPI3MR_NVME_CMD_PRP2_OFFSET 32
+#define MPI3MR_NVME_CMD_SGL_OFFSET 24
+#define MPI3MR_NVME_DATA_FORMAT_PRP 0
+#define MPI3MR_NVME_DATA_FORMAT_SGL1 1
+#define MPI3MR_NVME_DATA_FORMAT_SGL2 2
+struct mpi3_scsi_task_mgmt_request {
+ __le16 host_tag;
+ __u8 ioc_use_only02;
+ __u8 function;
+ __le16 ioc_use_only04;
+ __u8 ioc_use_only06;
+ __u8 msg_flags;
+ __le16 change_count;
+ __le16 dev_handle;
+ __le16 task_host_tag;
+ __u8 task_type;
+ __u8 reserved0f;
+ __le16 task_request_queue_id;
+ __le16 reserved12;
+ __le32 reserved14;
+ __u8 lun[8];
+};
+#define MPI3_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x08)
+#define MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01)
+#define MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK_SET (0x02)
+#define MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03)
+#define MPI3_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05)
+#define MPI3_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06)
+#define MPI3_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07)
+#define MPI3_SCSITASKMGMT_TASKTYPE_CLEAR_ACA (0x08)
+#define MPI3_SCSITASKMGMT_TASKTYPE_QUERY_TASK_SET (0x09)
+#define MPI3_SCSITASKMGMT_TASKTYPE_QUERY_ASYNC_EVENT (0x0a)
+#define MPI3_SCSITASKMGMT_TASKTYPE_I_T_NEXUS_RESET (0x0b)
+struct mpi3_scsi_task_mgmt_reply {
+ __le16 host_tag;
+ __u8 ioc_use_only02;
+ __u8 function;
+ __le16 ioc_use_only04;
+ __u8 ioc_use_only06;
+ __u8 msg_flags;
+ __le16 ioc_use_only08;
+ __le16 ioc_status;
+ __le32 ioc_log_info;
+ __le32 termination_count;
+ __le32 response_data;
+ __le32 reserved18;
+};
+#define MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE (0x00)
+#define MPI3_SCSITASKMGMT_RSPCODE_INVALID_FRAME (0x02)
+#define MPI3_SCSITASKMGMT_RSPCODE_TM_FUNCTION_NOT_SUPPORTED (0x04)
+#define MPI3_SCSITASKMGMT_RSPCODE_TM_FAILED (0x05)
+#define MPI3_SCSITASKMGMT_RSPCODE_TM_SUCCEEDED (0x08)
+#define MPI3_SCSITASKMGMT_RSPCODE_TM_INVALID_LUN (0x09)
+#define MPI3_SCSITASKMGMT_RSPCODE_TM_OVERLAPPED_TAG (0x0a)
+#define MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC (0x80)
+#define MPI3_SCSITASKMGMT_RSPCODE_TM_NVME_DENIED (0x81)
+#define MPI3_PEL_LOCALE_FLAGS_NON_BLOCKING_BOOT_EVENT (0x0200)
+#define MPI3_PEL_LOCALE_FLAGS_BLOCKING_BOOT_EVENT (0x0100)
+#define MPI3_PEL_LOCALE_FLAGS_PCIE (0x0080)
+#define MPI3_PEL_LOCALE_FLAGS_CONFIGURATION (0x0040)
+#define MPI3_PEL_LOCALE_FLAGS_CONTROLER (0x0020)
+#define MPI3_PEL_LOCALE_FLAGS_SAS (0x0010)
+#define MPI3_PEL_LOCALE_FLAGS_EPACK (0x0008)
+#define MPI3_PEL_LOCALE_FLAGS_ENCLOSURE (0x0004)
+#define MPI3_PEL_LOCALE_FLAGS_PD (0x0002)
+#define MPI3_PEL_LOCALE_FLAGS_VD (0x0001)
+#define MPI3_PEL_CLASS_DEBUG (0x00)
+#define MPI3_PEL_CLASS_PROGRESS (0x01)
+#define MPI3_PEL_CLASS_INFORMATIONAL (0x02)
+#define MPI3_PEL_CLASS_WARNING (0x03)
+#define MPI3_PEL_CLASS_CRITICAL (0x04)
+#define MPI3_PEL_CLASS_FATAL (0x05)
+#define MPI3_PEL_CLASS_FAULT (0x06)
+#define MPI3_BSG_FUNCTION_MGMT_PASSTHROUGH (0x0a)
+#define MPI3_BSG_FUNCTION_SCSI_IO (0x20)
+#define MPI3_BSG_FUNCTION_SCSI_TASK_MGMT (0x21)
+#define MPI3_BSG_FUNCTION_SMP_PASSTHROUGH (0x22)
+#define MPI3_BSG_FUNCTION_NVME_ENCAPSULATED (0x24)
+#endif
diff --git a/libc/kernel/uapi/sound/intel/avs/tokens.h b/libc/kernel/uapi/sound/intel/avs/tokens.h
new file mode 100644
index 0000000..b6b3002
--- /dev/null
+++ b/libc/kernel/uapi/sound/intel/avs/tokens.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __UAPI_SOUND_INTEL_AVS_TOKENS_H
+#define __UAPI_SOUND_INTEL_AVS_TOKENS_H
+enum avs_tplg_token {
+ AVS_TKN_MANIFEST_NAME_STRING = 1,
+ AVS_TKN_MANIFEST_VERSION_U32 = 2,
+ AVS_TKN_MANIFEST_NUM_LIBRARIES_U32 = 3,
+ AVS_TKN_MANIFEST_NUM_AFMTS_U32 = 4,
+ AVS_TKN_MANIFEST_NUM_MODCFGS_BASE_U32 = 5,
+ AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32 = 6,
+ AVS_TKN_MANIFEST_NUM_PPLCFGS_U32 = 7,
+ AVS_TKN_MANIFEST_NUM_BINDINGS_U32 = 8,
+ AVS_TKN_LIBRARY_ID_U32 = 101,
+ AVS_TKN_LIBRARY_NAME_STRING = 102,
+ AVS_TKN_AFMT_ID_U32 = 201,
+ AVS_TKN_AFMT_SAMPLE_RATE_U32 = 202,
+ AVS_TKN_AFMT_BIT_DEPTH_U32 = 203,
+ AVS_TKN_AFMT_CHANNEL_MAP_U32 = 204,
+ AVS_TKN_AFMT_CHANNEL_CFG_U32 = 205,
+ AVS_TKN_AFMT_INTERLEAVING_U32 = 206,
+ AVS_TKN_AFMT_NUM_CHANNELS_U32 = 207,
+ AVS_TKN_AFMT_VALID_BIT_DEPTH_U32 = 208,
+ AVS_TKN_AFMT_SAMPLE_TYPE_U32 = 209,
+ AVS_TKN_MODCFG_BASE_ID_U32 = 301,
+ AVS_TKN_MODCFG_BASE_CPC_U32 = 302,
+ AVS_TKN_MODCFG_BASE_IBS_U32 = 303,
+ AVS_TKN_MODCFG_BASE_OBS_U32 = 304,
+ AVS_TKN_MODCFG_BASE_PAGES_U32 = 305,
+ AVS_TKN_MODCFG_EXT_ID_U32 = 401,
+ AVS_TKN_MODCFG_EXT_TYPE_UUID = 402,
+ AVS_TKN_MODCFG_CPR_OUT_AFMT_ID_U32 = 403,
+ AVS_TKN_MODCFG_CPR_FEATURE_MASK_U32 = 404,
+ AVS_TKN_MODCFG_CPR_DMA_TYPE_U32 = 405,
+ AVS_TKN_MODCFG_CPR_DMABUFF_SIZE_U32 = 406,
+ AVS_TKN_MODCFG_CPR_VINDEX_U8 = 407,
+ AVS_TKN_MODCFG_CPR_BLOB_FMT_ID_U32 = 408,
+ AVS_TKN_MODCFG_MICSEL_OUT_AFMT_ID_U32 = 409,
+ AVS_TKN_MODCFG_INTELWOV_CPC_LP_MODE_U32 = 410,
+ AVS_TKN_MODCFG_SRC_OUT_FREQ_U32 = 411,
+ AVS_TKN_MODCFG_MUX_REF_AFMT_ID_U32 = 412,
+ AVS_TKN_MODCFG_MUX_OUT_AFMT_ID_U32 = 413,
+ AVS_TKN_MODCFG_AEC_REF_AFMT_ID_U32 = 414,
+ AVS_TKN_MODCFG_AEC_OUT_AFMT_ID_U32 = 415,
+ AVS_TKN_MODCFG_AEC_CPC_LP_MODE_U32 = 416,
+ AVS_TKN_MODCFG_ASRC_OUT_FREQ_U32 = 417,
+ AVS_TKN_MODCFG_ASRC_MODE_U8 = 418,
+ AVS_TKN_MODCFG_ASRC_DISABLE_JITTER_U8 = 419,
+ AVS_TKN_MODCFG_UPDOWN_MIX_OUT_CHAN_CFG_U32 = 420,
+ AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_SELECT_U32 = 421,
+ AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_0_S32 = 422,
+ AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_1_S32 = 423,
+ AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_2_S32 = 424,
+ AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_3_S32 = 425,
+ AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_4_S32 = 426,
+ AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_5_S32 = 427,
+ AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_6_S32 = 428,
+ AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_7_S32 = 429,
+ AVS_TKN_MODCFG_UPDOWN_MIX_CHAN_MAP_U32 = 430,
+ AVS_TKN_MODCFG_EXT_NUM_INPUT_PINS_U16 = 431,
+ AVS_TKN_MODCFG_EXT_NUM_OUTPUT_PINS_U16 = 432,
+ AVS_TKN_PPLCFG_ID_U32 = 1401,
+ AVS_TKN_PPLCFG_REQ_SIZE_U16 = 1402,
+ AVS_TKN_PPLCFG_PRIORITY_U8 = 1403,
+ AVS_TKN_PPLCFG_LOW_POWER_BOOL = 1404,
+ AVS_TKN_PPLCFG_ATTRIBUTES_U16 = 1405,
+ AVS_TKN_PPLCFG_TRIGGER_U32 = 1406,
+ AVS_TKN_BINDING_ID_U32 = 1501,
+ AVS_TKN_BINDING_TARGET_TPLG_NAME_STRING = 1502,
+ AVS_TKN_BINDING_TARGET_PATH_TMPL_ID_U32 = 1503,
+ AVS_TKN_BINDING_TARGET_PPL_ID_U32 = 1504,
+ AVS_TKN_BINDING_TARGET_MOD_ID_U32 = 1505,
+ AVS_TKN_BINDING_TARGET_MOD_PIN_U8 = 1506,
+ AVS_TKN_BINDING_MOD_ID_U32 = 1507,
+ AVS_TKN_BINDING_MOD_PIN_U8 = 1508,
+ AVS_TKN_BINDING_IS_SINK_U8 = 1509,
+ AVS_TKN_PPL_ID_U32 = 1601,
+ AVS_TKN_PPL_PPLCFG_ID_U32 = 1602,
+ AVS_TKN_PPL_NUM_BINDING_IDS_U32 = 1603,
+ AVS_TKN_PPL_BINDING_ID_U32 = 1604,
+ AVS_TKN_MOD_ID_U32 = 1701,
+ AVS_TKN_MOD_MODCFG_BASE_ID_U32 = 1702,
+ AVS_TKN_MOD_IN_AFMT_ID_U32 = 1703,
+ AVS_TKN_MOD_CORE_ID_U8 = 1704,
+ AVS_TKN_MOD_PROC_DOMAIN_U8 = 1705,
+ AVS_TKN_MOD_MODCFG_EXT_ID_U32 = 1706,
+ AVS_TKN_PATH_TMPL_ID_U32 = 1801,
+ AVS_TKN_PATH_ID_U32 = 1901,
+ AVS_TKN_PATH_FE_FMT_ID_U32 = 1902,
+ AVS_TKN_PATH_BE_FMT_ID_U32 = 1903,
+ AVS_TKN_PIN_FMT_INDEX_U32 = 2201,
+ AVS_TKN_PIN_FMT_IOBS_U32 = 2202,
+ AVS_TKN_PIN_FMT_AFMT_ID_U32 = 2203,
+};
+#endif
diff --git a/libc/kernel/uapi/sound/sof/abi.h b/libc/kernel/uapi/sound/sof/abi.h
index 3af3c9d..091c8ed 100644
--- a/libc/kernel/uapi/sound/sof/abi.h
+++ b/libc/kernel/uapi/sound/sof/abi.h
@@ -19,7 +19,7 @@
#ifndef __INCLUDE_UAPI_SOUND_SOF_ABI_H__
#define __INCLUDE_UAPI_SOUND_SOF_ABI_H__
#define SOF_ABI_MAJOR 3
-#define SOF_ABI_MINOR 18
+#define SOF_ABI_MINOR 21
#define SOF_ABI_PATCH 0
#define SOF_ABI_MAJOR_SHIFT 24
#define SOF_ABI_MAJOR_MASK 0xff
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 7397b68..dc1b6f6 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -680,28 +680,28 @@
nftw64; # introduced=21
nice;
nrand48;
- ns_format_ttl; # arm64 x86_64 introduced=22
- ns_get16; # arm64 x86_64 introduced=22
- ns_get32; # arm64 x86_64 introduced=22
- ns_initparse; # arm64 x86_64 introduced=22
- ns_makecanon; # arm64 x86_64 introduced=22
- ns_msg_getflag; # arm64 x86_64 introduced=22
- ns_name_compress; # arm64 x86_64 introduced=22
- ns_name_ntol; # arm64 x86_64 introduced=22
- ns_name_ntop; # arm64 x86_64 introduced=22
- ns_name_pack; # arm64 x86_64 introduced=22
- ns_name_pton; # arm64 x86_64 introduced=22
- ns_name_rollback; # arm64 x86_64 introduced=22
- ns_name_skip; # arm64 x86_64 introduced=22
- ns_name_uncompress; # arm64 x86_64 introduced=22
- ns_name_unpack; # arm64 x86_64 introduced=22
- ns_parserr; # arm64 x86_64 introduced=22
- ns_put16; # arm64 x86_64 introduced=22
- ns_put32; # arm64 x86_64 introduced=22
- ns_samename; # arm64 x86_64 introduced=22
- ns_skiprr; # arm64 x86_64 introduced=22
- ns_sprintrr; # arm64 x86_64 introduced=22
- ns_sprintrrf; # arm64 x86_64 introduced=22
+ ns_format_ttl; # arm64 x86_64 riscv64 introduced=22
+ ns_get16; # arm64 x86_64 riscv64 introduced=22
+ ns_get32; # arm64 x86_64 riscv64 introduced=22
+ ns_initparse; # arm64 x86_64 riscv64 introduced=22
+ ns_makecanon; # arm64 x86_64 riscv64 introduced=22
+ ns_msg_getflag; # arm64 x86_64 riscv64 introduced=22
+ ns_name_compress; # arm64 x86_64 riscv64 introduced=22
+ ns_name_ntol; # arm64 x86_64 riscv64 introduced=22
+ ns_name_ntop; # arm64 x86_64 riscv64 introduced=22
+ ns_name_pack; # arm64 x86_64 riscv64 introduced=22
+ ns_name_pton; # arm64 x86_64 riscv64 introduced=22
+ ns_name_rollback; # arm64 x86_64 riscv64 introduced=22
+ ns_name_skip; # arm64 x86_64 riscv64 introduced=22
+ ns_name_uncompress; # arm64 x86_64 riscv64 introduced=22
+ ns_name_unpack; # arm64 x86_64 riscv64 introduced=22
+ ns_parserr; # arm64 x86_64 riscv64 introduced=22
+ ns_put16; # arm64 x86_64 riscv64 introduced=22
+ ns_put32; # arm64 x86_64 riscv64 introduced=22
+ ns_samename; # arm64 x86_64 riscv64 introduced=22
+ ns_skiprr; # arm64 x86_64 riscv64 introduced=22
+ ns_sprintrr; # arm64 x86_64 riscv64 introduced=22
+ ns_sprintrrf; # arm64 x86_64 riscv64 introduced=22
nsdispatch;
ntohl; # introduced=21
ntohs; # introduced=21
@@ -740,7 +740,7 @@
pread;
pread64; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
printf;
- prlimit; # arm64 x86_64
+ prlimit; # arm64 x86_64 riscv64
prlimit64; # introduced=21
process_vm_readv; # introduced=23
process_vm_writev; # introduced=23
@@ -1449,7 +1449,7 @@
___tls_get_addr; # x86
__aeabi_read_tp; # arm
__res_randomid;
- __tls_get_addr; # arm x86_64
+ __tls_get_addr; # arm riscv64 x86_64
android_fdsan_close_with_tag;
android_fdsan_create_owner_tag;
android_fdsan_exchange_owner_tag;
@@ -1576,6 +1576,14 @@
pwritev64v2;
} LIBC_S;
+LIBC_U { # introduced=UpsideDownCake
+ global:
+ __freadahead;
+ close_range;
+ copy_file_range;
+ memset_explicit;
+} LIBC_T;
+
LIBC_PRIVATE {
global:
__accept4; # arm x86
diff --git a/libc/libstdc++.map.txt b/libc/libstdc++.map.txt
index bb7040f..8af3b91 100644
--- a/libc/libstdc++.map.txt
+++ b/libc/libstdc++.map.txt
@@ -7,12 +7,12 @@
_ZdlPvRKSt9nothrow_t; # weak
_Znaj; # arm x86 weak
_ZnajRKSt9nothrow_t; # arm x86 weak
- _Znam; # arm64 x86_64 weak
- _ZnamRKSt9nothrow_t; # arm64 x86_64 weak
+ _Znam; # arm64 x86_64 riscv64 weak
+ _ZnamRKSt9nothrow_t; # arm64 x86_64 riscv64 weak
_Znwj; # arm x86 weak
_ZnwjRKSt9nothrow_t; # arm x86 weak
- _Znwm; # arm64 x86_64 weak
- _ZnwmRKSt9nothrow_t; # arm64 x86_64 weak
+ _Znwm; # arm64 x86_64 riscv64 weak
+ _ZnwmRKSt9nothrow_t; # arm64 x86_64 riscv64 weak
__cxa_guard_abort;
__cxa_guard_acquire;
__cxa_guard_release;
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index 7ff3db2..e7a157e 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -64,6 +64,7 @@
"malloc_debug.cpp",
"PointerData.cpp",
"RecordData.cpp",
+ "Unreachable.cpp",
"UnwindBacktrace.cpp",
],
@@ -73,6 +74,7 @@
"libasync_safe",
"libbase",
"libc_malloc_debug_backtrace",
+ "libmemunreachable",
],
shared_libs: [
@@ -120,6 +122,7 @@
cc_test {
name: "malloc_debug_unit_tests",
test_suites: ["device-tests"],
+ isolated: true,
srcs: [
"tests/backtrace_fake.cpp",
@@ -179,7 +182,6 @@
shared_libs: [
"libbase",
- "libbacktrace",
"liblog",
"libunwindstack",
],
diff --git a/libc/malloc_debug/Config.cpp b/libc/malloc_debug/Config.cpp
index 11887e2..6a81277 100644
--- a/libc/malloc_debug/Config.cpp
+++ b/libc/malloc_debug/Config.cpp
@@ -70,17 +70,34 @@
const std::unordered_map<std::string, Config::OptionInfo> Config::kOptions = {
{
- "guard", {FRONT_GUARD | REAR_GUARD | TRACK_ALLOCS, &Config::SetGuard},
+ "guard",
+ {FRONT_GUARD | REAR_GUARD | TRACK_ALLOCS, &Config::SetGuard},
},
{
- "front_guard", {FRONT_GUARD | TRACK_ALLOCS, &Config::SetFrontGuard},
+ "front_guard",
+ {FRONT_GUARD | TRACK_ALLOCS, &Config::SetFrontGuard},
},
{
- "rear_guard", {REAR_GUARD | TRACK_ALLOCS, &Config::SetRearGuard},
+ "rear_guard",
+ {REAR_GUARD | TRACK_ALLOCS, &Config::SetRearGuard},
},
{
- "backtrace", {BACKTRACE | TRACK_ALLOCS, &Config::SetBacktrace},
+ "backtrace_size",
+ {BACKTRACE_SPECIFIC_SIZES, &Config::SetBacktraceSize},
+ },
+ {
+ "backtrace_min_size",
+ {BACKTRACE_SPECIFIC_SIZES, &Config::SetBacktraceMinSize},
+ },
+ {
+ "backtrace_max_size",
+ {BACKTRACE_SPECIFIC_SIZES, &Config::SetBacktraceMaxSize},
+ },
+
+ {
+ "backtrace",
+ {BACKTRACE | TRACK_ALLOCS, &Config::SetBacktrace},
},
{
"backtrace_enable_on_signal",
@@ -88,55 +105,74 @@
},
{
- "backtrace_dump_on_exit", {0, &Config::SetBacktraceDumpOnExit},
+ "backtrace_dump_on_exit",
+ {0, &Config::SetBacktraceDumpOnExit},
},
{
- "backtrace_dump_prefix", {0, &Config::SetBacktraceDumpPrefix},
+ "backtrace_dump_prefix",
+ {0, &Config::SetBacktraceDumpPrefix},
},
{
- "backtrace_full", {BACKTRACE_FULL, &Config::VerifyValueEmpty},
+ "backtrace_full",
+ {BACKTRACE_FULL, &Config::VerifyValueEmpty},
},
{
- "fill", {FILL_ON_ALLOC | FILL_ON_FREE, &Config::SetFill},
+ "fill",
+ {FILL_ON_ALLOC | FILL_ON_FREE, &Config::SetFill},
},
{
- "fill_on_alloc", {FILL_ON_ALLOC, &Config::SetFillOnAlloc},
+ "fill_on_alloc",
+ {FILL_ON_ALLOC, &Config::SetFillOnAlloc},
},
{
- "fill_on_free", {FILL_ON_FREE, &Config::SetFillOnFree},
+ "fill_on_free",
+ {FILL_ON_FREE, &Config::SetFillOnFree},
},
{
- "expand_alloc", {EXPAND_ALLOC, &Config::SetExpandAlloc},
+ "expand_alloc",
+ {EXPAND_ALLOC, &Config::SetExpandAlloc},
},
{
- "free_track", {FREE_TRACK | FILL_ON_FREE | TRACK_ALLOCS, &Config::SetFreeTrack},
+ "free_track",
+ {FREE_TRACK | FILL_ON_FREE | TRACK_ALLOCS, &Config::SetFreeTrack},
},
{
- "free_track_backtrace_num_frames", {0, &Config::SetFreeTrackBacktraceNumFrames},
+ "free_track_backtrace_num_frames",
+ {0, &Config::SetFreeTrackBacktraceNumFrames},
},
{
- "leak_track", {LEAK_TRACK | TRACK_ALLOCS, &Config::VerifyValueEmpty},
+ "leak_track",
+ {LEAK_TRACK | TRACK_ALLOCS, &Config::VerifyValueEmpty},
},
{
- "record_allocs", {RECORD_ALLOCS, &Config::SetRecordAllocs},
+ "record_allocs",
+ {RECORD_ALLOCS, &Config::SetRecordAllocs},
},
{
- "record_allocs_file", {0, &Config::SetRecordAllocsFile},
+ "record_allocs_file",
+ {0, &Config::SetRecordAllocsFile},
},
{
- "verify_pointers", {TRACK_ALLOCS, &Config::VerifyValueEmpty},
+ "verify_pointers",
+ {TRACK_ALLOCS, &Config::VerifyValueEmpty},
},
{
- "abort_on_error", {ABORT_ON_ERROR, &Config::VerifyValueEmpty},
+ "abort_on_error",
+ {ABORT_ON_ERROR, &Config::VerifyValueEmpty},
},
{
- "verbose", {VERBOSE, &Config::VerifyValueEmpty},
+ "verbose",
+ {VERBOSE, &Config::VerifyValueEmpty},
+ },
+ {
+ "check_unreachable_on_signal",
+ {CHECK_UNREACHABLE_ON_SIGNAL, &Config::VerifyValueEmpty},
},
};
@@ -274,6 +310,23 @@
return true;
}
+bool Config::SetBacktraceSize(const std::string& option, const std::string& value) {
+ if (!ParseValue(option, value, 1, SIZE_MAX, &backtrace_min_size_bytes_)) {
+ return false;
+ }
+ backtrace_max_size_bytes_ = backtrace_min_size_bytes_;
+
+ return true;
+}
+
+bool Config::SetBacktraceMinSize(const std::string& option, const std::string& value) {
+ return ParseValue(option, value, 1, SIZE_MAX, &backtrace_min_size_bytes_);
+}
+
+bool Config::SetBacktraceMaxSize(const std::string& option, const std::string& value) {
+ return ParseValue(option, value, 1, SIZE_MAX, &backtrace_max_size_bytes_);
+}
+
bool Config::SetExpandAlloc(const std::string& option, const std::string& value) {
return ParseValue(option, value, DEFAULT_EXPAND_BYTES, 1, MAX_EXPAND_BYTES, &expand_alloc_bytes_);
}
@@ -380,6 +433,9 @@
backtrace_enabled_ = false;
backtrace_dump_on_exit_ = false;
backtrace_dump_prefix_ = DEFAULT_BACKTRACE_DUMP_PREFIX;
+ backtrace_min_size_bytes_ = 0;
+ backtrace_max_size_bytes_ = SIZE_MAX;
+ check_unreachable_signal_ = SIGRTMAX - 16;
// Process each option name we can find.
std::string option;
diff --git a/libc/malloc_debug/Config.h b/libc/malloc_debug/Config.h
index 1b5c748..ef1d2a9 100644
--- a/libc/malloc_debug/Config.h
+++ b/libc/malloc_debug/Config.h
@@ -46,6 +46,8 @@
constexpr uint64_t BACKTRACE_FULL = 0x400;
constexpr uint64_t ABORT_ON_ERROR = 0x800;
constexpr uint64_t VERBOSE = 0x1000;
+constexpr uint64_t CHECK_UNREACHABLE_ON_SIGNAL = 0x2000;
+constexpr uint64_t BACKTRACE_SPECIFIC_SIZES = 0x4000;
// In order to guarantee posix compliance, set the minimum alignment
// to 8 bytes for 32 bit systems and 16 bytes for 64 bit systems.
@@ -89,10 +91,15 @@
uint8_t fill_alloc_value() const { return fill_alloc_value_; }
uint8_t fill_free_value() const { return fill_free_value_; }
+ size_t backtrace_min_size_bytes() const { return backtrace_min_size_bytes_; }
+ size_t backtrace_max_size_bytes() const { return backtrace_max_size_bytes_; }
+
int record_allocs_signal() const { return record_allocs_signal_; }
size_t record_allocs_num_entries() const { return record_allocs_num_entries_; }
const std::string& record_allocs_file() const { return record_allocs_file_; }
+ int check_unreachable_signal() const { return check_unreachable_signal_; }
+
private:
struct OptionInfo {
uint64_t option;
@@ -118,6 +125,10 @@
bool SetBacktraceDumpOnExit(const std::string& option, const std::string& value);
bool SetBacktraceDumpPrefix(const std::string& option, const std::string& value);
+ bool SetBacktraceSize(const std::string& option, const std::string& value);
+ bool SetBacktraceMinSize(const std::string& option, const std::string& value);
+ bool SetBacktraceMaxSize(const std::string& option, const std::string& value);
+
bool SetExpandAlloc(const std::string& option, const std::string& value);
bool SetFreeTrack(const std::string& option, const std::string& value);
@@ -142,6 +153,8 @@
size_t backtrace_frames_ = 0;
bool backtrace_dump_on_exit_ = false;
std::string backtrace_dump_prefix_;
+ size_t backtrace_min_size_bytes_ = 0;
+ size_t backtrace_max_size_bytes_ = 0;
size_t fill_on_alloc_bytes_ = 0;
size_t fill_on_free_bytes_ = 0;
@@ -160,4 +173,6 @@
uint8_t fill_free_value_;
uint8_t front_guard_value_;
uint8_t rear_guard_value_;
+
+ int check_unreachable_signal_ = 0;
};
diff --git a/libc/malloc_debug/MapData.cpp b/libc/malloc_debug/MapData.cpp
index ded81a2..b22c109 100644
--- a/libc/malloc_debug/MapData.cpp
+++ b/libc/malloc_debug/MapData.cpp
@@ -210,7 +210,7 @@
}
}
}
- *rel_pc = pc - entry->start + entry->load_bias;
+ *rel_pc = pc - entry->start + entry->offset + entry->load_bias;
}
return entry;
}
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp
index b982c0a..5ab2232 100644
--- a/libc/malloc_debug/PointerData.cpp
+++ b/libc/malloc_debug/PointerData.cpp
@@ -35,6 +35,7 @@
#include <sys/types.h>
#include <unistd.h>
+#include <functional>
#include <mutex>
#include <string>
#include <unordered_map>
@@ -135,7 +136,22 @@
return true;
}
-size_t PointerData::AddBacktrace(size_t num_frames) {
+static inline bool ShouldBacktraceAllocSize(size_t size_bytes) {
+ static bool only_backtrace_specific_sizes =
+ g_debug->config().options() & BACKTRACE_SPECIFIC_SIZES;
+ if (!only_backtrace_specific_sizes) {
+ return true;
+ }
+ static size_t min_size_bytes = g_debug->config().backtrace_min_size_bytes();
+ static size_t max_size_bytes = g_debug->config().backtrace_max_size_bytes();
+ return size_bytes >= min_size_bytes && size_bytes <= max_size_bytes;
+}
+
+size_t PointerData::AddBacktrace(size_t num_frames, size_t size_bytes) {
+ if (!ShouldBacktraceAllocSize(size_bytes)) {
+ return kBacktraceEmptyIndex;
+ }
+
std::vector<uintptr_t> frames;
std::vector<unwindstack::FrameData> frames_info;
if (g_debug->config().options() & BACKTRACE_FULL) {
@@ -148,14 +164,14 @@
if (num_frames == 0) {
return kBacktraceEmptyIndex;
}
+ frames.resize(num_frames);
}
- FrameKeyType key{.num_frames = num_frames, .frames = frames.data()};
+ FrameKeyType key{.num_frames = frames.size(), .frames = frames.data()};
size_t hash_index;
std::lock_guard<std::mutex> frame_guard(frame_mutex_);
auto entry = key_to_index_.find(key);
if (entry == key_to_index_.end()) {
- frames.resize(num_frames);
hash_index = cur_hash_index_++;
key.frames = frames.data();
key_to_index_.emplace(key, hash_index);
@@ -195,40 +211,41 @@
}
void PointerData::Add(const void* ptr, size_t pointer_size) {
- uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
size_t hash_index = 0;
if (backtrace_enabled_) {
- hash_index = AddBacktrace(g_debug->config().backtrace_frames());
+ hash_index = AddBacktrace(g_debug->config().backtrace_frames(), pointer_size);
}
std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
- pointers_[pointer] = PointerInfoType{PointerInfoType::GetEncodedSize(pointer_size), hash_index};
+ uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+ pointers_[mangled_ptr] =
+ PointerInfoType{PointerInfoType::GetEncodedSize(pointer_size), hash_index};
}
void PointerData::Remove(const void* ptr) {
- uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
size_t hash_index;
{
std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
- auto entry = pointers_.find(pointer);
+ uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+ auto entry = pointers_.find(mangled_ptr);
if (entry == pointers_.end()) {
// Attempt to remove unknown pointer.
- error_log("No tracked pointer found for 0x%" PRIxPTR, pointer);
+ error_log("No tracked pointer found for 0x%" PRIxPTR, DemanglePointer(mangled_ptr));
return;
}
hash_index = entry->second.hash_index;
- pointers_.erase(pointer);
+ pointers_.erase(mangled_ptr);
}
RemoveBacktrace(hash_index);
}
size_t PointerData::GetFrames(const void* ptr, uintptr_t* frames, size_t max_frames) {
- uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
size_t hash_index;
{
std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
- auto entry = pointers_.find(pointer);
+ uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+ auto entry = pointers_.find(mangled_ptr);
if (entry == pointers_.end()) {
return 0;
}
@@ -274,7 +291,8 @@
void PointerData::LogFreeError(const FreePointerInfoType& info, size_t max_cmp_bytes) {
error_log(LOG_DIVIDER);
- uint8_t* memory = reinterpret_cast<uint8_t*>(info.pointer);
+ uintptr_t pointer = DemanglePointer(info.mangled_ptr);
+ uint8_t* memory = reinterpret_cast<uint8_t*>(pointer);
error_log("+++ ALLOCATION %p USED AFTER FREE", memory);
uint8_t fill_free_value = g_debug->config().fill_free_value();
for (size_t i = 0; i < max_cmp_bytes; i++) {
@@ -296,13 +314,14 @@
void PointerData::VerifyFreedPointer(const FreePointerInfoType& info) {
size_t usable_size;
+ uintptr_t pointer = DemanglePointer(info.mangled_ptr);
if (g_debug->HeaderEnabled()) {
// Check to see if the tag data has been damaged.
- Header* header = g_debug->GetHeader(reinterpret_cast<const void*>(info.pointer));
+ Header* header = g_debug->GetHeader(reinterpret_cast<const void*>(pointer));
if (header->tag != DEBUG_FREE_TAG) {
error_log(LOG_DIVIDER);
- error_log("+++ ALLOCATION 0x%" PRIxPTR " HAS CORRUPTED HEADER TAG 0x%x AFTER FREE",
- info.pointer, header->tag);
+ error_log("+++ ALLOCATION 0x%" PRIxPTR " HAS CORRUPTED HEADER TAG 0x%x AFTER FREE", pointer,
+ header->tag);
error_log(LOG_DIVIDER);
if (g_debug->config().options() & ABORT_ON_ERROR) {
abort();
@@ -314,14 +333,14 @@
}
usable_size = header->usable_size;
} else {
- usable_size = g_dispatch->malloc_usable_size(reinterpret_cast<const void*>(info.pointer));
+ usable_size = g_dispatch->malloc_usable_size(reinterpret_cast<const void*>(pointer));
}
size_t bytes = (usable_size < g_debug->config().fill_on_free_bytes())
? usable_size
: g_debug->config().fill_on_free_bytes();
size_t max_cmp_bytes = bytes;
- const uint8_t* memory = reinterpret_cast<const uint8_t*>(info.pointer);
+ const uint8_t* memory = reinterpret_cast<const uint8_t*>(pointer);
while (bytes > 0) {
size_t bytes_to_cmp = (bytes < g_cmp_mem.size()) ? bytes : g_cmp_mem.size();
if (memcmp(memory, g_cmp_mem.data(), bytes_to_cmp) != 0) {
@@ -332,13 +351,11 @@
}
}
-void* PointerData::AddFreed(const void* ptr) {
- uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
-
+void* PointerData::AddFreed(const void* ptr, size_t size_bytes) {
size_t hash_index = 0;
size_t num_frames = g_debug->config().free_track_backtrace_num_frames();
if (num_frames) {
- hash_index = AddBacktrace(num_frames);
+ hash_index = AddBacktrace(num_frames, size_bytes);
}
void* last = nullptr;
@@ -348,10 +365,11 @@
free_pointers_.pop_front();
VerifyFreedPointer(info);
RemoveBacktrace(info.hash_index);
- last = reinterpret_cast<void*>(info.pointer);
+ last = reinterpret_cast<void*>(DemanglePointer(info.mangled_ptr));
}
- free_pointers_.emplace_back(FreePointerInfoType{pointer, hash_index});
+ uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+ free_pointers_.emplace_back(FreePointerInfoType{mangled_ptr, hash_index});
return last;
}
@@ -361,7 +379,7 @@
uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
std::lock_guard<std::mutex> freed_guard(free_pointer_mutex_);
for (const auto& info : free_pointers_) {
- if (info.pointer == pointer) {
+ if (DemanglePointer(info.mangled_ptr) == pointer) {
hash_index = info.hash_index;
break;
}
@@ -388,6 +406,7 @@
for (const auto& entry : pointers_) {
FrameInfoType* frame_info = nullptr;
std::vector<unwindstack::FrameData>* backtrace_info = nullptr;
+ uintptr_t pointer = DemanglePointer(entry.first);
size_t hash_index = entry.second.hash_index;
if (hash_index > kBacktraceEmptyIndex) {
auto frame_entry = frames_.find(hash_index);
@@ -397,7 +416,7 @@
// occurs after the hash_index and frame data have been added.
// When removing a pointer, the pointer is deleted before the frame
// data.
- error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", entry.first, hash_index);
+ error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", pointer, hash_index);
} else {
frame_info = &frame_entry->second;
}
@@ -405,7 +424,7 @@
if (g_debug->config().options() & BACKTRACE_FULL) {
auto backtrace_entry = backtraces_info_.find(hash_index);
if (backtrace_entry == backtraces_info_.end()) {
- error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", entry.first, hash_index);
+ error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", pointer, hash_index);
} else {
backtrace_info = &backtrace_entry->second;
}
@@ -415,7 +434,7 @@
continue;
}
- list->emplace_back(ListInfoType{entry.first, 1, entry.second.RealSize(),
+ list->emplace_back(ListInfoType{pointer, 1, entry.second.RealSize(),
entry.second.ZygoteChildAlloc(), frame_info, backtrace_info});
}
@@ -550,9 +569,9 @@
}
bool PointerData::Exists(const void* ptr) {
- uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
- return pointers_.count(pointer) != 0;
+ uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+ return pointers_.count(mangled_ptr) != 0;
}
void PointerData::DumpLiveToFile(int fd) {
@@ -637,3 +656,10 @@
free_pointer_mutex_.try_lock();
free_pointer_mutex_.unlock();
}
+
+void PointerData::IteratePointers(std::function<void(uintptr_t pointer)> fn) {
+ std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
+ for (const auto entry : pointers_) {
+ fn(DemanglePointer(entry.first));
+ }
+}
diff --git a/libc/malloc_debug/PointerData.h b/libc/malloc_debug/PointerData.h
index 92d2653..3194bab 100644
--- a/libc/malloc_debug/PointerData.h
+++ b/libc/malloc_debug/PointerData.h
@@ -33,6 +33,7 @@
#include <atomic>
#include <deque>
+#include <functional>
#include <mutex>
#include <string>
#include <unordered_map>
@@ -99,7 +100,7 @@
};
struct FreePointerInfoType {
- uintptr_t pointer;
+ uintptr_t mangled_ptr;
size_t hash_index;
};
@@ -134,17 +135,15 @@
void PostForkParent();
void PostForkChild();
- static size_t AddBacktrace(size_t num_frames);
+ static void IteratePointers(std::function<void(uintptr_t pointer)> fn);
+
+ static size_t AddBacktrace(size_t num_frames, size_t size_bytes);
static void RemoveBacktrace(size_t hash_index);
static void Add(const void* pointer, size_t size);
static void Remove(const void* pointer);
- typedef std::unordered_map<uintptr_t, PointerInfoType>::iterator iterator;
- static iterator begin() { return pointers_.begin(); }
- static iterator end() { return pointers_.end(); }
-
- static void* AddFreed(const void* pointer);
+ static void* AddFreed(const void* pointer, size_t size_bytes);
static void LogFreeError(const FreePointerInfoType& info, size_t usable_size);
static void LogFreeBacktrace(const void* ptr);
static void VerifyFreedPointer(const FreePointerInfoType& info);
@@ -162,6 +161,12 @@
static bool Exists(const void* pointer);
private:
+ // Only keep mangled pointers in internal data structures. This avoids
+ // problems where libmemunreachable finds these pointers and thinks they
+ // are not unreachable.
+ static inline uintptr_t ManglePointer(uintptr_t pointer) { return pointer ^ UINTPTR_MAX; }
+ static inline uintptr_t DemanglePointer(uintptr_t pointer) { return pointer ^ UINTPTR_MAX; }
+
static std::string GetHashString(uintptr_t* frames, size_t num_frames);
static void LogBacktrace(size_t hash_index);
diff --git a/libc/malloc_debug/README.md b/libc/malloc_debug/README.md
index 662f5f8..3667624 100644
--- a/libc/malloc_debug/README.md
+++ b/libc/malloc_debug/README.md
@@ -114,7 +114,7 @@
option will not add a special header.
As of P, this option will also enable dumping backtrace heap data to a
-file when the process receives the signal SIGRTMAX - 17 ( which is 47 on most
+file when the process receives the signal SIGRTMAX - 17 ( which is 47 on
Android devices). The format of this dumped data is the same format as
that dumped when running am dumpheap -n. The default is to dump this data
to the file /data/local/tmp/backtrace\_heap.**PID**.txt. This is useful when
@@ -127,7 +127,7 @@
### backtrace\_enable\_on\_signal[=MAX\_FRAMES]
Enable capturing the backtrace of each allocation site. If the
backtrace capture is toggled when the process receives the signal
-SIGRTMAX - 19 (which is 45 on most Android devices). When this
+SIGRTMAX - 19 (which is 45 on Android devices). When this
option is used alone, backtrace capture starts out disabled until the signal
is received. If both this option and the backtrace option are set, then
backtrace capture is enabled until the signal is received.
@@ -160,11 +160,69 @@
on the signal will be backtrace\_dump\_prefix.**PID**.txt. The filename chosen
when the program exits will be backtrace\_dump\_prefix.**PID**.exit.txt.
+### backtrace\_min\_size=ALLOCATION\_SIZE\_BYTES
+As of U, setting this in combination with the backtrace option means
+that only allocations of a size greater than or equal to
+**ALLOCATION\_SIZE\_BYTES** will be backtraced. When used in combination
+with the backtrace\_max\_size option, then allocations greater than or
+equal to backtrace\_min\_size and less than or equal to
+backtrace\_max\_size will be backtraced. The backtrace\_size option
+overrides this option, and should not be used at the same time.
+
+This option can also be used in combination with other tools such
+as [libmemunreachable](https://android.googlesource.com/platform/system/memory/libmemunreachable/+/master/README.md)
+to only get backtraces for sizes of allocations listed as being leaked.
+
+### backtrace\_max\_size=ALLOCATION\_SIZE\_BYTES
+As of U, setting this in combination with the backtrace option means
+that only allocations of a size less than or equal to
+**ALLOCATION\_SIZE\_BYTES** will be backtraced. When used in combination
+with the backtrace\_min\_size option, then allocations greater than or
+equal to backtrace\_min\_size and less than or equal to
+backtrace\_max\_size will be backtraced. The backtrace\_size option
+overrides this option, and should not be used at the same time.
+
+This option can also be used in combination with other tools such
+as [libmemunreachable](https://android.googlesource.com/platform/system/memory/libmemunreachable/+/master/README.md)
+to only get backtraces for sizes of allocations listed as being leaked.
+
+### backtrace\_size=ALLOCATION\_SIZE\_BYTES
+As of U, setting this in combination with the backtrace option means
+that only allocations of size **ALLOCATION\_SIZE\_BYTES** will be backtraced.
+This option overrides the backtrace\_min\_size and the backtrace\_max\_size.
+
+This option can also be used in combination with other tools such
+as [libmemunreachable](https://android.googlesource.com/platform/system/memory/libmemunreachable/+/master/README.md)
+to only get backtraces for sizes of allocations listed as being leaked.
+
### backtrace\_full
As of Q, any time that a backtrace is gathered, a different algorithm is used
that is extra thorough and can unwind through Java frames. This will run
slower than the normal backtracing function.
+### check\_unreachable\_on\_signal
+As of Android U, this option will trigger a check for unreachable memory
+in a process. Specifically, if the signal SIGRTMAX - 16 (which is 48 on
+Android devices). The best way to see the exact signal being used is to
+enable the verbose option then look at the log for the message:
+
+ Run: 'kill -48 <PID>' to check for unreachable memory.
+
+When the signal is received, the actual unreachable check only triggers
+on the next allocation that happens in the process (malloc/free, etc).
+
+If a process is not doing any allocations, it can be forced to trigger when
+running:
+
+ debuggerd -b <PID>
+
+**NOTE**: The unreachable check can fail for protected processes, so it
+might be necessary to run:
+
+ setenforce 0
+
+To get the unreachable data.
+
### fill\_on\_alloc[=MAX\_FILLED\_BYTES]
Any allocation routine, other than calloc, will result in the allocation being
filled with the value 0xeb. When doing a realloc to a larger size, the bytes
@@ -270,7 +328,7 @@
### record\_allocs[=TOTAL\_ENTRIES]
Keep track of every allocation/free made on every thread and dump them
-to a file when the signal SIGRTMAX - 18 (which is 46 on most Android devices)
+to a file when the signal SIGRTMAX - 18 (which is 46 on Android devices)
is received.
If TOTAL\_ENTRIES is set, then it indicates the total number of
diff --git a/libc/malloc_debug/RecordData.cpp b/libc/malloc_debug/RecordData.cpp
index 5c550c0..a829a09 100644
--- a/libc/malloc_debug/RecordData.cpp
+++ b/libc/malloc_debug/RecordData.cpp
@@ -48,44 +48,44 @@
RecordEntry::RecordEntry() : tid_(gettid()) {
}
-std::string ThreadCompleteEntry::GetString() const {
- return android::base::StringPrintf("%d: thread_done 0x0\n", tid_);
+bool ThreadCompleteEntry::Write(int fd) const {
+ return dprintf(fd, "%d: thread_done 0x0\n", tid_) > 0;
}
AllocEntry::AllocEntry(void* pointer) : pointer_(pointer) {}
MallocEntry::MallocEntry(void* pointer, size_t size) : AllocEntry(pointer), size_(size) {}
-std::string MallocEntry::GetString() const {
- return android::base::StringPrintf("%d: malloc %p %zu\n", tid_, pointer_, size_);
+bool MallocEntry::Write(int fd) const {
+ return dprintf(fd, "%d: malloc %p %zu\n", tid_, pointer_, size_) > 0;
}
FreeEntry::FreeEntry(void* pointer) : AllocEntry(pointer) {}
-std::string FreeEntry::GetString() const {
- return android::base::StringPrintf("%d: free %p\n", tid_, pointer_);
+bool FreeEntry::Write(int fd) const {
+ return dprintf(fd, "%d: free %p\n", tid_, pointer_) > 0;
}
CallocEntry::CallocEntry(void* pointer, size_t nmemb, size_t size)
: MallocEntry(pointer, size), nmemb_(nmemb) {}
-std::string CallocEntry::GetString() const {
- return android::base::StringPrintf("%d: calloc %p %zu %zu\n", tid_, pointer_, nmemb_, size_);
+bool CallocEntry::Write(int fd) const {
+ return dprintf(fd, "%d: calloc %p %zu %zu\n", tid_, pointer_, nmemb_, size_) > 0;
}
ReallocEntry::ReallocEntry(void* pointer, size_t size, void* old_pointer)
: MallocEntry(pointer, size), old_pointer_(old_pointer) {}
-std::string ReallocEntry::GetString() const {
- return android::base::StringPrintf("%d: realloc %p %p %zu\n", tid_, pointer_, old_pointer_, size_);
+bool ReallocEntry::Write(int fd) const {
+ return dprintf(fd, "%d: realloc %p %p %zu\n", tid_, pointer_, old_pointer_, size_) > 0;
}
// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
MemalignEntry::MemalignEntry(void* pointer, size_t size, size_t alignment)
: MallocEntry(pointer, size), alignment_(alignment) {}
-std::string MemalignEntry::GetString() const {
- return android::base::StringPrintf("%d: memalign %p %zu %zu\n", tid_, pointer_, alignment_, size_);
+bool MemalignEntry::Write(int fd) const {
+ return dprintf(fd, "%d: memalign %p %zu %zu\n", tid_, pointer_, alignment_, size_) > 0;
}
struct ThreadData {
@@ -112,59 +112,37 @@
}
}
-static void RecordDump(int, siginfo_t*, void*) {
- // It's not necessarily safe to do the dump here, instead wait for the
- // next allocation call to do the dump.
- g_debug->record->SetToDump();
+RecordData* RecordData::record_obj_ = nullptr;
+
+void RecordData::WriteData(int, siginfo_t*, void*) {
+ // Dump from here, the function must not allocate so this is safe.
+ record_obj_->WriteEntries();
}
-void RecordData::Dump() {
- std::lock_guard<std::mutex> lock(dump_lock_);
-
- // Make it so that no more entries can be added while dumping.
- unsigned int last_entry_index = cur_index_.exchange(static_cast<unsigned int>(num_entries_));
- if (dump_ == false) {
- // Multiple Dump() calls from different threads, and we lost. Do nothing.
+void RecordData::WriteEntries() {
+ std::lock_guard<std::mutex> entries_lock(entries_lock_);
+ if (cur_index_ == 0) {
+ info_log("No alloc entries to write.");
return;
}
- // cur_index_ keeps getting incremented even if we hit the num_entries_.
- // If that happens, cap the entries to dump by num_entries_.
- if (last_entry_index > num_entries_) {
- last_entry_index = num_entries_;
- }
-
int dump_fd =
open(dump_file_.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, 0755);
- if (dump_fd != -1) {
- for (size_t i = 0; i < last_entry_index; i++) {
- std::string line = entries_[i]->GetString();
- ssize_t bytes = write(dump_fd, line.c_str(), line.length());
- if (bytes == -1 || static_cast<size_t>(bytes) != line.length()) {
- error_log("Failed to write record alloc information: %s", strerror(errno));
- // Free all of the rest of the errors, we don't have any way
- // to dump a partial list of the entries.
- for (i++; i < last_entry_index; i++) {
- delete entries_[i];
- entries_[i] = nullptr;
- }
- break;
- }
- delete entries_[i];
- entries_[i] = nullptr;
- }
- close(dump_fd);
-
- // Mark the entries dumped.
- cur_index_ = 0U;
- } else {
+ if (dump_fd == -1) {
error_log("Cannot create record alloc file %s: %s", dump_file_.c_str(), strerror(errno));
- // Since we couldn't create the file, reset the entries dumped back
- // to the original value.
- cur_index_ = last_entry_index;
+ return;
}
- dump_ = false;
+ for (size_t i = 0; i < cur_index_; i++) {
+ if (!entries_[i]->Write(dump_fd)) {
+ error_log("Failed to write record alloc information: %s", strerror(errno));
+ break;
+ }
+ }
+ close(dump_fd);
+
+ // Mark the entries dumped.
+ cur_index_ = 0U;
}
RecordData::RecordData() {
@@ -172,8 +150,9 @@
}
bool RecordData::Initialize(const Config& config) {
+ record_obj_ = this;
struct sigaction64 dump_act = {};
- dump_act.sa_sigaction = RecordDump;
+ dump_act.sa_sigaction = RecordData::WriteData;
dump_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
if (sigaction64(config.record_allocs_signal(), &dump_act, nullptr) != 0) {
error_log("Unable to set up record dump signal function: %s", strerror(errno));
@@ -186,24 +165,27 @@
config.record_allocs_signal(), getpid());
}
- num_entries_ = config.record_allocs_num_entries();
- entries_ = new const RecordEntry*[num_entries_];
- cur_index_ = 0;
- dump_ = false;
+ entries_.resize(config.record_allocs_num_entries());
+ cur_index_ = 0U;
dump_file_ = config.record_allocs_file();
return true;
}
RecordData::~RecordData() {
- delete[] entries_;
pthread_key_delete(key_);
}
void RecordData::AddEntryOnly(const RecordEntry* entry) {
- unsigned int entry_index = cur_index_.fetch_add(1);
- if (entry_index < num_entries_) {
- entries_[entry_index] = entry;
+ std::lock_guard<std::mutex> entries_lock(entries_lock_);
+ if (cur_index_ == entries_.size()) {
+ // Maxed out, throw the entry away.
+ return;
+ }
+
+ entries_[cur_index_++].reset(entry);
+ if (cur_index_ == entries_.size()) {
+ info_log("Maximum number of records added, all new operations will be dropped.");
}
}
@@ -215,9 +197,4 @@
}
AddEntryOnly(entry);
-
- // Check to see if it's time to dump the entries.
- if (dump_) {
- Dump();
- }
}
diff --git a/libc/malloc_debug/RecordData.h b/libc/malloc_debug/RecordData.h
index 3d37529..43dba6a 100644
--- a/libc/malloc_debug/RecordData.h
+++ b/libc/malloc_debug/RecordData.h
@@ -29,12 +29,15 @@
#pragma once
#include <pthread.h>
+#include <signal.h>
#include <stdint.h>
#include <unistd.h>
#include <atomic>
+#include <memory>
#include <mutex>
#include <string>
+#include <vector>
#include <platform/bionic/macros.h>
@@ -43,7 +46,7 @@
RecordEntry();
virtual ~RecordEntry() = default;
- virtual std::string GetString() const = 0;
+ virtual bool Write(int fd) const = 0;
protected:
pid_t tid_;
@@ -57,7 +60,7 @@
ThreadCompleteEntry() = default;
virtual ~ThreadCompleteEntry() = default;
- std::string GetString() const override;
+ bool Write(int fd) const override;
private:
BIONIC_DISALLOW_COPY_AND_ASSIGN(ThreadCompleteEntry);
@@ -80,7 +83,7 @@
MallocEntry(void* pointer, size_t size);
virtual ~MallocEntry() = default;
- std::string GetString() const override;
+ bool Write(int fd) const override;
protected:
size_t size_;
@@ -94,7 +97,7 @@
explicit FreeEntry(void* pointer);
virtual ~FreeEntry() = default;
- std::string GetString() const override;
+ bool Write(int fd) const override;
private:
BIONIC_DISALLOW_COPY_AND_ASSIGN(FreeEntry);
@@ -105,7 +108,7 @@
CallocEntry(void* pointer, size_t size, size_t nmemb);
virtual ~CallocEntry() = default;
- std::string GetString() const override;
+ bool Write(int fd) const override;
protected:
size_t nmemb_;
@@ -119,7 +122,7 @@
ReallocEntry(void* pointer, size_t size, void* old_pointer);
virtual ~ReallocEntry() = default;
- std::string GetString() const override;
+ bool Write(int fd) const override;
protected:
void* old_pointer_;
@@ -134,7 +137,7 @@
MemalignEntry(void* pointer, size_t size, size_t alignment);
virtual ~MemalignEntry() = default;
- std::string GetString() const override;
+ bool Write(int fd) const override;
protected:
size_t alignment_;
@@ -155,19 +158,18 @@
void AddEntry(const RecordEntry* entry);
void AddEntryOnly(const RecordEntry* entry);
- void SetToDump() { dump_ = true; }
-
pthread_key_t key() { return key_; }
private:
- void Dump();
+ static void WriteData(int, siginfo_t*, void*);
+ static RecordData* record_obj_;
- std::mutex dump_lock_;
+ void WriteEntries();
+
+ std::mutex entries_lock_;
pthread_key_t key_;
- const RecordEntry** entries_ = nullptr;
- size_t num_entries_ = 0;
- std::atomic_uint cur_index_;
- std::atomic_bool dump_;
+ std::vector<std::unique_ptr<const RecordEntry>> entries_;
+ size_t cur_index_;
std::string dump_file_;
BIONIC_DISALLOW_COPY_AND_ASSIGN(RecordData);
diff --git a/libc/malloc_debug/Unreachable.cpp b/libc/malloc_debug/Unreachable.cpp
new file mode 100644
index 0000000..af47257
--- /dev/null
+++ b/libc/malloc_debug/Unreachable.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <atomic>
+#include <string>
+
+#include <memunreachable/memunreachable.h>
+#include <platform/bionic/macros.h>
+
+#include "Config.h"
+#include "Unreachable.h"
+#include "debug_log.h"
+
+std::atomic_bool Unreachable::do_check_;
+
+static void EnableUnreachableCheck(int, struct siginfo*, void*) {
+ Unreachable::EnableCheck();
+}
+
+void Unreachable::CheckIfRequested(const Config& config) {
+ if ((config.options() & CHECK_UNREACHABLE_ON_SIGNAL) && do_check_.exchange(false)) {
+ info_log("Starting to check for unreachable memory.");
+ if (!LogUnreachableMemory(false, 100)) {
+ error_log("Unreachable check failed, run setenforce 0 and try again.");
+ }
+ }
+}
+
+bool Unreachable::Initialize(const Config& config) {
+ if (!(config.options() & CHECK_UNREACHABLE_ON_SIGNAL)) {
+ return true;
+ }
+
+ struct sigaction64 unreachable_act = {};
+ unreachable_act.sa_sigaction = EnableUnreachableCheck;
+ unreachable_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
+ if (sigaction64(config.check_unreachable_signal(), &unreachable_act, nullptr) != 0) {
+ error_log("Unable to set up check unreachable signal function: %s", strerror(errno));
+ return false;
+ }
+
+ if (config.options() & VERBOSE) {
+ info_log("%s: Run: 'kill -%d %d' to check for unreachable memory.", getprogname(),
+ config.check_unreachable_signal(), getpid());
+ }
+
+ return true;
+}
diff --git a/libc/malloc_debug/Unreachable.h b/libc/malloc_debug/Unreachable.h
new file mode 100644
index 0000000..36c0bdb
--- /dev/null
+++ b/libc/malloc_debug/Unreachable.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <atomic>
+
+// Forward declarations
+class ConfigData;
+
+class Unreachable {
+ public:
+ static bool Initialize(const Config& config);
+ static void CheckIfRequested(const Config& config);
+
+ static void EnableCheck() { do_check_ = true; }
+
+ private:
+ static std::atomic_bool do_check_;
+
+ BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(Unreachable);
+};
diff --git a/libc/malloc_debug/UnwindBacktrace.cpp b/libc/malloc_debug/UnwindBacktrace.cpp
index f6c3e69..c892a39 100644
--- a/libc/malloc_debug/UnwindBacktrace.cpp
+++ b/libc/malloc_debug/UnwindBacktrace.cpp
@@ -36,11 +36,7 @@
#include <vector>
#include <android-base/stringprintf.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/RegsGetLocal.h>
+#include <unwindstack/AndroidUnwinder.h>
#include <unwindstack/Unwinder.h>
#include "UnwindBacktrace.h"
@@ -54,51 +50,22 @@
extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*);
-static pthread_once_t g_setup_once = PTHREAD_ONCE_INIT;
-
-static unwindstack::LocalUpdatableMaps* g_maps;
-static std::shared_ptr<unwindstack::Memory> g_process_memory;
-#if defined(__LP64__)
-static std::vector<std::string> g_skip_libraries{"/system/lib64/libunwindstack.so",
- "/system/lib64/libc_malloc_debug.so"};
-#else
-static std::vector<std::string> g_skip_libraries{"/system/lib/libunwindstack.so",
- "/system/lib/libc_malloc_debug.so"};
-#endif
-
-static void Setup() {
- g_maps = new unwindstack::LocalUpdatableMaps;
- if (!g_maps->Parse()) {
- delete g_maps;
- g_maps = nullptr;
- }
-
- g_process_memory = unwindstack::Memory::CreateProcessMemoryThreadCached(getpid());
-}
-
bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::FrameData>* frame_info,
size_t max_frames) {
- pthread_once(&g_setup_once, Setup);
-
- if (g_maps == nullptr) {
- return false;
- }
-
- std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
- unwindstack::RegsGetLocal(regs.get());
- unwindstack::Unwinder unwinder(max_frames, g_maps, regs.get(), g_process_memory);
- unwinder.Unwind(&g_skip_libraries);
- if (unwinder.NumFrames() == 0) {
+ [[clang::no_destroy]] static unwindstack::AndroidLocalUnwinder unwinder(
+ std::vector<std::string>{"libc_malloc_debug.so"});
+ unwindstack::AndroidUnwinderData data(max_frames);
+ if (!unwinder.Unwind(data)) {
frames->clear();
frame_info->clear();
return false;
}
- *frame_info = unwinder.ConsumeFrames();
- frames->resize(frame_info->size());
- for (size_t i = 0; i < frame_info->size(); i++) {
- frames->at(i) = frame_info->at(i).pc;
+ frames->resize(data.frames.size());
+ for (const auto& frame : data.frames) {
+ frames->at(frame.num) = frame.pc;
}
+ *frame_info = std::move(data.frames);
return true;
}
diff --git a/libc/malloc_debug/UnwindBacktrace.h b/libc/malloc_debug/UnwindBacktrace.h
index 7f89907..091865e 100644
--- a/libc/malloc_debug/UnwindBacktrace.h
+++ b/libc/malloc_debug/UnwindBacktrace.h
@@ -30,10 +30,8 @@
#include <stdint.h>
-#include <string>
#include <vector>
-#include <unwindstack/MapInfo.h>
#include <unwindstack/Unwinder.h>
bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::FrameData>* info,
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 9f38946..617858a 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -53,11 +53,12 @@
#include "Config.h"
#include "DebugData.h"
+#include "Unreachable.h"
+#include "UnwindBacktrace.h"
#include "backtrace.h"
#include "debug_disable.h"
#include "debug_log.h"
#include "malloc_debug.h"
-#include "UnwindBacktrace.h"
// ------------------------------------------------------------------------
// Global Data
@@ -315,7 +316,7 @@
}
DebugData* debug = new DebugData();
- if (!debug->Initialize(options)) {
+ if (!debug->Initialize(options) || !Unreachable::Initialize(debug->config())) {
delete debug;
DebugDisableFinalize();
return false;
@@ -402,6 +403,8 @@
}
size_t debug_malloc_usable_size(void* pointer) {
+ Unreachable::CheckIfRequested(g_debug->config());
+
if (DebugCallsDisabled() || pointer == nullptr) {
return g_dispatch->malloc_usable_size(pointer);
}
@@ -467,6 +470,8 @@
}
void* debug_malloc(size_t size) {
+ Unreachable::CheckIfRequested(g_debug->config());
+
if (DebugCallsDisabled()) {
return g_dispatch->malloc(size);
}
@@ -517,8 +522,8 @@
if (g_debug->config().options() & FILL_ON_FREE) {
size_t fill_bytes = g_debug->config().fill_on_free_bytes();
- bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
- memset(pointer, g_debug->config().fill_free_value(), bytes);
+ fill_bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
+ memset(pointer, g_debug->config().fill_free_value(), fill_bytes);
}
if (g_debug->TrackPointers()) {
@@ -531,7 +536,7 @@
// frees at the same time and we wind up trying to really free this
// pointer from another thread, while still trying to free it in
// this function.
- pointer = PointerData::AddFreed(pointer);
+ pointer = PointerData::AddFreed(pointer, bytes);
if (pointer != nullptr) {
if (g_debug->HeaderEnabled()) {
pointer = g_debug->GetHeader(pointer)->orig_pointer;
@@ -544,6 +549,8 @@
}
void debug_free(void* pointer) {
+ Unreachable::CheckIfRequested(g_debug->config());
+
if (DebugCallsDisabled() || pointer == nullptr) {
return g_dispatch->free(pointer);
}
@@ -563,6 +570,8 @@
}
void* debug_memalign(size_t alignment, size_t bytes) {
+ Unreachable::CheckIfRequested(g_debug->config());
+
if (DebugCallsDisabled()) {
return g_dispatch->memalign(alignment, bytes);
}
@@ -643,6 +652,8 @@
}
void* debug_realloc(void* pointer, size_t bytes) {
+ Unreachable::CheckIfRequested(g_debug->config());
+
if (DebugCallsDisabled()) {
return g_dispatch->realloc(pointer, bytes);
}
@@ -763,6 +774,8 @@
}
void* debug_calloc(size_t nmemb, size_t bytes) {
+ Unreachable::CheckIfRequested(g_debug->config());
+
if (DebugCallsDisabled()) {
return g_dispatch->calloc(nmemb, bytes);
}
@@ -862,6 +875,8 @@
}
void* debug_aligned_alloc(size_t alignment, size_t size) {
+ Unreachable::CheckIfRequested(g_debug->config());
+
if (DebugCallsDisabled()) {
return g_dispatch->aligned_alloc(alignment, size);
}
@@ -873,6 +888,8 @@
}
int debug_posix_memalign(void** memptr, size_t alignment, size_t size) {
+ Unreachable::CheckIfRequested(g_debug->config());
+
if (DebugCallsDisabled()) {
return g_dispatch->posix_memalign(memptr, alignment, size);
}
@@ -890,10 +907,9 @@
void* arg) {
ScopedConcurrentLock lock;
if (g_debug->TrackPointers()) {
- // Since malloc is disabled, don't bother acquiring any locks.
- for (auto it = PointerData::begin(); it != PointerData::end(); ++it) {
- callback(it->first, InternalMallocUsableSize(reinterpret_cast<void*>(it->first)), arg);
- }
+ PointerData::IteratePointers([&callback, &arg](uintptr_t pointer) {
+ callback(pointer, InternalMallocUsableSize(reinterpret_cast<void*>(pointer)), arg);
+ });
return 0;
}
@@ -935,6 +951,8 @@
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
void* debug_pvalloc(size_t bytes) {
+ Unreachable::CheckIfRequested(g_debug->config());
+
if (DebugCallsDisabled()) {
return g_dispatch->pvalloc(bytes);
}
@@ -950,6 +968,8 @@
}
void* debug_valloc(size_t size) {
+ Unreachable::CheckIfRequested(g_debug->config());
+
if (DebugCallsDisabled()) {
return g_dispatch->valloc(size);
}
diff --git a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
index 42d1415..0a0eaef 100644
--- a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
@@ -761,3 +761,87 @@
"which does not take a value\n");
ASSERT_STREQ((log_msg + usage_string).c_str(), getFakeLogPrint().c_str());
}
+
+TEST_F(MallocDebugConfigTest, check_unreachable_on_signal) {
+ ASSERT_TRUE(InitConfig("check_unreachable_on_signal")) << getFakeLogPrint();
+ ASSERT_EQ(CHECK_UNREACHABLE_ON_SIGNAL, config->options());
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, trigger_check_unreachable_on_signal_fail) {
+ ASSERT_FALSE(InitConfig("check_unreachable_on_signal=200")) << getFakeLogPrint();
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string log_msg(
+ "6 malloc_debug malloc_testing: value set for option 'check_unreachable_on_signal' "
+ "which does not take a value\n");
+ ASSERT_STREQ((log_msg + usage_string).c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, size) {
+ ASSERT_TRUE(InitConfig("backtrace_size=37")) << getFakeLogPrint();
+ ASSERT_EQ(BACKTRACE_SPECIFIC_SIZES, config->options());
+ ASSERT_EQ(37U, config->backtrace_min_size_bytes());
+ ASSERT_EQ(37U, config->backtrace_max_size_bytes());
+
+ ASSERT_FALSE(InitConfig("backtrace_size")) << getFakeLogPrint();
+ ASSERT_FALSE(InitConfig("backtrace_size=0")) << getFakeLogPrint();
+ ASSERT_FALSE(InitConfig("backtrace_size=-1")) << getFakeLogPrint();
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string log_msg("6 malloc_debug malloc_testing: bad value for option 'backtrace_size'\n" +
+ usage_string +
+ "6 malloc_debug malloc_testing: bad value for option 'backtrace_size', value "
+ "must be >= 1: 0\n" +
+ usage_string +
+ "6 malloc_debug malloc_testing: bad value for option 'backtrace_size', value "
+ "cannot be negative: -1\n" +
+ usage_string);
+ ASSERT_STREQ(log_msg.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, min_size) {
+ ASSERT_TRUE(InitConfig("backtrace_min_size=9")) << getFakeLogPrint();
+ ASSERT_EQ(BACKTRACE_SPECIFIC_SIZES, config->options());
+ ASSERT_EQ(9U, config->backtrace_min_size_bytes());
+ ASSERT_EQ(SIZE_MAX, config->backtrace_max_size_bytes());
+
+ ASSERT_FALSE(InitConfig("backtrace_min_size")) << getFakeLogPrint();
+ ASSERT_FALSE(InitConfig("backtrace_min_size=0")) << getFakeLogPrint();
+ ASSERT_FALSE(InitConfig("backtrace_min_size=-1")) << getFakeLogPrint();
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string log_msg("6 malloc_debug malloc_testing: bad value for option 'backtrace_min_size'\n" +
+ usage_string +
+ "6 malloc_debug malloc_testing: bad value for option 'backtrace_min_size', "
+ "value must be >= 1: 0\n" +
+ usage_string +
+ "6 malloc_debug malloc_testing: bad value for option 'backtrace_min_size', "
+ "value cannot be negative: -1\n" +
+ usage_string);
+ ASSERT_STREQ(log_msg.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, max_size) {
+ ASSERT_TRUE(InitConfig("backtrace_max_size=13")) << getFakeLogPrint();
+ ASSERT_EQ(BACKTRACE_SPECIFIC_SIZES, config->options());
+ ASSERT_EQ(0U, config->backtrace_min_size_bytes());
+ ASSERT_EQ(13U, config->backtrace_max_size_bytes());
+
+ ASSERT_FALSE(InitConfig("backtrace_max_size")) << getFakeLogPrint();
+ ASSERT_FALSE(InitConfig("backtrace_max_size=0")) << getFakeLogPrint();
+ ASSERT_FALSE(InitConfig("backtrace_max_size=-1")) << getFakeLogPrint();
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string log_msg("6 malloc_debug malloc_testing: bad value for option 'backtrace_max_size'\n" +
+ usage_string +
+ "6 malloc_debug malloc_testing: bad value for option 'backtrace_max_size', "
+ "value must be >= 1: 0\n" +
+ usage_string +
+ "6 malloc_debug malloc_testing: bad value for option 'backtrace_max_size', "
+ "value cannot be negative: -1\n" +
+ usage_string);
+ ASSERT_STREQ(log_msg.c_str(), getFakeLogPrint().c_str());
+}
diff --git a/libc/malloc_debug/tests/malloc_debug_system_tests.cpp b/libc/malloc_debug/tests/malloc_debug_system_tests.cpp
index 92679e4..aee2572 100644
--- a/libc/malloc_debug/tests/malloc_debug_system_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_system_tests.cpp
@@ -52,8 +52,7 @@
#include <thread>
#include <vector>
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
+#include <unwindstack/AndroidUnwinder.h>
#include <bionic/malloc.h>
#include <tests/utils.h>
@@ -452,12 +451,19 @@
static constexpr size_t kMaxRetries = 3;
};
-TEST(MallocTests, DISABLED_smoke) {}
+TEST(MallocTests, DISABLED_smoke) {
+ void* ptr = malloc(128);
+ free(ptr);
+}
TEST_F(MallocDebugSystemTest, smoke) {
Exec("MallocTests.DISABLED_smoke", "verbose backtrace");
}
+TEST_F(MallocDebugSystemTest, backtrace_full_smoke) {
+ Exec("MallocTests.DISABLED_smoke", "verbose backtrace backtrace_full");
+}
+
static void SetAllocationLimit() {
// Set to a large value, this is only to enable the limit code and
// verify that malloc debug is still called properly.
@@ -763,13 +769,14 @@
}
static constexpr size_t kNumUnwinds = 1000;
+ unwindstack::AndroidLocalUnwinder unwinder;
for (size_t i = 0; i < kNumUnwinds; i++) {
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), tid));
// Only verify that there is at least one frame in the unwind.
// This is not a test of the unwinder and clang for arm seems to
// produces an increasing number of code that does not have unwind
// information.
- ASSERT_TRUE(backtrace->Unwind(0)) << "Failed on unwind " << i;
+ unwindstack::AndroidUnwinderData data;
+ ASSERT_TRUE(unwinder.Unwind(data)) << "Failed on unwind " << i;
}
running = false;
thread.join();
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index ea2dc78..c6378f5 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -81,8 +81,19 @@
bool debug_write_malloc_leak_info(FILE*);
void debug_dump_heap(const char*);
+void malloc_enable();
+void malloc_disable();
+
__END_DECLS
+// Change the slow threshold since some tests take more than 2 seconds.
+extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
+ static const char* initial_args[] = {"--slow_threshold_ms=5000"};
+ *args = initial_args;
+ *num_args = 1;
+ return true;
+}
+
constexpr char DIVIDER[] =
"6 malloc_debug *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n";
@@ -90,7 +101,7 @@
return __BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
}
-static constexpr const char RECORD_ALLOCS_FILE[] = "/data/local/tmp/record_allocs.txt";
+static constexpr const char RECORD_ALLOCS_FILE[] = "/data/local/tmp/record_allocs";
static constexpr const char BACKTRACE_DUMP_PREFIX[] = "/data/local/tmp/backtrace_heap";
@@ -100,14 +111,16 @@
initialized = false;
resetLogs();
backtrace_fake_clear_all();
- // Delete the record data file if it exists.
- unlink(RECORD_ALLOCS_FILE);
}
void TearDown() override {
if (initialized) {
debug_finalize();
}
+ if (!record_filename.empty()) {
+ // Try to delete the record data file even it doesn't exist.
+ unlink(record_filename.c_str());
+ }
}
void Init(const char* options) {
@@ -116,6 +129,13 @@
initialized = true;
}
+ void InitRecordAllocs(const char* options) {
+ record_filename = android::base::StringPrintf("%s.%d.txt", RECORD_ALLOCS_FILE, getpid());
+ std::string init(options);
+ init += android::base::StringPrintf(" record_allocs_file=%s", record_filename.c_str());
+ Init(init.c_str());
+ }
+
void BacktraceDumpOnSignal(bool trigger_with_alloc);
static size_t GetInfoEntrySize(size_t max_frames) {
@@ -126,6 +146,8 @@
bool zygote_child;
+ std::string record_filename;
+
static MallocDispatch dispatch;
};
@@ -227,6 +249,9 @@
expected_log += android::base::StringPrintf(
"4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the allocation records.\n",
SIGRTMAX - 18, getpid());
+ expected_log += android::base::StringPrintf(
+ "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to check for unreachable memory.\n",
+ SIGRTMAX - 16, getpid());
}
expected_log += "4 malloc_debug malloc_testing: malloc debug enabled\n";
ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
@@ -296,6 +321,16 @@
ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
}
+TEST_F(MallocDebugTest, verbose_check_unreachable_on_signal) {
+ Init("verbose check_unreachable_on_signal");
+
+ std::string expected_log = android::base::StringPrintf(
+ "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to check for unreachable memory.\n",
+ SIGRTMAX - 16, getpid());
+ expected_log += "4 malloc_debug malloc_testing: malloc debug enabled\n";
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
TEST_F(MallocDebugTest, fill_on_free) {
Init("fill_on_free free_track free_track_backtrace_num_frames=0");
@@ -359,7 +394,7 @@
TEST_F(MallocDebugTest, all_options) {
Init(
"guard backtrace backtrace_enable_on_signal fill expand_alloc free_track leak_track "
- "record_allocs verify_pointers abort_on_error verbose");
+ "record_allocs verify_pointers abort_on_error verbose check_unreachable_on_signal");
VerifyAllocCalls(true);
}
@@ -2135,7 +2170,7 @@
}
#endif
-void VerifyRecordAllocs() {
+void VerifyRecordAllocs(const std::string& record_filename) {
std::string expected;
void* pointer = debug_malloc(10);
@@ -2195,40 +2230,31 @@
// Dump all of the data accumulated so far.
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
- sleep(1);
-
- // This triggers the dumping.
- pointer = debug_malloc(110);
- ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 110\n", getpid(), pointer);
// Read all of the contents.
std::string actual;
- ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
- ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
+ ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
ASSERT_STREQ(expected.c_str(), actual.c_str());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
-
- debug_free(pointer);
}
TEST_F(MallocDebugTest, record_allocs_no_header) {
- Init("record_allocs");
+ InitRecordAllocs("record_allocs");
- VerifyRecordAllocs();
+ VerifyRecordAllocs(record_filename);
}
TEST_F(MallocDebugTest, record_allocs_with_header) {
- Init("record_allocs front_guard");
+ InitRecordAllocs("record_allocs front_guard");
- VerifyRecordAllocs();
+ VerifyRecordAllocs(record_filename);
}
TEST_F(MallocDebugTest, record_allocs_max) {
- Init("record_allocs=5");
+ InitRecordAllocs("record_allocs=5");
std::string expected;
@@ -2251,27 +2277,21 @@
// Dump all of the data accumulated so far.
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
- sleep(1);
-
- // This triggers the dumping.
- pointer = debug_malloc(110);
- ASSERT_TRUE(pointer != nullptr);
// Read all of the contents.
std::string actual;
- ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
- ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
+ ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
ASSERT_STREQ(expected.c_str(), actual.c_str());
ASSERT_STREQ("", getFakeLogBuf().c_str());
- ASSERT_STREQ("", getFakeLogPrint().c_str());
-
- debug_free(pointer);
+ ASSERT_STREQ(
+ "4 malloc_debug Maximum number of records added, all new operations will be dropped.\n",
+ getFakeLogPrint().c_str());
}
TEST_F(MallocDebugTest, record_allocs_thread_done) {
- Init("record_allocs=5");
+ InitRecordAllocs("record_allocs=5");
static pid_t tid = 0;
static void* pointer = nullptr;
@@ -2289,34 +2309,25 @@
// Dump all of the data accumulated so far.
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
- sleep(1);
-
- // This triggers the dumping.
- pointer = debug_malloc(23);
- ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 23\n", getpid(), pointer);
// Read all of the contents.
std::string actual;
- ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
- ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
+ ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
ASSERT_STREQ(expected.c_str(), actual.c_str());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
-
- debug_free(pointer);
}
TEST_F(MallocDebugTest, record_allocs_file_name_fail) {
- Init("record_allocs=5");
+ InitRecordAllocs("record_allocs=5");
- // Delete the special.txt file and create a symbolic link there to
+ // Delete the records file and create a symbolic link there to
// make sure the create file will fail.
- unlink(RECORD_ALLOCS_FILE);
+ unlink(record_filename.c_str());
- ASSERT_EQ(0, symlink("/data/local/tmp/does_not_exist", RECORD_ALLOCS_FILE));
+ ASSERT_EQ(0, symlink("/data/local/tmp/does_not_exist", record_filename.c_str()));
std::string expected;
@@ -2328,39 +2339,62 @@
// Dump all of the data accumulated so far.
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
- sleep(1);
-
- // This triggers the dumping.
- pointer = debug_malloc(110);
- ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 110\n", getpid(), pointer);
// Read all of the contents.
std::string actual;
- ASSERT_FALSE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
+ ASSERT_FALSE(android::base::ReadFileToString(record_filename, &actual));
// Unlink the file so the next dump passes.
- ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
+ ASSERT_EQ(0, unlink(record_filename.c_str()));
// Dump all of the data accumulated so far.
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
- sleep(1);
- // This triggers the dumping.
- debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
-
- ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
- ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
+ ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
ASSERT_STREQ(expected.c_str(), actual.c_str());
ASSERT_STREQ("", getFakeLogBuf().c_str());
std::string expected_log = android::base::StringPrintf(
"6 malloc_debug Cannot create record alloc file %s: Too many symbolic links encountered\n",
- RECORD_ALLOCS_FILE);
+ record_filename.c_str());
ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
}
+TEST_F(MallocDebugTest, record_allocs_no_entries_to_write) {
+ InitRecordAllocs("record_allocs=5");
+
+ kill(getpid(), SIGRTMAX - 18);
+
+ std::string actual;
+ ASSERT_FALSE(android::base::ReadFileToString(record_filename, &actual));
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ ASSERT_STREQ("4 malloc_debug No alloc entries to write.\n", getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugTest, record_allocs_write_entries_does_not_allocate) {
+ InitRecordAllocs("record_allocs=5");
+
+ std::string expected;
+
+ void* pointer = debug_malloc(10);
+ ASSERT_TRUE(pointer != nullptr);
+ expected += android::base::StringPrintf("%d: malloc %p 10\n", getpid(), pointer);
+ debug_free(pointer);
+ expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+
+ malloc_disable();
+ kill(getpid(), SIGRTMAX - 18);
+ malloc_enable();
+
+ std::string actual;
+ ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
+ ASSERT_STREQ(expected.c_str(), actual.c_str());
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
TEST_F(MallocDebugTest, verify_pointers) {
Init("verify_pointers");
@@ -2695,3 +2729,209 @@
std::string expected_log = std::string("6 malloc_debug Dumping to file: ") + tf.path + "\n\n";
ASSERT_EQ(expected_log, getFakeLogPrint());
}
+
+extern "C" bool LogUnreachableMemory(bool, size_t) {
+ static bool return_value = false;
+ return_value = !return_value;
+ return return_value;
+}
+
+TEST_F(MallocDebugTest, check_unreachable_on_signal) {
+ Init("check_unreachable_on_signal");
+
+ ASSERT_TRUE(kill(getpid(), SIGRTMAX - 16) == 0);
+ sleep(1);
+
+ // The first unreachable check will pass.
+ void* pointer = debug_malloc(110);
+ ASSERT_TRUE(pointer != nullptr);
+
+ ASSERT_TRUE(kill(getpid(), SIGRTMAX - 16) == 0);
+ sleep(1);
+
+ // The second unreachable check will fail.
+ debug_free(pointer);
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string expected_log = "4 malloc_debug Starting to check for unreachable memory.\n";
+ ASSERT_STREQ(
+ "4 malloc_debug Starting to check for unreachable memory.\n"
+ "4 malloc_debug Starting to check for unreachable memory.\n"
+ "6 malloc_debug Unreachable check failed, run setenforce 0 and try again.\n",
+ getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugTest, backtrace_only_some_sizes_with_backtrace_size) {
+ Init("leak_track backtrace backtrace_size=120");
+
+ backtrace_fake_add(std::vector<uintptr_t>{0x1000, 0x2000, 0x3000});
+
+ void* pointer1 = debug_malloc(119);
+ ASSERT_TRUE(pointer1 != nullptr);
+
+ backtrace_fake_add(std::vector<uintptr_t>{0xa000, 0xb000, 0xc000, 0xd000});
+
+ void* pointer2 = debug_malloc(120);
+ ASSERT_TRUE(pointer2 != nullptr);
+
+ backtrace_fake_add(std::vector<uintptr_t>{0xfe000, 0xde000, 0xce000, 0xbe000, 0xae000});
+
+ void* pointer3 = debug_malloc(121);
+ ASSERT_TRUE(pointer3 != nullptr);
+
+ debug_finalize();
+ initialized = false;
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string expected_log = android::base::StringPrintf(
+ "6 malloc_debug +++ malloc_testing leaked block of size 121 at %p (leak 1 of 3)\n", pointer3);
+
+ expected_log += android::base::StringPrintf(
+ "6 malloc_debug +++ malloc_testing leaked block of size 120 at %p (leak 2 of 3)\n", pointer2);
+ expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
+ expected_log += "6 malloc_debug #00 pc 0x1000\n";
+ expected_log += "6 malloc_debug #01 pc 0x2000\n";
+ expected_log += "6 malloc_debug #02 pc 0x3000\n";
+
+ expected_log += android::base::StringPrintf(
+ "6 malloc_debug +++ malloc_testing leaked block of size 119 at %p (leak 3 of 3)\n", pointer1);
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugTest, backtrace_only_some_sizes_with_backtrace_min_size) {
+ Init("leak_track backtrace backtrace_min_size=1000");
+
+ backtrace_fake_add(std::vector<uintptr_t>{0x1000, 0x2000, 0x3000});
+
+ void* pointer1 = debug_malloc(500);
+ ASSERT_TRUE(pointer1 != nullptr);
+
+ backtrace_fake_add(std::vector<uintptr_t>{0xa000, 0xb000, 0xc000, 0xd000});
+
+ void* pointer2 = debug_malloc(1000);
+ ASSERT_TRUE(pointer2 != nullptr);
+
+ backtrace_fake_add(std::vector<uintptr_t>{0xfe000, 0xde000, 0xce000, 0xbe000, 0xae000});
+
+ void* pointer3 = debug_malloc(1001);
+ ASSERT_TRUE(pointer3 != nullptr);
+
+ debug_finalize();
+ initialized = false;
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string expected_log = android::base::StringPrintf(
+ "6 malloc_debug +++ malloc_testing leaked block of size 1001 at %p (leak 1 of 3)\n",
+ pointer3);
+ expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
+ expected_log += "6 malloc_debug #00 pc 0xa000\n";
+ expected_log += "6 malloc_debug #01 pc 0xb000\n";
+ expected_log += "6 malloc_debug #02 pc 0xc000\n";
+ expected_log += "6 malloc_debug #03 pc 0xd000\n";
+
+ expected_log += android::base::StringPrintf(
+ "6 malloc_debug +++ malloc_testing leaked block of size 1000 at %p (leak 2 of 3)\n",
+ pointer2);
+ expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
+ expected_log += "6 malloc_debug #00 pc 0x1000\n";
+ expected_log += "6 malloc_debug #01 pc 0x2000\n";
+ expected_log += "6 malloc_debug #02 pc 0x3000\n";
+
+ expected_log += android::base::StringPrintf(
+ "6 malloc_debug +++ malloc_testing leaked block of size 500 at %p (leak 3 of 3)\n", pointer1);
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugTest, backtrace_only_some_sizes_with_backtrace_max_size) {
+ Init("leak_track backtrace backtrace_max_size=1000");
+
+ backtrace_fake_add(std::vector<uintptr_t>{0x1000, 0x2000, 0x3000});
+
+ void* pointer1 = debug_malloc(1000);
+ ASSERT_TRUE(pointer1 != nullptr);
+
+ backtrace_fake_add(std::vector<uintptr_t>{0xa000, 0xb000, 0xc000, 0xd000});
+
+ void* pointer2 = debug_malloc(1001);
+ ASSERT_TRUE(pointer2 != nullptr);
+
+ backtrace_fake_add(std::vector<uintptr_t>{0xfe000, 0xde000, 0xce000, 0xbe000, 0xae000});
+
+ void* pointer3 = debug_malloc(5000);
+ ASSERT_TRUE(pointer3 != nullptr);
+
+ debug_finalize();
+ initialized = false;
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string expected_log = android::base::StringPrintf(
+ "6 malloc_debug +++ malloc_testing leaked block of size 5000 at %p (leak 1 of 3)\n",
+ pointer3);
+
+ expected_log += android::base::StringPrintf(
+ "6 malloc_debug +++ malloc_testing leaked block of size 1001 at %p (leak 2 of 3)\n",
+ pointer2);
+
+ expected_log += android::base::StringPrintf(
+ "6 malloc_debug +++ malloc_testing leaked block of size 1000 at %p (leak 3 of 3)\n",
+ pointer1);
+ expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
+ expected_log += "6 malloc_debug #00 pc 0x1000\n";
+ expected_log += "6 malloc_debug #01 pc 0x2000\n";
+ expected_log += "6 malloc_debug #02 pc 0x3000\n";
+
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugTest, backtrace_only_some_sizes_with_backtrace_min_max_size) {
+ Init("leak_track backtrace backtrace_min_size=50 backtrace_max_size=1000");
+
+ backtrace_fake_add(std::vector<uintptr_t>{0x1000, 0x2000, 0x3000});
+
+ void* pointer1 = debug_malloc(49);
+ ASSERT_TRUE(pointer1 != nullptr);
+
+ backtrace_fake_add(std::vector<uintptr_t>{0xa000, 0xb000, 0xc000, 0xd000});
+
+ void* pointer2 = debug_malloc(50);
+ ASSERT_TRUE(pointer2 != nullptr);
+
+ backtrace_fake_add(std::vector<uintptr_t>{0xfe000, 0xde000, 0xce000, 0xbe000, 0xae000});
+
+ void* pointer3 = debug_malloc(1000);
+ ASSERT_TRUE(pointer3 != nullptr);
+
+ backtrace_fake_add(std::vector<uintptr_t>{0x1a000, 0x1b000, 0x1c000, 0x1d000, 0x1e000});
+
+ void* pointer4 = debug_malloc(1001);
+ ASSERT_TRUE(pointer4 != nullptr);
+
+ debug_finalize();
+ initialized = false;
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string expected_log = android::base::StringPrintf(
+ "6 malloc_debug +++ malloc_testing leaked block of size 1001 at %p (leak 1 of 4)\n",
+ pointer4);
+
+ expected_log += android::base::StringPrintf(
+ "6 malloc_debug +++ malloc_testing leaked block of size 1000 at %p (leak 2 of 4)\n",
+ pointer3);
+ expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
+ expected_log += "6 malloc_debug #00 pc 0xa000\n";
+ expected_log += "6 malloc_debug #01 pc 0xb000\n";
+ expected_log += "6 malloc_debug #02 pc 0xc000\n";
+ expected_log += "6 malloc_debug #03 pc 0xd000\n";
+
+ expected_log += android::base::StringPrintf(
+ "6 malloc_debug +++ malloc_testing leaked block of size 50 at %p (leak 3 of 4)\n", pointer2);
+ expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
+ expected_log += "6 malloc_debug #00 pc 0x1000\n";
+ expected_log += "6 malloc_debug #01 pc 0x2000\n";
+ expected_log += "6 malloc_debug #02 pc 0x3000\n";
+
+ expected_log += android::base::StringPrintf(
+ "6 malloc_debug +++ malloc_testing leaked block of size 49 at %p (leak 4 of 4)\n", pointer1);
+
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
diff --git a/libc/platform/bionic/macros.h b/libc/platform/bionic/macros.h
index 076cff1..9e13e0d 100644
--- a/libc/platform/bionic/macros.h
+++ b/libc/platform/bionic/macros.h
@@ -55,6 +55,8 @@
#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined x30")
#elif defined(__i386__)
#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined \%eip")
+#elif defined(__riscv)
+#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined ra")
#elif defined(__x86_64__)
#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined \%rip")
#endif
diff --git a/libc/platform/bionic/malloc.h b/libc/platform/bionic/malloc.h
index f0f13d0..ecc8743 100644
--- a/libc/platform/bionic/malloc.h
+++ b/libc/platform/bionic/malloc.h
@@ -100,6 +100,9 @@
// arg_size = sizeof(android_mallopt_gwp_asan_options_t)
M_INITIALIZE_GWP_ASAN = 10,
#define M_INITIALIZE_GWP_ASAN M_INITIALIZE_GWP_ASAN
+ // Query whether memtag stack is enabled for this process.
+ M_MEMTAG_STACK_IS_ON = 11,
+#define M_MEMTAG_STACK_IS_ON M_MEMTAG_STACK_IS_ON
};
typedef struct {
@@ -133,7 +136,7 @@
} android_mallopt_gwp_asan_options_t;
// Manipulates bionic-specific handling of memory allocation APIs such as
-// malloc. Only for use by the Android platform itself.
+// malloc. Only for use by the Android platform and APEXes.
//
// On success, returns true. On failure, returns false and sets errno.
extern "C" bool android_mallopt(int opcode, void* arg, size_t arg_size);
diff --git a/libc/platform/bionic/tls.h b/libc/platform/bionic/tls.h
index bf9e65b..e01eccd 100644
--- a/libc/platform/bionic/tls.h
+++ b/libc/platform/bionic/tls.h
@@ -34,6 +34,8 @@
# define __get_tls() ({ void** __val; __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__val)); __val; })
#elif defined(__i386__)
# define __get_tls() ({ void** __val; __asm__("movl %%gs:0, %0" : "=r"(__val)); __val; })
+#elif defined(__riscv)
+# define __get_tls() ({ void** __val; __asm__("mv %0, tp" : "=r"(__val)); __val; })
#elif defined(__x86_64__)
# define __get_tls() ({ void** __val; __asm__("mov %%fs:0, %0" : "=r"(__val)); __val; })
#else
diff --git a/libc/platform/bionic/tls_defines.h b/libc/platform/bionic/tls_defines.h
index 78099b3..3e2efa3 100644
--- a/libc/platform/bionic/tls_defines.h
+++ b/libc/platform/bionic/tls_defines.h
@@ -114,6 +114,28 @@
#define TLS_SLOT_BIONIC_TLS 9
#define MAX_TLS_SLOT 9 // update this value when reserving a slot
+#elif defined(__riscv)
+
+// RISC-V ELF Specification[1] specifies that RISC-V uses Variant I as described
+// by the ELF TLS specification, with tp containing the address one past the end
+// of the TCB.
+//
+// [1]: RISC-V ELF Specification. Section: Thread Local Storage
+// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#thread-local-storage
+
+#define MIN_TLS_SLOT (-9) // update this value when reserving a slot
+
+#define TLS_SLOT_BIONIC_TLS (-9)
+#define TLS_SLOT_DTV (-8)
+#define TLS_SLOT_THREAD_ID (-7)
+#define TLS_SLOT_APP (-6)
+#define TLS_SLOT_OPENGL (-5)
+#define TLS_SLOT_OPENGL_API (-4)
+#define TLS_SLOT_STACK_GUARD (-3)
+#define TLS_SLOT_SANITIZER (-2)
+#define TLS_SLOT_ART_THREAD_SELF (-1)
+#define MAX_TLS_SLOT (-1)
+
#endif
#define BIONIC_TLS_SLOTS (MAX_TLS_SLOT - MIN_TLS_SLOT + 1)
diff --git a/libc/private/bionic_asm.h b/libc/private/bionic_asm.h
index d68a2d6..78e5046 100644
--- a/libc/private/bionic_asm.h
+++ b/libc/private/bionic_asm.h
@@ -45,6 +45,8 @@
#include <private/bionic_asm_arm.h>
#elif defined(__i386__)
#include <private/bionic_asm_x86.h>
+#elif defined(__riscv)
+#include <private/bionic_asm_riscv64.h>
#elif defined(__x86_64__)
#include <private/bionic_asm_x86_64.h>
#endif
diff --git a/libc/private/bionic_asm_arm64.h b/libc/private/bionic_asm_arm64.h
index 5d83d9b..ffc7181 100644
--- a/libc/private/bionic_asm_arm64.h
+++ b/libc/private/bionic_asm_arm64.h
@@ -76,3 +76,4 @@
#define NT_MEMTAG_LEVEL_ASYNC 1
#define NT_MEMTAG_LEVEL_SYNC 2
#define NT_MEMTAG_HEAP 4
+#define NT_MEMTAG_STACK 8
diff --git a/libc/private/bionic_asm_riscv64.h b/libc/private/bionic_asm_riscv64.h
new file mode 100644
index 0000000..463ca31
--- /dev/null
+++ b/libc/private/bionic_asm_riscv64.h
@@ -0,0 +1,43 @@
+/* $OpenBSD: asm.h,v 1.1 2004/02/01 05:09:49 drahn Exp $ */
+/* $NetBSD: asm.h,v 1.4 2001/07/16 05:43:32 matt Exp $ */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)asm.h 5.5 (Berkeley) 5/7/91
+ */
+
+#pragma once
+
+#define __bionic_asm_align 16
+
+#undef __bionic_asm_function_type
+#define __bionic_asm_function_type %function
diff --git a/libc/private/bionic_elf_tls.h b/libc/private/bionic_elf_tls.h
index e0ec7b5..79ffcc4 100644
--- a/libc/private/bionic_elf_tls.h
+++ b/libc/private/bionic_elf_tls.h
@@ -201,3 +201,18 @@
struct bionic_tcb;
void __free_dynamic_tls(bionic_tcb* tcb);
void __notify_thread_exit_callbacks();
+
+#if defined(__riscv)
+// TLS_DTV_OFFSET is a constant used in relocation fields, defined in RISC-V ELF Specification[1]
+// The front of the TCB contains a pointer to the DTV, and each pointer in DTV
+// points to 0x800 past the start of a TLS block to make full use of the range
+// of load/store instructions, refer to [2].
+//
+// [1]: RISC-V ELF Specification.
+// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#constants
+// [2]: Documentation of TLS data structures
+// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/53
+#define TLS_DTV_OFFSET 0x800
+#else
+#define TLS_DTV_OFFSET 0
+#endif
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index e105c18..c7e951d 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -29,24 +29,25 @@
#ifndef _PRIVATE_BIONIC_GLOBALS_H
#define _PRIVATE_BIONIC_GLOBALS_H
+#include <inttypes.h>
+#include <link.h>
+#include <platform/bionic/malloc.h>
+#include <pthread.h>
#include <stdatomic.h>
#include <sys/cdefs.h>
-#include <link.h>
-#include <pthread.h>
+#include "private/WriteProtected.h"
#include "private/bionic_allocator.h"
#include "private/bionic_elf_tls.h"
#include "private/bionic_fdsan.h"
#include "private/bionic_malloc_dispatch.h"
#include "private/bionic_vdso.h"
-#include "private/WriteProtected.h"
-
-#include <platform/bionic/malloc.h>
struct libc_globals {
vdso_entry vdso[VDSO_END];
long setjmp_cookie;
uintptr_t heap_pointer_tag;
+ _Atomic(bool) memtag_stack;
// In order to allow a complete switch between dispatch tables without
// the need for copying each function by function in the structure,
@@ -112,6 +113,8 @@
const char* scudo_ring_buffer = nullptr;
HeapTaggingLevel initial_heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
+ bool initial_memtag_stack = false;
+ int64_t heap_tagging_upgrade_timer_sec = 0;
};
__LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals();
diff --git a/libc/seccomp/seccomp_bpfs.h b/libc/seccomp/seccomp_bpfs.h
index 3bdffa9..34219e2 100644
--- a/libc/seccomp/seccomp_bpfs.h
+++ b/libc/seccomp/seccomp_bpfs.h
@@ -33,6 +33,13 @@
extern const struct sock_filter arm64_system_filter[];
extern const size_t arm64_system_filter_size;
+extern const struct sock_filter riscv64_app_filter[];
+extern const size_t riscv64_app_filter_size;
+extern const struct sock_filter riscv64_app_zygote_filter[];
+extern const size_t riscv64_app_zygote_filter_size;
+extern const struct sock_filter riscv64_system_filter[];
+extern const size_t riscv64_system_filter_size;
+
extern const struct sock_filter x86_app_filter[];
extern const size_t x86_app_filter_size;
extern const struct sock_filter x86_app_zygote_filter[];
diff --git a/libc/seccomp/seccomp_policy.cpp b/libc/seccomp/seccomp_policy.cpp
index a42816e..1ca4eec 100644
--- a/libc/seccomp/seccomp_policy.cpp
+++ b/libc/seccomp/seccomp_policy.cpp
@@ -25,13 +25,13 @@
#include <vector>
#include <android-base/logging.h>
+#include <android-base/macros.h>
#include "func_to_syscall_nrs.h"
#include "seccomp_bpfs.h"
#if defined __arm__ || defined __aarch64__
-#define DUAL_ARCH
#define PRIMARY_ARCH AUDIT_ARCH_AARCH64
static const struct sock_filter* primary_app_filter = arm64_app_filter;
static const size_t primary_app_filter_size = arm64_app_filter_size;
@@ -52,9 +52,9 @@
static const long secondary_setresgid = __arm_setresgid;
static const long secondary_setresuid = __arm_setresuid;
+
#elif defined __i386__ || defined __x86_64__
-#define DUAL_ARCH
#define PRIMARY_ARCH AUDIT_ARCH_X86_64
static const struct sock_filter* primary_app_filter = x86_64_app_filter;
static const size_t primary_app_filter_size = x86_64_app_filter_size;
@@ -75,6 +75,20 @@
static const long secondary_setresgid = __x86_setresgid;
static const long secondary_setresuid = __x86_setresuid;
+
+#elif defined(__riscv)
+
+#define PRIMARY_ARCH AUDIT_ARCH_RISCV64
+static const struct sock_filter* primary_app_filter = riscv64_app_filter;
+static const size_t primary_app_filter_size = riscv64_app_filter_size;
+static const struct sock_filter* primary_app_zygote_filter = riscv64_app_zygote_filter;
+static const size_t primary_app_zygote_filter_size = riscv64_app_zygote_filter_size;
+static const struct sock_filter* primary_system_filter = riscv64_system_filter;
+static const size_t primary_system_filter_size = riscv64_system_filter_size;
+
+static const long primary_setresgid = __riscv64_setresgid;
+static const long primary_setresuid = __riscv64_setresuid;
+
#else
#error No architecture was defined!
#endif
@@ -98,7 +112,7 @@
f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_nr));
}
-#ifdef DUAL_ARCH
+#if defined(SECONDARY_ARCH)
static bool SetValidateArchitectureJumpTarget(size_t offset, filter& f) {
size_t jump_length = f.size() - offset - 1;
auto u8_jump_length = (__u8) jump_length;
@@ -149,9 +163,17 @@
// that's the only system call we need to check here. A CTS test ensures the other
// calls will remain blocked.
static void ValidateSetUidGid(filter& f, uint32_t uid_gid_min, uint32_t uid_gid_max, bool primary) {
+#if defined(SECONDARY_ARCH)
+ __u32 setresuid_nr = primary ? primary_setresuid : secondary_setresuid;
+ __u32 setresgid_nr = primary ? primary_setresgid : secondary_setresgid;
+#else
+ __u32 setresuid_nr = primary_setresuid;
+ __u32 setresgid_nr = primary_setresgid;
+ UNUSED(primary);
+#endif
+
// Check setresuid(ruid, euid, sguid) fall within range
ExamineSyscall(f);
- __u32 setresuid_nr = primary ? primary_setresuid : secondary_setresuid;
f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, setresuid_nr, 0, 12));
for (int arg = 0; arg < 3; arg++) {
ValidateSyscallArgInRange(f, arg, uid_gid_min, uid_gid_max);
@@ -159,7 +181,6 @@
// Check setresgid(rgid, egid, sgid) fall within range
ExamineSyscall(f);
- __u32 setresgid_nr = primary ? primary_setresgid : secondary_setresgid;
f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, setresgid_nr, 0, 12));
for (int arg = 0; arg < 3; arg++) {
ValidateSyscallArgInRange(f, arg, uid_gid_min, uid_gid_max);
@@ -184,7 +205,7 @@
bool _install_setuidgid_filter(uint32_t uid_gid_min, uint32_t uid_gid_max) {
filter f;
-#ifdef DUAL_ARCH
+#if defined(SECONDARY_ARCH)
// Note that for mixed 64/32 bit architectures, ValidateArchitecture inserts a
// jump that must be changed to point to the start of the 32-bit policy
// 32 bit syscalls will not hit the policy between here and the call to SetJump
@@ -195,7 +216,7 @@
ValidateSetUidGid(f, uid_gid_min, uid_gid_max, true /* primary */);
-#ifdef DUAL_ARCH
+#if defined(SECONDARY_ARCH)
if (!SetValidateArchitectureJumpTarget(offset_to_secondary_filter, f)) {
return false;
}
@@ -213,32 +234,43 @@
};
bool _set_seccomp_filter(FilterType type) {
- const sock_filter *p, *s;
- size_t p_size, s_size;
filter f;
+ const sock_filter* p;
+ size_t p_size;
+#if defined(SECONDARY_ARCH)
+ const sock_filter* s;
+ size_t s_size;
+#endif
+
switch (type) {
case APP:
p = primary_app_filter;
p_size = primary_app_filter_size;
+#if defined(SECONDARY_ARCH)
s = secondary_app_filter;
s_size = secondary_app_filter_size;
+#endif
break;
case APP_ZYGOTE:
p = primary_app_zygote_filter;
p_size = primary_app_zygote_filter_size;
+#if defined(SECONDARY_ARCH)
s = secondary_app_zygote_filter;
s_size = secondary_app_zygote_filter_size;
+#endif
break;
case SYSTEM:
p = primary_system_filter;
p_size = primary_system_filter_size;
+#if defined(SECONDARY_ARCH)
s = secondary_system_filter;
s_size = secondary_system_filter_size;
+#endif
break;
}
-#ifdef DUAL_ARCH
+#if defined(SECONDARY_ARCH)
// Note that for mixed 64/32 bit architectures, ValidateArchitecture inserts a
// jump that must be changed to point to the start of the 32-bit policy
// 32 bit syscalls will not hit the policy between here and the call to SetJump
@@ -254,7 +286,7 @@
}
Disallow(f);
-#ifdef DUAL_ARCH
+#if defined(SECONDARY_ARCH)
if (!SetValidateArchitectureJumpTarget(offset_to_secondary_filter, f)) {
return false;
}
diff --git a/libc/stdio/printf_common.h b/libc/stdio/printf_common.h
index 4dc5ca1..e761835 100644
--- a/libc/stdio/printf_common.h
+++ b/libc/stdio/printf_common.h
@@ -524,6 +524,8 @@
case 'u':
case 'X':
case 'x':
+ case 'B':
+ case 'b':
ADDUARG();
break;
default: /* "%?" prints ?, unless ? is NUL */
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index 08df2eb..27813a6 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -1129,7 +1129,9 @@
// Read directly into the caller's buffer.
while (total > 0) {
- ssize_t bytes_read = (*fp->_read)(fp->_cookie, dst, total);
+ // The _read function pointer takes an int instead of a size_t.
+ int chunk_size = MIN(total, INT_MAX);
+ ssize_t bytes_read = (*fp->_read)(fp->_cookie, dst, chunk_size);
if (bytes_read <= 0) {
fp->_flags |= (bytes_read == 0) ? __SEOF : __SERR;
break;
diff --git a/libc/stdio/stdio_ext.cpp b/libc/stdio/stdio_ext.cpp
index 945813e..99a8af7 100644
--- a/libc/stdio/stdio_ext.cpp
+++ b/libc/stdio/stdio_ext.cpp
@@ -67,6 +67,12 @@
return fp->_p - fp->_bf._base;
}
+size_t __freadahead(FILE* fp) {
+ // Normally _r is the amount of input already available.
+ // When there's ungetc() data, _r counts that and _ur is the previous _r.
+ return fp->_r + (HASUB(fp) ? fp->_ur : 0);
+}
+
void _flushlbf() {
// If we flush all streams, we know we've flushed all the line-buffered streams.
fflush(nullptr);
diff --git a/libc/stdio/vfprintf.cpp b/libc/stdio/vfprintf.cpp
index d99d09c..d83a5bf 100644
--- a/libc/stdio/vfprintf.cpp
+++ b/libc/stdio/vfprintf.cpp
@@ -81,8 +81,8 @@
char* dtoaresult = nullptr;
uintmax_t _umax; /* integer arguments %[diouxX] */
- enum { OCT, DEC, HEX } base; /* base for %[diouxX] conversion */
- int dprec; /* a copy of prec if %[diouxX], 0 otherwise */
+ enum { BIN, OCT, DEC, HEX } base; /* base for %[bBdiouxX] conversion */
+ int dprec; /* a copy of prec if %[bBdiouxX], 0 otherwise */
int realsz; /* field size expanded by dprec */
int size; /* size of converted field or string */
const char* xdigs; /* digits for %[xX] conversion */
@@ -304,6 +304,12 @@
case 'z':
flags |= SIZEINT;
goto rflag;
+ case 'B':
+ case 'b':
+ _umax = UARG();
+ base = BIN;
+ if (flags & ALT && _umax != 0) ox[1] = ch;
+ goto nosign;
case 'C':
flags |= LONGINT;
__BIONIC_FALLTHROUGH;
@@ -550,6 +556,13 @@
* a variable; hence this switch.
*/
switch (base) {
+ case BIN:
+ do {
+ *--cp = to_char(_umax & 1);
+ _umax >>= 1;
+ } while (_umax);
+ break;
+
case OCT:
do {
*--cp = to_char(_umax & 7);
@@ -599,7 +612,7 @@
* first be prefixed by any sign or other prefix; otherwise,
* it should be blank padded before the prefix is emitted.
* After any left-hand padding and prefixing, emit zeroes
- * required by a decimal %[diouxX] precision, then print the
+ * required by a decimal %[bBdiouxX] precision, then print the
* string proper, then emit zeroes required by any leftover
* floating precision; finally, if LADJUST, pad with blanks.
*
diff --git a/libc/stdio/vfscanf.cpp b/libc/stdio/vfscanf.cpp
index 424c4ef..d05a3a6 100644
--- a/libc/stdio/vfscanf.cpp
+++ b/libc/stdio/vfscanf.cpp
@@ -69,7 +69,8 @@
#define HAVESIGN 0x04000 // Sign detected
#define NDIGITS 0x08000 // No digits detected
#define PFXOK 0x10000 // "0x" prefix is (still) legal
-#define NZDIGITS 0x20000 // No zero digits detected
+#define PFBOK 0x20000 // "0b" prefix is (still) legal
+#define NZDIGITS 0x40000 // No zero digits detected
// Conversion types.
#define CT_CHAR 0 // %c conversion
@@ -101,9 +102,6 @@
void* allocation = nullptr; // Allocated but unassigned result for %mc/%ms/%m[.
size_t capacity = 0; // Number of char/wchar_t units allocated in `allocation`.
- /* `basefix' is used to avoid `if' tests in the integer scanner */
- static short basefix[17] = { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
-
_SET_ORIENTATION(fp, -1);
nassigned = 0;
@@ -188,6 +186,12 @@
* Conversions.
* Those marked `compat' are for 4.[123]BSD compatibility.
*/
+ case 'b':
+ c = CT_INT;
+ base = 2;
+ flags |= PFBOK; /* enable 0b prefixing */
+ break;
+
case 'D': /* compat */
flags |= LONG;
__BIONIC_FALLTHROUGH;
@@ -558,7 +562,7 @@
* digits (zero or nonzero) have been
* scanned (only signs), we will have
* base==0. In that case, we should set
- * it to 8 and enable 0x prefixing.
+ * it to 8 and enable 0b/0x prefixing.
* Also, if we have not scanned zero digits
* before this, do not turn off prefixing
* (someone else will turn it off if we
@@ -567,15 +571,24 @@
case '0':
if (base == 0) {
base = 8;
- flags |= PFXOK;
+ flags |= PFBOK | PFXOK;
}
- if (flags & NZDIGITS)
+ if (flags & NZDIGITS) {
flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
- else
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ } else {
+ flags &= ~(SIGNOK | PFBOK | PFXOK | NDIGITS);
+ }
goto ok;
-
- /* 1 through 7 always legal */
+ case 'B':
+ case 'b':
+ // Is this 'b' or 'B' potentially part of an "0b" prefix?
+ if ((flags & PFBOK) && p == buf + 1 + !!(flags & HAVESIGN)) {
+ base = 2;
+ flags &= ~PFBOK;
+ goto ok;
+ }
+ // No? Fall through and see if it's a hex digit instead then...
+ __BIONIC_FALLTHROUGH;
case '1':
case '2':
case '3':
@@ -583,34 +596,21 @@
case '5':
case '6':
case '7':
- base = basefix[base];
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
- goto ok;
-
- /* digits 8 and 9 ok iff decimal or hex */
case '8':
case '9':
- base = basefix[base];
- if (base <= 8) break; /* not legal here */
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
- goto ok;
-
- /* letters ok iff hex */
case 'A':
- case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'a':
- case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
- /* no need to fix base here */
- if (base <= 10) break; /* not legal here */
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ if (base == 0) base = 10;
+ if (base != 16 && (c - '0') >= base) break; /* not legal here */
+ flags &= ~(SIGNOK | PFBOK | PFXOK | NDIGITS);
goto ok;
/* sign ok only as first character */
@@ -653,17 +653,16 @@
break; /* EOF */
}
/*
- * If we had only a sign, it is no good; push
- * back the sign. If the number ends in `x',
- * it was [sign] '0' 'x', so push back the x
- * and treat it as [sign] '0'.
+ * If we had only a sign, it is no good; push back the sign.
+ * If the number was `[-+]0[BbXx]`, push back and treat it
+ * as `[-+]0`.
*/
if (flags & NDIGITS) {
if (p > buf) (void)ungetc(*(u_char*)--p, fp);
goto match_failure;
}
c = ((u_char*)p)[-1];
- if (c == 'x' || c == 'X') {
+ if ((base == 2 && (c == 'b' || c == 'B')) || c == 'x' || c == 'X') {
--p;
(void)ungetc(c, fp);
}
diff --git a/libc/stdio/vfwprintf.cpp b/libc/stdio/vfwprintf.cpp
index dd51eec..9819a73 100644
--- a/libc/stdio/vfwprintf.cpp
+++ b/libc/stdio/vfwprintf.cpp
@@ -81,8 +81,8 @@
char* dtoaresult = nullptr;
uintmax_t _umax; /* integer arguments %[diouxX] */
- enum { OCT, DEC, HEX } base; /* base for %[diouxX] conversion */
- int dprec; /* a copy of prec if %[diouxX], 0 otherwise */
+ enum { BIN, OCT, DEC, HEX } base; /* base for %[bBdiouxX] conversion */
+ int dprec; /* a copy of prec if %[bBdiouxX], 0 otherwise */
int realsz; /* field size expanded by dprec */
int size; /* size of converted field or string */
const char* xdigs; /* digits for %[xX] conversion */
@@ -293,6 +293,12 @@
case 'z':
flags |= SIZEINT;
goto rflag;
+ case 'B':
+ case 'b':
+ _umax = UARG();
+ base = BIN;
+ if (flags & ALT && _umax != 0) ox[1] = ch;
+ goto nosign;
case 'C':
flags |= LONGINT;
__BIONIC_FALLTHROUGH;
@@ -539,6 +545,13 @@
* a variable; hence this switch.
*/
switch (base) {
+ case BIN:
+ do {
+ *--cp = to_char(_umax & 1);
+ _umax >>= 1;
+ } while (_umax);
+ break;
+
case OCT:
do {
*--cp = to_char(_umax & 7);
@@ -588,7 +601,7 @@
* first be prefixed by any sign or other prefix; otherwise,
* it should be blank padded before the prefix is emitted.
* After any left-hand padding and prefixing, emit zeroes
- * required by a decimal %[diouxX] precision, then print the
+ * required by a decimal %[bBdiouxX] precision, then print the
* string proper, then emit zeroes required by any leftover
* floating precision; finally, if LADJUST, pad with blanks.
*
diff --git a/libc/stdio/vfwscanf.c b/libc/stdio/vfwscanf.cpp
similarity index 91%
rename from libc/stdio/vfwscanf.c
rename to libc/stdio/vfwscanf.cpp
index 71cd49b..06f706a 100644
--- a/libc/stdio/vfwscanf.c
+++ b/libc/stdio/vfwscanf.cpp
@@ -42,6 +42,8 @@
#include <wctype.h>
#include "local.h"
+#include <platform/bionic/macros.h>
+
#define BUF 513 /* Maximum length of numeric string. */
/*
@@ -65,15 +67,16 @@
* SIGNOK, HAVESIGN, NDIGITS, DPTOK, and EXPOK are for floating point;
* SIGNOK, HAVESIGN, NDIGITS, PFXOK, and NZDIGITS are for integral.
*/
-#define SIGNOK 0x01000 /* +/- is (still) legal */
+#define SIGNOK 0x01000 /* +/- is (still) legal */
#define HAVESIGN 0x02000 /* sign detected */
-#define NDIGITS 0x04000 /* no digits detected */
+#define NDIGITS 0x04000 /* no digits detected */
-#define DPTOK 0x08000 /* (float) decimal point is still legal */
-#define EXPOK 0x10000 /* (float) exponent (e+3, etc) still legal */
+#define DPTOK 0x08000 /* (float) decimal point is still legal */
+#define EXPOK 0x10000 /* (float) exponent (e+3, etc) still legal */
-#define PFXOK 0x08000 /* 0x prefix is (still) legal */
-#define NZDIGITS 0x10000 /* no zero digits detected */
+#define PFBOK 0x20000 /* 0x prefix is (still) legal */
+#define PFXOK 0x40000 /* 0x prefix is (still) legal */
+#define NZDIGITS 0x80000 /* no zero digits detected */
/*
* Conversion types.
@@ -147,9 +150,6 @@
char mbbuf[MB_LEN_MAX]; /* temporary mb. character buffer */
mbstate_t mbs;
- /* `basefix' is used to avoid `if' tests in the integer scanner */
- static short basefix[17] = { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
-
_SET_ORIENTATION(fp, 1);
nassigned = 0;
@@ -239,9 +239,15 @@
* Conversions.
* Those marked `compat' are for 4.[123]BSD compatibility.
*/
+ case 'b':
+ c = CT_INT;
+ base = 2;
+ flags |= PFBOK; /* enable 0b prefixing */
+ break;
+
case 'D': /* compat */
flags |= LONG;
- /* FALLTHROUGH */
+ __BIONIC_FALLTHROUGH;
case 'd':
c = CT_INT;
base = 10;
@@ -254,7 +260,7 @@
case 'O': /* compat */
flags |= LONG;
- /* FALLTHROUGH */
+ __BIONIC_FALLTHROUGH;
case 'o':
c = CT_INT;
flags |= UNSIGNED;
@@ -468,7 +474,7 @@
* digits (zero or nonzero) have been
* scanned (only signs), we will have
* base==0. In that case, we should set
- * it to 8 and enable 0x prefixing.
+ * it to 8 and enable 0b/0x prefixing.
* Also, if we have not scanned zero digits
* before this, do not turn off prefixing
* (someone else will turn it off if we
@@ -477,15 +483,26 @@
case '0':
if (base == 0) {
base = 8;
- flags |= PFXOK;
+ flags |= PFBOK | PFXOK;
}
- if (flags & NZDIGITS)
+ if (flags & NZDIGITS) {
flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
- else
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ } else {
+ flags &= ~(SIGNOK | PFBOK | PFXOK | NDIGITS);
+ }
goto ok;
/* 1 through 7 always legal */
+ case 'B':
+ case 'b':
+ // Is this 'b' potentially part of an "0b" prefix?
+ if ((flags & PFBOK) && p == buf + 1 + !!(flags & HAVESIGN)) {
+ base = 2;
+ flags &= ~PFBOK;
+ goto ok;
+ }
+ // No? Fall through and see if it's a hex digit instead then...
+ __BIONIC_FALLTHROUGH;
case '1':
case '2':
case '3':
@@ -493,34 +510,21 @@
case '5':
case '6':
case '7':
- base = basefix[base];
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
- goto ok;
-
- /* digits 8 and 9 ok iff decimal or hex */
case '8':
case '9':
- base = basefix[base];
- if (base <= 8) break; /* not legal here */
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
- goto ok;
-
- /* letters ok iff hex */
case 'A':
- case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'a':
- case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
- /* no need to fix base here */
- if (base <= 10) break; /* not legal here */
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ if (base == 0) base = 10;
+ if (base != 16 && (int)(c - '0') >= base) break; /* not legal here */
+ flags &= ~(SIGNOK | PFBOK | PFXOK | NDIGITS);
goto ok;
/* sign ok only as first character */
@@ -560,17 +564,16 @@
*p++ = (wchar_t)c;
}
/*
- * If we had only a sign, it is no good; push
- * back the sign. If the number ends in `x',
- * it was [sign] '0' 'x', so push back the x
- * and treat it as [sign] '0'.
+ * If we had only a sign, it is no good; push back the sign.
+ * If the number was `[-+]0[BbXx]`, push back and treat it
+ * as `[-+]0`.
*/
if (flags & NDIGITS) {
if (p > buf) __ungetwc(*--p, fp);
goto match_failure;
}
c = p[-1];
- if (c == 'x' || c == 'X') {
+ if ((base == 2 && (c == 'b' || c == 'B')) || c == 'x' || c == 'X') {
--p;
__ungetwc(c, fp);
}
diff --git a/libc/tools/Android.bp b/libc/tools/Android.bp
index 116b853..c7fce64 100644
--- a/libc/tools/Android.bp
+++ b/libc/tools/Android.bp
@@ -8,8 +8,8 @@
default_applicable_licenses: ["bionic_libc_license"],
}
-filegroup {
- name: "bionic-gensyscalls",
+python_binary_host {
+ name: "gensyscalls",
srcs: ["gensyscalls.py"],
}
diff --git a/libc/tools/genfunctosyscallnrs.py b/libc/tools/genfunctosyscallnrs.py
index fa48844..9b8f7ee 100755
--- a/libc/tools/genfunctosyscallnrs.py
+++ b/libc/tools/genfunctosyscallnrs.py
@@ -21,12 +21,12 @@
def gen_syscall_nrs(out_file, base_syscall_file, syscall_NRs):
- for arch in SupportedArchitectures:
+ for arch in syscall_NRs.keys():
base_names = load_syscall_names_from_file(base_syscall_file, arch)
for func, syscall in base_names.items():
out_file.write("#define __" + arch + "_" + func + " " +
- str(syscall_NRs[arch][syscall]) + ";\n")
+ str(syscall_NRs[arch][syscall]) + "\n")
def main():
diff --git a/libc/tools/genseccomp.py b/libc/tools/genseccomp.py
index 33bf470..8a07caf 100755
--- a/libc/tools/genseccomp.py
+++ b/libc/tools/genseccomp.py
@@ -5,9 +5,10 @@
import operator
import os
import re
+import sys
import textwrap
-from gensyscalls import SupportedArchitectures, SysCallsTxtParser
+from gensyscalls import SysCallsTxtParser
BPF_JGE = "BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, {0}, {1}, {2})"
@@ -84,42 +85,46 @@
# #define __(ARM_)?NR_${NAME} ${VALUE}
#
# Where ${VALUE} is a preprocessor expression.
+ #
+ # Newer architectures have things like this though:
+ #
+ # #define __NR3264_fcntl 25
+ # #define __NR_fcntl __NR3264_fcntl
+ #
+ # So we need to keep track of the __NR3264_* constants and substitute them.
- constant_re = re.compile(
- r'^\s*#define\s+([A-Za-z_][A-Za-z0-9_]+)\s+(.+)\s*$')
+ line_re = re.compile(r'^# \d+ ".*".*')
+ undef_re = re.compile(r'^#undef\s.*')
+ define_re = re.compile(r'^\s*#define\s+([A-Za-z0-9_(,)]+)(?:\s+(.+))?\s*$')
token_re = re.compile(r'\b[A-Za-z_][A-Za-z0-9_]+\b')
constants = {}
+ nr3264s = {}
with open(names_path) as f:
for line in f:
- m = constant_re.match(line)
- if m is None:
- continue
- try:
+ line = line.strip()
+ m = define_re.match(line)
+ if m:
name = m.group(1)
- # eval() takes care of any arithmetic that may be done
- value = eval(token_re.sub(lambda x: str(constants[x.group(0)]),
- m.group(2)))
+ value = m.group(2)
+ if name.startswith('__NR3264'):
+ nr3264s[name] = value
+ elif name.startswith('__NR_') or name.startswith('__ARM_NR_'):
+ if value in nr3264s:
+ value = nr3264s[value]
+ # eval() takes care of any arithmetic that may be done
+ value = eval(token_re.sub(lambda x: str(constants[x.group(0)]), value))
- constants[name] = value
- except: # pylint: disable=bare-except
- # TODO: This seems wrong.
- # Key error doesn't seem like the error the original author was trying
- # to catch. It looks like the intent was to catch IndexError from
- # match.group() for non-matching lines, but that's impossible because
- # the match object is checked and continued if not matched. What
- # actually happens is that KeyError is thrown by constants[x.group(0)]
- # on at least the first run because the dict is empty.
- #
- # It's also matching syntax errors because not all C integer literals
- # are valid Python integer literals, e.g. 10L.
- logging.debug('Failed to parse %s', line)
+ constants[name] = value
+ else:
+ if not line_re.match(line) and not undef_re.match(line) and line:
+ print('%s: failed to parse line `%s`' % (names_path, line))
+ sys.exit(1)
syscalls = {}
for name, value in constants.items():
- if not name.startswith("__NR_") and not name.startswith("__ARM_NR"):
- continue
+ # Remove the __NR_ prefix.
+ # TODO: why not __ARM_NR too?
if name.startswith("__NR_"):
- # Remote the __NR_ prefix
name = name[len("__NR_"):]
syscalls[name] = value
@@ -237,7 +242,7 @@
def gen_policy(name_modifier, out_dir, base_syscall_file, syscall_files,
syscall_NRs, priority_file):
- for arch in SupportedArchitectures:
+ for arch in syscall_NRs.keys():
base_names = load_syscall_names_from_file(base_syscall_file, arch)
allowlist_names = set()
blocklist_names = set()
@@ -251,11 +256,11 @@
priorities = load_syscall_priorities_from_file(priority_file)
allowed_syscalls = []
- for name in merge_names(base_names, allowlist_names, blocklist_names):
+ for name in sorted(merge_names(base_names, allowlist_names, blocklist_names)):
try:
allowed_syscalls.append((name, syscall_NRs[arch][name]))
except:
- logging.exception("Failed to find %s in %s", name, arch)
+ logging.exception("Failed to find %s in %s (%s)", name, arch, syscall_NRs[arch])
raise
output = construct_bpf(allowed_syscalls, arch, name_modifier, priorities)
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index baaa52d..d3e6ef4 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -15,7 +15,7 @@
import tempfile
-SupportedArchitectures = [ "arm", "arm64", "x86", "x86_64" ]
+SupportedArchitectures = [ "arm", "arm64", "riscv64", "x86", "x86_64" ]
syscall_stub_header = \
"""
@@ -80,6 +80,24 @@
#
+# RISC-V64 assembler templates for each syscall stub
+#
+
+riscv64_call = syscall_stub_header + """\
+ li a7, %(__NR_name)s
+ ecall
+
+ li a7, -MAX_ERRNO
+ bgtu a0, a7, 1f
+
+ ret
+1:
+ neg a0, a0
+ j __set_errno_internal
+END(%(func)s)
+"""
+
+#
# x86 assembler templates for each syscall stub
#
@@ -228,6 +246,10 @@
return arm64_call % syscall
+def riscv64_genstub(syscall):
+ return riscv64_call % syscall
+
+
def x86_genstub(syscall):
result = syscall_stub_header % syscall
@@ -440,6 +462,9 @@
if "arm64" in syscall:
syscall["asm-arm64"] = add_footer(64, arm64_genstub(syscall), syscall)
+ if "riscv64" in syscall:
+ syscall["asm-riscv64"] = add_footer(64, riscv64_genstub(syscall), syscall)
+
if "x86" in syscall:
if syscall["socketcall_id"] >= 0:
syscall["asm-x86"] = add_footer(32, x86_genstub_socketcall(syscall), syscall)
diff --git a/libc/tzcode/asctime.c b/libc/tzcode/asctime.c
index 337a313..ce5d4be 100644
--- a/libc/tzcode/asctime.c
+++ b/libc/tzcode/asctime.c
@@ -1,3 +1,5 @@
+/* asctime and asctime_r a la POSIX and ISO C, except pad years before 1000. */
+
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
@@ -12,7 +14,7 @@
/*LINTLIBRARY*/
#include "private.h"
-#include "tzfile.h"
+#include <stdio.h>
/*
** Some systems only handle "%.2d"; others only handle "%02d";
@@ -29,13 +31,13 @@
** leading zeroes to get the newline in the traditional place.
** The -4 ensures that we get four characters of output even if
** we call a strftime variant that produces fewer characters for some years.
-** The ISO C 1999 and POSIX 1003.1-2004 standards prohibit padding the year,
+** The ISO C and POSIX standards prohibit padding the year,
** but many implementations pad anyway; most likely the standards are buggy.
*/
#ifdef __GNUC__
-#define ASCTIME_FMT "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %-4s\n"
+#define ASCTIME_FMT "%s %s%3d %2.2d:%2.2d:%2.2d %-4s\n"
#else /* !defined __GNUC__ */
-#define ASCTIME_FMT "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4s\n"
+#define ASCTIME_FMT "%s %s%3d %02.2d:%02.2d:%02.2d %-4s\n"
#endif /* !defined __GNUC__ */
/*
** For years that are more than four digits we put extra spaces before the year
@@ -44,9 +46,9 @@
** that no output is better than wrong output).
*/
#ifdef __GNUC__
-#define ASCTIME_FMT_B "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %s\n"
+#define ASCTIME_FMT_B "%s %s%3d %2.2d:%2.2d:%2.2d %s\n"
#else /* !defined __GNUC__ */
-#define ASCTIME_FMT_B "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %s\n"
+#define ASCTIME_FMT_B "%s %s%3d %02.2d:%02.2d:%02.2d %s\n"
#endif /* !defined __GNUC__ */
#define STD_ASCTIME_BUF_SIZE 26
@@ -64,17 +66,13 @@
static char buf_asctime[MAX_ASCTIME_BUF_SIZE];
-/*
-** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
-*/
-
char *
asctime_r(register const struct tm *timeptr, char *buf)
{
- static const char wday_name[][3] = {
+ static const char wday_name[][4] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
- static const char mon_name[][3] = {
+ static const char mon_name[][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
@@ -117,10 +115,6 @@
}
}
-/*
-** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
-*/
-
char *
asctime(register const struct tm *timeptr)
{
diff --git a/libc/tzcode/bionic.cpp b/libc/tzcode/bionic.cpp
index e134aaa..d2b5d80 100644
--- a/libc/tzcode/bionic.cpp
+++ b/libc/tzcode/bionic.cpp
@@ -190,6 +190,18 @@
// Give up now, and don't try fallback tzdata files. We don't log here
// because for all we know the given olson id was nonsense.
close(fd);
+ // This file descriptor (-1) is passed to localtime.c. In invalid fd case
+ // upstream passes errno value around methods and having 0 there will
+ // indicate that time zone was found and read successfully and localtime's
+ // internal state was properly initialized (which wasn't as we couldn't find
+ // requested time zone in the tzdata file).
+ // If we reached this point errno is unlikely to be touched. It is only
+ // close(fd) which can do it, but that is very unlikely to happen. And
+ // even if it happens we can't extract any useful insights from it.
+ // We are overriding it to ENOENT as it matches upstream expectations -
+ // time zone is absent in the tzdata file == there is no TZif file in
+ // /usr/share/zoneinfo.
+ errno = ENOENT;
return -1;
}
@@ -206,24 +218,14 @@
int __bionic_open_tzdata(const char* olson_id, int32_t* entry_length) {
int fd;
- // Try the three locations for the tzdata file in a strict order:
- // 1: The O-MR1 time zone updates via APK update mechanism. This is
- // tried first because it allows us to test that the time zone updates
- // via APK mechanism still works even on devices with the time zone
- // module.
- // TODO: remove this when those devices are no longer supported.
- // 2: The time zone data module which contains the main copy. This is the
+ // Try the two locations for the tzdata file in a strict order:
+ // 1: The time zone data module which contains the main copy. This is the
// common case for current devices.
- // 3: The ultimate fallback: the non-updatable copy in /system.
+ // 2: The ultimate fallback: the non-updatable copy in /system.
#if defined(__ANDROID__)
// On Android devices, bionic has to work even if exec takes place without
// environment variables set. So, all paths are hardcoded here.
-
- fd = __bionic_open_tzdata_path("/data/misc/zoneinfo/current/tzdata",
- olson_id, entry_length);
- if (fd >= -1) return fd;
-
fd = __bionic_open_tzdata_path("/apex/com.android.tzdata/etc/tz/tzdata",
olson_id, entry_length);
if (fd >= -1) return fd;
@@ -233,16 +235,10 @@
if (fd >= -1) return fd;
#else
// On the host, we don't expect the hard-coded locations above to exist, and
- // we're not worried about security so we trust $ANDROID_DATA,
- // $ANDROID_TZDATA_ROOT, and $ANDROID_ROOT to point us in the right direction
- // instead.
+ // we're not worried about security so we trust $ANDROID_TZDATA_ROOT, and
+ // $ANDROID_ROOT to point us in the right direction instead.
- char* path = make_path("ANDROID_DATA", "/misc/zoneinfo/current/tzdata");
- fd = __bionic_open_tzdata_path(path, olson_id, entry_length);
- free(path);
- if (fd >= -1) return fd;
-
- path = make_path("ANDROID_TZDATA_ROOT", "/etc/tz/tzdata");
+ char* path = make_path("ANDROID_TZDATA_ROOT", "/etc/tz/tzdata");
fd = __bionic_open_tzdata_path(path, olson_id, entry_length);
free(path);
if (fd >= -1) return fd;
diff --git a/libc/tzcode/difftime.c b/libc/tzcode/difftime.c
index ba2fd03..ff78f03 100644
--- a/libc/tzcode/difftime.c
+++ b/libc/tzcode/difftime.c
@@ -1,3 +1,5 @@
+/* Return the difference between two timestamps. */
+
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
@@ -14,14 +16,14 @@
return -x;
}
-double ATTRIBUTE_CONST
+double
difftime(time_t time1, time_t time0)
{
/*
** If double is large enough, simply convert and subtract
** (assuming that the larger type has more precision).
*/
- if (sizeof (time_t) < sizeof (double)) {
+ if (sizeof(time_t) < sizeof(double)) {
double t1 = time1, t0 = time0;
return t1 - t0;
}
@@ -34,7 +36,7 @@
return time0 <= time1 ? time1 - time0 : dminus(time0 - time1);
/* Use uintmax_t if wide enough. */
- if (sizeof (time_t) <= sizeof (uintmax_t)) {
+ if (sizeof(time_t) <= sizeof(uintmax_t)) {
uintmax_t t1 = time1, t0 = time0;
return time0 <= time1 ? t1 - t0 : dminus(t0 - t1);
}
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 091bab0..8ff5cee 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -1,3 +1,5 @@
+/* Convert timestamp from time_t to struct tm. */
+
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
@@ -14,9 +16,9 @@
#include "private.h"
#include "tzfile.h"
-#include "fcntl.h"
+#include <fcntl.h>
-#if THREAD_SAFE
+#if defined THREAD_SAFE && THREAD_SAFE
# include <pthread.h>
static pthread_mutex_t locallock = PTHREAD_MUTEX_INITIALIZER;
static int lock(void) { return pthread_mutex_lock(&locallock); }
@@ -26,14 +28,6 @@
static void unlock(void) { }
#endif
-/* NETBSD_INSPIRED_EXTERN functions are exported to callers if
- NETBSD_INSPIRED is defined, and are private otherwise. */
-#if NETBSD_INSPIRED
-# define NETBSD_INSPIRED_EXTERN
-#else
-# define NETBSD_INSPIRED_EXTERN static
-#endif
-
#ifndef TZ_ABBR_MAX_LEN
#define TZ_ABBR_MAX_LEN 16
#endif /* !defined TZ_ABBR_MAX_LEN */
@@ -87,31 +81,39 @@
/*
** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
-** We default to US rules as of 1999-08-17.
-** POSIX 1003.1 section 8.1.1 says that the default DST rules are
-** implementation dependent; for historical reasons, US rules are a
-** common default.
+** Default to US rules as of 2017-05-07.
+** POSIX does not specify the default DST rules;
+** for historical reasons, US rules are a common default.
*/
#ifndef TZDEFRULESTRING
-#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
-#endif /* !defined TZDEFDST */
+#define TZDEFRULESTRING ",M3.2.0,M11.1.0"
+#endif
struct ttinfo { /* time type information */
- int_fast32_t tt_gmtoff; /* UT offset in seconds */
+ int_fast32_t tt_utoff; /* UT offset in seconds */
bool tt_isdst; /* used to set tm_isdst */
- int tt_abbrind; /* abbreviation list index */
+ int tt_desigidx; /* abbreviation list index */
bool tt_ttisstd; /* transition is std time */
- bool tt_ttisgmt; /* transition is UT */
+ bool tt_ttisut; /* transition is UT */
};
struct lsinfo { /* leap second information */
time_t ls_trans; /* transition time */
- int_fast64_t ls_corr; /* correction to apply */
+ int_fast32_t ls_corr; /* correction to apply */
};
#define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
+/* This abbreviation means local time is unspecified. */
+static char const UNSPEC[] = "-00";
+
+/* How many extra bytes are needed at the end of struct state's chars array.
+ This needs to be at least 1 for null termination in case the input
+ data isn't properly terminated, and it also needs to be big enough
+ for ttunspecified to work without crashing. */
+enum { CHARS_EXTRA = BIGGEST(sizeof UNSPEC, 2) - 1 };
+
#ifdef TZNAME_MAX
#define MY_TZNAME_MAX TZNAME_MAX
#endif /* defined TZNAME_MAX */
@@ -129,10 +131,14 @@
time_t ats[TZ_MAX_TIMES];
unsigned char types[TZ_MAX_TIMES];
struct ttinfo ttis[TZ_MAX_TYPES];
- char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
+ char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + CHARS_EXTRA,
+ sizeof gmt),
(2 * (MY_TZNAME_MAX + 1)))];
struct lsinfo lsis[TZ_MAX_LEAPS];
- int defaulttype; /* for early times or if no transitions */
+ /* The time type to use for early times or if no transitions.
+ It is always zero for recent tzdb releases.
+ It might be nonzero for data from tzdb 2018e or earlier. */
+ int defaulttype;
};
enum r_type {
@@ -153,11 +159,12 @@
struct tm *);
static bool increment_overflow(int *, int);
static bool increment_overflow_time(time_t *, int_fast32_t);
+static int_fast32_t leapcorr(struct state const *, time_t);
static bool normalize_overflow32(int_fast32_t *, int *, int);
static struct tm *timesub(time_t const *, int_fast32_t, struct state const *,
struct tm *);
static bool typesequiv(struct state const *, int, int);
-static bool tzparse(char const *, struct state *, bool);
+static bool tzparse(char const *, struct state *, struct state *);
#ifdef ALL_STATE
static struct state * lclptr;
@@ -188,30 +195,39 @@
static struct tm tm;
-#if !HAVE_POSIX_DECLS
+#if 2 <= HAVE_TZNAME + TZ_TIME_T
char * tzname[2] = {
(char *) wildabbr,
(char *) wildabbr
};
-#ifdef USG_COMPAT
+#endif
+#if 2 <= USG_COMPAT + TZ_TIME_T
long timezone;
int daylight;
-# endif
#endif
-#ifdef ALTZONE
+#if 2 <= ALTZONE + TZ_TIME_T
long altzone;
-#endif /* defined ALTZONE */
+#endif
-/* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND. */
+/* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX. */
static void
-init_ttinfo(struct ttinfo *s, int_fast32_t gmtoff, bool isdst, int abbrind)
+init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx)
{
- s->tt_gmtoff = gmtoff;
+ s->tt_utoff = utoff;
s->tt_isdst = isdst;
- s->tt_abbrind = abbrind;
+ s->tt_desigidx = desigidx;
s->tt_ttisstd = false;
- s->tt_ttisgmt = false;
+ s->tt_ttisut = false;
+}
+
+/* Return true if SP's time type I does not specify local time. */
+static bool
+ttunspecified(struct state const *sp, int i)
+{
+ char const *abbr = &sp->chars[sp->ttis[i].tt_desigidx];
+ /* memcmp is likely faster than strcmp, and is safe due to CHARS_EXTRA. */
+ return memcmp(abbr, UNSPEC, sizeof UNSPEC) == 0;
}
static int_fast32_t
@@ -240,7 +256,7 @@
static int_fast64_t
detzcode64(const char *const codep)
{
- register uint_fast64_t result;
+ register int_fast64_t result;
register int i;
int_fast64_t one = 1;
int_fast64_t halfmaxval = one << (64 - 2);
@@ -263,52 +279,71 @@
static void
update_tzname_etc(struct state const *sp, struct ttinfo const *ttisp)
{
- tzname[ttisp->tt_isdst] = (char *) &sp->chars[ttisp->tt_abbrind];
-#ifdef USG_COMPAT
+#if HAVE_TZNAME
+ tzname[ttisp->tt_isdst] = (char *) &sp->chars[ttisp->tt_desigidx];
+#endif
+#if USG_COMPAT
if (!ttisp->tt_isdst)
- timezone = - ttisp->tt_gmtoff;
+ timezone = - ttisp->tt_utoff;
#endif
-#ifdef ALTZONE
+#if ALTZONE
if (ttisp->tt_isdst)
- altzone = - ttisp->tt_gmtoff;
+ altzone = - ttisp->tt_utoff;
#endif
}
+/* If STDDST_MASK indicates that SP's TYPE provides useful info,
+ update tzname, timezone, and/or altzone and return STDDST_MASK,
+ diminished by the provided info if it is a specified local time.
+ Otherwise, return STDDST_MASK. See settzname for STDDST_MASK. */
+static int
+may_update_tzname_etc(int stddst_mask, struct state *sp, int type)
+{
+ struct ttinfo *ttisp = &sp->ttis[type];
+ int this_bit = 1 << ttisp->tt_isdst;
+ if (stddst_mask & this_bit) {
+ update_tzname_etc(sp, ttisp);
+ if (!ttunspecified(sp, type))
+ return stddst_mask & ~this_bit;
+ }
+ return stddst_mask;
+}
+
static void
settzname(void)
{
register struct state * const sp = lclptr;
register int i;
- tzname[0] = tzname[1] = (char *) wildabbr;
-#ifdef USG_COMPAT
- daylight = 0;
+ /* If STDDST_MASK & 1 we need info about a standard time.
+ If STDDST_MASK & 2 we need info about a daylight saving time.
+ When STDDST_MASK becomes zero we can stop looking. */
+ int stddst_mask = 0;
+
+#if HAVE_TZNAME
+ tzname[0] = tzname[1] = (char *) (sp ? wildabbr : gmt);
+ stddst_mask = 3;
+#endif
+#if USG_COMPAT
timezone = 0;
-#endif /* defined USG_COMPAT */
-#ifdef ALTZONE
+ stddst_mask = 3;
+#endif
+#if ALTZONE
altzone = 0;
-#endif /* defined ALTZONE */
- if (sp == NULL) {
- tzname[0] = tzname[1] = (char *) gmt;
- return;
- }
+ stddst_mask |= 2;
+#endif
/*
- ** And to get the latest zone names into tzname. . .
+ ** And to get the latest time zone abbreviations into tzname. . .
*/
- for (i = 0; i < sp->typecnt; ++i) {
- register const struct ttinfo * const ttisp = &sp->ttis[i];
- update_tzname_etc(sp, ttisp);
+ if (sp) {
+ for (i = sp->timecnt - 1; stddst_mask && 0 <= i; i--)
+ stddst_mask = may_update_tzname_etc(stddst_mask, sp, sp->types[i]);
+ for (i = sp->typecnt - 1; stddst_mask && 0 <= i; i--)
+ stddst_mask = may_update_tzname_etc(stddst_mask, sp, i);
}
- for (i = 0; i < sp->timecnt; ++i) {
- register const struct ttinfo * const ttisp =
- &sp->ttis[
- sp->types[i]];
- update_tzname_etc(sp, ttisp);
-#ifdef USG_COMPAT
- if (ttisp->tt_isdst)
- daylight = 1;
-#endif /* defined USG_COMPAT */
- }
+#if USG_COMPAT
+ daylight = stddst_mask >> 1 ^ 1;
+#endif
}
static void
@@ -326,7 +361,7 @@
*/
for (i = 0; i < sp->typecnt; ++i) {
register const struct ttinfo * const ttisp = &sp->ttis[i];
- register char * cp = &sp->chars[ttisp->tt_abbrind];
+ char *cp = &sp->chars[ttisp->tt_desigidx];
if (strlen(cp) > TZ_ABBR_MAX_LEN &&
strcmp(cp, GRANDPARENTED) != 0)
@@ -334,39 +369,39 @@
}
}
-static bool
-differ_by_repeat(const time_t t1, const time_t t0)
-{
- if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
- return 0;
-#if defined(__LP64__) // 32-bit Android/glibc has a signed 32-bit time_t; 64-bit doesn't.
- return t1 - t0 == SECSPERREPEAT;
-#endif
-}
-
/* Input buffer for data read from a compiled tz file. */
union input_buffer {
/* The first part of the buffer, interpreted as a header. */
struct tzhead tzhead;
/* The entire buffer. */
- char buf[2 * sizeof(struct tzhead) + 2 * sizeof (struct state)
- + 4 * TZ_MAX_TIMES];
+ char buf[2 * sizeof(struct tzhead) + 2 * sizeof(struct state)
+ + 4 * TZ_MAX_TIMES];
};
+// Android-removed: There is no directory with file-per-time zone on Android.
+#ifndef __BIONIC__
+/* TZDIR with a trailing '/' rather than a trailing '\0'. */
+static char const tzdirslash[sizeof TZDIR] = TZDIR "/";
+#endif
+
/* Local storage needed for 'tzloadbody'. */
union local_storage {
- /* The file name to be opened. */
- char fullname[FILENAME_MAX + 1];
-
/* The results of analyzing the file's contents after it is opened. */
- struct {
+ struct file_analysis {
/* The input buffer. */
union input_buffer u;
/* A temporary state used for parsing a TZ string in the file. */
struct state st;
} u;
+
+ // Android-removed: There is no directory with file-per-time zone on Android.
+ #ifndef __BIONIC__
+ /* The file name to be opened. */
+ char fullname[BIGGEST(sizeof(struct file_analysis),
+ sizeof tzdirslash + 1024)];
+ #endif
};
/* Load tz data from the file named NAME into *SP. Read extended
@@ -385,7 +420,7 @@
register char *fullname = lsp->fullname;
#endif
register union input_buffer *up = &lsp->u.u;
- register int tzheadsize = sizeof (struct tzhead);
+ register int tzheadsize = sizeof(struct tzhead);
sp->goback = sp->goahead = false;
@@ -402,20 +437,36 @@
#else
if (name[0] == ':')
++name;
+#ifdef SUPPRESS_TZDIR
+ /* Do not prepend TZDIR. This is intended for specialized
+ applications only, due to its security implications. */
+ doaccess = true;
+#else
doaccess = name[0] == '/';
+#endif
if (!doaccess) {
- char const *p = TZDIR;
- if (! p)
- return EINVAL;
- if (sizeof lsp->fullname - 1 <= strlen(p) + strlen(name))
+ char const *dot;
+ size_t namelen = strlen(name);
+ if (sizeof lsp->fullname - sizeof tzdirslash <= namelen)
return ENAMETOOLONG;
- strcpy(fullname, p);
- strcat(fullname, "/");
- strcat(fullname, name);
- /* Set doaccess if '.' (as in "../") shows up in name. */
- if (strchr(name, '.'))
- doaccess = true;
- name = fullname;
+
+ /* Create a string "TZDIR/NAME". Using sprintf here
+ would pull in stdio (and would fail if the
+ resulting string length exceeded INT_MAX!). */
+ memcpy(lsp->fullname, tzdirslash, sizeof tzdirslash);
+ strcpy(lsp->fullname + sizeof tzdirslash, name);
+
+ /* Set doaccess if NAME contains a ".." file name
+ component, as such a name could read a file outside
+ the TZDIR virtual subtree. */
+ for (dot = name; (dot = strchr(dot, '.')); dot++)
+ if ((dot == name || dot[-1] == '/') && dot[1] == '.'
+ && (dot[2] == '/' || !dot[2])) {
+ doaccess = true;
+ break;
+ }
+
+ name = lsp->fullname;
}
if (doaccess && access(name, R_OK) != 0)
return errno;
@@ -437,47 +488,62 @@
if (close(fid) < 0)
return errno;
for (stored = 4; stored <= 8; stored *= 2) {
- int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
- int_fast32_t ttisgmtcnt = detzcode(up->tzhead.tzh_ttisgmtcnt);
- int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
- int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
- int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
- int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
- char const *p = up->buf + tzheadsize;
- if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
- && 0 < typecnt && typecnt < TZ_MAX_TYPES
- && 0 <= timecnt && timecnt < TZ_MAX_TIMES
- && 0 <= charcnt && charcnt < TZ_MAX_CHARS
- && (ttisstdcnt == typecnt || ttisstdcnt == 0)
- && (ttisgmtcnt == typecnt || ttisgmtcnt == 0)))
- return EINVAL;
- if (nread
- < (tzheadsize /* struct tzhead */
- + timecnt * stored /* ats */
+ char version = up->tzhead.tzh_version[0];
+ bool skip_datablock = stored == 4 && version;
+ int_fast32_t datablock_size;
+ int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
+ int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
+ int_fast64_t prevtr = -1;
+ int_fast32_t prevcorr;
+ int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
+ int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
+ int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
+ int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
+ char const *p = up->buf + tzheadsize;
+ /* Although tzfile(5) currently requires typecnt to be nonzero,
+ support future formats that may allow zero typecnt
+ in files that have a TZ string and no transitions. */
+ if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
+ && 0 <= typecnt && typecnt < TZ_MAX_TYPES
+ && 0 <= timecnt && timecnt < TZ_MAX_TIMES
+ && 0 <= charcnt && charcnt < TZ_MAX_CHARS
+ && 0 <= ttisstdcnt && ttisstdcnt < TZ_MAX_TYPES
+ && 0 <= ttisutcnt && ttisutcnt < TZ_MAX_TYPES))
+ return EINVAL;
+ datablock_size
+ = (timecnt * stored /* ats */
+ timecnt /* types */
+ typecnt * 6 /* ttinfos */
+ charcnt /* chars */
+ leapcnt * (stored + 4) /* lsinfos */
+ ttisstdcnt /* ttisstds */
- + ttisgmtcnt)) /* ttisgmts */
+ + ttisutcnt); /* ttisuts */
+ if (nread < tzheadsize + datablock_size)
+ return EINVAL;
+ if (skip_datablock)
+ p += datablock_size;
+ else {
+ if (! ((ttisstdcnt == typecnt || ttisstdcnt == 0)
+ && (ttisutcnt == typecnt || ttisutcnt == 0)))
return EINVAL;
+
sp->leapcnt = leapcnt;
sp->timecnt = timecnt;
sp->typecnt = typecnt;
sp->charcnt = charcnt;
/* Read transitions, discarding those out of time_t range.
- But pretend the last transition before time_t_min
- occurred at time_t_min. */
+ But pretend the last transition before TIME_T_MIN
+ occurred at TIME_T_MIN. */
timecnt = 0;
for (i = 0; i < sp->timecnt; ++i) {
int_fast64_t at
= stored == 4 ? detzcode(p) : detzcode64(p);
- sp->types[i] = at <= time_t_max;
+ sp->types[i] = at <= TIME_T_MAX;
if (sp->types[i]) {
time_t attime
- = ((TYPE_SIGNED(time_t) ? at < time_t_min : at < 0)
- ? time_t_min : at);
+ = ((TYPE_SIGNED(time_t) ? at < TIME_T_MIN : at < 0)
+ ? TIME_T_MIN : at);
if (timecnt && attime <= sp->ats[timecnt - 1]) {
if (attime < sp->ats[timecnt - 1])
return EINVAL;
@@ -500,23 +566,25 @@
sp->timecnt = timecnt;
for (i = 0; i < sp->typecnt; ++i) {
register struct ttinfo * ttisp;
- unsigned char isdst, abbrind;
+ unsigned char isdst, desigidx;
ttisp = &sp->ttis[i];
- ttisp->tt_gmtoff = detzcode(p);
+ ttisp->tt_utoff = detzcode(p);
p += 4;
isdst = *p++;
if (! (isdst < 2))
return EINVAL;
ttisp->tt_isdst = isdst;
- abbrind = *p++;
- if (! (abbrind < sp->charcnt))
+ desigidx = *p++;
+ if (! (desigidx < sp->charcnt))
return EINVAL;
- ttisp->tt_abbrind = abbrind;
+ ttisp->tt_desigidx = desigidx;
}
for (i = 0; i < sp->charcnt; ++i)
sp->chars[i] = *p++;
- sp->chars[i] = '\0'; /* ensure '\0' at end */
+ /* Ensure '\0'-terminated, and make it safe to call
+ ttunspecified later. */
+ memset(&sp->chars[i], 0, CHARS_EXTRA);
/* Read leap seconds, discarding those out of time_t range. */
leapcnt = 0;
@@ -524,16 +592,28 @@
int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p);
int_fast32_t corr = detzcode(p + stored);
p += stored + 4;
- if (tr <= time_t_max) {
- time_t trans
- = ((TYPE_SIGNED(time_t) ? tr < time_t_min : tr < 0)
- ? time_t_min : tr);
- if (leapcnt && trans <= sp->lsis[leapcnt - 1].ls_trans) {
- if (trans < sp->lsis[leapcnt - 1].ls_trans)
- return EINVAL;
- leapcnt--;
- }
- sp->lsis[leapcnt].ls_trans = trans;
+
+ /* Leap seconds cannot occur before the Epoch,
+ or out of order. */
+ if (tr <= prevtr)
+ return EINVAL;
+
+ /* To avoid other botches in this code, each leap second's
+ correction must differ from the previous one's by 1
+ second or less, except that the first correction can be
+ any value; these requirements are more generous than
+ RFC 8536, to allow future RFC extensions. */
+ if (! (i == 0
+ || (prevcorr < corr
+ ? corr == prevcorr + 1
+ : (corr == prevcorr
+ || corr == prevcorr - 1))))
+ return EINVAL;
+ prevtr = tr;
+ prevcorr = corr;
+
+ if (tr <= TIME_T_MAX) {
+ sp->lsis[leapcnt].ls_trans = tr;
sp->lsis[leapcnt].ls_corr = corr;
leapcnt++;
}
@@ -556,21 +636,22 @@
register struct ttinfo * ttisp;
ttisp = &sp->ttis[i];
- if (ttisgmtcnt == 0)
- ttisp->tt_ttisgmt = false;
+ if (ttisutcnt == 0)
+ ttisp->tt_ttisut = false;
else {
if (*p != true && *p != false)
return EINVAL;
- ttisp->tt_ttisgmt = *p++;
+ ttisp->tt_ttisut = *p++;
}
}
- /*
- ** If this is an old file, we're done.
- */
- if (up->tzhead.tzh_version[0] == '\0')
- break;
- nread -= p - up->buf;
- memmove(up->buf, p, nread);
+ }
+
+ nread -= p - up->buf;
+ memmove(up->buf, p, nread);
+
+ /* If this is an old file, we're done. */
+ if (!version)
+ break;
}
if (doextend && nread > 2 &&
up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
@@ -578,24 +659,23 @@
struct state *ts = &lsp->u.st;
up->buf[nread - 1] = '\0';
- if (tzparse(&up->buf[1], ts, false)
- && ts->typecnt == 2) {
+ if (tzparse(&up->buf[1], ts, sp)) {
/* Attempt to reuse existing abbreviations.
- Without this, America/Anchorage would stop
- working after 2037 when TZ_MAX_CHARS is 50, as
- sp->charcnt equals 42 (for LMT CAT CAWT CAPT AHST
+ Without this, America/Anchorage would be right on
+ the edge after 2037 when TZ_MAX_CHARS is 50, as
+ sp->charcnt equals 40 (for LMT AST AWT APT AHST
AHDT YST AKDT AKST) and ts->charcnt equals 10
(for AKST AKDT). Reusing means sp->charcnt can
- stay 42 in this example. */
+ stay 40 in this example. */
int gotabbr = 0;
int charcnt = sp->charcnt;
- for (i = 0; i < 2; i++) {
- char *tsabbr = ts->chars + ts->ttis[i].tt_abbrind;
+ for (i = 0; i < ts->typecnt; i++) {
+ char *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
int j;
for (j = 0; j < charcnt; j++)
if (strcmp(sp->chars + j, tsabbr) == 0) {
- ts->ttis[i].tt_abbrind = j;
+ ts->ttis[i].tt_desigidx = j;
gotabbr++;
break;
}
@@ -604,53 +684,83 @@
if (j + tsabbrlen < TZ_MAX_CHARS) {
strcpy(sp->chars + j, tsabbr);
charcnt = j + tsabbrlen + 1;
- ts->ttis[i].tt_abbrind = j;
+ ts->ttis[i].tt_desigidx = j;
gotabbr++;
}
}
}
- if (gotabbr == 2) {
+ if (gotabbr == ts->typecnt) {
sp->charcnt = charcnt;
- for (i = 0; i < ts->timecnt; i++)
- if (sp->ats[sp->timecnt - 1] < ts->ats[i])
- break;
- while (i < ts->timecnt
- && sp->timecnt < TZ_MAX_TIMES) {
- sp->ats[sp->timecnt] = ts->ats[i];
+
+ /* Ignore any trailing, no-op transitions generated
+ by zic as they don't help here and can run afoul
+ of bugs in zic 2016j or earlier. */
+ while (1 < sp->timecnt
+ && (sp->types[sp->timecnt - 1]
+ == sp->types[sp->timecnt - 2]))
+ sp->timecnt--;
+
+ for (i = 0;
+ i < ts->timecnt && sp->timecnt < TZ_MAX_TIMES;
+ i++) {
+ time_t t = ts->ats[i];
+ if (increment_overflow_time(&t, leapcorr(sp, t))
+ || (0 < sp->timecnt
+ && t <= sp->ats[sp->timecnt - 1]))
+ continue;
+ sp->ats[sp->timecnt] = t;
sp->types[sp->timecnt] = (sp->typecnt
+ ts->types[i]);
sp->timecnt++;
- i++;
}
- sp->ttis[sp->typecnt++] = ts->ttis[0];
- sp->ttis[sp->typecnt++] = ts->ttis[1];
+ for (i = 0; i < ts->typecnt; i++)
+ sp->ttis[sp->typecnt++] = ts->ttis[i];
}
}
}
+ if (sp->typecnt == 0)
+ return EINVAL;
if (sp->timecnt > 1) {
+ if (sp->ats[0] <= TIME_T_MAX - SECSPERREPEAT) {
+ time_t repeatat = sp->ats[0] + SECSPERREPEAT;
+ int repeattype = sp->types[0];
for (i = 1; i < sp->timecnt; ++i)
- if (typesequiv(sp, sp->types[i], sp->types[0]) &&
- differ_by_repeat(sp->ats[i], sp->ats[0])) {
+ if (sp->ats[i] == repeatat
+ && typesequiv(sp, sp->types[i], repeattype)) {
sp->goback = true;
break;
- }
+ }
+ }
+ if (TIME_T_MIN + SECSPERREPEAT <= sp->ats[sp->timecnt - 1]) {
+ time_t repeatat = sp->ats[sp->timecnt - 1] - SECSPERREPEAT;
+ int repeattype = sp->types[sp->timecnt - 1];
for (i = sp->timecnt - 2; i >= 0; --i)
- if (typesequiv(sp, sp->types[sp->timecnt - 1],
- sp->types[i]) &&
- differ_by_repeat(sp->ats[sp->timecnt - 1],
- sp->ats[i])) {
+ if (sp->ats[i] == repeatat
+ && typesequiv(sp, sp->types[i], repeattype)) {
sp->goahead = true;
break;
- }
+ }
+ }
}
+
+ /* Infer sp->defaulttype from the data. Although this default
+ type is always zero for data from recent tzdb releases,
+ things are trickier for data from tzdb 2018e or earlier.
+
+ The first set of heuristics work around bugs in 32-bit data
+ generated by tzdb 2013c or earlier. The workaround is for
+ zones like Australia/Macquarie where timestamps before the
+ first transition have a time type that is not the earliest
+ standard-time type. See:
+ https://mm.icann.org/pipermail/tz/2013-May/019368.html */
/*
- ** If type 0 is is unused in transitions,
+ ** If type 0 does not specify local time, or is unused in transitions,
** it's the type to use for early times.
*/
for (i = 0; i < sp->timecnt; ++i)
if (sp->types[i] == 0)
break;
- i = i < sp->timecnt ? -1 : 0;
+ i = i < sp->timecnt && ! ttunspecified(sp, 0) ? -1 : 0;
/*
** Absent the above,
** if there are transition times
@@ -664,6 +774,9 @@
if (!sp->ttis[i].tt_isdst)
break;
}
+ /* The next heuristics are for data generated by tzdb 2018e or
+ earlier, for zones like EST5EDT where the first transition
+ is to DST. */
/*
** If no result yet, find the first standard type.
** If there is none, punt to type zero.
@@ -676,7 +789,12 @@
break;
}
}
+ /* A simple 'sp->defaulttype = 0;' would suffice here if we
+ didn't have to worry about 2018e-or-earlier data. Even
+ simpler would be to remove the defaulttype member and just
+ use 0 in its place. */
sp->defaulttype = i;
+
return 0;
}
@@ -687,9 +805,9 @@
{
#ifdef ALL_STATE
union local_storage *lsp = malloc(sizeof *lsp);
- if (!lsp)
- return errno;
- else {
+ if (!lsp) {
+ return HAVE_MALLOC_ERRNO ? errno : ENOMEM;
+ } else {
int err = tzloadbody(name, sp, doextend, lsp);
free(lsp);
return err;
@@ -712,12 +830,13 @@
else {
register const struct ttinfo * ap = &sp->ttis[a];
register const struct ttinfo * bp = &sp->ttis[b];
- result = ap->tt_gmtoff == bp->tt_gmtoff &&
- ap->tt_isdst == bp->tt_isdst &&
- ap->tt_ttisstd == bp->tt_ttisstd &&
- ap->tt_ttisgmt == bp->tt_ttisgmt &&
- strcmp(&sp->chars[ap->tt_abbrind],
- &sp->chars[bp->tt_abbrind]) == 0;
+ result = (ap->tt_utoff == bp->tt_utoff
+ && ap->tt_isdst == bp->tt_isdst
+ && ap->tt_ttisstd == bp->tt_ttisstd
+ && ap->tt_ttisut == bp->tt_ttisut
+ && (strcmp(&sp->chars[ap->tt_desigidx],
+ &sp->chars[bp->tt_desigidx])
+ == 0));
}
return result;
}
@@ -731,13 +850,20 @@
DAYSPERNYEAR, DAYSPERLYEAR
};
+/* Is C an ASCII digit? */
+static bool
+is_digit(char c)
+{
+ return '0' <= c && c <= '9';
+}
+
/*
-** Given a pointer into a time zone string, scan until a character that is not
-** a valid character in a zone name is found. Return a pointer to that
-** character.
+** Given a pointer into a timezone string, scan until a character that is not
+** a valid character in a time zone abbreviation is found.
+** Return a pointer to that character.
*/
-static const char * ATTRIBUTE_PURE
+static ATTRIBUTE_PURE const char *
getzname(register const char *strp)
{
register char c;
@@ -749,15 +875,16 @@
}
/*
-** Given a pointer into an extended time zone string, scan until the ending
-** delimiter of the zone name is located. Return a pointer to the delimiter.
+** Given a pointer into an extended timezone string, scan until the ending
+** delimiter of the time zone abbreviation is located.
+** Return a pointer to the delimiter.
**
** As with getzname above, the legal character set is actually quite
** restricted, with other characters producing undefined results.
** We don't do any checking here; checking is done later in common-case code.
*/
-static const char * ATTRIBUTE_PURE
+static ATTRIBUTE_PURE const char *
getqzname(register const char *strp, const int delim)
{
register int c;
@@ -768,7 +895,7 @@
}
/*
-** Given a pointer into a time zone string, extract a number from that string.
+** Given a pointer into a timezone string, extract a number from that string.
** Check that the number is within a specified range; if it is not, return
** NULL.
** Otherwise, return a pointer to the first character not part of the number.
@@ -796,7 +923,7 @@
}
/*
-** Given a pointer into a time zone string, extract a number of seconds,
+** Given a pointer into a timezone string, extract a number of seconds,
** in hh[:mm[:ss]] form, from the string.
** If any error occurs, return NULL.
** Otherwise, return a pointer to the first character not part of the number
@@ -807,6 +934,7 @@
getsecs(register const char *strp, int_fast32_t *const secsp)
{
int num;
+ int_fast32_t secsperhour = SECSPERHOUR;
/*
** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
@@ -817,7 +945,7 @@
strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
if (strp == NULL)
return NULL;
- *secsp = num * (int_fast32_t) SECSPERHOUR;
+ *secsp = num * secsperhour;
if (*strp == ':') {
++strp;
strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
@@ -837,7 +965,7 @@
}
/*
-** Given a pointer into a time zone string, extract an offset, in
+** Given a pointer into a timezone string, extract an offset, in
** [+-]hh[:mm[:ss]] form, from the string.
** If any error occurs, return NULL.
** Otherwise, return a pointer to the first character not part of the time.
@@ -862,7 +990,7 @@
}
/*
-** Given a pointer into a time zone string, extract a rule in the form
+** Given a pointer into a timezone string, extract a rule in the form
** date[/time]. See POSIX section 8 for the format of "date" and "time".
** If a valid rule is not found, return NULL.
** Otherwise, return a pointer to the first character not part of the rule.
@@ -919,7 +1047,7 @@
** effect, calculate the year-relative time that rule takes effect.
*/
-static int_fast32_t ATTRIBUTE_PURE
+static int_fast32_t
transtime(const int year, register const struct rule *const rulep,
const int_fast32_t offset)
{
@@ -928,7 +1056,6 @@
register int i;
int d, m1, yy0, yy1, yy2, dow;
- INITIALIZE(value);
leapyear = isleap(year);
switch (rulep->r_type) {
@@ -994,6 +1121,8 @@
for (i = 0; i < rulep->r_mon - 1; ++i)
value += mon_lengths[leapyear][i] * SECSPERDAY;
break;
+
+ default: UNREACHABLE();
}
/*
@@ -1011,7 +1140,7 @@
*/
static bool
-tzparse(const char *name, struct state *sp, bool lastditch)
+tzparse(const char *name, struct state *sp, struct state *basep)
{
const char * stdname;
const char * dstname;
@@ -1022,37 +1151,42 @@
int_fast32_t dstoffset;
register char * cp;
register bool load_ok;
+ time_t atlo = TIME_T_MIN, leaplo = TIME_T_MIN;
stdname = name;
- if (lastditch) {
- stdlen = sizeof gmt - 1;
- name += stdlen;
- stdoffset = 0;
+ if (*name == '<') {
+ name++;
+ stdname = name;
+ name = getqzname(name, '>');
+ if (*name != '>')
+ return false;
+ stdlen = name - stdname;
+ name++;
} else {
- if (*name == '<') {
- name++;
- stdname = name;
- name = getqzname(name, '>');
- if (*name != '>')
- return false;
- stdlen = name - stdname;
- name++;
- } else {
- name = getzname(name);
- stdlen = name - stdname;
- }
- if (!stdlen)
- return false;
- name = getoffset(name, &stdoffset);
- if (name == NULL)
- return false;
+ name = getzname(name);
+ stdlen = name - stdname;
}
+ if (!stdlen)
+ return false;
+ name = getoffset(name, &stdoffset);
+ if (name == NULL)
+ return false;
charcnt = stdlen + 1;
if (sizeof sp->chars < charcnt)
return false;
- load_ok = tzload(TZDEFRULES, sp, false) == 0;
- if (!load_ok)
- sp->leapcnt = 0; /* so, we're off a little */
+ if (basep) {
+ if (0 < basep->timecnt)
+ atlo = basep->ats[basep->timecnt - 1];
+ load_ok = false;
+ sp->leapcnt = basep->leapcnt;
+ memcpy(sp->lsis, basep->lsis, sp->leapcnt * sizeof *sp->lsis);
+ } else {
+ load_ok = tzload(TZDEFRULES, sp, false) == 0;
+ if (!load_ok)
+ sp->leapcnt = 0; /* So, we're off a little. */
+ }
+ if (0 < sp->leapcnt)
+ leaplo = sp->lsis[sp->leapcnt - 1].ls_trans;
if (*name != '\0') {
if (*name == '<') {
dstname = ++name;
@@ -1064,7 +1198,7 @@
} else {
dstname = name;
name = getzname(name);
- dstlen = name - dstname; /* length of DST zone name */
+ dstlen = name - dstname; /* length of DST abbr. */
}
if (!dstlen)
return false;
@@ -1082,9 +1216,10 @@
struct rule start;
struct rule end;
register int year;
- register int yearlim;
register int timecnt;
time_t janfirst;
+ int_fast32_t janoffset = 0;
+ int yearbeg, yearlim;
++name;
if ((name = getrule(name, &start)) == NULL)
@@ -1099,13 +1234,41 @@
/*
** Two transitions per year, from EPOCH_YEAR forward.
*/
- init_ttinfo(&sp->ttis[0], -dstoffset, true, stdlen + 1);
- init_ttinfo(&sp->ttis[1], -stdoffset, false, 0);
+ init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
+ init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
sp->defaulttype = 0;
timecnt = 0;
janfirst = 0;
- yearlim = EPOCH_YEAR + YEARSPERREPEAT;
- for (year = EPOCH_YEAR; year < yearlim; year++) {
+ yearbeg = EPOCH_YEAR;
+
+ do {
+ int_fast32_t yearsecs
+ = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
+ yearbeg--;
+ if (increment_overflow_time(&janfirst, -yearsecs)) {
+ janoffset = -yearsecs;
+ break;
+ }
+ } while (atlo < janfirst
+ && EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
+
+ while (true) {
+ int_fast32_t yearsecs
+ = year_lengths[isleap(yearbeg)] * SECSPERDAY;
+ int yearbeg1 = yearbeg;
+ time_t janfirst1 = janfirst;
+ if (increment_overflow_time(&janfirst1, yearsecs)
+ || increment_overflow(&yearbeg1, 1)
+ || atlo <= janfirst1)
+ break;
+ yearbeg = yearbeg1;
+ janfirst = janfirst1;
+ }
+
+ yearlim = yearbeg;
+ if (increment_overflow(&yearlim, YEARSPERREPEAT + 1))
+ yearlim = INT_MAX;
+ for (year = yearbeg; year < yearlim; year++) {
int_fast32_t
starttime = transtime(year, &start, stdoffset),
endtime = transtime(year, &end, dstoffset);
@@ -1120,29 +1283,40 @@
}
if (reversed
|| (starttime < endtime
- && (endtime - starttime
- < (yearsecs
- + (stdoffset - dstoffset))))) {
+ && endtime - starttime < yearsecs)) {
if (TZ_MAX_TIMES - 2 < timecnt)
break;
- yearlim = year + YEARSPERREPEAT + 1;
sp->ats[timecnt] = janfirst;
- if (increment_overflow_time
- (&sp->ats[timecnt], starttime))
- break;
- sp->types[timecnt++] = reversed;
+ if (! increment_overflow_time
+ (&sp->ats[timecnt],
+ janoffset + starttime)
+ && atlo <= sp->ats[timecnt])
+ sp->types[timecnt++] = !reversed;
sp->ats[timecnt] = janfirst;
- if (increment_overflow_time
- (&sp->ats[timecnt], endtime))
- break;
- sp->types[timecnt++] = !reversed;
+ if (! increment_overflow_time
+ (&sp->ats[timecnt],
+ janoffset + endtime)
+ && atlo <= sp->ats[timecnt]) {
+ sp->types[timecnt++] = reversed;
+ }
}
- if (increment_overflow_time(&janfirst, yearsecs))
+ if (endtime < leaplo) {
+ yearlim = year;
+ if (increment_overflow(&yearlim,
+ YEARSPERREPEAT + 1))
+ yearlim = INT_MAX;
+ }
+ if (increment_overflow_time
+ (&janfirst, janoffset + yearsecs))
break;
+ janoffset = 0;
}
sp->timecnt = timecnt;
- if (!timecnt)
+ if (! timecnt) {
+ sp->ttis[0] = sp->ttis[1];
sp->typecnt = 1; /* Perpetual DST. */
+ } else if (YEARSPERREPEAT < year - yearbeg)
+ sp->goback = sp->goahead = true;
} else {
register int_fast32_t theirstdoffset;
register int_fast32_t theirdstoffset;
@@ -1161,7 +1335,7 @@
j = sp->types[i];
if (!sp->ttis[j].tt_isdst) {
theirstdoffset =
- -sp->ttis[j].tt_gmtoff;
+ - sp->ttis[j].tt_utoff;
break;
}
}
@@ -1170,7 +1344,7 @@
j = sp->types[i];
if (sp->ttis[j].tt_isdst) {
theirdstoffset =
- -sp->ttis[j].tt_gmtoff;
+ - sp->ttis[j].tt_utoff;
break;
}
}
@@ -1178,7 +1352,6 @@
** Initially we're assumed to be in standard time.
*/
isdst = false;
- theiroffset = theirstdoffset;
/*
** Now juggle transition times and types
** tracking offsets as you do.
@@ -1186,16 +1359,17 @@
for (i = 0; i < sp->timecnt; ++i) {
j = sp->types[i];
sp->types[i] = sp->ttis[j].tt_isdst;
- if (sp->ttis[j].tt_ttisgmt) {
+ if (sp->ttis[j].tt_ttisut) {
/* No adjustment to transition time */
} else {
/*
- ** If summer time is in effect, and the
- ** transition time was not specified as
- ** standard time, add the summer time
- ** offset to the transition time;
- ** otherwise, add the standard time
- ** offset to the transition time.
+ ** If daylight saving time is in
+ ** effect, and the transition time was
+ ** not specified as standard time, add
+ ** the daylight saving time offset to
+ ** the transition time; otherwise, add
+ ** the standard time offset to the
+ ** transition time.
*/
/*
** Transitions from DST to DDST
@@ -1211,7 +1385,7 @@
theirstdoffset;
}
}
- theiroffset = -sp->ttis[j].tt_gmtoff;
+ theiroffset = -sp->ttis[j].tt_utoff;
if (sp->ttis[j].tt_isdst)
theirdstoffset = theiroffset;
else theirstdoffset = theiroffset;
@@ -1247,7 +1421,7 @@
gmtload(struct state *const sp)
{
if (tzload(gmt, sp, true) != 0)
- tzparse(gmt, sp, true);
+ tzparse("GMT0", sp, NULL);
}
/* Initialize *SP to a value appropriate for the TZ setting NAME.
@@ -1270,7 +1444,7 @@
return 0;
} else {
int err = tzload(name, sp, true);
- if (err != 0 && name && name[0] != ':' && tzparse(name, sp, false))
+ if (err != 0 && name && name[0] != ':' && tzparse(name, sp, NULL))
err = 0;
if (err == 0)
scrub_abbrs(sp);
@@ -1301,17 +1475,6 @@
lcl_is_set = lcl;
}
-#ifdef STD_INSPIRED
-void
-tzsetwall(void)
-{
- if (lock() != 0)
- return;
- tzsetlcl(NULL);
- unlock();
-}
-#endif
-
#if defined(__BIONIC__)
extern void tzset_unlocked(void);
#else
@@ -1361,7 +1524,8 @@
errno = err;
return NULL;
}
- }
+ } else if (!HAVE_MALLOC_ERRNO)
+ errno = ENOMEM;
return sp;
}
@@ -1391,7 +1555,7 @@
**
** If successful and SETNAME is nonzero,
** set the applicable parts of tzname, timezone and altzone;
-** however, it's OK to omit this step if the time zone is POSIX-compatible,
+** however, it's OK to omit this step if the timezone is POSIX-compatible,
** since in that case tzset should have already done this step correctly.
** SETNAME's type is intfast32_t for compatibility with gmtsub,
** but it is actually a boolean and its value should be 0 or 1.
@@ -1413,7 +1577,7 @@
}
if ((sp->goback && t < sp->ats[0]) ||
(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
- time_t newt = t;
+ time_t newt;
register time_t seconds;
register time_t years;
@@ -1421,11 +1585,17 @@
seconds = sp->ats[0] - t;
else seconds = t - sp->ats[sp->timecnt - 1];
--seconds;
- years = (seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT;
+
+ /* Beware integer overflow, as SECONDS might
+ be close to the maximum time_t. */
+ years = seconds / SECSPERREPEAT * YEARSPERREPEAT;
seconds = years * AVGSECSPERYEAR;
+ years += YEARSPERREPEAT;
if (t < sp->ats[0])
- newt += seconds;
- else newt -= seconds;
+ newt = t + seconds + SECSPERREPEAT;
+ else
+ newt = t - seconds - SECSPERREPEAT;
+
if (newt < sp->ats[0] ||
newt > sp->ats[sp->timecnt - 1])
return NULL; /* "cannot happen" */
@@ -1456,20 +1626,20 @@
hi = mid;
else lo = mid + 1;
}
- i = (int) sp->types[lo - 1];
+ i = sp->types[lo - 1];
}
ttisp = &sp->ttis[i];
/*
** To get (wrong) behavior that's compatible with System V Release 2.0
** you'd replace the statement below with
- ** t += ttisp->tt_gmtoff;
+ ** t += ttisp->tt_utoff;
** timesub(&t, 0L, sp, tmp);
*/
- result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
+ result = timesub(&t, ttisp->tt_utoff, sp, tmp);
if (result) {
result->tm_isdst = ttisp->tt_isdst;
#ifdef TM_ZONE
- result->TM_ZONE = (char *) &sp->chars[ttisp->tt_abbrind];
+ result->TM_ZONE = (char *) &sp->chars[ttisp->tt_desigidx];
#endif /* defined TM_ZONE */
if (setname)
update_tzname_etc(sp, ttisp);
@@ -1534,7 +1704,7 @@
#ifdef TM_ZONE
/*
** Could get fancy here and deliver something such as
- ** "UT+xxxx" or "UT-xxxx" if offset is non-zero,
+ ** "+xx" or "-xx" if offset is non-zero,
** but this is no time for a treasure hunt.
*/
tmp->TM_ZONE = ((char *)
@@ -1576,11 +1746,18 @@
** where, to make the math easy, the answer for year zero is defined as zero.
*/
-static int ATTRIBUTE_PURE
-leaps_thru_end_of(register const int y)
+static time_t
+leaps_thru_end_of_nonneg(time_t y)
{
- return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
- -(leaps_thru_end_of(-(y + 1)) + 1);
+ return y / 4 - y / 100 + y / 400;
+}
+
+static time_t
+leaps_thru_end_of(time_t y)
+{
+ return (y < 0
+ ? -1 - leaps_thru_end_of_nonneg(-1 - y)
+ : leaps_thru_end_of_nonneg(y));
}
static struct tm *
@@ -1589,122 +1766,106 @@
{
register const struct lsinfo * lp;
register time_t tdays;
- register int idays; /* unsigned would be so 2003 */
- register int_fast64_t rem;
- int y;
register const int * ip;
- register int_fast64_t corr;
- register bool hit;
+ register int_fast32_t corr;
register int i;
+ int_fast32_t idays, rem, dayoff, dayrem;
+ time_t y;
+
+ /* If less than SECSPERMIN, the number of seconds since the
+ most recent positive leap second; otherwise, do not add 1
+ to localtime tm_sec because of leap seconds. */
+ time_t secs_since_posleap = SECSPERMIN;
corr = 0;
- hit = false;
i = (sp == NULL) ? 0 : sp->leapcnt;
while (--i >= 0) {
lp = &sp->lsis[i];
if (*timep >= lp->ls_trans) {
- if (*timep == lp->ls_trans) {
- hit = ((i == 0 && lp->ls_corr > 0) ||
- lp->ls_corr > sp->lsis[i - 1].ls_corr);
- if (hit)
- while (i > 0 &&
- sp->lsis[i].ls_trans ==
- sp->lsis[i - 1].ls_trans + 1 &&
- sp->lsis[i].ls_corr ==
- sp->lsis[i - 1].ls_corr + 1) {
- ++hit;
- --i;
- }
- }
corr = lp->ls_corr;
+ if ((i == 0 ? 0 : lp[-1].ls_corr) < corr)
+ secs_since_posleap = *timep - lp->ls_trans;
break;
}
}
- y = EPOCH_YEAR;
+
+ /* Calculate the year, avoiding integer overflow even if
+ time_t is unsigned. */
tdays = *timep / SECSPERDAY;
rem = *timep % SECSPERDAY;
- while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
- int newy;
- register time_t tdelta;
- register int idelta;
+ rem += offset % SECSPERDAY - corr % SECSPERDAY + 3 * SECSPERDAY;
+ dayoff = offset / SECSPERDAY - corr / SECSPERDAY + rem / SECSPERDAY - 3;
+ rem %= SECSPERDAY;
+ /* y = (EPOCH_YEAR
+ + floor((tdays + dayoff) / DAYSPERREPEAT) * YEARSPERREPEAT),
+ sans overflow. But calculate against 1570 (EPOCH_YEAR -
+ YEARSPERREPEAT) instead of against 1970 so that things work
+ for localtime values before 1970 when time_t is unsigned. */
+ dayrem = tdays % DAYSPERREPEAT;
+ dayrem += dayoff % DAYSPERREPEAT;
+ y = (EPOCH_YEAR - YEARSPERREPEAT
+ + ((1 + dayoff / DAYSPERREPEAT + dayrem / DAYSPERREPEAT
+ - ((dayrem % DAYSPERREPEAT) < 0)
+ + tdays / DAYSPERREPEAT)
+ * YEARSPERREPEAT));
+ /* idays = (tdays + dayoff) mod DAYSPERREPEAT, sans overflow. */
+ idays = tdays % DAYSPERREPEAT;
+ idays += dayoff % DAYSPERREPEAT + 2 * DAYSPERREPEAT;
+ idays %= DAYSPERREPEAT;
+ /* Increase Y and decrease IDAYS until IDAYS is in range for Y. */
+ while (year_lengths[isleap(y)] <= idays) {
+ int tdelta = idays / DAYSPERLYEAR;
+ int_fast32_t ydelta = tdelta + !tdelta;
+ time_t newy = y + ydelta;
register int leapdays;
-
- tdelta = tdays / DAYSPERLYEAR;
- if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
- && tdelta <= INT_MAX))
- goto out_of_range;
- idelta = tdelta;
- if (idelta == 0)
- idelta = (tdays < 0) ? -1 : 1;
- newy = y;
- if (increment_overflow(&newy, idelta))
- goto out_of_range;
leapdays = leaps_thru_end_of(newy - 1) -
leaps_thru_end_of(y - 1);
- tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
- tdays -= leapdays;
+ idays -= ydelta * DAYSPERNYEAR;
+ idays -= leapdays;
y = newy;
}
- /*
- ** Given the range, we can now fearlessly cast...
- */
- idays = tdays;
- rem += offset - corr;
- while (rem < 0) {
- rem += SECSPERDAY;
- --idays;
+
+ if (!TYPE_SIGNED(time_t) && y < TM_YEAR_BASE) {
+ int signed_y = y;
+ tmp->tm_year = signed_y - TM_YEAR_BASE;
+ } else if ((!TYPE_SIGNED(time_t) || INT_MIN + TM_YEAR_BASE <= y)
+ && y - TM_YEAR_BASE <= INT_MAX)
+ tmp->tm_year = y - TM_YEAR_BASE;
+ else {
+ errno = EOVERFLOW;
+ return NULL;
}
- while (rem >= SECSPERDAY) {
- rem -= SECSPERDAY;
- ++idays;
- }
- while (idays < 0) {
- if (increment_overflow(&y, -1))
- goto out_of_range;
- idays += year_lengths[isleap(y)];
- }
- while (idays >= year_lengths[isleap(y)]) {
- idays -= year_lengths[isleap(y)];
- if (increment_overflow(&y, 1))
- goto out_of_range;
- }
- tmp->tm_year = y;
- if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
- goto out_of_range;
tmp->tm_yday = idays;
/*
** The "extra" mods below avoid overflow problems.
*/
- tmp->tm_wday = EPOCH_WDAY +
- ((y - EPOCH_YEAR) % DAYSPERWEEK) *
- (DAYSPERNYEAR % DAYSPERWEEK) +
- leaps_thru_end_of(y - 1) -
- leaps_thru_end_of(EPOCH_YEAR - 1) +
- idays;
+ tmp->tm_wday = (TM_WDAY_BASE
+ + ((tmp->tm_year % DAYSPERWEEK)
+ * (DAYSPERNYEAR % DAYSPERWEEK))
+ + leaps_thru_end_of(y - 1)
+ - leaps_thru_end_of(TM_YEAR_BASE - 1)
+ + idays);
tmp->tm_wday %= DAYSPERWEEK;
if (tmp->tm_wday < 0)
tmp->tm_wday += DAYSPERWEEK;
- tmp->tm_hour = (int) (rem / SECSPERHOUR);
+ tmp->tm_hour = rem / SECSPERHOUR;
rem %= SECSPERHOUR;
- tmp->tm_min = (int) (rem / SECSPERMIN);
- /*
- ** A positive leap second requires a special
- ** representation. This uses "... ??:59:60" et seq.
- */
- tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
+ tmp->tm_min = rem / SECSPERMIN;
+ tmp->tm_sec = rem % SECSPERMIN;
+
+ /* Use "... ??:??:60" at the end of the localtime minute containing
+ the second just before the positive leap second. */
+ tmp->tm_sec += secs_since_posleap <= tmp->tm_sec;
+
ip = mon_lengths[isleap(y)];
for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
idays -= ip[tmp->tm_mon];
- tmp->tm_mday = (int) (idays + 1);
+ tmp->tm_mday = idays + 1;
tmp->tm_isdst = 0;
#ifdef TM_GMTOFF
tmp->TM_GMTOFF = offset;
#endif /* defined TM_GMTOFF */
return tmp;
-
- out_of_range:
- errno = EOVERFLOW;
- return NULL;
}
char *
@@ -1778,12 +1939,12 @@
{
/*
** This is like
- ** 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...',
+ ** 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
** except that it does the right thing even if *tp + j would overflow.
*/
if (! (j < 0
- ? (TYPE_SIGNED(time_t) ? time_t_min - j <= *tp : -1 - j < *tp)
- : *tp <= time_t_max - j))
+ ? (TYPE_SIGNED(time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
+ : *tp <= TIME_T_MAX - j))
return true;
*tp += j;
return false;
@@ -1919,8 +2080,8 @@
/*
** Do a binary search (this works whatever time_t's type is).
*/
- lo = time_t_min;
- hi = time_t_max;
+ lo = TIME_T_MIN;
+ hi = TIME_T_MAX;
for ( ; ; ) {
t = lo / 2 + hi / 2;
if (t < lo)
@@ -1937,12 +2098,12 @@
} else dir = tmcomp(&mytm, &yourtm);
if (dir != 0) {
if (t == lo) {
- if (t == time_t_max)
+ if (t == TIME_T_MAX)
return WRONG;
++t;
++lo;
} else if (t == hi) {
- if (t == time_t_min)
+ if (t == TIME_T_MIN)
return WRONG;
--t;
--hi;
@@ -1959,13 +2120,13 @@
&& (yourtm.TM_GMTOFF < 0
? (-SECSPERDAY <= yourtm.TM_GMTOFF
&& (mytm.TM_GMTOFF <=
- (SMALLEST (INT_FAST32_MAX, LONG_MAX)
+ (SMALLEST(INT_FAST32_MAX, LONG_MAX)
+ yourtm.TM_GMTOFF)))
: (yourtm.TM_GMTOFF <= SECSPERDAY
- && ((BIGGEST (INT_FAST32_MIN, LONG_MIN)
+ && ((BIGGEST(INT_FAST32_MIN, LONG_MIN)
+ yourtm.TM_GMTOFF)
<= mytm.TM_GMTOFF)))) {
- /* MYTM matches YOURTM except with the wrong UTC offset.
+ /* MYTM matches YOURTM except with the wrong UT offset.
YOURTM.TM_GMTOFF is plausible, so try it instead.
It's OK if YOURTM.TM_GMTOFF contains uninitialized data,
since the guess gets checked. */
@@ -1999,8 +2160,10 @@
for (j = sp->typecnt - 1; j >= 0; --j) {
if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
continue;
- newt = t + sp->ttis[j].tt_gmtoff -
- sp->ttis[i].tt_gmtoff;
+ if (ttunspecified(sp, j))
+ continue;
+ newt = (t + sp->ttis[j].tt_utoff
+ - sp->ttis[i].tt_utoff);
if (! funcp(sp, &newt, offset, &mytm))
continue;
if (tmcomp(&mytm, &yourtm) != 0)
@@ -2047,8 +2210,8 @@
static time_t
time1(struct tm *const tmp,
- struct tm *(*funcp) (struct state const *, time_t const *,
- int_fast32_t, struct tm *),
+ struct tm *(*funcp)(struct state const *, time_t const *,
+ int_fast32_t, struct tm *),
struct state const *sp,
const int_fast32_t offset)
{
@@ -2091,7 +2254,7 @@
seen[i] = false;
nseen = 0;
for (i = sp->timecnt - 1; i >= 0; --i)
- if (!seen[sp->types[i]]) {
+ if (!seen[sp->types[i]] && !ttunspecified(sp, sp->types[i])) {
seen[sp->types[i]] = true;
types[nseen++] = sp->types[i];
}
@@ -2103,14 +2266,14 @@
otheri = types[otherind];
if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
continue;
- tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
- sp->ttis[samei].tt_gmtoff;
+ tmp->tm_sec += (sp->ttis[otheri].tt_utoff
+ - sp->ttis[samei].tt_utoff);
tmp->tm_isdst = !tmp->tm_isdst;
t = time2(tmp, funcp, sp, offset, &okay);
if (okay)
return t;
- tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
- sp->ttis[samei].tt_gmtoff;
+ tmp->tm_sec -= (sp->ttis[otheri].tt_utoff
+ - sp->ttis[samei].tt_utoff);
tmp->tm_isdst = !tmp->tm_isdst;
}
}
@@ -2188,21 +2351,7 @@
#endif /* defined STD_INSPIRED */
-/*
-** XXX--is the below the right way to conditionalize??
-*/
-
-#ifdef STD_INSPIRED
-
-/*
-** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
-** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
-** is not the case if we are accounting for leap seconds.
-** So, we provide the following conversion routines for use
-** when exchanging timestamps with POSIX conforming systems.
-*/
-
-static int_fast64_t
+static int_fast32_t
leapcorr(struct state const *sp, time_t t)
{
register struct lsinfo const * lp;
@@ -2217,7 +2366,29 @@
return 0;
}
-NETBSD_INSPIRED_EXTERN time_t ATTRIBUTE_PURE
+/*
+** XXX--is the below the right way to conditionalize??
+*/
+
+#ifdef STD_INSPIRED
+
+/* NETBSD_INSPIRED_EXTERN functions are exported to callers if
+ NETBSD_INSPIRED is defined, and are private otherwise. */
+# if NETBSD_INSPIRED
+# define NETBSD_INSPIRED_EXTERN
+# else
+# define NETBSD_INSPIRED_EXTERN static
+# endif
+
+/*
+** IEEE Std 1003.1 (POSIX) says that 536457599
+** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
+** is not the case if we are accounting for leap seconds.
+** So, we provide the following conversion routines for use
+** when exchanging timestamps with POSIX conforming systems.
+*/
+
+NETBSD_INSPIRED_EXTERN time_t
time2posix_z(struct state *sp, time_t t)
{
return t - leapcorr(sp, t);
@@ -2239,7 +2410,7 @@
return t;
}
-NETBSD_INSPIRED_EXTERN time_t ATTRIBUTE_PURE
+NETBSD_INSPIRED_EXTERN time_t
posix2time_z(struct state *sp, time_t t)
{
time_t x;
@@ -2286,15 +2457,39 @@
#endif /* defined STD_INSPIRED */
-#ifdef time_tz
+#if TZ_TIME_T
+
+# if !USG_COMPAT
+# define daylight 0
+# define timezone 0
+# endif
+# if !ALTZONE
+# define altzone 0
+# endif
/* Convert from the underlying system's time_t to the ersatz time_tz,
- which is called 'time_t' in this file. */
+ which is called 'time_t' in this file. Typically, this merely
+ converts the time's integer width. On some platforms, the system
+ time is local time not UT, or uses some epoch other than the POSIX
+ epoch.
+
+ Although this code appears to define a function named 'time' that
+ returns time_t, the macros in private.h cause this code to actually
+ define a function named 'tz_time' that returns tz_time_t. The call
+ to sys_time invokes the underlying system's 'time' function. */
time_t
time(time_t *p)
{
time_t r = sys_time(0);
+ if (r != (time_t) -1) {
+ int_fast32_t offset = EPOCH_LOCAL ? (daylight ? timezone : altzone) : 0;
+ if (increment_overflow32(&offset, -EPOCH_OFFSET)
+ || increment_overflow_time(&r, offset)) {
+ errno = EOVERFLOW;
+ r = -1;
+ }
+ }
if (p)
*p = r;
return r;
diff --git a/libc/tzcode/private.h b/libc/tzcode/private.h
index 941e91b..4c03324 100644
--- a/libc/tzcode/private.h
+++ b/libc/tzcode/private.h
@@ -1,3 +1,5 @@
+/* Private header for tzdb code. */
+
#ifndef PRIVATE_H
#define PRIVATE_H
@@ -15,6 +17,17 @@
** Thank you!
*/
+/*
+** zdump has been made independent of the rest of the time
+** conversion package to increase confidence in the verification it provides.
+** You can use zdump to help in verifying other implementations.
+** To do this, compile with -DUSE_LTZ=0 and link without the tz library.
+*/
+#ifndef USE_LTZ
+# define USE_LTZ 1
+#endif
+
+/* This string was in the Factory zone through version 2016f. */
#define GRANDPARENTED "Local time zone must be set--see zic manual page"
/*
@@ -26,26 +39,53 @@
#define HAVE_DECL_ASCTIME_R 1
#endif
+#if !defined HAVE_GENERIC && defined __has_extension
+# if __has_extension(c_generic_selections)
+# define HAVE_GENERIC 1
+# else
+# define HAVE_GENERIC 0
+# endif
+#endif
+/* _Generic is buggy in pre-4.9 GCC. */
+#if !defined HAVE_GENERIC && defined __GNUC__
+# define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__))
+#endif
+#ifndef HAVE_GENERIC
+# define HAVE_GENERIC (201112 <= __STDC_VERSION__)
+#endif
+
#ifndef HAVE_GETTEXT
#define HAVE_GETTEXT 0
#endif /* !defined HAVE_GETTEXT */
#ifndef HAVE_INCOMPATIBLE_CTIME_R
#define HAVE_INCOMPATIBLE_CTIME_R 0
-#endif /* !defined INCOMPATIBLE_CTIME_R */
+#endif
#ifndef HAVE_LINK
#define HAVE_LINK 1
#endif /* !defined HAVE_LINK */
+#ifndef HAVE_MALLOC_ERRNO
+#define HAVE_MALLOC_ERRNO 1
+#endif
+
#ifndef HAVE_POSIX_DECLS
#define HAVE_POSIX_DECLS 1
#endif
+#ifndef HAVE_STDBOOL_H
+#define HAVE_STDBOOL_H (199901 <= __STDC_VERSION__)
+#endif
+
#ifndef HAVE_STRDUP
#define HAVE_STRDUP 1
#endif
+#ifndef HAVE_STRTOLL
+#define HAVE_STRTOLL 1
+#endif
+
#ifndef HAVE_SYMLINK
#define HAVE_SYMLINK 1
#endif /* !defined HAVE_SYMLINK */
@@ -54,10 +94,6 @@
#define HAVE_SYS_STAT_H 1
#endif /* !defined HAVE_SYS_STAT_H */
-#ifndef HAVE_SYS_WAIT_H
-#define HAVE_SYS_WAIT_H 1
-#endif /* !defined HAVE_SYS_WAIT_H */
-
#ifndef HAVE_UNISTD_H
#define HAVE_UNISTD_H 1
#endif /* !defined HAVE_UNISTD_H */
@@ -75,22 +111,37 @@
#define ctime_r _incompatible_ctime_r
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
-/* Enable tm_gmtoff and tm_zone on GNUish systems. */
+/* Enable tm_gmtoff, tm_zone, and environ on GNUish systems. */
#define _GNU_SOURCE 1
-/* Fix asctime_r on Solaris 10. */
+/* Fix asctime_r on Solaris 11. */
#define _POSIX_PTHREAD_SEMANTICS 1
-/* Enable strtoimax on Solaris 10. */
+/* Enable strtoimax on pre-C99 Solaris 11. */
#define __EXTENSIONS__ 1
+/* To avoid having 'stat' fail unnecessarily with errno == EOVERFLOW,
+ enable large files on GNUish systems ... */
+#ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 64
+#endif
+/* ... and on AIX ... */
+#define _LARGE_FILES 1
+/* ... and enable large inode numbers on Mac OS X 10.5 and later. */
+#define _DARWIN_USE_64_BIT_INODE 1
+
/*
** Nested includes
*/
-/* Avoid clashes with NetBSD by renaming NetBSD's declarations. */
+/* Avoid clashes with NetBSD by renaming NetBSD's declarations.
+ If defining the 'timezone' variable, avoid a clash with FreeBSD's
+ 'timezone' function by renaming its declaration. */
#define localtime_rz sys_localtime_rz
#define mktime_z sys_mktime_z
#define posix2time_z sys_posix2time_z
#define time2posix_z sys_time2posix_z
+#if defined USG_COMPAT && USG_COMPAT == 2
+# define timezone sys_timezone
+#endif
#define timezone_t sys_timezone_t
#define tzalloc sys_tzalloc
#define tzfree sys_tzfree
@@ -99,21 +150,30 @@
#undef mktime_z
#undef posix2time_z
#undef time2posix_z
+#if defined USG_COMPAT && USG_COMPAT == 2
+# undef timezone
+#endif
#undef timezone_t
#undef tzalloc
#undef tzfree
-#include "sys/types.h" /* for time_t */
-#include "stdio.h"
-#include "string.h"
-#include "limits.h" /* for CHAR_BIT et al. */
-#include "stdlib.h"
+#include <sys/types.h> /* for time_t */
+#include <string.h>
+#include <limits.h> /* for CHAR_BIT et al. */
+#include <stdlib.h>
-#include "errno.h"
+#include <errno.h>
+
+#ifndef EINVAL
+# define EINVAL ERANGE
+#endif
#ifndef ENAMETOOLONG
# define ENAMETOOLONG EINVAL
#endif
+#ifndef ENOMEM
+# define ENOMEM EINVAL
+#endif
#ifndef ENOTSUP
# define ENOTSUP EINVAL
#endif
@@ -122,22 +182,11 @@
#endif
#if HAVE_GETTEXT
-#include "libintl.h"
+#include <libintl.h>
#endif /* HAVE_GETTEXT */
-#if HAVE_SYS_WAIT_H
-#include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
-#endif /* HAVE_SYS_WAIT_H */
-
-#ifndef WIFEXITED
-#define WIFEXITED(status) (((status) & 0xff) == 0)
-#endif /* !defined WIFEXITED */
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
-#endif /* !defined WEXITSTATUS */
-
#if HAVE_UNISTD_H
-#include "unistd.h" /* for F_OK, R_OK, and other POSIX goodness */
+#include <unistd.h> /* for R_OK, and other POSIX goodness */
#endif /* HAVE_UNISTD_H */
#ifndef HAVE_STRFTIME_L
@@ -148,31 +197,49 @@
# endif
#endif
-#ifndef F_OK
-#define F_OK 0
-#endif /* !defined F_OK */
+#ifndef USG_COMPAT
+# ifndef _XOPEN_VERSION
+# define USG_COMPAT 0
+# else
+# define USG_COMPAT 1
+# endif
+#endif
+
+#ifndef HAVE_TZNAME
+# if _POSIX_VERSION < 198808 && !USG_COMPAT
+# define HAVE_TZNAME 0
+# else
+# define HAVE_TZNAME 1
+# endif
+#endif
+
+#ifndef ALTZONE
+# if defined __sun || defined _M_XENIX
+# define ALTZONE 1
+# else
+# define ALTZONE 0
+# endif
+#endif
+
#ifndef R_OK
#define R_OK 4
#endif /* !defined R_OK */
-/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
-#define is_digit(c) ((unsigned)(c) - '0' <= 9)
-
/*
** Define HAVE_STDINT_H's default value here, rather than at the
-** start, since __GLIBC__'s value depends on previously-included
-** files.
-** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.)
+** start, since __GLIBC__ and INTMAX_MAX's values depend on
+** previously-included files. glibc 2.1 and Solaris 10 and later have
+** stdint.h, even with pre-C99 compilers.
*/
#ifndef HAVE_STDINT_H
#define HAVE_STDINT_H \
(199901 <= __STDC_VERSION__ \
|| 2 < __GLIBC__ + (1 <= __GLIBC_MINOR__) \
- || __CYGWIN__)
+ || __CYGWIN__ || INTMAX_MAX)
#endif /* !defined HAVE_STDINT_H */
#if HAVE_STDINT_H
-#include "stdint.h"
+#include <stdint.h>
#endif /* !HAVE_STDINT_H */
#ifndef HAVE_INTTYPES_H
@@ -208,14 +275,18 @@
# endif
#endif
-#ifndef SCNdFAST64
+#ifndef PRIdFAST64
# if INT_FAST64_MAX == LLONG_MAX
-# define SCNdFAST64 "lld"
+# define PRIdFAST64 "lld"
# else
-# define SCNdFAST64 "ld"
+# define PRIdFAST64 "ld"
# endif
#endif
+#ifndef SCNdFAST64
+# define SCNdFAST64 PRIdFAST64
+#endif
+
#ifndef INT_FAST32_MAX
# if INT_MAX >> 31 == 0
typedef long int_fast32_t;
@@ -231,15 +302,19 @@
#ifndef INTMAX_MAX
# ifdef LLONG_MAX
typedef long long intmax_t;
-# define strtoimax strtoll
+# if HAVE_STRTOLL
+# define strtoimax strtoll
+# endif
# define INTMAX_MAX LLONG_MAX
# define INTMAX_MIN LLONG_MIN
# else
typedef long intmax_t;
-# define strtoimax strtol
# define INTMAX_MAX LONG_MAX
# define INTMAX_MIN LONG_MIN
# endif
+# ifndef strtoimax
+# define strtoimax strtol
+# endif
#endif
#ifndef PRIdMAX
@@ -250,6 +325,10 @@
# endif
#endif
+#ifndef UINT_FAST32_MAX
+typedef unsigned long uint_fast32_t;
+#endif
+
#ifndef UINT_FAST64_MAX
# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
typedef unsigned long long uint_fast64_t;
@@ -289,19 +368,21 @@
#define SIZE_MAX ((size_t) -1)
#endif
-#if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
-# define ATTRIBUTE_CONST __attribute__ ((const))
-# define ATTRIBUTE_PURE __attribute__ ((__pure__))
-# define ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
+#if 3 <= __GNUC__
+# define ATTRIBUTE_CONST __attribute__((const))
+# define ATTRIBUTE_MALLOC __attribute__((__malloc__))
+# define ATTRIBUTE_PURE __attribute__((__pure__))
+# define ATTRIBUTE_FORMAT(spec) __attribute__((__format__ spec))
#else
# define ATTRIBUTE_CONST /* empty */
+# define ATTRIBUTE_MALLOC /* empty */
# define ATTRIBUTE_PURE /* empty */
# define ATTRIBUTE_FORMAT(spec) /* empty */
#endif
#if !defined _Noreturn && __STDC_VERSION__ < 201112
# if 2 < __GNUC__ + (8 <= __GNUC_MINOR__)
-# define _Noreturn __attribute__ ((__noreturn__))
+# define _Noreturn __attribute__((__noreturn__))
# else
# define _Noreturn
# endif
@@ -315,6 +396,23 @@
** Workarounds for compilers/systems.
*/
+#ifndef EPOCH_LOCAL
+# define EPOCH_LOCAL 0
+#endif
+#ifndef EPOCH_OFFSET
+# define EPOCH_OFFSET 0
+#endif
+#ifndef RESERVE_STD_EXT_IDS
+# define RESERVE_STD_EXT_IDS 0
+#endif
+
+/* If standard C identifiers with external linkage (e.g., localtime)
+ are reserved and are not already being renamed anyway, rename them
+ as if compiling with '-Dtime_tz=time_t'. */
+#if !defined time_tz && RESERVE_STD_EXT_IDS && USE_LTZ
+# define time_tz time_t
+#endif
+
/*
** Compile with -Dtime_tz=T to build the tz package with a private
** time_t type equivalent to T rather than the system-supplied time_t.
@@ -322,13 +420,24 @@
** (e.g., time_t wider than 'long', or unsigned time_t) even on
** typical platforms.
*/
-#ifdef time_tz
-# ifdef LOCALTIME_IMPLEMENTATION
+#if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
+# define TZ_TIME_T 1
+#else
+# define TZ_TIME_T 0
+#endif
+
+#if defined LOCALTIME_IMPLEMENTATION && TZ_TIME_T
static time_t sys_time(time_t *x) { return time(x); }
-# endif
+#endif
+
+#if TZ_TIME_T
typedef time_tz tz_time_t;
+# undef asctime
+# define asctime tz_asctime
+# undef asctime_r
+# define asctime_r tz_asctime_r
# undef ctime
# define ctime tz_ctime
# undef ctime_r
@@ -355,6 +464,8 @@
# define posix2time tz_posix2time
# undef posix2time_z
# define posix2time_z tz_posix2time_z
+# undef strftime
+# define strftime tz_strftime
# undef time
# define time tz_time
# undef time2posix
@@ -375,12 +486,36 @@
# define tzfree tz_tzfree
# undef tzset
# define tzset tz_tzset
-# undef tzsetwall
-# define tzsetwall tz_tzsetwall
+# if HAVE_STRFTIME_L
+# undef strftime_l
+# define strftime_l tz_strftime_l
+# endif
+# if HAVE_TZNAME
+# undef tzname
+# define tzname tz_tzname
+# endif
+# if USG_COMPAT
+# undef daylight
+# define daylight tz_daylight
+# undef timezone
+# define timezone tz_timezone
+# endif
+# if ALTZONE
+# undef altzone
+# define altzone tz_altzone
+# endif
+char *asctime(struct tm const *);
+char *asctime_r(struct tm const *restrict, char *restrict);
char *ctime(time_t const *);
char *ctime_r(time_t const *, char *);
-double difftime(time_t, time_t);
+double difftime(time_t, time_t) ATTRIBUTE_CONST;
+size_t strftime(char *restrict, size_t, char const *restrict,
+ struct tm const *restrict);
+# if HAVE_STRFTIME_L
+size_t strftime_l(char *restrict, size_t, char const *restrict,
+ struct tm const *restrict, locale_t);
+# endif
struct tm *gmtime(time_t const *);
struct tm *gmtime_r(time_t const *restrict, struct tm *restrict);
struct tm *localtime(time_t const *);
@@ -394,18 +529,26 @@
extern char *asctime_r(struct tm const *restrict, char *restrict);
#endif
-#if !HAVE_POSIX_DECLS
-# ifdef USG_COMPAT
-# ifndef timezone
-extern long timezone;
-# endif
-# ifndef daylight
-extern int daylight;
-# endif
+#ifndef HAVE_DECL_ENVIRON
+# if defined environ || defined __USE_GNU
+# define HAVE_DECL_ENVIRON 1
+# else
+# define HAVE_DECL_ENVIRON 0
# endif
#endif
-#if defined ALTZONE && !defined altzone
+#if !HAVE_DECL_ENVIRON
+extern char **environ;
+#endif
+
+#if 2 <= HAVE_TZNAME + (TZ_TIME_T || !HAVE_POSIX_DECLS)
+extern char *tzname[];
+#endif
+#if 2 <= USG_COMPAT + (TZ_TIME_T || !HAVE_POSIX_DECLS)
+extern long timezone;
+extern int daylight;
+#endif
+#if 2 <= ALTZONE + (TZ_TIME_T || !HAVE_POSIX_DECLS)
extern long altzone;
#endif
@@ -415,25 +558,22 @@
*/
#ifdef STD_INSPIRED
-# if !defined tzsetwall || defined time_tz
-void tzsetwall(void);
-# endif
-# if !defined offtime || defined time_tz
+# if TZ_TIME_T || !defined offtime
struct tm *offtime(time_t const *, long);
# endif
-# if !defined timegm || defined time_tz
+# if TZ_TIME_T || !defined timegm
time_t timegm(struct tm *);
# endif
-# if !defined timelocal || defined time_tz
+# if TZ_TIME_T || !defined timelocal
time_t timelocal(struct tm *);
# endif
-# if !defined timeoff || defined time_tz
+# if TZ_TIME_T || !defined timeoff
time_t timeoff(struct tm *, long);
# endif
-# if !defined time2posix || defined time_tz
+# if TZ_TIME_T || !defined time2posix
time_t time2posix(time_t);
# endif
-# if !defined posix2time || defined time_tz
+# if TZ_TIME_T || !defined posix2time
time_t posix2time(time_t);
# endif
#endif
@@ -467,10 +607,10 @@
timezone_t tzalloc(char const *);
void tzfree(timezone_t);
# ifdef STD_INSPIRED
-# if !defined posix2time_z || defined time_tz
+# if TZ_TIME_T || !defined posix2time_z
time_t posix2time_z(timezone_t, time_t) ATTRIBUTE_PURE;
# endif
-# if !defined time2posix_z || defined time_tz
+# if TZ_TIME_T || !defined time2posix_z
time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
# endif
# endif
@@ -480,22 +620,16 @@
** Finally, some convenience items.
*/
-#if __STDC_VERSION__ < 199901
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
# define true 1
# define false 0
# define bool int
-#else
-# include <stdbool.h>
#endif
-#ifndef TYPE_BIT
-#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
-#endif /* !defined TYPE_BIT */
-
-#ifndef TYPE_SIGNED
+#define TYPE_BIT(type) (sizeof(type) * CHAR_BIT)
#define TYPE_SIGNED(type) (((type) -1) < 0)
-#endif /* !defined TYPE_SIGNED */
-
#define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0)
/* Max and min values of the integer type T, of which only the bottom
@@ -507,11 +641,34 @@
#define MINVAL(t, b) \
((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
-/* The minimum and maximum finite time values. This assumes no padding. */
-static time_t const time_t_min = MINVAL(time_t, TYPE_BIT(time_t));
-static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t));
+/* The extreme time values, assuming no padding. */
+#define TIME_T_MIN_NO_PADDING MINVAL(time_t, TYPE_BIT(time_t))
+#define TIME_T_MAX_NO_PADDING MAXVAL(time_t, TYPE_BIT(time_t))
-#ifndef INT_STRLEN_MAXIMUM
+/* The extreme time values. These are macros, not constants, so that
+ any portability problems occur only when compiling .c files that use
+ the macros, which is safer for applications that need only zdump and zic.
+ This implementation assumes no padding if time_t is signed and
+ either the compiler lacks support for _Generic or time_t is not one
+ of the standard signed integer types. */
+#if HAVE_GENERIC
+# define TIME_T_MIN \
+ _Generic((time_t) 0, \
+ signed char: SCHAR_MIN, short: SHRT_MIN, \
+ int: INT_MIN, long: LONG_MIN, long long: LLONG_MIN, \
+ default: TIME_T_MIN_NO_PADDING)
+# define TIME_T_MAX \
+ (TYPE_SIGNED(time_t) \
+ ? _Generic((time_t) 0, \
+ signed char: SCHAR_MAX, short: SHRT_MAX, \
+ int: INT_MAX, long: LONG_MAX, long long: LLONG_MAX, \
+ default: TIME_T_MAX_NO_PADDING) \
+ : (time_t) -1)
+#else
+# define TIME_T_MIN TIME_T_MIN_NO_PADDING
+# define TIME_T_MAX TIME_T_MAX_NO_PADDING
+#endif
+
/*
** 302 / 1000 is log10(2.0) rounded up.
** Subtract one for the sign bit if the type is signed;
@@ -521,13 +678,12 @@
#define INT_STRLEN_MAXIMUM(type) \
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
1 + TYPE_SIGNED(type))
-#endif /* !defined INT_STRLEN_MAXIMUM */
/*
** INITIALIZE(x)
*/
-#ifdef lint
+#ifdef GCC_LINT
# define INITIALIZE(x) ((x) = 0)
#else
# define INITIALIZE(x)
@@ -537,19 +693,30 @@
# define UNINIT_TRAP 0
#endif
+#ifdef DEBUG
+# define UNREACHABLE() abort()
+#elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__)
+# define UNREACHABLE() __builtin_unreachable()
+#elif defined __has_builtin
+# if __has_builtin(__builtin_unreachable)
+# define UNREACHABLE() __builtin_unreachable()
+# endif
+#endif
+#ifndef UNREACHABLE
+# define UNREACHABLE() ((void) 0)
+#endif
+
/*
** For the benefit of GNU folk...
** '_(MSGID)' uses the current locale's message library string for MSGID.
** The default is to use gettext if available, and use MSGID otherwise.
*/
-#ifndef _
#if HAVE_GETTEXT
#define _(msgid) gettext(msgid)
#else /* !HAVE_GETTEXT */
#define _(msgid) msgid
#endif /* !HAVE_GETTEXT */
-#endif /* !defined _ */
#if !defined TZ_DOMAIN && defined HAVE_GETTEXT
# define TZ_DOMAIN "tz"
@@ -562,24 +729,64 @@
char *ctime_r(time_t const *, char *);
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
-#ifndef YEARSPERREPEAT
+/* Handy macros that are independent of tzfile implementation. */
+
+#define SECSPERMIN 60
+#define MINSPERHOUR 60
+#define HOURSPERDAY 24
+#define DAYSPERWEEK 7
+#define DAYSPERNYEAR 365
+#define DAYSPERLYEAR 366
+#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
+#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
+#define MONSPERYEAR 12
+
#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
-#endif /* !defined YEARSPERREPEAT */
+#define DAYSPERREPEAT ((int_fast32_t) 400 * 365 + 100 - 4 + 1)
+#define SECSPERREPEAT ((int_fast64_t) DAYSPERREPEAT * SECSPERDAY)
+#define AVGSECSPERYEAR (SECSPERREPEAT / YEARSPERREPEAT)
+
+#define TM_SUNDAY 0
+#define TM_MONDAY 1
+#define TM_TUESDAY 2
+#define TM_WEDNESDAY 3
+#define TM_THURSDAY 4
+#define TM_FRIDAY 5
+#define TM_SATURDAY 6
+
+#define TM_JANUARY 0
+#define TM_FEBRUARY 1
+#define TM_MARCH 2
+#define TM_APRIL 3
+#define TM_MAY 4
+#define TM_JUNE 5
+#define TM_JULY 6
+#define TM_AUGUST 7
+#define TM_SEPTEMBER 8
+#define TM_OCTOBER 9
+#define TM_NOVEMBER 10
+#define TM_DECEMBER 11
+
+#define TM_YEAR_BASE 1900
+#define TM_WDAY_BASE TM_MONDAY
+
+#define EPOCH_YEAR 1970
+#define EPOCH_WDAY TM_THURSDAY
+
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
/*
-** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
+** Since everything in isleap is modulo 400 (or a factor of 400), we know that
+** isleap(y) == isleap(y % 400)
+** and so
+** isleap(a + b) == isleap((a + b) % 400)
+** or
+** isleap(a + b) == isleap(a % 400 + b % 400)
+** This is true even if % means modulo rather than Fortran remainder
+** (which is allowed by C89 but not by C99 or later).
+** We use this to avoid addition overflow problems.
*/
-#ifndef AVGSECSPERYEAR
-#define AVGSECSPERYEAR 31556952L
-#endif /* !defined AVGSECSPERYEAR */
-
-#ifndef SECSPERREPEAT
-#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
-#endif /* !defined SECSPERREPEAT */
-
-#ifndef SECSPERREPEAT_BITS
-#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
-#endif /* !defined SECSPERREPEAT_BITS */
+#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
#endif /* !defined PRIVATE_H */
diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c
index 7c4be49..d04c5ba 100644
--- a/libc/tzcode/strftime.c
+++ b/libc/tzcode/strftime.c
@@ -1,4 +1,4 @@
-/* Convert a broken-down time stamp to a string. */
+/* Convert a broken-down timestamp to a string. */
/* Copyright 1989 The Regents of the University of California.
All rights reserved.
@@ -35,9 +35,13 @@
#include "private.h"
-#include "tzfile.h"
-#include "fcntl.h"
-#include "locale.h"
+#include <fcntl.h>
+#include <locale.h>
+#include <stdio.h>
+
+#ifndef DEPRECATE_TWO_DIGIT_YEARS
+# define DEPRECATE_TWO_DIGIT_YEARS false
+#endif
#if defined(__BIONIC__)
@@ -45,6 +49,7 @@
#if defined(__LP64__)
#define time64_t time_t
#define mktime64 mktime
+#define localtime64_r localtime_r
#else
#include <time64.h>
#endif
@@ -88,7 +93,7 @@
/*
** x_fmt
- ** C99 requires this format.
+ ** C99 and later require this format.
** Using just numbers (as here) makes Quakers happier;
** it's also compatible with SVR4.
*/
@@ -96,7 +101,7 @@
/*
** c_fmt
- ** C99 requires this format.
+ ** C99 and later require this format.
** Previously this code used "%D %X", but we now conform to C99.
** Note that
** "%a %b %d %H:%M:%S %Y"
@@ -114,25 +119,18 @@
"%a %b %e %H:%M:%S %Z %Y"
};
+enum warn { IN_NONE, IN_SOME, IN_THIS, IN_ALL };
+
static char * _add(const char *, char *, const char *, int);
static char * _conv(int, const char *, char *, const char *);
static char * _fmt(const char *, const struct tm *, char *, const char *,
- int *);
+ enum warn *);
static char * _yconv(int, int, bool, bool, char *, const char *, int);
-#if !HAVE_POSIX_DECLS
-extern char * tzname[];
-#endif
-
#ifndef YEAR_2000_NAME
#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
#endif /* !defined YEAR_2000_NAME */
-#define IN_NONE 0
-#define IN_SOME 1
-#define IN_THIS 2
-#define IN_ALL 3
-
#if HAVE_STRFTIME_L
size_t
strftime_l(char *s, size_t maxsize, char const *format, struct tm const *t,
@@ -149,18 +147,19 @@
strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
{
char * p;
- int warn;
+ int saved_errno = errno;
+ enum warn warn = IN_NONE;
tzset();
- warn = IN_NONE;
- p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
-#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
- if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
+ p = _fmt(format, t, s, s + maxsize, &warn);
+ if (!p) {
+ errno = EOVERFLOW;
+ return 0;
+ }
+ if (DEPRECATE_TWO_DIGIT_YEARS
+ && warn != IN_NONE && getenv(YEAR_2000_NAME)) {
fprintf(stderr, "\n");
- if (format == NULL)
- fprintf(stderr, "NULL strftime format ");
- else fprintf(stderr, "strftime format \"%s\" ",
- format);
+ fprintf(stderr, "strftime format \"%s\" ", format);
fprintf(stderr, "yields only two digits of years in ");
if (warn == IN_SOME)
fprintf(stderr, "some locales");
@@ -169,10 +168,12 @@
else fprintf(stderr, "all locales");
fprintf(stderr, "\n");
}
-#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
- if (p == s + maxsize)
+ if (p == s + maxsize) {
+ errno = ERANGE;
return 0;
+ }
*p = '\0';
+ errno = saved_errno;
return p - s;
}
@@ -189,9 +190,32 @@
return normal;
}
+// Android-added: fall back mechanism when TM_ZONE is not initialized.
+#ifdef TM_ZONE
+static const char* _safe_tm_zone(const struct tm* tm) {
+ const char* zone = tm->TM_ZONE;
+ if (!zone || !*zone) {
+ // "The value of tm_isdst shall be positive if Daylight Savings Time is
+ // in effect, 0 if Daylight Savings Time is not in effect, and negative
+ // if the information is not available."
+ if (tm->tm_isdst == 0) {
+ zone = tzname[0];
+ } else if (tm->tm_isdst > 0) {
+ zone = tzname[1];
+ }
+
+ // "Replaced by the timezone name or abbreviation, or by no bytes if no
+ // timezone information exists."
+ if (!zone || !*zone) zone = "";
+ }
+
+ return zone;
+}
+#endif
+
static char *
_fmt(const char *format, const struct tm *t, char *pt,
- const char *ptlim, int *warnp)
+ const char *ptlim, enum warn *warnp)
{
for ( ; *format; ++format) {
if (*format == '%') {
@@ -239,7 +263,7 @@
continue;
case 'c':
{
- int warn2 = IN_SOME;
+ enum warn warn2 = IN_SOME;
pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
@@ -257,12 +281,12 @@
case 'E':
case 'O':
/*
- ** C99 locale modifiers.
+ ** Locale modifiers of C99 and later.
** The sequences
** %Ec %EC %Ex %EX %Ey %EY
** %Od %oe %OH %OI %Om %OM
** %OS %Ou %OU %OV %Ow %OW %Oy
- ** are supposed to provide alternate
+ ** are supposed to provide alternative
** representations.
*/
goto label;
@@ -356,11 +380,17 @@
tm = *t;
mkt = mktime64(&tm);
- if (TYPE_SIGNED(time64_t))
- snprintf(buf, sizeof(buf), "%"PRIdMAX,
- (intmax_t) mkt);
- else snprintf(buf, sizeof(buf), "%"PRIuMAX,
- (uintmax_t) mkt);
+ /* There is no portable, definitive
+ test for whether whether mktime
+ succeeded, so treat (time_t) -1 as
+ the success that it might be. */
+ if (TYPE_SIGNED(time64_t)) {
+ intmax_t n = mkt;
+ sprintf(buf, "%"PRIdMAX, n);
+ } else {
+ uintmax_t n = mkt;
+ sprintf(buf, "%"PRIuMAX, n);
+ }
pt = _add(buf, pt, ptlim, modifier);
}
continue;
@@ -392,7 +422,7 @@
** (01-53)."
** (ado, 1993-05-24)
**
-** From <http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html> by Markus Kuhn:
+** From <https://www.cl.cam.ac.uk/~mgk25/iso-time.html> by Markus Kuhn:
** "Week 01 of a year is per definition the first week which has the
** Thursday in this year, which is equivalent to the week which contains
** the fourth day of January. In other words, the first week of a new year
@@ -494,7 +524,7 @@
continue;
case 'x':
{
- int warn2 = IN_SOME;
+ enum warn warn2 = IN_SOME;
pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
@@ -517,45 +547,32 @@
case 'Z':
#ifdef TM_ZONE
// BEGIN: Android-changed.
- {
- const char* zone = t->TM_ZONE;
- if (!zone || !*zone) {
- // "The value of tm_isdst shall be positive if Daylight Savings Time is
- // in effect, 0 if Daylight Savings Time is not in effect, and negative
- // if the information is not available."
- if (t->tm_isdst == 0) zone = tzname[0];
- else if (t->tm_isdst > 0) zone = tzname[1];
-
- // "Replaced by the timezone name or abbreviation, or by no bytes if no
- // timezone information exists."
- if (!zone || !*zone) zone = "";
- }
- pt = _add(zone, pt, ptlim, modifier);
- }
+ pt = _add(_safe_tm_zone(t), pt, ptlim, modifier);
// END: Android-changed.
-#else
+#elif HAVE_TZNAME
if (t->tm_isdst >= 0)
pt = _add(tzname[t->tm_isdst != 0],
pt, ptlim);
#endif
/*
- ** C99 says that %Z must be replaced by the
- ** empty string if the time zone is not
+ ** C99 and later say that %Z must be
+ ** replaced by the empty string if the
+ ** time zone abbreviation is not
** determinable.
*/
continue;
case 'z':
+#if defined TM_GMTOFF || USG_COMPAT || ALTZONE
{
long diff;
char const * sign;
+ bool negative;
- if (t->tm_isdst < 0)
- continue;
-#ifdef TM_GMTOFF
+# ifdef TM_GMTOFF
diff = t->TM_GMTOFF;
-#else /* !defined TM_GMTOFF */
+# else
/*
- ** C99 says that the UT offset must
+ ** C99 and later say that the UT offset must
** be computed by looking only at
** tm_isdst. This requirement is
** incorrect, since it means the code
@@ -563,30 +580,48 @@
** altzone and timezone), and the
** magic might not have the correct
** offset. Doing things correctly is
- ** tricky and requires disobeying C99;
+ ** tricky and requires disobeying the standard;
** see GNU C strftime for details.
** For now, punt and conform to the
** standard, even though it's incorrect.
**
- ** C99 says that %z must be replaced by the
- ** empty string if the time zone is not
+ ** C99 and later say that %z must be replaced by
+ ** the empty string if the time zone is not
** determinable, so output nothing if the
** appropriate variables are not available.
*/
+ if (t->tm_isdst < 0)
+ continue;
if (t->tm_isdst == 0)
-#ifdef USG_COMPAT
+# if USG_COMPAT
diff = -timezone;
-#else /* !defined USG_COMPAT */
+# else
continue;
-#endif /* !defined USG_COMPAT */
+# endif
else
-#ifdef ALTZONE
+# if ALTZONE
diff = -altzone;
-#else /* !defined ALTZONE */
+# else
continue;
-#endif /* !defined ALTZONE */
-#endif /* !defined TM_GMTOFF */
- if (diff < 0) {
+# endif
+# endif
+ negative = diff < 0;
+ if (diff == 0) {
+#ifdef TM_ZONE
+ // Android-changed: do not use TM_ZONE as it is as it may be null.
+ {
+ const char* zone = _safe_tm_zone(t);
+ negative = zone[0] == '-';
+ }
+#else
+ negative = t->tm_isdst < 0;
+# if HAVE_TZNAME
+ if (tzname[t->tm_isdst != 0][0] == '-')
+ negative = true;
+# endif
+#endif
+ }
+ if (negative) {
sign = "-";
diff = -diff;
} else sign = "+";
@@ -596,6 +631,7 @@
(diff % MINSPERHOUR);
pt = _conv(diff, getformat(modifier, "04", " 4", " ", "04"), pt, ptlim);
}
+#endif
continue;
case '+':
pt = _fmt(Locale->date_fmt, t, pt, ptlim,
diff --git a/libc/tzcode/tzfile.h b/libc/tzcode/tzfile.h
index ebecd68..c5f9967 100644
--- a/libc/tzcode/tzfile.h
+++ b/libc/tzcode/tzfile.h
@@ -1,3 +1,5 @@
+/* Layout and location of TZif files. */
+
#ifndef TZFILE_H
#define TZFILE_H
@@ -20,17 +22,20 @@
*/
#ifndef TZDIR
-#define TZDIR "/usr/local/etc/zoneinfo" /* Time zone object file directory */
+#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
#endif /* !defined TZDIR */
#ifndef TZDEFAULT
-#define TZDEFAULT "localtime"
+#define TZDEFAULT "/etc/localtime"
#endif /* !defined TZDEFAULT */
#ifndef TZDEFRULES
#define TZDEFRULES "posixrules"
#endif /* !defined TZDEFRULES */
+
+/* See Internet RFC 8536 for more details about the following format. */
+
/*
** Each file begins with. . .
*/
@@ -39,9 +44,9 @@
struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */
- char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
+ char tzh_version[1]; /* '\0' or '2'-'4' as of 2021 */
char tzh_reserved[15]; /* reserved; must be zero */
- char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
+ char tzh_ttisutcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
char tzh_leapcnt[4]; /* coded number of leap seconds */
char tzh_timecnt[4]; /* coded number of transition times */
@@ -64,14 +69,15 @@
** one (char [4]) total correction after above
** tzh_ttisstdcnt (char)s indexed by type; if 1, transition
** time is standard time, if 0,
-** transition time is wall clock time
-** if absent, transition times are
-** assumed to be wall clock time
-** tzh_ttisgmtcnt (char)s indexed by type; if 1, transition
-** time is UT, if 0,
-** transition time is local time
-** if absent, transition times are
+** transition time is local (wall clock)
+** time; if absent, transition times are
** assumed to be local time
+** tzh_ttisutcnt (char)s indexed by type; if 1, transition
+** time is UT, if 0, transition time is
+** local time; if absent, transition
+** times are assumed to be local time.
+** When this is 1, the corresponding
+** std/wall indicator must also be 1.
*/
/*
diff --git a/libc/upstream-freebsd/lib/libc/string/bcopy.c b/libc/upstream-freebsd/lib/libc/string/bcopy.c
new file mode 100644
index 0000000..84715d0
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/string/bcopy.c
@@ -0,0 +1,137 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bcopy.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+typedef intptr_t word; /* "word" used for optimal copy speed */
+
+#define wsize sizeof(word)
+#define wmask (wsize - 1)
+
+/*
+ * Copy a block of memory, handling overlap.
+ * This is the routine that actually implements
+ * (the portable versions of) bcopy, memcpy, and memmove.
+ */
+#if defined(MEMCOPY) || defined(MEMMOVE)
+#include <string.h>
+
+void *
+#ifdef MEMCOPY
+memcpy
+#else
+memmove
+#endif
+(void *dst0, const void *src0, size_t length)
+#else
+#include <strings.h>
+
+void
+bcopy(const void *src0, void *dst0, size_t length)
+#endif
+{
+ char *dst = dst0;
+ const char *src = src0;
+ size_t t;
+
+ if (length == 0 || dst == src) /* nothing to do */
+ goto done;
+
+ /*
+ * Macros: loop-t-times; and loop-t-times, t>0
+ */
+#define TLOOP(s) if (t) TLOOP1(s)
+#define TLOOP1(s) do { s; } while (--t)
+
+ if ((unsigned long)dst < (unsigned long)src) {
+ /*
+ * Copy forward.
+ */
+ t = (uintptr_t)src; /* only need low bits */
+ if ((t | (uintptr_t)dst) & wmask) {
+ /*
+ * Try to align operands. This cannot be done
+ * unless the low bits match.
+ */
+ if ((t ^ (uintptr_t)dst) & wmask || length < wsize)
+ t = length;
+ else
+ t = wsize - (t & wmask);
+ length -= t;
+ TLOOP1(*dst++ = *src++);
+ }
+ /*
+ * Copy whole words, then mop up any trailing bytes.
+ */
+ t = length / wsize;
+ TLOOP(*(word *)(void *)dst = *(const word *)(const void *)src;
+ src += wsize; dst += wsize);
+ t = length & wmask;
+ TLOOP(*dst++ = *src++);
+ } else {
+ /*
+ * Copy backwards. Otherwise essentially the same.
+ * Alignment works as before, except that it takes
+ * (t&wmask) bytes to align, not wsize-(t&wmask).
+ */
+ src += length;
+ dst += length;
+ t = (uintptr_t)src;
+ if ((t | (uintptr_t)dst) & wmask) {
+ if ((t ^ (uintptr_t)dst) & wmask || length <= wsize)
+ t = length;
+ else
+ t &= wmask;
+ length -= t;
+ TLOOP1(*--dst = *--src);
+ }
+ t = length / wsize;
+ TLOOP(src -= wsize; dst -= wsize;
+ *(word *)(void *)dst = *(const word *)(const void *)src);
+ t = length & wmask;
+ TLOOP(*--dst = *--src);
+ }
+done:
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ return (dst0);
+#else
+ return;
+#endif
+}
diff --git a/libc/upstream-freebsd/lib/libc/string/memcmp.c b/libc/upstream-freebsd/lib/libc/string/memcmp.c
new file mode 100644
index 0000000..c8d5d92
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/string/memcmp.c
@@ -0,0 +1,58 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)memcmp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+/*
+ * Compare memory regions.
+ */
+int
+memcmp(const void *s1, const void *s2, size_t n)
+{
+ if (n != 0) {
+ const unsigned char *p1 = s1, *p2 = s2;
+
+ do {
+ if (*p1++ != *p2++)
+ return (*--p1 - *--p2);
+ } while (--n != 0);
+ }
+ return (0);
+}
diff --git a/libc/upstream-freebsd/lib/libc/string/memcpy.c b/libc/upstream-freebsd/lib/libc/string/memcpy.c
new file mode 100644
index 0000000..ed03856
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/string/memcpy.c
@@ -0,0 +1,5 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define MEMCOPY
+#include "bcopy.c"
diff --git a/libc/upstream-freebsd/lib/libc/string/memmove.c b/libc/upstream-freebsd/lib/libc/string/memmove.c
new file mode 100644
index 0000000..05cf75a
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/string/memmove.c
@@ -0,0 +1,5 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define MEMMOVE
+#include "bcopy.c"
diff --git a/libc/upstream-freebsd/lib/libc/string/memset.c b/libc/upstream-freebsd/lib/libc/string/memset.c
new file mode 100644
index 0000000..e2d4027
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/string/memset.c
@@ -0,0 +1,133 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Hibler and Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)memset.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <limits.h>
+
+#define wsize sizeof(u_long)
+#define wmask (wsize - 1)
+
+#ifdef BZERO
+#include <strings.h>
+
+#define RETURN return
+#define VAL 0
+#define WIDEVAL 0
+
+void
+bzero(void *dst0, size_t length)
+#else
+#include <string.h>
+
+#define RETURN return (dst0)
+#define VAL c0
+#define WIDEVAL c
+
+void *
+memset(void *dst0, int c0, size_t length)
+#endif
+{
+ size_t t;
+#ifndef BZERO
+ u_long c;
+#endif
+ u_char *dst;
+
+ dst = dst0;
+ /*
+ * If not enough words, just fill bytes. A length >= 2 words
+ * guarantees that at least one of them is `complete' after
+ * any necessary alignment. For instance:
+ *
+ * |-----------|-----------|-----------|
+ * |00|01|02|03|04|05|06|07|08|09|0A|00|
+ * ^---------------------^
+ * dst dst+length-1
+ *
+ * but we use a minimum of 3 here since the overhead of the code
+ * to do word writes is substantial.
+ *
+ * TODO: This threshold might not be sensible for 64-bit u_long.
+ * We should benchmark and revisit this decision.
+ */
+ if (length < 3 * wsize) {
+ while (length != 0) {
+ *dst++ = VAL;
+ --length;
+ }
+ RETURN;
+ }
+
+#ifndef BZERO
+ if ((c = (u_char)c0) != 0) { /* Fill the word. */
+ c = (c << 8) | c; /* u_long is 16 bits. */
+#if ULONG_MAX > 0xffff
+ c = (c << 16) | c; /* u_long is 32 bits. */
+#endif
+#if ULONG_MAX > 0xffffffff
+ c = (c << 32) | c; /* u_long is 64 bits. */
+#endif
+ }
+#endif
+ /* Align destination by filling in bytes. */
+ if ((t = (long)dst & wmask) != 0) {
+ t = wsize - t;
+ length -= t;
+ do {
+ *dst++ = VAL;
+ } while (--t != 0);
+ }
+
+ /* Fill words. Length was >= 2*words so we know t >= 1 here. */
+ t = length / wsize;
+ do {
+ *(u_long *)(void *)dst = WIDEVAL;
+ dst += wsize;
+ } while (--t != 0);
+
+ /* Mop up trailing bytes, if any. */
+ t = length & wmask;
+ if (t != 0)
+ do {
+ *dst++ = VAL;
+ } while (--t != 0);
+ RETURN;
+}
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/misc.c b/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
index 79a3104..fef51a9 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
@@ -41,7 +41,7 @@
#endif
#ifdef MULTIPLE_THREADS
-extern void *__dtoa_locks[];
+static void *__dtoa_locks[] = { NULL, NULL };
#endif
Bigint *
diff --git a/libc/upstream-openbsd/lib/libc/gen/alarm.c b/libc/upstream-openbsd/lib/libc/gen/alarm.c
index f15dd15..ac17f9d 100644
--- a/libc/upstream-openbsd/lib/libc/gen/alarm.c
+++ b/libc/upstream-openbsd/lib/libc/gen/alarm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: alarm.c,v 1.9 2019/06/28 13:32:41 deraadt Exp $ */
+/* $OpenBSD: alarm.c,v 1.10 2021/06/24 22:43:31 cheloha Exp $ */
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
@@ -34,13 +34,12 @@
unsigned int
alarm(unsigned int secs)
{
- struct itimerval it, oitv;
- struct itimerval *itp = ⁢
+ struct itimerval itv, oitv;
- timerclear(&itp->it_interval);
- itp->it_value.tv_sec = secs;
- itp->it_value.tv_usec = 0;
- if (setitimer(ITIMER_REAL, itp, &oitv) == -1)
+ timerclear(&itv.it_interval);
+ itv.it_value.tv_sec = secs;
+ itv.it_value.tv_usec = 0;
+ if (setitimer(ITIMER_REAL, &itv, &oitv) == -1)
return ((unsigned int) -1);
if (oitv.it_value.tv_usec)
oitv.it_value.tv_sec++;
diff --git a/libc/upstream-openbsd/lib/libc/gen/charclass.h b/libc/upstream-openbsd/lib/libc/gen/charclass.h
index 073baf6..1d1ec07 100644
--- a/libc/upstream-openbsd/lib/libc/gen/charclass.h
+++ b/libc/upstream-openbsd/lib/libc/gen/charclass.h
@@ -1,13 +1,13 @@
/*
* Public domain, 2008, Todd C. Miller <millert@openbsd.org>
*
- * $OpenBSD: charclass.h,v 1.2 2019/01/25 00:19:25 millert Exp $
+ * $OpenBSD: charclass.h,v 1.3 2020/10/13 04:42:28 guenther Exp $
*/
/*
* POSIX character class support for fnmatch() and glob().
*/
-static struct cclass {
+static const struct cclass {
const char *name;
int (*isctype)(int);
} cclasses[] = {
diff --git a/libc/upstream-openbsd/lib/libc/gen/daemon.c b/libc/upstream-openbsd/lib/libc/gen/daemon.c
index 79f4264..b84cb4f 100644
--- a/libc/upstream-openbsd/lib/libc/gen/daemon.c
+++ b/libc/upstream-openbsd/lib/libc/gen/daemon.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: daemon.c,v 1.7 2010/07/27 22:29:09 marco Exp $ */
+/* $OpenBSD: daemon.c,v 1.8 2021/10/24 21:24:20 deraadt Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -53,7 +53,7 @@
if (!nochdir)
(void)chdir("/");
- if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+ if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR)) != -1) {
(void)dup2(fd, STDIN_FILENO);
(void)dup2(fd, STDOUT_FILENO);
(void)dup2(fd, STDERR_FILENO);
diff --git a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
index d7afd5f..ff6b26e 100644
--- a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
+++ b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fnmatch.c,v 1.22 2020/03/13 03:25:45 djm Exp $ */
+/* $OpenBSD: fnmatch.c,v 1.23 2020/10/13 04:42:28 guenther Exp $ */
/* Copyright (c) 2011, VMware, Inc.
* All rights reserved.
@@ -100,7 +100,7 @@
{
const char * const mismatch = pattern;
const char *colon;
- struct cclass *cc;
+ const struct cclass *cc;
int rval = RANGE_NOMATCH;
size_t len;
diff --git a/libc/upstream-openbsd/lib/libc/gen/ftok.c b/libc/upstream-openbsd/lib/libc/gen/ftok.c
index ea1edf1..9edcd30 100644
--- a/libc/upstream-openbsd/lib/libc/gen/ftok.c
+++ b/libc/upstream-openbsd/lib/libc/gen/ftok.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ftok.c,v 1.9 2019/06/28 13:32:41 deraadt Exp $ */
+/* $OpenBSD: ftok.c,v 1.10 2022/04/13 16:23:53 millert Exp $ */
/*
* Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
* All rights reserved.
@@ -32,11 +32,12 @@
key_t
ftok(const char *path, int id)
{
+ const unsigned int u_id = id;
struct stat st;
if (stat(path, &st) == -1)
return (key_t)-1;
return (key_t)
- ((id & 0xff) << 24 | (st.st_dev & 0xff) << 16 | (st.st_ino & 0xffff));
+ ((u_id & 0xff) << 24 | (st.st_dev & 0xff) << 16 | (st.st_ino & 0xffff));
}
diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstol.h b/libc/upstream-openbsd/lib/libc/locale/_wcstol.h
deleted file mode 100644
index 1b60a3a..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/_wcstol.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* $OpenBSD: _wcstol.h,v 1.3 2015/10/01 02:32:07 guenther Exp $ */
-/* $NetBSD: _wcstol.h,v 1.2 2003/08/07 16:43:03 agc Exp $ */
-
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * Original version ID:
- * @(#)strtol.c 8.1 (Berkeley) 6/4/93
- * NetBSD: wcstol.c,v 1.1 2001/09/27 16:30:36 yamt Exp
- * Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstol.c,v 1.2 2001/09/21 16:11:41 yamt Exp
- */
-
-/*
- * function template for wcstol, wcstoll and wcstoimax.
- *
- * parameters:
- * FUNCNAME : function name
- * int_type : return type
- * MIN_VALUE : lower limit of the return type
- * MAX_VALUE : upper limit of the return type
- */
-
-int_type
-FUNCNAME(const wchar_t *nptr, wchar_t **endptr, int base)
-{
- const wchar_t *s;
- int_type acc, cutoff;
- wint_t wc;
- int i;
- int neg, any, cutlim;
-
- /* check base value */
- if (base && (base < 2 || base > 36)) {
- errno = EINVAL;
- return 0;
- }
-
- /*
- * Skip white space and pick up leading +/- sign if any.
- * If base is 0, allow 0x for hex and 0 for octal, else
- * assume decimal; if base is already 16, allow 0x.
- */
- s = nptr;
- do {
- wc = (wchar_t) *s++;
- } while (iswspace(wc));
- if (wc == L'-') {
- neg = 1;
- wc = *s++;
- } else {
- neg = 0;
- if (wc == L'+')
- wc = *s++;
- }
- if ((base == 0 || base == 16) &&
- wc == L'0' && (*s == L'x' || *s == L'X')) {
- wc = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = wc == L'0' ? 8 : 10;
-
- /*
- * See strtol for comments as to the logic used.
- */
- cutoff = neg ? MIN_VALUE : MAX_VALUE;
- cutlim = (int)(cutoff % base);
- cutoff /= base;
- if (neg) {
- if (cutlim > 0) {
- cutlim -= base;
- cutoff += 1;
- }
- cutlim = -cutlim;
- }
- for (acc = 0, any = 0;; wc = (wchar_t) *s++) {
- i = wctoint(wc);
- if (i == -1)
- break;
- if (i >= base)
- break;
- if (any < 0)
- continue;
- if (neg) {
- if (acc < cutoff || (acc == cutoff && i > cutlim)) {
- any = -1;
- acc = MIN_VALUE;
- errno = ERANGE;
- } else {
- any = 1;
- acc *= base;
- acc -= i;
- }
- } else {
- if (acc > cutoff || (acc == cutoff && i > cutlim)) {
- any = -1;
- acc = MAX_VALUE;
- errno = ERANGE;
- } else {
- any = 1;
- acc *= base;
- acc += i;
- }
- }
- }
- if (endptr != 0)
- *endptr = (wchar_t *)(any ? s - 1 : nptr);
- return (acc);
-}
-DEF_STRONG(FUNCNAME);
diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h b/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h
deleted file mode 100644
index 159b22b..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* $OpenBSD: _wcstoul.h,v 1.3 2015/10/01 02:32:07 guenther Exp $ */
-/* $NetBSD: _wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp $ */
-
-/*
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * Original version ID:
- * @(#)strtoul.c 8.1 (Berkeley) 6/4/93
- * Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstoul.c,v 1.2 2001/09/21 16:11:41 yamt Exp
- * NetBSD: wcstoul.c,v 1.1 2001/09/27 16:30:37 yamt Exp
- */
-
-/*
- * function template for wcstoul, wcstoull and wcstoumax.
- *
- * parameters:
- * FUNCNAME : function name
- * uint_type : return type
- * MAX_VALUE : upper limit of the return type
- */
-
-uint_type
-FUNCNAME(const wchar_t *nptr, wchar_t **endptr, int base)
-{
- const wchar_t *s;
- uint_type acc, cutoff;
- wint_t wc;
- int i;
- int neg, any, cutlim;
-
- if (base && (base < 2 || base > 36)) {
- errno = EINVAL;
- return 0;
- }
-
- /*
- * Skip white space and pick up leading +/- sign if any.
- * If base is 0, allow 0x for hex and 0 for octal, else
- * assume decimal; if base is already 16, allow 0x.
- */
- s = nptr;
- do {
- wc = (wchar_t) *s++;
- } while (iswspace(wc));
- if (wc == L'-') {
- neg = 1;
- wc = *s++;
- } else {
- neg = 0;
- if (wc == L'+')
- wc = *s++;
- }
- if ((base == 0 || base == 16) &&
- wc == L'0' && (*s == L'x' || *s == L'X')) {
- wc = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = wc == L'0' ? 8 : 10;
-
- /*
- * See strtoul for comments as to the logic used.
- */
- cutoff = MAX_VALUE / (uint_type)base;
- cutlim = (int)(MAX_VALUE % (uint_type)base);
- for (acc = 0, any = 0;; wc = (wchar_t) *s++) {
- i = wctoint(wc);
- if (i == (wint_t)-1)
- break;
- if (i >= base)
- break;
- if (any < 0)
- continue;
- if (acc > cutoff || (acc == cutoff && i > cutlim)) {
- any = -1;
- acc = MAX_VALUE;
- errno = ERANGE;
- } else {
- any = 1;
- acc *= (uint_type)base;
- acc += i;
- }
- }
- if (neg && any > 0)
- acc = -acc;
- if (endptr != 0)
- *endptr = (wchar_t *)(any ? s - 1 : nptr);
- return (acc);
-}
-DEF_STRONG(FUNCNAME);
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoimax.c b/libc/upstream-openbsd/lib/libc/locale/wcstoimax.c
deleted file mode 100644
index d46a7c7..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wcstoimax.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* $OpenBSD: wcstoimax.c,v 1.1 2009/01/13 18:13:51 kettenis Exp $ */
-/* $NetBSD: wcstol.c,v 1.2 2003/03/11 09:21:23 tshiozak Exp $ */
-
-#include <ctype.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "wctoint.h"
-
-#define FUNCNAME wcstoimax
-typedef intmax_t int_type;
-#define MIN_VALUE INTMAX_MIN
-#define MAX_VALUE INTMAX_MAX
-
-#include "_wcstol.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstol.c b/libc/upstream-openbsd/lib/libc/locale/wcstol.c
deleted file mode 100644
index 03395a0..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wcstol.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $OpenBSD: wcstol.c,v 1.2 2005/08/08 08:05:35 espie Exp $ */
-/* $NetBSD: wcstol.c,v 1.2 2003/03/11 09:21:23 tshiozak Exp $ */
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "wctoint.h"
-
-#define FUNCNAME wcstol
-typedef long int_type;
-#define MIN_VALUE LONG_MIN
-#define MAX_VALUE LONG_MAX
-
-#include "_wcstol.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoll.c b/libc/upstream-openbsd/lib/libc/locale/wcstoll.c
deleted file mode 100644
index 926db70..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wcstoll.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $OpenBSD: wcstoll.c,v 1.2 2005/08/08 08:05:35 espie Exp $ */
-/* $NetBSD: wcstoll.c,v 1.1 2003/03/11 09:21:23 tshiozak Exp $ */
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "wctoint.h"
-
-#define FUNCNAME wcstoll
-typedef long long int int_type;
-#define MIN_VALUE LLONG_MIN
-#define MAX_VALUE LLONG_MAX
-
-#include "_wcstol.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoul.c b/libc/upstream-openbsd/lib/libc/locale/wcstoul.c
deleted file mode 100644
index e863862..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wcstoul.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $OpenBSD: wcstoul.c,v 1.2 2005/08/08 08:05:35 espie Exp $ */
-/* $NetBSD: wcstoul.c,v 1.2 2003/03/11 09:21:24 tshiozak Exp $ */
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "wctoint.h"
-
-#define FUNCNAME wcstoul
-typedef unsigned long uint_type;
-#define MAX_VALUE ULONG_MAX
-
-#include "_wcstoul.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoull.c b/libc/upstream-openbsd/lib/libc/locale/wcstoull.c
deleted file mode 100644
index 6671c37..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wcstoull.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $OpenBSD: wcstoull.c,v 1.2 2005/08/08 08:05:35 espie Exp $ */
-/* $NetBSD: wcstoull.c,v 1.1 2003/03/11 09:21:24 tshiozak Exp $ */
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "wctoint.h"
-
-#define FUNCNAME wcstoull
-typedef unsigned long long int uint_type;
-#define MAX_VALUE ULLONG_MAX
-
-#include "_wcstoul.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoumax.c b/libc/upstream-openbsd/lib/libc/locale/wcstoumax.c
deleted file mode 100644
index ccd4713..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wcstoumax.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $OpenBSD: wcstoumax.c,v 1.1 2009/01/13 18:13:51 kettenis Exp $ */
-/* $NetBSD: wcstoul.c,v 1.2 2003/03/11 09:21:24 tshiozak Exp $ */
-
-#include <ctype.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "wctoint.h"
-
-#define FUNCNAME wcstoumax
-typedef uintmax_t uint_type;
-#define MAX_VALUE UINTMAX_MAX
-
-#include "_wcstoul.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wctoint.h b/libc/upstream-openbsd/lib/libc/locale/wctoint.h
deleted file mode 100644
index ea50c5a..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wctoint.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* $OpenBSD: wctoint.h,v 1.2 2015/09/13 11:38:08 guenther Exp $ */
-/* $NetBSD: __wctoint.h,v 1.1 2001/09/28 11:25:37 yamt Exp $ */
-
-/*-
- * Copyright (c)2001 Citrus Project,
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/__wctoint.h,v 1.1 2001/09/21 13:52:32 yamt Exp $
- */
-
-
-inline static int
-wctoint(wchar_t wc)
-{
- int n;
-
- switch (wc) {
- case L'0': n = 0; break;
- case L'1': n = 1; break;
- case L'2': n = 2; break;
- case L'3': n = 3; break;
- case L'4': n = 4; break;
- case L'5': n = 5; break;
- case L'6': n = 6; break;
- case L'7': n = 7; break;
- case L'8': n = 8; break;
- case L'9': n = 9; break;
- case L'A': case L'a': n = 10; break;
- case L'B': case L'b': n = 11; break;
- case L'C': case L'c': n = 12; break;
- case L'D': case L'd': n = 13; break;
- case L'E': case L'e': n = 14; break;
- case L'F': case L'f': n = 15; break;
- case L'G': case L'g': n = 16; break;
- case L'H': case L'h': n = 17; break;
- case L'I': case L'i': n = 18; break;
- case L'J': case L'j': n = 19; break;
- case L'K': case L'k': n = 20; break;
- case L'L': case L'l': n = 21; break;
- case L'M': case L'm': n = 22; break;
- case L'N': case L'n': n = 23; break;
- case L'O': case L'o': n = 24; break;
- case L'P': case L'p': n = 25; break;
- case L'Q': case L'q': n = 26; break;
- case L'R': case L'r': n = 27; break;
- case L'S': case L's': n = 28; break;
- case L'T': case L't': n = 29; break;
- case L'U': case L'u': n = 30; break;
- case L'V': case L'v': n = 31; break;
- case L'W': case L'w': n = 32; break;
- case L'X': case L'x': n = 33; break;
- case L'Y': case L'y': n = 34; break;
- case L'Z': case L'z': n = 35; break;
- default: n = -1; break; /* error */
- }
-
- return n;
-}
diff --git a/libc/upstream-openbsd/lib/libc/net/base64.c b/libc/upstream-openbsd/lib/libc/net/base64.c
index e90696d..f36c11a 100644
--- a/libc/upstream-openbsd/lib/libc/net/base64.c
+++ b/libc/upstream-openbsd/lib/libc/net/base64.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: base64.c,v 1.8 2015/01/16 16:48:51 deraadt Exp $ */
+/* $OpenBSD: base64.c,v 1.15 2021/10/25 14:41:09 jca Exp $ */
/*
* Copyright (c) 1996 by Internet Software Consortium.
@@ -46,11 +46,9 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <arpa/nameser.h>
#include <ctype.h>
#include <resolv.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -107,9 +105,9 @@
end of the data is performed using the '=' character.
Since all base64 input is an integral number of octets, only the
- -------------------------------------------------
+ -------------------------------------------------
following cases can arise:
-
+
(1) the final quantum of encoding input is an integral
multiple of 24 bits; here, the final unit of encoded
output will be an integral multiple of 4 characters
@@ -123,15 +121,12 @@
*/
int
-b64_ntop(src, srclength, target, targsize)
- u_char const *src;
- size_t srclength;
- char *target;
- size_t targsize;
+b64_ntop(unsigned char const *src, size_t srclength, char *target,
+ size_t targsize)
{
size_t datalength = 0;
- u_char input[3];
- u_char output[4];
+ unsigned char input[3];
+ unsigned char output[4];
int i;
while (2 < srclength) {
@@ -152,14 +147,14 @@
target[datalength++] = Base64[output[2]];
target[datalength++] = Base64[output[3]];
}
-
+
/* Now we worry about padding. */
if (0 != srclength) {
/* Get what's left. */
input[0] = input[1] = input[2] = '\0';
for (i = 0; i < srclength; i++)
input[i] = *src++;
-
+
output[0] = input[0] >> 2;
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
@@ -187,13 +182,10 @@
*/
int
-b64_pton(src, target, targsize)
- char const *src;
- u_char *target;
- size_t targsize;
+b64_pton(char const *src, unsigned char *target, size_t targsize)
{
int tarindex, state, ch;
- u_char nextbyte;
+ unsigned char nextbyte;
char *pos;
state = 0;
@@ -207,7 +199,7 @@
break;
pos = strchr(Base64, ch);
- if (pos == 0) /* A non-base64 character. */
+ if (pos == 0) /* A non-base64 character. */
return (-1);
switch (state) {
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fputws.c b/libc/upstream-openbsd/lib/libc/stdio/fputws.c
index 8961571..4f619b6 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fputws.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fputws.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fputws.c,v 1.8 2015/08/31 02:53:57 guenther Exp $ */
+/* $OpenBSD: fputws.c,v 1.9 2021/10/24 10:05:23 jsg Exp $ */
/* $NetBSD: fputws.c,v 1.1 2003/03/07 07:11:37 tshiozak Exp $ */
/*-
@@ -37,9 +37,7 @@
#include "fvwrite.h"
int
-fputws(ws, fp)
- const wchar_t * __restrict ws;
- FILE * __restrict fp;
+fputws(const wchar_t * __restrict ws, FILE * __restrict fp)
{
FLOCKFILE(fp);
_SET_ORIENTATION(fp, 1);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c b/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c
index da68b90..9a08d13 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c
@@ -131,7 +131,8 @@
flags |= __SNPT;
/*
- * Fix up the FILE fields.
+ * Fix up the FILE fields, and set __cleanup for output flush on
+ * exit (since we are buffered in some way).
*/
if (mode == _IOLBF)
flags |= __SLBF;
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/lsearch.c b/libc/upstream-openbsd/lib/libc/stdlib/lsearch.c
index 8cad05f..95ebf49 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/lsearch.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/lsearch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lsearch.c,v 1.5 2014/07/18 04:16:09 matthew Exp $ */
+/* $OpenBSD: lsearch.c,v 1.7 2021/12/08 22:06:28 cheloha Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -37,48 +37,34 @@
#include <search.h>
typedef int (*cmp_fn_t)(const void *, const void *);
-static void *linear_base(const void *, const void *, size_t *, size_t,
- cmp_fn_t, int);
void *
lsearch(const void *key, void *base, size_t *nelp, size_t width,
cmp_fn_t compar)
{
+ void *element = lfind(key, base, nelp, width, compar);
- return(linear_base(key, base, nelp, width, compar, 1));
+ /*
+ * Use memmove(3) to ensure the key is copied cleanly into the
+ * array, even if the key overlaps with the end of the array.
+ */
+ if (element == NULL) {
+ element = memmove((char *)base + *nelp * width, key, width);
+ *nelp += 1;
+ }
+ return element;
}
void *
lfind(const void *key, const void *base, size_t *nelp, size_t width,
cmp_fn_t compar)
{
- return(linear_base(key, base, nelp, width, compar, 0));
-}
-
-static void *
-linear_base(const void *key, const void *base, size_t *nelp, size_t width,
- cmp_fn_t compar, int add_flag)
-{
const char *element, *end;
end = (const char *)base + *nelp * width;
for (element = base; element < end; element += width)
if (!compar(key, element)) /* key found */
return((void *)element);
-
- if (!add_flag) /* key not found */
- return(NULL);
-
- /*
- * The UNIX System User's Manual, 1986 edition claims that
- * a NULL pointer is returned by lsearch with errno set
- * appropriately, if there is not enough room in the table
- * to add a new item. This can't be done as none of these
- * routines have any method of determining the size of the
- * table. This comment isn't in the 1986-87 System V
- * manual.
- */
- ++*nelp;
- memcpy((void *)end, key, width);
- return((void *)end);
+ return NULL;
}
+DEF_WEAK(lfind);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c b/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c
index a2f37fe..81059e6 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $ */
+/* $OpenBSD: recallocarray.c,v 1.2 2021/03/18 11:16:58 claudio Exp $ */
/*
* Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
*
@@ -57,7 +57,7 @@
if (newsize <= oldsize) {
size_t d = oldsize - newsize;
- if (d < oldsize / 2 && d < getpagesize()) {
+ if (d < oldsize / 2 && d < (size_t)getpagesize()) {
memset((char *)ptr + newsize, 0, d);
return ptr;
}
diff --git a/libc/versioner-dependencies/riscv64/kernel_uapi_asm-riscv64 b/libc/versioner-dependencies/riscv64/kernel_uapi_asm-riscv64
new file mode 120000
index 0000000..61353cb
--- /dev/null
+++ b/libc/versioner-dependencies/riscv64/kernel_uapi_asm-riscv64
@@ -0,0 +1 @@
+../../kernel/uapi/asm-riscv/
\ No newline at end of file
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 750a6e2..4cdec44 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -74,6 +74,7 @@
"-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
+ "-Wl,--exclude-libs=libclang_rt.builtins-riscv64-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
],
@@ -87,6 +88,9 @@
arm64: {
version_script: ":libdl.arm64.map",
},
+ riscv64: {
+ version_script: ":libdl.riscv64.map",
+ },
x86: {
pack_relocations: false,
ldflags: [
@@ -174,6 +178,7 @@
"-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
+ "-Wl,--exclude-libs=libclang_rt.builtins-riscv64-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
],
@@ -241,30 +246,38 @@
name: "libdl.arm.map",
out: ["libdl.arm.map"],
srcs: ["libdl.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) arm $(in) $(out)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) arm $(in) $(out)",
}
genrule {
name: "libdl.arm64.map",
out: ["libdl.arm64.map"],
srcs: ["libdl.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) arm64 $(in) $(out)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) arm64 $(in) $(out)",
+}
+
+genrule {
+ name: "libdl.riscv64.map",
+ out: ["libdl.riscv64.map"],
+ srcs: ["libdl.map.txt"],
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) riscv64 $(in) $(out)",
}
genrule {
name: "libdl.x86.map",
out: ["libdl.x86.map"],
srcs: ["libdl.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) x86 $(in) $(out)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) x86 $(in) $(out)",
}
genrule {
name: "libdl.x86_64.map",
out: ["libdl.x86_64.map"],
srcs: ["libdl.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) x86_64 $(in) $(out)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) x86_64 $(in) $(out)",
}
diff --git a/libm/Android.bp b/libm/Android.bp
index 7469cde..8024fbe 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -73,8 +73,6 @@
"upstream-freebsd/lib/msun/src/e_scalbf.c",
"upstream-freebsd/lib/msun/src/e_sinh.c",
"upstream-freebsd/lib/msun/src/e_sinhf.c",
- "upstream-freebsd/lib/msun/src/e_sqrt.c",
- "upstream-freebsd/lib/msun/src/e_sqrtf.c",
"upstream-freebsd/lib/msun/src/k_cos.c",
"upstream-freebsd/lib/msun/src/k_cosf.c",
"upstream-freebsd/lib/msun/src/k_exp.c",
@@ -282,24 +280,16 @@
},
},
- // arch-specific settings
arch: {
arm: {
srcs: [
"arm/fenv.c",
+ "arm/floor.S",
+ "arm/sqrt.S",
],
- neon: {
- srcs: [
- "arm/sqrt.S",
- "arm/floor.S",
- ],
-
- exclude_srcs: [
- "upstream-freebsd/lib/msun/src/e_sqrt.c",
- "upstream-freebsd/lib/msun/src/e_sqrtf.c",
- "upstream-freebsd/lib/msun/src/s_floor.c",
- ],
- },
+ exclude_srcs: [
+ "upstream-freebsd/lib/msun/src/s_floor.c",
+ ],
instruction_set: "arm",
pack_relocations: false,
ldflags: ["-Wl,--hash-style=both"],
@@ -318,10 +308,10 @@
"arm64/sqrt.S",
],
exclude_srcs: [
- "upstream-freebsd/lib/msun/src/e_sqrt.c",
- "upstream-freebsd/lib/msun/src/e_sqrtf.c",
"upstream-freebsd/lib/msun/src/s_ceil.c",
"upstream-freebsd/lib/msun/src/s_ceilf.c",
+ "upstream-freebsd/lib/msun/src/s_copysign.c",
+ "upstream-freebsd/lib/msun/src/s_copysignf.c",
"upstream-freebsd/lib/msun/src/s_floor.c",
"upstream-freebsd/lib/msun/src/s_floorf.c",
"upstream-freebsd/lib/msun/src/s_fma.c",
@@ -332,8 +322,12 @@
"upstream-freebsd/lib/msun/src/s_fminf.c",
"upstream-freebsd/lib/msun/src/s_llrint.c",
"upstream-freebsd/lib/msun/src/s_llrintf.c",
+ "upstream-freebsd/lib/msun/src/s_llround.c",
+ "upstream-freebsd/lib/msun/src/s_llroundf.c",
"upstream-freebsd/lib/msun/src/s_lrint.c",
"upstream-freebsd/lib/msun/src/s_lrintf.c",
+ "upstream-freebsd/lib/msun/src/s_lround.c",
+ "upstream-freebsd/lib/msun/src/s_lroundf.c",
"upstream-freebsd/lib/msun/src/s_rint.c",
"upstream-freebsd/lib/msun/src/s_rintf.c",
"upstream-freebsd/lib/msun/src/s_round.c",
@@ -344,6 +338,22 @@
version_script: ":libm.arm64.map",
},
+ riscv64: {
+ srcs: [
+ "riscv64/fenv.c",
+ "riscv64/lrint.S",
+ "riscv64/sqrt.S",
+ ],
+
+ exclude_srcs: [
+ "upstream-freebsd/lib/msun/src/s_llrint.c",
+ "upstream-freebsd/lib/msun/src/s_llrintf.c",
+ "upstream-freebsd/lib/msun/src/s_lrint.c",
+ "upstream-freebsd/lib/msun/src/s_lrintf.c",
+ ],
+ version_script: ":libm.riscv64.map",
+ },
+
x86: {
srcs: [
"i387/fenv.c",
@@ -386,8 +396,6 @@
"upstream-freebsd/lib/msun/src/e_hypot.c",
"upstream-freebsd/lib/msun/src/e_log10.c",
"upstream-freebsd/lib/msun/src/e_sinh.c",
- "upstream-freebsd/lib/msun/src/e_sqrt.c",
- "upstream-freebsd/lib/msun/src/e_sqrtf.c",
"upstream-freebsd/lib/msun/src/s_atan.c",
"upstream-freebsd/lib/msun/src/s_cbrt.c",
"upstream-freebsd/lib/msun/src/s_ceil.c",
@@ -452,8 +460,6 @@
"upstream-freebsd/lib/msun/src/e_hypot.c",
"upstream-freebsd/lib/msun/src/e_log10.c",
"upstream-freebsd/lib/msun/src/e_sinh.c",
- "upstream-freebsd/lib/msun/src/e_sqrt.c",
- "upstream-freebsd/lib/msun/src/e_sqrtf.c",
"upstream-freebsd/lib/msun/src/s_atan.c",
"upstream-freebsd/lib/msun/src/s_cbrt.c",
"upstream-freebsd/lib/msun/src/s_ceil.c",
@@ -560,30 +566,38 @@
name: "libm.arm.map",
out: ["libm.arm.map"],
srcs: ["libm.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) arm $(in) $(out)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) arm $(in) $(out)",
}
genrule {
name: "libm.arm64.map",
out: ["libm.arm64.map"],
srcs: ["libm.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) arm64 $(in) $(out)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) arm64 $(in) $(out)",
+}
+
+genrule {
+ name: "libm.riscv64.map",
+ out: ["libm.riscv64.map"],
+ srcs: ["libm.map.txt"],
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) riscv64 $(in) $(out)",
}
genrule {
name: "libm.x86.map",
out: ["libm.x86.map"],
srcs: ["libm.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) x86 $(in) $(out)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) x86 $(in) $(out)",
}
genrule {
name: "libm.x86_64.map",
out: ["libm.x86_64.map"],
srcs: ["libm.map.txt"],
- tool_files: [":bionic-generate-version-script"],
- cmd: "$(location :bionic-generate-version-script) x86_64 $(in) $(out)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) x86_64 $(in) $(out)",
}
diff --git a/libm/NOTICE b/libm/NOTICE
index 64d253a..bce49ad 100644
--- a/libm/NOTICE
+++ b/libm/NOTICE
@@ -309,6 +309,34 @@
-------------------------------------------------------------------
+Copyright (C) 2022 The Android Open Source Project
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
Copyright (c) 1985, 1993
The Regents of the University of California. All rights reserved.
diff --git a/libm/arm64/fenv.c b/libm/arm64/fenv.c
index a99288b..0f28d0c 100644
--- a/libm/arm64/fenv.c
+++ b/libm/arm64/fenv.c
@@ -59,7 +59,6 @@
int fesetenv(const fenv_t* envp) {
fpu_control_t fpcr;
-
__get_fpcr(fpcr);
if (envp->__control != fpcr) {
__set_fpcr(envp->__control);
@@ -70,27 +69,22 @@
int feclearexcept(int excepts) {
fpu_status_t fpsr;
-
- excepts &= FE_ALL_EXCEPT;
__get_fpsr(fpsr);
- fpsr &= ~excepts;
+ fpsr &= ~(excepts & FE_ALL_EXCEPT);
__set_fpsr(fpsr);
return 0;
}
int fegetexceptflag(fexcept_t* flagp, int excepts) {
fpu_status_t fpsr;
-
- excepts &= FE_ALL_EXCEPT;
__get_fpsr(fpsr);
- *flagp = fpsr & excepts;
+ *flagp = fpsr & (excepts & FE_ALL_EXCEPT);
return 0;
}
int fesetexceptflag(const fexcept_t* flagp, int excepts) {
- fpu_status_t fpsr;
-
excepts &= FE_ALL_EXCEPT;
+ fpu_status_t fpsr;
__get_fpsr(fpsr);
fpsr &= ~excepts;
fpsr |= *flagp & excepts;
@@ -100,32 +94,27 @@
int feraiseexcept(int excepts) {
fexcept_t ex = excepts;
-
fesetexceptflag(&ex, excepts);
return 0;
}
int fetestexcept(int excepts) {
fpu_status_t fpsr;
-
- excepts &= FE_ALL_EXCEPT;
__get_fpsr(fpsr);
- return (fpsr & excepts);
+ return (fpsr & (excepts & FE_ALL_EXCEPT));
}
int fegetround(void) {
fpu_control_t fpcr;
-
__get_fpcr(fpcr);
return ((fpcr >> FPCR_RMODE_SHIFT) & FE_TOWARDZERO);
}
int fesetround(int round) {
- fpu_control_t fpcr, new_fpcr;
-
- round &= FE_TOWARDZERO;
+ if (round < FE_TONEAREST || round > FE_TOWARDZERO) return -1;
+ fpu_control_t fpcr;
__get_fpcr(fpcr);
- new_fpcr = fpcr & ~(FE_TOWARDZERO << FPCR_RMODE_SHIFT);
+ fpu_control_t new_fpcr = fpcr & ~(FE_TOWARDZERO << FPCR_RMODE_SHIFT);
new_fpcr |= (round << FPCR_RMODE_SHIFT);
if (new_fpcr != fpcr) {
__set_fpcr(new_fpcr);
@@ -134,33 +123,15 @@
}
int feholdexcept(fenv_t* envp) {
- fpu_status_t fpsr;
- __get_fpsr(fpsr);
- fpu_control_t fpcr;
- __get_fpcr(fpcr);
- fenv_t env = { .__status = fpsr, .__control = fpcr };
- *envp = env;
-
- // Clear all exceptions.
- fpsr &= ~FE_ALL_EXCEPT;
- __set_fpsr(fpsr);
+ fegetenv(envp);
+ feclearexcept(FE_ALL_EXCEPT);
return 0;
}
int feupdateenv(const fenv_t* envp) {
- fpu_status_t fpsr;
- fpu_control_t fpcr;
-
- // Set FPU Control register.
- __get_fpcr(fpcr);
- if (envp->__control != fpcr) {
- __set_fpcr(envp->__control);
- }
-
- // Set FPU Status register to status | currently raised exceptions.
- __get_fpsr(fpsr);
- fpsr = envp->__status | (fpsr & FE_ALL_EXCEPT);
- __set_fpsr(fpsr);
+ int excepts = fetestexcept(FE_ALL_EXCEPT);
+ fesetenv(envp);
+ feraiseexcept(excepts);
return 0;
}
diff --git a/libm/builtins.cpp b/libm/builtins.cpp
index 3b9228c..7487323 100644
--- a/libm/builtins.cpp
+++ b/libm/builtins.cpp
@@ -49,6 +49,9 @@
float ceilf(float x) { return __builtin_ceilf(x); }
double ceil(double x) { return __builtin_ceil(x); }
+double copysign(double x, double y) { return __builtin_copysign(x, y); }
+float copysignf(float x, float y) { return __builtin_copysignf(x, y); }
+
float floorf(float x) { return __builtin_floorf(x); }
double floor(double x) { return __builtin_floor(x); }
@@ -61,6 +64,11 @@
float fminf(float x, float y) { return __builtin_fminf(x, y); }
double fmin(double x, double y) { return __builtin_fmin(x, y); }
+long lround(double x) { return __builtin_lround(x); }
+long lroundf(float x) { return __builtin_lroundf(x); }
+long long llround(double x) { return __builtin_llround(x); }
+long long llroundf(float x) { return __builtin_llroundf(x); }
+
float rintf(float x) { return __builtin_rintf(x); }
double rint(double x) { return __builtin_rint(x); }
diff --git a/libm/riscv64/fenv.c b/libm/riscv64/fenv.c
new file mode 100644
index 0000000..f16e5a9
--- /dev/null
+++ b/libm/riscv64/fenv.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <fenv.h>
+#include <stdint.h>
+
+const fenv_t __fe_dfl_env = 0;
+
+int fegetenv(fenv_t* envp) {
+ __asm__ __volatile__("frcsr %0" : "=r"(*envp));
+ return 0;
+}
+
+int fesetenv(const fenv_t* envp) {
+ fenv_t env;
+ fegetenv(&env);
+ if (*envp != env) {
+ __asm__ __volatile__("fscsr %z0" : : "r"(*envp));
+ }
+ return 0;
+}
+
+int feclearexcept(int excepts) {
+ __asm__ __volatile__("csrc fflags, %0" : : "r"(excepts & FE_ALL_EXCEPT));
+ return 0;
+}
+
+int fegetexceptflag(fexcept_t* flagp, int excepts) {
+ *flagp = fetestexcept(excepts & FE_ALL_EXCEPT);
+ return 0;
+}
+
+int fesetexceptflag(const fexcept_t* flagp, int excepts) {
+ feclearexcept((~*flagp) & excepts);
+ feraiseexcept(*flagp & excepts);
+ return 0;
+}
+
+int feraiseexcept(int excepts) {
+ __asm__ __volatile__("csrs fflags, %0" : : "r"(excepts));
+ return 0;
+}
+
+int fetestexcept(int excepts) {
+ int flags;
+ __asm__ __volatile__("frflags %0" : "=r"(flags));
+ return flags & excepts;
+}
+
+int fegetround(void) {
+ int rm;
+ __asm__ __volatile__("frrm %0" : "=r"(rm));
+ return rm;
+}
+
+int fesetround(int round) {
+ if (round < FE_TONEAREST || round > FE_UPWARD) return -1;
+ __asm__ __volatile__("fsrm %z0" : : "r"(round));
+ return 0;
+}
+
+int feholdexcept(fenv_t* envp) {
+ fegetenv(envp);
+ feclearexcept(FE_ALL_EXCEPT);
+ return 0;
+}
+
+int feupdateenv(const fenv_t* envp) {
+ int excepts = fetestexcept(FE_ALL_EXCEPT);
+ fesetenv(envp);
+ feraiseexcept(excepts);
+ return 0;
+}
+
+int feenableexcept(int mask __unused) {
+ return -1;
+}
+
+int fedisableexcept(int mask __unused) {
+ return 0;
+}
+
+int fegetexcept(void) {
+ return 0;
+}
diff --git a/libm/riscv64/lrint.S b/libm/riscv64/lrint.S
new file mode 100644
index 0000000..eb13833
--- /dev/null
+++ b/libm/riscv64/lrint.S
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+
+ENTRY(lrint)
+ fcvt.l.d a0, fa0, dyn
+ ret
+END(lrint)
+
+ENTRY(lrintf)
+ fcvt.l.s a0, fa0, dyn
+ ret
+END(lrintf)
+
+// sizeof(long) and sizeof(long long) are the same for riscv64
+ALIAS_SYMBOL(llrint, lrint);
+
+ALIAS_SYMBOL(llrintf, lrintf);
diff --git a/libm/riscv64/sqrt.S b/libm/riscv64/sqrt.S
new file mode 100644
index 0000000..0db1335
--- /dev/null
+++ b/libm/riscv64/sqrt.S
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+
+ENTRY(sqrt)
+ fsqrt.d fa0, fa0
+ ret
+END(sqrt)
+
+ENTRY(sqrtf)
+ fsqrt.s fa0, fa0
+ ret
+END(sqrtf)
diff --git a/libm/upstream-freebsd/lib/msun/src/e_sqrt.c b/libm/upstream-freebsd/lib/msun/src/e_sqrt.c
deleted file mode 100644
index 37351a4..0000000
--- a/libm/upstream-freebsd/lib/msun/src/e_sqrt.c
+++ /dev/null
@@ -1,459 +0,0 @@
-
-/* @(#)e_sqrt.c 1.3 95/01/18 */
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunSoft, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <float.h>
-
-#include "math.h"
-#include "math_private.h"
-
-#ifdef USE_BUILTIN_SQRT
-double
-__ieee754_sqrt(double x)
-{
- return (__builtin_sqrt(x));
-}
-#else
-/* __ieee754_sqrt(x)
- * Return correctly rounded sqrt.
- * ------------------------------------------
- * | Use the hardware sqrt if you have one |
- * ------------------------------------------
- * Method:
- * Bit by bit method using integer arithmetic. (Slow, but portable)
- * 1. Normalization
- * Scale x to y in [1,4) with even powers of 2:
- * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then
- * sqrt(x) = 2^k * sqrt(y)
- * 2. Bit by bit computation
- * Let q = sqrt(y) truncated to i bit after binary point (q = 1),
- * i 0
- * i+1 2
- * s = 2*q , and y = 2 * ( y - q ). (1)
- * i i i i
- *
- * To compute q from q , one checks whether
- * i+1 i
- *
- * -(i+1) 2
- * (q + 2 ) <= y. (2)
- * i
- * -(i+1)
- * If (2) is false, then q = q ; otherwise q = q + 2 .
- * i+1 i i+1 i
- *
- * With some algebric manipulation, it is not difficult to see
- * that (2) is equivalent to
- * -(i+1)
- * s + 2 <= y (3)
- * i i
- *
- * The advantage of (3) is that s and y can be computed by
- * i i
- * the following recurrence formula:
- * if (3) is false
- *
- * s = s , y = y ; (4)
- * i+1 i i+1 i
- *
- * otherwise,
- * -i -(i+1)
- * s = s + 2 , y = y - s - 2 (5)
- * i+1 i i+1 i i
- *
- * One may easily use induction to prove (4) and (5).
- * Note. Since the left hand side of (3) contain only i+2 bits,
- * it does not necessary to do a full (53-bit) comparison
- * in (3).
- * 3. Final rounding
- * After generating the 53 bits result, we compute one more bit.
- * Together with the remainder, we can decide whether the
- * result is exact, bigger than 1/2ulp, or less than 1/2ulp
- * (it will never equal to 1/2ulp).
- * The rounding mode can be detected by checking whether
- * huge + tiny is equal to huge, and whether huge - tiny is
- * equal to huge for some floating point number "huge" and "tiny".
- *
- * Special cases:
- * sqrt(+-0) = +-0 ... exact
- * sqrt(inf) = inf
- * sqrt(-ve) = NaN ... with invalid signal
- * sqrt(NaN) = NaN ... with invalid signal for signaling NaN
- *
- * Other methods : see the appended file at the end of the program below.
- *---------------
- */
-
-static const double one = 1.0, tiny=1.0e-300;
-
-double
-__ieee754_sqrt(double x)
-{
- double z;
- int32_t sign = (int)0x80000000;
- int32_t ix0,s0,q,m,t,i;
- u_int32_t r,t1,s1,ix1,q1;
-
- EXTRACT_WORDS(ix0,ix1,x);
-
- /* take care of Inf and NaN */
- if((ix0&0x7ff00000)==0x7ff00000) {
- return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
- sqrt(-inf)=sNaN */
- }
- /* take care of zero */
- if(ix0<=0) {
- if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
- else if(ix0<0)
- return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
- }
- /* normalize x */
- m = (ix0>>20);
- if(m==0) { /* subnormal x */
- while(ix0==0) {
- m -= 21;
- ix0 |= (ix1>>11); ix1 <<= 21;
- }
- for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
- m -= i-1;
- ix0 |= (ix1>>(32-i));
- ix1 <<= i;
- }
- m -= 1023; /* unbias exponent */
- ix0 = (ix0&0x000fffff)|0x00100000;
- if(m&1){ /* odd m, double x to make it even */
- ix0 += ix0 + ((ix1&sign)>>31);
- ix1 += ix1;
- }
- m >>= 1; /* m = [m/2] */
-
- /* generate sqrt(x) bit by bit */
- ix0 += ix0 + ((ix1&sign)>>31);
- ix1 += ix1;
- q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
- r = 0x00200000; /* r = moving bit from right to left */
-
- while(r!=0) {
- t = s0+r;
- if(t<=ix0) {
- s0 = t+r;
- ix0 -= t;
- q += r;
- }
- ix0 += ix0 + ((ix1&sign)>>31);
- ix1 += ix1;
- r>>=1;
- }
-
- r = sign;
- while(r!=0) {
- t1 = s1+r;
- t = s0;
- if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
- s1 = t1+r;
- if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
- ix0 -= t;
- if (ix1 < t1) ix0 -= 1;
- ix1 -= t1;
- q1 += r;
- }
- ix0 += ix0 + ((ix1&sign)>>31);
- ix1 += ix1;
- r>>=1;
- }
-
- /* use floating add to find out rounding direction */
- if((ix0|ix1)!=0) {
- z = one-tiny; /* trigger inexact flag */
- if (z>=one) {
- z = one+tiny;
- if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;}
- else if (z>one) {
- if (q1==(u_int32_t)0xfffffffe) q+=1;
- q1+=2;
- } else
- q1 += (q1&1);
- }
- }
- ix0 = (q>>1)+0x3fe00000;
- ix1 = q1>>1;
- if ((q&1)==1) ix1 |= sign;
- ix0 += (m <<20);
- INSERT_WORDS(z,ix0,ix1);
- return z;
-}
-#endif
-
-#if (LDBL_MANT_DIG == 53)
-__weak_reference(sqrt, sqrtl);
-#endif
-
-/*
-Other methods (use floating-point arithmetic)
--------------
-(This is a copy of a drafted paper by Prof W. Kahan
-and K.C. Ng, written in May, 1986)
-
- Two algorithms are given here to implement sqrt(x)
- (IEEE double precision arithmetic) in software.
- Both supply sqrt(x) correctly rounded. The first algorithm (in
- Section A) uses newton iterations and involves four divisions.
- The second one uses reciproot iterations to avoid division, but
- requires more multiplications. Both algorithms need the ability
- to chop results of arithmetic operations instead of round them,
- and the INEXACT flag to indicate when an arithmetic operation
- is executed exactly with no roundoff error, all part of the
- standard (IEEE 754-1985). The ability to perform shift, add,
- subtract and logical AND operations upon 32-bit words is needed
- too, though not part of the standard.
-
-A. sqrt(x) by Newton Iteration
-
- (1) Initial approximation
-
- Let x0 and x1 be the leading and the trailing 32-bit words of
- a floating point number x (in IEEE double format) respectively
-
- 1 11 52 ...widths
- ------------------------------------------------------
- x: |s| e | f |
- ------------------------------------------------------
- msb lsb msb lsb ...order
-
-
- ------------------------ ------------------------
- x0: |s| e | f1 | x1: | f2 |
- ------------------------ ------------------------
-
- By performing shifts and subtracts on x0 and x1 (both regarded
- as integers), we obtain an 8-bit approximation of sqrt(x) as
- follows.
-
- k := (x0>>1) + 0x1ff80000;
- y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits
- Here k is a 32-bit integer and T1[] is an integer array containing
- correction terms. Now magically the floating value of y (y's
- leading 32-bit word is y0, the value of its trailing word is 0)
- approximates sqrt(x) to almost 8-bit.
-
- Value of T1:
- static int T1[32]= {
- 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592,
- 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215,
- 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581,
- 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,};
-
- (2) Iterative refinement
-
- Apply Heron's rule three times to y, we have y approximates
- sqrt(x) to within 1 ulp (Unit in the Last Place):
-
- y := (y+x/y)/2 ... almost 17 sig. bits
- y := (y+x/y)/2 ... almost 35 sig. bits
- y := y-(y-x/y)/2 ... within 1 ulp
-
-
- Remark 1.
- Another way to improve y to within 1 ulp is:
-
- y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x)
- y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x)
-
- 2
- (x-y )*y
- y := y + 2* ---------- ...within 1 ulp
- 2
- 3y + x
-
-
- This formula has one division fewer than the one above; however,
- it requires more multiplications and additions. Also x must be
- scaled in advance to avoid spurious overflow in evaluating the
- expression 3y*y+x. Hence it is not recommended uless division
- is slow. If division is very slow, then one should use the
- reciproot algorithm given in section B.
-
- (3) Final adjustment
-
- By twiddling y's last bit it is possible to force y to be
- correctly rounded according to the prevailing rounding mode
- as follows. Let r and i be copies of the rounding mode and
- inexact flag before entering the square root program. Also we
- use the expression y+-ulp for the next representable floating
- numbers (up and down) of y. Note that y+-ulp = either fixed
- point y+-1, or multiply y by nextafter(1,+-inf) in chopped
- mode.
-
- I := FALSE; ... reset INEXACT flag I
- R := RZ; ... set rounding mode to round-toward-zero
- z := x/y; ... chopped quotient, possibly inexact
- If(not I) then { ... if the quotient is exact
- if(z=y) {
- I := i; ... restore inexact flag
- R := r; ... restore rounded mode
- return sqrt(x):=y.
- } else {
- z := z - ulp; ... special rounding
- }
- }
- i := TRUE; ... sqrt(x) is inexact
- If (r=RN) then z=z+ulp ... rounded-to-nearest
- If (r=RP) then { ... round-toward-+inf
- y = y+ulp; z=z+ulp;
- }
- y := y+z; ... chopped sum
- y0:=y0-0x00100000; ... y := y/2 is correctly rounded.
- I := i; ... restore inexact flag
- R := r; ... restore rounded mode
- return sqrt(x):=y.
-
- (4) Special cases
-
- Square root of +inf, +-0, or NaN is itself;
- Square root of a negative number is NaN with invalid signal.
-
-
-B. sqrt(x) by Reciproot Iteration
-
- (1) Initial approximation
-
- Let x0 and x1 be the leading and the trailing 32-bit words of
- a floating point number x (in IEEE double format) respectively
- (see section A). By performing shifs and subtracts on x0 and y0,
- we obtain a 7.8-bit approximation of 1/sqrt(x) as follows.
-
- k := 0x5fe80000 - (x0>>1);
- y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits
-
- Here k is a 32-bit integer and T2[] is an integer array
- containing correction terms. Now magically the floating
- value of y (y's leading 32-bit word is y0, the value of
- its trailing word y1 is set to zero) approximates 1/sqrt(x)
- to almost 7.8-bit.
-
- Value of T2:
- static int T2[64]= {
- 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866,
- 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f,
- 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d,
- 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0,
- 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989,
- 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd,
- 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e,
- 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,};
-
- (2) Iterative refinement
-
- Apply Reciproot iteration three times to y and multiply the
- result by x to get an approximation z that matches sqrt(x)
- to about 1 ulp. To be exact, we will have
- -1ulp < sqrt(x)-z<1.0625ulp.
-
- ... set rounding mode to Round-to-nearest
- y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x)
- y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x)
- ... special arrangement for better accuracy
- z := x*y ... 29 bits to sqrt(x), with z*y<1
- z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x)
-
- Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that
- (a) the term z*y in the final iteration is always less than 1;
- (b) the error in the final result is biased upward so that
- -1 ulp < sqrt(x) - z < 1.0625 ulp
- instead of |sqrt(x)-z|<1.03125ulp.
-
- (3) Final adjustment
-
- By twiddling y's last bit it is possible to force y to be
- correctly rounded according to the prevailing rounding mode
- as follows. Let r and i be copies of the rounding mode and
- inexact flag before entering the square root program. Also we
- use the expression y+-ulp for the next representable floating
- numbers (up and down) of y. Note that y+-ulp = either fixed
- point y+-1, or multiply y by nextafter(1,+-inf) in chopped
- mode.
-
- R := RZ; ... set rounding mode to round-toward-zero
- switch(r) {
- case RN: ... round-to-nearest
- if(x<= z*(z-ulp)...chopped) z = z - ulp; else
- if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp;
- break;
- case RZ:case RM: ... round-to-zero or round-to--inf
- R:=RP; ... reset rounding mod to round-to-+inf
- if(x<z*z ... rounded up) z = z - ulp; else
- if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp;
- break;
- case RP: ... round-to-+inf
- if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else
- if(x>z*z ...chopped) z = z+ulp;
- break;
- }
-
- Remark 3. The above comparisons can be done in fixed point. For
- example, to compare x and w=z*z chopped, it suffices to compare
- x1 and w1 (the trailing parts of x and w), regarding them as
- two's complement integers.
-
- ...Is z an exact square root?
- To determine whether z is an exact square root of x, let z1 be the
- trailing part of z, and also let x0 and x1 be the leading and
- trailing parts of x.
-
- If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0
- I := 1; ... Raise Inexact flag: z is not exact
- else {
- j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2
- k := z1 >> 26; ... get z's 25-th and 26-th
- fraction bits
- I := i or (k&j) or ((k&(j+j+1))!=(x1&3));
- }
- R:= r ... restore rounded mode
- return sqrt(x):=z.
-
- If multiplication is cheaper then the foregoing red tape, the
- Inexact flag can be evaluated by
-
- I := i;
- I := (z*z!=x) or I.
-
- Note that z*z can overwrite I; this value must be sensed if it is
- True.
-
- Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be
- zero.
-
- --------------------
- z1: | f2 |
- --------------------
- bit 31 bit 0
-
- Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd
- or even of logb(x) have the following relations:
-
- -------------------------------------------------
- bit 27,26 of z1 bit 1,0 of x1 logb(x)
- -------------------------------------------------
- 00 00 odd and even
- 01 01 even
- 10 10 odd
- 10 00 even
- 11 01 even
- -------------------------------------------------
-
- (4) Special cases (see (4) of Section A).
-
- */
-
diff --git a/libm/upstream-freebsd/lib/msun/src/e_sqrtf.c b/libm/upstream-freebsd/lib/msun/src/e_sqrtf.c
deleted file mode 100644
index 06e5d62..0000000
--- a/libm/upstream-freebsd/lib/msun/src/e_sqrtf.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/* e_sqrtf.c -- float version of e_sqrt.c.
- * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
- */
-
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-#include "math.h"
-#include "math_private.h"
-
-#ifdef USE_BUILTIN_SQRTF
-float
-__ieee754_sqrtf(float x)
-{
- return (__builtin_sqrtf(x));
-}
-#else
-static const float one = 1.0, tiny=1.0e-30;
-
-float
-__ieee754_sqrtf(float x)
-{
- float z;
- int32_t sign = (int)0x80000000;
- int32_t ix,s,q,m,t,i;
- u_int32_t r;
-
- GET_FLOAT_WORD(ix,x);
-
- /* take care of Inf and NaN */
- if((ix&0x7f800000)==0x7f800000) {
- return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
- sqrt(-inf)=sNaN */
- }
- /* take care of zero */
- if(ix<=0) {
- if((ix&(~sign))==0) return x;/* sqrt(+-0) = +-0 */
- else if(ix<0)
- return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
- }
- /* normalize x */
- m = (ix>>23);
- if(m==0) { /* subnormal x */
- for(i=0;(ix&0x00800000)==0;i++) ix<<=1;
- m -= i-1;
- }
- m -= 127; /* unbias exponent */
- ix = (ix&0x007fffff)|0x00800000;
- if(m&1) /* odd m, double x to make it even */
- ix += ix;
- m >>= 1; /* m = [m/2] */
-
- /* generate sqrt(x) bit by bit */
- ix += ix;
- q = s = 0; /* q = sqrt(x) */
- r = 0x01000000; /* r = moving bit from right to left */
-
- while(r!=0) {
- t = s+r;
- if(t<=ix) {
- s = t+r;
- ix -= t;
- q += r;
- }
- ix += ix;
- r>>=1;
- }
-
- /* use floating add to find out rounding direction */
- if(ix!=0) {
- z = one-tiny; /* trigger inexact flag */
- if (z>=one) {
- z = one+tiny;
- if (z>one)
- q += 2;
- else
- q += (q&1);
- }
- }
- ix = (q>>1)+0x3f000000;
- ix += (m <<23);
- SET_FLOAT_WORD(z,ix);
- return z;
-}
-#endif
diff --git a/libm/upstream-freebsd/lib/msun/src/math_private.h b/libm/upstream-freebsd/lib/msun/src/math_private.h
index b91b54c..df526e7 100644
--- a/libm/upstream-freebsd/lib/msun/src/math_private.h
+++ b/libm/upstream-freebsd/lib/msun/src/math_private.h
@@ -460,7 +460,7 @@
* or by having |c| a few percent smaller than |a|. Pre-normalization of
* (a, b) may help.
*
- * This is is a variant of an algorithm of Kahan (see Knuth (1981) 4.2.2
+ * This is a variant of an algorithm of Kahan (see Knuth (1981) 4.2.2
* exercise 19). We gain considerable efficiency by requiring the terms to
* be sufficiently normalized and sufficiently increasing.
*/
@@ -644,7 +644,7 @@
* return type provided their arg is a floating point integer. They can
* sometimes be more efficient because no rounding is required.
*/
-#if (defined(amd64) || defined(__i386__)) && defined(__GNUCLIKE_ASM)
+#if defined(amd64) || defined(__i386__)
#define irint(x) \
(sizeof(x) == sizeof(float) && \
sizeof(__float_t) == sizeof(long double) ? irintf(x) : \
@@ -657,7 +657,7 @@
#define i64rint(x) ((int64_t)(x)) /* only needed for ld128 so not opt. */
-#if defined(__i386__) && defined(__GNUCLIKE_ASM)
+#if defined(__i386__)
static __inline int
irintf(float x)
{
@@ -677,7 +677,7 @@
}
#endif
-#if (defined(__amd64__) || defined(__i386__)) && defined(__GNUCLIKE_ASM)
+#if defined(__amd64__) || defined(__i386__)
static __inline int
irintl(long double x)
{
diff --git a/libm/upstream-freebsd/lib/msun/src/w_cabsf.c b/libm/upstream-freebsd/lib/msun/src/w_cabsf.c
index e7bfe22..b5065c8 100644
--- a/libm/upstream-freebsd/lib/msun/src/w_cabsf.c
+++ b/libm/upstream-freebsd/lib/msun/src/w_cabsf.c
@@ -15,8 +15,7 @@
#include "math_private.h"
float
-cabsf(z)
- float complex z;
+cabsf(float complex z)
{
return hypotf(crealf(z), cimagf(z));
diff --git a/libm/upstream-freebsd/lib/msun/src/w_drem.c b/libm/upstream-freebsd/lib/msun/src/w_drem.c
index 0f68409..74008a5 100644
--- a/libm/upstream-freebsd/lib/msun/src/w_drem.c
+++ b/libm/upstream-freebsd/lib/msun/src/w_drem.c
@@ -8,8 +8,7 @@
#include <math.h>
double
-drem(x, y)
- double x, y;
+drem(double x, double y)
{
return remainder(x, y);
}
diff --git a/linker/Android.bp b/linker/Android.bp
index d5e7367..83077c6 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -52,6 +52,9 @@
arm64: {
srcs: ["arch/arm64/linker_wrapper_begin.S"],
},
+ riscv64: {
+ srcs: ["arch/riscv64/linker_wrapper_begin.S"],
+ },
x86_64: {
srcs: ["arch/x86_64/linker_wrapper_begin.S"],
},
@@ -115,7 +118,7 @@
"libasync_safe",
- "liblog",
+ "liblog_for_runtime_apex",
],
// We need to access Bionic private headers in the linker.
@@ -208,6 +211,13 @@
}
filegroup {
+ name: "linker_sources_riscv64",
+ srcs: [
+ "arch/riscv64/begin.S",
+ ],
+}
+
+filegroup {
name: "linker_sources_x86",
srcs: [
"arch/x86/begin.S",
@@ -224,10 +234,11 @@
cc_defaults {
name: "linker_version_script_overlay",
arch: {
- arm: { version_script: "linker.arm.map" },
- arm64: { version_script: "linker.generic.map" },
- x86: { version_script: "linker.generic.map" },
- x86_64: { version_script: "linker.generic.map" },
+ arm: { version_script: "linker.arm.map" },
+ arm64: { version_script: "linker.generic.map" },
+ riscv64: { version_script: "linker.generic.map" },
+ x86: { version_script: "linker.generic.map" },
+ x86_64: { version_script: "linker.generic.map" },
},
}
@@ -241,15 +252,50 @@
arch: {
arm: {
srcs: [":linker_sources_arm"],
+
+ // Arm 32 bit does not produce complete exidx unwind information
+ // so keep the .debug_frame which is relatively small and does
+ // include needed unwind information.
+ // See b/242162222 for details.
+ strip: {
+ keep_symbols_and_debug_frame: true,
+ },
},
arm64: {
srcs: [":linker_sources_arm64"],
+
+ // Leave the symbols in the shared library so that stack unwinders can produce
+ // meaningful name resolution.
+ strip: {
+ keep_symbols: true,
+ },
+ },
+ riscv64: {
+ srcs: [":linker_sources_riscv64"],
+
+ // Leave the symbols in the shared library so that stack unwinders can produce
+ // meaningful name resolution.
+ strip: {
+ keep_symbols: true,
+ },
},
x86: {
srcs: [":linker_sources_x86"],
+
+ // Leave the symbols in the shared library so that stack unwinders can produce
+ // meaningful name resolution.
+ strip: {
+ keep_symbols: true,
+ },
},
x86_64: {
srcs: [":linker_sources_x86_64"],
+
+ // Leave the symbols in the shared library so that stack unwinders can produce
+ // meaningful name resolution.
+ strip: {
+ keep_symbols: true,
+ },
},
},
@@ -275,12 +321,6 @@
static_executable: true,
- // Leave the symbols in the shared library so that stack unwinders can produce
- // meaningful name resolution.
- strip: {
- keep_symbols: true,
- },
-
// Insert an extra objcopy step to add prefix to symbols. This is needed to prevent gdb
// looking up symbols in the linker by mistake.
prefix_symbols: "__dl_",
@@ -406,6 +446,7 @@
"-Wl,--exclude-libs=libgcc_stripped.a",
"-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
+ "-Wl,--exclude-libs=libclang_rt.builtins-riscv64-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
],
@@ -494,7 +535,7 @@
static_libs: [
"libasync_safe",
"libbase",
- "liblog",
+ "liblog_for_runtime_apex",
],
arch: {
diff --git a/linker/NOTICE b/linker/NOTICE
index 8f70d87..d61a193 100644
--- a/linker/NOTICE
+++ b/linker/NOTICE
@@ -334,3 +334,31 @@
-------------------------------------------------------------------
+Copyright (C) 2022 The Android Open Source Project
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
diff --git a/linker/arch/arm/begin.S b/linker/arch/arm/begin.S
index 80d9fe1..3b673f0 100644
--- a/linker/arch/arm/begin.S
+++ b/linker/arch/arm/begin.S
@@ -35,6 +35,6 @@
mov r0, sp
bl __linker_init
- /* linker init returns the _entry address in the main image */
+ // __linker_init returns the address of the entry point in the main image.
bx r0
END(_start)
diff --git a/linker/arch/arm64/begin.S b/linker/arch/arm64/begin.S
index a947475..14999cd 100644
--- a/linker/arch/arm64/begin.S
+++ b/linker/arch/arm64/begin.S
@@ -35,6 +35,6 @@
mov x0, sp
bl __linker_init
- /* linker init returns the _entry address in the main image */
+ // __linker_init returns the address of the entry point in the main image.
br x0
END(_start)
diff --git a/linker/arch/riscv64/begin.S b/linker/arch/riscv64/begin.S
new file mode 100644
index 0000000..f7509c6
--- /dev/null
+++ b/linker/arch/riscv64/begin.S
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+
+ENTRY(_start)
+ // Force unwinds to end in this function.
+ .cfi_undefined ra
+
+ mv a0, sp
+ jal __linker_init
+
+ // __linker_init returns the address of the entry point in the main image.
+ jr a0
+END(_start)
diff --git a/linker/arch/x86/begin.S b/linker/arch/x86/begin.S
index 3812646..81e2740 100644
--- a/linker/arch/x86/begin.S
+++ b/linker/arch/x86/begin.S
@@ -38,6 +38,6 @@
call __linker_init // %esp is aligned to 16 before the call.
addl $16, %esp
- /* linker init returns (%eax) the _entry address in the main image */
+ // __linker_init returns the address of the entry point in the main image.
jmp *%eax
END(_start)
diff --git a/linker/arch/x86_64/begin.S b/linker/arch/x86_64/begin.S
index 4722301..baba0db 100644
--- a/linker/arch/x86_64/begin.S
+++ b/linker/arch/x86_64/begin.S
@@ -35,6 +35,6 @@
mov %rsp, %rdi
call __linker_init
- /* linker init returns (%rax) the _entry address in the main image */
+ // __linker_init returns the address of the entry point in the main image.
jmp *%rax
END(_start)
diff --git a/linker/linker.cpp b/linker/linker.cpp
index c6588d2..9779c8d 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -371,7 +371,7 @@
char* static_tls = reinterpret_cast<char*>(__get_bionic_tcb()) - layout.offset_bionic_tcb();
return static_tls + tls_mod.static_offset;
} else if (should_alloc) {
- const TlsIndex ti { si_tls->module_id, 0 };
+ const TlsIndex ti { si_tls->module_id, static_cast<size_t>(0 - TLS_DTV_OFFSET) };
return TLS_GET_ADDR(&ti);
} else {
TlsDtv* dtv = __get_tcb_dtv(__get_bionic_tcb());
@@ -1568,18 +1568,16 @@
task->set_extinfo(is_dt_needed ? nullptr : extinfo);
task->set_dt_needed(is_dt_needed);
- LD_LOG(kLogDlopen, "find_libraries(ns=%s): task=%s, is_dt_needed=%d", ns->get_name(),
- task->get_name(), is_dt_needed);
-
// Note: start from the namespace that is stored in the LoadTask. This namespace
// is different from the current namespace when the LoadTask is for a transitive
// dependency and the lib that created the LoadTask is not found in the
- // current namespace but in one of the linked namespace.
- if (!find_library_internal(const_cast<android_namespace_t*>(task->get_start_from()),
- task,
- &zip_archive_cache,
- &load_tasks,
- rtld_flags)) {
+ // current namespace but in one of the linked namespaces.
+ android_namespace_t* start_ns = const_cast<android_namespace_t*>(task->get_start_from());
+
+ LD_LOG(kLogDlopen, "find_library_internal(ns=%s@%p): task=%s, is_dt_needed=%d",
+ start_ns->get_name(), start_ns, task->get_name(), is_dt_needed);
+
+ if (!find_library_internal(start_ns, task, &zip_archive_cache, &load_tasks, rtld_flags)) {
return false;
}
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 9e5be34..f0e7b1b 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -68,7 +68,8 @@
static void set_bss_vma_name(soinfo* si);
-void __libc_init_mte(const void* phdr_start, size_t phdr_count, uintptr_t load_bias);
+void __libc_init_mte(const void* phdr_start, size_t phdr_count, uintptr_t load_bias,
+ void* stack_top);
// These should be preserved static to avoid emitting
// RELATIVE relocations for the part of the code running
@@ -408,7 +409,7 @@
}
}
- __libc_init_mte(somain->phdr, somain->phnum, somain->load_bias);
+ __libc_init_mte(somain->phdr, somain->phnum, somain->load_bias, args.argv);
#endif
// Register the main executable and the linker upfront to have
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 60fd776..aa1a208 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -51,6 +51,8 @@
return EM_AARCH64;
#elif defined(__i386__)
return EM_386;
+#elif defined(__riscv)
+ return EM_RISCV;
#elif defined(__x86_64__)
return EM_X86_64;
#endif
diff --git a/linker/linker_relocate.cpp b/linker/linker_relocate.cpp
index c7c7bfb..952dade 100644
--- a/linker/linker_relocate.cpp
+++ b/linker/linker_relocate.cpp
@@ -49,7 +49,9 @@
case R_GENERIC_TLS_DTPMOD:
case R_GENERIC_TLS_DTPREL:
case R_GENERIC_TLS_TPREL:
+#if defined(R_GENERIC_TLSDESC)
case R_GENERIC_TLSDESC:
+#endif
return true;
default:
return false;
@@ -426,7 +428,7 @@
case R_GENERIC_TLS_DTPREL:
count_relocation_if<IsGeneral>(kRelocRelative);
{
- const ElfW(Addr) result = sym_addr + get_addend_rel();
+ const ElfW(Addr) result = sym_addr + get_addend_rel() - TLS_DTV_OFFSET;
trace_reloc("RELO TLS_DTPREL %16p <- %16p %s",
rel_target, reinterpret_cast<void*>(result), sym_name);
*static_cast<ElfW(Addr)*>(rel_target) = result;
diff --git a/linker/linker_relocs.h b/linker/linker_relocs.h
index 93d899e..37a7880 100644
--- a/linker/linker_relocs.h
+++ b/linker/linker_relocs.h
@@ -73,6 +73,20 @@
#define R_GENERIC_TLS_TPREL R_386_TLS_TPOFF
#define R_GENERIC_TLSDESC R_386_TLS_DESC
+#elif defined (__riscv)
+
+#define R_GENERIC_JUMP_SLOT R_RISCV_JUMP_SLOT
+#define R_GENERIC_ABSOLUTE R_RISCV_64
+#define R_GENERIC_GLOB_DAT R_RISCV_64
+#define R_GENERIC_RELATIVE R_RISCV_RELATIVE
+#define R_GENERIC_IRELATIVE R_RISCV_IRELATIVE
+#define R_GENERIC_COPY R_RISCV_COPY
+#define R_GENERIC_TLS_DTPMOD R_RISCV_TLS_DTPMOD64
+#define R_GENERIC_TLS_DTPREL R_RISCV_TLS_DTPREL64
+#define R_GENERIC_TLS_TPREL R_RISCV_TLS_TPREL64
+// TODO: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/94
+// #define R_GENERIC_TLSDESC R_RISCV_TLS_DESC
+
#elif defined (__x86_64__)
#define R_GENERIC_JUMP_SLOT R_X86_64_JUMP_SLOT
diff --git a/linker/linker_transparent_hugepage_support.cpp b/linker/linker_transparent_hugepage_support.cpp
index 65ba4cd..0631577 100644
--- a/linker/linker_transparent_hugepage_support.cpp
+++ b/linker/linker_transparent_hugepage_support.cpp
@@ -39,6 +39,6 @@
return false;
}
return enabled.find("[never]") == std::string::npos;
- };
+ }();
return transparent_hugepages_supported;
}
diff --git a/tests/Android.bp b/tests/Android.bp
index a54ffb8..71be058 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -331,8 +331,8 @@
cc_test_library {
name: "clang_diagnostic_tests",
cflags: [
- "-Xclang",
- "-verify",
+ "-Xclang",
+ "-verify",
],
srcs: ["sys_ioctl_diag_test.cpp"],
}
@@ -393,6 +393,7 @@
"math_test.cpp",
"math_force_long_double_test.cpp",
"membarrier_test.cpp",
+ "memtag_stack_test.cpp",
"mntent_test.cpp",
"mte_test.cpp",
"netdb_test.cpp",
@@ -479,6 +480,7 @@
"uchar_test.cpp",
"unistd_nofortify_test.cpp",
"unistd_test.cpp",
+ "utils.cpp",
"utmp_test.cpp",
"wchar_test.cpp",
"wctype_test.cpp",
@@ -598,18 +600,6 @@
],
}
-cc_test_library {
- name: "libBionicGwpAsanTests",
- defaults: ["bionic_tests_defaults"],
- srcs: [
- "gwp_asan_test.cpp",
- ],
- include_dirs: [
- "bionic/libc",
- ],
- static_libs: ["libbase"],
-}
-
// -----------------------------------------------------------------------------
// Fortify tests.
// -----------------------------------------------------------------------------
@@ -641,9 +631,6 @@
],
tidy: false,
target: {
- host: {
- clang_cflags: ["-D__clang__"],
- },
musl: {
// Musl doesn't have fortify
enabled: false,
@@ -727,7 +714,7 @@
tidy: false,
target: {
host: {
- clang_cflags: ["-D__clang__"],
+ cflags: ["-D__clang__"],
},
},
}
@@ -762,7 +749,6 @@
},
}
-
// -----------------------------------------------------------------------------
// Library of all tests (excluding the dynamic linker tests).
// -----------------------------------------------------------------------------
@@ -774,7 +760,6 @@
"libBionicStandardTests",
"libBionicElfTlsTests",
"libBionicFramePointerTests",
- "libBionicGwpAsanTests",
"libfortify1-tests-clang",
"libfortify1-new-tests-clang",
"libfortify2-tests-clang",
@@ -876,6 +861,7 @@
"__cxa_thread_atexit_test.cpp",
"gtest_globals.cpp",
"gtest_main.cpp",
+ "gwp_asan_test.cpp",
"thread_local_test.cpp",
],
@@ -928,6 +914,8 @@
"heap_tagging_static_disabled_helper",
"heap_tagging_static_sync_helper",
"heap_tagging_sync_helper",
+ "stack_tagging_helper",
+ "stack_tagging_static_helper",
"ld_config_test_helper",
"ld_config_test_helper_lib1",
"ld_config_test_helper_lib2",
@@ -1176,6 +1164,8 @@
"heap_tagging_static_disabled_helper",
"heap_tagging_static_sync_helper",
"heap_tagging_sync_helper",
+ "stack_tagging_helper",
+ "stack_tagging_static_helper",
],
}
diff --git a/tests/NOTICE b/tests/NOTICE
index 8c3483c..167f90b 100644
--- a/tests/NOTICE
+++ b/tests/NOTICE
@@ -383,6 +383,22 @@
-------------------------------------------------------------------
Copyright (C) 2022 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2022 The Android Open Source Project
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index a61586b..2f3e905 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -32,9 +32,10 @@
#include <regex>
#include <string>
-#include "gtest_globals.h"
#include <android-base/file.h>
+#include <android-base/macros.h>
#include <android-base/test_utils.h>
+#include "gtest_globals.h"
#include "utils.h"
extern "C" int main_global_default_serial() {
@@ -84,22 +85,13 @@
#if defined(__BIONIC__)
#if defined(__LP64__)
- static constexpr const char* kPathToLinker = "/system/bin/linker64";
+#define LINKER_NAME "linker64"
#else
- static constexpr const char* kPathToLinker = "/system/bin/linker";
+#define LINKER_NAME "linker"
#endif
-
-#if defined (__aarch64__)
- static constexpr const char* kAlternatePathToLinker = "/system/bin/arm64/linker64";
-#elif defined (__arm__)
- static constexpr const char* kAlternatePathToLinker = "/system/bin/arm/linker";
-#elif defined (__x86_64__)
- static constexpr const char* kAlternatePathToLinker = "/system/bin/x86_64/linker64";
-#elif defined (__i386__)
- static constexpr const char* kAlternatePathToLinker = "/system/bin/x86/linker";
-#else
-#error "Unknown architecture"
-#endif
+static constexpr const char* kPathToLinker = "/system/bin/" LINKER_NAME;
+static constexpr const char* kAlternatePathToLinker = "/system/bin/" ABI_STRING "/" LINKER_NAME;
+#undef LINKER_NAME
const char* PathToLinker() {
// On the systems with emulated architecture linker would be of different
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 940e726..c5d1218 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -33,6 +33,7 @@
#include <thread>
#include <android-base/file.h>
+#include <android-base/macros.h>
#include <android-base/scopeguard.h>
#include "gtest_globals.h"
@@ -966,17 +967,7 @@
#endif
}
-#if defined (__aarch64__)
-#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib64/arm64/"
-#elif defined (__arm__)
-#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/arm/"
-#elif defined (__i386__)
-#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/x86/"
-#elif defined (__x86_64__)
-#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib64/x86_64/"
-#else
-#error "Unknown architecture"
-#endif
+#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib64/" ABI_STRING "/"
#define PATH_TO_LIBC PATH_TO_SYSTEM_LIB "libc.so"
#define PATH_TO_BOOTSTRAP_LIBC PATH_TO_SYSTEM_LIB "bootstrap/libc.so"
#define ALTERNATE_PATH_TO_LIBC ALTERNATE_PATH_TO_SYSTEM_LIB "libc.so"
diff --git a/tests/fenv_test.cpp b/tests/fenv_test.cpp
index c5b5eca..9cf9d98 100644
--- a/tests/fenv_test.cpp
+++ b/tests/fenv_test.cpp
@@ -117,6 +117,21 @@
ASSERT_EQ(FE_OVERFLOW, fetestexcept(FE_ALL_EXCEPT));
}
+TEST(fenv, fegetenv_fesetenv_rounding_mode) {
+ // Test that fegetenv()/fesetenv() includes the rounding mode.
+ fesetround(FE_DOWNWARD);
+ ASSERT_EQ(FE_DOWNWARD, fegetround());
+
+ fenv_t env;
+ fegetenv(&env);
+
+ fesetround(FE_UPWARD);
+ ASSERT_EQ(FE_UPWARD, fegetround());
+
+ fesetenv(&env);
+ ASSERT_EQ(FE_DOWNWARD, fegetround());
+}
+
TEST(fenv, feholdexcept_feupdateenv) {
// Set FE_OVERFLOW only.
feclearexcept(FE_ALL_EXCEPT);
@@ -187,9 +202,10 @@
TEST(fenv, feenableexcept_fegetexcept) {
#if !defined(ANDROID_HOST_MUSL)
-#if defined(__aarch64__) || defined(__arm__)
- // ARM doesn't support this. They used to if you go back far enough, but it was removed in
- // the Cortex-A8 between r3p1 and r3p2.
+#if defined(__aarch64__) || defined(__arm__) || defined(__riscv)
+ // ARM and RISC-V don't support hardware trapping of floating point
+ // exceptions. ARM used to if you go back far enough, but it was
+ // removed in the Cortex-A8 between r3p1 and r3p2. RISC-V never has.
ASSERT_EQ(-1, feenableexcept(FE_INVALID));
ASSERT_EQ(0, fegetexcept());
ASSERT_EQ(-1, feenableexcept(FE_DIVBYZERO));
@@ -200,8 +216,10 @@
ASSERT_EQ(0, fegetexcept());
ASSERT_EQ(-1, feenableexcept(FE_INEXACT));
ASSERT_EQ(0, fegetexcept());
+#if defined(_FE_DENORMAL) // riscv64 doesn't support this.
ASSERT_EQ(-1, feenableexcept(FE_DENORMAL));
ASSERT_EQ(0, fegetexcept());
+#endif
#else
// We can't recover from SIGFPE, so sacrifice a child...
pid_t pid = fork();
diff --git a/tests/gwp_asan_test.cpp b/tests/gwp_asan_test.cpp
index b2c7780..5f5e3dd 100644
--- a/tests/gwp_asan_test.cpp
+++ b/tests/gwp_asan_test.cpp
@@ -28,26 +28,28 @@
#include <gtest/gtest.h>
#include <stdio.h>
+#include <sys/file.h>
#include <string>
#if defined(__BIONIC__)
+#include "android-base/file.h"
#include "gwp_asan/options.h"
#include "platform/bionic/malloc.h"
+#include "sys/system_properties.h"
#include "utils.h"
-void RunGwpAsanTest(const char* test_name) {
- ExecTestHelper eh;
- eh.SetEnv({"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1", "GWP_ASAN_MAX_ALLOCS=40000",
- nullptr});
- std::string filter_arg = "--gtest_filter=";
- filter_arg += test_name;
- std::string exec(testing::internal::GetArgvs()[0]);
- eh.SetArgs({exec.c_str(), "--gtest_also_run_disabled_tests", filter_arg.c_str(), nullptr});
- eh.Run([&]() { execve(exec.c_str(), eh.GetArgs(), eh.GetEnv()); },
- /* expected_exit_status */ 0,
- // |expected_output_regex|, ensure at least one test ran:
- R"(\[ PASSED \] [1-9]+0? test)");
+// basename is a mess, use gnu basename explicitly to avoid the need for string
+// mutation.
+extern "C" const char* __gnu_basename(const char* path);
+
+// GWP-ASan tests can run much slower, especially when combined with HWASan.
+// Triple the deadline to avoid flakes (b/238585984).
+extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
+ static const char* initial_args[] = {"--deadline_threshold_ms=270000"};
+ *args = initial_args;
+ *num_args = 1;
+ return true;
}
// This file implements "torture testing" under GWP-ASan, where we sample every
@@ -58,4 +60,191 @@
RunGwpAsanTest("malloc.*:-malloc.mallinfo*");
}
+class SyspropRestorer {
+ private:
+ std::vector<std::pair<std::string, std::string>> props_to_restore_;
+ // System properties are global for a device, so the tests that mutate the
+ // GWP-ASan system properties must be run mutually exclusive. Because
+ // bionic-unit-tests is run in an isolated gtest fashion (each test is run in
+ // its own process), we have to use flocks to synchronise between tests.
+ int flock_fd_;
+
+ public:
+ SyspropRestorer() {
+ std::string path = testing::internal::GetArgvs()[0];
+ flock_fd_ = open(path.c_str(), O_RDONLY);
+ EXPECT_NE(flock_fd_, -1) << "failed to open self for a flock";
+ EXPECT_NE(flock(flock_fd_, LOCK_EX), -1) << "failed to flock myself";
+
+ const char* basename = __gnu_basename(path.c_str());
+ std::vector<std::string> props = {
+ std::string("libc.debug.gwp_asan.sample_rate.") + basename,
+ std::string("libc.debug.gwp_asan.process_sampling.") + basename,
+ std::string("libc.debug.gwp_asan.max_allocs.") + basename,
+ "libc.debug.gwp_asan.sample_rate.system_default",
+ "libc.debug.gwp_asan.sample_rate.app_default",
+ "libc.debug.gwp_asan.process_sampling.system_default",
+ "libc.debug.gwp_asan.process_sampling.app_default",
+ "libc.debug.gwp_asan.max_allocs.system_default",
+ "libc.debug.gwp_asan.max_allocs.app_default",
+ };
+
+ size_t base_props_size = props.size();
+ for (size_t i = 0; i < base_props_size; ++i) {
+ props.push_back("persist." + props[i]);
+ }
+
+ std::string reset_log;
+
+ for (const std::string& prop : props) {
+ std::string value = GetSysprop(prop);
+ props_to_restore_.emplace_back(prop, value);
+ if (!value.empty()) {
+ __system_property_set(prop.c_str(), "");
+ }
+ }
+ }
+
+ ~SyspropRestorer() {
+ for (const auto& kv : props_to_restore_) {
+ if (kv.second != GetSysprop(kv.first)) {
+ __system_property_set(kv.first.c_str(), kv.second.c_str());
+ }
+ }
+ close(flock_fd_);
+ }
+
+ static std::string GetSysprop(const std::string& name) {
+ std::string value;
+ const prop_info* pi = __system_property_find(name.c_str());
+ if (pi == nullptr) return value;
+ __system_property_read_callback(
+ pi,
+ [](void* cookie, const char* /* name */, const char* value, uint32_t /* serial */) {
+ std::string* v = static_cast<std::string*>(cookie);
+ *v = value;
+ },
+ &value);
+ return value;
+ }
+};
+
+TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_enabled) {
+ std::string maps;
+ EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps));
+ EXPECT_TRUE(maps.find("GWP-ASan") != std::string::npos) << maps;
+
+ volatile int* x = new int;
+ delete x;
+ EXPECT_DEATH({ *x = 7; }, "");
+}
+
+TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_disabled) {
+ std::string maps;
+ EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps));
+ EXPECT_TRUE(maps.find("GWP-ASan") == std::string::npos);
+}
+
+TEST(gwp_asan_integration, sysprops_program_specific) {
+ SyspropRestorer restorer;
+
+ std::string path = testing::internal::GetArgvs()[0];
+ const char* basename = __gnu_basename(path.c_str());
+ __system_property_set((std::string("libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
+ __system_property_set((std::string("libc.debug.gwp_asan.process_sampling.") + basename).c_str(),
+ "1");
+ __system_property_set((std::string("libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
+ "40000");
+
+ RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
+TEST(gwp_asan_integration, sysprops_persist_program_specific) {
+ SyspropRestorer restorer;
+
+ std::string path = testing::internal::GetArgvs()[0];
+ const char* basename = __gnu_basename(path.c_str());
+ __system_property_set(
+ (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
+ __system_property_set(
+ (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1");
+ __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
+ "40000");
+
+ RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
+TEST(gwp_asan_integration, sysprops_system) {
+ SyspropRestorer restorer;
+
+ __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "1");
+ __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "1");
+ __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "40000");
+
+ RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
+TEST(gwp_asan_integration, sysprops_persist_system) {
+ SyspropRestorer restorer;
+
+ __system_property_set("persist.libc.debug.gwp_asan.sample_rate.system_default", "1");
+ __system_property_set("persist.libc.debug.gwp_asan.process_sampling.system_default", "1");
+ __system_property_set("persist.libc.debug.gwp_asan.max_allocs.system_default", "40000");
+
+ RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
+TEST(gwp_asan_integration, sysprops_non_persist_overrides_persist) {
+ SyspropRestorer restorer;
+
+ __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "1");
+ __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "1");
+ __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "40000");
+
+ __system_property_set("persist.libc.debug.gwp_asan.sample_rate.system_default", "0");
+ __system_property_set("persist.libc.debug.gwp_asan.process_sampling.system_default", "0");
+ __system_property_set("persist.libc.debug.gwp_asan.max_allocs.system_default", "0");
+
+ RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
+TEST(gwp_asan_integration, sysprops_program_specific_overrides_default) {
+ SyspropRestorer restorer;
+
+ std::string path = testing::internal::GetArgvs()[0];
+ const char* basename = __gnu_basename(path.c_str());
+ __system_property_set(
+ (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
+ __system_property_set(
+ (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1");
+ __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
+ "40000");
+
+ __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
+ __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
+ __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
+
+ RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
+TEST(gwp_asan_integration, sysprops_can_disable) {
+ SyspropRestorer restorer;
+
+ __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
+ __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
+ __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
+
+ RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_disabled");
+}
+
+TEST(gwp_asan_integration, env_overrides_sysprop) {
+ SyspropRestorer restorer;
+
+ __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
+ __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
+ __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
+
+ RunGwpAsanTest("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
#endif // defined(__BIONIC__)
diff --git a/tests/headers/posix/sys_stat_h.c b/tests/headers/posix/sys_stat_h.c
index b22e34f..a299426 100644
--- a/tests/headers/posix/sys_stat_h.c
+++ b/tests/headers/posix/sys_stat_h.c
@@ -69,7 +69,7 @@
STRUCT_MEMBER(struct stat, struct timespec, st_mtim);
STRUCT_MEMBER(struct stat, struct timespec, st_ctim);
#if defined(__BIONIC__)
-#if defined(__aarch64__)
+#if defined(__aarch64__) || defined(__riscv)
STRUCT_MEMBER(struct stat, int, st_blksize);
#elif defined(__x86_64__)
STRUCT_MEMBER(struct stat, long, st_blksize);
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 0046ef6..0c9a2e0 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -41,6 +41,9 @@
enabled: false,
},
},
+ strip: {
+ none: true,
+ },
}
// -----------------------------------------------------------------------------
@@ -1532,12 +1535,6 @@
host_supported: false,
defaults: ["bionic_testlib_defaults"],
srcs: ["relocations.cpp"],
-
- // Hack to ensure we're using llvm-objcopy because our binutils prebuilt
- // only supports the old numbers (http://b/141010852).
- strip: {
- keep_symbols: true,
- },
}
// This is the same encoding as SHT_RELR, but using OS-specific constants.
@@ -1652,6 +1649,35 @@
},
}
+cc_test {
+ name: "stack_tagging_helper",
+ defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+ srcs: ["stack_tagging_helper.cpp"],
+ sanitize: {
+ memtag_heap: true,
+ memtag_stack: true,
+ diag: {
+ memtag_heap: true,
+ },
+ },
+ header_libs: ["bionic_libc_platform_headers"],
+}
+
+cc_test {
+ name: "stack_tagging_static_helper",
+ defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+ srcs: ["stack_tagging_helper.cpp"],
+ static_executable: true,
+ sanitize: {
+ memtag_heap: true,
+ memtag_stack: true,
+ diag: {
+ memtag_heap: true,
+ },
+ },
+ header_libs: ["bionic_libc_platform_headers"],
+}
+
cc_genrule {
name: "libdlext_test_zip_zipaligned",
out: ["bionic-loader-test-libs/libdlext_test_zip/libdlext_test_zip_zipaligned.zip"],
diff --git a/tests/libs/heap_tagging_helper.cpp b/tests/libs/heap_tagging_helper.cpp
index 16a8c8b..ed5601a 100644
--- a/tests/libs/heap_tagging_helper.cpp
+++ b/tests/libs/heap_tagging_helper.cpp
@@ -49,6 +49,10 @@
sa.sa_sigaction = action;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &sa, nullptr);
+ // suppress HWASan crash in logcat / tombstone.
+ struct sigaction dfl_sa = {};
+ dfl_sa.sa_handler = SIG_DFL;
+ sigaction(SIGABRT, &dfl_sa, nullptr);
std::unique_ptr<int[]> p = std::make_unique<int[]>(4);
volatile int oob = p[-1];
diff --git a/tests/libs/stack_tagging_helper.cpp b/tests/libs/stack_tagging_helper.cpp
new file mode 100644
index 0000000..a239dc1
--- /dev/null
+++ b/tests/libs/stack_tagging_helper.cpp
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <thread>
+
+#include <bionic/malloc.h>
+
+#include "libs_utils.h"
+
+#if defined(__aarch64__)
+
+template <typename T>
+static inline void mte_set_tag(T* p) {
+ __asm__ __volatile__(
+ ".arch_extension memtag\n"
+ "stg %[Ptr], [%[Ptr]]\n"
+ :
+ : [Ptr] "r"(p)
+ : "memory");
+}
+
+template <typename T>
+static inline T* mte_get_tag(T* p) {
+ __asm__ __volatile__(
+ ".arch_extension memtag\n"
+ "ldg %[Ptr], [%[Ptr]]\n"
+ : [Ptr] "+r"(p)
+ :
+ : "memory");
+ return p;
+}
+
+template <typename T>
+static inline T* mte_increment_tag(T* p) {
+ T* res;
+ __asm__ __volatile__(
+ ".arch_extension memtag\n"
+ "addg %[Res], %[Ptr], #0, #1\n"
+ : [Res] "=r"(res)
+ : [Ptr] "r"(p)
+ : "memory");
+ return res;
+}
+
+constexpr size_t kStackAllocationSize = 128 * 1024;
+
+// Prevent optimizations.
+volatile void* sink;
+
+enum struct ChildAction { Exit, Execve, Execl };
+
+// Either execve or _exit, transferring control back to parent.
+__attribute__((no_sanitize("memtag"), optnone, noinline)) void vfork_child2(ChildAction action,
+ void* fp_parent) {
+ // Make sure that the buffer in the caller has not been optimized out.
+ void* fp = __builtin_frame_address(0);
+ CHECK(reinterpret_cast<uintptr_t>(fp_parent) - reinterpret_cast<uintptr_t>(fp) >=
+ kStackAllocationSize);
+ if (action == ChildAction::Execve) {
+ const char* argv[] = {"/system/bin/true", nullptr};
+ const char* envp[] = {nullptr};
+ execve("/system/bin/true", const_cast<char**>(argv), const_cast<char**>(envp));
+ fprintf(stderr, "execve failed: %m\n");
+ _exit(1);
+ } else if (action == ChildAction::Execl) {
+ execl("/system/bin/true", "/system/bin/true", "unusedA", "unusedB", nullptr);
+ fprintf(stderr, "execl failed: %m\n");
+ _exit(1);
+ } else if (action == ChildAction::Exit) {
+ _exit(0);
+ }
+ CHECK(0);
+}
+
+// Place a tagged buffer on the stack. Do not tag the top half so that the parent does not crash too
+// early even if things go wrong.
+__attribute__((no_sanitize("memtag"), optnone, noinline)) void vfork_child(ChildAction action) {
+ alignas(16) char buf[kStackAllocationSize] __attribute__((uninitialized));
+ sink = &buf;
+
+ for (char* p = buf; p < buf + sizeof(buf) / 2; p += 16) {
+ char* q = mte_increment_tag(p);
+ mte_set_tag(q);
+ CHECK(mte_get_tag(p) == q);
+ }
+ vfork_child2(action, __builtin_frame_address(0));
+}
+
+// Parent. Check that the stack has correct allocation tags.
+__attribute__((no_sanitize("memtag"), optnone, noinline)) void vfork_parent(pid_t pid) {
+ alignas(16) char buf[kStackAllocationSize] __attribute__((uninitialized));
+ fprintf(stderr, "vfork_parent %p\n", &buf);
+ bool success = true;
+ for (char* p = buf; p < buf + sizeof(buf); p += 16) {
+ char* q = mte_get_tag(p);
+ if (p != q) {
+ fprintf(stderr, "tag mismatch at offset %zx: %p != %p\n", p - buf, p, q);
+ success = false;
+ break;
+ }
+ }
+
+ int wstatus;
+ do {
+ int res = waitpid(pid, &wstatus, 0);
+ CHECK(res == pid);
+ } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
+
+ CHECK(WIFEXITED(wstatus));
+ CHECK(WEXITSTATUS(wstatus) == 0);
+
+ if (!success) exit(1);
+}
+
+void test_vfork(ChildAction action) {
+ pid_t pid = vfork();
+ if (pid == 0) {
+ vfork_child(action);
+ } else {
+ vfork_parent(pid);
+ }
+}
+
+__attribute__((no_sanitize("memtag"), optnone, noinline)) static void settag_and_longjmp(
+ jmp_buf cont) {
+ alignas(16) char buf[kStackAllocationSize] __attribute__((uninitialized));
+ sink = &buf;
+
+ for (char* p = buf; p < buf + sizeof(buf) / 2; p += 16) {
+ char* q = mte_increment_tag(p);
+ mte_set_tag(q);
+ if (mte_get_tag(p) != q) {
+ fprintf(stderr, "failed to set allocation tags on stack: %p != %p\n", mte_get_tag(p), q);
+ exit(1);
+ }
+ }
+ longjmp(cont, 42);
+}
+
+// Check that the stack has correct allocation tags.
+__attribute__((no_sanitize("memtag"), optnone, noinline)) static void check_stack_tags() {
+ alignas(16) char buf[kStackAllocationSize] __attribute__((uninitialized));
+ for (char* p = buf; p < buf + sizeof(buf); p += 16) {
+ void* q = mte_get_tag(p);
+ if (p != q) {
+ fprintf(stderr, "stack tags mismatch: expected %p, got %p", p, q);
+ exit(1);
+ }
+ }
+}
+
+void check_longjmp_restores_tags() {
+ int value;
+ jmp_buf jb;
+ if ((value = setjmp(jb)) == 0) {
+ settag_and_longjmp(jb);
+ exit(2); // Unreachable.
+ } else {
+ CHECK(value == 42);
+ check_stack_tags();
+ }
+}
+
+class SigAltStackScoped {
+ stack_t old_ss;
+ void* altstack_start;
+ size_t altstack_size;
+
+ public:
+ SigAltStackScoped(size_t sz) : altstack_size(sz) {
+ altstack_start = mmap(nullptr, altstack_size, PROT_READ | PROT_WRITE | PROT_MTE,
+ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+ if (altstack_start == MAP_FAILED) {
+ fprintf(stderr, "sigaltstack mmap failed: %m\n");
+ exit(1);
+ }
+ stack_t ss = {};
+ ss.ss_sp = altstack_start;
+ ss.ss_size = altstack_size;
+ int res = sigaltstack(&ss, &old_ss);
+ CHECK(res == 0);
+ }
+
+ ~SigAltStackScoped() {
+ int res = sigaltstack(&old_ss, nullptr);
+ CHECK(res == 0);
+ munmap(altstack_start, altstack_size);
+ }
+};
+
+class SigActionScoped {
+ int signo;
+ struct sigaction oldsa;
+
+ public:
+ using handler_t = void (*)(int, siginfo_t* siginfo, void*);
+
+ SigActionScoped(int signo, handler_t handler) : signo(signo) {
+ struct sigaction sa = {};
+ sa.sa_sigaction = handler;
+ sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+ int res = sigaction(signo, &sa, &oldsa);
+ CHECK(res == 0);
+ }
+
+ ~SigActionScoped() {
+ int res = sigaction(signo, &oldsa, nullptr);
+ CHECK(res == 0);
+ }
+};
+
+void test_longjmp() {
+ check_longjmp_restores_tags();
+
+ std::thread t([]() { check_longjmp_restores_tags(); });
+ t.join();
+}
+
+void test_longjmp_sigaltstack() {
+ constexpr size_t kAltStackSize = kStackAllocationSize + PAGE_SIZE * 16;
+ SigAltStackScoped sigAltStackScoped(kAltStackSize);
+ SigActionScoped sigActionScoped(
+ SIGUSR1, [](int, siginfo_t*, void*) { check_longjmp_restores_tags(); });
+ raise(SIGUSR1);
+
+ // same for a secondary thread
+ std::thread t([]() {
+ SigAltStackScoped sigAltStackScoped(kAltStackSize);
+ raise(SIGUSR1);
+ });
+ t.join();
+}
+
+void test_android_mallopt() {
+ bool memtag_stack;
+ CHECK(android_mallopt(M_MEMTAG_STACK_IS_ON, &memtag_stack, sizeof(memtag_stack)));
+ CHECK(memtag_stack);
+}
+
+int main(int argc, char** argv) {
+ if (argc < 2) {
+ printf("nothing to do\n");
+ return 1;
+ }
+
+ if (strcmp(argv[1], "vfork_execve") == 0) {
+ test_vfork(ChildAction::Execve);
+ return 0;
+ }
+
+ if (strcmp(argv[1], "vfork_execl") == 0) {
+ test_vfork(ChildAction::Execl);
+ return 0;
+ }
+
+ if (strcmp(argv[1], "vfork_exit") == 0) {
+ test_vfork(ChildAction::Exit);
+ return 0;
+ }
+
+ if (strcmp(argv[1], "longjmp") == 0) {
+ test_longjmp();
+ return 0;
+ }
+
+ if (strcmp(argv[1], "longjmp_sigaltstack") == 0) {
+ test_longjmp_sigaltstack();
+ return 0;
+ }
+
+ if (strcmp(argv[1], "android_mallopt") == 0) {
+ test_android_mallopt();
+ return 0;
+ }
+
+ printf("unrecognized command: %s\n", argv[1]);
+ return 1;
+}
+#else
+int main(int, char**) {
+ printf("aarch64 only\n");
+ return 1;
+}
+#endif // defined(__aarch64__)
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index 69f8506..3cc5bbd 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -1383,6 +1383,15 @@
#endif
}
+TEST(android_mallopt, memtag_stack_is_on) {
+#if defined(__BIONIC__)
+ bool memtag_stack;
+ EXPECT_TRUE(android_mallopt(M_MEMTAG_STACK_IS_ON, &memtag_stack, sizeof(memtag_stack)));
+#else
+ GTEST_SKIP() << "bionic extension";
+#endif
+}
+
void TestHeapZeroing(int num_iterations, int (*get_alloc_size)(int iteration)) {
std::vector<void*> allocs;
constexpr int kMaxBytesToCheckZero = 64;
diff --git a/tests/math_test.cpp b/tests/math_test.cpp
index 76b5078..60872f3 100644
--- a/tests/math_test.cpp
+++ b/tests/math_test.cpp
@@ -1053,22 +1053,22 @@
auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
fesetround(FE_UPWARD); // lrint/lrintf/lrintl obey the rounding mode.
- ASSERT_EQ(1235, lrint(1234.01));
- ASSERT_EQ(1235, lrintf(1234.01f));
- ASSERT_EQ(1235, lrintl(1234.01L));
+ EXPECT_EQ(1235, lrint(1234.01));
+ EXPECT_EQ(1235, lrintf(1234.01f));
+ EXPECT_EQ(1235, lrintl(1234.01L));
fesetround(FE_TOWARDZERO); // lrint/lrintf/lrintl obey the rounding mode.
- ASSERT_EQ(1234, lrint(1234.01));
- ASSERT_EQ(1234, lrintf(1234.01f));
- ASSERT_EQ(1234, lrintl(1234.01L));
+ EXPECT_EQ(1234, lrint(1234.01));
+ EXPECT_EQ(1234, lrintf(1234.01f));
+ EXPECT_EQ(1234, lrintl(1234.01L));
fesetround(FE_UPWARD); // llrint/llrintf/llrintl obey the rounding mode.
- ASSERT_EQ(1235L, llrint(1234.01));
- ASSERT_EQ(1235L, llrintf(1234.01f));
- ASSERT_EQ(1235L, llrintl(1234.01L));
+ EXPECT_EQ(1235L, llrint(1234.01));
+ EXPECT_EQ(1235L, llrintf(1234.01f));
+ EXPECT_EQ(1235L, llrintl(1234.01L));
fesetround(FE_TOWARDZERO); // llrint/llrintf/llrintl obey the rounding mode.
- ASSERT_EQ(1234L, llrint(1234.01));
- ASSERT_EQ(1234L, llrintf(1234.01f));
- ASSERT_EQ(1234L, llrintl(1234.01L));
+ EXPECT_EQ(1234L, llrint(1234.01));
+ EXPECT_EQ(1234L, llrintf(1234.01f));
+ EXPECT_EQ(1234L, llrintl(1234.01L));
}
TEST(MATH_TEST, rint) {
diff --git a/tests/memtag_stack_test.cpp b/tests/memtag_stack_test.cpp
new file mode 100644
index 0000000..84ee8d1
--- /dev/null
+++ b/tests/memtag_stack_test.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <tuple>
+
+#include <gtest/gtest.h>
+
+#if defined(__BIONIC__)
+#include "gtest_globals.h"
+#include "platform/bionic/mte.h"
+#include "utils.h"
+#endif
+
+class MemtagStackTest : public testing::TestWithParam<std::tuple<const char*, bool>> {};
+
+TEST_P(MemtagStackTest, test) {
+#if defined(__BIONIC__) && defined(__aarch64__)
+ if (!mte_supported()) {
+ GTEST_SKIP() << "MTE unsupported";
+ }
+ bool is_static = std::get<1>(GetParam());
+ std::string helper =
+ GetTestlibRoot() + (is_static ? "/stack_tagging_static_helper" : "/stack_tagging_helper");
+ const char* arg = std::get<0>(GetParam());
+ chmod(helper.c_str(), 0755);
+ ExecTestHelper eth;
+ eth.SetArgs({helper.c_str(), arg, nullptr});
+ eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "");
+#else
+ GTEST_SKIP() << "bionic/arm64 only";
+#endif
+}
+
+INSTANTIATE_TEST_SUITE_P(, MemtagStackTest,
+ testing::Combine(testing::Values("vfork_execve", "vfork_execl",
+ "vfork_exit", "longjmp",
+ "longjmp_sigaltstack", "android_mallopt"),
+ testing::Bool()),
+ [](const ::testing::TestParamInfo<MemtagStackTest::ParamType>& info) {
+ std::string s = std::get<0>(info.param);
+ if (std::get<1>(info.param)) s += "_static";
+ return s;
+ });
diff --git a/tests/mte_test.cpp b/tests/mte_test.cpp
index ade9532..5eb804f 100644
--- a/tests/mte_test.cpp
+++ b/tests/mte_test.cpp
@@ -32,6 +32,7 @@
reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(p.get()) + (1ULL << 56));
{
ScopedDisableMTE x;
+ // Test that nested ScopedDisableMTE does not reset MTE state.
{ ScopedDisableMTE y; }
#if defined(__aarch64__)
volatile int load ATTRIBUTE_UNUSED = *mistagged_p;
diff --git a/tests/setjmp_test.cpp b/tests/setjmp_test.cpp
index 472aa20..2f891ec 100644
--- a/tests/setjmp_test.cpp
+++ b/tests/setjmp_test.cpp
@@ -81,8 +81,10 @@
sigset64_t ss;
sigemptyset64(&ss);
sigaddset64(&ss, SIGUSR1 + offset);
+#if defined(__BIONIC__)
// TIMER_SIGNAL.
sigaddset64(&ss, __SIGRTMIN);
+#endif
sigaddset64(&ss, SIGRTMIN + offset);
return ss;
}
@@ -224,13 +226,15 @@
}
#if defined(__arm__)
-#define __JB_SIGFLAG 0
+#define JB_SIGFLAG_OFFSET 0
#elif defined(__aarch64__)
-#define __JB_SIGFLAG 0
+#define JB_SIGFLAG_OFFSET 0
#elif defined(__i386__)
-#define __JB_SIGFLAG 8
+#define JB_SIGFLAG_OFFSET 8
+#elif defined(__riscv)
+#define JB_SIGFLAG_OFFSET 0
#elif defined(__x86_64)
-#define __JB_SIGFLAG 8
+#define JB_SIGFLAG_OFFSET 8
#endif
TEST_F(setjmp_DeathTest, setjmp_cookie) {
@@ -238,7 +242,7 @@
int value = setjmp(jb);
ASSERT_EQ(0, value);
- long* sigflag = reinterpret_cast<long*>(jb) + __JB_SIGFLAG;
+ long* sigflag = reinterpret_cast<long*>(jb) + JB_SIGFLAG_OFFSET;
// Make sure there's actually a cookie.
EXPECT_NE(0, *sigflag & ~1);
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index 5bda8b3..7f7f3db 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -34,6 +34,13 @@
using namespace std::chrono_literals;
+#if defined(ANDROID_HOST_MUSL)
+// Musl doesn't export __SIGRTMIN and __SIGRTMAX, #define
+// them here.
+#define __SIGRTMIN 32
+#define __SIGRTMAX 64
+#endif
+
static int SIGNAL_MIN() {
return 1; // Signals start at 1 (SIGHUP), not 0.
}
diff --git a/tests/stdio_ext_test.cpp b/tests/stdio_ext_test.cpp
index fce600a..dce1a66 100644
--- a/tests/stdio_ext_test.cpp
+++ b/tests/stdio_ext_test.cpp
@@ -78,6 +78,24 @@
fclose(fp);
}
+TEST(stdio_ext, __freadahead) {
+#if defined(__GLIBC__)
+ GTEST_SKIP() << "glibc doesn't have __freadahead";
+#else
+ FILE* fp = tmpfile();
+ ASSERT_NE(EOF, fputs("hello", fp));
+ rewind(fp);
+
+ ASSERT_EQ('h', fgetc(fp));
+ ASSERT_EQ(4u, __freadahead(fp));
+
+ ASSERT_EQ('H', ungetc('H', fp));
+ ASSERT_EQ(5u, __freadahead(fp));
+
+ fclose(fp);
+#endif
+}
+
TEST(stdio_ext, __fpurge) {
FILE* fp = tmpfile();
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 87031f6..acc7ccd 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -25,6 +25,7 @@
#include <sys/cdefs.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>
#include <wchar.h>
@@ -364,13 +365,13 @@
TEST_F(STDIO_DEATHTEST, snprintf_n) {
#if defined(__BIONIC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat"
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat"
// http://b/14492135 and http://b/31832608.
char buf[32];
int i = 1234;
EXPECT_DEATH(snprintf(buf, sizeof(buf), "a %n b", &i), "%n not allowed on Android");
-#pragma GCC diagnostic pop
+#pragma clang diagnostic pop
#else
GTEST_SKIP() << "glibc does allow %n";
#endif
@@ -489,22 +490,22 @@
// NaN.
- snprintf_fn(buf, sizeof(buf), fmt, nanf(""));
+ snprintf_fn(buf, sizeof(buf), fmt, nan(""));
EXPECT_STREQ(nan_, buf) << fmt;
EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
EXPECT_TRUE(isnan(f));
- snprintf_fn(buf, sizeof(buf), fmt, -nanf(""));
+ snprintf_fn(buf, sizeof(buf), fmt, -nan(""));
EXPECT_STREQ(minus_nan, buf) << fmt;
EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
EXPECT_TRUE(isnan(f));
- snprintf_fn(buf, sizeof(buf), fmt_plus, nanf(""));
+ snprintf_fn(buf, sizeof(buf), fmt_plus, nan(""));
EXPECT_STREQ(plus_nan, buf) << fmt_plus;
EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
EXPECT_TRUE(isnan(f));
- snprintf_fn(buf, sizeof(buf), fmt_plus, -nanf(""));
+ snprintf_fn(buf, sizeof(buf), fmt_plus, -nan(""));
EXPECT_STREQ(minus_nan, buf) << fmt_plus;
EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
EXPECT_TRUE(isnan(f));
@@ -2938,3 +2939,245 @@
fclose(fp);
}
+
+#if defined(__LP64__)
+static int64_t GetTotalRamGiB() {
+ struct sysinfo si;
+ sysinfo(&si);
+ return (static_cast<int64_t>(si.totalram) * si.mem_unit) / 1024 / 1024 / 1024;
+}
+#endif
+
+TEST(STDIO_TEST, fread_int_overflow) {
+#if defined(__LP64__)
+ if (GetTotalRamGiB() <= 4) GTEST_SKIP() << "not enough memory";
+
+ const size_t too_big_for_an_int = 0x80000000ULL;
+ std::vector<char> buf(too_big_for_an_int);
+ std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/zero", "re"), fclose};
+ ASSERT_EQ(too_big_for_an_int, fread(&buf[0], 1, too_big_for_an_int, fp.get()));
+#else
+ GTEST_SKIP() << "32-bit can't allocate 2GiB";
+#endif
+}
+
+TEST(STDIO_TEST, fwrite_int_overflow) {
+#if defined(__LP64__)
+ if (GetTotalRamGiB() <= 4) GTEST_SKIP() << "not enough memory";
+
+ const size_t too_big_for_an_int = 0x80000000ULL;
+ std::vector<char> buf(too_big_for_an_int);
+ std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/null", "we"), fclose};
+ ASSERT_EQ(too_big_for_an_int, fwrite(&buf[0], 1, too_big_for_an_int, fp.get()));
+#else
+ GTEST_SKIP() << "32-bit can't allocate 2GiB";
+#endif
+}
+
+TEST(STDIO_TEST, snprintf_b) {
+ // Our clang doesn't know about %b/%B yet.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
+ char buf[BUFSIZ];
+ EXPECT_EQ(5, snprintf(buf, sizeof(buf), "<%b>", 5));
+ EXPECT_STREQ("<101>", buf);
+ EXPECT_EQ(10, snprintf(buf, sizeof(buf), "<%08b>", 5));
+ EXPECT_STREQ("<00000101>", buf);
+ EXPECT_EQ(34, snprintf(buf, sizeof(buf), "<%b>", 0xaaaaaaaa));
+ EXPECT_STREQ("<10101010101010101010101010101010>", buf);
+ EXPECT_EQ(36, snprintf(buf, sizeof(buf), "<%#b>", 0xaaaaaaaa));
+ EXPECT_STREQ("<0b10101010101010101010101010101010>", buf);
+ EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%#b>", 0));
+ EXPECT_STREQ("<0>", buf);
+#pragma clang diagnostic pop
+}
+
+TEST(STDIO_TEST, snprintf_B) {
+ // Our clang doesn't know about %b/%B yet.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
+ char buf[BUFSIZ];
+ EXPECT_EQ(5, snprintf(buf, sizeof(buf), "<%B>", 5));
+ EXPECT_STREQ("<101>", buf);
+ EXPECT_EQ(10, snprintf(buf, sizeof(buf), "<%08B>", 5));
+ EXPECT_STREQ("<00000101>", buf);
+ EXPECT_EQ(34, snprintf(buf, sizeof(buf), "<%B>", 0xaaaaaaaa));
+ EXPECT_STREQ("<10101010101010101010101010101010>", buf);
+ EXPECT_EQ(36, snprintf(buf, sizeof(buf), "<%#B>", 0xaaaaaaaa));
+ EXPECT_STREQ("<0B10101010101010101010101010101010>", buf);
+ EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%#B>", 0));
+ EXPECT_STREQ("<0>", buf);
+#pragma clang diagnostic pop
+}
+
+TEST(STDIO_TEST, swprintf_b) {
+ // Our clang doesn't know about %b/%B yet.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
+ wchar_t buf[BUFSIZ];
+ EXPECT_EQ(5, swprintf(buf, sizeof(buf), L"<%b>", 5));
+ EXPECT_EQ(std::wstring(L"<101>"), buf);
+ EXPECT_EQ(10, swprintf(buf, sizeof(buf), L"<%08b>", 5));
+ EXPECT_EQ(std::wstring(L"<00000101>"), buf);
+ EXPECT_EQ(34, swprintf(buf, sizeof(buf), L"<%b>", 0xaaaaaaaa));
+ EXPECT_EQ(std::wstring(L"<10101010101010101010101010101010>"), buf);
+ EXPECT_EQ(36, swprintf(buf, sizeof(buf), L"<%#b>", 0xaaaaaaaa));
+ EXPECT_EQ(std::wstring(L"<0b10101010101010101010101010101010>"), buf);
+ EXPECT_EQ(3, swprintf(buf, sizeof(buf), L"<%#b>", 0));
+ EXPECT_EQ(std::wstring(L"<0>"), buf);
+#pragma clang diagnostic pop
+}
+
+TEST(STDIO_TEST, swprintf_B) {
+ // Our clang doesn't know about %b/%B yet.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
+ wchar_t buf[BUFSIZ];
+ EXPECT_EQ(5, swprintf(buf, sizeof(buf), L"<%B>", 5));
+ EXPECT_EQ(std::wstring(L"<101>"), buf);
+ EXPECT_EQ(10, swprintf(buf, sizeof(buf), L"<%08B>", 5));
+ EXPECT_EQ(std::wstring(L"<00000101>"), buf);
+ EXPECT_EQ(34, swprintf(buf, sizeof(buf), L"<%B>", 0xaaaaaaaa));
+ EXPECT_EQ(std::wstring(L"<10101010101010101010101010101010>"), buf);
+ EXPECT_EQ(36, swprintf(buf, sizeof(buf), L"<%#B>", 0xaaaaaaaa));
+ EXPECT_EQ(std::wstring(L"<0B10101010101010101010101010101010>"), buf);
+ EXPECT_EQ(3, swprintf(buf, sizeof(buf), L"<%#B>", 0));
+ EXPECT_EQ(std::wstring(L"<0>"), buf);
+#pragma clang diagnostic pop
+}
+
+TEST(STDIO_TEST, scanf_i_decimal) {
+ int i;
+ EXPECT_EQ(1, sscanf("<123789>", "<%i>", &i));
+ EXPECT_EQ(123789, i);
+
+ long long int lli;
+ char ch;
+ EXPECT_EQ(2, sscanf("1234567890abcdefg", "%lli%c", &lli, &ch));
+ EXPECT_EQ(1234567890, lli);
+ EXPECT_EQ('a', ch);
+}
+
+TEST(STDIO_TEST, scanf_i_hex) {
+ int i;
+ EXPECT_EQ(1, sscanf("<0x123abf>", "<%i>", &i));
+ EXPECT_EQ(0x123abf, i);
+
+ long long int lli;
+ char ch;
+ EXPECT_EQ(2, sscanf("0x1234567890abcdefg", "%lli%c", &lli, &ch));
+ EXPECT_EQ(0x1234567890abcdefLL, lli);
+ EXPECT_EQ('g', ch);
+}
+
+TEST(STDIO_TEST, scanf_i_octal) {
+ int i;
+ EXPECT_EQ(1, sscanf("<01234567>", "<%i>", &i));
+ EXPECT_EQ(01234567, i);
+
+ long long int lli;
+ char ch;
+ EXPECT_EQ(2, sscanf("010234567890abcdefg", "%lli%c", &lli, &ch));
+ EXPECT_EQ(010234567, lli);
+ EXPECT_EQ('8', ch);
+}
+
+TEST(STDIO_TEST, scanf_i_binary) {
+ int i;
+ EXPECT_EQ(1, sscanf("<0b101>", "<%i>", &i));
+ EXPECT_EQ(0b101, i);
+
+ long long int lli;
+ char ch;
+ EXPECT_EQ(2, sscanf("0b10234567890abcdefg", "%lli%c", &lli, &ch));
+ EXPECT_EQ(0b10, lli);
+ EXPECT_EQ('2', ch);
+}
+
+TEST(STDIO_TEST, wscanf_i_decimal) {
+ int i;
+ EXPECT_EQ(1, swscanf(L"<123789>", L"<%i>", &i));
+ EXPECT_EQ(123789, i);
+
+ long long int lli;
+ char ch;
+ EXPECT_EQ(2, swscanf(L"1234567890abcdefg", L"%lli%c", &lli, &ch));
+ EXPECT_EQ(1234567890, lli);
+ EXPECT_EQ('a', ch);
+}
+
+TEST(STDIO_TEST, wscanf_i_hex) {
+ int i;
+ EXPECT_EQ(1, swscanf(L"<0x123abf>", L"<%i>", &i));
+ EXPECT_EQ(0x123abf, i);
+
+ long long int lli;
+ char ch;
+ EXPECT_EQ(2, swscanf(L"0x1234567890abcdefg", L"%lli%c", &lli, &ch));
+ EXPECT_EQ(0x1234567890abcdefLL, lli);
+ EXPECT_EQ('g', ch);
+}
+
+TEST(STDIO_TEST, wscanf_i_octal) {
+ int i;
+ EXPECT_EQ(1, swscanf(L"<01234567>", L"<%i>", &i));
+ EXPECT_EQ(01234567, i);
+
+ long long int lli;
+ char ch;
+ EXPECT_EQ(2, swscanf(L"010234567890abcdefg", L"%lli%c", &lli, &ch));
+ EXPECT_EQ(010234567, lli);
+ EXPECT_EQ('8', ch);
+}
+
+TEST(STDIO_TEST, wscanf_i_binary) {
+ int i;
+ EXPECT_EQ(1, swscanf(L"<0b101>", L"<%i>", &i));
+ EXPECT_EQ(0b101, i);
+
+ long long int lli;
+ char ch;
+ EXPECT_EQ(2, swscanf(L"0b10234567890abcdefg", L"%lli%c", &lli, &ch));
+ EXPECT_EQ(0b10, lli);
+ EXPECT_EQ('2', ch);
+}
+
+TEST(STDIO_TEST, scanf_b) {
+ // Our clang doesn't know about %b yet.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat"
+#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
+ int i;
+ char ch;
+ EXPECT_EQ(2, sscanf("<1012>", "<%b%c>", &i, &ch));
+ EXPECT_EQ(0b101, i);
+ EXPECT_EQ('2', ch);
+ EXPECT_EQ(1, sscanf("<00000101>", "<%08b>", &i));
+ EXPECT_EQ(0b00000101, i);
+ EXPECT_EQ(1, sscanf("<0b1010>", "<%b>", &i));
+ EXPECT_EQ(0b1010, i);
+ EXPECT_EQ(2, sscanf("-0b", "%i%c", &i, &ch));
+ EXPECT_EQ(0, i);
+ EXPECT_EQ('b', ch);
+#pragma clang diagnostic pop
+}
+
+TEST(STDIO_TEST, swscanf_b) {
+ // Our clang doesn't know about %b yet.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat"
+#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
+ int i;
+ char ch;
+ EXPECT_EQ(2, swscanf(L"<1012>", L"<%b%c>", &i, &ch));
+ EXPECT_EQ(0b101, i);
+ EXPECT_EQ('2', ch);
+ EXPECT_EQ(1, swscanf(L"<00000101>", L"<%08b>", &i));
+ EXPECT_EQ(0b00000101, i);
+ EXPECT_EQ(1, swscanf(L"<0b1010>", L"<%b>", &i));
+ EXPECT_EQ(0b1010, i);
+ EXPECT_EQ(2, swscanf(L"-0b", L"%i%c", &i, &ch));
+ EXPECT_EQ(0, i);
+ EXPECT_EQ('b', ch);
+#pragma clang diagnostic pop
+}
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 465e61a..f507e08 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -843,11 +843,19 @@
ASSERT_EQ(T(-123), fn("-123", &end_p, 10));
ASSERT_EQ(T(123), fn("+123", &end_p, 10));
+ // If we see "0b" *not* followed by a binary digit, we shouldn't swallow the 'b'.
+ ASSERT_EQ(T(0), fn("0b", &end_p, 2));
+ ASSERT_EQ('b', *end_p);
+
+ // Binary (the "0b" prefix) is case-insensitive.
+ ASSERT_EQ(T(0b101), fn("0b101", &end_p, 0));
+ ASSERT_EQ(T(0b101), fn("0B101", &end_p, 0));
+
// If we see "0x" *not* followed by a hex digit, we shouldn't swallow the 'x'.
ASSERT_EQ(T(0), fn("0xy", &end_p, 16));
ASSERT_EQ('x', *end_p);
- // Hexadecimal (both the 0x and the digits) is case-insensitive.
+ // Hexadecimal (both the "0x" prefix and the digits) is case-insensitive.
ASSERT_EQ(T(0xab), fn("0xab", &end_p, 0));
ASSERT_EQ(T(0xab), fn("0Xab", &end_p, 0));
ASSERT_EQ(T(0xab), fn("0xAB", &end_p, 0));
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index 8d3fb68..38957e2 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -136,7 +136,7 @@
// A real-time signal.
ASSERT_STREQ("Real-time signal 14", strsignal(SIGRTMIN + 14));
// One of the signals the C library keeps to itself.
- ASSERT_STREQ("Unknown signal 32", strsignal(__SIGRTMIN));
+ ASSERT_STREQ("Unknown signal 32", strsignal(32)); // __SIGRTMIN
// Errors.
ASSERT_STREQ("Unknown signal -1", strsignal(-1)); // Too small.
@@ -1673,3 +1673,15 @@
ASSERT_EQ(nullptr, memccpy(dst, "hello world", ' ', 4));
ASSERT_STREQ("hell", dst);
}
+
+TEST(STRING_TEST, memset_explicit_smoke) {
+#if defined(__BIONIC__)
+ // We can't reliably test that the compiler won't optimize out calls to
+ // memset_explicit(), but we can at least check that it behaves like memset.
+ char buf[32];
+ memset_explicit(buf, 'x', sizeof(buf));
+ ASSERT_TRUE(memcmp(buf, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", sizeof(buf)) == 0);
+#else
+ GTEST_SKIP() << "memset_explicit not available";
+#endif
+}
diff --git a/tests/struct_layout_test.cpp b/tests/struct_layout_test.cpp
index 0123ed9..10c100a 100644
--- a/tests/struct_layout_test.cpp
+++ b/tests/struct_layout_test.cpp
@@ -30,7 +30,7 @@
#define CHECK_OFFSET(name, field, offset) \
check_offset(#name, #field, offsetof(name, field), offset);
#ifdef __LP64__
- CHECK_SIZE(pthread_internal_t, 776);
+ CHECK_SIZE(pthread_internal_t, 784);
CHECK_OFFSET(pthread_internal_t, next, 0);
CHECK_OFFSET(pthread_internal_t, prev, 8);
CHECK_OFFSET(pthread_internal_t, tid, 16);
@@ -55,6 +55,7 @@
CHECK_OFFSET(pthread_internal_t, dlerror_buffer, 248);
CHECK_OFFSET(pthread_internal_t, bionic_tls, 760);
CHECK_OFFSET(pthread_internal_t, errno_value, 768);
+ CHECK_OFFSET(pthread_internal_t, vfork_child_stack_bottom, 776);
CHECK_SIZE(bionic_tls, 12200);
CHECK_OFFSET(bionic_tls, key_data, 0);
CHECK_OFFSET(bionic_tls, locale, 2080);
@@ -72,7 +73,7 @@
CHECK_OFFSET(bionic_tls, bionic_systrace_disabled, 12193);
CHECK_OFFSET(bionic_tls, padding, 12194);
#else
- CHECK_SIZE(pthread_internal_t, 668);
+ CHECK_SIZE(pthread_internal_t, 672);
CHECK_OFFSET(pthread_internal_t, next, 0);
CHECK_OFFSET(pthread_internal_t, prev, 4);
CHECK_OFFSET(pthread_internal_t, tid, 8);
@@ -97,6 +98,7 @@
CHECK_OFFSET(pthread_internal_t, dlerror_buffer, 148);
CHECK_OFFSET(pthread_internal_t, bionic_tls, 660);
CHECK_OFFSET(pthread_internal_t, errno_value, 664);
+ CHECK_OFFSET(pthread_internal_t, vfork_child_stack_bottom, 668);
CHECK_SIZE(bionic_tls, 11080);
CHECK_OFFSET(bionic_tls, key_data, 0);
CHECK_OFFSET(bionic_tls, locale, 1040);
diff --git a/tests/sys_sysinfo_test.cpp b/tests/sys_sysinfo_test.cpp
index cca2f44..69656ad 100644
--- a/tests/sys_sysinfo_test.cpp
+++ b/tests/sys_sysinfo_test.cpp
@@ -43,7 +43,7 @@
memset(&si, 0, sizeof(si));
ASSERT_EQ(0, sysinfo(&si));
- ASSERT_GT(si.uptime, 10); // You're not running CTS within 10s of booting!
+ ASSERT_GT(static_cast<long>(si.uptime), 10); // You're not running CTS within 10s of booting!
ASSERT_GT(uint64_t(si.totalram) * si.mem_unit, uint64_t(512 * 1024 * 1024));
ASSERT_GE(si.totalram, si.freeram);
ASSERT_GE(si.totalswap, si.freeswap);
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 5fc4cad..40e5c6d 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -84,6 +84,16 @@
ASSERT_EQ(1970, broken_down->tm_year + 1900);
}
+TEST(time, mktime_TZ_as_UTC_and_offset) {
+ struct tm tm = {.tm_year = 70, .tm_mon = 0, .tm_mday = 1};
+
+ // This TZ value is not a valid Olson ID and is not present in tzdata file,
+ // but is a valid TZ string according to POSIX standard.
+ setenv("TZ", "UTC+08:00:00", 1);
+ tzset();
+ ASSERT_EQ(static_cast<time_t>(8 * 60 * 60), mktime(&tm));
+}
+
static void* gmtime_no_stack_overflow_14313703_fn(void*) {
const char* original_tz = getenv("TZ");
// Ensure we'll actually have to enter tzload by using a time zone that doesn't exist.
@@ -134,15 +144,11 @@
}
TEST(time, mktime_10310929) {
- struct tm t;
- memset(&t, 0, sizeof(tm));
- t.tm_year = 200;
- t.tm_mon = 2;
- t.tm_mday = 10;
+ struct tm tm = {.tm_year = 2100 - 1900, .tm_mon = 2, .tm_mday = 10};
#if !defined(__LP64__)
// 32-bit bionic has a signed 32-bit time_t.
- ASSERT_EQ(-1, mktime(&t));
+ ASSERT_EQ(-1, mktime(&tm));
ASSERT_EQ(EOVERFLOW, errno);
#else
// Everyone else should be using a signed 64-bit time_t.
@@ -151,13 +157,12 @@
setenv("TZ", "America/Los_Angeles", 1);
tzset();
errno = 0;
- ASSERT_EQ(static_cast<time_t>(4108348800U), mktime(&t));
- ASSERT_EQ(0, errno);
- setenv("TZ", "UTC", 1);
- tzset();
- errno = 0;
- ASSERT_EQ(static_cast<time_t>(4108320000U), mktime(&t));
+ // On the date/time specified by tm America/Los_Angeles
+ // follows DST. But tm_isdst is set to 0, which forces
+ // mktime to interpret that time as local standard, hence offset
+ // is 8 hours, not 7.
+ ASSERT_EQ(static_cast<time_t>(4108348800U), mktime(&tm));
ASSERT_EQ(0, errno);
#endif
}
@@ -184,6 +189,43 @@
ASSERT_EQ(EOVERFLOW, errno);
}
+TEST(time, mktime_invalid_tm_TZ_combination) {
+ setenv("TZ", "UTC", 1);
+
+ struct tm t;
+ memset(&t, 0, sizeof(tm));
+ t.tm_year = 2022 - 1900;
+ t.tm_mon = 11;
+ t.tm_mday = 31;
+ // UTC does not observe DST
+ t.tm_isdst = 1;
+
+ errno = 0;
+
+ EXPECT_EQ(static_cast<time_t>(-1), mktime(&t));
+ // mktime sets errno to EOVERFLOW if result is unrepresentable.
+ EXPECT_EQ(EOVERFLOW, errno);
+}
+
+// Transitions in the tzdata file are generated up to the year 2100. Testing
+// that dates beyond that are handled properly too.
+TEST(time, mktime_after_2100) {
+ struct tm tm = {.tm_year = 2150 - 1900, .tm_mon = 2, .tm_mday = 10, .tm_isdst = -1};
+
+#if !defined(__LP64__)
+ // 32-bit bionic has a signed 32-bit time_t.
+ ASSERT_EQ(-1, mktime(&tm));
+ ASSERT_EQ(EOVERFLOW, errno);
+#else
+ setenv("TZ", "Europe/London", 1);
+ tzset();
+ errno = 0;
+
+ ASSERT_EQ(static_cast<time_t>(5686156800U), mktime(&tm));
+ ASSERT_EQ(0, errno);
+#endif
+}
+
TEST(time, strftime) {
setenv("TZ", "UTC", 1);
@@ -206,7 +248,25 @@
EXPECT_STREQ("Sun Mar 10 00:00:00 2100", buf);
}
-TEST(time, strftime_null_tm_zone) {
+TEST(time, strftime_second_before_epoch) {
+ setenv("TZ", "UTC", 1);
+
+ struct tm t;
+ memset(&t, 0, sizeof(tm));
+ t.tm_year = 1969 - 1900;
+ t.tm_mon = 11;
+ t.tm_mday = 31;
+ t.tm_hour = 23;
+ t.tm_min = 59;
+ t.tm_sec = 59;
+
+ char buf[64];
+
+ EXPECT_EQ(2U, strftime(buf, sizeof(buf), "%s", &t));
+ EXPECT_STREQ("-1", buf);
+}
+
+TEST(time, strftime_Z_null_tm_zone) {
// Netflix on Nexus Player wouldn't start (http://b/25170306).
struct tm t;
memset(&t, 0, sizeof(tm));
@@ -244,6 +304,86 @@
#endif
}
+// According to C language specification the only tm struct field needed to
+// find out replacement for %z and %Z in strftime is tm_isdst. Which is
+// wrong, as time zones change their standard offset and even DST savings.
+// tzcode deviates from C language specification and requires tm struct either
+// to be output of localtime-like functions or to be modified by mktime call
+// before passing to strftime. See tz mailing discussion for more details
+// https://mm.icann.org/pipermail/tz/2022-July/031674.html
+// But we are testing case when tm.tm_zone is null, which means that tm struct
+// is not coming from localtime and is neither modified by mktime. That's why
+// we are comparing against +0000, even though America/Los_Angeles never
+// observes it.
+TEST(time, strftime_z_null_tm_zone) {
+ char str[64];
+ struct tm tm = {.tm_year = 109, .tm_mon = 4, .tm_mday = 2, .tm_isdst = 0};
+
+ setenv("TZ", "America/Los_Angeles", 1);
+ tzset();
+
+ tm.tm_zone = NULL;
+
+ size_t result = strftime(str, sizeof(str), "%z", &tm);
+
+ EXPECT_EQ(5U, result);
+ EXPECT_STREQ("+0000", str);
+
+ tm.tm_isdst = 1;
+
+ result = strftime(str, sizeof(str), "%z", &tm);
+
+ EXPECT_EQ(5U, result);
+ EXPECT_STREQ("+0000", str);
+
+ setenv("TZ", "UTC", 1);
+ tzset();
+
+ tm.tm_isdst = 0;
+
+ result = strftime(str, sizeof(str), "%z", &tm);
+
+ EXPECT_EQ(5U, result);
+ EXPECT_STREQ("+0000", str);
+
+ tm.tm_isdst = 1;
+
+ result = strftime(str, sizeof(str), "%z", &tm);
+
+ EXPECT_EQ(5U, result);
+ EXPECT_STREQ("+0000", str);
+}
+
+TEST(time, strftime_z_Europe_Lisbon) {
+ char str[64];
+ // During 1992-1996 Europe/Lisbon standard offset was 1 hour.
+ // tm_isdst is not set as it will be overridden by mktime call anyway.
+ struct tm tm = {.tm_year = 1996 - 1900, .tm_mon = 2, .tm_mday = 13};
+
+ setenv("TZ", "Europe/Lisbon", 1);
+ tzset();
+
+ // tzcode's strftime implementation for %z relies on prior mktime call.
+ // At the moment of writing %z value is taken from tm_gmtoff. So without
+ // mktime call %z is replaced with +0000.
+ // See https://mm.icann.org/pipermail/tz/2022-July/031674.html
+ mktime(&tm);
+
+ size_t result = strftime(str, sizeof(str), "%z", &tm);
+
+ EXPECT_EQ(5U, result);
+ EXPECT_STREQ("+0100", str);
+
+ // Now standard offset is 0.
+ tm = {.tm_year = 2022 - 1900, .tm_mon = 2, .tm_mday = 13};
+
+ mktime(&tm);
+ result = strftime(str, sizeof(str), "%z", &tm);
+
+ EXPECT_EQ(5U, result);
+ EXPECT_STREQ("+0000", str);
+}
+
TEST(time, strftime_l) {
locale_t cloc = newlocale(LC_ALL, "C.UTF-8", nullptr);
locale_t old_locale = uselocale(cloc);
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 6d7e687..5fce5b8 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -1103,6 +1103,10 @@
ASSERT_EQ(4, GetCpuCountFromString("0, 1-2, 4\n"));
}
+TEST(UNISTD_TEST, sysconf_SC_NPROCESSORS_make_sense) {
+ ASSERT_LE(sysconf(_SC_NPROCESSORS_ONLN), sysconf(_SC_NPROCESSORS_CONF));
+}
+
TEST(UNISTD_TEST, sysconf_SC_NPROCESSORS_ONLN) {
std::string line;
ASSERT_TRUE(android::base::ReadFileToString("/sys/devices/system/cpu/online", &line));
@@ -1648,3 +1652,41 @@
auto t1 = std::chrono::steady_clock::now();
ASSERT_GE(t1-t0, 1s);
}
+
+TEST(UNISTD_TEST, close_range) {
+#if defined(__GLIBC__)
+ GTEST_SKIP() << "glibc too old";
+#elif defined(ANDROID_HOST_MUSL)
+ GTEST_SKIP() << "musl does not have close_range";
+#else // __GLIBC__
+ int fd = open("/proc/version", O_RDONLY);
+ ASSERT_GE(fd, 0);
+
+ // Try to close the file descriptor (this requires a 5.9+ kernel)
+ if (close_range(fd, fd, 0) == 0) {
+ // we can't close it *again*
+ ASSERT_EQ(close(fd), -1);
+ ASSERT_EQ(errno, EBADF);
+ } else {
+ ASSERT_EQ(errno, ENOSYS);
+ // since close_range() failed, we can close it normally
+ ASSERT_EQ(close(fd), 0);
+ }
+#endif // __GLIBC__
+}
+
+TEST(UNISTD_TEST, copy_file_range) {
+#if defined(__GLIBC__)
+ GTEST_SKIP() << "glibc too old";
+#else // __GLIBC__
+ TemporaryFile tf;
+ ASSERT_TRUE(android::base::WriteStringToFd("hello world", tf.fd));
+ ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+ TemporaryFile tf2;
+ ASSERT_EQ(11, copy_file_range(tf.fd, NULL, tf2.fd, NULL, 11, 0));
+ ASSERT_EQ(0, lseek(tf2.fd, SEEK_SET, 0));
+ std::string content;
+ ASSERT_TRUE(android::base::ReadFdToString(tf2.fd, &content));
+ ASSERT_EQ("hello world", content);
+#endif // __GLIBC__
+}
diff --git a/tests/utils.cpp b/tests/utils.cpp
new file mode 100644
index 0000000..8258833
--- /dev/null
+++ b/tests/utils.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "utils.h"
+
+void RunGwpAsanTest(const char* test_name) {
+ ExecTestHelper eh;
+ eh.SetEnv({"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1", "GWP_ASAN_MAX_ALLOCS=40000",
+ nullptr});
+ std::string filter_arg = "--gtest_filter=";
+ filter_arg += test_name;
+ std::string exec(testing::internal::GetArgvs()[0]);
+ eh.SetArgs({exec.c_str(), "--gtest_also_run_disabled_tests", filter_arg.c_str(), nullptr});
+ eh.Run([&]() { execve(exec.c_str(), eh.GetArgs(), eh.GetEnv()); },
+ /* expected_exit_status */ 0,
+ // |expected_output_regex|, ensure at least one test ran:
+ R"(\[ PASSED \] [1-9][0-9]* test)");
+}
+
+void RunSubtestNoEnv(const char* test_name) {
+ ExecTestHelper eh;
+ std::string filter_arg = "--gtest_filter=";
+ filter_arg += test_name;
+ std::string exec(testing::internal::GetArgvs()[0]);
+ eh.SetArgs({exec.c_str(), "--gtest_also_run_disabled_tests", filter_arg.c_str(), nullptr});
+ eh.Run([&]() { execve(exec.c_str(), eh.GetArgs(), eh.GetEnv()); },
+ /* expected_exit_status */ 0,
+ // |expected_output_regex|, ensure at least one test ran:
+ R"(\[ PASSED \] [1-9]+0? test)");
+}
diff --git a/tests/utils.h b/tests/utils.h
index 72214c2..81869e3 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -19,6 +19,7 @@
#include <dirent.h>
#include <dlfcn.h>
#include <fcntl.h>
+#include <gtest/gtest.h>
#include <inttypes.h>
#include <sys/mman.h>
#include <sys/prctl.h>
@@ -264,6 +265,7 @@
};
void RunGwpAsanTest(const char* test_name);
+void RunSubtestNoEnv(const char* test_name);
#endif
class FdLeakChecker {
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 85a75ec..16d4348 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -460,6 +460,7 @@
TestSingleWcsToInt(fn, L" 123 45", 0, static_cast<T>(123), 6);
TestSingleWcsToInt(fn, L" -123", 0, static_cast<T>(-123), 6);
TestSingleWcsToInt(fn, L"0x10000", 0, static_cast<T>(65536), 7);
+ TestSingleWcsToInt(fn, L"0b1011", 0, static_cast<T>(0b1011), 6);
}
template <typename T>
diff --git a/tools/Android.bp b/tools/Android.bp
index dcd2a7d..d3ca28a 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -15,7 +15,7 @@
subdirs = ["*"]
-filegroup {
- name: "bionic-generate-version-script",
+python_binary_host {
+ name: "generate-version-script",
srcs: ["generate-version-script.py"],
}
diff --git a/tools/generate-version-script.py b/tools/generate-version-script.py
index def621e..fab46b9 100755
--- a/tools/generate-version-script.py
+++ b/tools/generate-version-script.py
@@ -8,7 +8,7 @@
import sys
def has_arch_tags(tags):
- for arch in ["arm", "arm64", "x86", "x86_64"]:
+ for arch in ["arm", "arm64", "riscv64", "x86", "x86_64"]:
if arch in tags:
return True
return False
diff --git a/tools/versioner/src/Arch.cpp b/tools/versioner/src/Arch.cpp
index 3a27a6e..d4d0208 100644
--- a/tools/versioner/src/Arch.cpp
+++ b/tools/versioner/src/Arch.cpp
@@ -28,6 +28,9 @@
case Arch::arm64:
return "arm64";
+ case Arch::riscv64:
+ return "riscv64";
+
case Arch::x86:
return "x86";
@@ -41,6 +44,7 @@
static const std::unordered_map<std::string, Arch> arch_name_map{
{"arm", Arch::arm},
{"arm64", Arch::arm64},
+ {"riscv64", Arch::riscv64},
{"x86", Arch::x86},
{"x86_64", Arch::x86_64},
};
diff --git a/tools/versioner/src/Arch.h b/tools/versioner/src/Arch.h
index 74d0f8f..fd98abc 100644
--- a/tools/versioner/src/Arch.h
+++ b/tools/versioner/src/Arch.h
@@ -28,6 +28,7 @@
enum class Arch : size_t {
arm = 0,
arm64,
+ riscv64,
x86,
x86_64,
};
@@ -121,6 +122,7 @@
static const std::set<Arch> supported_archs = {
Arch::arm,
Arch::arm64,
+ Arch::riscv64,
Arch::x86,
Arch::x86_64,
};
@@ -128,17 +130,19 @@
static ArchMap<std::string> arch_targets = {
{ Arch::arm, "arm-linux-androideabi" },
{ Arch::arm64, "aarch64-linux-android" },
+ { Arch::riscv64, "riscv64-linux-android" },
{ Arch::x86, "i686-linux-android" },
{ Arch::x86_64, "x86_64-linux-android" },
};
static const std::set<int> default_levels = {
- 14, 15, 16, 17, 18, 19, 21, 23, 24, 25, 26, 27, 28, 29, 30,
+ 14, 15, 16, 17, 18, 19, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 34,
};
static const ArchMap<int> arch_min_api = {
{ Arch::arm, 9 },
{ Arch::arm64, 21 },
+ { Arch::riscv64, 10000 },
{ Arch::x86, 9 },
{ Arch::x86_64, 21 },
};
@@ -160,4 +164,7 @@
{"P", 28},
{"Q", 29},
{"R", 30},
+ {"S", 31},
+ {"T", 33},
+ {"U", 34},
};
diff --git a/tools/versioner/src/DeclarationDatabase.cpp b/tools/versioner/src/DeclarationDatabase.cpp
index ec2e38d..a029c3b 100644
--- a/tools/versioner/src/DeclarationDatabase.cpp
+++ b/tools/versioner/src/DeclarationDatabase.cpp
@@ -170,6 +170,7 @@
&arch_availability[Arch::x86].introduced } },
{ "introduced_in_64",
{ &arch_availability[Arch::arm64].introduced,
+ &arch_availability[Arch::riscv64].introduced,
&arch_availability[Arch::x86_64].introduced } },
};
diff --git a/tools/versioner/src/Preprocessor.cpp b/tools/versioner/src/Preprocessor.cpp
index eb88c46..14f80d8 100644
--- a/tools/versioner/src/Preprocessor.cpp
+++ b/tools/versioner/src/Preprocessor.cpp
@@ -141,11 +141,12 @@
static const std::vector<std::pair<std::string, std::set<Arch>>> arch_sets = {
{ "", supported_archs },
{ "!defined(__LP64__)", { Arch::arm, Arch::x86 } },
- { "defined(__LP64__)", { Arch::arm64, Arch::x86_64 } },
+ { "defined(__LP64__)", { Arch::arm64, Arch::riscv64, Arch::x86_64 } },
};
std::map<Arch, std::string> individual_archs = {
{ Arch::arm, "defined(__arm__)" },
{ Arch::arm64, "defined(__aarch64__)" },
+ { Arch::riscv64, "defined(__riscv)" },
{ Arch::x86, "defined(__i386__)" },
{ Arch::x86_64, "defined(__x86_64__)" },
};
diff --git a/tools/versioner/src/versioner.h b/tools/versioner/src/versioner.h
index e9c4989..225e14b 100644
--- a/tools/versioner/src/versioner.h
+++ b/tools/versioner/src/versioner.h
@@ -39,5 +39,5 @@
{ "sys/_system_properties.h", supported_archs },
// time64.h #errors when included on LP64 archs.
- { "time64.h", { Arch::arm64, Arch::x86_64 } },
+ { "time64.h", { Arch::arm64, Arch::riscv64, Arch::x86_64 } },
};