Libsanitizer: merge from trunk with merge.sh.
2019-11-05 Martin Liska <mliska@suse.cz> * all source files: Merge from upstream r375507. From-SVN: r277834
This commit is contained in:
parent
9bae89924a
commit
3ca75cd550
126 changed files with 2696 additions and 2154 deletions
|
@ -1,3 +1,7 @@
|
|||
2019-11-05 Martin Liska <mliska@suse.cz>
|
||||
|
||||
* all source files: Merge from upstream r375507.
|
||||
|
||||
2019-10-22 Tamar Christina <tamar.christina@arm.com>
|
||||
|
||||
PR sanitizer/92154
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
368656
|
||||
375507
|
||||
|
||||
The first line of this file holds the svn revision number of the
|
||||
last merge done from the master library sources.
|
||||
|
|
|
@ -1075,7 +1075,7 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) {
|
|||
} // namespace __lsan
|
||||
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
using namespace __asan;
|
||||
|
||||
// ASan allocator doesn't reserve extra bytes, so normally we would
|
||||
// just return "size". We don't want to expose our redzone sizes, etc here.
|
||||
|
|
|
@ -25,7 +25,7 @@ using namespace __asan;
|
|||
|
||||
static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset,
|
||||
char *name, uptr name_size,
|
||||
uptr ®ion_address, uptr ®ion_size) {
|
||||
uptr *region_address, uptr *region_size) {
|
||||
InternalMmapVector<StackVarDescr> vars;
|
||||
vars.reserve(16);
|
||||
if (!ParseFrameDescription(frame_descr, &vars)) {
|
||||
|
@ -39,8 +39,8 @@ static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset,
|
|||
// the whole name and then terminate with '\0'.
|
||||
internal_strlcpy(name, vars[i].name_pos,
|
||||
Min(name_size, vars[i].name_len + 1));
|
||||
region_address = addr - (offset - vars[i].beg);
|
||||
region_size = vars[i].size;
|
||||
*region_address = addr - (offset - vars[i].beg);
|
||||
*region_size = vars[i].size;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ const char *__asan_locate_address(uptr addr, char *name, uptr name_size,
|
|||
// region_{address,size} are already 0
|
||||
} else {
|
||||
FindInfoForStackVar(addr, stack->frame_descr, stack->offset, name,
|
||||
name_size, region_address, region_size);
|
||||
name_size, ®ion_address, ®ion_size);
|
||||
}
|
||||
} else if (auto global = descr.AsGlobal()) {
|
||||
region_kind = "global";
|
||||
|
|
|
@ -203,7 +203,7 @@ class AddressDescription {
|
|||
AddressDescription() = default;
|
||||
// shouldLockThreadRegistry allows us to skip locking if we're sure we already
|
||||
// have done it.
|
||||
AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
|
||||
explicit AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
|
||||
: AddressDescription(addr, 1, shouldLockThreadRegistry) {}
|
||||
AddressDescription(uptr addr, uptr access_size,
|
||||
bool shouldLockThreadRegistry = true);
|
||||
|
|
|
@ -35,7 +35,8 @@ static void OnStackUnwind(const SignalContext &sig,
|
|||
// corresponding code in the sanitizer_common and we use this callback to
|
||||
// print it.
|
||||
static_cast<const ScarinessScoreBase *>(callback_context)->Print();
|
||||
stack->Unwind(sig.pc, sig.bp, sig.context, fast);
|
||||
stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
|
||||
fast);
|
||||
}
|
||||
|
||||
void ErrorDeadlySignal::Print() {
|
||||
|
@ -244,7 +245,7 @@ void ErrorInvalidPosixMemalignAlignment::Print() {
|
|||
"ERROR: AddressSanitizer: invalid alignment requested in posix_memalign: "
|
||||
"%zd, alignment must be a power of two and a multiple of sizeof(void*) "
|
||||
"== %zd (thread %s)\n",
|
||||
alignment, sizeof(void*), AsanThreadIdAndName(tid).c_str()); // NOLINT
|
||||
alignment, sizeof(void *), AsanThreadIdAndName(tid).c_str());
|
||||
Printf("%s", d.Default());
|
||||
stack->Print();
|
||||
PrintHintAllocatorCannotReturnNull();
|
||||
|
|
|
@ -48,7 +48,8 @@ struct ErrorDeadlySignal : ErrorBase {
|
|||
scariness.Scare(10, "stack-overflow");
|
||||
} else if (!signal.is_memory_access) {
|
||||
scariness.Scare(10, "signal");
|
||||
} else if (signal.addr < GetPageSizeCached()) {
|
||||
} else if (signal.is_true_faulting_addr &&
|
||||
signal.addr < GetPageSizeCached()) {
|
||||
scariness.Scare(10, "null-deref");
|
||||
} else if (signal.addr == signal.pc) {
|
||||
scariness.Scare(60, "wild-jump");
|
||||
|
|
|
@ -139,10 +139,10 @@ ASAN_FLAG(
|
|||
"If >= 2, detect operations like <, <=, >, >= and - on invalid pointer "
|
||||
"pairs (e.g. when pointers belong to different objects); "
|
||||
"If == 1, detect invalid operations only when both pointers are non-null.")
|
||||
ASAN_FLAG(
|
||||
bool, detect_container_overflow, true,
|
||||
"If true, honor the container overflow annotations. See "
|
||||
"https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow")
|
||||
ASAN_FLAG(bool, detect_container_overflow, true,
|
||||
"If true, honor the container overflow annotations. See "
|
||||
"https://github.com/google/sanitizers/wiki/"
|
||||
"AddressSanitizerContainerOverflow")
|
||||
ASAN_FLAG(int, detect_odr_violation, 2,
|
||||
"If >=2, detect violation of One-Definition-Rule (ODR); "
|
||||
"If ==1, detect ODR-violation only if the two variables "
|
||||
|
@ -158,5 +158,6 @@ ASAN_FLAG(bool, allocator_frees_and_returns_null_on_realloc_zero, true,
|
|||
ASAN_FLAG(bool, verify_asan_link_order, true,
|
||||
"Check position of ASan runtime in library list (needs to be disabled"
|
||||
" when other library has to be preloaded system-wide)")
|
||||
ASAN_FLAG(bool, windows_hook_rtl_allocators, false,
|
||||
"(Windows only) enable hooking of Rtl(Allocate|Free|Size|ReAllocate)Heap.")
|
||||
ASAN_FLAG(
|
||||
bool, windows_hook_rtl_allocators, false,
|
||||
"(Windows only) enable hooking of Rtl(Allocate|Free|Size|ReAllocate)Heap.")
|
||||
|
|
|
@ -154,6 +154,23 @@ static void CheckODRViolationViaIndicator(const Global *g) {
|
|||
}
|
||||
}
|
||||
|
||||
// Check ODR violation for given global G by checking if it's already poisoned.
|
||||
// We use this method in case compiler doesn't use private aliases for global
|
||||
// variables.
|
||||
static void CheckODRViolationViaPoisoning(const Global *g) {
|
||||
if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
|
||||
// This check may not be enough: if the first global is much larger
|
||||
// the entire redzone of the second global may be within the first global.
|
||||
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
|
||||
if (g->beg == l->g->beg &&
|
||||
(flags()->detect_odr_violation >= 2 || g->size != l->g->size) &&
|
||||
!IsODRViolationSuppressed(g->name))
|
||||
ReportODRViolation(g, FindRegistrationSite(g),
|
||||
l->g, FindRegistrationSite(l->g));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clang provides two different ways for global variables protection:
|
||||
// it can poison the global itself or its private alias. In former
|
||||
// case we may poison same symbol multiple times, that can help us to
|
||||
|
@ -199,6 +216,8 @@ static void RegisterGlobal(const Global *g) {
|
|||
// where two globals with the same name are defined in different modules.
|
||||
if (UseODRIndicator(g))
|
||||
CheckODRViolationViaIndicator(g);
|
||||
else
|
||||
CheckODRViolationViaPoisoning(g);
|
||||
}
|
||||
if (CanPoisonMemory())
|
||||
PoisonRedZones(*g);
|
||||
|
@ -208,8 +227,7 @@ static void RegisterGlobal(const Global *g) {
|
|||
list_of_all_globals = l;
|
||||
if (g->has_dynamic_init) {
|
||||
if (!dynamic_init_globals) {
|
||||
dynamic_init_globals =
|
||||
new (allocator_for_globals) VectorOfGlobals; // NOLINT
|
||||
dynamic_init_globals = new (allocator_for_globals) VectorOfGlobals;
|
||||
dynamic_init_globals->reserve(kDynamicInitGlobalsInitialCapacity);
|
||||
}
|
||||
DynInitGlobal dyn_global = { *g, false };
|
||||
|
@ -296,8 +314,7 @@ void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g) {
|
|||
} // namespace __asan
|
||||
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
|
||||
using namespace __asan;
|
||||
|
||||
// Apply __asan_register_globals to all globals found in the same loaded
|
||||
// executable or shared library as `flag'. The flag tracks whether globals have
|
||||
|
@ -345,7 +362,7 @@ void __asan_register_globals(__asan_global *globals, uptr n) {
|
|||
BlockingMutexLock lock(&mu_for_globals);
|
||||
if (!global_registration_site_vector) {
|
||||
global_registration_site_vector =
|
||||
new (allocator_for_globals) GlobalRegistrationSiteVector; // NOLINT
|
||||
new (allocator_for_globals) GlobalRegistrationSiteVector;
|
||||
global_registration_site_vector->reserve(128);
|
||||
}
|
||||
GlobalRegistrationSite site = {stack_id, &globals[0], &globals[n - 1]};
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
|
||||
namespace __asan {
|
||||
|
||||
#pragma section(".ASAN$GA", read, write) // NOLINT
|
||||
#pragma section(".ASAN$GZ", read, write) // NOLINT
|
||||
#pragma section(".ASAN$GA", read, write)
|
||||
#pragma section(".ASAN$GZ", read, write)
|
||||
extern "C" __declspec(allocate(".ASAN$GA"))
|
||||
ALIGNED(sizeof(__asan_global)) __asan_global __asan_globals_start = {};
|
||||
extern "C" __declspec(allocate(".ASAN$GZ"))
|
||||
|
@ -49,8 +49,8 @@ static void unregister_dso_globals() {
|
|||
}
|
||||
|
||||
// Register globals
|
||||
#pragma section(".CRT$XCU", long, read) // NOLINT
|
||||
#pragma section(".CRT$XTX", long, read) // NOLINT
|
||||
#pragma section(".CRT$XCU", long, read)
|
||||
#pragma section(".CRT$XTX", long, read)
|
||||
extern "C" __declspec(allocate(".CRT$XCU"))
|
||||
void (*const __asan_dso_reg_hook)() = ®ister_dso_globals;
|
||||
extern "C" __declspec(allocate(".CRT$XTX"))
|
||||
|
|
|
@ -79,7 +79,7 @@ int OnExit() {
|
|||
} // namespace __asan
|
||||
|
||||
// ---------------------- Wrappers ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
using namespace __asan;
|
||||
|
||||
DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
|
||||
DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
|
||||
|
@ -164,6 +164,11 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
|
|||
ASAN_MEMSET_IMPL(ctx, block, c, size); \
|
||||
} while (false)
|
||||
|
||||
#if CAN_SANITIZE_LEAKS
|
||||
#define COMMON_INTERCEPTOR_STRERROR() \
|
||||
__lsan::ScopedInterceptorDisabler disabler
|
||||
#endif
|
||||
|
||||
#include "sanitizer_common/sanitizer_common_interceptors.inc"
|
||||
#include "sanitizer_common/sanitizer_signal_interceptors.inc"
|
||||
|
||||
|
@ -373,26 +378,26 @@ DEFINE_REAL(char*, index, const char *string, int c)
|
|||
|
||||
// For both strcat() and strncat() we need to check the validity of |to|
|
||||
// argument irrespective of the |from| length.
|
||||
INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
|
||||
void *ctx;
|
||||
ASAN_INTERCEPTOR_ENTER(ctx, strcat); // NOLINT
|
||||
ENSURE_ASAN_INITED();
|
||||
if (flags()->replace_str) {
|
||||
uptr from_length = REAL(strlen)(from);
|
||||
ASAN_READ_RANGE(ctx, from, from_length + 1);
|
||||
uptr to_length = REAL(strlen)(to);
|
||||
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
|
||||
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
|
||||
// If the copying actually happens, the |from| string should not overlap
|
||||
// with the resulting string starting at |to|, which has a length of
|
||||
// to_length + from_length + 1.
|
||||
if (from_length > 0) {
|
||||
CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
|
||||
from, from_length + 1);
|
||||
INTERCEPTOR(char *, strcat, char *to, const char *from) {
|
||||
void *ctx;
|
||||
ASAN_INTERCEPTOR_ENTER(ctx, strcat);
|
||||
ENSURE_ASAN_INITED();
|
||||
if (flags()->replace_str) {
|
||||
uptr from_length = REAL(strlen)(from);
|
||||
ASAN_READ_RANGE(ctx, from, from_length + 1);
|
||||
uptr to_length = REAL(strlen)(to);
|
||||
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
|
||||
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
|
||||
// If the copying actually happens, the |from| string should not overlap
|
||||
// with the resulting string starting at |to|, which has a length of
|
||||
// to_length + from_length + 1.
|
||||
if (from_length > 0) {
|
||||
CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from,
|
||||
from_length + 1);
|
||||
}
|
||||
}
|
||||
return REAL(strcat)(to, from);
|
||||
}
|
||||
return REAL(strcat)(to, from); // NOLINT
|
||||
}
|
||||
|
||||
INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
|
||||
void *ctx;
|
||||
|
@ -413,16 +418,17 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
|
|||
return REAL(strncat)(to, from, size);
|
||||
}
|
||||
|
||||
INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
|
||||
INTERCEPTOR(char *, strcpy, char *to, const char *from) {
|
||||
void *ctx;
|
||||
ASAN_INTERCEPTOR_ENTER(ctx, strcpy); // NOLINT
|
||||
ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
|
||||
#if SANITIZER_MAC
|
||||
if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT
|
||||
if (UNLIKELY(!asan_inited))
|
||||
return REAL(strcpy)(to, from);
|
||||
#endif
|
||||
// strcpy is called from malloc_default_purgeable_zone()
|
||||
// in __asan::ReplaceSystemAlloc() on Mac.
|
||||
if (asan_init_is_running) {
|
||||
return REAL(strcpy)(to, from); // NOLINT
|
||||
return REAL(strcpy)(to, from);
|
||||
}
|
||||
ENSURE_ASAN_INITED();
|
||||
if (flags()->replace_str) {
|
||||
|
@ -431,7 +437,7 @@ INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
|
|||
ASAN_READ_RANGE(ctx, from, from_size);
|
||||
ASAN_WRITE_RANGE(ctx, to, from_size);
|
||||
}
|
||||
return REAL(strcpy)(to, from); // NOLINT
|
||||
return REAL(strcpy)(to, from);
|
||||
}
|
||||
|
||||
INTERCEPTOR(char*, strdup, const char *s) {
|
||||
|
@ -479,8 +485,7 @@ INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
|
|||
return REAL(strncpy)(to, from, size);
|
||||
}
|
||||
|
||||
INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
|
||||
char **endptr, int base) {
|
||||
INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) {
|
||||
void *ctx;
|
||||
ASAN_INTERCEPTOR_ENTER(ctx, strtol);
|
||||
ENSURE_ASAN_INITED();
|
||||
|
@ -488,7 +493,7 @@ INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
|
|||
return REAL(strtol)(nptr, endptr, base);
|
||||
}
|
||||
char *real_endptr;
|
||||
long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
|
||||
long result = REAL(strtol)(nptr, &real_endptr, base);
|
||||
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
|
||||
return result;
|
||||
}
|
||||
|
@ -514,7 +519,7 @@ INTERCEPTOR(int, atoi, const char *nptr) {
|
|||
return result;
|
||||
}
|
||||
|
||||
INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
|
||||
INTERCEPTOR(long, atol, const char *nptr) {
|
||||
void *ctx;
|
||||
ASAN_INTERCEPTOR_ENTER(ctx, atol);
|
||||
#if SANITIZER_MAC
|
||||
|
@ -525,15 +530,14 @@ INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
|
|||
return REAL(atol)(nptr);
|
||||
}
|
||||
char *real_endptr;
|
||||
long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
|
||||
long result = REAL(strtol)(nptr, &real_endptr, 10);
|
||||
FixRealStrtolEndptr(nptr, &real_endptr);
|
||||
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
|
||||
INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
|
||||
char **endptr, int base) {
|
||||
INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) {
|
||||
void *ctx;
|
||||
ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
|
||||
ENSURE_ASAN_INITED();
|
||||
|
@ -541,12 +545,12 @@ INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
|
|||
return REAL(strtoll)(nptr, endptr, base);
|
||||
}
|
||||
char *real_endptr;
|
||||
long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
|
||||
long long result = REAL(strtoll)(nptr, &real_endptr, base);
|
||||
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
|
||||
INTERCEPTOR(long long, atoll, const char *nptr) {
|
||||
void *ctx;
|
||||
ASAN_INTERCEPTOR_ENTER(ctx, atoll);
|
||||
ENSURE_ASAN_INITED();
|
||||
|
@ -554,31 +558,66 @@ INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
|
|||
return REAL(atoll)(nptr);
|
||||
}
|
||||
char *real_endptr;
|
||||
long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT
|
||||
long long result = REAL(strtoll)(nptr, &real_endptr, 10);
|
||||
FixRealStrtolEndptr(nptr, &real_endptr);
|
||||
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
|
||||
return result;
|
||||
}
|
||||
#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
|
||||
|
||||
#if ASAN_INTERCEPT___CXA_ATEXIT
|
||||
#if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
|
||||
static void AtCxaAtexit(void *unused) {
|
||||
(void)unused;
|
||||
StopInitOrderChecking();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASAN_INTERCEPT___CXA_ATEXIT
|
||||
INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
|
||||
void *dso_handle) {
|
||||
#if SANITIZER_MAC
|
||||
if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
|
||||
#endif
|
||||
ENSURE_ASAN_INITED();
|
||||
#if CAN_SANITIZE_LEAKS
|
||||
__lsan::ScopedInterceptorDisabler disabler;
|
||||
#endif
|
||||
int res = REAL(__cxa_atexit)(func, arg, dso_handle);
|
||||
REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
|
||||
return res;
|
||||
}
|
||||
#endif // ASAN_INTERCEPT___CXA_ATEXIT
|
||||
|
||||
#if ASAN_INTERCEPT_ATEXIT
|
||||
INTERCEPTOR(int, atexit, void (*func)()) {
|
||||
ENSURE_ASAN_INITED();
|
||||
#if CAN_SANITIZE_LEAKS
|
||||
__lsan::ScopedInterceptorDisabler disabler;
|
||||
#endif
|
||||
// Avoid calling real atexit as it is unrechable on at least on Linux.
|
||||
int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr);
|
||||
REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASAN_INTERCEPT_PTHREAD_ATFORK
|
||||
extern "C" {
|
||||
extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
|
||||
void (*child)());
|
||||
};
|
||||
|
||||
INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
|
||||
void (*child)()) {
|
||||
#if CAN_SANITIZE_LEAKS
|
||||
__lsan::ScopedInterceptorDisabler disabler;
|
||||
#endif
|
||||
// REAL(pthread_atfork) cannot be called due to symbol indirections at least
|
||||
// on NetBSD
|
||||
return _pthread_atfork(prepare, parent, child);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASAN_INTERCEPT_VFORK
|
||||
DEFINE_REAL(int, vfork)
|
||||
DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
|
||||
|
@ -594,8 +633,8 @@ void InitializeAsanInterceptors() {
|
|||
InitializeSignalInterceptors();
|
||||
|
||||
// Intercept str* functions.
|
||||
ASAN_INTERCEPT_FUNC(strcat); // NOLINT
|
||||
ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
|
||||
ASAN_INTERCEPT_FUNC(strcat);
|
||||
ASAN_INTERCEPT_FUNC(strcpy);
|
||||
ASAN_INTERCEPT_FUNC(strncat);
|
||||
ASAN_INTERCEPT_FUNC(strncpy);
|
||||
ASAN_INTERCEPT_FUNC(strdup);
|
||||
|
@ -661,6 +700,14 @@ void InitializeAsanInterceptors() {
|
|||
ASAN_INTERCEPT_FUNC(__cxa_atexit);
|
||||
#endif
|
||||
|
||||
#if ASAN_INTERCEPT_ATEXIT
|
||||
ASAN_INTERCEPT_FUNC(atexit);
|
||||
#endif
|
||||
|
||||
#if ASAN_INTERCEPT_PTHREAD_ATFORK
|
||||
ASAN_INTERCEPT_FUNC(pthread_atfork);
|
||||
#endif
|
||||
|
||||
#if ASAN_INTERCEPT_VFORK
|
||||
ASAN_INTERCEPT_FUNC(vfork);
|
||||
#endif
|
||||
|
|
|
@ -80,12 +80,7 @@ void InitializePlatformInterceptors();
|
|||
#if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS && !SANITIZER_SOLARIS && \
|
||||
!SANITIZER_NETBSD
|
||||
# define ASAN_INTERCEPT___CXA_THROW 1
|
||||
# if ! defined(ASAN_HAS_CXA_RETHROW_PRIMARY_EXCEPTION) \
|
||||
|| ASAN_HAS_CXA_RETHROW_PRIMARY_EXCEPTION
|
||||
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
|
||||
# else
|
||||
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 0
|
||||
# endif
|
||||
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
|
||||
# if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && defined(__arm__))
|
||||
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1
|
||||
# else
|
||||
|
@ -104,6 +99,12 @@ void InitializePlatformInterceptors();
|
|||
# define ASAN_INTERCEPT___CXA_ATEXIT 0
|
||||
#endif
|
||||
|
||||
#if SANITIZER_NETBSD
|
||||
# define ASAN_INTERCEPT_ATEXIT 1
|
||||
#else
|
||||
# define ASAN_INTERCEPT_ATEXIT 0
|
||||
#endif
|
||||
|
||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
# define ASAN_INTERCEPT___STRDUP 1
|
||||
#else
|
||||
|
@ -117,6 +118,12 @@ void InitializePlatformInterceptors();
|
|||
# define ASAN_INTERCEPT_VFORK 0
|
||||
#endif
|
||||
|
||||
#if SANITIZER_NETBSD
|
||||
# define ASAN_INTERCEPT_PTHREAD_ATFORK 1
|
||||
#else
|
||||
# define ASAN_INTERCEPT_PTHREAD_ATFORK 0
|
||||
#endif
|
||||
|
||||
DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size)
|
||||
DECLARE_REAL(char*, strchr, const char *str, int c)
|
||||
DECLARE_REAL(SIZE_T, strlen, const char *s)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "asan_stack.h"
|
||||
#include "asan_suppressions.h"
|
||||
|
||||
using namespace __asan; // NOLINT
|
||||
using namespace __asan;
|
||||
|
||||
void *__asan_memcpy(void *to, const void *from, uptr size) {
|
||||
ASAN_MEMCPY_IMPL(nullptr, to, from, size);
|
||||
|
|
|
@ -205,7 +205,7 @@ void asan_dispatch_call_block_and_release(void *block) {
|
|||
|
||||
} // namespace __asan
|
||||
|
||||
using namespace __asan; // NOLINT
|
||||
using namespace __asan;
|
||||
|
||||
// Wrap |ctxt| and |func| into an asan_block_context_t.
|
||||
// The caller retains control of the allocated context.
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "asan_stack.h"
|
||||
|
||||
// ---------------------- Replacement functions ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
using namespace __asan;
|
||||
|
||||
static uptr allocated_for_dlsym;
|
||||
static uptr last_dlsym_alloc_size_in_words;
|
||||
|
|
|
@ -54,7 +54,7 @@ size_t WINAPI HeapSize(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem);
|
|||
BOOL WINAPI HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem);
|
||||
}
|
||||
|
||||
using namespace __asan; // NOLINT
|
||||
using namespace __asan;
|
||||
|
||||
// MT: Simply defining functions with the same signature in *.obj
|
||||
// files overrides the standard functions in the CRT.
|
||||
|
@ -528,10 +528,11 @@ void ReplaceSystemMalloc() {
|
|||
(uptr)WRAP(RtlAllocateHeap),
|
||||
(uptr *)&REAL(RtlAllocateHeap));
|
||||
} else {
|
||||
#define INTERCEPT_UCRT_FUNCTION(func) \
|
||||
if (!INTERCEPT_FUNCTION_DLLIMPORT("ucrtbase.dll", \
|
||||
"api-ms-win-core-heap-l1-1-0.dll", func)) \
|
||||
VPrintf(2, "Failed to intercept ucrtbase.dll import %s\n", #func);
|
||||
#define INTERCEPT_UCRT_FUNCTION(func) \
|
||||
if (!INTERCEPT_FUNCTION_DLLIMPORT( \
|
||||
"ucrtbase.dll", "api-ms-win-core-heap-l1-1-0.dll", func)) { \
|
||||
VPrintf(2, "Failed to intercept ucrtbase.dll import %s\n", #func); \
|
||||
}
|
||||
INTERCEPT_UCRT_FUNCTION(HeapAlloc);
|
||||
INTERCEPT_UCRT_FUNCTION(HeapFree);
|
||||
INTERCEPT_UCRT_FUNCTION(HeapReAlloc);
|
||||
|
|
|
@ -163,7 +163,7 @@ static const u64 kDefaultShort64bitShadowOffset =
|
|||
static const u64 kAArch64_ShadowOffset64 = 1ULL << 36;
|
||||
static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000;
|
||||
static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37;
|
||||
static const u64 kPPC64_ShadowOffset64 = 1ULL << 41;
|
||||
static const u64 kPPC64_ShadowOffset64 = 1ULL << 44;
|
||||
static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52;
|
||||
static const u64 kSPARC64_ShadowOffset64 = 1ULL << 43; // 0x80000000000
|
||||
static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000
|
||||
|
|
|
@ -48,7 +48,7 @@ COMMENT_EXPORT("??_V@YAXPAX@Z") // operator delete[]
|
|||
#define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE
|
||||
#endif
|
||||
|
||||
using namespace __asan; // NOLINT
|
||||
using namespace __asan;
|
||||
|
||||
// FreeBSD prior v9.2 have wrong definition of 'size_t'.
|
||||
// http://svnweb.freebsd.org/base?view=revision&revision=232261
|
||||
|
|
|
@ -92,7 +92,7 @@ void AsanPoisonOrUnpoisonIntraObjectRedzone(uptr ptr, uptr size, bool poison) {
|
|||
} // namespace __asan
|
||||
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
using namespace __asan;
|
||||
|
||||
// Current implementation of __asan_(un)poison_memory_region doesn't check
|
||||
// that user program (un)poisons the memory it owns. It poisons memory
|
||||
|
|
|
@ -410,8 +410,12 @@ static bool IsInvalidPointerPair(uptr a1, uptr a2) {
|
|||
|
||||
static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
|
||||
switch (flags()->detect_invalid_pointer_pairs) {
|
||||
case 0 : return;
|
||||
case 1 : if (p1 == nullptr || p2 == nullptr) return; break;
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
if (p1 == nullptr || p2 == nullptr)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
uptr a1 = reinterpret_cast<uptr>(p1);
|
||||
|
@ -472,7 +476,7 @@ void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
|
|||
} // namespace __asan
|
||||
|
||||
// --------------------------- Interface --------------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
using namespace __asan;
|
||||
|
||||
void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
|
||||
uptr access_size, u32 exp) {
|
||||
|
|
|
@ -181,11 +181,11 @@ static void ThreadStartHook(void *hook, uptr os_id) {
|
|||
asanThreadRegistry().GetThreadLocked(thread->tid())->status;
|
||||
DCHECK(status == ThreadStatusCreated || status == ThreadStatusRunning);
|
||||
// Determine whether we are starting or restarting the thread.
|
||||
if (status == ThreadStatusCreated)
|
||||
if (status == ThreadStatusCreated) {
|
||||
// In lieu of AsanThread::ThreadStart.
|
||||
asanThreadRegistry().StartThread(thread->tid(), os_id, ThreadType::Regular,
|
||||
nullptr);
|
||||
else {
|
||||
} else {
|
||||
// In a thread restart, a thread may resume execution at an
|
||||
// arbitrary function entry point, with its stack and TLS state
|
||||
// reset. We unpoison the stack in that case.
|
||||
|
|
|
@ -402,7 +402,6 @@ static void AsanInitInternal() {
|
|||
asan_init_is_running = true;
|
||||
|
||||
CacheBinaryName();
|
||||
CheckASLR();
|
||||
|
||||
// Initialize flags. This must be done early, because most of the
|
||||
// initialization steps look at flags().
|
||||
|
@ -450,6 +449,7 @@ static void AsanInitInternal() {
|
|||
SetLowLevelAllocateCallback(OnLowLevelAllocate);
|
||||
|
||||
InitializeAsanInterceptors();
|
||||
CheckASLR();
|
||||
|
||||
// Enable system log ("adb logcat") on Android.
|
||||
// Doing this before interceptors are initialized crashes in:
|
||||
|
@ -542,7 +542,7 @@ void AsanInitFromRtl() {
|
|||
// (and thus normal initializers from .preinit_array or modules haven't run).
|
||||
|
||||
class AsanInitializer {
|
||||
public: // NOLINT
|
||||
public:
|
||||
AsanInitializer() {
|
||||
AsanInitFromRtl();
|
||||
}
|
||||
|
@ -554,7 +554,7 @@ static AsanInitializer asan_initializer;
|
|||
} // namespace __asan
|
||||
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
using namespace __asan;
|
||||
|
||||
void NOINLINE __asan_handle_no_return() {
|
||||
if (asan_init_is_running)
|
||||
|
|
|
@ -43,7 +43,7 @@ struct ScarinessScoreBase {
|
|||
internal_strlcat(descr, "-", sizeof(descr));
|
||||
internal_strlcat(descr, reason, sizeof(descr));
|
||||
score += add_to_score;
|
||||
};
|
||||
}
|
||||
int GetScore() const { return score; }
|
||||
const char *GetDescription() const { return descr; }
|
||||
void Print() const {
|
||||
|
|
|
@ -30,14 +30,13 @@ void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) {
|
|||
CHECK_EQ(((end + 1) % GetMmapGranularity()), 0);
|
||||
uptr size = end - beg + 1;
|
||||
DecreaseTotalMmap(size); // Don't count the shadow against mmap_limit_mb.
|
||||
if (!MmapFixedNoReserve(beg, size, name)) {
|
||||
if (!MmapFixedSuperNoReserve(beg, size, name)) {
|
||||
Report(
|
||||
"ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
|
||||
"Perhaps you're using ulimit -v\n",
|
||||
size);
|
||||
Abort();
|
||||
}
|
||||
SetShadowRegionHugePageMode(beg, size);
|
||||
if (common_flags()->use_madv_dontdump) DontDumpShadowMemory(beg, size);
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ static void PrintAccumulatedStats() {
|
|||
} // namespace __asan
|
||||
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
using namespace __asan;
|
||||
|
||||
uptr __sanitizer_get_current_allocated_bytes() {
|
||||
AsanStats stats;
|
||||
|
|
|
@ -36,7 +36,7 @@ SANITIZER_INTERFACE_WEAK_DEF(const char *, __asan_default_suppressions, void) {
|
|||
|
||||
void InitializeSuppressions() {
|
||||
CHECK_EQ(nullptr, suppression_ctx);
|
||||
suppression_ctx = new (suppression_placeholder) // NOLINT
|
||||
suppression_ctx = new (suppression_placeholder)
|
||||
SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
|
||||
suppression_ctx->ParseFromFile(flags()->suppressions);
|
||||
if (&__asan_default_suppressions)
|
||||
|
|
|
@ -367,8 +367,9 @@ uptr AsanThread::GetStackVariableShadowStart(uptr addr) {
|
|||
} else if (has_fake_stack()) {
|
||||
bottom = fake_stack()->AddrIsInFakeStack(addr);
|
||||
CHECK(bottom);
|
||||
} else
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uptr aligned_addr = RoundDownTo(addr, SANITIZER_WORDSIZE / 8); // align addr.
|
||||
u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
|
||||
|
@ -505,7 +506,7 @@ void EnsureMainThreadIDIsCorrect() {
|
|||
} // namespace __lsan
|
||||
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
using namespace __asan;
|
||||
|
||||
extern "C" {
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include "sanitizer_common/sanitizer_win.h"
|
||||
#include "sanitizer_common/sanitizer_win_defs.h"
|
||||
|
||||
using namespace __asan; // NOLINT
|
||||
using namespace __asan;
|
||||
|
||||
extern "C" {
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
|
@ -106,7 +106,7 @@ INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
|
|||
|
||||
INTERCEPTOR_WINAPI(EXCEPTION_DISPOSITION, __C_specific_handler,
|
||||
_EXCEPTION_RECORD *a, void *b, _CONTEXT *c,
|
||||
_DISPATCHER_CONTEXT *d) { // NOLINT
|
||||
_DISPATCHER_CONTEXT *d) {
|
||||
CHECK(REAL(__C_specific_handler));
|
||||
__asan_handle_no_return();
|
||||
return REAL(__C_specific_handler)(a, b, c, d);
|
||||
|
@ -362,7 +362,7 @@ bool HandleDlopenInit() {
|
|||
// beginning of C++ initialization. We set our priority to XCAB to run
|
||||
// immediately after the CRT runs. This way, our exception filter is called
|
||||
// first and we can delegate to their filter if appropriate.
|
||||
#pragma section(".CRT$XCAB", long, read) // NOLINT
|
||||
#pragma section(".CRT$XCAB", long, read)
|
||||
__declspec(allocate(".CRT$XCAB")) int (*__intercept_seh)() =
|
||||
__asan_set_seh_filter;
|
||||
|
||||
|
@ -375,7 +375,7 @@ static void NTAPI asan_thread_init(void *module, DWORD reason, void *reserved) {
|
|||
__asan_init();
|
||||
}
|
||||
|
||||
#pragma section(".CRT$XLAB", long, read) // NOLINT
|
||||
#pragma section(".CRT$XLAB", long, read)
|
||||
__declspec(allocate(".CRT$XLAB")) void(NTAPI *__asan_tls_init)(
|
||||
void *, unsigned long, void *) = asan_thread_init;
|
||||
#endif
|
||||
|
@ -389,7 +389,7 @@ static void NTAPI asan_thread_exit(void *module, DWORD reason, void *reserved) {
|
|||
}
|
||||
}
|
||||
|
||||
#pragma section(".CRT$XLY", long, read) // NOLINT
|
||||
#pragma section(".CRT$XLY", long, read)
|
||||
__declspec(allocate(".CRT$XLY")) void(NTAPI *__asan_tls_exit)(
|
||||
void *, unsigned long, void *) = asan_thread_exit;
|
||||
|
||||
|
|
|
@ -67,10 +67,10 @@ INTERCEPT_LIBRARY_FUNCTION(memcmp);
|
|||
INTERCEPT_LIBRARY_FUNCTION(memcpy);
|
||||
INTERCEPT_LIBRARY_FUNCTION(memmove);
|
||||
INTERCEPT_LIBRARY_FUNCTION(memset);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strcat); // NOLINT
|
||||
INTERCEPT_LIBRARY_FUNCTION(strcat);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strchr);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strcmp);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strcpy); // NOLINT
|
||||
INTERCEPT_LIBRARY_FUNCTION(strcpy);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strcspn);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strdup);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strlen);
|
||||
|
@ -135,7 +135,7 @@ static int asan_dll_thunk_init() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#pragma section(".CRT$XIB", long, read) // NOLINT
|
||||
#pragma section(".CRT$XIB", long, read)
|
||||
__declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = asan_dll_thunk_init;
|
||||
|
||||
static void WINAPI asan_thread_init(void *mod, unsigned long reason,
|
||||
|
@ -143,7 +143,7 @@ static void WINAPI asan_thread_init(void *mod, unsigned long reason,
|
|||
if (reason == /*DLL_PROCESS_ATTACH=*/1) asan_dll_thunk_init();
|
||||
}
|
||||
|
||||
#pragma section(".CRT$XLAB", long, read) // NOLINT
|
||||
#pragma section(".CRT$XLAB", long, read)
|
||||
__declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *,
|
||||
unsigned long, void *) = asan_thread_init;
|
||||
|
||||
|
|
|
@ -32,12 +32,12 @@
|
|||
#include "asan_interface.inc"
|
||||
|
||||
// First, declare CRT sections we'll be using in this file
|
||||
#pragma section(".CRT$XIB", long, read) // NOLINT
|
||||
#pragma section(".CRT$XID", long, read) // NOLINT
|
||||
#pragma section(".CRT$XCAB", long, read) // NOLINT
|
||||
#pragma section(".CRT$XTW", long, read) // NOLINT
|
||||
#pragma section(".CRT$XTY", long, read) // NOLINT
|
||||
#pragma section(".CRT$XLAB", long, read) // NOLINT
|
||||
#pragma section(".CRT$XIB", long, read)
|
||||
#pragma section(".CRT$XID", long, read)
|
||||
#pragma section(".CRT$XCAB", long, read)
|
||||
#pragma section(".CRT$XTW", long, read)
|
||||
#pragma section(".CRT$XTY", long, read)
|
||||
#pragma section(".CRT$XLAB", long, read)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Define a copy of __asan_option_detect_stack_use_after_return that should be
|
||||
|
|
|
@ -112,7 +112,7 @@ void dfsan_weak_hook_strncmp(void *caller_pc, const char *s1, const char *s2,
|
|||
} // extern "C"
|
||||
|
||||
template <typename T>
|
||||
void dfsan_set_label(dfsan_label label, T &data) { // NOLINT
|
||||
void dfsan_set_label(dfsan_label label, T &data) { // NOLINT
|
||||
dfsan_set_label(label, (void *)&data, sizeof(T));
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef char __tsan_atomic8;
|
||||
typedef short __tsan_atomic16; // NOLINT
|
||||
typedef int __tsan_atomic32;
|
||||
typedef long __tsan_atomic64; // NOLINT
|
||||
typedef char __tsan_atomic8;
|
||||
typedef short __tsan_atomic16;
|
||||
typedef int __tsan_atomic32;
|
||||
typedef long __tsan_atomic64;
|
||||
#if defined(__SIZEOF_INT128__) \
|
||||
|| (__clang_major__ * 100 + __clang_minor__ >= 302)
|
||||
__extension__ typedef __int128 __tsan_atomic128;
|
||||
|
|
32
libsanitizer/include/sanitizer/ubsan_interface.h
Normal file
32
libsanitizer/include/sanitizer/ubsan_interface.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//===-- sanitizer/ubsan_interface.h -----------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is a part of UBSanitizer (UBSan).
|
||||
//
|
||||
// Public interface header.
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef SANITIZER_UBSAN_INTERFACE_H
|
||||
#define SANITIZER_UBSAN_INTERFACE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/// User-provided default option settings.
|
||||
///
|
||||
/// You can provide your own implementation of this function to return a string
|
||||
/// containing UBSan runtime options (for example,
|
||||
/// <c>verbosity=1:halt_on_error=0</c>).
|
||||
///
|
||||
/// \returns Default options string.
|
||||
const char* __ubsan_default_options(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // SANITIZER_UBSAN_INTERFACE_H
|
|
@ -272,9 +272,9 @@ const interpose_substitution substitution_##func_name[] \
|
|||
// INTERCEPT_FUNCTION macro, only its name.
|
||||
namespace __interception {
|
||||
#if defined(_WIN64)
|
||||
typedef unsigned long long uptr; // NOLINT
|
||||
typedef unsigned long long uptr;
|
||||
#else
|
||||
typedef unsigned long uptr; // NOLINT
|
||||
typedef unsigned long uptr;
|
||||
#endif // _WIN64
|
||||
} // namespace __interception
|
||||
|
||||
|
|
|
@ -883,8 +883,8 @@ uptr InternalGetProcAddress(void *module, const char *func_name) {
|
|||
// Check that the module header is full and present.
|
||||
RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0);
|
||||
RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew);
|
||||
if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
|
||||
headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0"
|
||||
if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
|
||||
headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0"
|
||||
headers->FileHeader.SizeOfOptionalHeader <
|
||||
sizeof(IMAGE_OPTIONAL_HEADER)) {
|
||||
return 0;
|
||||
|
@ -963,8 +963,8 @@ bool OverrideImportedFunction(const char *module_to_patch,
|
|||
// Check that the module header is full and present.
|
||||
RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0);
|
||||
RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew);
|
||||
if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
|
||||
headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0"
|
||||
if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
|
||||
headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0"
|
||||
headers->FileHeader.SizeOfOptionalHeader <
|
||||
sizeof(IMAGE_OPTIONAL_HEADER)) {
|
||||
return false;
|
||||
|
|
|
@ -50,7 +50,7 @@ void __sanitizer::BufferedStackTrace::UnwindImpl(
|
|||
}
|
||||
}
|
||||
|
||||
using namespace __lsan; // NOLINT
|
||||
using namespace __lsan;
|
||||
|
||||
static void InitializeFlags() {
|
||||
// Set all the default values.
|
||||
|
@ -89,7 +89,7 @@ static void InitializeFlags() {
|
|||
|
||||
static void OnStackUnwind(const SignalContext &sig, const void *,
|
||||
BufferedStackTrace *stack) {
|
||||
stack->Unwind(sig.pc, sig.bp, sig.context,
|
||||
stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
|
||||
common_flags()->fast_unwind_on_fatal);
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ static const char kStdSuppressions[] =
|
|||
|
||||
void InitializeSuppressions() {
|
||||
CHECK_EQ(nullptr, suppression_ctx);
|
||||
suppression_ctx = new (suppression_placeholder) // NOLINT
|
||||
suppression_ctx = new (suppression_placeholder)
|
||||
SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
|
||||
suppression_ctx->ParseFromFile(flags()->suppressions);
|
||||
if (&__lsan_default_suppressions)
|
||||
|
@ -104,7 +104,7 @@ InternalMmapVector<RootRegion> const *GetRootRegions() { return root_regions; }
|
|||
void InitializeRootRegions() {
|
||||
CHECK(!root_regions);
|
||||
ALIGNED(64) static char placeholder[sizeof(InternalMmapVector<RootRegion>)];
|
||||
root_regions = new (placeholder) InternalMmapVector<RootRegion>(); // NOLINT
|
||||
root_regions = new (placeholder) InternalMmapVector<RootRegion>();
|
||||
}
|
||||
|
||||
const char *MaybeCallLsanDefaultOptions() {
|
||||
|
@ -162,7 +162,7 @@ void ScanRangeForPointers(uptr begin, uptr end,
|
|||
uptr pp = begin;
|
||||
if (pp % alignment)
|
||||
pp = pp + alignment - pp % alignment;
|
||||
for (; pp + sizeof(void *) <= end; pp += alignment) { // NOLINT
|
||||
for (; pp + sizeof(void *) <= end; pp += alignment) {
|
||||
void *p = *reinterpret_cast<void **>(pp);
|
||||
if (!CanBeAHeapPointer(reinterpret_cast<uptr>(p))) continue;
|
||||
uptr chunk = PointsIntoChunk(p);
|
||||
|
@ -535,7 +535,7 @@ static void ReportIfNotSuspended(ThreadContextBase *tctx, void *arg) {
|
|||
if (i >= suspended_threads.size() || suspended_threads[i] != tctx->os_id)
|
||||
Report("Running thread %d was not suspended. False leaks are possible.\n",
|
||||
tctx->os_id);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static void ReportUnsuspendedThreads(
|
||||
|
@ -570,11 +570,7 @@ static bool CheckForLeaks() {
|
|||
EnsureMainThreadIDIsCorrect();
|
||||
CheckForLeaksParam param;
|
||||
param.success = false;
|
||||
LockThreadRegistry();
|
||||
LockAllocator();
|
||||
DoStopTheWorld(CheckForLeaksCallback, ¶m);
|
||||
UnlockAllocator();
|
||||
UnlockThreadRegistry();
|
||||
LockStuffAndStopTheWorld(CheckForLeaksCallback, ¶m);
|
||||
|
||||
if (!param.success) {
|
||||
Report("LeakSanitizer has encountered a fatal error.\n");
|
||||
|
@ -794,7 +790,7 @@ void EnableInThisThread() { }
|
|||
}
|
||||
#endif // CAN_SANITIZE_LEAKS
|
||||
|
||||
using namespace __lsan; // NOLINT
|
||||
using namespace __lsan;
|
||||
|
||||
extern "C" {
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
|
|
|
@ -129,8 +129,9 @@ struct RootRegion {
|
|||
InternalMmapVector<RootRegion> const *GetRootRegions();
|
||||
void ScanRootRegion(Frontier *frontier, RootRegion const ®ion,
|
||||
uptr region_begin, uptr region_end, bool is_readable);
|
||||
// Run stoptheworld while holding any platform-specific locks.
|
||||
void DoStopTheWorld(StopTheWorldCallback callback, void* argument);
|
||||
// Run stoptheworld while holding any platform-specific locks, as well as the
|
||||
// allocator and thread registry locks.
|
||||
void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void* argument);
|
||||
|
||||
void ScanRangeForPointers(uptr begin, uptr end,
|
||||
Frontier *frontier,
|
||||
|
|
|
@ -115,10 +115,14 @@ void HandleLeaks() {
|
|||
if (common_flags()->exitcode) Die();
|
||||
}
|
||||
|
||||
static int DoStopTheWorldCallback(struct dl_phdr_info *info, size_t size,
|
||||
void *data) {
|
||||
static int LockStuffAndStopTheWorldCallback(struct dl_phdr_info *info,
|
||||
size_t size, void *data) {
|
||||
LockThreadRegistry();
|
||||
LockAllocator();
|
||||
DoStopTheWorldParam *param = reinterpret_cast<DoStopTheWorldParam *>(data);
|
||||
StopTheWorld(param->callback, param->argument);
|
||||
UnlockAllocator();
|
||||
UnlockThreadRegistry();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -130,9 +134,9 @@ static int DoStopTheWorldCallback(struct dl_phdr_info *info, size_t size,
|
|||
// while holding the libdl lock in the parent thread, we can safely reenter it
|
||||
// in the tracer. The solution is to run stoptheworld from a dl_iterate_phdr()
|
||||
// callback in the parent thread.
|
||||
void DoStopTheWorld(StopTheWorldCallback callback, void *argument) {
|
||||
void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void *argument) {
|
||||
DoStopTheWorldParam param = {callback, argument};
|
||||
dl_iterate_phdr(DoStopTheWorldCallback, ¶m);
|
||||
dl_iterate_phdr(LockStuffAndStopTheWorldCallback, ¶m);
|
||||
}
|
||||
|
||||
} // namespace __lsan
|
||||
|
|
|
@ -193,8 +193,12 @@ void ProcessPlatformSpecificAllocations(Frontier *frontier) {
|
|||
// causes rare race conditions.
|
||||
void HandleLeaks() {}
|
||||
|
||||
void DoStopTheWorld(StopTheWorldCallback callback, void *argument) {
|
||||
void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void *argument) {
|
||||
LockThreadRegistry();
|
||||
LockAllocator();
|
||||
StopTheWorld(callback, argument);
|
||||
UnlockAllocator();
|
||||
UnlockThreadRegistry();
|
||||
}
|
||||
|
||||
} // namespace __lsan
|
||||
|
|
|
@ -345,6 +345,55 @@ INTERCEPTOR(void, thr_exit, tid_t *state) {
|
|||
#define LSAN_MAYBE_INTERCEPT_THR_EXIT
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT___CXA_ATEXIT
|
||||
INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
|
||||
void *dso_handle) {
|
||||
__lsan::ScopedInterceptorDisabler disabler;
|
||||
return REAL(__cxa_atexit)(func, arg, dso_handle);
|
||||
}
|
||||
#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit)
|
||||
#else
|
||||
#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_ATEXIT
|
||||
INTERCEPTOR(int, atexit, void (*f)()) {
|
||||
__lsan::ScopedInterceptorDisabler disabler;
|
||||
return REAL(__cxa_atexit)((void (*)(void *a))f, 0, 0);
|
||||
}
|
||||
#define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit)
|
||||
#else
|
||||
#define LSAN_MAYBE_INTERCEPT_ATEXIT
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_PTHREAD_ATFORK
|
||||
extern "C" {
|
||||
extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
|
||||
void (*child)());
|
||||
};
|
||||
|
||||
INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
|
||||
void (*child)()) {
|
||||
__lsan::ScopedInterceptorDisabler disabler;
|
||||
// REAL(pthread_atfork) cannot be called due to symbol indirections at least
|
||||
// on NetBSD
|
||||
return _pthread_atfork(prepare, parent, child);
|
||||
}
|
||||
#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork)
|
||||
#else
|
||||
#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_STRERROR
|
||||
INTERCEPTOR(char *, strerror, int errnum) {
|
||||
__lsan::ScopedInterceptorDisabler disabler;
|
||||
return REAL(strerror)(errnum);
|
||||
}
|
||||
#define LSAN_MAYBE_INTERCEPT_STRERROR INTERCEPT_FUNCTION(strerror)
|
||||
#else
|
||||
#define LSAN_MAYBE_INTERCEPT_STRERROR
|
||||
#endif
|
||||
|
||||
struct ThreadParam {
|
||||
void *(*callback)(void *arg);
|
||||
void *param;
|
||||
|
@ -454,6 +503,12 @@ void InitializeInterceptors() {
|
|||
LSAN_MAYBE_INTERCEPT__LWP_EXIT;
|
||||
LSAN_MAYBE_INTERCEPT_THR_EXIT;
|
||||
|
||||
LSAN_MAYBE_INTERCEPT___CXA_ATEXIT;
|
||||
LSAN_MAYBE_INTERCEPT_ATEXIT;
|
||||
LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK;
|
||||
|
||||
LSAN_MAYBE_INTERCEPT_STRERROR;
|
||||
|
||||
#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
|
||||
if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
|
||||
Report("LeakSanitizer: failed to create thread key.\n");
|
||||
|
|
|
@ -90,7 +90,7 @@ extern "C" void lsan_dispatch_call_block_and_release(void *block) {
|
|||
|
||||
} // namespace __lsan
|
||||
|
||||
using namespace __lsan; // NOLINT
|
||||
using namespace __lsan;
|
||||
|
||||
// Wrap |ctxt| and |func| into an lsan_block_context_t.
|
||||
// The caller retains control of the allocated context.
|
||||
|
|
|
@ -74,7 +74,6 @@ merge lib/tsan/rtl tsan
|
|||
merge lib/sanitizer_common sanitizer_common
|
||||
merge lib/interception interception
|
||||
merge lib/ubsan ubsan
|
||||
merge lib/BlocksRuntime/ BlocksRuntime
|
||||
|
||||
# Need to merge lib/builtins/assembly.h file:
|
||||
mkdir -p builtins
|
||||
|
|
|
@ -54,7 +54,7 @@ INLINE bool CheckAlignedAllocAlignmentAndSize(uptr alignment, uptr size) {
|
|||
// and a multiple of sizeof(void *).
|
||||
INLINE bool CheckPosixMemalignAlignment(uptr alignment) {
|
||||
return alignment != 0 && IsPowerOfTwo(alignment) &&
|
||||
(alignment % sizeof(void *)) == 0; // NOLINT
|
||||
(alignment % sizeof(void *)) == 0;
|
||||
}
|
||||
|
||||
// Returns true if calloc(size, n) call overflows on size*n calculation.
|
||||
|
|
|
@ -106,10 +106,11 @@ void NORETURN ReportInvalidPosixMemalignAlignment(uptr alignment,
|
|||
{
|
||||
ScopedAllocatorErrorReport report("invalid-posix-memalign-alignment",
|
||||
stack);
|
||||
Report("ERROR: %s: invalid alignment requested in "
|
||||
"posix_memalign: %zd, alignment must be a power of two and a "
|
||||
"multiple of sizeof(void*) == %zd\n", SanitizerToolName, alignment,
|
||||
sizeof(void*)); // NOLINT
|
||||
Report(
|
||||
"ERROR: %s: invalid alignment requested in "
|
||||
"posix_memalign: %zd, alignment must be a power of two and a "
|
||||
"multiple of sizeof(void*) == %zd\n",
|
||||
SanitizerToolName, alignment, sizeof(void *));
|
||||
}
|
||||
Die();
|
||||
}
|
||||
|
|
|
@ -60,7 +60,9 @@
|
|||
|
||||
#if defined(__ELF__) && (defined(__GNU__) || defined(__FreeBSD__) || \
|
||||
defined(__Fuchsia__) || defined(__linux__))
|
||||
#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits // NOLINT
|
||||
// clang-format off
|
||||
#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits // NOLINT
|
||||
// clang-format on
|
||||
#else
|
||||
#define NO_EXEC_STACK_DIRECTIVE
|
||||
#endif
|
||||
|
|
|
@ -20,44 +20,35 @@ extern "C" void _mm_mfence();
|
|||
#pragma intrinsic(_mm_mfence)
|
||||
extern "C" void _mm_pause();
|
||||
#pragma intrinsic(_mm_pause)
|
||||
extern "C" char _InterlockedExchange8( // NOLINT
|
||||
char volatile *Addend, char Value); // NOLINT
|
||||
extern "C" char _InterlockedExchange8(char volatile *Addend, char Value);
|
||||
#pragma intrinsic(_InterlockedExchange8)
|
||||
extern "C" short _InterlockedExchange16( // NOLINT
|
||||
short volatile *Addend, short Value); // NOLINT
|
||||
extern "C" short _InterlockedExchange16(short volatile *Addend, short Value);
|
||||
#pragma intrinsic(_InterlockedExchange16)
|
||||
extern "C" long _InterlockedExchange( // NOLINT
|
||||
long volatile *Addend, long Value); // NOLINT
|
||||
extern "C" long _InterlockedExchange(long volatile *Addend, long Value);
|
||||
#pragma intrinsic(_InterlockedExchange)
|
||||
extern "C" long _InterlockedExchangeAdd( // NOLINT
|
||||
long volatile * Addend, long Value); // NOLINT
|
||||
extern "C" long _InterlockedExchangeAdd(long volatile *Addend, long Value);
|
||||
#pragma intrinsic(_InterlockedExchangeAdd)
|
||||
extern "C" char _InterlockedCompareExchange8( // NOLINT
|
||||
char volatile *Destination, // NOLINT
|
||||
char Exchange, char Comparand); // NOLINT
|
||||
extern "C" char _InterlockedCompareExchange8(char volatile *Destination,
|
||||
char Exchange, char Comparand);
|
||||
#pragma intrinsic(_InterlockedCompareExchange8)
|
||||
extern "C" short _InterlockedCompareExchange16( // NOLINT
|
||||
short volatile *Destination, // NOLINT
|
||||
short Exchange, short Comparand); // NOLINT
|
||||
extern "C" short _InterlockedCompareExchange16(short volatile *Destination,
|
||||
short Exchange, short Comparand);
|
||||
#pragma intrinsic(_InterlockedCompareExchange16)
|
||||
extern "C"
|
||||
long long _InterlockedCompareExchange64( // NOLINT
|
||||
long long volatile *Destination, // NOLINT
|
||||
long long Exchange, long long Comparand); // NOLINT
|
||||
extern "C" long long _InterlockedCompareExchange64(
|
||||
long long volatile *Destination, long long Exchange, long long Comparand);
|
||||
#pragma intrinsic(_InterlockedCompareExchange64)
|
||||
extern "C" void *_InterlockedCompareExchangePointer(
|
||||
void *volatile *Destination,
|
||||
void *Exchange, void *Comparand);
|
||||
#pragma intrinsic(_InterlockedCompareExchangePointer)
|
||||
extern "C"
|
||||
long __cdecl _InterlockedCompareExchange( // NOLINT
|
||||
long volatile *Destination, // NOLINT
|
||||
long Exchange, long Comparand); // NOLINT
|
||||
extern "C" long __cdecl _InterlockedCompareExchange(long volatile *Destination,
|
||||
long Exchange,
|
||||
long Comparand);
|
||||
#pragma intrinsic(_InterlockedCompareExchange)
|
||||
|
||||
#ifdef _WIN64
|
||||
extern "C" long long _InterlockedExchangeAdd64( // NOLINT
|
||||
long long volatile * Addend, long long Value); // NOLINT
|
||||
extern "C" long long _InterlockedExchangeAdd64(long long volatile *Addend,
|
||||
long long Value);
|
||||
#pragma intrinsic(_InterlockedExchangeAdd64)
|
||||
#endif
|
||||
|
||||
|
@ -115,8 +106,8 @@ INLINE u32 atomic_fetch_add(volatile atomic_uint32_t *a,
|
|||
u32 v, memory_order mo) {
|
||||
(void)mo;
|
||||
DCHECK(!((uptr)a % sizeof(*a)));
|
||||
return (u32)_InterlockedExchangeAdd(
|
||||
(volatile long*)&a->val_dont_use, (long)v); // NOLINT
|
||||
return (u32)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
|
||||
(long)v);
|
||||
}
|
||||
|
||||
INLINE uptr atomic_fetch_add(volatile atomic_uintptr_t *a,
|
||||
|
@ -124,11 +115,11 @@ INLINE uptr atomic_fetch_add(volatile atomic_uintptr_t *a,
|
|||
(void)mo;
|
||||
DCHECK(!((uptr)a % sizeof(*a)));
|
||||
#ifdef _WIN64
|
||||
return (uptr)_InterlockedExchangeAdd64(
|
||||
(volatile long long*)&a->val_dont_use, (long long)v); // NOLINT
|
||||
return (uptr)_InterlockedExchangeAdd64((volatile long long *)&a->val_dont_use,
|
||||
(long long)v);
|
||||
#else
|
||||
return (uptr)_InterlockedExchangeAdd(
|
||||
(volatile long*)&a->val_dont_use, (long)v); // NOLINT
|
||||
return (uptr)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
|
||||
(long)v);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -136,8 +127,8 @@ INLINE u32 atomic_fetch_sub(volatile atomic_uint32_t *a,
|
|||
u32 v, memory_order mo) {
|
||||
(void)mo;
|
||||
DCHECK(!((uptr)a % sizeof(*a)));
|
||||
return (u32)_InterlockedExchangeAdd(
|
||||
(volatile long*)&a->val_dont_use, -(long)v); // NOLINT
|
||||
return (u32)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
|
||||
-(long)v);
|
||||
}
|
||||
|
||||
INLINE uptr atomic_fetch_sub(volatile atomic_uintptr_t *a,
|
||||
|
@ -145,11 +136,11 @@ INLINE uptr atomic_fetch_sub(volatile atomic_uintptr_t *a,
|
|||
(void)mo;
|
||||
DCHECK(!((uptr)a % sizeof(*a)));
|
||||
#ifdef _WIN64
|
||||
return (uptr)_InterlockedExchangeAdd64(
|
||||
(volatile long long*)&a->val_dont_use, -(long long)v); // NOLINT
|
||||
return (uptr)_InterlockedExchangeAdd64((volatile long long *)&a->val_dont_use,
|
||||
-(long long)v);
|
||||
#else
|
||||
return (uptr)_InterlockedExchangeAdd(
|
||||
(volatile long*)&a->val_dont_use, -(long)v); // NOLINT
|
||||
return (uptr)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
|
||||
-(long)v);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -323,7 +323,7 @@ static int InstallMallocFreeHooks(void (*malloc_hook)(const void *, uptr),
|
|||
|
||||
} // namespace __sanitizer
|
||||
|
||||
using namespace __sanitizer; // NOLINT
|
||||
using namespace __sanitizer;
|
||||
|
||||
extern "C" {
|
||||
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_report_error_summary,
|
||||
|
|
|
@ -100,6 +100,8 @@ void UnmapOrDie(void *addr, uptr size);
|
|||
void *MmapOrDieOnFatalError(uptr size, const char *mem_type);
|
||||
bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr)
|
||||
WARN_UNUSED_RESULT;
|
||||
bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size,
|
||||
const char *name = nullptr) WARN_UNUSED_RESULT;
|
||||
void *MmapNoReserveOrDie(uptr size, const char *mem_type);
|
||||
void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name = nullptr);
|
||||
// Behaves just like MmapFixedOrDie, but tolerates out of memory condition, in
|
||||
|
@ -337,18 +339,18 @@ void ReportMmapWriteExec(int prot);
|
|||
// Math
|
||||
#if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
|
||||
extern "C" {
|
||||
unsigned char _BitScanForward(unsigned long *index, unsigned long mask); // NOLINT
|
||||
unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); // NOLINT
|
||||
unsigned char _BitScanForward(unsigned long *index, unsigned long mask);
|
||||
unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
|
||||
#if defined(_WIN64)
|
||||
unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask); // NOLINT
|
||||
unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask); // NOLINT
|
||||
unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask);
|
||||
unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
INLINE uptr MostSignificantSetBitIndex(uptr x) {
|
||||
CHECK_NE(x, 0U);
|
||||
unsigned long up; // NOLINT
|
||||
unsigned long up;
|
||||
#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
|
||||
# ifdef _WIN64
|
||||
up = SANITIZER_WORDSIZE - 1 - __builtin_clzll(x);
|
||||
|
@ -365,7 +367,7 @@ INLINE uptr MostSignificantSetBitIndex(uptr x) {
|
|||
|
||||
INLINE uptr LeastSignificantSetBitIndex(uptr x) {
|
||||
CHECK_NE(x, 0U);
|
||||
unsigned long up; // NOLINT
|
||||
unsigned long up;
|
||||
#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
|
||||
# ifdef _WIN64
|
||||
up = __builtin_ctzll(x);
|
||||
|
@ -879,6 +881,11 @@ struct SignalContext {
|
|||
bool is_memory_access;
|
||||
enum WriteFlag { UNKNOWN, READ, WRITE } write_flag;
|
||||
|
||||
// In some cases the kernel cannot provide the true faulting address; `addr`
|
||||
// will be zero then. This field allows to distinguish between these cases
|
||||
// and dereferences of null.
|
||||
bool is_true_faulting_addr;
|
||||
|
||||
// VS2013 doesn't implement unrestricted unions, so we need a trivial default
|
||||
// constructor
|
||||
SignalContext() = default;
|
||||
|
@ -891,7 +898,8 @@ struct SignalContext {
|
|||
context(context),
|
||||
addr(GetAddress()),
|
||||
is_memory_access(IsMemoryAccess()),
|
||||
write_flag(GetWriteFlag()) {
|
||||
write_flag(GetWriteFlag()),
|
||||
is_true_faulting_addr(IsTrueFaultingAddress()) {
|
||||
InitPcSpBp();
|
||||
}
|
||||
|
||||
|
@ -912,6 +920,7 @@ struct SignalContext {
|
|||
uptr GetAddress() const;
|
||||
WriteFlag GetWriteFlag() const;
|
||||
bool IsMemoryAccess() const;
|
||||
bool IsTrueFaultingAddress() const;
|
||||
};
|
||||
|
||||
void InitializePlatformEarly();
|
||||
|
@ -971,7 +980,7 @@ INLINE u32 GetNumberOfCPUsCached() {
|
|||
} // namespace __sanitizer
|
||||
|
||||
inline void *operator new(__sanitizer::operator_new_size_type size,
|
||||
__sanitizer::LowLevelAllocator &alloc) {
|
||||
__sanitizer::LowLevelAllocator &alloc) { // NOLINT
|
||||
return alloc.Allocate(size);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
// COMMON_INTERCEPTOR_MMAP_IMPL
|
||||
// COMMON_INTERCEPTOR_COPY_STRING
|
||||
// COMMON_INTERCEPTOR_STRNDUP_IMPL
|
||||
// COMMON_INTERCEPTOR_STRERROR
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "interception/interception.h"
|
||||
|
@ -301,6 +302,10 @@ bool PlatformHasDifferentMemcpyAndMemmove();
|
|||
return new_mem;
|
||||
#endif
|
||||
|
||||
#ifndef COMMON_INTERCEPTOR_STRERROR
|
||||
#define COMMON_INTERCEPTOR_STRERROR() {}
|
||||
#endif
|
||||
|
||||
struct FileMetadata {
|
||||
// For open_memstream().
|
||||
char **addr;
|
||||
|
@ -1267,9 +1272,8 @@ INTERCEPTOR(int, puts, char *s) {
|
|||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_PRCTL
|
||||
INTERCEPTOR(int, prctl, int option, unsigned long arg2,
|
||||
unsigned long arg3, // NOLINT
|
||||
unsigned long arg4, unsigned long arg5) { // NOLINT
|
||||
INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
|
||||
unsigned long arg4, unsigned long arg5) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
|
||||
static const int PR_SET_NAME = 15;
|
||||
|
@ -1701,13 +1705,13 @@ INTERCEPTOR(int, __fprintf_chk, __sanitizer_FILE *stream, SIZE_T size,
|
|||
FORMAT_INTERCEPTOR_IMPL(__fprintf_chk, vfprintf, stream, format)
|
||||
#endif
|
||||
|
||||
INTERCEPTOR(int, sprintf, char *str, const char *format, ...) // NOLINT
|
||||
FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format) // NOLINT
|
||||
INTERCEPTOR(int, sprintf, char *str, const char *format, ...)
|
||||
FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format)
|
||||
|
||||
#if SANITIZER_INTERCEPT___PRINTF_CHK
|
||||
INTERCEPTOR(int, __sprintf_chk, char *str, int flag, SIZE_T size_to,
|
||||
const char *format, ...) // NOLINT
|
||||
FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format) // NOLINT
|
||||
const char *format, ...)
|
||||
FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format)
|
||||
#endif
|
||||
|
||||
INTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...)
|
||||
|
@ -1715,8 +1719,8 @@ FORMAT_INTERCEPTOR_IMPL(snprintf, vsnprintf, str, size, format)
|
|||
|
||||
#if SANITIZER_INTERCEPT___PRINTF_CHK
|
||||
INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag,
|
||||
SIZE_T size_to, const char *format, ...) // NOLINT
|
||||
FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format) // NOLINT
|
||||
SIZE_T size_to, const char *format, ...)
|
||||
FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format)
|
||||
#endif
|
||||
|
||||
INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
|
||||
|
@ -3071,13 +3075,14 @@ INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
|
|||
COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
||||
}
|
||||
int res = REAL(sendmmsg)(fd, msgvec, vlen, flags);
|
||||
if (res >= 0 && msgvec)
|
||||
if (res >= 0 && msgvec) {
|
||||
for (int i = 0; i < res; ++i) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
|
||||
sizeof(msgvec[i].msg_len));
|
||||
if (common_flags()->intercept_send)
|
||||
read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#define INIT_SENDMMSG COMMON_INTERCEPT_FUNCTION(sendmmsg);
|
||||
|
@ -3208,20 +3213,21 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
|
|||
__sanitizer_iovec local_iovec;
|
||||
|
||||
if (data) {
|
||||
if (request == ptrace_setregs)
|
||||
if (request == ptrace_setregs) {
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
|
||||
else if (request == ptrace_setfpregs)
|
||||
} else if (request == ptrace_setfpregs) {
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
|
||||
else if (request == ptrace_setfpxregs)
|
||||
} else if (request == ptrace_setfpxregs) {
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
|
||||
else if (request == ptrace_setvfpregs)
|
||||
} else if (request == ptrace_setvfpregs) {
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
|
||||
else if (request == ptrace_setsiginfo)
|
||||
} else if (request == ptrace_setsiginfo) {
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
|
||||
|
||||
// Some kernel might zero the iovec::iov_base in case of invalid
|
||||
// write access. In this case copy the invalid address for further
|
||||
// inspection.
|
||||
else if (request == ptrace_setregset || request == ptrace_getregset) {
|
||||
} else if (request == ptrace_setregset || request == ptrace_getregset) {
|
||||
__sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));
|
||||
local_iovec = *iovec;
|
||||
|
@ -3238,19 +3244,19 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
|
|||
if (!res && data) {
|
||||
// Note that PEEK* requests assign different meaning to the return value.
|
||||
// This function does not handle them (nor does it need to).
|
||||
if (request == ptrace_getregs)
|
||||
if (request == ptrace_getregs) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
|
||||
else if (request == ptrace_getfpregs)
|
||||
} else if (request == ptrace_getfpregs) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
|
||||
else if (request == ptrace_getfpxregs)
|
||||
} else if (request == ptrace_getfpxregs) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
|
||||
else if (request == ptrace_getvfpregs)
|
||||
} else if (request == ptrace_getvfpregs) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
|
||||
else if (request == ptrace_getsiginfo)
|
||||
} else if (request == ptrace_getsiginfo) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
|
||||
else if (request == ptrace_geteventmsg)
|
||||
} else if (request == ptrace_geteventmsg) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long));
|
||||
else if (request == ptrace_getregset) {
|
||||
} else if (request == ptrace_getregset) {
|
||||
__sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base,
|
||||
|
@ -3676,6 +3682,7 @@ INTERCEPTOR(int, sched_getparam, int pid, void *param) {
|
|||
INTERCEPTOR(char *, strerror, int errnum) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
|
||||
COMMON_INTERCEPTOR_STRERROR();
|
||||
char *res = REAL(strerror)(errnum);
|
||||
if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
|
||||
return res;
|
||||
|
@ -6716,7 +6723,7 @@ INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
|
|||
COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
|
||||
(src_size + 1) * sizeof(wchar_t));
|
||||
return REAL(wcscat)(dst, src); // NOLINT
|
||||
return REAL(wcscat)(dst, src);
|
||||
}
|
||||
|
||||
INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
|
||||
|
@ -6729,7 +6736,7 @@ INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
|
|||
COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
|
||||
(src_size + 1) * sizeof(wchar_t));
|
||||
return REAL(wcsncat)(dst, src, n); // NOLINT
|
||||
return REAL(wcsncat)(dst, src, n);
|
||||
}
|
||||
#define INIT_WCSCAT \
|
||||
COMMON_INTERCEPT_FUNCTION(wcscat); \
|
||||
|
@ -7843,10 +7850,11 @@ INTERCEPTOR(int, modctl, int operation, void *argp) {
|
|||
if (iov)
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(
|
||||
ctx, iov->iov_base, Min(iov_len, iov->iov_len));
|
||||
} else if (operation == modctl_exists)
|
||||
} else if (operation == modctl_exists) {
|
||||
ret = REAL(modctl)(operation, argp);
|
||||
else
|
||||
} else {
|
||||
ret = REAL(modctl)(operation, argp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -9565,11 +9573,60 @@ 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;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, getentropy, buf, buflen);
|
||||
int r = REAL(getentropy)(buf, buflen);
|
||||
if (r == 0) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
#define INIT_GETENTROPY COMMON_INTERCEPT_FUNCTION(getentropy)
|
||||
#else
|
||||
#define INIT_GETENTROPY
|
||||
#endif
|
||||
|
||||
static void InitializeCommonInterceptors() {
|
||||
#if SI_POSIX
|
||||
static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
|
||||
interceptor_metadata_map =
|
||||
new ((void *)&metadata_mem) MetadataHashMap(); // NOLINT
|
||||
interceptor_metadata_map = new ((void *)&metadata_mem) MetadataHashMap();
|
||||
#endif
|
||||
|
||||
INIT_MMAP;
|
||||
|
@ -9864,6 +9921,9 @@ static void InitializeCommonInterceptors() {
|
|||
INIT_GETUSERSHELL;
|
||||
INIT_SL_INIT;
|
||||
INIT_GETRANDOM;
|
||||
INIT_CRYPT;
|
||||
INIT_CRYPT_R;
|
||||
INIT_GETENTROPY;
|
||||
|
||||
INIT___PRINTF_CHK;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ INTERFACE_FUNCTION(__sanitizer_set_death_callback)
|
|||
INTERFACE_FUNCTION(__sanitizer_set_report_path)
|
||||
INTERFACE_FUNCTION(__sanitizer_set_report_fd)
|
||||
INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container)
|
||||
INTERFACE_WEAK_FUNCTION(__sanitizer_on_print)
|
||||
INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary)
|
||||
INTERFACE_WEAK_FUNCTION(__sanitizer_sandbox_on_notify)
|
||||
// Sanitizer weak hooks
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include <zircon/sanitizer.h>
|
||||
#include <zircon/syscalls.h>
|
||||
|
||||
using namespace __sanitizer; // NOLINT
|
||||
using namespace __sanitizer;
|
||||
|
||||
namespace __sancov {
|
||||
namespace {
|
||||
|
@ -198,8 +198,8 @@ void InitializeCoverage(bool enabled, const char *dir) {
|
|||
} // namespace __sanitizer
|
||||
|
||||
extern "C" {
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage( // NOLINT
|
||||
const uptr *pcs, uptr len) {
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(const uptr *pcs,
|
||||
uptr len) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
|
|
@ -166,8 +166,8 @@ void InitializeCoverage(bool enabled, const char *dir) {
|
|||
} // namespace __sanitizer
|
||||
|
||||
extern "C" {
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage( // NOLINT
|
||||
const uptr* pcs, uptr len) {
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(const uptr* pcs,
|
||||
uptr len) {
|
||||
return __sancov::SanitizerDumpCoverage(pcs, len);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
// Use uint64_t so the linker won't need to add any padding if it tries to word
|
||||
// align the start of the 8-bit counters array. The array will always start 8
|
||||
// bytes after __start_sancov_cntrs.
|
||||
#pragma section(".SCOV$CA", read, write) // NOLINT
|
||||
#pragma section(".SCOV$CA", read, write)
|
||||
__declspec(allocate(".SCOV$CA")) uint64_t __start___sancov_cntrs = 0;
|
||||
|
||||
// Even though we said not to align __stop__sancov_cntrs (using the "align"
|
||||
|
@ -41,13 +41,13 @@ __declspec(allocate(".SCOV$CA")) uint64_t __start___sancov_cntrs = 0;
|
|||
// padding would be added to align .SCOVP$Z, However, if .SCOV$CZ section is 1
|
||||
// byte, the linker won't try to align it on an 8-byte boundary, so use a
|
||||
// uint8_t for __stop_sancov_cntrs.
|
||||
#pragma section(".SCOV$CZ", read, write) // NOLINT
|
||||
#pragma section(".SCOV$CZ", read, write)
|
||||
__declspec(allocate(".SCOV$CZ")) __declspec(align(1)) uint8_t
|
||||
__stop___sancov_cntrs = 0;
|
||||
|
||||
#pragma section(".SCOV$GA", read, write) // NOLINT
|
||||
#pragma section(".SCOV$GA", read, write)
|
||||
__declspec(allocate(".SCOV$GA")) uint64_t __start___sancov_guards = 0;
|
||||
#pragma section(".SCOV$GZ", read, write) // NOLINT
|
||||
#pragma section(".SCOV$GZ", read, write)
|
||||
__declspec(allocate(".SCOV$GZ")) __declspec(align(1)) uint8_t
|
||||
__stop___sancov_guards = 0;
|
||||
|
||||
|
@ -56,9 +56,9 @@ __declspec(allocate(".SCOV$GZ")) __declspec(align(1)) uint8_t
|
|||
// constant it should be merged with the .rdata section.
|
||||
#pragma comment(linker, "/MERGE:.SCOV=.data")
|
||||
|
||||
#pragma section(".SCOVP$A", read) // NOLINT
|
||||
#pragma section(".SCOVP$A", read)
|
||||
__declspec(allocate(".SCOVP$A")) uint64_t __start___sancov_pcs = 0;
|
||||
#pragma section(".SCOVP$Z", read) // NOLINT
|
||||
#pragma section(".SCOVP$Z", read)
|
||||
__declspec(allocate(".SCOVP$Z")) __declspec(align(1)) uint8_t
|
||||
__stop___sancov_pcs = 0;
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ char *FindPathToBinary(const char *name) {
|
|||
|
||||
} // namespace __sanitizer
|
||||
|
||||
using namespace __sanitizer; // NOLINT
|
||||
using namespace __sanitizer;
|
||||
|
||||
extern "C" {
|
||||
void __sanitizer_set_report_path(const char *path) {
|
||||
|
|
|
@ -83,8 +83,9 @@ void FlagParser::parse_flag(const char *env_option_name) {
|
|||
Printf("%s: ERROR: expected '=' in %s\n", SanitizerToolName,
|
||||
env_option_name);
|
||||
Die();
|
||||
} else
|
||||
} else {
|
||||
fatal_error("expected '='");
|
||||
}
|
||||
}
|
||||
char *name = ll_strndup(buf_ + name_start, pos_ - name_start);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ class FlagHandlerBase {
|
|||
virtual bool Parse(const char *value) { return false; }
|
||||
|
||||
protected:
|
||||
~FlagHandlerBase() {};
|
||||
~FlagHandlerBase() {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -144,7 +144,7 @@ class FlagParser {
|
|||
template <typename T>
|
||||
static void RegisterFlag(FlagParser *parser, const char *name, const char *desc,
|
||||
T *var) {
|
||||
FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var); // NOLINT
|
||||
FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var);
|
||||
parser->RegisterHandler(name, fh, desc);
|
||||
}
|
||||
|
||||
|
|
|
@ -92,11 +92,11 @@ class FlagHandlerInclude : public FlagHandlerBase {
|
|||
};
|
||||
|
||||
void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) {
|
||||
FlagHandlerInclude *fh_include = new (FlagParser::Alloc) // NOLINT
|
||||
FlagHandlerInclude *fh_include = new (FlagParser::Alloc)
|
||||
FlagHandlerInclude(parser, /*ignore_missing*/ false);
|
||||
parser->RegisterHandler("include", fh_include,
|
||||
"read more options from the given file");
|
||||
FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc) // NOLINT
|
||||
FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc)
|
||||
FlagHandlerInclude(parser, /*ignore_missing*/ true);
|
||||
parser->RegisterHandler(
|
||||
"include_if_exists", fh_include_if_exists,
|
||||
|
|
|
@ -502,7 +502,7 @@ uptr GetRSS() { UNIMPLEMENTED(); }
|
|||
|
||||
} // namespace __sanitizer
|
||||
|
||||
using namespace __sanitizer; // NOLINT
|
||||
using namespace __sanitizer;
|
||||
|
||||
extern "C" {
|
||||
void __sanitizer_startup_hook(int argc, char **argv, char **envp,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// Common getauxval() guards and definitions.
|
||||
// getauxval() is not defined until glibc version 2.16, or until API level 21
|
||||
// for Android.
|
||||
// Implement the getauxval() compat function for NetBSD.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -16,15 +17,10 @@
|
|||
#define SANITIZER_GETAUXVAL_H
|
||||
|
||||
#include "sanitizer_platform.h"
|
||||
#include "sanitizer_glibc_version.h"
|
||||
|
||||
#if SANITIZER_LINUX || SANITIZER_FUCHSIA
|
||||
|
||||
# include <features.h>
|
||||
|
||||
# ifndef __GLIBC_PREREQ
|
||||
# define __GLIBC_PREREQ(x, y) 0
|
||||
# endif
|
||||
|
||||
# if __GLIBC_PREREQ(2, 16) || (SANITIZER_ANDROID && __ANDROID_API__ >= 21) || \
|
||||
SANITIZER_FUCHSIA
|
||||
# define SANITIZER_USE_GETAUXVAL 1
|
||||
|
@ -38,10 +34,26 @@
|
|||
// The weak getauxval definition allows to check for the function at runtime.
|
||||
// This is useful for Android, when compiled at a lower API level yet running
|
||||
// on a more recent platform that offers the function.
|
||||
extern "C" SANITIZER_WEAK_ATTRIBUTE
|
||||
unsigned long getauxval(unsigned long type); // NOLINT
|
||||
extern "C" SANITIZER_WEAK_ATTRIBUTE unsigned long getauxval(unsigned long type);
|
||||
# endif
|
||||
|
||||
#endif // SANITIZER_LINUX || SANITIZER_FUCHSIA
|
||||
#elif SANITIZER_NETBSD
|
||||
|
||||
#define SANITIZER_USE_GETAUXVAL 1
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <elf.h>
|
||||
|
||||
static inline decltype(AuxInfo::a_v) getauxval(decltype(AuxInfo::a_type) type) {
|
||||
for (const AuxInfo *aux = (const AuxInfo *)_dlauxinfo();
|
||||
aux->a_type != AT_NULL; ++aux) {
|
||||
if (type == aux->a_type)
|
||||
return aux->a_v;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // SANITIZER_GETAUXVAL_H
|
||||
|
|
26
libsanitizer/sanitizer_common/sanitizer_glibc_version.h
Normal file
26
libsanitizer/sanitizer_common/sanitizer_glibc_version.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
//===-- sanitizer_glibc_version.h -----------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is a part of Sanitizer common code.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SANITIZER_GLIBC_VERSION_H
|
||||
#define SANITIZER_GLIBC_VERSION_H
|
||||
|
||||
#include "sanitizer_platform.h"
|
||||
|
||||
#if SANITIZER_LINUX || SANITIZER_FUCHSIA
|
||||
#include <features.h>
|
||||
#endif
|
||||
|
||||
#ifndef __GLIBC_PREREQ
|
||||
#define __GLIBC_PREREQ(x, y) 0
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1404,7 +1404,7 @@ static void ioctl_table_fill() {
|
|||
_(SNDCTL_DSP_SKIP, NONE, 0);
|
||||
_(SNDCTL_DSP_SILENCE, NONE, 0);
|
||||
#undef _
|
||||
}
|
||||
} // NOLINT
|
||||
|
||||
static bool ioctl_initialized = false;
|
||||
|
||||
|
|
|
@ -133,27 +133,27 @@ namespace __sanitizer {
|
|||
|
||||
#if defined(_WIN64)
|
||||
// 64-bit Windows uses LLP64 data model.
|
||||
typedef unsigned long long uptr; // NOLINT
|
||||
typedef signed long long sptr; // NOLINT
|
||||
typedef unsigned long long uptr;
|
||||
typedef signed long long sptr;
|
||||
#else
|
||||
typedef unsigned long uptr; // NOLINT
|
||||
typedef signed long sptr; // NOLINT
|
||||
typedef unsigned long uptr;
|
||||
typedef signed long sptr;
|
||||
#endif // defined(_WIN64)
|
||||
#if defined(__x86_64__)
|
||||
// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use
|
||||
// 64-bit pointer to unwind stack frame.
|
||||
typedef unsigned long long uhwptr; // NOLINT
|
||||
typedef unsigned long long uhwptr;
|
||||
#else
|
||||
typedef uptr uhwptr; // NOLINT
|
||||
typedef uptr uhwptr;
|
||||
#endif
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16; // NOLINT
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64; // NOLINT
|
||||
typedef signed char s8;
|
||||
typedef signed short s16; // NOLINT
|
||||
typedef signed int s32;
|
||||
typedef signed long long s64; // NOLINT
|
||||
typedef unsigned long long u64;
|
||||
typedef signed char s8;
|
||||
typedef signed short s16;
|
||||
typedef signed int s32;
|
||||
typedef signed long long s64;
|
||||
#if SANITIZER_WINDOWS
|
||||
// On Windows, files are HANDLE, which is a synonim of void*.
|
||||
// Use void* to avoid including <windows.h> everywhere.
|
||||
|
@ -264,7 +264,7 @@ typedef ALIGNED(1) s64 us64;
|
|||
|
||||
#if SANITIZER_WINDOWS
|
||||
} // namespace __sanitizer
|
||||
typedef unsigned long DWORD; // NOLINT
|
||||
typedef unsigned long DWORD;
|
||||
namespace __sanitizer {
|
||||
typedef DWORD thread_return_t;
|
||||
# define THREAD_CALLING_CONV __stdcall
|
||||
|
@ -419,18 +419,41 @@ inline void Trap() {
|
|||
|
||||
} // namespace __sanitizer
|
||||
|
||||
namespace __asan { using namespace __sanitizer; } // NOLINT
|
||||
namespace __dsan { using namespace __sanitizer; } // NOLINT
|
||||
namespace __dfsan { using namespace __sanitizer; } // NOLINT
|
||||
namespace __lsan { using namespace __sanitizer; } // NOLINT
|
||||
namespace __msan { using namespace __sanitizer; } // NOLINT
|
||||
namespace __hwasan { using namespace __sanitizer; } // NOLINT
|
||||
namespace __tsan { using namespace __sanitizer; } // NOLINT
|
||||
namespace __scudo { using namespace __sanitizer; } // NOLINT
|
||||
namespace __ubsan { using namespace __sanitizer; } // NOLINT
|
||||
namespace __xray { using namespace __sanitizer; } // NOLINT
|
||||
namespace __interception { using namespace __sanitizer; } // NOLINT
|
||||
namespace __hwasan { using namespace __sanitizer; } // NOLINT
|
||||
|
||||
namespace __asan {
|
||||
using namespace __sanitizer;
|
||||
}
|
||||
namespace __dsan {
|
||||
using namespace __sanitizer;
|
||||
}
|
||||
namespace __dfsan {
|
||||
using namespace __sanitizer;
|
||||
}
|
||||
namespace __lsan {
|
||||
using namespace __sanitizer;
|
||||
}
|
||||
namespace __msan {
|
||||
using namespace __sanitizer;
|
||||
}
|
||||
namespace __hwasan {
|
||||
using namespace __sanitizer;
|
||||
}
|
||||
namespace __tsan {
|
||||
using namespace __sanitizer;
|
||||
}
|
||||
namespace __scudo {
|
||||
using namespace __sanitizer;
|
||||
}
|
||||
namespace __ubsan {
|
||||
using namespace __sanitizer;
|
||||
}
|
||||
namespace __xray {
|
||||
using namespace __sanitizer;
|
||||
}
|
||||
namespace __interception {
|
||||
using namespace __sanitizer;
|
||||
}
|
||||
namespace __hwasan {
|
||||
using namespace __sanitizer;
|
||||
}
|
||||
|
||||
#endif // SANITIZER_DEFS_H
|
||||
|
|
|
@ -63,10 +63,11 @@ void *internal_memmove(void *dest, const void *src, uptr n) {
|
|||
for (i = 0; i < signed_n; ++i)
|
||||
d[i] = s[i];
|
||||
} else {
|
||||
if (d > s && signed_n > 0)
|
||||
for (i = signed_n - 1; i >= 0 ; --i) {
|
||||
if (d > s && signed_n > 0) {
|
||||
for (i = signed_n - 1; i >= 0; --i) {
|
||||
d[i] = s[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
@ -270,9 +271,9 @@ bool mem_is_zero(const char *beg, uptr size) {
|
|||
for (; aligned_beg < aligned_end; aligned_beg++)
|
||||
all |= *aligned_beg;
|
||||
// Epilogue.
|
||||
if ((char*)aligned_end >= beg)
|
||||
for (const char *mem = (char*)aligned_end; mem < end; mem++)
|
||||
all |= *mem;
|
||||
if ((char *)aligned_end >= beg) {
|
||||
for (const char *mem = (char *)aligned_end; mem < end; mem++) all |= *mem;
|
||||
}
|
||||
return all == 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1062,8 +1062,6 @@ uptr GetMaxUserVirtualAddress() {
|
|||
uptr GetPageSize() {
|
||||
#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__))
|
||||
return EXEC_PAGESIZE;
|
||||
#elif SANITIZER_USE_GETAUXVAL
|
||||
return getauxval(AT_PAGESZ);
|
||||
#elif SANITIZER_FREEBSD || SANITIZER_NETBSD
|
||||
// Use sysctl as sysconf can trigger interceptors internally.
|
||||
int pz = 0;
|
||||
|
@ -1072,6 +1070,8 @@ uptr GetPageSize() {
|
|||
int rv = internal_sysctl(mib, 2, &pz, &pzl, nullptr, 0);
|
||||
CHECK_EQ(rv, 0);
|
||||
return (uptr)pz;
|
||||
#elif SANITIZER_USE_GETAUXVAL
|
||||
return getauxval(AT_PAGESZ);
|
||||
#else
|
||||
return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.
|
||||
#endif
|
||||
|
@ -1849,6 +1849,12 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool SignalContext::IsTrueFaultingAddress() const {
|
||||
auto si = static_cast<const siginfo_t *>(siginfo);
|
||||
// SIGSEGV signals without a true fault address have si_code set to 128.
|
||||
return si->si_signo == SIGSEGV && si->si_code != 128;
|
||||
}
|
||||
|
||||
void SignalContext::DumpAllRegisters(void *context) {
|
||||
// FIXME: Implement this.
|
||||
}
|
||||
|
@ -2011,6 +2017,35 @@ void CheckASLR() {
|
|||
CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
|
||||
ReExec();
|
||||
}
|
||||
#elif SANITIZER_FREEBSD
|
||||
int aslr_pie;
|
||||
uptr len = sizeof(aslr_pie);
|
||||
#if SANITIZER_WORDSIZE == 64
|
||||
if (UNLIKELY(internal_sysctlbyname("kern.elf64.aslr.pie_enable",
|
||||
&aslr_pie, &len, NULL, 0) == -1)) {
|
||||
// We're making things less 'dramatic' here since
|
||||
// the OID is not necessarily guaranteed to be here
|
||||
// just yet regarding FreeBSD release
|
||||
return;
|
||||
}
|
||||
|
||||
if (aslr_pie > 0) {
|
||||
Printf("This sanitizer is not compatible with enabled ASLR "
|
||||
"and binaries compiled with PIE\n");
|
||||
Die();
|
||||
}
|
||||
#endif
|
||||
// there might be 32 bits compat for 64 bits
|
||||
if (UNLIKELY(internal_sysctlbyname("kern.elf32.aslr.pie_enable",
|
||||
&aslr_pie, &len, NULL, 0) == -1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aslr_pie > 0) {
|
||||
Printf("This sanitizer is not compatible with enabled ASLR "
|
||||
"and binaries compiled with PIE\n");
|
||||
Die();
|
||||
}
|
||||
#else
|
||||
// Do nothing
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "sanitizer_flags.h"
|
||||
#include "sanitizer_freebsd.h"
|
||||
#include "sanitizer_getauxval.h"
|
||||
#include "sanitizer_glibc_version.h"
|
||||
#include "sanitizer_linux.h"
|
||||
#include "sanitizer_placement_new.h"
|
||||
#include "sanitizer_procmaps.h"
|
||||
|
@ -188,11 +189,7 @@ __attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,
|
|||
static uptr g_tls_size;
|
||||
|
||||
#ifdef __i386__
|
||||
# ifndef __GLIBC_PREREQ
|
||||
# define CHECK_GET_TLS_STATIC_INFO_VERSION 1
|
||||
# else
|
||||
# define CHECK_GET_TLS_STATIC_INFO_VERSION (!__GLIBC_PREREQ(2, 27))
|
||||
# endif
|
||||
# define CHECK_GET_TLS_STATIC_INFO_VERSION (!__GLIBC_PREREQ(2, 27))
|
||||
#else
|
||||
# define CHECK_GET_TLS_STATIC_INFO_VERSION 0
|
||||
#endif
|
||||
|
@ -701,13 +698,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
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "sanitizer_platform.h"
|
||||
#if SANITIZER_MAC
|
||||
#include "sanitizer_mac.h"
|
||||
#include "interception/interception.h"
|
||||
|
||||
// Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
|
||||
// the clients will most certainly use 64-bit ones as well.
|
||||
|
@ -36,7 +37,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
|
||||
|
@ -64,7 +65,9 @@ extern "C" {
|
|||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <spawn.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -239,27 +242,102 @@ int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
|
|||
(size_t)newlen);
|
||||
}
|
||||
|
||||
int internal_forkpty(int *aparent) {
|
||||
int parent, worker;
|
||||
if (openpty(&parent, &worker, nullptr, nullptr, nullptr) == -1) return -1;
|
||||
int pid = internal_fork();
|
||||
if (pid == -1) {
|
||||
close(parent);
|
||||
close(worker);
|
||||
return -1;
|
||||
static fd_t internal_spawn_impl(const char *argv[], pid_t *pid) {
|
||||
fd_t master_fd = kInvalidFd;
|
||||
fd_t slave_fd = kInvalidFd;
|
||||
|
||||
auto fd_closer = at_scope_exit([&] {
|
||||
internal_close(master_fd);
|
||||
internal_close(slave_fd);
|
||||
});
|
||||
|
||||
// We need a new pseudoterminal to avoid buffering problems. The 'atos' tool
|
||||
// in particular detects when it's talking to a pipe and forgets to flush the
|
||||
// output stream after sending a response.
|
||||
master_fd = posix_openpt(O_RDWR);
|
||||
if (master_fd == kInvalidFd) return kInvalidFd;
|
||||
|
||||
int res = grantpt(master_fd) || unlockpt(master_fd);
|
||||
if (res != 0) return kInvalidFd;
|
||||
|
||||
// Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
|
||||
char slave_pty_name[128];
|
||||
res = ioctl(master_fd, TIOCPTYGNAME, slave_pty_name);
|
||||
if (res == -1) return kInvalidFd;
|
||||
|
||||
slave_fd = internal_open(slave_pty_name, O_RDWR);
|
||||
if (slave_fd == kInvalidFd) return kInvalidFd;
|
||||
|
||||
// File descriptor actions
|
||||
posix_spawn_file_actions_t acts;
|
||||
res = posix_spawn_file_actions_init(&acts);
|
||||
if (res != 0) return kInvalidFd;
|
||||
|
||||
auto acts_cleanup = at_scope_exit([&] {
|
||||
posix_spawn_file_actions_destroy(&acts);
|
||||
});
|
||||
|
||||
res = posix_spawn_file_actions_adddup2(&acts, slave_fd, STDIN_FILENO) ||
|
||||
posix_spawn_file_actions_adddup2(&acts, slave_fd, STDOUT_FILENO) ||
|
||||
posix_spawn_file_actions_addclose(&acts, slave_fd);
|
||||
if (res != 0) return kInvalidFd;
|
||||
|
||||
// Spawn attributes
|
||||
posix_spawnattr_t attrs;
|
||||
res = posix_spawnattr_init(&attrs);
|
||||
if (res != 0) return kInvalidFd;
|
||||
|
||||
auto attrs_cleanup = at_scope_exit([&] {
|
||||
posix_spawnattr_destroy(&attrs);
|
||||
});
|
||||
|
||||
// In the spawned process, close all file descriptors that are not explicitly
|
||||
// described by the file actions object. This is Darwin-specific extension.
|
||||
res = posix_spawnattr_setflags(&attrs, POSIX_SPAWN_CLOEXEC_DEFAULT);
|
||||
if (res != 0) return kInvalidFd;
|
||||
|
||||
// posix_spawn
|
||||
char **argv_casted = const_cast<char **>(argv);
|
||||
char **env = GetEnviron();
|
||||
res = posix_spawn(pid, argv[0], &acts, &attrs, argv_casted, env);
|
||||
if (res != 0) return kInvalidFd;
|
||||
|
||||
// Disable echo in the new terminal, disable CR.
|
||||
struct termios termflags;
|
||||
tcgetattr(master_fd, &termflags);
|
||||
termflags.c_oflag &= ~ONLCR;
|
||||
termflags.c_lflag &= ~ECHO;
|
||||
tcsetattr(master_fd, TCSANOW, &termflags);
|
||||
|
||||
// On success, do not close master_fd on scope exit.
|
||||
fd_t fd = master_fd;
|
||||
master_fd = kInvalidFd;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
fd_t internal_spawn(const char *argv[], pid_t *pid) {
|
||||
// The client program may close its stdin and/or stdout and/or stderr thus
|
||||
// allowing open/posix_openpt to reuse file descriptors 0, 1 or 2. In this
|
||||
// case the communication is broken if either the parent or the child tries to
|
||||
// close or duplicate these descriptors. We temporarily reserve these
|
||||
// descriptors here to prevent this.
|
||||
fd_t low_fds[3];
|
||||
size_t count = 0;
|
||||
|
||||
for (; count < 3; count++) {
|
||||
low_fds[count] = posix_openpt(O_RDWR);
|
||||
if (low_fds[count] >= STDERR_FILENO)
|
||||
break;
|
||||
}
|
||||
if (pid == 0) {
|
||||
close(parent);
|
||||
if (login_tty(worker) != 0) {
|
||||
// We already forked, there's not much we can do. Let's quit.
|
||||
Report("login_tty failed (errno %d)\n", errno);
|
||||
internal__exit(1);
|
||||
}
|
||||
} else {
|
||||
*aparent = parent;
|
||||
close(worker);
|
||||
|
||||
fd_t fd = internal_spawn_impl(argv, pid);
|
||||
|
||||
for (; count > 0; count--) {
|
||||
internal_close(low_fds[count]);
|
||||
}
|
||||
return pid;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
uptr internal_rename(const char *oldpath, const char *newpath) {
|
||||
|
@ -676,6 +754,12 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool SignalContext::IsTrueFaultingAddress() const {
|
||||
auto si = static_cast<const siginfo_t *>(siginfo);
|
||||
// "Real" SIGSEGV codes (e.g., SEGV_MAPERR, SEGV_MAPERR) are non-zero.
|
||||
return si->si_signo == SIGSEGV && si->si_code != 0;
|
||||
}
|
||||
|
||||
static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
# if defined(__aarch64__)
|
||||
|
@ -1122,7 +1206,7 @@ bool GetRandom(void *buffer, uptr length, bool blocking) {
|
|||
if (!buffer || !length || length > 256)
|
||||
return false;
|
||||
// arc4random never fails.
|
||||
arc4random_buf(buffer, length);
|
||||
REAL(arc4random_buf)(buffer, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
|
||||
#define SANITIZER_PLATFORM_INTERCEPTORS_H
|
||||
|
||||
#include "sanitizer_glibc_version.h"
|
||||
#include "sanitizer_internal_defs.h"
|
||||
|
||||
#if SANITIZER_POSIX
|
||||
|
@ -331,10 +332,9 @@
|
|||
#define SANITIZER_INTERCEPT_ETHER_HOST \
|
||||
(SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID)
|
||||
#define SANITIZER_INTERCEPT_ETHER_R (SI_FREEBSD || SI_LINUX_NOT_ANDROID)
|
||||
#define SANITIZER_INTERCEPT_SHMCTL \
|
||||
(SI_NETBSD || SI_OPENBSD || SI_SOLARIS || \
|
||||
((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && \
|
||||
SANITIZER_WORDSIZE == 64)) // NOLINT
|
||||
#define SANITIZER_INTERCEPT_SHMCTL \
|
||||
(((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && SANITIZER_WORDSIZE == 64) || \
|
||||
SI_NETBSD || SI_OPENBSD || SI_SOLARIS) // NOLINT
|
||||
#define SANITIZER_INTERCEPT_RANDOM_R SI_LINUX_NOT_ANDROID
|
||||
#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_POSIX
|
||||
#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED \
|
||||
|
@ -489,7 +489,8 @@
|
|||
SI_NOT_RTEMS)
|
||||
#define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX
|
||||
#define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC && SI_NOT_RTEMS)
|
||||
#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_OPENBSD)
|
||||
#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE \
|
||||
(!SI_MAC && !SI_OPENBSD && !SI_NETBSD)
|
||||
#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
|
||||
#define SANITIZER_INTERCEPT_WCSCAT SI_POSIX
|
||||
#define SANITIZER_INTERCEPT_WCSDUP SI_POSIX
|
||||
|
@ -561,11 +562,18 @@
|
|||
#define SANITIZER_INTERCEPT_FUNOPEN (SI_NETBSD || SI_FREEBSD)
|
||||
#define SANITIZER_INTERCEPT_FUNOPEN2 SI_NETBSD
|
||||
#define SANITIZER_INTERCEPT_GETFSENT (SI_FREEBSD || SI_NETBSD || SI_MAC)
|
||||
#define SANITIZER_INTERCEPT_ARC4RANDOM (SI_FREEBSD || SI_NETBSD)
|
||||
#define SANITIZER_INTERCEPT_ARC4RANDOM (SI_FREEBSD || SI_NETBSD || SI_MAC)
|
||||
#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
|
||||
#define SANITIZER_INTERCEPT_GETRANDOM \
|
||||
((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD)
|
||||
#define SANITIZER_INTERCEPT___CXA_ATEXIT SI_NETBSD
|
||||
#define SANITIZER_INTERCEPT_ATEXIT SI_NETBSD
|
||||
#define SANITIZER_INTERCEPT_PTHREAD_ATFORK SI_NETBSD
|
||||
#define SANITIZER_INTERCEPT_GETENTROPY SI_FREEBSD
|
||||
|
||||
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,12 +26,9 @@
|
|||
|
||||
// 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__)
|
||||
#if defined(__x86_64__) || defined(__mips__)
|
||||
#include <sys/stat.h>
|
||||
#else
|
||||
#define ino_t __kernel_ino_t
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
#ifdef _FILE_OFFSET_BITS
|
||||
#undef _FILE_OFFSET_BITS
|
||||
#endif
|
||||
|
||||
// Must go after undef _FILE_OFFSET_BITS.
|
||||
#include "sanitizer_glibc_version.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <dirent.h>
|
||||
#include <grp.h>
|
||||
|
@ -136,6 +140,7 @@ typedef struct user_fpregs elf_fpregset_t;
|
|||
#include <linux/serial.h>
|
||||
#include <sys/msg.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <crypt.h>
|
||||
#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
|
||||
#if SANITIZER_ANDROID
|
||||
|
@ -236,6 +241,7 @@ namespace __sanitizer {
|
|||
unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT;
|
||||
unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
|
||||
unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
|
||||
unsigned struct_crypt_data_sz = sizeof(struct crypt_data);
|
||||
#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
|
||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
|
@ -1005,10 +1011,6 @@ CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
|
|||
CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
|
||||
CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
|
||||
|
||||
#ifndef __GLIBC_PREREQ
|
||||
#define __GLIBC_PREREQ(x, y) 0
|
||||
#endif
|
||||
|
||||
#if SANITIZER_LINUX && (__ANDROID_API__ >= 21 || __GLIBC_PREREQ (2, 14))
|
||||
CHECK_TYPE_SIZE(mmsghdr);
|
||||
CHECK_SIZE_AND_OFFSET(mmsghdr, msg_hdr);
|
||||
|
@ -1129,9 +1131,8 @@ CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
|
|||
#if (!defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21)) && \
|
||||
!defined(__arm__)
|
||||
/* On aarch64 glibc 2.20 and earlier provided incorrect mode field. */
|
||||
/* On Arm glibc 2.31 and later provide a different mode field, this field is
|
||||
never used by libsanitizer so we can simply ignore this assert for all glibc
|
||||
versions. */
|
||||
/* On Arm newer glibc provide a different mode field, it's hard to detect
|
||||
so just disable the check. */
|
||||
CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
|
||||
#endif
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -68,7 +68,7 @@ struct __sanitizer_ipc_perm {
|
|||
#if !defined(_LP64)
|
||||
int pad[4];
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
struct __sanitizer_shmid_ds {
|
||||
__sanitizer_ipc_perm shm_perm;
|
||||
|
@ -237,9 +237,8 @@ typedef int __sanitizer_clockid_t;
|
|||
|
||||
// This thing depends on the platform. We are only interested in the upper
|
||||
// limit. Verified with a compiler assert in .cpp.
|
||||
const int pthread_attr_t_max_sz = 128;
|
||||
union __sanitizer_pthread_attr_t {
|
||||
char size[pthread_attr_t_max_sz]; // NOLINT
|
||||
char size[128];
|
||||
void *align;
|
||||
};
|
||||
|
||||
|
|
|
@ -312,6 +312,8 @@ const char *SignalContext::Describe() const {
|
|||
return "SEGV";
|
||||
case SIGBUS:
|
||||
return "BUS";
|
||||
case SIGTRAP:
|
||||
return "TRAP";
|
||||
}
|
||||
return "UNKNOWN SIGNAL";
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ uptr internal_ptrace(int request, int pid, void *addr, void *data);
|
|||
uptr internal_waitpid(int pid, int *status, int options);
|
||||
|
||||
int internal_fork();
|
||||
int internal_forkpty(int *amaster);
|
||||
fd_t internal_spawn(const char *argv[], pid_t *pid);
|
||||
|
||||
int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
|
||||
uptr *oldlenp, const void *newp, uptr newlen);
|
||||
|
|
|
@ -304,11 +304,13 @@ void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
|
|||
MemoryMappingLayout::CacheMemoryMappings();
|
||||
}
|
||||
|
||||
bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
|
||||
static bool MmapFixed(uptr fixed_addr, uptr size, int additional_flags,
|
||||
const char *name) {
|
||||
size = RoundUpTo(size, GetPageSizeCached());
|
||||
fixed_addr = RoundDownTo(fixed_addr, GetPageSizeCached());
|
||||
uptr p = MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANON, name);
|
||||
uptr p =
|
||||
MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_FIXED | additional_flags | MAP_ANON, name);
|
||||
int reserrno;
|
||||
if (internal_iserror(p, &reserrno)) {
|
||||
Report("ERROR: %s failed to "
|
||||
|
@ -320,6 +322,24 @@ bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
|
||||
return MmapFixed(fixed_addr, size, MAP_NORESERVE, name);
|
||||
}
|
||||
|
||||
bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name) {
|
||||
#if SANITIZER_FREEBSD
|
||||
if (common_flags()->no_huge_pages_for_shadow)
|
||||
return MmapFixedNoReserve(fixed_addr, size, name);
|
||||
// MAP_NORESERVE is implicit with FreeBSD
|
||||
return MmapFixed(fixed_addr, size, MAP_ALIGNED_SUPER, name);
|
||||
#else
|
||||
bool r = MmapFixedNoReserve(fixed_addr, size, name);
|
||||
if (r)
|
||||
SetShadowRegionHugePageMode(fixed_addr, size);
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
||||
uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) {
|
||||
base_ = fixed_addr ? MmapFixedNoAccess(fixed_addr, size, name)
|
||||
: MmapNoAccess(size);
|
||||
|
|
|
@ -229,15 +229,15 @@ void SetPrintfAndReportCallback(void (*callback)(const char *)) {
|
|||
// Can be overriden in frontend.
|
||||
#if SANITIZER_GO && defined(TSAN_EXTERNAL_HOOKS)
|
||||
// Implementation must be defined in frontend.
|
||||
extern "C" void OnPrint(const char *str);
|
||||
extern "C" void __sanitizer_on_print(const char *str);
|
||||
#else
|
||||
SANITIZER_INTERFACE_WEAK_DEF(void, OnPrint, const char *str) {
|
||||
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_on_print, const char *str) {
|
||||
(void)str;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void CallPrintfAndReportCallback(const char *str) {
|
||||
OnPrint(str);
|
||||
__sanitizer_on_print(str);
|
||||
if (PrintfAndReportCallback)
|
||||
PrintfAndReportCallback(str);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ struct MemoryMappedSegmentData;
|
|||
|
||||
class MemoryMappedSegment {
|
||||
public:
|
||||
MemoryMappedSegment(char *buff = nullptr, uptr size = 0)
|
||||
explicit MemoryMappedSegment(char *buff = nullptr, uptr size = 0)
|
||||
: filename(buff), filename_size(size), data_(nullptr) {}
|
||||
~MemoryMappedSegment() {}
|
||||
|
||||
|
|
|
@ -181,13 +181,14 @@ const mach_header *get_dyld_hdr() {
|
|||
// Note that the segment addresses are not necessarily sorted.
|
||||
template <u32 kLCSegment, typename SegmentCommand>
|
||||
static bool NextSegmentLoad(MemoryMappedSegment *segment,
|
||||
MemoryMappedSegmentData *seg_data, MemoryMappingLayoutData &layout_data) {
|
||||
const char *lc = layout_data.current_load_cmd_addr;
|
||||
layout_data.current_load_cmd_addr += ((const load_command *)lc)->cmdsize;
|
||||
MemoryMappedSegmentData *seg_data,
|
||||
MemoryMappingLayoutData *layout_data) {
|
||||
const char *lc = layout_data->current_load_cmd_addr;
|
||||
layout_data->current_load_cmd_addr += ((const load_command *)lc)->cmdsize;
|
||||
if (((const load_command *)lc)->cmd == kLCSegment) {
|
||||
const SegmentCommand* sc = (const SegmentCommand *)lc;
|
||||
uptr base_virt_addr, addr_mask;
|
||||
if (layout_data.current_image == kDyldImageIdx) {
|
||||
if (layout_data->current_image == kDyldImageIdx) {
|
||||
base_virt_addr = (uptr)get_dyld_hdr();
|
||||
// vmaddr is masked with 0xfffff because on macOS versions < 10.12,
|
||||
// it contains an absolute address rather than an offset for dyld.
|
||||
|
@ -198,7 +199,7 @@ MemoryMappedSegmentData *seg_data, MemoryMappingLayoutData &layout_data) {
|
|||
addr_mask = 0xfffff;
|
||||
} else {
|
||||
base_virt_addr =
|
||||
(uptr)_dyld_get_image_vmaddr_slide(layout_data.current_image);
|
||||
(uptr)_dyld_get_image_vmaddr_slide(layout_data->current_image);
|
||||
addr_mask = ~0;
|
||||
}
|
||||
|
||||
|
@ -219,18 +220,18 @@ MemoryMappedSegmentData *seg_data, MemoryMappingLayoutData &layout_data) {
|
|||
|
||||
// Return the initial protection.
|
||||
segment->protection = sc->initprot;
|
||||
segment->offset = (layout_data.current_filetype ==
|
||||
segment->offset = (layout_data->current_filetype ==
|
||||
/*MH_EXECUTE*/ 0x2)
|
||||
? sc->vmaddr
|
||||
: sc->fileoff;
|
||||
if (segment->filename) {
|
||||
const char *src = (layout_data.current_image == kDyldImageIdx)
|
||||
const char *src = (layout_data->current_image == kDyldImageIdx)
|
||||
? kDyldPath
|
||||
: _dyld_get_image_name(layout_data.current_image);
|
||||
: _dyld_get_image_name(layout_data->current_image);
|
||||
internal_strncpy(segment->filename, src, segment->filename_size);
|
||||
}
|
||||
segment->arch = layout_data.current_arch;
|
||||
internal_memcpy(segment->uuid, layout_data.current_uuid, kModuleUUIDSize);
|
||||
segment->arch = layout_data->current_arch;
|
||||
internal_memcpy(segment->uuid, layout_data->current_uuid, kModuleUUIDSize);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -331,14 +332,14 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
|
|||
#ifdef MH_MAGIC_64
|
||||
case MH_MAGIC_64: {
|
||||
if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
|
||||
segment, segment->data_, data_))
|
||||
segment, segment->data_, &data_))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case MH_MAGIC: {
|
||||
if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
|
||||
segment, segment->data_, data_))
|
||||
segment, segment->data_, &data_))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -60,8 +60,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
|
||||
|
@ -84,21 +84,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];
|
||||
#else
|
||||
|
|
|
@ -150,8 +150,9 @@ void __sanitizer_symbolize_global(uptr data_addr, const char *fmt,
|
|||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
int __sanitizer_get_module_and_offset_for_pc( // NOLINT
|
||||
uptr pc, char *module_name, uptr module_name_len, uptr *pc_offset) {
|
||||
int __sanitizer_get_module_and_offset_for_pc(uptr pc, char *module_name,
|
||||
uptr module_name_len,
|
||||
uptr *pc_offset) {
|
||||
return __sanitizer::GetModuleAndOffsetForPc(pc, module_name, module_name_len,
|
||||
pc_offset);
|
||||
}
|
||||
|
|
|
@ -223,10 +223,11 @@ bool ThreadSuspender::SuspendAllThreads() {
|
|||
case ThreadLister::Ok:
|
||||
break;
|
||||
}
|
||||
for (tid_t tid : threads)
|
||||
for (tid_t tid : threads) {
|
||||
if (SuspendThread(tid))
|
||||
retry = true;
|
||||
};
|
||||
}
|
||||
}
|
||||
return suspended_threads_list_.ThreadCount();
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ class SuppressionContext {
|
|||
void GetMatched(InternalMmapVector<Suppression *> *matched);
|
||||
|
||||
private:
|
||||
static const int kMaxSuppressionTypes = 32;
|
||||
static const int kMaxSuppressionTypes = 64;
|
||||
const char **const suppression_types_;
|
||||
const int suppression_types_num_;
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ class SymbolizerTool {
|
|||
// SymbolizerProcess may not be used from two threads simultaneously.
|
||||
class SymbolizerProcess {
|
||||
public:
|
||||
explicit SymbolizerProcess(const char *path, bool use_forkpty = false);
|
||||
explicit SymbolizerProcess(const char *path, bool use_posix_spawn = false);
|
||||
const char *SendCommand(const char *command);
|
||||
|
||||
protected:
|
||||
|
@ -114,7 +114,7 @@ class SymbolizerProcess {
|
|||
uptr times_restarted_;
|
||||
bool failed_to_start_;
|
||||
bool reported_invalid_path_;
|
||||
bool use_forkpty_;
|
||||
bool use_posix_spawn_;
|
||||
};
|
||||
|
||||
class LLVMSymbolizerProcess;
|
||||
|
|
|
@ -238,7 +238,8 @@ const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) {
|
|||
// <empty line>
|
||||
class LLVMSymbolizerProcess : public SymbolizerProcess {
|
||||
public:
|
||||
explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {}
|
||||
explicit LLVMSymbolizerProcess(const char *path)
|
||||
: SymbolizerProcess(path, /*use_posix_spawn=*/SANITIZER_MAC) {}
|
||||
|
||||
private:
|
||||
bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
|
||||
|
@ -452,14 +453,14 @@ const char *LLVMSymbolizer::FormatAndSendCommand(const char *command_prefix,
|
|||
return symbolizer_process_->SendCommand(buffer_);
|
||||
}
|
||||
|
||||
SymbolizerProcess::SymbolizerProcess(const char *path, bool use_forkpty)
|
||||
SymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn)
|
||||
: path_(path),
|
||||
input_fd_(kInvalidFd),
|
||||
output_fd_(kInvalidFd),
|
||||
times_restarted_(0),
|
||||
failed_to_start_(false),
|
||||
reported_invalid_path_(false),
|
||||
use_forkpty_(use_forkpty) {
|
||||
use_posix_spawn_(use_posix_spawn) {
|
||||
CHECK(path_);
|
||||
CHECK_NE(path_[0], '\0');
|
||||
}
|
||||
|
|
|
@ -50,14 +50,14 @@ bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) {
|
|||
class AtosSymbolizerProcess : public SymbolizerProcess {
|
||||
public:
|
||||
explicit AtosSymbolizerProcess(const char *path, pid_t parent_pid)
|
||||
: SymbolizerProcess(path, /*use_forkpty*/ true) {
|
||||
: SymbolizerProcess(path, /*use_posix_spawn*/ true) {
|
||||
// Put the string command line argument in the object so that it outlives
|
||||
// the call to GetArgV.
|
||||
internal_snprintf(pid_str_, sizeof(pid_str_), "%d", parent_pid);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual bool StartSymbolizerSubprocess() override {
|
||||
bool StartSymbolizerSubprocess() override {
|
||||
// Configure sandbox before starting atos process.
|
||||
return SymbolizerProcess::StartSymbolizerSubprocess();
|
||||
}
|
||||
|
|
|
@ -33,10 +33,6 @@
|
|||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if SANITIZER_MAC
|
||||
#include <util.h> // for forkpty()
|
||||
#endif // SANITIZER_MAC
|
||||
|
||||
// C++ demangling function, as required by Itanium C++ ABI. This is weak,
|
||||
// because we do not require a C++ ABI library to be linked to a program
|
||||
// using sanitizers; if it's not present, we'll just use the mangled name.
|
||||
|
@ -151,80 +147,32 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
|
|||
return false;
|
||||
}
|
||||
|
||||
int pid = -1;
|
||||
const char *argv[kArgVMax];
|
||||
GetArgV(path_, argv);
|
||||
pid_t pid;
|
||||
|
||||
int infd[2];
|
||||
internal_memset(&infd, 0, sizeof(infd));
|
||||
int outfd[2];
|
||||
internal_memset(&outfd, 0, sizeof(outfd));
|
||||
if (!CreateTwoHighNumberedPipes(infd, outfd)) {
|
||||
Report("WARNING: Can't create a socket pair to start "
|
||||
"external symbolizer (errno: %d)\n", errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (use_forkpty_) {
|
||||
if (use_posix_spawn_) {
|
||||
#if SANITIZER_MAC
|
||||
fd_t fd = kInvalidFd;
|
||||
|
||||
// forkpty redirects stdout and stderr into a single stream, so we would
|
||||
// receive error messages as standard replies. To avoid that, let's dup
|
||||
// stderr and restore it in the child.
|
||||
int saved_stderr = dup(STDERR_FILENO);
|
||||
CHECK_GE(saved_stderr, 0);
|
||||
|
||||
// We only need one pipe, for stdin of the child.
|
||||
close(outfd[0]);
|
||||
close(outfd[1]);
|
||||
|
||||
// Use forkpty to disable buffering in the new terminal.
|
||||
pid = internal_forkpty(&fd);
|
||||
if (pid == -1) {
|
||||
// forkpty() failed.
|
||||
Report("WARNING: failed to fork external symbolizer (errno: %d)\n",
|
||||
fd_t fd = internal_spawn(argv, &pid);
|
||||
if (fd == kInvalidFd) {
|
||||
Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
|
||||
errno);
|
||||
return false;
|
||||
} else if (pid == 0) {
|
||||
// Child subprocess.
|
||||
|
||||
// infd[0] is the child's reading end.
|
||||
close(infd[1]);
|
||||
|
||||
// Set up stdin to read from the pipe.
|
||||
CHECK_GE(dup2(infd[0], STDIN_FILENO), 0);
|
||||
close(infd[0]);
|
||||
|
||||
// Restore stderr.
|
||||
CHECK_GE(dup2(saved_stderr, STDERR_FILENO), 0);
|
||||
close(saved_stderr);
|
||||
|
||||
const char *argv[kArgVMax];
|
||||
GetArgV(path_, argv);
|
||||
execv(path_, const_cast<char **>(&argv[0]));
|
||||
internal__exit(1);
|
||||
}
|
||||
|
||||
// Input for the child, infd[1] is our writing end.
|
||||
output_fd_ = infd[1];
|
||||
close(infd[0]);
|
||||
|
||||
// Continue execution in parent process.
|
||||
input_fd_ = fd;
|
||||
|
||||
close(saved_stderr);
|
||||
|
||||
// Disable echo in the new terminal, disable CR.
|
||||
struct termios termflags;
|
||||
tcgetattr(fd, &termflags);
|
||||
termflags.c_oflag &= ~ONLCR;
|
||||
termflags.c_lflag &= ~ECHO;
|
||||
tcsetattr(fd, TCSANOW, &termflags);
|
||||
output_fd_ = fd;
|
||||
#else // SANITIZER_MAC
|
||||
UNIMPLEMENTED();
|
||||
#endif // SANITIZER_MAC
|
||||
} else {
|
||||
const char *argv[kArgVMax];
|
||||
GetArgV(path_, argv);
|
||||
fd_t infd[2] = {}, outfd[2] = {};
|
||||
if (!CreateTwoHighNumberedPipes(infd, outfd)) {
|
||||
Report("WARNING: Can't create a socket pair to start "
|
||||
"external symbolizer (errno: %d)\n", errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
pid = StartSubprocess(path_, argv, /* stdin */ outfd[0],
|
||||
/* stdout */ infd[1]);
|
||||
if (pid < 0) {
|
||||
|
|
|
@ -106,8 +106,9 @@ void ReportMmapWriteExec(int prot) {
|
|||
if (StackTrace::WillUseFastUnwind(fast)) {
|
||||
GetThreadStackTopAndBottom(false, &top, &bottom);
|
||||
stack->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, true);
|
||||
} else
|
||||
} else {
|
||||
stack->Unwind(kStackTraceMax, pc, 0, nullptr, 0, 0, false);
|
||||
}
|
||||
|
||||
Printf("%s", d.Warning());
|
||||
Report("WARNING: %s: writable-executable page usage\n", SanitizerToolName);
|
||||
|
@ -190,9 +191,14 @@ static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
|
|||
SanitizerCommonDecorator d;
|
||||
Printf("%s", d.Warning());
|
||||
const char *description = sig.Describe();
|
||||
Report("ERROR: %s: %s on unknown address %p (pc %p bp %p sp %p T%d)\n",
|
||||
SanitizerToolName, description, (void *)sig.addr, (void *)sig.pc,
|
||||
(void *)sig.bp, (void *)sig.sp, tid);
|
||||
if (sig.is_memory_access && !sig.is_true_faulting_addr)
|
||||
Report("ERROR: %s: %s on unknown address (pc %p bp %p sp %p T%d)\n",
|
||||
SanitizerToolName, description, (void *)sig.pc, (void *)sig.bp,
|
||||
(void *)sig.sp, tid);
|
||||
else
|
||||
Report("ERROR: %s: %s on unknown address %p (pc %p bp %p sp %p T%d)\n",
|
||||
SanitizerToolName, description, (void *)sig.addr, (void *)sig.pc,
|
||||
(void *)sig.bp, (void *)sig.sp, tid);
|
||||
Printf("%s", d.Default());
|
||||
if (sig.pc < GetPageSizeCached())
|
||||
Report("Hint: pc points to the zero page.\n");
|
||||
|
@ -202,7 +208,11 @@ static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
|
|||
? "WRITE"
|
||||
: (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
|
||||
Report("The signal is caused by a %s memory access.\n", access_type);
|
||||
if (sig.addr < GetPageSizeCached())
|
||||
if (!sig.is_true_faulting_addr)
|
||||
Report("Hint: this fault was caused by a dereference of a high value "
|
||||
"address (see register values below). Dissassemble the provided "
|
||||
"pc to learn which register was used.\n");
|
||||
else if (sig.addr < GetPageSizeCached())
|
||||
Report("Hint: address points to the zero page.\n");
|
||||
}
|
||||
MaybeReportNonExecRegion(sig.pc);
|
||||
|
|
|
@ -84,7 +84,7 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
|
|||
|
||||
} // namespace __sanitizer
|
||||
|
||||
using namespace __sanitizer; // NOLINT
|
||||
using namespace __sanitizer;
|
||||
|
||||
extern "C" {
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
namespace __sanitizer {
|
||||
|
||||
namespace {
|
||||
|
||||
//---------------------------- UnwindSlow --------------------------------------
|
||||
|
||||
typedef struct {
|
||||
|
@ -46,38 +48,6 @@ release_my_map_info_list_func release_my_map_info_list;
|
|||
unwind_backtrace_signal_arch_func unwind_backtrace_signal_arch;
|
||||
} // extern "C"
|
||||
|
||||
#if SANITIZER_ANDROID
|
||||
void SanitizerInitializeUnwinder() {
|
||||
if (AndroidGetApiLevel() >= ANDROID_LOLLIPOP_MR1) return;
|
||||
|
||||
// Pre-lollipop Android can not unwind through signal handler frames with
|
||||
// libgcc unwinder, but it has a libcorkscrew.so library with the necessary
|
||||
// workarounds.
|
||||
void *p = dlopen("libcorkscrew.so", RTLD_LAZY);
|
||||
if (!p) {
|
||||
VReport(1,
|
||||
"Failed to open libcorkscrew.so. You may see broken stack traces "
|
||||
"in SEGV reports.");
|
||||
return;
|
||||
}
|
||||
acquire_my_map_info_list =
|
||||
(acquire_my_map_info_list_func)(uptr)dlsym(p, "acquire_my_map_info_list");
|
||||
release_my_map_info_list =
|
||||
(release_my_map_info_list_func)(uptr)dlsym(p, "release_my_map_info_list");
|
||||
unwind_backtrace_signal_arch = (unwind_backtrace_signal_arch_func)(uptr)dlsym(
|
||||
p, "unwind_backtrace_signal_arch");
|
||||
if (!acquire_my_map_info_list || !release_my_map_info_list ||
|
||||
!unwind_backtrace_signal_arch) {
|
||||
VReport(1,
|
||||
"Failed to find one of the required symbols in libcorkscrew.so. "
|
||||
"You may see broken stack traces in SEGV reports.");
|
||||
acquire_my_map_info_list = 0;
|
||||
unwind_backtrace_signal_arch = 0;
|
||||
release_my_map_info_list = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__arm__) && !SANITIZER_NETBSD
|
||||
// NetBSD uses dwarf EH
|
||||
#define UNWIND_STOP _URC_END_OF_STACK
|
||||
|
@ -119,6 +89,40 @@ _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
|
|||
return UNWIND_CONTINUE;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#if SANITIZER_ANDROID
|
||||
void SanitizerInitializeUnwinder() {
|
||||
if (AndroidGetApiLevel() >= ANDROID_LOLLIPOP_MR1) return;
|
||||
|
||||
// Pre-lollipop Android can not unwind through signal handler frames with
|
||||
// libgcc unwinder, but it has a libcorkscrew.so library with the necessary
|
||||
// workarounds.
|
||||
void *p = dlopen("libcorkscrew.so", RTLD_LAZY);
|
||||
if (!p) {
|
||||
VReport(1,
|
||||
"Failed to open libcorkscrew.so. You may see broken stack traces "
|
||||
"in SEGV reports.");
|
||||
return;
|
||||
}
|
||||
acquire_my_map_info_list =
|
||||
(acquire_my_map_info_list_func)(uptr)dlsym(p, "acquire_my_map_info_list");
|
||||
release_my_map_info_list =
|
||||
(release_my_map_info_list_func)(uptr)dlsym(p, "release_my_map_info_list");
|
||||
unwind_backtrace_signal_arch = (unwind_backtrace_signal_arch_func)(uptr)dlsym(
|
||||
p, "unwind_backtrace_signal_arch");
|
||||
if (!acquire_my_map_info_list || !release_my_map_info_list ||
|
||||
!unwind_backtrace_signal_arch) {
|
||||
VReport(1,
|
||||
"Failed to find one of the required symbols in libcorkscrew.so. "
|
||||
"You may see broken stack traces in SEGV reports.");
|
||||
acquire_my_map_info_list = 0;
|
||||
unwind_backtrace_signal_arch = 0;
|
||||
release_my_map_info_list = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
|
||||
CHECK_GE(max_depth, 2);
|
||||
size = 0;
|
||||
|
|
|
@ -23,11 +23,7 @@ namespace __sanitizer {
|
|||
template<typename T>
|
||||
class Vector {
|
||||
public:
|
||||
explicit Vector()
|
||||
: begin_()
|
||||
, end_()
|
||||
, last_() {
|
||||
}
|
||||
Vector() : begin_(), end_(), last_() {}
|
||||
|
||||
~Vector() {
|
||||
if (begin_)
|
||||
|
|
|
@ -239,6 +239,11 @@ bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name) {
|
||||
// FIXME: Windows support large pages too. Might be worth checking
|
||||
return MmapFixedNoReserve(fixed_addr, size, name);
|
||||
}
|
||||
|
||||
// Memory space mapped by 'MmapFixedOrDie' must have been reserved by
|
||||
// 'MmapFixedNoAccess'.
|
||||
void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) {
|
||||
|
@ -671,7 +676,7 @@ static int RunAtexit() {
|
|||
return ret;
|
||||
}
|
||||
|
||||
#pragma section(".CRT$XID", long, read) // NOLINT
|
||||
#pragma section(".CRT$XID", long, read)
|
||||
__declspec(allocate(".CRT$XID")) int (*__run_atexit)() = RunAtexit;
|
||||
#endif
|
||||
|
||||
|
@ -940,6 +945,11 @@ bool SignalContext::IsMemoryAccess() const {
|
|||
return GetWriteFlag() != SignalContext::UNKNOWN;
|
||||
}
|
||||
|
||||
bool SignalContext::IsTrueFaultingAddress() const {
|
||||
// FIXME: Provide real implementation for this. See Linux and Mac variants.
|
||||
return IsMemoryAccess();
|
||||
}
|
||||
|
||||
SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
|
||||
EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
|
||||
// The contents of this array are documented at
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#define STRINGIFY_(A) #A
|
||||
#define STRINGIFY(A) STRINGIFY_(A)
|
||||
|
||||
#if !SANITIZER_GO
|
||||
|
||||
// ----------------- A workaround for the absence of weak symbols --------------
|
||||
// We don't have a direct equivalent of weak symbols when using MSVC, but we can
|
||||
// use the /alternatename directive to tell the linker to default a specific
|
||||
|
@ -158,5 +160,15 @@
|
|||
// return a >= b;
|
||||
// }
|
||||
//
|
||||
|
||||
#else // SANITIZER_GO
|
||||
|
||||
// Go neither needs nor wants weak references.
|
||||
// The shenanigans above don't work for gcc.
|
||||
# define WIN_WEAK_EXPORT_DEF(ReturnType, Name, ...) \
|
||||
extern "C" ReturnType Name(__VA_ARGS__)
|
||||
|
||||
#endif // SANITIZER_GO
|
||||
|
||||
#endif // SANITIZER_WINDOWS
|
||||
#endif // SANITIZER_WIN_DEFS_H
|
||||
|
|
|
@ -54,8 +54,8 @@ int dllThunkInterceptWhenPossible(const char* main_function,
|
|||
#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
|
||||
#include "sanitizer_common_interface.inc"
|
||||
|
||||
#pragma section(".DLLTH$A", read) // NOLINT
|
||||
#pragma section(".DLLTH$Z", read) // NOLINT
|
||||
#pragma section(".DLLTH$A", read)
|
||||
#pragma section(".DLLTH$Z", read)
|
||||
|
||||
typedef void (*DllThunkCB)();
|
||||
extern "C" {
|
||||
|
@ -85,7 +85,7 @@ extern "C" int __dll_thunk_init() {
|
|||
|
||||
// We want to call dll_thunk_init before C/C++ initializers / constructors are
|
||||
// executed, otherwise functions like memset might be invoked.
|
||||
#pragma section(".CRT$XIB", long, read) // NOLINT
|
||||
#pragma section(".CRT$XIB", long, read)
|
||||
__declspec(allocate(".CRT$XIB")) int (*__dll_thunk_preinit)() =
|
||||
__dll_thunk_init;
|
||||
|
||||
|
@ -94,7 +94,7 @@ static void WINAPI dll_thunk_thread_init(void *mod, unsigned long reason,
|
|||
if (reason == /*DLL_PROCESS_ATTACH=*/1) __dll_thunk_init();
|
||||
}
|
||||
|
||||
#pragma section(".CRT$XLAB", long, read) // NOLINT
|
||||
#pragma section(".CRT$XLAB", long, read)
|
||||
__declspec(allocate(".CRT$XLAB")) void (WINAPI *__dll_thunk_tls_init)(void *,
|
||||
unsigned long, void *) = dll_thunk_thread_init;
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ int interceptWhenPossible(uptr dll_function, const char *real_function) {
|
|||
|
||||
// Declare weak hooks.
|
||||
extern "C" {
|
||||
void __sanitizer_on_print(const char *str);
|
||||
void __sanitizer_weak_hook_memcmp(uptr called_pc, const void *s1,
|
||||
const void *s2, uptr n, int result);
|
||||
void __sanitizer_weak_hook_strcmp(uptr called_pc, const char *s1,
|
||||
|
@ -53,8 +54,8 @@ void __sanitizer_weak_hook_strstr(uptr called_pc, const char *s1,
|
|||
#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
|
||||
#include "sanitizer_common_interface.inc"
|
||||
|
||||
#pragma section(".WEAK$A", read) // NOLINT
|
||||
#pragma section(".WEAK$Z", read) // NOLINT
|
||||
#pragma section(".WEAK$A", read)
|
||||
#pragma section(".WEAK$Z", read)
|
||||
|
||||
typedef void (*InterceptCB)();
|
||||
extern "C" {
|
||||
|
@ -77,7 +78,7 @@ static int weak_intercept_init() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#pragma section(".CRT$XIB", long, read) // NOLINT
|
||||
#pragma section(".CRT$XIB", long, read)
|
||||
__declspec(allocate(".CRT$XIB")) int (*__weak_intercept_preinit)() =
|
||||
weak_intercept_init;
|
||||
|
||||
|
@ -86,7 +87,7 @@ static void WINAPI weak_intercept_thread_init(void *mod, unsigned long reason,
|
|||
if (reason == /*DLL_PROCESS_ATTACH=*/1) weak_intercept_init();
|
||||
}
|
||||
|
||||
#pragma section(".CRT$XLAB", long, read) // NOLINT
|
||||
#pragma section(".CRT$XLAB", long, read)
|
||||
__declspec(allocate(".CRT$XLAB")) void(WINAPI *__weak_intercept_tls_init)(
|
||||
void *, unsigned long, void *) = weak_intercept_thread_init;
|
||||
|
||||
|
|
|
@ -31,11 +31,11 @@ typedef void (^dispatch_block_t)(void);
|
|||
typedef void (^dispatch_io_handler_t)(bool done, dispatch_data_t data,
|
||||
int error);
|
||||
|
||||
typedef long dispatch_once_t; // NOLINT
|
||||
typedef long dispatch_once_t;
|
||||
typedef __sanitizer::u64 dispatch_time_t;
|
||||
typedef int dispatch_fd_t; // NOLINT
|
||||
typedef unsigned long dispatch_io_type_t; // NOLINT
|
||||
typedef unsigned long dispatch_io_close_flags_t; // NOLINT
|
||||
typedef int dispatch_fd_t;
|
||||
typedef unsigned long dispatch_io_type_t;
|
||||
typedef unsigned long dispatch_io_close_flags_t;
|
||||
|
||||
extern "C" {
|
||||
void *dispatch_get_context(dispatch_object_t object);
|
||||
|
@ -57,10 +57,10 @@ extern const dispatch_block_t _dispatch_data_destructor_munmap;
|
|||
#endif
|
||||
|
||||
// Data types used in dispatch APIs
|
||||
typedef unsigned long size_t; // NOLINT
|
||||
typedef unsigned long uintptr_t; // NOLINT
|
||||
typedef unsigned long size_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef __sanitizer::s64 off_t;
|
||||
typedef __sanitizer::u16 mode_t;
|
||||
typedef long long_t; // NOLINT
|
||||
typedef long long_t;
|
||||
|
||||
#endif // TSAN_DISPATCH_DEFS_H
|
||||
|
|
|
@ -25,7 +25,7 @@ static TagData registered_tags[kExternalTagMax] = {
|
|||
{},
|
||||
{"Swift variable", "Swift access race"},
|
||||
};
|
||||
static atomic_uint32_t used_tags{kExternalTagFirstUserAvailable}; // NOLINT.
|
||||
static atomic_uint32_t used_tags{kExternalTagFirstUserAvailable};
|
||||
static TagData *GetTagData(uptr tag) {
|
||||
// Invalid/corrupted tag? Better return NULL and let the caller deal with it.
|
||||
if (tag >= atomic_load(&used_tags, memory_order_relaxed)) return nullptr;
|
||||
|
|
|
@ -86,7 +86,8 @@ static FdDesc *fddesc(ThreadState *thr, uptr pc, int fd) {
|
|||
else
|
||||
user_free(thr, pc, p, false);
|
||||
}
|
||||
return &((FdDesc*)l1)[fd % kTableSizeL2]; // NOLINT
|
||||
FdDesc *fds = reinterpret_cast<FdDesc *>(l1);
|
||||
return &fds[fd % kTableSizeL2];
|
||||
}
|
||||
|
||||
// pd must be already ref'ed.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//===-- tsan_libdispatch.cpp ----------------------------------------------===//
|
||||
//===-- tsan_interceptors_libdispatch.cpp ---------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
@ -16,6 +16,7 @@
|
|||
#include "tsan_interceptors.h"
|
||||
#include "tsan_rtl.h"
|
||||
|
||||
#include "BlocksRuntime/Block.h"
|
||||
#include "tsan_dispatch_defs.h"
|
||||
|
||||
namespace __tsan {
|
|
@ -23,13 +23,14 @@
|
|||
#include <errno.h>
|
||||
#include <libkern/OSAtomic.h>
|
||||
#include <objc/objc-sync.h>
|
||||
#include <os/lock.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#if defined(__has_include) && __has_include(<xpc/xpc.h>)
|
||||
#include <xpc/xpc.h>
|
||||
#endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
|
||||
|
||||
typedef long long_t; // NOLINT
|
||||
typedef long long_t;
|
||||
|
||||
extern "C" {
|
||||
int getcontext(ucontext_t *ucp) __attribute__((returns_twice));
|
||||
|
@ -246,6 +247,45 @@ TSAN_INTERCEPTOR(void, os_lock_unlock, void *lock) {
|
|||
REAL(os_lock_unlock)(lock);
|
||||
}
|
||||
|
||||
TSAN_INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
|
||||
if (!cur_thread()->is_inited || cur_thread()->is_dead) {
|
||||
return REAL(os_unfair_lock_lock)(lock);
|
||||
}
|
||||
SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_lock, lock);
|
||||
REAL(os_unfair_lock_lock)(lock);
|
||||
Acquire(thr, pc, (uptr)lock);
|
||||
}
|
||||
|
||||
TSAN_INTERCEPTOR(void, os_unfair_lock_lock_with_options, os_unfair_lock_t lock,
|
||||
u32 options) {
|
||||
if (!cur_thread()->is_inited || cur_thread()->is_dead) {
|
||||
return REAL(os_unfair_lock_lock_with_options)(lock, options);
|
||||
}
|
||||
SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_lock_with_options, lock, options);
|
||||
REAL(os_unfair_lock_lock_with_options)(lock, options);
|
||||
Acquire(thr, pc, (uptr)lock);
|
||||
}
|
||||
|
||||
TSAN_INTERCEPTOR(bool, os_unfair_lock_trylock, os_unfair_lock_t lock) {
|
||||
if (!cur_thread()->is_inited || cur_thread()->is_dead) {
|
||||
return REAL(os_unfair_lock_trylock)(lock);
|
||||
}
|
||||
SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_trylock, lock);
|
||||
bool result = REAL(os_unfair_lock_trylock)(lock);
|
||||
if (result)
|
||||
Acquire(thr, pc, (uptr)lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
TSAN_INTERCEPTOR(void, os_unfair_lock_unlock, os_unfair_lock_t lock) {
|
||||
if (!cur_thread()->is_inited || cur_thread()->is_dead) {
|
||||
return REAL(os_unfair_lock_unlock)(lock);
|
||||
}
|
||||
SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_unlock, lock);
|
||||
Release(thr, pc, (uptr)lock);
|
||||
REAL(os_unfair_lock_unlock)(lock);
|
||||
}
|
||||
|
||||
#if defined(__has_include) && __has_include(<xpc/xpc.h>)
|
||||
|
||||
TSAN_INTERCEPTOR(void, xpc_connection_set_event_handler,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue