Merge "Disable clang-tidy for some malloc tests."
diff --git a/OWNERS b/OWNERS
index 670f88d..3818b1d 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,6 +1,7 @@
enh@google.com
cferris@google.com
+chiahungduan@google.com
danalbert@google.com
rprichard@google.com
yabinc@google.com
diff --git a/libc/Android.bp b/libc/Android.bp
index e1803b8..6442bc9 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -248,6 +248,7 @@
cc_library_static {
defaults: ["libc_defaults"],
+ tidy_disabled_srcs: ["upstream-*/**/*.c"],
srcs: [
"tzcode/**/*.c",
"tzcode/bionic.cpp",
@@ -291,6 +292,7 @@
cc_library_static {
defaults: ["libc_defaults"],
+ tidy_disabled_srcs: ["upstream-*/**/*.c"],
srcs: [
"dns/**/*.c*",
@@ -326,6 +328,7 @@
cc_library_static {
defaults: ["libc_defaults"],
+ tidy_disabled_srcs: ["upstream-*/**/*.c"],
srcs: [
"upstream-freebsd/lib/libc/gen/ldexp.c",
"upstream-freebsd/lib/libc/stdlib/getopt_long.c",
@@ -392,6 +395,7 @@
cc_library_static {
defaults: ["libc_defaults"],
+ tidy_disabled_srcs: ["upstream-*/**/*.c"],
srcs: [
"upstream-freebsd/lib/libc/gen/glob.c",
],
@@ -419,6 +423,7 @@
cc_library_static {
defaults: ["libc_defaults"],
+ tidy_disabled_srcs: ["upstream-*/**/*.c"],
srcs: [
"upstream-netbsd/common/lib/libc/stdlib/random.c",
"upstream-netbsd/lib/libc/gen/nice.c",
@@ -476,6 +481,7 @@
cc_library_static {
name: "libc_openbsd_ndk",
defaults: ["libc_defaults"],
+ tidy_disabled_srcs: ["upstream-*/**/*.c"],
srcs: [
"upstream-openbsd/lib/libc/gen/alarm.c",
"upstream-openbsd/lib/libc/gen/ctype_.c",
@@ -594,6 +600,7 @@
cc_library_static {
name: "libc_openbsd_large_stack",
defaults: ["libc_defaults"],
+ tidy_disabled_srcs: ["upstream-*/**/*.c"],
srcs: [
"stdio/vfprintf.cpp",
"stdio/vfwprintf.cpp",
@@ -623,6 +630,7 @@
// automatically included.
cc_library_static {
defaults: ["libc_defaults"],
+ tidy_disabled_srcs: ["upstream-*/**/*.c"],
srcs: [
// These two depend on getentropy, which isn't in libc_ndk.a.
"upstream-openbsd/lib/libc/crypt/arc4random.c",
@@ -722,6 +730,7 @@
cc_library_static {
defaults: ["libc_defaults"],
+ tidy_disabled_srcs: ["upstream-*/**/*.c"],
srcs: [
"upstream-openbsd/android/gdtoa_support.cpp",
"upstream-openbsd/lib/libc/gdtoa/dmisc.c",
@@ -2263,8 +2272,8 @@
// libc dependencies for baremetal Rust projects.
// ========================================================
-cc_defaults {
- name: "librust_baremetal_defaults",
+cc_library_static {
+ name: "librust_baremetal",
header_libs: ["libc_headers"],
include_dirs: [
"bionic/libc/async_safe/include",
@@ -2274,17 +2283,12 @@
"-Wall",
"-Werror",
],
- system_shared_libs: [],
- nocrt: true,
- stl: "none",
-}
-
-cc_library_static {
- name: "librust_baremetal",
- defaults: ["librust_baremetal_defaults"],
whole_static_libs: [
"libarm-optimized-routines-mem",
],
+ system_shared_libs: [],
+ nocrt: true,
+ stl: "none",
visibility: [
"//packages/modules/Virtualization/vmbase",
],
@@ -2812,6 +2816,7 @@
cc_library_host_static {
name: "libfts",
+ tidy_disabled_srcs: ["upstream-*/**/*.c"],
srcs: [
"bionic/fts.c",
"upstream-openbsd/lib/libc/stdlib/recallocarray.c",
@@ -2854,6 +2859,7 @@
cc_library_host_static {
name: "libb64",
visibility: ["//external/musl"],
+ tidy_disabled_srcs: ["upstream-*/**/*.c"],
srcs: ["upstream-openbsd/lib/libc/net/base64.c"],
export_include_dirs: ["b64/include"],
local_include_dirs: [
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 97e8d15..802a94f 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -371,6 +371,7 @@
extern "C" const char* __scudo_get_stack_depot_addr();
extern "C" const char* __scudo_get_region_info_addr();
extern "C" const char* __scudo_get_ring_buffer_addr();
+extern "C" size_t __scudo_get_ring_buffer_size();
// Initializes memory allocation framework once per process.
static void MallocInitImpl(libc_globals* globals) {
@@ -383,6 +384,7 @@
__libc_shared_globals()->scudo_stack_depot = __scudo_get_stack_depot_addr();
__libc_shared_globals()->scudo_region_info = __scudo_get_region_info_addr();
__libc_shared_globals()->scudo_ring_buffer = __scudo_get_ring_buffer_addr();
+ __libc_shared_globals()->scudo_ring_buffer_size = __scudo_get_ring_buffer_size();
#endif
// Prefer malloc debug since it existed first and is a more complete
diff --git a/libc/include/inttypes.h b/libc/include/inttypes.h
index 7a409d8..f8b7f7d 100644
--- a/libc/include/inttypes.h
+++ b/libc/include/inttypes.h
@@ -257,10 +257,10 @@
__BEGIN_DECLS
intmax_t imaxabs(intmax_t __i) __attribute_const__ __INTRODUCED_IN(19);
imaxdiv_t imaxdiv(intmax_t __numerator, intmax_t __denominator) __attribute_const__ __INTRODUCED_IN(19);
-intmax_t strtoimax(const char* __s, char** __end_ptr, int __base);
-uintmax_t strtoumax(const char* __s, char** __end_ptr, int __base);
-intmax_t wcstoimax(const wchar_t* __s, wchar_t** __end_ptr, int __base) __INTRODUCED_IN(21);
-uintmax_t wcstoumax(const wchar_t* __s, wchar_t** __end_ptr, int __base) __INTRODUCED_IN(21);
+intmax_t strtoimax(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base);
+uintmax_t strtoumax(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base);
+intmax_t wcstoimax(const wchar_t* _Nonnull __s, wchar_t* _Nullable * _Nullable __end_ptr, int __base) __INTRODUCED_IN(21);
+uintmax_t wcstoumax(const wchar_t* _Nonnull __s, wchar_t* _Nullable * _Nullable __end_ptr, int __base) __INTRODUCED_IN(21);
__END_DECLS
#endif
diff --git a/libc/include/langinfo.h b/libc/include/langinfo.h
index d9d8c15..2b43892 100644
--- a/libc/include/langinfo.h
+++ b/libc/include/langinfo.h
@@ -92,8 +92,8 @@
#define NOEXPR 54
#define CRNCYSTR 55
-char* nl_langinfo(nl_item __item) __INTRODUCED_IN(26);
-char* nl_langinfo_l(nl_item __item, locale_t __l) __INTRODUCED_IN(26);
+char* _Nonnull nl_langinfo(nl_item __item) __INTRODUCED_IN(26);
+char* _Nonnull nl_langinfo_l(nl_item __item, locale_t _Nonnull __l) __INTRODUCED_IN(26);
__END_DECLS
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index 40786fa..02bda60 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -40,7 +40,7 @@
* Returns a pointer to the allocated memory on success and returns a null
* pointer and sets `errno` on failure.
*/
-void* malloc(size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(1) __wur;
+void* _Nullable malloc(size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(1) __wur;
/**
* [calloc(3)](http://man7.org/linux/man-pages/man3/calloc.3.html) allocates
@@ -49,7 +49,7 @@
* Returns a pointer to the allocated memory on success and returns a null
* pointer and sets `errno` on failure.
*/
-void* calloc(size_t __item_count, size_t __item_size) __mallocfunc __BIONIC_ALLOC_SIZE(1,2) __wur;
+void* _Nullable calloc(size_t __item_count, size_t __item_size) __mallocfunc __BIONIC_ALLOC_SIZE(1,2) __wur;
/**
* [realloc(3)](http://man7.org/linux/man-pages/man3/realloc.3.html) resizes
@@ -58,7 +58,7 @@
* Returns a pointer (which may be different from `__ptr`) to the resized
* memory on success and returns a null pointer and sets `errno` on failure.
*/
-void* realloc(void* __ptr, size_t __byte_count) __BIONIC_ALLOC_SIZE(2) __wur;
+void* _Nullable realloc(void* _Nullable __ptr, size_t __byte_count) __BIONIC_ALLOC_SIZE(2) __wur;
/**
* [reallocarray(3)](http://man7.org/linux/man-pages/man3/realloc.3.html) resizes
@@ -70,13 +70,13 @@
* Returns a pointer (which may be different from `__ptr`) to the resized
* memory on success and returns a null pointer and sets `errno` on failure.
*/
-void* reallocarray(void* __ptr, size_t __item_count, size_t __item_size) __BIONIC_ALLOC_SIZE(2, 3) __wur __INTRODUCED_IN(29);
+void* _Nullable reallocarray(void* _Nullable __ptr, size_t __item_count, size_t __item_size) __BIONIC_ALLOC_SIZE(2, 3) __wur __INTRODUCED_IN(29);
/**
* [free(3)](http://man7.org/linux/man-pages/man3/free.3.html) deallocates
* memory on the heap.
*/
-void free(void* __ptr);
+void free(void* _Nullable __ptr);
/**
* [memalign(3)](http://man7.org/linux/man-pages/man3/memalign.3.html) allocates
@@ -87,7 +87,7 @@
*
* See also posix_memalign().
*/
-void* memalign(size_t __alignment, size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(2) __wur;
+void* _Nullable memalign(size_t __alignment, size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(2) __wur;
/**
* [malloc_usable_size(3)](http://man7.org/linux/man-pages/man3/malloc_usable_size.3.html)
@@ -95,7 +95,7 @@
*
* Available since API level 17.
*/
-size_t malloc_usable_size(const void* __ptr) __INTRODUCED_IN(17);
+size_t malloc_usable_size(const void* _Nullable __ptr) __INTRODUCED_IN(17);
#define __MALLINFO_BODY \
/** Total number of non-mmapped bytes currently allocated from OS. */ \
@@ -168,7 +168,7 @@
*
* Available since API level 23.
*/
-int malloc_info(int __must_be_zero, FILE* __fp) __INTRODUCED_IN(23);
+int malloc_info(int __must_be_zero, FILE* _Nonnull __fp) __INTRODUCED_IN(23);
/**
* mallopt() option to set the decay time. Valid values are 0 and 1.
@@ -329,7 +329,7 @@
*
* See also: [extra documentation](https://android.googlesource.com/platform/bionic/+/master/libc/malloc_hooks/README.md)
*/
-extern void* (*volatile __malloc_hook)(size_t __byte_count, const void* __caller) __INTRODUCED_IN(28);
+extern void* _Nonnull (*volatile _Nonnull __malloc_hook)(size_t __byte_count, const void* _Nonnull __caller) __INTRODUCED_IN(28);
/**
* [__realloc_hook(3)](http://man7.org/linux/man-pages/man3/__realloc_hook.3.html)
@@ -340,7 +340,7 @@
*
* See also: [extra documentation](https://android.googlesource.com/platform/bionic/+/master/libc/malloc_hooks/README.md)
*/
-extern void* (*volatile __realloc_hook)(void* __ptr, size_t __byte_count, const void* __caller) __INTRODUCED_IN(28);
+extern void* _Nonnull (*volatile _Nonnull __realloc_hook)(void* _Nullable __ptr, size_t __byte_count, const void* _Nonnull __caller) __INTRODUCED_IN(28);
/**
* [__free_hook(3)](http://man7.org/linux/man-pages/man3/__free_hook.3.html)
@@ -351,7 +351,7 @@
*
* See also: [extra documentation](https://android.googlesource.com/platform/bionic/+/master/libc/malloc_hooks/README.md)
*/
-extern void (*volatile __free_hook)(void* __ptr, const void* __caller) __INTRODUCED_IN(28);
+extern void (*volatile _Nonnull __free_hook)(void* _Nullable __ptr, const void* _Nonnull __caller) __INTRODUCED_IN(28);
/**
* [__memalign_hook(3)](http://man7.org/linux/man-pages/man3/__memalign_hook.3.html)
@@ -362,6 +362,6 @@
*
* See also: [extra documentation](https://android.googlesource.com/platform/bionic/+/master/libc/malloc_hooks/README.md)
*/
-extern void* (*volatile __memalign_hook)(size_t __alignment, size_t __byte_count, const void* __caller) __INTRODUCED_IN(28);
+extern void* _Nonnull (*volatile _Nonnull __memalign_hook)(size_t __alignment, size_t __byte_count, const void* _Nonnull __caller) __INTRODUCED_IN(28);
__END_DECLS
diff --git a/libc/include/syslog.h b/libc/include/syslog.h
index 45de253..d89d769 100644
--- a/libc/include/syslog.h
+++ b/libc/include/syslog.h
@@ -133,9 +133,10 @@
/**
* [openlog(3)](http://man7.org/linux/man-pages/man3/openlog.3.html) sets
- * the log tag to `__prefix`. On Android, the other two arguments are ignored.
+ * the log tag to `__prefix`, which can be NULL to return to the default of
+ * getprogname(). On Android, the other two arguments are ignored.
*/
-void openlog(const char* __prefix, int __option, int __facility);
+void openlog(const char* _Nullable __prefix, int __option, int __facility);
/**
* [setlogmask(3)](http://man7.org/linux/man-pages/man3/setlogmask.3.html)
@@ -149,13 +150,13 @@
* the printf()-like message and logs it with the given priority, unless
* suppressed by setlogmask(). On Android, the output goes to logcat.
*/
-void syslog(int __priority, const char* __fmt, ...) __printflike(2, 3);
+void syslog(int __priority, const char* _Nonnull __fmt, ...) __printflike(2, 3);
/**
* [vsyslog(3)](http://man7.org/linux/man-pages/man3/vsyslog.3.html) formats
* the vprintf()-like message and logs it with the given priority, unless
* suppressed by setlogmask(). On Android, the output goes to logcat.
*/
-void vsyslog(int __priority, const char* __fmt, va_list __args) __printflike(2, 0);
+void vsyslog(int __priority, const char* _Nonnull __fmt, va_list __args) __printflike(2, 0);
__END_DECLS
diff --git a/libc/include/time.h b/libc/include/time.h
index 0db14ff..4b005c6 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -37,7 +37,7 @@
#define CLOCKS_PER_SEC 1000000
-extern char* tzname[];
+extern char* _Nonnull tzname[];
extern int daylight;
extern long int timezone;
@@ -54,62 +54,64 @@
int tm_yday;
int tm_isdst;
long int tm_gmtoff;
- const char* tm_zone;
+ const char* _Nullable tm_zone;
};
#define TM_ZONE tm_zone
-time_t time(time_t* __t);
-int nanosleep(const struct timespec* __request, struct timespec* __remainder);
+time_t time(time_t* _Nullable __t);
+int nanosleep(const struct timespec* _Nonnull __request, struct timespec* _Nullable __remainder);
-char* asctime(const struct tm* __tm);
-char* asctime_r(const struct tm* __tm, char* __buf);
+char* _Nullable asctime(const struct tm* _Nonnull __tm);
+char* _Nullable asctime_r(const struct tm* _Nonnull __tm, char* _Nonnull __buf);
double difftime(time_t __lhs, time_t __rhs);
-time_t mktime(struct tm* __tm);
+time_t mktime(struct tm* _Nonnull __tm);
-struct tm* localtime(const time_t* __t);
-struct tm* localtime_r(const time_t* __t, struct tm* __tm);
+struct tm* _Nullable localtime(const time_t* _Nonnull __t);
+struct tm* _Nullable localtime_r(const time_t* _Nonnull __t, struct tm* _Nonnull __tm);
-struct tm* gmtime(const time_t* __t);
-struct tm* gmtime_r(const time_t* __t, struct tm* __tm);
+struct tm* _Nullable gmtime(const time_t* _Nonnull __t);
+struct tm* _Nullable gmtime_r(const time_t* _Nonnull __t, struct tm* _Nonnull __tm);
-char* strptime(const char* __s, const char* __fmt, struct tm* __tm) __strftimelike(2);
-char* strptime_l(const char* __s, const char* __fmt, struct tm* __tm, locale_t __l) __strftimelike(2) __INTRODUCED_IN(28);
+char* _Nullable strptime(const char* _Nonnull __s, const char* _Nonnull __fmt, struct tm* _Nonnull __tm) __strftimelike(2);
+char* _Nullable strptime_l(const char* _Nonnull __s, const char* _Nonnull __fmt, struct tm* _Nonnull __tm, locale_t _Nonnull __l) __strftimelike(2) __INTRODUCED_IN(28);
-size_t strftime(char* __buf, size_t __n, const char* __fmt, const struct tm* __tm) __strftimelike(3);
+size_t strftime(char* _Nonnull __buf, size_t __n, const char* _Nonnull __fmt, const struct tm* _Nullable __tm) __strftimelike(3);
#if __ANDROID_API__ >= 21
-size_t strftime_l(char* __buf, size_t __n, const char* __fmt, const struct tm* __tm, locale_t __l) __strftimelike(3) __INTRODUCED_IN(21);
+size_t strftime_l(char* _Nonnull __buf, size_t __n, const char* _Nonnull __fmt, const struct tm* _Nullable __tm, locale_t _Nonnull __l) __strftimelike(3) __INTRODUCED_IN(21);
#else
// Implemented as static inline before 21.
#endif
-char* ctime(const time_t* __t);
-char* ctime_r(const time_t* __t, char* __buf);
+
+char* _Nullable ctime(const time_t* _Nonnull __t);
+char* _Nullable ctime_r(const time_t* _Nonnull __t, char* _Nonnull __buf);
void tzset(void);
clock_t clock(void);
-int clock_getcpuclockid(pid_t __pid, clockid_t* __clock) __INTRODUCED_IN(23);
+int clock_getcpuclockid(pid_t __pid, clockid_t* _Nonnull __clock) __INTRODUCED_IN(23);
-int clock_getres(clockid_t __clock, struct timespec* __resolution);
-int clock_gettime(clockid_t __clock, struct timespec* __ts);
-int clock_nanosleep(clockid_t __clock, int __flags, const struct timespec* __request, struct timespec* __remainder);
-int clock_settime(clockid_t __clock, const struct timespec* __ts);
-int timer_create(clockid_t __clock, struct sigevent* __event, timer_t* __timer_ptr);
-int timer_delete(timer_t __timer);
-int timer_settime(timer_t __timer, int __flags, const struct itimerspec* __new_value, struct itimerspec* __old_value);
-int timer_gettime(timer_t __timer, struct itimerspec* __ts);
-int timer_getoverrun(timer_t __timer);
+int clock_getres(clockid_t __clock, struct timespec* _Nullable __resolution);
+int clock_gettime(clockid_t __clock, struct timespec* _Nonnull __ts);
+int clock_nanosleep(clockid_t __clock, int __flags, const struct timespec* _Nonnull __request, struct timespec* _Nullable __remainder);
+int clock_settime(clockid_t __clock, const struct timespec* _Nonnull __ts);
+
+int timer_create(clockid_t __clock, struct sigevent* _Nullable __event, timer_t _Nonnull * _Nonnull __timer_ptr);
+int timer_delete(timer_t _Nonnull __timer);
+int timer_settime(timer_t _Nonnull __timer, int __flags, const struct itimerspec* _Nonnull __new_value, struct itimerspec* _Nullable __old_value);
+int timer_gettime(timer_t _Nonnull _timer, struct itimerspec* _Nonnull __ts);
+int timer_getoverrun(timer_t _Nonnull __timer);
/* Non-standard extensions that are in the BSDs and glibc. */
-time_t timelocal(struct tm* __tm);
-time_t timegm(struct tm* __tm);
+time_t timelocal(struct tm* _Nonnull __tm);
+time_t timegm(struct tm* _Nonnull __tm);
#define TIME_UTC 1
-int timespec_get(struct timespec* __ts, int __base) __INTRODUCED_IN(29);
+int timespec_get(struct timespec* _Nonnull __ts, int __base) __INTRODUCED_IN(29);
__END_DECLS
diff --git a/libc/include/time64.h b/libc/include/time64.h
index 905669d..7d70030 100644
--- a/libc/include/time64.h
+++ b/libc/include/time64.h
@@ -47,17 +47,17 @@
typedef int64_t time64_t;
-char* asctime64(const struct tm*);
-char* asctime64_r(const struct tm*, char*);
-char* ctime64(const time64_t*);
-char* ctime64_r(const time64_t*, char*);
-struct tm* gmtime64(const time64_t*);
-struct tm* gmtime64_r(const time64_t*, struct tm*);
-struct tm* localtime64(const time64_t*);
-struct tm* localtime64_r(const time64_t*, struct tm*);
-time64_t mktime64(const struct tm*);
-time64_t timegm64(const struct tm*);
-time64_t timelocal64(const struct tm*);
+char* _Nullable asctime64(const struct tm* _Nonnull);
+char* _Nullable asctime64_r(const struct tm* _Nonnull, char* _Nonnull);
+char* _Nullable ctime64(const time64_t* _Nonnull);
+char* _Nullable ctime64_r(const time64_t* _Nonnull, char* _Nonnull);
+struct tm* _Nullable gmtime64(const time64_t* _Nonnull);
+struct tm* _Nullable gmtime64_r(const time64_t* _Nonnull, struct tm* _Nonnull);
+struct tm* _Nullable localtime64(const time64_t* _Nonnull);
+struct tm* _Nullable localtime64_r(const time64_t* _Nonnull, struct tm* _Nonnull);
+time64_t mktime64(const struct tm* _Nonnull);
+time64_t timegm64(const struct tm* _Nonnull);
+time64_t timelocal64(const struct tm* _Nonnull);
__END_DECLS
diff --git a/libc/malloc_debug/RecordData.cpp b/libc/malloc_debug/RecordData.cpp
index a829a09..8a77170 100644
--- a/libc/malloc_debug/RecordData.cpp
+++ b/libc/malloc_debug/RecordData.cpp
@@ -28,6 +28,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <pthread.h>
#include <stdatomic.h>
#include <stdint.h>
@@ -52,40 +53,51 @@
return dprintf(fd, "%d: thread_done 0x0\n", tid_) > 0;
}
-AllocEntry::AllocEntry(void* pointer) : pointer_(pointer) {}
+AllocEntry::AllocEntry(void* pointer, uint64_t start_ns, uint64_t end_ns)
+ : pointer_(pointer), start_ns_(start_ns), end_ns_(end_ns) {}
-MallocEntry::MallocEntry(void* pointer, size_t size) : AllocEntry(pointer), size_(size) {}
+MallocEntry::MallocEntry(void* pointer, size_t size, uint64_t start_ns, uint64_t end_ns)
+ : AllocEntry(pointer, start_ns, end_ns), size_(size) {}
bool MallocEntry::Write(int fd) const {
- return dprintf(fd, "%d: malloc %p %zu\n", tid_, pointer_, size_) > 0;
+ return dprintf(fd, "%d: malloc %p %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_, size_,
+ start_ns_, end_ns_) > 0;
}
-FreeEntry::FreeEntry(void* pointer) : AllocEntry(pointer) {}
+FreeEntry::FreeEntry(void* pointer, uint64_t start_ns, uint64_t end_ns)
+ : AllocEntry(pointer, start_ns, end_ns) {}
bool FreeEntry::Write(int fd) const {
- return dprintf(fd, "%d: free %p\n", tid_, pointer_) > 0;
+ return dprintf(fd, "%d: free %p %" PRIu64 " %" PRIu64 "\n", tid_, pointer_, start_ns_, end_ns_) >
+ 0;
}
-CallocEntry::CallocEntry(void* pointer, size_t nmemb, size_t size)
- : MallocEntry(pointer, size), nmemb_(nmemb) {}
+CallocEntry::CallocEntry(void* pointer, size_t nmemb, size_t size, uint64_t start_ns,
+ uint64_t end_ns)
+ : MallocEntry(pointer, size, start_ns, end_ns), nmemb_(nmemb) {}
bool CallocEntry::Write(int fd) const {
- return dprintf(fd, "%d: calloc %p %zu %zu\n", tid_, pointer_, nmemb_, size_) > 0;
+ return dprintf(fd, "%d: calloc %p %zu %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_, nmemb_,
+ size_, start_ns_, end_ns_) > 0;
}
-ReallocEntry::ReallocEntry(void* pointer, size_t size, void* old_pointer)
- : MallocEntry(pointer, size), old_pointer_(old_pointer) {}
+ReallocEntry::ReallocEntry(void* pointer, size_t size, void* old_pointer, uint64_t start_ns,
+ uint64_t end_ns)
+ : MallocEntry(pointer, size, start_ns, end_ns), old_pointer_(old_pointer) {}
bool ReallocEntry::Write(int fd) const {
- return dprintf(fd, "%d: realloc %p %p %zu\n", tid_, pointer_, old_pointer_, size_) > 0;
+ return dprintf(fd, "%d: realloc %p %p %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_,
+ old_pointer_, size_, start_ns_, end_ns_) > 0;
}
// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
-MemalignEntry::MemalignEntry(void* pointer, size_t size, size_t alignment)
- : MallocEntry(pointer, size), alignment_(alignment) {}
+MemalignEntry::MemalignEntry(void* pointer, size_t size, size_t alignment, uint64_t start_ns,
+ uint64_t end_ns)
+ : MallocEntry(pointer, size, start_ns, end_ns), alignment_(alignment) {}
bool MemalignEntry::Write(int fd) const {
- return dprintf(fd, "%d: memalign %p %zu %zu\n", tid_, pointer_, alignment_, size_) > 0;
+ return dprintf(fd, "%d: memalign %p %zu %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_,
+ alignment_, size_, start_ns_, end_ns_) > 0;
}
struct ThreadData {
diff --git a/libc/malloc_debug/RecordData.h b/libc/malloc_debug/RecordData.h
index 43dba6a..a02c956 100644
--- a/libc/malloc_debug/RecordData.h
+++ b/libc/malloc_debug/RecordData.h
@@ -68,19 +68,23 @@
class AllocEntry : public RecordEntry {
public:
- explicit AllocEntry(void* pointer);
+ explicit AllocEntry(void* pointer, uint64_t st, uint64_t et);
virtual ~AllocEntry() = default;
protected:
void* pointer_;
+ // The start/end time of this operation.
+ uint64_t start_ns_;
+ uint64_t end_ns_;
+
private:
BIONIC_DISALLOW_COPY_AND_ASSIGN(AllocEntry);
};
class MallocEntry : public AllocEntry {
public:
- MallocEntry(void* pointer, size_t size);
+ MallocEntry(void* pointer, size_t size, uint64_t st, uint64_t et);
virtual ~MallocEntry() = default;
bool Write(int fd) const override;
@@ -94,7 +98,7 @@
class FreeEntry : public AllocEntry {
public:
- explicit FreeEntry(void* pointer);
+ explicit FreeEntry(void* pointer, uint64_t st, uint64_t et);
virtual ~FreeEntry() = default;
bool Write(int fd) const override;
@@ -105,7 +109,7 @@
class CallocEntry : public MallocEntry {
public:
- CallocEntry(void* pointer, size_t size, size_t nmemb);
+ CallocEntry(void* pointer, size_t nmemb, size_t size, uint64_t st, uint64_t et);
virtual ~CallocEntry() = default;
bool Write(int fd) const override;
@@ -119,7 +123,7 @@
class ReallocEntry : public MallocEntry {
public:
- ReallocEntry(void* pointer, size_t size, void* old_pointer);
+ ReallocEntry(void* pointer, size_t size, void* old_pointer, uint64_t st, uint64_t et);
virtual ~ReallocEntry() = default;
bool Write(int fd) const override;
@@ -134,7 +138,7 @@
// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
class MemalignEntry : public MallocEntry {
public:
- MemalignEntry(void* pointer, size_t size, size_t alignment);
+ MemalignEntry(void* pointer, size_t size, size_t alignment, uint64_t st, uint64_t et);
virtual ~MemalignEntry() = default;
bool Write(int fd) const override;
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 617858a..4bc5649 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -68,6 +68,100 @@
bool* g_zygote_child;
const MallocDispatch* g_dispatch;
+
+static __always_inline uint64_t Nanotime() {
+ struct timespec t = {};
+ clock_gettime(CLOCK_MONOTONIC, &t);
+ return static_cast<uint64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
+}
+
+namespace {
+// A TimedResult contains the result of from malloc end_ns al. functions and the
+// start/end timestamps.
+struct TimedResult {
+ uint64_t start_ns = 0;
+ uint64_t end_ns = 0;
+ union {
+ size_t s;
+ int i;
+ void* p;
+ } v;
+
+ uint64_t GetStartTimeNS() const { return start_ns; }
+ uint64_t GetEndTimeNS() const { return end_ns; }
+ void SetStartTimeNS(uint64_t t) { start_ns = t; }
+ void SetEndTimeNS(uint64_t t) { end_ns = t; }
+
+ template <typename T>
+ void setValue(T);
+ template <>
+ void setValue(size_t s) {
+ v.s = s;
+ }
+ template <>
+ void setValue(int i) {
+ v.i = i;
+ }
+ template <>
+ void setValue(void* p) {
+ v.p = p;
+ }
+
+ template <typename T>
+ T getValue() const;
+ template <>
+ size_t getValue<size_t>() const {
+ return v.s;
+ }
+ template <>
+ int getValue<int>() const {
+ return v.i;
+ }
+ template <>
+ void* getValue<void*>() const {
+ return v.p;
+ }
+};
+
+class ScopedTimer {
+ public:
+ ScopedTimer(TimedResult& res) : res_(res) { res_.start_ns = Nanotime(); }
+
+ ~ScopedTimer() { res_.end_ns = Nanotime(); }
+
+ private:
+ TimedResult& res_;
+};
+
+} // namespace
+
+template <typename MallocFn, typename... Args>
+static TimedResult TimerCall(MallocFn fn, Args... args) {
+ TimedResult ret;
+ decltype((g_dispatch->*fn)(args...)) r;
+ if (g_debug->config().options() & RECORD_ALLOCS) {
+ ScopedTimer t(ret);
+ r = (g_dispatch->*fn)(args...);
+ } else {
+ r = (g_dispatch->*fn)(args...);
+ }
+ ret.setValue<decltype(r)>(r);
+ return ret;
+}
+
+template <typename MallocFn, typename... Args>
+static TimedResult TimerCallVoid(MallocFn fn, Args... args) {
+ TimedResult ret;
+ {
+ ScopedTimer t(ret);
+ (g_dispatch->*fn)(args...);
+ }
+ return ret;
+}
+
+#define TCALL(FUNC, ...) TimerCall(&MallocDispatch::FUNC, __VA_ARGS__);
+#define TCALLVOID(FUNC, ...) TimerCallVoid(&MallocDispatch::FUNC, __VA_ARGS__);
+
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
@@ -419,7 +513,7 @@
return InternalMallocUsableSize(pointer);
}
-static void* InternalMalloc(size_t size) {
+static TimedResult InternalMalloc(size_t size) {
if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
debug_dump_heap(android::base::StringPrintf(
"%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
@@ -430,30 +524,35 @@
size = 1;
}
+ TimedResult result;
+
size_t real_size = size + g_debug->extra_bytes();
if (real_size < size) {
// Overflow.
errno = ENOMEM;
- return nullptr;
+ result.setValue<void*>(nullptr);
+ return result;
}
if (size > PointerInfoType::MaxSize()) {
errno = ENOMEM;
- return nullptr;
+ result.setValue<void*>(nullptr);
+ return result;
}
- void* pointer;
if (g_debug->HeaderEnabled()) {
- Header* header =
- reinterpret_cast<Header*>(g_dispatch->memalign(MINIMUM_ALIGNMENT_BYTES, real_size));
+ result = TCALL(memalign, MINIMUM_ALIGNMENT_BYTES, real_size);
+ Header* header = reinterpret_cast<Header*>(result.getValue<void*>());
if (header == nullptr) {
- return nullptr;
+ return result;
}
- pointer = InitHeader(header, header, size);
+ result.setValue<void*>(InitHeader(header, header, size));
} else {
- pointer = g_dispatch->malloc(real_size);
+ result = TCALL(malloc, real_size);
}
+ void* pointer = result.getValue<void*>();
+
if (pointer != nullptr) {
if (g_debug->TrackPointers()) {
PointerData::Add(pointer, size);
@@ -466,7 +565,8 @@
memset(pointer, g_debug->config().fill_alloc_value(), bytes);
}
}
- return pointer;
+
+ return result;
}
void* debug_malloc(size_t size) {
@@ -479,16 +579,17 @@
ScopedDisableDebugCalls disable;
ScopedBacktraceSignalBlocker blocked;
- void* pointer = InternalMalloc(size);
+ TimedResult result = InternalMalloc(size);
if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new MallocEntry(pointer, size));
+ g_debug->record->AddEntry(new MallocEntry(result.getValue<void*>(), size,
+ result.GetStartTimeNS(), result.GetEndTimeNS()));
}
- return pointer;
+ return result.getValue<void*>();
}
-static void InternalFree(void* pointer) {
+static TimedResult InternalFree(void* pointer) {
if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
debug_dump_heap(android::base::StringPrintf(
"%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
@@ -530,6 +631,7 @@
PointerData::Remove(pointer);
}
+ TimedResult result;
if (g_debug->config().options() & FREE_TRACK) {
// Do not add the allocation until we are done modifying the pointer
// itself. This avoids a race if a lot of threads are all doing
@@ -537,15 +639,15 @@
// pointer from another thread, while still trying to free it in
// this function.
pointer = PointerData::AddFreed(pointer, bytes);
- if (pointer != nullptr) {
- if (g_debug->HeaderEnabled()) {
- pointer = g_debug->GetHeader(pointer)->orig_pointer;
- }
- g_dispatch->free(pointer);
+ if (pointer != nullptr && g_debug->HeaderEnabled()) {
+ pointer = g_debug->GetHeader(pointer)->orig_pointer;
}
+ result = TCALLVOID(free, pointer);
} else {
- g_dispatch->free(free_pointer);
+ result = TCALLVOID(free, free_pointer);
}
+
+ return result;
}
void debug_free(void* pointer) {
@@ -558,15 +660,16 @@
ScopedDisableDebugCalls disable;
ScopedBacktraceSignalBlocker blocked;
- if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new FreeEntry(pointer));
- }
-
if (!VerifyPointer(pointer, "free")) {
return;
}
- InternalFree(pointer);
+ TimedResult result = InternalFree(pointer);
+
+ if (g_debug->config().options() & RECORD_ALLOCS) {
+ g_debug->record->AddEntry(
+ new FreeEntry(pointer, result.GetStartTimeNS(), result.GetEndTimeNS()));
+ }
}
void* debug_memalign(size_t alignment, size_t bytes) {
@@ -588,6 +691,7 @@
return nullptr;
}
+ TimedResult result;
void* pointer;
if (g_debug->HeaderEnabled()) {
// Make the alignment a power of two.
@@ -610,7 +714,8 @@
return nullptr;
}
- pointer = g_dispatch->malloc(real_size);
+ result = TCALL(malloc, real_size);
+ pointer = result.getValue<void*>();
if (pointer == nullptr) {
return nullptr;
}
@@ -620,6 +725,7 @@
value += (-value % alignment);
Header* header = g_debug->GetHeader(reinterpret_cast<void*>(value));
+ // Don't need to update `result` here because we only need the timestamps.
pointer = InitHeader(header, pointer, bytes);
} else {
size_t real_size = bytes + g_debug->extra_bytes();
@@ -628,7 +734,8 @@
errno = ENOMEM;
return nullptr;
}
- pointer = g_dispatch->memalign(alignment, real_size);
+ result = TCALL(memalign, alignment, real_size);
+ pointer = result.getValue<void*>();
}
if (pointer != nullptr) {
@@ -644,7 +751,8 @@
}
if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new MemalignEntry(pointer, bytes, alignment));
+ g_debug->record->AddEntry(new MemalignEntry(pointer, bytes, alignment,
+ result.GetStartTimeNS(), result.GetEndTimeNS()));
}
}
@@ -662,10 +770,12 @@
ScopedBacktraceSignalBlocker blocked;
if (pointer == nullptr) {
- pointer = InternalMalloc(bytes);
+ TimedResult result = InternalMalloc(bytes);
if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new ReallocEntry(pointer, bytes, nullptr));
+ g_debug->record->AddEntry(new ReallocEntry(result.getValue<void*>(), bytes, nullptr,
+ result.GetStartTimeNS(), result.GetEndTimeNS()));
}
+ pointer = result.getValue<void*>();
return pointer;
}
@@ -674,11 +784,13 @@
}
if (bytes == 0) {
+ TimedResult result = InternalFree(pointer);
+
if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new ReallocEntry(nullptr, bytes, pointer));
+ g_debug->record->AddEntry(new ReallocEntry(nullptr, bytes, pointer, result.GetStartTimeNS(),
+ result.GetEndTimeNS()));
}
- InternalFree(pointer);
return nullptr;
}
@@ -697,6 +809,7 @@
return nullptr;
}
+ TimedResult result;
void* new_pointer;
size_t prev_size;
if (g_debug->HeaderEnabled()) {
@@ -730,7 +843,8 @@
}
// Allocate the new size.
- new_pointer = InternalMalloc(bytes);
+ result = InternalMalloc(bytes);
+ new_pointer = result.getValue<void*>();
if (new_pointer == nullptr) {
errno = ENOMEM;
return nullptr;
@@ -738,14 +852,18 @@
prev_size = header->usable_size;
memcpy(new_pointer, pointer, prev_size);
- InternalFree(pointer);
+ TimedResult free_time = InternalFree(pointer);
+ // `realloc` is split into two steps, update the end time to the finish time
+ // of the second operation.
+ result.SetEndTimeNS(free_time.GetEndTimeNS());
} else {
if (g_debug->TrackPointers()) {
PointerData::Remove(pointer);
}
prev_size = g_dispatch->malloc_usable_size(pointer);
- new_pointer = g_dispatch->realloc(pointer, real_size);
+ result = TCALL(realloc, pointer, real_size);
+ new_pointer = result.getValue<void*>();
if (new_pointer == nullptr) {
return nullptr;
}
@@ -767,7 +885,8 @@
}
if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new ReallocEntry(new_pointer, bytes, pointer));
+ g_debug->record->AddEntry(new ReallocEntry(new_pointer, bytes, pointer, result.GetStartTimeNS(),
+ result.GetEndTimeNS()));
}
return new_pointer;
@@ -807,21 +926,24 @@
}
void* pointer;
+ TimedResult result;
if (g_debug->HeaderEnabled()) {
// Need to guarantee the alignment of the header.
- Header* header =
- reinterpret_cast<Header*>(g_dispatch->memalign(MINIMUM_ALIGNMENT_BYTES, real_size));
+ result = TCALL(memalign, MINIMUM_ALIGNMENT_BYTES, real_size);
+ Header* header = reinterpret_cast<Header*>(result.getValue<void*>());
if (header == nullptr) {
return nullptr;
}
memset(header, 0, g_dispatch->malloc_usable_size(header));
pointer = InitHeader(header, header, size);
} else {
- pointer = g_dispatch->calloc(1, real_size);
+ result = TCALL(calloc, 1, real_size);
+ pointer = result.getValue<void*>();
}
if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new CallocEntry(pointer, bytes, nmemb));
+ g_debug->record->AddEntry(
+ new CallocEntry(pointer, nmemb, bytes, result.GetStartTimeNS(), result.GetEndTimeNS()));
}
if (pointer != nullptr && g_debug->TrackPointers()) {
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index c6378f5..bf3ed14 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -184,6 +184,23 @@
return diff;
}
+static void VerifyRecords(std::vector<std::string>& expected, std::string& actual) {
+ size_t offset = 0;
+ for (std::string& str : expected) {
+ ASSERT_STREQ(str.c_str(), actual.substr(offset, str.size()).c_str());
+ if (str.find("thread_done") != std::string::npos) {
+ offset = actual.find_first_of("\n", offset) + 1;
+ continue;
+ }
+ offset += str.size() + 1;
+ uint64_t st = strtoull(&actual[offset], nullptr, 10);
+ offset = actual.find_first_of(" ", offset) + 1;
+ uint64_t et = strtoull(&actual[offset], nullptr, 10);
+ ASSERT_GT(et, st);
+ offset = actual.find_first_of("\n", offset) + 1;
+ }
+}
+
void VerifyAllocCalls(bool all_options) {
size_t alloc_size = 1024;
@@ -2171,61 +2188,61 @@
#endif
void VerifyRecordAllocs(const std::string& record_filename) {
- std::string expected;
+ std::vector<std::string> expected;
void* pointer = debug_malloc(10);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 10\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 10", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
- pointer = debug_calloc(1, 20);
+ pointer = debug_calloc(20, 1);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: calloc %p 20 1\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: calloc %p 20 1", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
pointer = debug_realloc(nullptr, 30);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: realloc %p 0x0 30\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: realloc %p 0x0 30", getpid(), pointer));
void* old_pointer = pointer;
pointer = debug_realloc(pointer, 2048);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: realloc %p %p 2048\n", getpid(),
- pointer, old_pointer);
+ expected.push_back(
+ android::base::StringPrintf("%d: realloc %p %p 2048", getpid(), pointer, old_pointer));
debug_realloc(pointer, 0);
- expected += android::base::StringPrintf("%d: realloc 0x0 %p 0\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: realloc 0x0 %p 0", getpid(), pointer));
pointer = debug_memalign(16, 40);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: memalign %p 16 40\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: memalign %p 16 40", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
pointer = debug_aligned_alloc(32, 64);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: memalign %p 32 64\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: memalign %p 32 64", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
ASSERT_EQ(0, debug_posix_memalign(&pointer, 32, 50));
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: memalign %p 32 50\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: memalign %p 32 50", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
pointer = debug_pvalloc(60);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: memalign %p 4096 4096\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: memalign %p 4096 4096", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
pointer = debug_valloc(70);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: memalign %p 4096 70\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: memalign %p 4096 70", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
#endif
// Dump all of the data accumulated so far.
@@ -2235,7 +2252,7 @@
std::string actual;
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
- ASSERT_STREQ(expected.c_str(), actual.c_str());
+ VerifyRecords(expected, actual);
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -2256,23 +2273,23 @@
TEST_F(MallocDebugTest, record_allocs_max) {
InitRecordAllocs("record_allocs=5");
- std::string expected;
+ std::vector<std::string> expected;
void* pointer = debug_malloc(10);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 10\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 10", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
pointer = debug_malloc(20);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 20\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 20", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
pointer = debug_malloc(1024);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 1024\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 1024", getpid(), pointer));
debug_free(pointer);
// Dump all of the data accumulated so far.
@@ -2282,7 +2299,7 @@
std::string actual;
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
- ASSERT_STREQ(expected.c_str(), actual.c_str());
+ VerifyRecords(expected, actual);
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ(
@@ -2303,9 +2320,10 @@
});
thread.join();
- std::string expected = android::base::StringPrintf("%d: malloc %p 100\n", tid, pointer);
- expected += android::base::StringPrintf("%d: free %p\n", tid, pointer);
- expected += android::base::StringPrintf("%d: thread_done 0x0\n", tid);
+ std::vector<std::string> expected;
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 100", tid, pointer));
+ expected.push_back(android::base::StringPrintf("%d: free %p", tid, pointer));
+ expected.push_back(android::base::StringPrintf("%d: thread_done 0x0", tid));
// Dump all of the data accumulated so far.
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
@@ -2314,7 +2332,7 @@
std::string actual;
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
- ASSERT_STREQ(expected.c_str(), actual.c_str());
+ VerifyRecords(expected, actual);
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -2329,13 +2347,13 @@
ASSERT_EQ(0, symlink("/data/local/tmp/does_not_exist", record_filename.c_str()));
- std::string expected;
+ std::vector<std::string> expected;
void* pointer = debug_malloc(10);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 10\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 10", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
// Dump all of the data accumulated so far.
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
@@ -2351,7 +2369,8 @@
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
- ASSERT_STREQ(expected.c_str(), actual.c_str());
+
+ VerifyRecords(expected, actual);
ASSERT_STREQ("", getFakeLogBuf().c_str());
std::string expected_log = android::base::StringPrintf(
@@ -2375,13 +2394,13 @@
TEST_F(MallocDebugTest, record_allocs_write_entries_does_not_allocate) {
InitRecordAllocs("record_allocs=5");
- std::string expected;
+ std::vector<std::string> expected;
void* pointer = debug_malloc(10);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 10\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 10", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
malloc_disable();
kill(getpid(), SIGRTMAX - 18);
@@ -2389,7 +2408,8 @@
std::string actual;
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
- ASSERT_STREQ(expected.c_str(), actual.c_str());
+
+ VerifyRecords(expected, actual);
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index c7e951d..520e50f 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -111,6 +111,7 @@
const char* scudo_stack_depot = nullptr;
const char* scudo_region_info = nullptr;
const char* scudo_ring_buffer = nullptr;
+ size_t scudo_ring_buffer_size = 0;
HeapTaggingLevel initial_heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
bool initial_memtag_stack = false;
diff --git a/libm/Android.bp b/libm/Android.bp
index 2748871..3e271fa 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -29,6 +29,7 @@
whole_static_libs: ["libarm-optimized-routines-math"],
+ tidy_disabled_srcs: ["upstream-*/**/*.c"],
srcs: [
"upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c",
"upstream-freebsd/lib/msun/src/catrig.c",
diff --git a/linker/linker_debuggerd_android.cpp b/linker/linker_debuggerd_android.cpp
index cba6345..3d64628 100644
--- a/linker/linker_debuggerd_android.cpp
+++ b/linker/linker_debuggerd_android.cpp
@@ -43,6 +43,7 @@
.scudo_stack_depot = __libc_shared_globals()->scudo_stack_depot,
.scudo_region_info = __libc_shared_globals()->scudo_region_info,
.scudo_ring_buffer = __libc_shared_globals()->scudo_ring_buffer,
+ .scudo_ring_buffer_size = __libc_shared_globals()->scudo_ring_buffer_size,
};
}
#endif
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 19f0cab..73cfced 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -175,7 +175,8 @@
if (did_load_) {
return true;
}
- if (ReserveAddressSpace(address_space) && LoadSegments() && FindPhdr() &&
+ bool reserveSuccess = ReserveAddressSpace(address_space);
+ if (reserveSuccess && LoadSegments() && FindPhdr() &&
FindGnuPropertySection()) {
did_load_ = true;
#if defined(__aarch64__)
@@ -186,6 +187,13 @@
}
#endif
}
+ if (reserveSuccess && !did_load_) {
+ if (load_start_ != nullptr && load_size_ != 0) {
+ if (!mapped_by_caller_) {
+ munmap(load_start_, load_size_);
+ }
+ }
+ }
return did_load_;
}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 40e5c6d..f0ad937 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -998,6 +998,10 @@
ASSERT_EQ(-1, ts.tv_sec);
}
+TEST(time, clock_getres_null_resolution) {
+ ASSERT_EQ(0, clock_getres(CLOCK_REALTIME, nullptr));
+}
+
TEST(time, clock) {
// clock(3) is hard to test, but a 1s sleep should cost less than 10ms on average.
static const clock_t N = 5;