Merge "libc.map.txt: remove the two riscv64 special cases." into main
diff --git a/docs/status.md b/docs/status.md
index 7ebd195..0436c40 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -55,6 +55,9 @@
Current libc symbols: https://android.googlesource.com/platform/bionic/+/main/libc/libc.map.txt
+New libc functions in API level 36:
+ * `qsort_r` (new POSIX addition).
+
New libc functions in V (API level 35):
* New `android_crash_detail_register`, `android_crash_detail_unregister`,
`android_crash_detail_replace_name`, and `android_crash_detail_replace_data`
diff --git a/libc/Android.bp b/libc/Android.bp
index 79b85c5..42ffd37 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -389,6 +389,7 @@
"upstream-freebsd/lib/libc/stdlib/hdestroy_r.c",
"upstream-freebsd/lib/libc/stdlib/hsearch_r.c",
"upstream-freebsd/lib/libc/stdlib/qsort.c",
+ "upstream-freebsd/lib/libc/stdlib/qsort_r.c",
"upstream-freebsd/lib/libc/stdlib/quick_exit.c",
"upstream-freebsd/lib/libc/string/wcpcpy.c",
"upstream-freebsd/lib/libc/string/wcpncpy.c",
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index e50fca0..ba20c51 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -118,12 +118,15 @@
static void __init_shadow_call_stack(pthread_internal_t* thread __unused) {
#if defined(__aarch64__) || defined(__riscv)
- // Allocate the stack and the guard region.
+ // Allocate the shadow call stack and its guard region.
char* scs_guard_region = reinterpret_cast<char*>(
- mmap(nullptr, SCS_GUARD_REGION_SIZE, 0, MAP_PRIVATE | MAP_ANON, -1, 0));
+ mmap(nullptr, SCS_GUARD_REGION_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0));
+ if (scs_guard_region == MAP_FAILED) {
+ async_safe_fatal("failed to allocate shadow stack: %m");
+ }
thread->shadow_call_stack_guard_region = scs_guard_region;
- // The address is aligned to SCS_SIZE so that we only need to store the lower log2(SCS_SIZE) bits
+ // Align the address to SCS_SIZE so that we only need to store the lower log2(SCS_SIZE) bits
// in jmp_buf. See the SCS commentary in pthread_internal.h for more detail.
char* scs_aligned_guard_region =
reinterpret_cast<char*>(align_up(reinterpret_cast<uintptr_t>(scs_guard_region), SCS_SIZE));
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index d0efc4c..b160e6b 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -114,7 +114,20 @@
*/
__wur void* _Nullable bsearch(const void* _Nonnull __key, const void* _Nullable __base, size_t __nmemb, size_t __size, int (* _Nonnull __comparator)(const void* _Nonnull __lhs, const void* _Nonnull __rhs));
-void qsort(void* _Nullable __base, size_t __nmemb, size_t __size, int (* _Nonnull __comparator)(const void* _Nullable __lhs, const void* _Nullable __rhs));
+/**
+ * [qsort(3)](http://man7.org/linux/man-pages/man3/qsort.3.html) sorts an array
+ * of n elements each of the given size, using the given comparator.
+ */
+void qsort(void* _Nullable __array, size_t __n, size_t __size, int (* _Nonnull __comparator)(const void* _Nullable __lhs, const void* _Nullable __rhs));
+
+/**
+ * [qsort_r(3)](http://man7.org/linux/man-pages/man3/qsort_r.3.html) sorts an
+ * array of n elements each of the given size, using the given comparator,
+ * and passing the given context argument to the comparator.
+ *
+ * Available since API level 36.
+ */
+void qsort_r(void* _Nullable __array, size_t __n, size_t __size, int (* _Nonnull __comparator)(const void* _Nullable __lhs, const void* _Nullable __rhs, void* _Nullable __context), void* _Nullable __context) __INTRODUCED_IN(36);
uint32_t arc4random(void);
uint32_t arc4random_uniform(uint32_t __upper_bound);
diff --git a/libc/include/sys/_system_properties.h b/libc/include/sys/_system_properties.h
index 078e857..05612b3 100644
--- a/libc/include/sys/_system_properties.h
+++ b/libc/include/sys/_system_properties.h
@@ -26,8 +26,7 @@
* SUCH DAMAGE.
*/
-#ifndef _INCLUDE_SYS__SYSTEM_PROPERTIES_H
-#define _INCLUDE_SYS__SYSTEM_PROPERTIES_H
+#pragma once
#include <sys/cdefs.h>
#include <stdint.h>
@@ -40,13 +39,67 @@
__BEGIN_DECLS
+/**
+ * Reads the global serial number of the system properties _area_.
+ *
+ * Called to predict if a series of cached __system_property_find()
+ * objects will have seen __system_property_serial() values change.
+ * Also aids the converse, as changes in the global serial can
+ * also be used to predict if a failed __system_property_find()
+ * could in turn now find a new object; thus preventing the
+ * cycles of effort to poll __system_property_find().
+ *
+ * Typically called at beginning of a cache cycle to signal if _any_ possible
+ * changes have occurred since last. If there is, one may check each individual
+ * __system_property_serial() to confirm dirty, or __system_property_find()
+ * to check if the property now exists. If a call to __system_property_add()
+ * or __system_property_update() has completed between two calls to
+ * __system_property_area_serial() then the second call will return a larger
+ * value than the first call. Beware of race conditions as changes to the
+ * properties are not atomic, the main value of this call is to determine
+ * whether the expensive __system_property_find() is worth retrying to see if
+ * a property now exists.
+ *
+ * Returns the serial number on success, -1 on error.
+ */
+uint32_t __system_property_area_serial(void);
+
+/**
+ * Reads the serial number of a specific system property previously returned by
+ * __system_property_find(). This is a cheap way to check whether a system
+ * property has changed or not.
+ *
+ * Returns the serial number on success, -1 on error.
+ */
+uint32_t __system_property_serial(const prop_info* _Nonnull __pi);
+
+//
+// libc implementation detail.
+//
+
+/**
+ * Initializes the system properties area in read-only mode.
+ *
+ * This is called automatically during libc initialization,
+ * so user code should never need to call this.
+ *
+ * Returns 0 on success, -1 otherwise.
+ */
+int __system_properties_init(void);
+
+//
+// init implementation details.
+//
+
#define PROP_SERVICE_NAME "property_service"
#define PROP_SERVICE_FOR_SYSTEM_NAME "property_service_for_system"
#define PROP_DIRNAME "/dev/__properties__"
+// Messages sent to init.
#define PROP_MSG_SETPROP 1
#define PROP_MSG_SETPROP2 0x00020001
+// Status codes returned by init (but not passed from libc to the caller).
#define PROP_SUCCESS 0
#define PROP_ERROR_READ_CMD 0x0004
#define PROP_ERROR_READ_DATA 0x0008
@@ -58,93 +111,62 @@
#define PROP_ERROR_HANDLE_CONTROL_MESSAGE 0x0020
#define PROP_ERROR_SET_FAILED 0x0024
-/*
-** This was previously for testing, but now that SystemProperties is its own testable class,
-** there is never a reason to call this function and its implementation simply returns -1.
-*/
-int __system_property_set_filename(const char* __unused __filename);
-
-/*
-** Initialize the area to be used to store properties. Can
-** only be done by a single process that has write access to
-** the property area.
-*/
+/**
+ * Initializes the area to be used to store properties.
+ *
+ * Can only be done by the process that has write access to the property area,
+ * typically init.
+ *
+ * See __system_properties_init() for the equivalent for all other processes.
+ */
int __system_property_area_init(void);
-/* Read the global serial number of the system properties
-**
-** Called to predict if a series of cached __system_property_find
-** objects will have seen __system_property_serial values change.
-** But also aids the converse, as changes in the global serial can
-** also be used to predict if a failed __system_property_find
-** could in-turn now find a new object; thus preventing the
-** cycles of effort to poll __system_property_find.
-**
-** Typically called at beginning of a cache cycle to signal if _any_ possible
-** changes have occurred since last. If there is, one may check each individual
-** __system_property_serial to confirm dirty, or __system_property_find
-** to check if the property now exists. If a call to __system_property_add
-** or __system_property_update has completed between two calls to
-** __system_property_area_serial then the second call will return a larger
-** value than the first call. Beware of race conditions as changes to the
-** properties are not atomic, the main value of this call is to determine
-** whether the expensive __system_property_find is worth retrying to see if
-** a property now exists.
-**
-** Returns the serial number on success, -1 on error.
-*/
-uint32_t __system_property_area_serial(void);
-
-/* Add a new system property. Can only be done by a single
-** process that has write access to the property area, and
-** that process must handle sequencing to ensure the property
-** does not already exist and that only one property is added
-** or updated at a time.
-**
-** Returns 0 on success, -1 if the property area is full.
-*/
+/**
+ * Adds a new system property.
+ * Can only be done by the process that has write access to the property area --
+ * typically init -- which must handle sequencing to ensure that only one property is
+ * updated at a time.
+ *
+ * Returns 0 on success, -1 if the property area is full.
+ */
int __system_property_add(const char* _Nonnull __name, unsigned int __name_length, const char* _Nonnull __value, unsigned int __value_length);
-/* Update the value of a system property returned by
-** __system_property_find. Can only be done by a single process
-** that has write access to the property area, and that process
-** must handle sequencing to ensure that only one property is
-** updated at a time.
-**
-** Returns 0 on success, -1 if the parameters are incorrect.
-*/
+/**
+ * Updates the value of a system property returned by __system_property_find().
+ * Can only be done by the process that has write access to the property area --
+ * typically init -- which must handle sequencing to ensure that only one property is
+ * updated at a time.
+ *
+ * Returns 0 on success, -1 if the parameters are incorrect.
+ */
int __system_property_update(prop_info* _Nonnull __pi, const char* _Nonnull __value, unsigned int __value_length);
-/* Read the serial number of a system property returned by
-** __system_property_find.
-**
-** Returns the serial number on success, -1 on error.
-*/
-uint32_t __system_property_serial(const prop_info* _Nonnull __pi);
-
-/* Initialize the system properties area in read only mode.
- * Should be done by all processes that need to read system
- * properties.
+/**
+ * Reloads the system properties from disk.
+ * Not intended for use by any apps except the Zygote.
+ * Should only be called from the main thread.
+ *
+ * Pointers received from functions such as __system_property_find()
+ * may be invalidated by calls to this function.
*
* Returns 0 on success, -1 otherwise.
- */
-int __system_properties_init(void);
-
-/*
- * Reloads the system properties from disk.
- * Not intended for use by any apps except the Zygote. Should only be called from the main thread.
*
- * NOTE: Any pointers received from methods such as __system_property_find should be assumed to be
- * invalid after this method is called.
- *
- * Returns 0 on success, -1 if the system properties failed to re-initialize (same conditions as
- * __system properties_init)
+ * Available since API level 35.
*/
-int __system_properties_zygote_reload(void) __INTRODUCED_IN(__ANDROID_API_V__);
+int __system_properties_zygote_reload(void) __INTRODUCED_IN(35);
-/* Deprecated: use __system_property_wait instead. */
+//
+// Deprecated functions.
+//
+
+/** Deprecated: use __system_property_wait instead. */
uint32_t __system_property_wait_any(uint32_t __old_serial);
-__END_DECLS
+/**
+ * Deprecated: previously for testing, but now that SystemProperties is its own
+ * testable class, there is never a reason to call this function and its
+ * implementation simply returns -1.
+ */
+int __system_property_set_filename(const char* __unused __filename);
-#endif
+__END_DECLS
diff --git a/libc/include/sys/select.h b/libc/include/sys/select.h
index 84c2621..437a234 100644
--- a/libc/include/sys/select.h
+++ b/libc/include/sys/select.h
@@ -44,7 +44,7 @@
typedef unsigned long fd_mask;
/**
- * The limit on the largest fd that can be used with this API.
+ * The limit on the largest fd that can be used with fd_set.
* Use <poll.h> instead.
*/
#define FD_SETSIZE 1024
@@ -52,6 +52,9 @@
/**
* The type of a file descriptor set. Limited to 1024 fds.
+ * The underlying system calls do not have this limit,
+ * and callers can allocate their own sets with calloc().
+ *
* Use <poll.h> instead.
*/
typedef struct {
@@ -60,30 +63,27 @@
#define __FDELT(fd) ((fd) / NFDBITS)
#define __FDMASK(fd) (1UL << ((fd) % NFDBITS))
-#define __FDS_BITS(type,set) (__BIONIC_CAST(static_cast, type, set)->fds_bits)
-
-/* Inline loop so we don't have to declare memset. */
-#define FD_ZERO(set) \
- do { \
- size_t __i; \
- for (__i = 0; __i < sizeof(fd_set)/sizeof(fd_mask); ++__i) { \
- (set)->fds_bits[__i] = 0; \
- } \
- } while (0)
+#define __FDS_BITS(type, set) (__BIONIC_CAST(static_cast, type, set)->fds_bits)
void __FD_CLR_chk(int, fd_set* _Nonnull , size_t);
void __FD_SET_chk(int, fd_set* _Nonnull, size_t);
int __FD_ISSET_chk(int, const fd_set* _Nonnull, size_t);
-#define __FD_CLR(fd, set) (__FDS_BITS(fd_set*,set)[__FDELT(fd)] &= ~__FDMASK(fd))
-#define __FD_SET(fd, set) (__FDS_BITS(fd_set*,set)[__FDELT(fd)] |= __FDMASK(fd))
-#define __FD_ISSET(fd, set) ((__FDS_BITS(const fd_set*,set)[__FDELT(fd)] & __FDMASK(fd)) != 0)
+/** FD_CLR() with no bounds checking for users that allocated their own set. */
+#define __FD_CLR(fd, set) (__FDS_BITS(fd_set*, set)[__FDELT(fd)] &= ~__FDMASK(fd))
+/** FD_SET() with no bounds checking for users that allocated their own set. */
+#define __FD_SET(fd, set) (__FDS_BITS(fd_set*, set)[__FDELT(fd)] |= __FDMASK(fd))
+/** FD_ISSET() with no bounds checking for users that allocated their own set. */
+#define __FD_ISSET(fd, set) ((__FDS_BITS(const fd_set*, set)[__FDELT(fd)] & __FDMASK(fd)) != 0)
-/** Removes `fd` from the given set. Use <poll.h> instead. */
+/** Removes all 1024 fds from the given set. Use <poll.h> instead. */
+#define FD_ZERO(set) __builtin_memset(set, 0, sizeof(*__BIONIC_CAST(static_cast, const fd_set*, set)))
+
+/** Removes `fd` from the given set. Limited to fds under 1024. Use <poll.h> instead. */
#define FD_CLR(fd, set) __FD_CLR_chk(fd, set, __bos(set))
-/** Adds `fd` to the given set. Use <poll.h> instead. */
+/** Adds `fd` to the given set. Limited to fds under 1024. Use <poll.h> instead. */
#define FD_SET(fd, set) __FD_SET_chk(fd, set, __bos(set))
-/** Tests whether `fd` is in the given set. Use <poll.h> instead. */
+/** Tests whether `fd` is in the given set. Limited to fds under 1024. Use <poll.h> instead. */
#define FD_ISSET(fd, set) __FD_ISSET_chk(fd, set, __bos(set))
/**
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 4298b87..35e67c8 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -844,6 +844,7 @@
pwrite;
pwrite64;
qsort;
+ qsort_r; # introduced=36
quick_exit;
raise;
rand;
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/qsort_r.c b/libc/upstream-freebsd/lib/libc/stdlib/qsort_r.c
new file mode 100644
index 0000000..b382b40
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/qsort_r.c
@@ -0,0 +1,6 @@
+/*
+ * This file is in the public domain. Originally written by Garrett
+ * A. Wollman.
+ */
+#define I_AM_QSORT_R
+#include "qsort.c"
diff --git a/linker/linker_note_gnu_property_test.cpp b/linker/linker_note_gnu_property_test.cpp
index 41fc47b..960118c 100644
--- a/linker/linker_note_gnu_property_test.cpp
+++ b/linker/linker_note_gnu_property_test.cpp
@@ -137,18 +137,18 @@
dump_member("entries ", entries);
if (entries > 0) {
std::cout << " raw data:";
- const uintptr_t offset = note->nhdr.n_descsz + 16;
- for (uintptr_t offs = 16; offs < offset; ++offs) {
+ const uintptr_t end = note->nhdr.n_descsz + 16;
+ for (uintptr_t offset = 16; offset < end; ++offset) {
std::cout << std::hex;
- if ((offs % 8) == 0) {
+ if ((offset % 8) == 0) {
std::cout << "\n ";
}
- auto value = static_cast<unsigned>(section[offs]);
+ auto value = static_cast<unsigned>(section[offset]);
std::cout << " ";
if (value < 0x10) {
std::cout << "0";
}
- std::cout << static_cast<unsigned>(section[offs]);
+ std::cout << static_cast<unsigned>(section[offset]);
}
std::cout << std::dec << "\n";
}
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index ad60efd..b0675c1 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -345,19 +345,19 @@
((offset % alignment) == 0);
}
-void* ElfReader::MapData(MappedFileFragment* fragment, off64_t offs, off64_t size) {
+void* ElfReader::MapData(MappedFileFragment* fragment, off64_t offset, off64_t size) {
off64_t end;
- CHECK(safe_add(&end, offs, size));
+ CHECK(safe_add(&end, offset, size));
// If the data is already mapped just return it
if (static_cast<off64_t>(file_fragment_.size()) >= end) {
- return static_cast<char*>(file_fragment_.data()) + offs;
+ return static_cast<char*>(file_fragment_.data()) + offset;
}
// Use the passed-in fragment if area is not mapped. We can't remap the original fragment
// because that invalidates all previous pointers if the file is remapped to a different
// virtual address. A local variable can't be used in place of the passed-in fragment because
// the area would be unmapped as soon as the local object goes out of scope.
- if (fragment->Map(fd_, file_offset_, offs, size)) {
+ if (fragment->Map(fd_, file_offset_, offset, size)) {
return fragment->data();
}
return nullptr;
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index dc1ca99..e7aae6e 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -73,7 +73,7 @@
[[nodiscard]] bool FindGnuPropertySection();
[[nodiscard]] bool CheckPhdr(ElfW(Addr));
[[nodiscard]] bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment);
- [[nodiscard]] void* MapData(MappedFileFragment* fragment, off64_t offs, off64_t size);
+ [[nodiscard]] void* MapData(MappedFileFragment* fragment, off64_t offset, off64_t size);
bool did_read_;
bool did_load_;
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index a5916d3..813f348 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -1627,6 +1627,7 @@
#if !defined(__BIONIC__)
GTEST_SKIP() << "Only valid on bionic";
#endif
+ SKIP_WITH_HWASAN << "Only test system allocator, not hwasan allocator.";
if (IsLowRamDevice()) {
GTEST_SKIP() << "Skipped on low memory devices.";
@@ -1657,6 +1658,7 @@
#if !defined(__BIONIC__)
GTEST_SKIP() << "Only valid on bionic";
#endif
+ SKIP_WITH_HWASAN << "Only test system allocator, not hwasan allocator.";
if (IsLowRamDevice()) {
GTEST_SKIP() << "Skipped on low memory devices.";
@@ -1687,6 +1689,7 @@
#if !defined(__BIONIC__)
GTEST_SKIP() << "Only valid on bionic";
#endif
+ SKIP_WITH_HWASAN << "Only test system allocator, not hwasan allocator.";
if (IsLowRamDevice()) {
GTEST_SKIP() << "Skipped on low memory devices.";
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index f5e57a5..3216066 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -431,6 +431,31 @@
ASSERT_STREQ("charlie", entries[2].name);
}
+TEST(stdlib, qsort_r) {
+ struct s {
+ char name[16];
+ static int comparator(const void* lhs, const void* rhs, void* context) {
+ int* count_p = reinterpret_cast<int*>(context);
+ *count_p += 1;
+ return strcmp(reinterpret_cast<const s*>(lhs)->name, reinterpret_cast<const s*>(rhs)->name);
+ }
+ };
+ s entries[3];
+ strcpy(entries[0].name, "charlie");
+ strcpy(entries[1].name, "bravo");
+ strcpy(entries[2].name, "alpha");
+
+ int count;
+ void* context = &count;
+
+ count = 0;
+ qsort_r(entries, 3, sizeof(s), s::comparator, context);
+ ASSERT_STREQ("alpha", entries[0].name);
+ ASSERT_STREQ("bravo", entries[1].name);
+ ASSERT_STREQ("charlie", entries[2].name);
+ ASSERT_EQ(count, 3);
+}
+
static void* TestBug57421_child(void* arg) {
pthread_t main_thread = reinterpret_cast<pthread_t>(arg);
pthread_join(main_thread, nullptr);