diff options
author | Martin Liska <mliska@suse.cz> | 2023-04-30 09:38:14 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2023-04-30 09:38:14 +0200 |
commit | d96e14ceb9475f9bccbbc0325d5b11419fad9246 (patch) | |
tree | f14ef6e6439c6705bcbe73f1da6c9e6d30db93ec /libsanitizer/sanitizer_common | |
parent | d5e2694e82591d734008982bafdc9ce6da65c0b0 (diff) | |
download | gcc-d96e14ceb9475f9bccbbc0325d5b11419fad9246.zip gcc-d96e14ceb9475f9bccbbc0325d5b11419fad9246.tar.gz gcc-d96e14ceb9475f9bccbbc0325d5b11419fad9246.tar.bz2 |
libsanitizer: merge from upstream (87e6e490e79384a5)
Diffstat (limited to 'libsanitizer/sanitizer_common')
11 files changed, 71 insertions, 119 deletions
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc index 3bd73cf..490a8b1 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc +++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc @@ -7748,8 +7748,7 @@ static void write_protoent(void *ctx, struct __sanitizer_protoent *p) { for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, internal_strlen(*pp) + 1); - COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases, - pp_size * sizeof(char **)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases, pp_size * sizeof(char *)); } INTERCEPTOR(struct __sanitizer_protoent *, getprotoent) { @@ -7855,8 +7854,7 @@ INTERCEPTOR(struct __sanitizer_netent *, getnetent) { for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1); - COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, - nn_size * sizeof(char **)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *)); } return n; } @@ -7877,8 +7875,7 @@ INTERCEPTOR(struct __sanitizer_netent *, getnetbyname, const char *name) { for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1); - COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, - nn_size * sizeof(char **)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *)); } return n; } @@ -7897,8 +7894,7 @@ INTERCEPTOR(struct __sanitizer_netent *, getnetbyaddr, u32 net, int type) { for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1); - COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, - nn_size * sizeof(char **)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *)); } return n; } @@ -10090,41 +10086,6 @@ INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) { #define INIT_GETRANDOM #endif -#if SANITIZER_INTERCEPT_CRYPT -INTERCEPTOR(char *, crypt, char *key, char *salt) { - void *ctx; - COMMON_INTERCEPTOR_ENTER(ctx, crypt, key, salt); - COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1); - COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1); - char *res = REAL(crypt)(key, salt); - if (res != nullptr) - COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1); - return res; -} -#define INIT_CRYPT COMMON_INTERCEPT_FUNCTION(crypt); -#else -#define INIT_CRYPT -#endif - -#if SANITIZER_INTERCEPT_CRYPT_R -INTERCEPTOR(char *, crypt_r, char *key, char *salt, void *data) { - void *ctx; - COMMON_INTERCEPTOR_ENTER(ctx, crypt_r, key, salt, data); - COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1); - COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1); - char *res = REAL(crypt_r)(key, salt, data); - if (res != nullptr) { - COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, - __sanitizer::struct_crypt_data_sz); - COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1); - } - return res; -} -#define INIT_CRYPT_R COMMON_INTERCEPT_FUNCTION(crypt_r); -#else -#define INIT_CRYPT_R -#endif - #if SANITIZER_INTERCEPT_GETENTROPY INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) { void *ctx; @@ -10702,8 +10663,6 @@ static void InitializeCommonInterceptors() { INIT_GETUSERSHELL; INIT_SL_INIT; INIT_GETRANDOM; - INIT_CRYPT; - INIT_CRYPT_R; INIT_GETENTROPY; INIT_QSORT; INIT_QSORT_R; diff --git a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc index 93b988b..3900bcf 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc +++ b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc @@ -1374,9 +1374,8 @@ PRE_SYSCALL(io_setup)(long nr_reqs, void **ctx) { } POST_SYSCALL(io_setup)(long res, long nr_reqs, void **ctx) { - if (res >= 0) { - if (ctx) - POST_WRITE(ctx, sizeof(*ctx)); + if (res >= 0 && ctx) { + POST_WRITE(ctx, sizeof(*ctx)); // (*ctx) is actually a pointer to a kernel mapped page, and there are // people out there who are crazy enough to peek into that page's 32-byte // header. diff --git a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp index 2720a3c..37b2b57 100644 --- a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -838,13 +838,9 @@ u32 GetNumberOfCPUs() { #elif SANITIZER_SOLARIS return sysconf(_SC_NPROCESSORS_ONLN); #else -#if defined(CPU_COUNT) cpu_set_t CPUs; CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0); return CPU_COUNT(&CPUs); -#else - return 1; -#endif #endif } diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.cpp b/libsanitizer/sanitizer_common/sanitizer_mac.cpp index e1f83e4..24e3d11 100644 --- a/libsanitizer/sanitizer_common/sanitizer_mac.cpp +++ b/libsanitizer/sanitizer_common/sanitizer_mac.cpp @@ -38,7 +38,7 @@ extern char **environ; # endif -# if defined(__has_include) && __has_include(<os/trace.h>) && defined(__BLOCKS__) +# if defined(__has_include) && __has_include(<os/trace.h>) # define SANITIZER_OS_TRACE 1 # include <os/trace.h> # else @@ -71,15 +71,7 @@ extern char ***_NSGetArgv(void); # include <mach/mach_time.h> # include <mach/vm_statistics.h> # include <malloc/malloc.h> -# if defined(__has_builtin) && __has_builtin(__builtin_os_log_format) -# include <os/log.h> -# else - /* Without support for __builtin_os_log_format, fall back to the older - method. */ -# define OS_LOG_DEFAULT 0 -# define os_log_error(A,B,C) \ - asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", (C)); -# endif +# include <os/log.h> # include <pthread.h> # include <pthread/introspection.h> # include <sched.h> diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.h b/libsanitizer/sanitizer_common/sanitizer_mac.h index 1cf2e29..f0a97d0 100644 --- a/libsanitizer/sanitizer_common/sanitizer_mac.h +++ b/libsanitizer/sanitizer_common/sanitizer_mac.h @@ -14,26 +14,6 @@ #include "sanitizer_common.h" #include "sanitizer_platform.h" - -/* TARGET_OS_OSX is not present in SDKs before Darwin16 (macOS 10.12) use - TARGET_OS_MAC (we have no support for iOS in any form for these versions, - so there's no ambiguity). */ -#if !defined(TARGET_OS_OSX) && TARGET_OS_MAC -# define TARGET_OS_OSX 1 -#endif - -/* Other TARGET_OS_xxx are not present on earlier versions, define them to - 0 (we have no support for them; they are not valid targets anyway). */ -#ifndef TARGET_OS_IOS -#define TARGET_OS_IOS 0 -#endif -#ifndef TARGET_OS_TV -#define TARGET_OS_TV 0 -#endif -#ifndef TARGET_OS_WATCH -#define TARGET_OS_WATCH 0 -#endif - #if SANITIZER_APPLE #include "sanitizer_posix.h" diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h index eb39fab..c82ab5c 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h +++ b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h @@ -569,8 +569,6 @@ #define SANITIZER_INTERCEPT_FDEVNAME SI_FREEBSD #define SANITIZER_INTERCEPT_GETUSERSHELL (SI_POSIX && !SI_ANDROID) #define SANITIZER_INTERCEPT_SL_INIT (SI_FREEBSD || SI_NETBSD) -#define SANITIZER_INTERCEPT_CRYPT (SI_POSIX && !SI_ANDROID) -#define SANITIZER_INTERCEPT_CRYPT_R (SI_LINUX && !SI_ANDROID) #define SANITIZER_INTERCEPT_GETRANDOM \ ((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD) diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp index c278c87..bf0f355 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp @@ -26,10 +26,7 @@ // With old kernels (and even new kernels on powerpc) asm/stat.h uses types that // are not defined anywhere in userspace headers. Fake them. This seems to work -// fine with newer headers, too. Beware that with <sys/stat.h>, struct stat -// takes the form of struct stat64 on 32-bit platforms if _FILE_OFFSET_BITS=64. -// Also, for some platforms (e.g. mips) there are additional members in the -// <sys/stat.h> struct stat:s. +// fine with newer headers, too. #include <linux/posix_types.h> # if defined(__x86_64__) || defined(__mips__) || defined(__hexagon__) # include <sys/stat.h> diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp index a04eed7..6d61d27 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp @@ -177,10 +177,6 @@ typedef struct user_fpregs elf_fpregset_t; # include "sanitizer_platform_interceptors.h" # include "sanitizer_platform_limits_posix.h" -#if SANITIZER_INTERCEPT_CRYPT_R -#include <crypt.h> -#endif - namespace __sanitizer { unsigned struct_utsname_sz = sizeof(struct utsname); unsigned struct_stat_sz = sizeof(struct stat); @@ -300,10 +296,6 @@ namespace __sanitizer { unsigned struct_statvfs64_sz = sizeof(struct statvfs64); #endif // SANITIZER_GLIBC -#if SANITIZER_INTERCEPT_CRYPT_R - unsigned struct_crypt_data_sz = sizeof(struct crypt_data); -#endif - #if SANITIZER_LINUX && !SANITIZER_ANDROID unsigned struct_timex_sz = sizeof(struct timex); unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds); diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h index cfca7bd..58244c9 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h @@ -309,7 +309,6 @@ extern unsigned struct_msqid_ds_sz; extern unsigned struct_mq_attr_sz; extern unsigned struct_timex_sz; extern unsigned struct_statvfs_sz; -extern unsigned struct_crypt_data_sz; #endif // SANITIZER_LINUX && !SANITIZER_ANDROID struct __sanitizer_iovec { @@ -578,8 +577,13 @@ struct __sanitizer_sigset_t { #endif struct __sanitizer_siginfo_pad { +#if SANITIZER_X32 + // x32 siginfo_t is aligned to 8 bytes. + u64 pad[128 / sizeof(u64)]; +#else // Require uptr, because siginfo_t is always pointer-size aligned on Linux. uptr pad[128 / sizeof(uptr)]; +#endif }; #if SANITIZER_LINUX diff --git a/libsanitizer/sanitizer_common/sanitizer_procmaps_mac.cpp b/libsanitizer/sanitizer_common/sanitizer_procmaps_mac.cpp index f2f3846..b44e016 100644 --- a/libsanitizer/sanitizer_common/sanitizer_procmaps_mac.cpp +++ b/libsanitizer/sanitizer_common/sanitizer_procmaps_mac.cpp @@ -146,13 +146,8 @@ static bool IsDyldHdr(const mach_header *hdr) { // until we hit a Mach header matching dyld instead. These recurse // calls are expensive, but the first memory map generation occurs // early in the process, when dyld is one of the only images loaded, -// so it will be hit after only a few iterations. These assumptions don't -// hold on macOS 13+ anymore (dyld itself has moved into the shared cache). - -// FIXME: Unfortunately, the upstream revised version to deal with macOS 13+ -// is incompatible with GCC and also uses APIs not available on earlier -// systems which we support; backed out for now. - +// so it will be hit after only a few iterations. These assumptions don't hold +// on macOS 13+ anymore (dyld itself has moved into the shared cache). static mach_header *GetDyldImageHeaderViaVMRegion() { vm_address_t address = 0; @@ -176,17 +171,64 @@ static mach_header *GetDyldImageHeaderViaVMRegion() { } } +extern "C" { +struct dyld_shared_cache_dylib_text_info { + uint64_t version; // current version 2 + // following fields all exist in version 1 + uint64_t loadAddressUnslid; + uint64_t textSegmentSize; + uuid_t dylibUuid; + const char *path; // pointer invalid at end of iterations + // following fields all exist in version 2 + uint64_t textSegmentOffset; // offset from start of cache +}; +typedef struct dyld_shared_cache_dylib_text_info + dyld_shared_cache_dylib_text_info; + +extern bool _dyld_get_shared_cache_uuid(uuid_t uuid); +extern const void *_dyld_get_shared_cache_range(size_t *length); +extern int dyld_shared_cache_iterate_text( + const uuid_t cacheUuid, + void (^callback)(const dyld_shared_cache_dylib_text_info *info)); +} // extern "C" + +static mach_header *GetDyldImageHeaderViaSharedCache() { + uuid_t uuid; + bool hasCache = _dyld_get_shared_cache_uuid(uuid); + if (!hasCache) + return nullptr; + + size_t cacheLength; + __block uptr cacheStart = (uptr)_dyld_get_shared_cache_range(&cacheLength); + CHECK(cacheStart && cacheLength); + + __block mach_header *dyldHdr = nullptr; + int res = dyld_shared_cache_iterate_text( + uuid, ^(const dyld_shared_cache_dylib_text_info *info) { + CHECK_GE(info->version, 2); + mach_header *hdr = + (mach_header *)(cacheStart + info->textSegmentOffset); + if (IsDyldHdr(hdr)) + dyldHdr = hdr; + }); + CHECK_EQ(res, 0); + + return dyldHdr; +} + const mach_header *get_dyld_hdr() { if (!dyld_hdr) { // On macOS 13+, dyld itself has moved into the shared cache. Looking it up // via vm_region_recurse_64() causes spins/hangs/crashes. - // FIXME: find a way to do this compatible with GCC. if (GetMacosAlignedVersion() >= MacosVersion(13, 0)) { + dyld_hdr = GetDyldImageHeaderViaSharedCache(); + if (!dyld_hdr) { VReport(1, - "looking up the dyld image header in the shared cache on " - "macOS 13+ is not yet supported. Falling back to " + "Failed to lookup the dyld image header in the shared cache on " + "macOS 13+ (or no shared cache in use). Falling back to " "lookup via vm_region_recurse_64().\n"); dyld_hdr = GetDyldImageHeaderViaVMRegion(); + } } else { dyld_hdr = GetDyldImageHeaderViaVMRegion(); } diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp index 661495e..d24fae9 100644 --- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp +++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp @@ -87,8 +87,8 @@ static inline uhwptr *GetCanonicFrame(uptr bp, // Nope, this does not look right either. This means the frame after next does // not have a valid frame pointer, but we can still extract the caller PC. // Unfortunately, there is no way to decide between GCC and LLVM frame - // layouts. Assume GCC. - return bp_prev - 1; + // layouts. Assume LLVM. + return bp_prev; #else return (uhwptr*)bp; #endif @@ -111,21 +111,14 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top, IsAligned((uptr)frame, sizeof(*frame)) && size < max_depth) { #ifdef __powerpc__ - // PowerPC ABIs specify that the return address is saved on the - // *caller's* stack frame. Thus we must dereference the back chain - // to find the caller frame before extracting it. + // PowerPC ABIs specify that the return address is saved at offset + // 16 of the *caller's* stack frame. Thus we must dereference the + // back chain to find the caller frame before extracting it. uhwptr *caller_frame = (uhwptr*)frame[0]; if (!IsValidFrame((uptr)caller_frame, stack_top, bottom) || !IsAligned((uptr)caller_frame, sizeof(uhwptr))) break; - // For most ABIs the offset where the return address is saved is two - // register sizes. The exception is the SVR4 ABI, which uses an - // offset of only one register size. -#ifdef _CALL_SYSV - uhwptr pc1 = caller_frame[1]; -#else uhwptr pc1 = caller_frame[2]; -#endif #elif defined(__s390__) uhwptr pc1 = frame[14]; #elif defined(__loongarch__) || defined(__riscv) |