Merge changes from topic "revert-2709995-VVPYYBKIHY" into main
* changes:
Revert "Linker support for MTE globals."
Revert "Add a memtag-globals test to bionic"
diff --git a/libc/Android.bp b/libc/Android.bp
index c816bdf..6f36aad 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1052,8 +1052,8 @@
name: "generated_android_ids",
out: ["generated_android_ids.h"],
srcs: [":android_filesystem_config_header"],
- tool_files: ["fs_config_generator.py"],
- cmd: "$(location fs_config_generator.py) aidarray $(in) > $(out)",
+ tools: ["fs_config_generator"],
+ cmd: "$(location fs_config_generator) aidarray $(in) > $(out)",
}
// ========================================================
diff --git a/libc/bionic/bionic_call_ifunc_resolver.cpp b/libc/bionic/bionic_call_ifunc_resolver.cpp
index 3cfb8b5..e44d998 100644
--- a/libc/bionic/bionic_call_ifunc_resolver.cpp
+++ b/libc/bionic/bionic_call_ifunc_resolver.cpp
@@ -28,6 +28,7 @@
#include "private/bionic_call_ifunc_resolver.h"
#include <sys/auxv.h>
+#include <sys/hwprobe.h>
#include <sys/ifunc.h>
#include "private/bionic_auxv.h"
@@ -50,20 +51,15 @@
return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(arg._hwcap | _IFUNC_ARG_HWCAP, &arg);
#elif defined(__arm__)
typedef ElfW(Addr) (*ifunc_resolver_t)(unsigned long);
- static unsigned long hwcap;
- static bool initialized = false;
- if (!initialized) {
- initialized = true;
- hwcap = getauxval(AT_HWCAP);
- }
+ static unsigned long hwcap = getauxval(AT_HWCAP);
return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap);
#elif defined(__riscv)
- // The pointer argument is currently unused, but reserved for future
+ // The third argument is currently unused, but reserved for future
// expansion. If we pass nullptr from the beginning, it'll be easier
// to recognize if/when we pass actual data (and matches glibc).
- typedef ElfW(Addr) (*ifunc_resolver_t)(uint64_t, void*);
+ typedef ElfW(Addr) (*ifunc_resolver_t)(uint64_t, __riscv_hwprobe_t, void*);
static uint64_t hwcap = getauxval(AT_HWCAP);
- return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap, nullptr);
+ return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap, __riscv_hwprobe, nullptr);
#else
typedef ElfW(Addr) (*ifunc_resolver_t)(void);
return reinterpret_cast<ifunc_resolver_t>(resolver_addr)();
diff --git a/libc/fs_config_generator.py b/libc/fs_config_generator.py
deleted file mode 120000
index aafb7dc..0000000
--- a/libc/fs_config_generator.py
+++ /dev/null
@@ -1 +0,0 @@
-../../build/tools/fs_config/fs_config_generator.py
\ No newline at end of file
diff --git a/libc/include/bits/signal_types.h b/libc/include/bits/signal_types.h
index 699e257..d98901c 100644
--- a/libc/include/bits/signal_types.h
+++ b/libc/include/bits/signal_types.h
@@ -28,18 +28,11 @@
#pragma once
-#include <limits.h>
#include <sys/cdefs.h>
-#include <sys/types.h>
-/* For 64-bit, the kernel's struct sigaction doesn't match the POSIX one,
- * so we need to expose our own and translate behind the scenes.
- * For 32-bit, we're stuck with the definitions we already shipped,
- * even though they contain a sigset_t that's too small. See sigaction64.
- */
-#define sigaction __kernel_sigaction
+#include <limits.h>
#include <linux/signal.h>
-#undef sigaction
+#include <sys/types.h>
/* The arm and x86 kernel header files don't define _NSIG. */
#ifndef _KERNEL__NSIG
@@ -64,8 +57,13 @@
typedef struct { unsigned long __bits[_KERNEL__NSIG/(8*sizeof(long))]; } sigset64_t;
#endif
+/* The kernel's struct sigaction doesn't match the POSIX one. */
+
#if defined(__LP64__)
+/* For 64-bit, that's the only problem, and we only need two structs
+ * for source compatibility with 32-bit. */
+
#define __SIGACTION_BODY \
int sa_flags; \
union { \
@@ -82,6 +80,12 @@
#else
+/* For 32-bit, Android's ABIs used a too-small sigset_t that doesn't
+ * support RT signals, so we need two different structs.
+ */
+
+/* The arm32 kernel headers also pollute the namespace with these,
+ * but our header scrubber doesn't know how to remove #defines. */
#undef sa_handler
#undef sa_sigaction
@@ -95,7 +99,6 @@
void (*sa_restorer)(void);
};
-/* This matches the kernel's internal structure. */
struct sigaction64 {
union {
sighandler_t sa_handler;
diff --git a/libc/include/bits/tcphdr.h b/libc/include/bits/tcphdr.h
new file mode 100644
index 0000000..a9b6fe0
--- /dev/null
+++ b/libc/include/bits/tcphdr.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+struct tcphdr {
+ __extension__ union {
+ struct {
+ uint16_t th_sport;
+ uint16_t th_dport;
+ uint32_t th_seq;
+ uint32_t th_ack;
+ uint8_t th_x2:4;
+ uint8_t th_off:4;
+ uint8_t th_flags;
+ uint16_t th_win;
+ uint16_t th_sum;
+ uint16_t th_urp;
+ };
+ struct {
+ uint16_t source;
+ uint16_t dest;
+ uint32_t seq;
+ uint32_t ack_seq;
+ uint16_t res1:4;
+ uint16_t doff:4;
+ uint16_t fin:1;
+ uint16_t syn:1;
+ uint16_t rst:1;
+ uint16_t psh:1;
+ uint16_t ack:1;
+ uint16_t urg:1;
+ uint16_t res2:2;
+ uint16_t window;
+ uint16_t check;
+ uint16_t urg_ptr;
+ };
+ };
+};
+
+__END_DECLS
diff --git a/libc/include/netinet/tcp.h b/libc/include/netinet/tcp.h
index 147f6f7..d1c657b 100644
--- a/libc/include/netinet/tcp.h
+++ b/libc/include/netinet/tcp.h
@@ -32,47 +32,10 @@
#include <sys/cdefs.h>
#include <stdint.h>
-#define tcphdr __kernel_tcphdr
#include <linux/tcp.h>
-#undef tcphdr
__BEGIN_DECLS
-struct tcphdr {
- __extension__ union {
- struct {
- uint16_t th_sport;
- uint16_t th_dport;
- uint32_t th_seq;
- uint32_t th_ack;
- uint8_t th_x2:4;
- uint8_t th_off:4;
- uint8_t th_flags;
- uint16_t th_win;
- uint16_t th_sum;
- uint16_t th_urp;
- };
- struct {
- uint16_t source;
- uint16_t dest;
- uint32_t seq;
- uint32_t ack_seq;
- uint16_t res1:4;
- uint16_t doff:4;
- uint16_t fin:1;
- uint16_t syn:1;
- uint16_t rst:1;
- uint16_t psh:1;
- uint16_t ack:1;
- uint16_t urg:1;
- uint16_t res2:2;
- uint16_t window;
- uint16_t check;
- uint16_t urg_ptr;
- };
- };
-};
-
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 4feade5..9d99aa1 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -77,12 +77,12 @@
#if defined(__LP64__)
#if defined(PAGE_SIZE)
-#define PTHREAD_STACK_MIN (4 * PAGE_SIZE)
+#define PTHREAD_STACK_MIN 16384
#else
#define PTHREAD_STACK_MIN 65536
#endif
#else
-#define PTHREAD_STACK_MIN (2 * PAGE_SIZE)
+#define PTHREAD_STACK_MIN 8192
#endif
#define PTHREAD_CREATE_DETACHED 1
diff --git a/libc/include/sys/hwprobe.h b/libc/include/sys/hwprobe.h
index b1a8400..8e69e8a 100644
--- a/libc/include/sys/hwprobe.h
+++ b/libc/include/sys/hwprobe.h
@@ -53,6 +53,14 @@
*/
int __riscv_hwprobe(struct riscv_hwprobe* _Nonnull __pairs, size_t __pair_count, size_t __cpu_count, unsigned long* _Nullable __cpus, unsigned __flags);
+/**
+ * The type of the second argument passed to riscv64 ifunc resolvers.
+ * This argument allows riscv64 ifunc resolvers to call __riscv_hwprobe()
+ * without worrying about whether that relocation is resolved before
+ * the ifunc resolver is called.
+ */
+typedef int (*__riscv_hwprobe_t)(struct riscv_hwprobe* _Nonnull __pairs, size_t __pair_count, size_t __cpu_count, unsigned long* _Nullable __cpus, unsigned __flags);
+
__END_DECLS
#endif
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index c0b379b..6939bda 100755
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -1202,7 +1202,7 @@
def removeStructs(self, structs):
"""Remove structs."""
- extra_includes = []
+ extra_includes = set()
block_num = 0
num_blocks = len(self.blocks)
while block_num < num_blocks:
@@ -1248,7 +1248,7 @@
# #include <bits/STRUCT_NAME.h>
struct_token = b.tokens[i + 1]
if not structs[struct_token.id]:
- extra_includes.append("<bits/%s.h>" % struct_token.id)
+ extra_includes.add("<bits/%s.h>" % struct_token.id)
# Search forward for the end of the structure.
# Very simple search, look for } and ; tokens.
@@ -1292,7 +1292,7 @@
continue
i += 1
- for extra_include in extra_includes:
+ for extra_include in sorted(extra_includes):
replacement = CppStringTokenizer(extra_include)
self.blocks.insert(2, Block(replacement.tokens, directive='include'))
diff --git a/libc/kernel/tools/defaults.py b/libc/kernel/tools/defaults.py
index ac12fc7..9b357f1 100644
--- a/libc/kernel/tools/defaults.py
+++ b/libc/kernel/tools/defaults.py
@@ -43,6 +43,7 @@
"in_addr": False,
"ip_mreq_source": False,
"ip_msfilter": False,
+ "tcphdr": False,
"timespec": False,
}
@@ -97,6 +98,9 @@
# Remove unused macros (http://b/262917450).
"__force": "",
"__user": "",
+ # Rename the kernel's sigaction so we can expose our POSIX one publicly,
+ # but translate to the kernel's one internally.
+ "sigaction": "__kernel_sigaction",
}
diff --git a/libc/kernel/uapi/asm-arm/asm/signal.h b/libc/kernel/uapi/asm-arm/asm/signal.h
index 838bb13..fde3b9e 100644
--- a/libc/kernel/uapi/asm-arm/asm/signal.h
+++ b/libc/kernel/uapi/asm-arm/asm/signal.h
@@ -52,7 +52,7 @@
#define MINSIGSTKSZ 2048
#define SIGSTKSZ 8192
#include <asm-generic/signal-defs.h>
-struct sigaction {
+struct __kernel_sigaction {
union {
__sighandler_t _sa_handler;
void(* _sa_sigaction) (int, struct siginfo *, void *);
diff --git a/libc/kernel/uapi/asm-generic/signal.h b/libc/kernel/uapi/asm-generic/signal.h
index bea99a7..21c7100 100644
--- a/libc/kernel/uapi/asm-generic/signal.h
+++ b/libc/kernel/uapi/asm-generic/signal.h
@@ -61,7 +61,7 @@
#ifdef SA_RESTORER
#define __ARCH_HAS_SA_RESTORER
#endif
-struct sigaction {
+struct __kernel_sigaction {
__sighandler_t sa_handler;
unsigned long sa_flags;
#ifdef SA_RESTORER
diff --git a/libc/kernel/uapi/asm-x86/asm/signal.h b/libc/kernel/uapi/asm-x86/asm/signal.h
index 2e51445..96ac8fb 100644
--- a/libc/kernel/uapi/asm-x86/asm/signal.h
+++ b/libc/kernel/uapi/asm-x86/asm/signal.h
@@ -56,7 +56,7 @@
#include <asm-generic/signal-defs.h>
#ifndef __ASSEMBLY__
#ifdef __i386__
-struct sigaction {
+struct __kernel_sigaction {
union {
__sighandler_t _sa_handler;
void(* _sa_sigaction) (int, struct siginfo *, void *);
@@ -68,7 +68,7 @@
#define sa_handler _u._sa_handler
#define sa_sigaction _u._sa_sigaction
#else
-struct sigaction {
+struct __kernel_sigaction {
__sighandler_t sa_handler;
unsigned long sa_flags;
__sigrestore_t sa_restorer;
diff --git a/libc/kernel/uapi/linux/tcp.h b/libc/kernel/uapi/linux/tcp.h
index 843b6ef..20fbcec 100644
--- a/libc/kernel/uapi/linux/tcp.h
+++ b/libc/kernel/uapi/linux/tcp.h
@@ -6,25 +6,10 @@
*/
#ifndef _UAPI_LINUX_TCP_H
#define _UAPI_LINUX_TCP_H
+#include <bits/tcphdr.h>
#include <linux/types.h>
#include <asm/byteorder.h>
#include <linux/socket.h>
-struct tcphdr {
- __be16 source;
- __be16 dest;
- __be32 seq;
- __be32 ack_seq;
-#ifdef __LITTLE_ENDIAN_BITFIELD
- __u16 res1 : 4, doff : 4, fin : 1, syn : 1, rst : 1, psh : 1, ack : 1, urg : 1, ece : 1, cwr : 1;
-#elif defined(__BIG_ENDIAN_BITFIELD)
- __u16 doff : 4, res1 : 4, cwr : 1, ece : 1, urg : 1, ack : 1, psh : 1, rst : 1, syn : 1, fin : 1;
-#else
-#error "Adjust your <asm/byteorder.h> defines"
-#endif
- __be16 window;
- __sum16 check;
- __be16 urg_ptr;
-};
union tcp_word_hdr {
struct tcphdr hdr;
__be32 words[5];
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index 24bb18a..83e4aa8 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -61,6 +61,7 @@
"DebugData.cpp",
"debug_disable.cpp",
"GuardData.cpp",
+ "LogAllocatorStats.cpp",
"malloc_debug.cpp",
"PointerData.cpp",
"RecordData.cpp",
diff --git a/libc/malloc_debug/Config.cpp b/libc/malloc_debug/Config.cpp
index 77d2f02..89a7ce7 100644
--- a/libc/malloc_debug/Config.cpp
+++ b/libc/malloc_debug/Config.cpp
@@ -204,6 +204,10 @@
"check_unreachable_on_signal",
{CHECK_UNREACHABLE_ON_SIGNAL, &Config::VerifyValueEmpty},
},
+ {
+ "log_allocator_stats_on_signal",
+ {LOG_ALLOCATOR_STATS_ON_SIGNAL, &Config::VerifyValueEmpty},
+ },
};
bool Config::ParseValue(const std::string& option, const std::string& value, size_t min_value,
@@ -467,6 +471,7 @@
backtrace_min_size_bytes_ = 0;
backtrace_max_size_bytes_ = SIZE_MAX;
check_unreachable_signal_ = SIGRTMAX - 16;
+ log_allocator_stats_signal_ = SIGRTMAX - 15;
// Process each option name we can find.
std::string option;
diff --git a/libc/malloc_debug/Config.h b/libc/malloc_debug/Config.h
index ef1d2a9..754970f 100644
--- a/libc/malloc_debug/Config.h
+++ b/libc/malloc_debug/Config.h
@@ -48,6 +48,7 @@
constexpr uint64_t VERBOSE = 0x1000;
constexpr uint64_t CHECK_UNREACHABLE_ON_SIGNAL = 0x2000;
constexpr uint64_t BACKTRACE_SPECIFIC_SIZES = 0x4000;
+constexpr uint64_t LOG_ALLOCATOR_STATS_ON_SIGNAL = 0x8000;
// In order to guarantee posix compliance, set the minimum alignment
// to 8 bytes for 32 bit systems and 16 bytes for 64 bit systems.
@@ -100,6 +101,8 @@
int check_unreachable_signal() const { return check_unreachable_signal_; }
+ int log_allocator_stats_signal() const { return log_allocator_stats_signal_; }
+
private:
struct OptionInfo {
uint64_t option;
@@ -175,4 +178,5 @@
uint8_t rear_guard_value_;
int check_unreachable_signal_ = 0;
+ int log_allocator_stats_signal_ = 0;
};
diff --git a/libc/malloc_debug/DebugData.cpp b/libc/malloc_debug/DebugData.cpp
index 44c4a10..885cc95 100644
--- a/libc/malloc_debug/DebugData.cpp
+++ b/libc/malloc_debug/DebugData.cpp
@@ -31,6 +31,7 @@
#include "Config.h"
#include "DebugData.h"
#include "GuardData.h"
+#include "LogAllocatorStats.h"
#include "PointerData.h"
#include "debug_disable.h"
#include "malloc_debug.h"
@@ -75,6 +76,13 @@
if (config_.options() & EXPAND_ALLOC) {
extra_bytes_ += config_.expand_alloc_bytes();
}
+
+ if (config_.options() & LOG_ALLOCATOR_STATS_ON_SIGNAL) {
+ if (!LogAllocatorStats::Initialize(config_)) {
+ return false;
+ }
+ }
+
return true;
}
diff --git a/libc/malloc_debug/LogAllocatorStats.cpp b/libc/malloc_debug/LogAllocatorStats.cpp
new file mode 100644
index 0000000..6d1434e
--- /dev/null
+++ b/libc/malloc_debug/LogAllocatorStats.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <malloc.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "Config.h"
+#include "LogAllocatorStats.h"
+#include "debug_log.h"
+
+namespace LogAllocatorStats {
+
+static std::atomic_bool g_call_mallopt = {};
+
+static void CallMalloptLogStats(int, struct siginfo*, void*) {
+ g_call_mallopt = true;
+}
+
+void CheckIfShouldLog() {
+ bool expected = true;
+ if (g_call_mallopt.compare_exchange_strong(expected, false)) {
+ info_log("Logging allocator stats...");
+ if (mallopt(M_LOG_STATS, 0) == 0) {
+ error_log("mallopt(M_LOG_STATS, 0) call failed.");
+ }
+ }
+}
+
+bool Initialize(const Config& config) {
+ struct sigaction64 log_stats_act = {};
+ log_stats_act.sa_sigaction = CallMalloptLogStats;
+ log_stats_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
+ if (sigaction64(config.log_allocator_stats_signal(), &log_stats_act, nullptr) != 0) {
+ error_log("Unable to set up log allocator stats signal function: %s", strerror(errno));
+ return false;
+ }
+
+ if (config.options() & VERBOSE) {
+ info_log("%s: Run: 'kill -%d %d' to log allocator stats.", getprogname(),
+ config.log_allocator_stats_signal(), getpid());
+ }
+
+ return true;
+}
+
+} // namespace LogAllocatorStats
diff --git a/libc/malloc_debug/LogAllocatorStats.h b/libc/malloc_debug/LogAllocatorStats.h
new file mode 100644
index 0000000..99e0738
--- /dev/null
+++ b/libc/malloc_debug/LogAllocatorStats.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+// Forward declarations
+class ConfigData;
+
+namespace LogAllocatorStats {
+
+bool Initialize(const Config& config);
+
+void CheckIfShouldLog();
+
+} // namespace LogAllocatorStats
diff --git a/libc/malloc_debug/README.md b/libc/malloc_debug/README.md
index 37fafa7..4e39bed 100644
--- a/libc/malloc_debug/README.md
+++ b/libc/malloc_debug/README.md
@@ -340,6 +340,16 @@
04-15 12:35:33.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so
04-15 12:35:33.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so
+### log\_allocator\_stats\_on\_signal
+As of Android V, this option will trigger a call to:
+
+ mallopt(M_LOG_STATS, 0);
+
+When a process receives the signal SIGRTMAX - 15 (which is 49 on Android
+devices). The mallopt call is not async safe and is not called from the
+signal handler directly. Instead, the next time any allocation call occurs,
+the mallopt is called.
+
### record\_allocs[=TOTAL\_ENTRIES]
Keep track of every allocation/free made on every thread and dump them
to a file when the signal SIGRTMAX - 18 (which is 46 on Android devices)
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index b06ec9e..3731a5d 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -53,6 +53,7 @@
#include "Config.h"
#include "DebugData.h"
+#include "LogAllocatorStats.h"
#include "Unreachable.h"
#include "UnwindBacktrace.h"
#include "backtrace.h"
@@ -517,11 +518,15 @@
}
static TimedResult InternalMalloc(size_t size) {
- if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
+ uint64_t options = g_debug->config().options();
+ if ((options & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
debug_dump_heap(android::base::StringPrintf(
"%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
.c_str());
}
+ if (options & LOG_ALLOCATOR_STATS_ON_SIGNAL) {
+ LogAllocatorStats::CheckIfShouldLog();
+ }
if (size == 0) {
size = 1;
@@ -593,11 +598,15 @@
}
static TimedResult InternalFree(void* pointer) {
- if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
+ uint64_t options = g_debug->config().options();
+ if ((options & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
debug_dump_heap(android::base::StringPrintf(
"%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
.c_str());
}
+ if (options & LOG_ALLOCATOR_STATS_ON_SIGNAL) {
+ LogAllocatorStats::CheckIfShouldLog();
+ }
void* free_pointer = pointer;
size_t bytes;
diff --git a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
index a911e76..84c9145 100644
--- a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
@@ -824,6 +824,24 @@
ASSERT_STREQ((log_msg + usage_string).c_str(), getFakeLogPrint().c_str());
}
+TEST_F(MallocDebugConfigTest, log_allocator_stats_on_signal) {
+ ASSERT_TRUE(InitConfig("log_allocator_stats_on_signal")) << getFakeLogPrint();
+ ASSERT_EQ(LOG_ALLOCATOR_STATS_ON_SIGNAL, config->options());
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, trigger_log_allocator_stats_on_signal_fail) {
+ ASSERT_FALSE(InitConfig("log_allocator_stats_on_signal=200")) << getFakeLogPrint();
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string log_msg(
+ "6 malloc_debug malloc_testing: value set for option 'log_allocator_stats_on_signal' "
+ "which does not take a value\n");
+ ASSERT_STREQ((log_msg + usage_string).c_str(), getFakeLogPrint().c_str());
+}
+
TEST_F(MallocDebugConfigTest, size) {
ASSERT_TRUE(InitConfig("backtrace_size=37")) << getFakeLogPrint();
ASSERT_EQ(BACKTRACE_SPECIFIC_SIZES, config->options());
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index bf3ed14..334dada 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -267,6 +267,9 @@
"4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the allocation records.\n",
SIGRTMAX - 18, getpid());
expected_log += android::base::StringPrintf(
+ "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to log allocator stats.\n",
+ SIGRTMAX - 15, getpid());
+ expected_log += android::base::StringPrintf(
"4 malloc_debug malloc_testing: Run: 'kill -%d %d' to check for unreachable memory.\n",
SIGRTMAX - 16, getpid());
}
@@ -348,6 +351,16 @@
ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
}
+TEST_F(MallocDebugTest, verbose_log_allocator_stats_on_signal) {
+ Init("verbose log_allocator_stats_on_signal");
+
+ std::string expected_log = android::base::StringPrintf(
+ "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to log allocator stats.\n", SIGRTMAX - 15,
+ getpid());
+ expected_log += "4 malloc_debug malloc_testing: malloc debug enabled\n";
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
TEST_F(MallocDebugTest, fill_on_free) {
Init("fill_on_free free_track free_track_backtrace_num_frames=0");
@@ -411,7 +424,8 @@
TEST_F(MallocDebugTest, all_options) {
Init(
"guard backtrace backtrace_enable_on_signal fill expand_alloc free_track leak_track "
- "record_allocs verify_pointers abort_on_error verbose check_unreachable_on_signal");
+ "record_allocs verify_pointers abort_on_error verbose check_unreachable_on_signal "
+ "log_allocator_stats_on_signal");
VerifyAllocCalls(true);
}
@@ -2781,6 +2795,27 @@
getFakeLogPrint().c_str());
}
+TEST_F(MallocDebugTest, log_allocator_stats_on_signal) {
+ Init("log_allocator_stats_on_signal");
+
+ ASSERT_TRUE(kill(getpid(), SIGRTMAX - 15) == 0);
+ sleep(1);
+
+ // The first unreachable check will pass.
+ void* pointer = debug_malloc(110);
+ ASSERT_TRUE(pointer != nullptr);
+ debug_free(pointer);
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ if (!running_with_hwasan()) {
+ // Do an exact match because the mallopt should not fail in normal operation.
+ ASSERT_STREQ("4 malloc_debug Logging allocator stats...\n", getFakeLogPrint().c_str());
+ } else {
+ // mallopt fails with hwasan, so just verify that the message is present.
+ ASSERT_MATCH(getFakeLogPrint(), "4 malloc_debug Logging allocator stats...\\n");
+ }
+}
+
TEST_F(MallocDebugTest, backtrace_only_some_sizes_with_backtrace_size) {
Init("leak_track backtrace backtrace_size=120");
diff --git a/libc/tools/generate_notice.py b/libc/tools/generate_notice.py
index 505708a..69d2d00 100755
--- a/libc/tools/generate_notice.py
+++ b/libc/tools/generate_notice.py
@@ -45,14 +45,6 @@
return True
-def is_auto_generated(content):
- if "Generated by gensyscalls.py" in content or "generated by genserv.py" in content:
- return True
- if "This header was automatically generated from a Linux kernel header" in content:
- return True
- return False
-
-
def is_copyright_end(line: str, first_line_was_hash: bool) -> bool:
endings = [
" $FreeBSD: ",
@@ -153,10 +145,6 @@
warn_verbose("ignoring short file %s" % path)
return
- if is_auto_generated(content):
- warn_verbose("ignoring auto-generated file %s" % path)
- return
-
if not "Copyright" in content:
if "public domain" in content.lower():
warn_verbose("ignoring public domain file %s" % path)
diff --git a/libdl/Android.bp b/libdl/Android.bp
index fde3dfc..762aeef 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -148,10 +148,6 @@
"//apex_available:platform",
"com.android.runtime",
],
-
- lto: {
- never: true,
- },
}
cc_library {
diff --git a/linker/Android.bp b/linker/Android.bp
index 0ccd16d..2ca962a 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -498,10 +498,6 @@
"//apex_available:platform",
"com.android.runtime",
],
-
- lto: {
- never: true,
- },
}
cc_test {
diff --git a/tests/ifunc_test.cpp b/tests/ifunc_test.cpp
index 1fdbf1a..09d987d 100644
--- a/tests/ifunc_test.cpp
+++ b/tests/ifunc_test.cpp
@@ -65,18 +65,18 @@
#include <sys/hwprobe.h>
static uint64_t g_hwcap;
+static __riscv_hwprobe_t g_hwprobe_ptr;
+static void* g_null;
static riscv_hwprobe g_hwprobes[] = {{.key = RISCV_HWPROBE_KEY_IMA_EXT_0}};
-extern "C" fn_ptr_t hwcap_resolver(uint64_t hwcap, void* null) {
- // Check hwcap like arm32/arm64.
+extern "C" fn_ptr_t hwcap_resolver(uint64_t hwcap, __riscv_hwprobe_t hwprobe_ptr, void* null) {
g_hwcap = hwcap;
-
- // For now, the pointer argument is reserved for future expansion.
- if (null != NULL) abort();
+ g_hwprobe_ptr = hwprobe_ptr;
+ g_null = null;
// Ensure that __riscv_hwprobe() can be called from an ifunc.
- if (__riscv_hwprobe(g_hwprobes, 1, 0, nullptr, 0) != 0) return nullptr;
+ if ((*hwprobe_ptr)(g_hwprobes, 1, 0, nullptr, 0) != 0) return nullptr;
return ret42;
}
@@ -102,7 +102,11 @@
#elif defined(__arm__)
EXPECT_EQ(getauxval(AT_HWCAP), g_hwcap);
#elif defined(__riscv)
+ printf("hwcap=%lx hwprobe_ptr=%p (__riscv_hwprobe=%p) null=%p\n", g_hwcap, g_hwprobe_ptr,
+ __riscv_hwprobe, g_null);
+
EXPECT_EQ(getauxval(AT_HWCAP), g_hwcap);
+ EXPECT_EQ(nullptr, g_null);
riscv_hwprobe probes[] = {{.key = RISCV_HWPROBE_KEY_IMA_EXT_0}};
ASSERT_EQ(0, __riscv_hwprobe(probes, 1, 0, nullptr, 0));
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 51f5ac6..5d143f8 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -29,6 +29,7 @@
"-Wl,--rpath,${ORIGIN}",
"-Wl,--enable-new-dtags",
],
+ static_libs: ["libbase"],
relative_install_path: "bionic-loader-test-libs",
gtest: false,
sanitize: {
diff --git a/tests/libs/heap_tagging_helper.cpp b/tests/libs/heap_tagging_helper.cpp
index ed5601a..7aad392 100644
--- a/tests/libs/heap_tagging_helper.cpp
+++ b/tests/libs/heap_tagging_helper.cpp
@@ -16,12 +16,15 @@
#include <signal.h>
#include <stdio.h>
+#include <stdlib.h>
#include <sys/auxv.h>
#include <sys/cdefs.h>
#include <sys/mman.h>
#include <unistd.h>
#include <memory>
+#include <android-base/stringprintf.h>
+
void action(int signo, siginfo_t* info __unused, void*) {
#ifdef __ANDROID__
if (signo == 11 && info->si_code == SEGV_MTEAERR) {
@@ -89,6 +92,13 @@
}
#endif // __aarch64__
+ // In fact, make sure that there are no tagged mappings at all.
+ auto cmd = android::base::StringPrintf("cat /proc/%d/smaps | grep -E 'VmFlags:.* mt'", getpid());
+ if (system(cmd.c_str()) == 0) {
+ fprintf(stderr, "unexpected PROT_MTE mappings found\n");
+ return 1;
+ }
+
fprintf(stderr, "normal exit\n");
return 0;
}