Merge "[MTE] Allow remote mode override for process."
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 08fac4f..18e8bbc 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -38,6 +38,9 @@
},
{
"name": "memunreachable_unit_test"
+ },
+ {
+ "name": "toybox-tests"
}
],
"hwasan-presubmit": [
@@ -76,6 +79,9 @@
},
{
"name": "memunreachable_unit_test"
+ },
+ {
+ "name": "toybox-tests"
}
]
}
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..de1eed1 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -29,6 +29,7 @@
* `gethostid`
* `shm_open`/`shm_unlink`
* `sockatmark`
+ * `ualarm`
Missing functionality:
* `<aio.h>`
diff --git a/libc/Android.bp b/libc/Android.bp
index 97146aa..b7cb59d 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -259,18 +259,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 +376,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",
],
},
},
@@ -923,24 +926,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 +971,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 +981,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 +994,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",
@@ -1303,8 +1298,8 @@
name: "syscalls-arm.S",
out: ["syscalls-arm.S"],
srcs: ["SYSCALLS.TXT"],
- tool_files: [":bionic-gensyscalls"],
- cmd: "$(location :bionic-gensyscalls) arm $(in) > $(out)",
+ tools: ["gensyscalls"],
+ cmd: "$(location gensyscalls) arm $(in) > $(out)",
bazel_module: {
bp2build_available: true,
}
@@ -1314,8 +1309,8 @@
name: "syscalls-arm64.S",
out: ["syscalls-arm64.S"],
srcs: ["SYSCALLS.TXT"],
- tool_files: [":bionic-gensyscalls"],
- cmd: "$(location :bionic-gensyscalls) arm64 $(in) > $(out)",
+ tools: ["gensyscalls"],
+ cmd: "$(location gensyscalls) arm64 $(in) > $(out)",
bazel_module: {
bp2build_available: true,
},
@@ -1325,8 +1320,8 @@
name: "syscalls-x86.S",
out: ["syscalls-x86.S"],
srcs: ["SYSCALLS.TXT"],
- tool_files: [":bionic-gensyscalls"],
- cmd: "$(location :bionic-gensyscalls) x86 $(in) > $(out)",
+ tools: ["gensyscalls"],
+ cmd: "$(location gensyscalls) x86 $(in) > $(out)",
bazel_module: {
bp2build_available: true,
},
@@ -1336,8 +1331,8 @@
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)",
+ tools: ["gensyscalls"],
+ cmd: "$(location gensyscalls) x86_64 $(in) > $(out)",
bazel_module: {
bp2build_available: true,
},
@@ -1511,6 +1506,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 +1534,9 @@
"-fno-jump-tables",
],
arch: {
+ x86_64: {
+ srcs: ["arch-x86_64/dynamic_function_dispatch.cpp"],
+ },
x86: {
srcs: ["arch-x86/dynamic_function_dispatch.cpp"],
},
@@ -1686,8 +1687,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.
@@ -1807,8 +1808,8 @@
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)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) arm $(in) $(out)",
bazel_module: { bp2build_available: true },
}
@@ -1816,8 +1817,8 @@
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)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) arm64 $(in) $(out)",
bazel_module: { bp2build_available: true },
}
@@ -1825,8 +1826,8 @@
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)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) x86 $(in) $(out)",
bazel_module: { bp2build_available: true },
}
@@ -1834,8 +1835,8 @@
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)",
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) x86_64 $(in) $(out)",
bazel_module: { bp2build_available: true },
}
@@ -2036,32 +2037,32 @@
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++.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)",
}
// ========================================================
diff --git a/libc/BUILD b/libc/BUILD
new file mode 100644
index 0000000..e26c026
--- /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",
+ library_name="libc",
+ api=":libc.map.txt",
+ hdrs=[
+ "//bionic/libc/kernel/android:libc_kernel_android_uapi_headers",
+ "//bionic/libc/kernel/android:libc_kernel_android_scsi_headers",
+ "//bionic/libc/kernel/uapi:libc_kernel_uapi_headers",
+ "//bionic/libc/kernel/uapi:libc_kernal_uapi_asm_arm_headers", #arm
+ "//bionic/libc/kernel/uapi:libc_kernal_uapi_asm_arm64_headers", #arm64
+ "//bionic/libc/kernel/uapi:libc_kernal_uapi_asm_x86_headers", #x86
+ "//bionic/libc/kernel/uapi:libc_kernal_uapi_asm_x86_64_headers", #x86_64
+ ],
+)
diff --git a/libc/NOTICE b/libc/NOTICE
index 9cbbde2..fa3dd2c 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.
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/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/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/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/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..536b8c3 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -460,8 +460,6 @@
#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
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/uapi/BUILD b/libc/kernel/uapi/BUILD
new file mode 100644
index 0000000..2f92464
--- /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_kernal_uapi_asm_arm_headers",
+ include_dir="asm-arm",
+ hdrs=glob(["asm-arm/**/*.h"]),
+ system=True,
+ arch="arm",
+)
+
+cc_api_headers(
+ name="libc_kernal_uapi_asm_arm64_headers",
+ include_dir="asm-arm64",
+ hdrs=glob(["asm-arm64/**/*.h"]),
+ system=True,
+ arch="arm64",
+)
+
+cc_api_headers(
+ name="libc_kernal_uapi_asm_x86_headers",
+ include_dir="asm-x86",
+ hdrs=glob(["asm-x86/**/*.h"]),
+ system=True,
+ arch="x86",
+)
+
+cc_api_headers(
+ name="libc_kernal_uapi_asm_x86_64_headers",
+ include_dir="asm-x86_64",
+ hdrs=glob(["asm-x86_64/**/*.h"]),
+ system=True,
+ arch="x86_64",
+)
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..e0dbb13 100644
--- a/libc/kernel/uapi/asm-arm64/asm/hwcap.h
+++ b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
@@ -72,4 +72,5 @@
#define HWCAP2_ECV (1 << 19)
#define HWCAP2_AFP (1 << 20)
#define HWCAP2_RPRES (1 << 21)
+#define HWCAP2_MTE3 (1 << 22)
#endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/kvm.h b/libc/kernel/uapi/asm-arm64/asm/kvm.h
index c53ee87..eee066b 100644
--- a/libc/kernel/uapi/asm-arm64/asm/kvm.h
+++ b/libc/kernel/uapi/asm-arm64/asm/kvm.h
@@ -214,6 +214,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 +245,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-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/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..6926187 100644
--- a/libc/kernel/uapi/asm-generic/socket.h
+++ b/libc/kernel/uapi/asm-generic/socket.h
@@ -100,6 +100,7 @@
#define SO_NETNS_COOKIE 71
#define SO_BUF_LOCK 72
#define SO_RESERVE_MEM 73
+#define SO_TXREHASH 74
#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-x86/asm/amd_hsmp.h b/libc/kernel/uapi/asm-x86/asm/amd_hsmp.h
new file mode 100644
index 0000000..ed59bb8
--- /dev/null
+++ b/libc/kernel/uapi/asm-x86/asm/amd_hsmp.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** 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_DDR_BANDWIDTH = 0x14,
+ HSMP_GET_TEMP_MONITOR,
+ 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
+ }
+ , {
+ 0, 0, HSMP_RSVD
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ , {
+ 0, 1, HSMP_GET
+ }
+ ,
+};
+#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/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/drm/amdgpu_drm.h b/libc/kernel/uapi/drm/amdgpu_drm.h
index 3764d51..f38b612 100644
--- a/libc/kernel/uapi/drm/amdgpu_drm.h
+++ b/libc/kernel/uapi/drm/amdgpu_drm.h
@@ -112,6 +112,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 +129,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 +151,10 @@
__u32 hangs;
__u32 reset_status;
} state;
+ struct {
+ __u32 flags;
+ __u32 _pad;
+ } pstate;
};
union drm_amdgpu_ctx {
struct drm_amdgpu_ctx_in in;
@@ -438,6 +450,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
@@ -682,6 +695,8 @@
#define AMDGPU_FAMILY_NV 143
#define AMDGPU_FAMILY_VGH 144
#define AMDGPU_FAMILY_YC 146
+#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/msm_drm.h b/libc/kernel/uapi/drm/msm_drm.h
index b4ba1d0..376f909 100644
--- a/libc/kernel/uapi/drm/msm_drm.h
+++ b/libc/kernel/uapi/drm/msm_drm.h
@@ -43,6 +43,7 @@
#define MSM_PARAM_PP_PGTABLE 0x08
#define MSM_PARAM_FAULTS 0x09
#define MSM_PARAM_SUSPENDS 0x0a
+#define MSM_PARAM_SYSPROF 0x0b
#define MSM_PARAM_NR_RINGS MSM_PARAM_PRIORITIES
struct drm_msm_param {
__u32 pipe;
@@ -119,7 +120,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 +174,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 +186,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/linux/android/binder.h b/libc/kernel/uapi/linux/android/binder.h
index ded1756..34ccf44 100644
--- a/libc/kernel/uapi/linux/android/binder.h
+++ b/libc/kernel/uapi/linux/android/binder.h
@@ -155,7 +155,11 @@
binder_uintptr_t cookie;
__u32 code;
__u32 flags;
- pid_t sender_pid;
+ __kernel_pid_t sender_pid;
+ /* Modified to __kernel_uid_t in the headers but this is not the same size
+ * as uid_t on 32 bit systems. This is fixed in upstream, but wait until
+ * 5.19 to get the fix. See b/234125620.
+ */
uid_t sender_euid;
binder_size_t data_size;
binder_size_t offsets_size;
diff --git a/libc/kernel/uapi/linux/bpf.h b/libc/kernel/uapi/linux/bpf.h
index d363e81..8de48a1 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,7 @@
BPF_LINK_TYPE_NETNS = 5,
BPF_LINK_TYPE_XDP = 6,
BPF_LINK_TYPE_PERF_EVENT = 7,
+ BPF_LINK_TYPE_KPROBE_MULTI = 8,
MAX_BPF_LINK_TYPE,
};
#define BPF_F_ALLOW_OVERRIDE (1U << 0)
@@ -250,6 +252,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 +285,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 +397,7 @@
__aligned_u64 ctx_out;
__u32 flags;
__u32 cpu;
+ __u32 batch_size;
} test;
struct {
union {
@@ -456,6 +462,13 @@
struct {
__u64 bpf_cookie;
} perf_event;
+ struct {
+ __u32 flags;
+ __u32 cnt;
+ __aligned_u64 syms;
+ __aligned_u64 addrs;
+ __aligned_u64 cookies;
+ } kprobe_multi;
};
} link_create;
struct {
@@ -480,7 +493,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),
#define __BPF_ENUM_FN(x) BPF_FUNC_ ##x
enum bpf_func_id {
__BPF_FUNC_MAPPER(__BPF_ENUM_FN) __BPF_FUNC_MAX_ID,
@@ -595,6 +608,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 +645,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 {
@@ -668,7 +686,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;
@@ -1160,7 +1179,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..8e3c6fe 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
diff --git a/libc/kernel/uapi/linux/can/isotp.h b/libc/kernel/uapi/linux/can/isotp.h
index dd5e4f5..57d3001 100644
--- a/libc/kernel/uapi/linux/can/isotp.h
+++ b/libc/kernel/uapi/linux/can/isotp.h
@@ -59,11 +59,12 @@
#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/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.h b/libc/kernel/uapi/linux/elf.h
index 7655f12..65ab245 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
diff --git a/libc/kernel/uapi/linux/ethtool_netlink.h b/libc/kernel/uapi/linux/ethtool_netlink.h
index 7dcae22..8e1f38f 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,8 @@
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_CNT,
ETHTOOL_A_RINGS_MAX = (__ETHTOOL_A_RINGS_CNT - 1)
};
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/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/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..640fa50 100644
--- a/libc/kernel/uapi/linux/if_link.h
+++ b/libc/kernel/uapi/linux/if_link.h
@@ -72,6 +72,17 @@
__u64 tx_compressed;
__u64 rx_nohandler;
};
+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;
__u64 mem_end;
@@ -289,6 +300,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 +440,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 +509,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 +539,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 +575,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 +612,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 +832,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 +848,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/io_uring.h b/libc/kernel/uapi/linux/io_uring.h
index 96944f8..2f599aa 100644
--- a/libc/kernel/uapi/linux/io_uring.h
+++ b/libc/kernel/uapi/linux/io_uring.h
@@ -87,6 +87,7 @@
#define IORING_SETUP_CLAMP (1U << 4)
#define IORING_SETUP_ATTACH_WQ (1U << 5)
#define IORING_SETUP_R_DISABLED (1U << 6)
+#define IORING_SETUP_SUBMIT_ALL (1U << 7)
enum {
IORING_OP_NOP,
IORING_OP_READV,
@@ -128,6 +129,7 @@
IORING_OP_MKDIRAT,
IORING_OP_SYMLINKAT,
IORING_OP_LINKAT,
+ IORING_OP_MSG_RING,
IORING_OP_LAST,
};
#define IORING_FSYNC_DATASYNC (1U << 0)
@@ -185,6 +187,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 +212,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 +234,8 @@
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_LAST
};
enum {
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/kexec.h b/libc/kernel/uapi/linux/kexec.h
index 2e3bd0c..7dbc87e 100644
--- a/libc/kernel/uapi/linux/kexec.h
+++ b/libc/kernel/uapi/linux/kexec.h
@@ -43,8 +43,8 @@
#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..5cc9905 100644
--- a/libc/kernel/uapi/linux/kvm.h
+++ b/libc/kernel/uapi/linux/kvm.h
@@ -337,7 +337,11 @@
#define KVM_SYSTEM_EVENT_RESET 2
#define KVM_SYSTEM_EVENT_CRASH 3
__u32 type;
- __u64 flags;
+ __u32 ndata;
+ union {
+ __u64 flags;
+ __u64 data[16];
+ };
} system_event;
struct {
__u64 addr;
@@ -419,7 +423,10 @@
__u32 op;
__u64 buf;
union {
- __u8 ar;
+ struct {
+ __u8 ar;
+ __u8 key;
+ };
__u32 sida_offset;
__u8 reserved[32];
};
@@ -428,8 +435,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;
};
@@ -890,6 +900,10 @@
#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_SYSTEM_EVENT_DATA 215
#ifdef KVM_CAP_IRQ_ROUTING
struct kvm_irq_routing_irqchip {
__u32 irqchip;
@@ -1480,6 +1494,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;
diff --git a/libc/kernel/uapi/linux/lirc.h b/libc/kernel/uapi/linux/lirc.h
index a0ac24a..ea45506 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,13 @@
#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_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/mptcp.h b/libc/kernel/uapi/linux/mptcp.h
index 67b0ce3..7b3acd5 100644
--- a/libc/kernel/uapi/linux/mptcp.h
+++ b/libc/kernel/uapi/linux/mptcp.h
@@ -77,6 +77,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,
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/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/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..61de391 100644
--- a/libc/kernel/uapi/linux/nl80211.h
+++ b/libc/kernel/uapi/linux/nl80211.h
@@ -511,6 +511,7 @@
NL80211_ATTR_MBSSID_ELEMS,
NL80211_ATTR_RADAR_BACKGROUND,
NL80211_ATTR_AP_SETTINGS_FLAGS,
+ NL80211_ATTR_EHT_CAPABILITY,
__NL80211_ATTR_AFTER_LAST,
NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
@@ -555,6 +556,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 +619,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 +661,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 +785,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 +845,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 +915,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 +1071,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..a2f9914 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;
@@ -84,4 +87,5 @@
#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)
#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/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..58d8205 100644
--- a/libc/kernel/uapi/linux/pkt_cls.h
+++ b/libc/kernel/uapi/linux/pkt_cls.h
@@ -476,6 +476,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 +504,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/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/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/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..49dce45 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 ((u8) - 1)
+#define SOCK_TXREHASH_DISABLED 0
+#define SOCK_TXREHASH_ENABLED 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/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/tty.h b/libc/kernel/uapi/linux/tty.h
index dcce572..fb2379e 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,6 @@
#define N_SPEAKUP 26
#define N_NULL 27
#define N_MCTP 28
+#define N_DEVELOPMENT 29
+#define NR_LDISCS 30
#endif
diff --git a/libc/kernel/uapi/linux/types.h b/libc/kernel/uapi/linux/types.h
index 9145e66..ce82a24 100644
--- a/libc/kernel/uapi/linux/types.h
+++ b/libc/kernel/uapi/linux/types.h
@@ -21,8 +21,7 @@
#include <asm/types.h>
#ifndef __ASSEMBLY__
#include <linux/posix_types.h>
-#define __bitwise__
-#define __bitwise __bitwise__
+#define __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..3727d0a 100644
--- a/libc/kernel/uapi/linux/userfaultfd.h
+++ b/libc/kernel/uapi/linux/userfaultfd.h
@@ -21,7 +21,7 @@
#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)
#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)
@@ -95,6 +95,7 @@
#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)
__u64 features;
__u64 ioctls;
};
diff --git a/libc/kernel/uapi/linux/v4l2-controls.h b/libc/kernel/uapi/linux/v4l2-controls.h
index 1a11355..43014ef 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)
@@ -1153,6 +1154,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/version.h b/libc/kernel/uapi/linux/version.h
index 2dfd696..2677406 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 332288
#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 18
#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..7769beb 100644
--- a/libc/kernel/uapi/linux/vhost.h
+++ b/libc/kernel/uapi/linux/vhost.h
@@ -64,4 +64,6 @@
#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)
#endif
diff --git a/libc/kernel/uapi/linux/videodev2.h b/libc/kernel/uapi/linux/videodev2.h
index 74bd328..55c1a95 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))
@@ -305,6 +300,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')
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..f9e1bb9 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,
@@ -294,6 +295,9 @@
__u8 card_name[HL_INFO_CARD_NAME_MAX_LEN];
__u64 reserved2;
__u64 dram_page_size;
+ __u32 reserved3;
+ __u16 number_of_user_interrupts;
+ __u16 pad2;
};
struct hl_info_dram_usage {
__u64 dram_free_mem;
@@ -512,6 +516,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 +542,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,6 +568,7 @@
#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
@@ -569,6 +577,7 @@
union {
struct {
__u64 mem_size;
+ __u64 page_size;
} alloc;
struct {
__u64 handle;
@@ -596,7 +605,7 @@
__u32 op;
__u32 flags;
__u32 ctx_id;
- __u32 pad;
+ __u32 num_of_elements;
};
struct hl_mem_out {
union {
diff --git a/libc/kernel/uapi/sound/sof/abi.h b/libc/kernel/uapi/sound/sof/abi.h
index 3af3c9d..810a0b4 100644
--- a/libc/kernel/uapi/sound/sof/abi.h
+++ b/libc/kernel/uapi/sound/sof/abi.h
@@ -19,8 +19,8 @@
#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_PATCH 0
+#define SOF_ABI_MINOR 19
+#define SOF_ABI_PATCH 1
#define SOF_ABI_MAJOR_SHIFT 24
#define SOF_ABI_MAJOR_MASK 0xff
#define SOF_ABI_MINOR_SHIFT 12
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/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/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-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/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/libdl/Android.bp b/libdl/Android.bp
index 750a6e2..9714af5 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -241,30 +241,30 @@
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.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..641956c 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -560,30 +560,30 @@
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.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/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/tests/Android.bp b/tests/Android.bp
index 6a41cf2..8f4ba2f 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -479,6 +479,7 @@
"uchar_test.cpp",
"unistd_nofortify_test.cpp",
"unistd_test.cpp",
+ "utils.cpp",
"utmp_test.cpp",
"wchar_test.cpp",
"wctype_test.cpp",
@@ -598,18 +599,6 @@
],
}
-cc_test_library {
- name: "libBionicGwpAsanTests",
- defaults: ["bionic_tests_defaults"],
- srcs: [
- "gwp_asan_test.cpp",
- ],
- include_dirs: [
- "bionic/libc",
- ],
- static_libs: ["libbase"],
-}
-
// -----------------------------------------------------------------------------
// Fortify tests.
// -----------------------------------------------------------------------------
@@ -770,7 +759,6 @@
"libBionicStandardTests",
"libBionicElfTlsTests",
"libBionicFramePointerTests",
- "libBionicGwpAsanTests",
"libfortify1-tests-clang",
"libfortify1-new-tests-clang",
"libfortify2-tests-clang",
@@ -872,6 +860,7 @@
"__cxa_thread_atexit_test.cpp",
"gtest_globals.cpp",
"gtest_main.cpp",
+ "gwp_asan_test.cpp",
"thread_local_test.cpp",
],
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/stdio_test.cpp b/tests/stdio_test.cpp
index 87031f6..5bc6567 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>
@@ -2938,3 +2939,27 @@
fclose(fp);
}
+
+static int64_t GetTotalRamGiB() {
+ struct sysinfo si;
+ sysinfo(&si);
+ return (static_cast<int64_t>(si.totalram) * si.mem_unit) / 1024 / 1024 / 1024;
+}
+
+TEST(STDIO_TEST, fread_int_overflow) {
+ 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()));
+}
+
+TEST(STDIO_TEST, fwrite_int_overflow) {
+ 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()));
+}
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 02da585..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));
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/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"],
}