Merge ^/vendor/compiler-rt/dist up to its last change, and resolve conflicts.
This commit is contained in:
commit
68d75eff68
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/clang1000-import/; revision=356999
@ -13,11 +13,10 @@
|
||||
#ifndef LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
|
||||
#define LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <initializer_list>
|
||||
#include <string>
|
||||
@ -25,8 +24,10 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// In addition to the comments below, the API is also briefly documented at
|
||||
// https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider
|
||||
class FuzzedDataProvider {
|
||||
public:
|
||||
public:
|
||||
// |data| is an array of length |size| that the FuzzedDataProvider wraps to
|
||||
// provide more granular access. |data| must outlive the FuzzedDataProvider.
|
||||
FuzzedDataProvider(const uint8_t *data, size_t size)
|
||||
@ -143,9 +144,9 @@ class FuzzedDataProvider {
|
||||
return ConsumeBytes<T>(remaining_bytes_);
|
||||
}
|
||||
|
||||
// Returns a std::string containing all remaining bytes of the input data.
|
||||
// Prefer using |ConsumeRemainingBytes| unless you actually need a std::string
|
||||
// object.
|
||||
// Returns a std::vector containing all remaining bytes of the input data.
|
||||
std::string ConsumeRemainingBytesAsString() {
|
||||
return ConsumeBytesAsString(remaining_bytes_);
|
||||
}
|
||||
@ -161,7 +162,7 @@ class FuzzedDataProvider {
|
||||
// Reads one byte and returns a bool, or false when no data remains.
|
||||
bool ConsumeBool() { return 1 & ConsumeIntegral<uint8_t>(); }
|
||||
|
||||
// Returns a copy of a value selected from a fixed-size |array|.
|
||||
// Returns a copy of the value selected from the given fixed-size |array|.
|
||||
template <typename T, size_t size>
|
||||
T PickValueInArray(const T (&array)[size]) {
|
||||
static_assert(size > 0, "The array must be non empty.");
|
||||
@ -170,11 +171,14 @@ class FuzzedDataProvider {
|
||||
|
||||
template <typename T>
|
||||
T PickValueInArray(std::initializer_list<const T> list) {
|
||||
// static_assert(list.size() > 0, "The array must be non empty.");
|
||||
// TODO(Dor1s): switch to static_assert once C++14 is allowed.
|
||||
if (!list.size())
|
||||
abort();
|
||||
|
||||
return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1));
|
||||
}
|
||||
|
||||
// Return an enum value. The enum must start at 0 and be contiguous. It must
|
||||
// Returns an enum value. The enum must start at 0 and be contiguous. It must
|
||||
// also contain |kMaxValue| aliased to its largest (inclusive) value. Such as:
|
||||
// enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue };
|
||||
template <typename T> T ConsumeEnum() {
|
||||
@ -183,10 +187,60 @@ class FuzzedDataProvider {
|
||||
0, static_cast<uint32_t>(T::kMaxValue)));
|
||||
}
|
||||
|
||||
// Returns a floating point number in the range [0.0, 1.0]. If there's no
|
||||
// input data left, always returns 0.
|
||||
template <typename T> T ConsumeProbability() {
|
||||
static_assert(std::is_floating_point<T>::value,
|
||||
"A floating point type is required.");
|
||||
|
||||
// Use different integral types for different floating point types in order
|
||||
// to provide better density of the resulting values.
|
||||
using IntegralType =
|
||||
typename std::conditional<(sizeof(T) <= sizeof(uint32_t)), uint32_t,
|
||||
uint64_t>::type;
|
||||
|
||||
T result = static_cast<T>(ConsumeIntegral<IntegralType>());
|
||||
result /= static_cast<T>(std::numeric_limits<IntegralType>::max());
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns a floating point value in the range [Type's lowest, Type's max] by
|
||||
// consuming bytes from the input data. If there's no input data left, always
|
||||
// returns approximately 0.
|
||||
template <typename T> T ConsumeFloatingPoint() {
|
||||
return ConsumeFloatingPointInRange<T>(std::numeric_limits<T>::lowest(),
|
||||
std::numeric_limits<T>::max());
|
||||
}
|
||||
|
||||
// Returns a floating point value in the given range by consuming bytes from
|
||||
// the input data. If there's no input data left, returns |min|. Note that
|
||||
// |min| must be less than or equal to |max|.
|
||||
template <typename T> T ConsumeFloatingPointInRange(T min, T max) {
|
||||
if (min > max)
|
||||
abort();
|
||||
|
||||
T range = .0;
|
||||
T result = min;
|
||||
constexpr T zero(.0);
|
||||
if (max > zero && min < zero && max > min + std::numeric_limits<T>::max()) {
|
||||
// The diff |max - min| would overflow the given floating point type. Use
|
||||
// the half of the diff as the range and consume a bool to decide whether
|
||||
// the result is in the first of the second part of the diff.
|
||||
range = (max / 2.0) - (min / 2.0);
|
||||
if (ConsumeBool()) {
|
||||
result += range;
|
||||
}
|
||||
} else {
|
||||
range = max - min;
|
||||
}
|
||||
|
||||
return result + range * ConsumeProbability<T>();
|
||||
}
|
||||
|
||||
// Reports the remaining bytes available for fuzzed input.
|
||||
size_t remaining_bytes() { return remaining_bytes_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
FuzzedDataProvider(const FuzzedDataProvider &) = delete;
|
||||
FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete;
|
||||
|
||||
@ -230,9 +284,9 @@ class FuzzedDataProvider {
|
||||
|
||||
// Avoid using implementation-defined unsigned to signer conversions.
|
||||
// To learn more, see https://stackoverflow.com/questions/13150449.
|
||||
if (value <= std::numeric_limits<TS>::max())
|
||||
if (value <= std::numeric_limits<TS>::max()) {
|
||||
return static_cast<TS>(value);
|
||||
else {
|
||||
} else {
|
||||
constexpr auto TS_min = std::numeric_limits<TS>::min();
|
||||
return TS_min + static_cast<char>(value - TS_min);
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_activation.cc --------------------------------------*- C++ -*-===//
|
||||
//===-- asan_activation.cpp -------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_allocator.cc -------------------------------------------------===//
|
||||
//===-- asan_allocator.cpp ------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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.
|
@ -8,7 +8,7 @@
|
||||
//
|
||||
// This file is a part of AddressSanitizer, an address sanity checker.
|
||||
//
|
||||
// ASan-private header for asan_allocator.cc.
|
||||
// ASan-private header for asan_allocator.cpp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef ASAN_ALLOCATOR_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_debugging.cc -------------------------------------------------===//
|
||||
//===-- asan_debugging.cpp ------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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";
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_descriptions.cc ------------------------------------*- C++ -*-===//
|
||||
//===-- asan_descriptions.cpp -----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -8,7 +8,7 @@
|
||||
//
|
||||
// This file is a part of AddressSanitizer, an address sanity checker.
|
||||
//
|
||||
// ASan-private header for asan_descriptions.cc.
|
||||
// ASan-private header for asan_descriptions.cpp.
|
||||
// TODO(filcab): Most struct definitions should move to the interface headers.
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef ASAN_DESCRIPTIONS_H
|
||||
@ -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);
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_errors.cc ------------------------------------------*- C++ -*-===//
|
||||
//===-- asan_errors.cpp -----------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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");
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_fake_stack.cc ------------------------------------------------===//
|
||||
//===-- asan_fake_stack.cpp -----------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -8,7 +8,7 @@
|
||||
//
|
||||
// This file is a part of AddressSanitizer, an address sanity checker.
|
||||
//
|
||||
// ASan-private header for asan_fake_stack.cc, implements FakeStack.
|
||||
// ASan-private header for asan_fake_stack.cpp, implements FakeStack.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef ASAN_FAKE_STACK_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_flags.cc -------------------------------------------*- C++ -*-===//
|
||||
//===-- asan_flags.cpp ------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -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.")
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_fuchsia.cc --------------------------------------------------===//
|
||||
//===-- asan_fuchsia.cpp -------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -28,7 +28,7 @@ namespace __asan {
|
||||
|
||||
// The system already set up the shadow memory for us.
|
||||
// __sanitizer::GetMaxUserVirtualAddress has already been called by
|
||||
// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cc).
|
||||
// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cpp).
|
||||
// Just do some additional sanity checks here.
|
||||
void InitializeShadowMemory() {
|
||||
if (Verbosity()) PrintAddressSpaceLayout();
|
||||
@ -172,7 +172,7 @@ static void ThreadCreateHook(void *hook, bool aborted) {
|
||||
|
||||
// This is called in the newly-created thread before it runs anything else,
|
||||
// with the pointer returned by BeforeThreadCreateHook (above).
|
||||
// cf. asan_interceptors.cc:asan_thread_start
|
||||
// cf. asan_interceptors.cpp:asan_thread_start
|
||||
static void ThreadStartHook(void *hook, uptr os_id) {
|
||||
AsanThread *thread = static_cast<AsanThread *>(hook);
|
||||
SetCurrentThread(thread);
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_globals.cc ---------------------------------------------------===//
|
||||
//===-- asan_globals.cpp --------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -227,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 };
|
||||
@ -315,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
|
||||
@ -364,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]};
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_globals_win.cc -----------------------------------------------===//
|
||||
//===-- asan_globals_win.cpp ----------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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"))
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_interceptors.cc ----------------------------------------------===//
|
||||
//===-- asan_interceptors.cpp ---------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -24,7 +24,7 @@
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
|
||||
// There is no general interception at all on Fuchsia and RTEMS.
|
||||
// Only the functions in asan_interceptors_memintrinsics.cc are
|
||||
// Only the functions in asan_interceptors_memintrinsics.cpp are
|
||||
// really defined to replace libc functions.
|
||||
#if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
|
||||
|
||||
@ -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
|
@ -8,7 +8,7 @@
|
||||
//
|
||||
// This file is a part of AddressSanitizer, an address sanity checker.
|
||||
//
|
||||
// ASan-private header for asan_interceptors.cc
|
||||
// ASan-private header for asan_interceptors.cpp
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef ASAN_INTERCEPTORS_H
|
||||
#define ASAN_INTERCEPTORS_H
|
||||
@ -99,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
|
||||
@ -112,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)
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_interceptors_memintrinsics.cc --------------------------------===//
|
||||
//===-- asan_interceptors_memintrinsics.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,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);
|
@ -8,7 +8,7 @@
|
||||
//
|
||||
// This file is a part of AddressSanitizer, an address sanity checker.
|
||||
//
|
||||
// ASan-private header for asan_memintrin.cc
|
||||
// ASan-private header for asan_interceptors_memintrinsics.cpp
|
||||
//===---------------------------------------------------------------------===//
|
||||
#ifndef ASAN_MEMINTRIN_H
|
||||
#define ASAN_MEMINTRIN_H
|
||||
|
@ -61,29 +61,29 @@ using __sanitizer::StackTrace;
|
||||
|
||||
void AsanInitFromRtl();
|
||||
|
||||
// asan_win.cc
|
||||
// asan_win.cpp
|
||||
void InitializePlatformExceptionHandlers();
|
||||
// Returns whether an address is a valid allocated system heap block.
|
||||
// 'addr' must point to the beginning of the block.
|
||||
bool IsSystemHeapAddress(uptr addr);
|
||||
|
||||
// asan_rtl.cc
|
||||
// asan_rtl.cpp
|
||||
void PrintAddressSpaceLayout();
|
||||
void NORETURN ShowStatsAndAbort();
|
||||
|
||||
// asan_shadow_setup.cc
|
||||
// asan_shadow_setup.cpp
|
||||
void InitializeShadowMemory();
|
||||
|
||||
// asan_malloc_linux.cc / asan_malloc_mac.cc
|
||||
// asan_malloc_linux.cpp / asan_malloc_mac.cpp
|
||||
void ReplaceSystemMalloc();
|
||||
|
||||
// asan_linux.cc / asan_mac.cc / asan_rtems.cc / asan_win.cc
|
||||
// asan_linux.cpp / asan_mac.cpp / asan_rtems.cpp / asan_win.cpp
|
||||
uptr FindDynamicShadowStart();
|
||||
void *AsanDoesNotSupportStaticLinkage();
|
||||
void AsanCheckDynamicRTPrereqs();
|
||||
void AsanCheckIncompatibleRT();
|
||||
|
||||
// asan_thread.cc
|
||||
// asan_thread.cpp
|
||||
AsanThread *CreateMainThread();
|
||||
|
||||
// Support function for __asan_(un)register_image_globals. Searches for the
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_linux.cc -----------------------------------------------------===//
|
||||
//===-- asan_linux.cpp ----------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_mac.cc -------------------------------------------------------===//
|
||||
//===-- asan_mac.cpp ------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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.
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_malloc_linux.cc ----------------------------------------------===//
|
||||
//===-- asan_malloc_linux.cpp ---------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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;
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_malloc_mac.cc ------------------------------------------------===//
|
||||
//===-- asan_malloc_mac.cpp -----------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_malloc_win.cc ------------------------------------------------===//
|
||||
//===-- asan_malloc_win.cpp -----------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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);
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_memory_profile.cc.cc -----------------------------------------===//
|
||||
//===-- asan_memory_profile.cpp ----------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_interceptors.cc ----------------------------------------------===//
|
||||
//===-- asan_interceptors.cpp ---------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_poisoning.cc -------------------------------------------------===//
|
||||
//===-- asan_poisoning.cpp ------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_posix.cc -----------------------------------------------------===//
|
||||
//===-- asan_posix.cpp ----------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_preinit.cc ---------------------------------------------------===//
|
||||
//===-- asan_preinit.cpp --------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_premap_shadow.cc ---------------------------------------------===//
|
||||
//===-- asan_premap_shadow.cpp --------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_report.cc ----------------------------------------------------===//
|
||||
//===-- asan_report.cpp ---------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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) {
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_rtems.cc -----------------------------------------------------===//
|
||||
//===-- asan_rtems.cpp ----------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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.
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_rtl.cc -------------------------------------------------------===//
|
||||
//===-- asan_rtl.cpp ------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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 {
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_shadow_setup.cc ----------------------------------------------===//
|
||||
//===-- asan_shadow_setup.cpp ---------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
|
||||
// asan_fuchsia.cc and asan_rtems.cc have their own
|
||||
// asan_fuchsia.cpp and asan_rtems.cpp have their own
|
||||
// InitializeShadowMemory implementation.
|
||||
#if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
|
||||
|
||||
@ -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();
|
||||
}
|
||||
if (common_flags()->no_huge_pages_for_shadow) NoHugePagesInRegion(beg, size);
|
||||
if (common_flags()->use_madv_dontdump) DontDumpShadowMemory(beg, size);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_stack.cc -----------------------------------------------------===//
|
||||
//===-- asan_stack.cpp ----------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -8,7 +8,7 @@
|
||||
//
|
||||
// This file is a part of AddressSanitizer, an address sanity checker.
|
||||
//
|
||||
// ASan-private header for asan_stack.cc.
|
||||
// ASan-private header for asan_stack.cpp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef ASAN_STACK_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_stats.cc -----------------------------------------------------===//
|
||||
//===-- asan_stats.cpp ----------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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;
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_suppressions.cc ----------------------------------------------===//
|
||||
//===-- asan_suppressions.cpp ---------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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)
|
@ -8,7 +8,7 @@
|
||||
//
|
||||
// This file is a part of AddressSanitizer, an address sanity checker.
|
||||
//
|
||||
// ASan-private header for asan_suppressions.cc.
|
||||
// ASan-private header for asan_suppressions.cpp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef ASAN_SUPPRESSIONS_H
|
||||
#define ASAN_SUPPRESSIONS_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_thread.cc ----------------------------------------------------===//
|
||||
//===-- asan_thread.cpp ---------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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
|
@ -8,7 +8,7 @@
|
||||
//
|
||||
// This file is a part of AddressSanitizer, an address sanity checker.
|
||||
//
|
||||
// ASan-private header for asan_thread.cc.
|
||||
// ASan-private header for asan_thread.cpp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef ASAN_THREAD_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_win.cc -------------------------------------------------------===//
|
||||
//===-- asan_win.cpp ------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_win_dll_thunk.cc ---------------------------------------------===//
|
||||
//===-- asan_win_dll_thunk.cpp --------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -54,7 +54,7 @@ INTERCEPT_WRAP_W_W(_expand_dbg)
|
||||
// TODO(timurrrr): Might want to add support for _aligned_* allocation
|
||||
// functions to detect a bit more bugs. Those functions seem to wrap malloc().
|
||||
|
||||
// TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cc).
|
||||
// TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cpp)
|
||||
|
||||
INTERCEPT_LIBRARY_FUNCTION(atoi);
|
||||
INTERCEPT_LIBRARY_FUNCTION(atol);
|
||||
@ -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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_win_dynamic_runtime_thunk.cc ---------------------------------===//
|
||||
//===-- asan_win_dynamic_runtime_thunk.cpp --------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -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
|
||||
@ -114,7 +114,7 @@ int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ASan SEH handling.
|
||||
// We need to set the ASan-specific SEH handler at the end of CRT initialization
|
||||
// of each module (see also asan_win.cc).
|
||||
// of each module (see also asan_win.cpp).
|
||||
extern "C" {
|
||||
__declspec(dllimport) int __asan_set_seh_filter();
|
||||
static int SetSEHFilter() { return __asan_set_seh_filter(); }
|
@ -1,4 +1,4 @@
|
||||
//===-- asan_win_weak_interception.cc -------------------------------------===//
|
||||
//===-- asan_win_weak_interception.cpp ------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -0,0 +1,59 @@
|
||||
//===----- lib/aarch64/fp_mode.c - Floaing-point mode utilities ---*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../fp_mode.h"
|
||||
|
||||
#define AARCH64_TONEAREST 0x0
|
||||
#define AARCH64_UPWARD 0x1
|
||||
#define AARCH64_DOWNWARD 0x2
|
||||
#define AARCH64_TOWARDZERO 0x3
|
||||
#define AARCH64_RMODE_MASK (AARCH64_TONEAREST | AARCH64_UPWARD | \
|
||||
AARCH64_DOWNWARD | AARCH64_TOWARDZERO)
|
||||
#define AARCH64_RMODE_SHIFT 22
|
||||
|
||||
#define AARCH64_INEXACT 0x10
|
||||
|
||||
#ifndef __ARM_FP
|
||||
// For soft float targets, allow changing rounding mode by overriding the weak
|
||||
// __aarch64_fe_default_rmode symbol.
|
||||
FE_ROUND_MODE __attribute__((weak)) __aarch64_fe_default_rmode = FE_TONEAREST;
|
||||
#endif
|
||||
|
||||
FE_ROUND_MODE __fe_getround() {
|
||||
#ifdef __ARM_FP
|
||||
uint64_t fpcr;
|
||||
__asm__ __volatile__("mrs %0, fpcr" : "=r" (fpcr));
|
||||
fpcr = fpcr >> AARCH64_RMODE_SHIFT & AARCH64_RMODE_MASK;
|
||||
switch (fpcr) {
|
||||
case AARCH64_UPWARD:
|
||||
return FE_UPWARD;
|
||||
case AARCH64_DOWNWARD:
|
||||
return FE_DOWNWARD;
|
||||
case AARCH64_TOWARDZERO:
|
||||
return FE_TOWARDZERO;
|
||||
case AARCH64_TONEAREST:
|
||||
default:
|
||||
return FE_TONEAREST;
|
||||
}
|
||||
#else
|
||||
return __aarch64_fe_default_rmode;
|
||||
#endif
|
||||
}
|
||||
|
||||
int __fe_raise_inexact() {
|
||||
#ifdef __ARM_FP
|
||||
uint64_t fpsr;
|
||||
__asm__ __volatile__("mrs %0, fpsr" : "=r" (fpsr));
|
||||
__asm__ __volatile__("msr fpsr, %0" : : "ri" (fpsr | AARCH64_INEXACT));
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
@ -6,8 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements double-precision soft-float addition with the IEEE-754
|
||||
// default rounding (to nearest, ties to even).
|
||||
// This file implements double-precision soft-float addition.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -6,8 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements single-precision soft-float addition with the IEEE-754
|
||||
// default rounding (to nearest, ties to even).
|
||||
// This file implements single-precision soft-float addition.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -6,8 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements quad-precision soft-float addition with the IEEE-754
|
||||
// default rounding (to nearest, ties to even).
|
||||
// This file implements quad-precision soft-float addition.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -17,7 +16,7 @@
|
||||
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
|
||||
#include "fp_add_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI long double __addtf3(long double a, long double b) {
|
||||
COMPILER_RT_ABI fp_t __addtf3(fp_t a, fp_t b) {
|
||||
return __addXf3__(a, b);
|
||||
}
|
||||
|
||||
|
59
contrib/llvm-project/compiler-rt/lib/builtins/arm/fp_mode.c
Normal file
59
contrib/llvm-project/compiler-rt/lib/builtins/arm/fp_mode.c
Normal file
@ -0,0 +1,59 @@
|
||||
//===----- lib/arm/fp_mode.c - Floaing-point mode utilities -------*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../fp_mode.h"
|
||||
|
||||
#define ARM_TONEAREST 0x0
|
||||
#define ARM_UPWARD 0x1
|
||||
#define ARM_DOWNWARD 0x2
|
||||
#define ARM_TOWARDZERO 0x3
|
||||
#define ARM_RMODE_MASK (ARM_TONEAREST | ARM_UPWARD | \
|
||||
ARM_DOWNWARD | ARM_TOWARDZERO)
|
||||
#define ARM_RMODE_SHIFT 22
|
||||
|
||||
#define ARM_INEXACT 0x1000
|
||||
|
||||
#ifndef __ARM_FP
|
||||
// For soft float targets, allow changing rounding mode by overriding the weak
|
||||
// __arm_fe_default_rmode symbol.
|
||||
FE_ROUND_MODE __attribute__((weak)) __arm_fe_default_rmode = FE_TONEAREST;
|
||||
#endif
|
||||
|
||||
FE_ROUND_MODE __fe_getround() {
|
||||
#ifdef __ARM_FP
|
||||
uint32_t fpscr;
|
||||
__asm__ __volatile__("vmrs %0, fpscr" : "=r" (fpscr));
|
||||
fpscr = fpscr >> ARM_RMODE_SHIFT & ARM_RMODE_MASK;
|
||||
switch (fpscr) {
|
||||
case ARM_UPWARD:
|
||||
return FE_UPWARD;
|
||||
case ARM_DOWNWARD:
|
||||
return FE_DOWNWARD;
|
||||
case ARM_TOWARDZERO:
|
||||
return FE_TOWARDZERO;
|
||||
case ARM_TONEAREST:
|
||||
default:
|
||||
return FE_TONEAREST;
|
||||
}
|
||||
#else
|
||||
return __arm_fe_default_rmode;
|
||||
#endif
|
||||
}
|
||||
|
||||
int __fe_raise_inexact() {
|
||||
#ifdef __ARM_FP
|
||||
uint32_t fpscr;
|
||||
__asm__ __volatile__("vmrs %0, fpscr" : "=r" (fpscr));
|
||||
__asm__ __volatile__("vmsr fpscr, %0" : : "ri" (fpscr | ARM_INEXACT));
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
@ -51,9 +51,11 @@ static const long SPINLOCK_MASK = SPINLOCK_COUNT - 1;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef __FreeBSD__
|
||||
#include <errno.h>
|
||||
// clang-format off
|
||||
#include <sys/types.h>
|
||||
#include <machine/atomic.h>
|
||||
#include <sys/umtx.h>
|
||||
// clang-format on
|
||||
typedef struct _usem Lock;
|
||||
__inline static void unlock(Lock *l) {
|
||||
__c11_atomic_store((_Atomic(uint32_t) *)&l->_count, 1, __ATOMIC_RELEASE);
|
||||
|
@ -23,8 +23,10 @@ uintptr_t GetCurrentProcess(void);
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) && defined(__arm__)
|
||||
#include <machine/sysarch.h>
|
||||
// clang-format off
|
||||
#include <sys/types.h>
|
||||
#include <machine/sysarch.h>
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
#if defined(__NetBSD__) && defined(__arm__)
|
||||
@ -32,54 +34,16 @@ uintptr_t GetCurrentProcess(void);
|
||||
#endif
|
||||
|
||||
#if defined(__OpenBSD__) && defined(__mips__)
|
||||
#include <machine/sysarch.h>
|
||||
// clang-format off
|
||||
#include <sys/types.h>
|
||||
#include <machine/sysarch.h>
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__mips__)
|
||||
#include <sys/cachectl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#if defined(__ANDROID__) && defined(__LP64__)
|
||||
// clear_mips_cache - Invalidates instruction cache for Mips.
|
||||
static void clear_mips_cache(const void *Addr, size_t Size) {
|
||||
__asm__ volatile(
|
||||
".set push\n"
|
||||
".set noreorder\n"
|
||||
".set noat\n"
|
||||
"beq %[Size], $zero, 20f\n" // If size == 0, branch around.
|
||||
"nop\n"
|
||||
"daddu %[Size], %[Addr], %[Size]\n" // Calculate end address + 1
|
||||
"rdhwr $v0, $1\n" // Get step size for SYNCI.
|
||||
// $1 is $HW_SYNCI_Step
|
||||
"beq $v0, $zero, 20f\n" // If no caches require
|
||||
// synchronization, branch
|
||||
// around.
|
||||
"nop\n"
|
||||
"10:\n"
|
||||
"synci 0(%[Addr])\n" // Synchronize all caches around
|
||||
// address.
|
||||
"daddu %[Addr], %[Addr], $v0\n" // Add step size.
|
||||
"sltu $at, %[Addr], %[Size]\n" // Compare current with end
|
||||
// address.
|
||||
"bne $at, $zero, 10b\n" // Branch if more to do.
|
||||
"nop\n"
|
||||
"sync\n" // Clear memory hazards.
|
||||
"20:\n"
|
||||
"bal 30f\n"
|
||||
"nop\n"
|
||||
"30:\n"
|
||||
"daddiu $ra, $ra, 12\n" // $ra has a value of $pc here.
|
||||
// Add offset of 12 to point to the
|
||||
// instruction after the last nop.
|
||||
//
|
||||
"jr.hb $ra\n" // Return, clearing instruction
|
||||
// hazards.
|
||||
"nop\n"
|
||||
".set pop\n"
|
||||
: [ Addr ] "+r"(Addr), [ Size ] "+r"(Size)::"at", "ra", "v0", "memory");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// The compiler generates calls to __clear_cache() when creating
|
||||
@ -123,17 +87,7 @@ void __clear_cache(void *start, void *end) {
|
||||
#elif defined(__linux__) && defined(__mips__)
|
||||
const uintptr_t start_int = (uintptr_t)start;
|
||||
const uintptr_t end_int = (uintptr_t)end;
|
||||
#if defined(__ANDROID__) && defined(__LP64__)
|
||||
// Call synci implementation for short address range.
|
||||
const uintptr_t address_range_limit = 256;
|
||||
if ((end_int - start_int) <= address_range_limit) {
|
||||
clear_mips_cache(start, (end_int - start_int));
|
||||
} else {
|
||||
syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE);
|
||||
}
|
||||
#else
|
||||
syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE);
|
||||
#endif
|
||||
#elif defined(__mips__) && defined(__OpenBSD__)
|
||||
cacheflush(start, (uintptr_t)end - (uintptr_t)start, BCACHE);
|
||||
#elif defined(__aarch64__) && !defined(__APPLE__)
|
||||
@ -173,6 +127,16 @@ void __clear_cache(void *start, void *end) {
|
||||
for (uintptr_t line = start_line; line < end_line; line += line_size)
|
||||
__asm__ volatile("icbi 0, %0" : : "r"(line));
|
||||
__asm__ volatile("isync");
|
||||
#elif defined(__sparc__)
|
||||
const size_t dword_size = 8;
|
||||
const size_t len = (uintptr_t)end - (uintptr_t)start;
|
||||
|
||||
const uintptr_t mask = ~(dword_size - 1);
|
||||
const uintptr_t start_dword = ((uintptr_t)start) & mask;
|
||||
const uintptr_t end_dword = ((uintptr_t)start + len + dword_size - 1) & mask;
|
||||
|
||||
for (uintptr_t dword = start_dword; dword < end_dword; dword += dword_size)
|
||||
__asm__ volatile("flush %0" : : "r"(dword));
|
||||
#else
|
||||
#if __APPLE__
|
||||
// On Darwin, sys_icache_invalidate() provides this functionality
|
||||
|
@ -121,7 +121,8 @@ enum ProcessorFeatures {
|
||||
FEATURE_GFNI,
|
||||
FEATURE_VPCLMULQDQ,
|
||||
FEATURE_AVX512VNNI,
|
||||
FEATURE_AVX512BITALG
|
||||
FEATURE_AVX512BITALG,
|
||||
FEATURE_AVX512BF16
|
||||
};
|
||||
|
||||
// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
|
||||
@ -415,8 +416,8 @@ static void getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
|
||||
|
||||
default: // Unknown family 6 CPU.
|
||||
break;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break; // Unknown.
|
||||
}
|
||||
@ -582,6 +583,11 @@ static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
|
||||
if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
|
||||
setFeature(FEATURE_AVX5124FMAPS);
|
||||
|
||||
bool HasLeaf7Subleaf1 =
|
||||
MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
|
||||
if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save)
|
||||
setFeature(FEATURE_AVX512BF16);
|
||||
|
||||
unsigned MaxExtLevel;
|
||||
getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
|
||||
|
||||
|
@ -213,7 +213,7 @@ COMPILER_RT_ABI fp_t __divtf3(fp_t a, fp_t b) {
|
||||
// Round.
|
||||
absResult += round;
|
||||
// Insert the sign and return.
|
||||
const long double result = fromRep(absResult | quotientSign);
|
||||
const fp_t result = fromRep(absResult | quotientSign);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -26,12 +26,23 @@
|
||||
#define EMUTLS_SKIP_DESTRUCTOR_ROUNDS 0
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
// MSVC raises a warning about a nonstandard extension being used for the 0
|
||||
// sized element in this array. Disable this for warn-as-error builds.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4206)
|
||||
#endif
|
||||
|
||||
typedef struct emutls_address_array {
|
||||
uintptr_t skip_destructor_rounds;
|
||||
uintptr_t size; // number of elements in the 'data' array
|
||||
void *data[];
|
||||
} emutls_address_array;
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
static void emutls_shutdown(emutls_address_array *array);
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -14,7 +14,7 @@
|
||||
#define DST_QUAD
|
||||
#include "fp_extend_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI long double __extenddftf2(double a) {
|
||||
COMPILER_RT_ABI fp_t __extenddftf2(double a) {
|
||||
return __extendXfYf2__(a);
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
#define DST_QUAD
|
||||
#include "fp_extend_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI long double __extendsftf2(float a) {
|
||||
COMPILER_RT_ABI fp_t __extendsftf2(float a) {
|
||||
return __extendXfYf2__(a);
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,13 @@
|
||||
// eeee | 1mmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm
|
||||
// mmmm mmmm mmmm
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
// MSVC throws a warning about 'unitialized variable use' here,
|
||||
// disable it for builds that warn-as-error
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4700)
|
||||
#endif
|
||||
|
||||
COMPILER_RT_ABI du_int __fixunsxfdi(long double a) {
|
||||
long_double_bits fb;
|
||||
fb.f = a;
|
||||
@ -36,4 +43,8 @@ COMPILER_RT_ABI du_int __fixunsxfdi(long double a) {
|
||||
return fb.u.low.all >> (63 - e);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif //!_ARCH_PPC
|
||||
|
@ -25,6 +25,13 @@
|
||||
// eeee | 1mmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm
|
||||
// mmmm mmmm mmmm
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
// MSVC throws a warning about 'unitialized variable use' here,
|
||||
// disable it for builds that warn-as-error
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4700)
|
||||
#endif
|
||||
|
||||
COMPILER_RT_ABI su_int __fixunsxfsi(long double a) {
|
||||
long_double_bits fb;
|
||||
fb.f = a;
|
||||
@ -36,4 +43,8 @@ COMPILER_RT_ABI su_int __fixunsxfsi(long double a) {
|
||||
return fb.u.low.s.high >> (31 - e);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // !_ARCH_PPC
|
||||
|
@ -24,6 +24,13 @@
|
||||
// eeee | 1mmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm
|
||||
// mmmm mmmm mmmm
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
// MSVC throws a warning about 'unitialized variable use' here,
|
||||
// disable it for builds that warn-as-error
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4700)
|
||||
#endif
|
||||
|
||||
COMPILER_RT_ABI di_int __fixxfdi(long double a) {
|
||||
const di_int di_max = (di_int)((~(du_int)0) / 2);
|
||||
const di_int di_min = -di_max - 1;
|
||||
@ -40,4 +47,8 @@ COMPILER_RT_ABI di_int __fixxfdi(long double a) {
|
||||
return (r ^ s) - s;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // !_ARCH_PPC
|
||||
|
@ -12,6 +12,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "fp_lib.h"
|
||||
#include "fp_mode.h"
|
||||
|
||||
static __inline fp_t __addXf3__(fp_t a, fp_t b) {
|
||||
rep_t aRep = toRep(a);
|
||||
@ -93,7 +94,7 @@ static __inline fp_t __addXf3__(fp_t a, fp_t b) {
|
||||
const unsigned int align = aExponent - bExponent;
|
||||
if (align) {
|
||||
if (align < typeWidth) {
|
||||
const bool sticky = bSignificand << (typeWidth - align);
|
||||
const bool sticky = (bSignificand << (typeWidth - align)) != 0;
|
||||
bSignificand = bSignificand >> align | sticky;
|
||||
} else {
|
||||
bSignificand = 1; // Set the sticky bit. b is known to be non-zero.
|
||||
@ -132,7 +133,7 @@ static __inline fp_t __addXf3__(fp_t a, fp_t b) {
|
||||
// The result is denormal before rounding. The exponent is zero and we
|
||||
// need to shift the significand.
|
||||
const int shift = 1 - aExponent;
|
||||
const bool sticky = aSignificand << (typeWidth - shift);
|
||||
const bool sticky = (aSignificand << (typeWidth - shift)) != 0;
|
||||
aSignificand = aSignificand >> shift | sticky;
|
||||
aExponent = 0;
|
||||
}
|
||||
@ -149,9 +150,23 @@ static __inline fp_t __addXf3__(fp_t a, fp_t b) {
|
||||
|
||||
// Perform the final rounding. The result may overflow to infinity, but
|
||||
// that is the correct result in that case.
|
||||
if (roundGuardSticky > 0x4)
|
||||
result++;
|
||||
if (roundGuardSticky == 0x4)
|
||||
result += result & 1;
|
||||
switch (__fe_getround()) {
|
||||
case FE_TONEAREST:
|
||||
if (roundGuardSticky > 0x4)
|
||||
result++;
|
||||
if (roundGuardSticky == 0x4)
|
||||
result += result & 1;
|
||||
break;
|
||||
case FE_DOWNWARD:
|
||||
if (resultSign && roundGuardSticky) result++;
|
||||
break;
|
||||
case FE_UPWARD:
|
||||
if (!resultSign && roundGuardSticky) result++;
|
||||
break;
|
||||
case FE_TOWARDZERO:
|
||||
break;
|
||||
}
|
||||
if (roundGuardSticky)
|
||||
__fe_raise_inexact();
|
||||
return fromRep(result);
|
||||
}
|
||||
|
@ -245,7 +245,7 @@ static __inline void wideLeftShift(rep_t *hi, rep_t *lo, int count) {
|
||||
static __inline void wideRightShiftWithSticky(rep_t *hi, rep_t *lo,
|
||||
unsigned int count) {
|
||||
if (count < typeWidth) {
|
||||
const bool sticky = *lo << (typeWidth - count);
|
||||
const bool sticky = (*lo << (typeWidth - count)) != 0;
|
||||
*lo = *hi << (typeWidth - count) | *lo >> count | sticky;
|
||||
*hi = *hi >> count;
|
||||
} else if (count < 2 * typeWidth) {
|
||||
|
24
contrib/llvm-project/compiler-rt/lib/builtins/fp_mode.c
Normal file
24
contrib/llvm-project/compiler-rt/lib/builtins/fp_mode.c
Normal file
@ -0,0 +1,24 @@
|
||||
//===----- lib/fp_mode.c - Floaing-point environment mode utilities --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 provides a default implementation of fp_mode.h for architectures
|
||||
// that does not support or does not have an implementation of floating point
|
||||
// environment mode.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "fp_mode.h"
|
||||
|
||||
// IEEE-754 default rounding (to nearest, ties to even).
|
||||
FE_ROUND_MODE __fe_getround() {
|
||||
return FE_TONEAREST;
|
||||
}
|
||||
|
||||
int __fe_raise_inexact() {
|
||||
return 0;
|
||||
}
|
29
contrib/llvm-project/compiler-rt/lib/builtins/fp_mode.h
Normal file
29
contrib/llvm-project/compiler-rt/lib/builtins/fp_mode.h
Normal file
@ -0,0 +1,29 @@
|
||||
//===----- lib/fp_mode.h - Floaing-point environment mode utilities --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 not part of the interface of this library.
|
||||
//
|
||||
// This file defines an interface for accessing hardware floating point
|
||||
// environment mode.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef FP_MODE
|
||||
#define FP_MODE
|
||||
|
||||
typedef enum {
|
||||
FE_TONEAREST,
|
||||
FE_DOWNWARD,
|
||||
FE_UPWARD,
|
||||
FE_TOWARDZERO
|
||||
} FE_ROUND_MODE;
|
||||
|
||||
FE_ROUND_MODE __fe_getround();
|
||||
int __fe_raise_inexact();
|
||||
|
||||
#endif // FP_MODE_H
|
@ -113,7 +113,7 @@ static __inline dst_t __truncXfYf2__(src_t a) {
|
||||
if (shift > srcSigBits) {
|
||||
absResult = 0;
|
||||
} else {
|
||||
const bool sticky = significand << (srcBits - shift);
|
||||
const bool sticky = (significand << (srcBits - shift)) != 0;
|
||||
src_rep_t denormalizedSignificand = significand >> shift | sticky;
|
||||
absResult = denormalizedSignificand >> (srcSigBits - dstSigBits);
|
||||
const src_rep_t roundBits = denormalizedSignificand & roundMask;
|
||||
|
@ -6,8 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements double-precision soft-float subtraction with the
|
||||
// IEEE-754 default rounding (to nearest, ties to even).
|
||||
// This file implements double-precision soft-float subtraction.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -6,8 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements single-precision soft-float subtraction with the
|
||||
// IEEE-754 default rounding (to nearest, ties to even).
|
||||
// This file implements single-precision soft-float subtraction.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -6,8 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements quad-precision soft-float subtraction with the
|
||||
// IEEE-754 default rounding (to nearest, ties to even).
|
||||
// This file implements quad-precision soft-float subtraction.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -17,6 +17,13 @@
|
||||
|
||||
// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
// MSVC throws a warning about mod 0 here, disable it for builds that
|
||||
// warn-as-error
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4724)
|
||||
#endif
|
||||
|
||||
COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) {
|
||||
const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
|
||||
const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT;
|
||||
@ -187,3 +194,7 @@ COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) {
|
||||
*rem = r.all;
|
||||
return q.all;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- dfsan.cc ----------------------------------------------------------===//
|
||||
//===-- dfsan.cpp ---------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -1,4 +1,4 @@
|
||||
//===-- dfsan.cc ----------------------------------------------------------===//
|
||||
//===-- dfsan.cpp ---------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -505,7 +505,7 @@ int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label,
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label,
|
||||
dfsan_label src_label, dfsan_label *ret_label) {
|
||||
char *ret = strcpy(dest, src);
|
||||
char *ret = strcpy(dest, src); // NOLINT
|
||||
if (ret) {
|
||||
internal_memcpy(shadow_for(dest), shadow_for(src),
|
||||
sizeof(dfsan_label) * (strlen(src) + 1));
|
@ -1,4 +1,4 @@
|
||||
//===-- dfsan_interceptors.cc ---------------------------------------------===//
|
||||
//===-- dfsan_interceptors.cpp --------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
@ -15,9 +15,6 @@
|
||||
#include "FuzzerDefs.h"
|
||||
|
||||
#if LIBFUZZER_MSVC
|
||||
#if !defined(_M_ARM) && !defined(_M_X64)
|
||||
#error "_BitScanReverse64 unavailable on this platform so MSVC is unsupported."
|
||||
#endif
|
||||
#include <intrin.h>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
@ -40,7 +37,18 @@ inline uint64_t Bswap(uint64_t x) { return _byteswap_uint64(x); }
|
||||
// outside of Windows.
|
||||
inline uint32_t Clzll(uint64_t X) {
|
||||
unsigned long LeadZeroIdx = 0;
|
||||
|
||||
#if !defined(_M_ARM) && !defined(_M_X64)
|
||||
// Scan the high 32 bits.
|
||||
if (_BitScanReverse(&LeadZeroIdx, static_cast<unsigned long>(X >> 32)))
|
||||
return static_cast<int>(63 - (LeadZeroIdx + 32)); // Create a bit offset from the MSB.
|
||||
// Scan the low 32 bits.
|
||||
if (_BitScanReverse(&LeadZeroIdx, static_cast<unsigned long>(X)))
|
||||
return static_cast<int>(63 - LeadZeroIdx);
|
||||
|
||||
#else
|
||||
if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx;
|
||||
#endif
|
||||
return 64;
|
||||
}
|
||||
|
||||
@ -50,7 +58,13 @@ inline uint32_t Clz(uint32_t X) {
|
||||
return 32;
|
||||
}
|
||||
|
||||
inline int Popcountll(unsigned long long X) { return __popcnt64(X); }
|
||||
inline int Popcountll(unsigned long long X) {
|
||||
#if !defined(_M_ARM) && !defined(_M_X64)
|
||||
return __popcnt(X) + __popcnt(X >> 32);
|
||||
#else
|
||||
return __popcnt64(X);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace fuzzer
|
||||
|
||||
|
@ -15,10 +15,11 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
|
||||
|
||||
// Platform detection.
|
||||
#ifdef __linux__
|
||||
|
@ -708,7 +708,6 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
|
||||
Options.FeaturesDir = Flags.features_dir;
|
||||
if (Flags.collect_data_flow)
|
||||
Options.CollectDataFlow = Flags.collect_data_flow;
|
||||
Options.LazyCounters = Flags.lazy_counters;
|
||||
if (Flags.stop_file)
|
||||
Options.StopFile = Flags.stop_file;
|
||||
|
||||
|
@ -16,12 +16,12 @@
|
||||
// Optional user functions
|
||||
EXT_FUNC(LLVMFuzzerInitialize, int, (int *argc, char ***argv), false);
|
||||
EXT_FUNC(LLVMFuzzerCustomMutator, size_t,
|
||||
(uint8_t * Data, size_t Size, size_t MaxSize, unsigned int Seed),
|
||||
(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed),
|
||||
false);
|
||||
EXT_FUNC(LLVMFuzzerCustomCrossOver, size_t,
|
||||
(const uint8_t * Data1, size_t Size1,
|
||||
const uint8_t * Data2, size_t Size2,
|
||||
uint8_t * Out, size_t MaxOutSize, unsigned int Seed),
|
||||
(const uint8_t *Data1, size_t Size1,
|
||||
const uint8_t *Data2, size_t Size2,
|
||||
uint8_t *Out, size_t MaxOutSize, unsigned int Seed),
|
||||
false);
|
||||
|
||||
// Sanitizer functions
|
||||
@ -33,8 +33,9 @@ EXT_FUNC(__sanitizer_install_malloc_and_free_hooks, int,
|
||||
(void (*malloc_hook)(const volatile void *, size_t),
|
||||
void (*free_hook)(const volatile void *)),
|
||||
false);
|
||||
EXT_FUNC(__sanitizer_log_write, void, (const char *buf, size_t len), false);
|
||||
EXT_FUNC(__sanitizer_purge_allocator, void, (), false);
|
||||
EXT_FUNC(__sanitizer_print_memory_profile, int, (size_t, size_t), false);
|
||||
EXT_FUNC(__sanitizer_print_memory_profile, void, (size_t, size_t), false);
|
||||
EXT_FUNC(__sanitizer_print_stack_trace, void, (), true);
|
||||
EXT_FUNC(__sanitizer_symbolize_pc, void,
|
||||
(void *, const char *fmt, char *out_buf, size_t out_buf_size), false);
|
||||
|
@ -123,9 +123,6 @@ FUZZER_FLAG_INT(handle_term, 1, "If 1, try to intercept SIGTERM.")
|
||||
FUZZER_FLAG_INT(handle_xfsz, 1, "If 1, try to intercept SIGXFSZ.")
|
||||
FUZZER_FLAG_INT(handle_usr1, 1, "If 1, try to intercept SIGUSR1.")
|
||||
FUZZER_FLAG_INT(handle_usr2, 1, "If 1, try to intercept SIGUSR2.")
|
||||
FUZZER_FLAG_INT(lazy_counters, 0, "If 1, a performance optimization is"
|
||||
"enabled for the 8bit inline counters. "
|
||||
"Requires that libFuzzer successfully installs its SEGV handler")
|
||||
FUZZER_FLAG_INT(close_fd_mask, 0, "If 1, close stdout at startup; "
|
||||
"if 2, close stderr; if 3, close both. "
|
||||
"Be careful, this will also close e.g. stderr of asan.")
|
||||
|
@ -98,7 +98,8 @@ class Fuzzer {
|
||||
void ReportNewCoverage(InputInfo *II, const Unit &U);
|
||||
void PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size);
|
||||
void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix);
|
||||
void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0);
|
||||
void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0,
|
||||
size_t Features = 0);
|
||||
void PrintStatusForNewUnit(const Unit &U, const char *Text);
|
||||
void CheckExitOnSrcPosOrItem();
|
||||
|
||||
|
@ -273,9 +273,9 @@ void Fuzzer::InterruptCallback() {
|
||||
NO_SANITIZE_MEMORY
|
||||
void Fuzzer::AlarmCallback() {
|
||||
assert(Options.UnitTimeoutSec > 0);
|
||||
// In Windows Alarm callback is executed by a different thread.
|
||||
// In Windows and Fuchsia, Alarm callback is executed by a different thread.
|
||||
// NetBSD's current behavior needs this change too.
|
||||
#if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD
|
||||
#if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD && !LIBFUZZER_FUCHSIA
|
||||
if (!InFuzzingThread())
|
||||
return;
|
||||
#endif
|
||||
@ -319,14 +319,15 @@ void Fuzzer::RssLimitCallback() {
|
||||
_Exit(Options.OOMExitCode); // Stop right now.
|
||||
}
|
||||
|
||||
void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) {
|
||||
void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units,
|
||||
size_t Features) {
|
||||
size_t ExecPerSec = execPerSec();
|
||||
if (!Options.Verbosity)
|
||||
return;
|
||||
Printf("#%zd\t%s", TotalNumberOfRuns, Where);
|
||||
if (size_t N = TPC.GetTotalPCCoverage())
|
||||
Printf(" cov: %zd", N);
|
||||
if (size_t N = Corpus.NumFeatures())
|
||||
if (size_t N = Features ? Features : Corpus.NumFeatures())
|
||||
Printf(" ft: %zd", N);
|
||||
if (!Corpus.empty()) {
|
||||
Printf(" corp: %zd", Corpus.NumActiveUnits());
|
||||
@ -512,10 +513,12 @@ size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
|
||||
}
|
||||
|
||||
void Fuzzer::CrashOnOverwrittenData() {
|
||||
Printf("==%d== ERROR: libFuzzer: fuzz target overwrites it's const input\n",
|
||||
Printf("==%d== ERROR: libFuzzer: fuzz target overwrites its const input\n",
|
||||
GetPid());
|
||||
PrintStackTrace();
|
||||
Printf("SUMMARY: libFuzzer: overwrites-const-input\n");
|
||||
DumpCurrentUnit("crash-");
|
||||
Printf("SUMMARY: libFuzzer: out-of-memory\n");
|
||||
PrintFinalStats();
|
||||
_Exit(Options.ErrorExitCode); // Stop right now.
|
||||
}
|
||||
|
||||
@ -739,10 +742,6 @@ void Fuzzer::ReadAndExecuteSeedCorpora(Vector<SizedFile> &CorporaFiles) {
|
||||
uint8_t dummy = 0;
|
||||
ExecuteCallback(&dummy, 0);
|
||||
|
||||
// Protect lazy counters here, after the once-init code has been executed.
|
||||
if (Options.LazyCounters)
|
||||
TPC.ProtectLazyCounters();
|
||||
|
||||
if (CorporaFiles.empty()) {
|
||||
Printf("INFO: A corpus is not provided, starting from an empty corpus\n");
|
||||
Unit U({'\n'}); // Valid ASCII input.
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace fuzzer {
|
||||
|
||||
@ -210,6 +211,9 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) {
|
||||
|
||||
std::ofstream OF(CFPath, std::ofstream::out | std::ofstream::app);
|
||||
Set<size_t> AllFeatures;
|
||||
auto PrintStatsWrapper = [this, &AllFeatures](const char* Where) {
|
||||
this->PrintStats(Where, "\n", 0, AllFeatures.size());
|
||||
};
|
||||
Set<const TracePC::PCTableEntry *> AllPCs;
|
||||
for (size_t i = M.FirstNotProcessedFile; i < M.Files.size(); i++) {
|
||||
Fuzzer::MaybeExitGracefully();
|
||||
@ -218,7 +222,7 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) {
|
||||
U.resize(MaxInputLen);
|
||||
U.shrink_to_fit();
|
||||
}
|
||||
std::ostringstream StartedLine;
|
||||
|
||||
// Write the pre-run marker.
|
||||
OF << "STARTED " << i << " " << U.size() << "\n";
|
||||
OF.flush(); // Flush is important since Command::Execute may crash.
|
||||
@ -238,7 +242,9 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) {
|
||||
TPC.UpdateObservedPCs();
|
||||
// Show stats.
|
||||
if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)))
|
||||
PrintStats("pulse ");
|
||||
PrintStatsWrapper("pulse ");
|
||||
if (TotalNumberOfRuns == M.NumFilesInFirstCorpus)
|
||||
PrintStatsWrapper("LOADED");
|
||||
// Write the post-run marker and the coverage.
|
||||
OF << "FT " << i;
|
||||
for (size_t F : UniqFeatures)
|
||||
@ -252,25 +258,42 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) {
|
||||
OF << "\n";
|
||||
OF.flush();
|
||||
}
|
||||
PrintStats("DONE ");
|
||||
PrintStatsWrapper("DONE ");
|
||||
}
|
||||
|
||||
static void WriteNewControlFile(const std::string &CFPath,
|
||||
const Vector<SizedFile> &OldCorpus,
|
||||
const Vector<SizedFile> &NewCorpus) {
|
||||
static size_t WriteNewControlFile(const std::string &CFPath,
|
||||
const Vector<SizedFile> &OldCorpus,
|
||||
const Vector<SizedFile> &NewCorpus,
|
||||
const Vector<MergeFileInfo> &KnownFiles) {
|
||||
std::unordered_set<std::string> FilesToSkip;
|
||||
for (auto &SF: KnownFiles)
|
||||
FilesToSkip.insert(SF.Name);
|
||||
|
||||
Vector<std::string> FilesToUse;
|
||||
auto MaybeUseFile = [=, &FilesToUse](std::string Name) {
|
||||
if (FilesToSkip.find(Name) == FilesToSkip.end())
|
||||
FilesToUse.push_back(Name);
|
||||
};
|
||||
for (auto &SF: OldCorpus)
|
||||
MaybeUseFile(SF.File);
|
||||
auto FilesToUseFromOldCorpus = FilesToUse.size();
|
||||
for (auto &SF: NewCorpus)
|
||||
MaybeUseFile(SF.File);
|
||||
|
||||
RemoveFile(CFPath);
|
||||
std::ofstream ControlFile(CFPath);
|
||||
ControlFile << (OldCorpus.size() + NewCorpus.size()) << "\n";
|
||||
ControlFile << OldCorpus.size() << "\n";
|
||||
for (auto &SF: OldCorpus)
|
||||
ControlFile << SF.File << "\n";
|
||||
for (auto &SF: NewCorpus)
|
||||
ControlFile << SF.File << "\n";
|
||||
ControlFile << FilesToUse.size() << "\n";
|
||||
ControlFile << FilesToUseFromOldCorpus << "\n";
|
||||
for (auto &FN: FilesToUse)
|
||||
ControlFile << FN << "\n";
|
||||
|
||||
if (!ControlFile) {
|
||||
Printf("MERGE-OUTER: failed to write to the control file: %s\n",
|
||||
CFPath.c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return FilesToUse.size();
|
||||
}
|
||||
|
||||
// Outer process. Does not call the target code and thus should not fail.
|
||||
@ -286,12 +309,13 @@ void CrashResistantMerge(const Vector<std::string> &Args,
|
||||
bool V /*Verbose*/) {
|
||||
if (NewCorpus.empty() && OldCorpus.empty()) return; // Nothing to merge.
|
||||
size_t NumAttempts = 0;
|
||||
Vector<MergeFileInfo> KnownFiles;
|
||||
if (FileSize(CFPath)) {
|
||||
VPrintf(V, "MERGE-OUTER: non-empty control file provided: '%s'\n",
|
||||
CFPath.c_str());
|
||||
Merger M;
|
||||
std::ifstream IF(CFPath);
|
||||
if (M.Parse(IF, /*ParseCoverage=*/false)) {
|
||||
if (M.Parse(IF, /*ParseCoverage=*/true)) {
|
||||
VPrintf(V, "MERGE-OUTER: control file ok, %zd files total,"
|
||||
" first not processed file %zd\n",
|
||||
M.Files.size(), M.FirstNotProcessedFile);
|
||||
@ -300,12 +324,25 @@ void CrashResistantMerge(const Vector<std::string> &Args,
|
||||
"(merge has stumbled on it the last time)\n",
|
||||
M.LastFailure.c_str());
|
||||
if (M.FirstNotProcessedFile >= M.Files.size()) {
|
||||
VPrintf(
|
||||
V, "MERGE-OUTER: nothing to do, merge has been completed before\n");
|
||||
exit(0);
|
||||
}
|
||||
// Merge has already been completed with the given merge control file.
|
||||
if (M.Files.size() == OldCorpus.size() + NewCorpus.size()) {
|
||||
VPrintf(
|
||||
V,
|
||||
"MERGE-OUTER: nothing to do, merge has been completed before\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
NumAttempts = M.Files.size() - M.FirstNotProcessedFile;
|
||||
// Number of input files likely changed, start merge from scratch, but
|
||||
// reuse coverage information from the given merge control file.
|
||||
VPrintf(
|
||||
V,
|
||||
"MERGE-OUTER: starting merge from scratch, but reusing coverage "
|
||||
"information from the given control file\n");
|
||||
KnownFiles = M.Files;
|
||||
} else {
|
||||
// There is a merge in progress, continue.
|
||||
NumAttempts = M.Files.size() - M.FirstNotProcessedFile;
|
||||
}
|
||||
} else {
|
||||
VPrintf(V, "MERGE-OUTER: bad control file, will overwrite it\n");
|
||||
}
|
||||
@ -313,10 +350,11 @@ void CrashResistantMerge(const Vector<std::string> &Args,
|
||||
|
||||
if (!NumAttempts) {
|
||||
// The supplied control file is empty or bad, create a fresh one.
|
||||
NumAttempts = OldCorpus.size() + NewCorpus.size();
|
||||
VPrintf(V, "MERGE-OUTER: %zd files, %zd in the initial corpus\n",
|
||||
NumAttempts, OldCorpus.size());
|
||||
WriteNewControlFile(CFPath, OldCorpus, NewCorpus);
|
||||
VPrintf(V, "MERGE-OUTER: "
|
||||
"%zd files, %zd in the initial corpus, %zd processed earlier\n",
|
||||
OldCorpus.size() + NewCorpus.size(), OldCorpus.size(),
|
||||
KnownFiles.size());
|
||||
NumAttempts = WriteNewControlFile(CFPath, OldCorpus, NewCorpus, KnownFiles);
|
||||
}
|
||||
|
||||
// Execute the inner process until it passes.
|
||||
@ -353,6 +391,8 @@ void CrashResistantMerge(const Vector<std::string> &Args,
|
||||
VPrintf(V,
|
||||
"MERGE-OUTER: consumed %zdMb (%zdMb rss) to parse the control file\n",
|
||||
M.ApproximateMemoryConsumption() >> 20, GetPeakRSSMb());
|
||||
|
||||
M.Files.insert(M.Files.end(), KnownFiles.begin(), KnownFiles.end());
|
||||
M.Merge(InitialFeatures, NewFeatures, InitialCov, NewCov, NewFiles);
|
||||
VPrintf(V, "MERGE-OUTER: %zd new files with %zd new features added; "
|
||||
"%zd new coverage edges\n",
|
||||
|
@ -75,7 +75,6 @@ struct FuzzingOptions {
|
||||
bool HandleXfsz = false;
|
||||
bool HandleUsr1 = false;
|
||||
bool HandleUsr2 = false;
|
||||
bool LazyCounters = false;
|
||||
};
|
||||
|
||||
} // namespace fuzzer
|
||||
|
@ -67,45 +67,6 @@ void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) {
|
||||
NumInline8bitCounters += M.Size();
|
||||
}
|
||||
|
||||
// Mark all full page counter regions as PROT_NONE and set Enabled=false.
|
||||
// The first time the instrumented code hits such a protected/disabled
|
||||
// counter region we should catch a SEGV and call UnprotectLazyCounters,
|
||||
// which will mark the page as PROT_READ|PROT_WRITE and set Enabled=true.
|
||||
//
|
||||
// Whenever other functions iterate over the counters they should ignore
|
||||
// regions with Enabled=false.
|
||||
void TracePC::ProtectLazyCounters() {
|
||||
size_t NumPagesProtected = 0;
|
||||
IterateCounterRegions([&](Module::Region &R) {
|
||||
if (!R.OneFullPage) return;
|
||||
if (Mprotect(R.Start, R.Stop - R.Start, false)) {
|
||||
R.Enabled = false;
|
||||
NumPagesProtected++;
|
||||
}
|
||||
});
|
||||
if (NumPagesProtected)
|
||||
Printf("INFO: %zd pages of counters where protected;"
|
||||
" libFuzzer's SEGV handler must be installed\n",
|
||||
NumPagesProtected);
|
||||
}
|
||||
|
||||
bool TracePC::UnprotectLazyCounters(void *CounterPtr) {
|
||||
// Printf("UnprotectLazyCounters: %p\n", CounterPtr);
|
||||
if (!CounterPtr)
|
||||
return false;
|
||||
bool Done = false;
|
||||
uint8_t *Addr = reinterpret_cast<uint8_t *>(CounterPtr);
|
||||
IterateCounterRegions([&](Module::Region &R) {
|
||||
if (!R.OneFullPage || R.Enabled || Done) return;
|
||||
if (Addr >= R.Start && Addr < R.Stop)
|
||||
if (Mprotect(R.Start, R.Stop - R.Start, true)) {
|
||||
R.Enabled = true;
|
||||
Done = true;
|
||||
}
|
||||
});
|
||||
return Done;
|
||||
}
|
||||
|
||||
void TracePC::HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop) {
|
||||
const PCTableEntry *B = reinterpret_cast<const PCTableEntry *>(Start);
|
||||
const PCTableEntry *E = reinterpret_cast<const PCTableEntry *>(Stop);
|
||||
@ -173,7 +134,7 @@ inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {
|
||||
}
|
||||
|
||||
/// \return the address of the next instruction.
|
||||
/// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.cc`
|
||||
/// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.cpp`
|
||||
ALWAYS_INLINE uintptr_t TracePC::GetNextInstructionPc(uintptr_t PC) {
|
||||
#if defined(__mips__)
|
||||
return PC + 8;
|
||||
|
@ -119,9 +119,6 @@ class TracePC {
|
||||
void SetFocusFunction(const std::string &FuncName);
|
||||
bool ObservedFocusFunction();
|
||||
|
||||
void ProtectLazyCounters();
|
||||
bool UnprotectLazyCounters(void *CounterPtr);
|
||||
|
||||
struct PCTableEntry {
|
||||
uintptr_t PC, PCFlags;
|
||||
};
|
||||
|
@ -52,8 +52,6 @@ void SetSignalHandler(const FuzzingOptions& Options);
|
||||
|
||||
void SleepSeconds(int Seconds);
|
||||
|
||||
bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite);
|
||||
|
||||
unsigned long GetPid();
|
||||
|
||||
size_t GetPeakRSSMb();
|
||||
|
@ -305,12 +305,19 @@ void CrashHandler(zx_handle_t *Event) {
|
||||
|
||||
} // namespace
|
||||
|
||||
bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) {
|
||||
return false; // UNIMPLEMENTED
|
||||
}
|
||||
|
||||
// Platform specific functions.
|
||||
void SetSignalHandler(const FuzzingOptions &Options) {
|
||||
// Make sure information from libFuzzer and the sanitizers are easy to
|
||||
// reassemble. `__sanitizer_log_write` has the added benefit of ensuring the
|
||||
// DSO map is always available for the symbolizer.
|
||||
// A uint64_t fits in 20 chars, so 64 is plenty.
|
||||
char Buf[64];
|
||||
memset(Buf, 0, sizeof(Buf));
|
||||
snprintf(Buf, sizeof(Buf), "==%lu== INFO: libFuzzer starting.\n", GetPid());
|
||||
if (EF->__sanitizer_log_write)
|
||||
__sanitizer_log_write(Buf, sizeof(Buf));
|
||||
Printf("%s", Buf);
|
||||
|
||||
// Set up alarm handler if needed.
|
||||
if (Options.UnitTimeoutSec > 0) {
|
||||
std::thread T(AlarmHandler, Options.UnitTimeoutSec / 2 + 1);
|
||||
@ -400,13 +407,14 @@ int ExecuteCommand(const Command &Cmd) {
|
||||
// that lacks a mutable working directory. Fortunately, when this is the case
|
||||
// a mutable output directory must be specified using "-artifact_prefix=...",
|
||||
// so write the log file(s) there.
|
||||
// However, we don't want to apply this logic for absolute paths.
|
||||
int FdOut = STDOUT_FILENO;
|
||||
if (Cmd.hasOutputFile()) {
|
||||
std::string Path;
|
||||
if (Cmd.hasFlag("artifact_prefix"))
|
||||
Path = Cmd.getFlagValue("artifact_prefix") + "/" + Cmd.getOutputFile();
|
||||
else
|
||||
Path = Cmd.getOutputFile();
|
||||
std::string Path = Cmd.getOutputFile();
|
||||
bool IsAbsolutePath = Path.length() > 1 && Path[0] == '/';
|
||||
if (!IsAbsolutePath && Cmd.hasFlag("artifact_prefix"))
|
||||
Path = Cmd.getFlagValue("artifact_prefix") + "/" + Path;
|
||||
|
||||
FdOut = open(Path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0);
|
||||
if (FdOut == -1) {
|
||||
Printf("libFuzzer: failed to open %s: %s\n", Path.c_str(),
|
||||
|
@ -37,7 +37,6 @@ static void (*upstream_segv_handler)(int, siginfo_t *, void *);
|
||||
|
||||
static void SegvHandler(int sig, siginfo_t *si, void *ucontext) {
|
||||
assert(si->si_signo == SIGSEGV);
|
||||
if (TPC.UnprotectLazyCounters(si->si_addr)) return;
|
||||
if (upstream_segv_handler)
|
||||
return upstream_segv_handler(sig, si, ucontext);
|
||||
Fuzzer::StaticCrashSignalCallback();
|
||||
@ -98,11 +97,6 @@ void SetTimer(int Seconds) {
|
||||
SetSigaction(SIGALRM, AlarmHandler);
|
||||
}
|
||||
|
||||
bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) {
|
||||
return 0 == mprotect(Ptr, Size,
|
||||
AllowReadWrite ? (PROT_READ | PROT_WRITE) : PROT_NONE);
|
||||
}
|
||||
|
||||
void SetSignalHandler(const FuzzingOptions& Options) {
|
||||
if (Options.UnitTimeoutSec > 0)
|
||||
SetTimer(Options.UnitTimeoutSec / 2 + 1);
|
||||
|
@ -111,10 +111,6 @@ static TimerQ Timer;
|
||||
|
||||
static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }
|
||||
|
||||
bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) {
|
||||
return false; // UNIMPLEMENTED
|
||||
}
|
||||
|
||||
void SetSignalHandler(const FuzzingOptions& Options) {
|
||||
HandlerOpt = &Options;
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
// RHEL creates the PRIu64 format macro (for printing uint64_t's) only when this
|
||||
// macro is defined before including <inttypes.h>.
|
||||
#ifndef __STDC_FORMAT_MACROS
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
@ -44,11 +44,12 @@ class ScopedBoolean {
|
||||
bool &Bool;
|
||||
};
|
||||
|
||||
void defaultPrintStackTrace(uintptr_t *Trace, options::Printf_t Printf) {
|
||||
if (Trace[0] == 0)
|
||||
void defaultPrintStackTrace(uintptr_t *Trace, size_t TraceLength,
|
||||
options::Printf_t Printf) {
|
||||
if (TraceLength == 0)
|
||||
Printf(" <unknown (does your allocator support backtracing?)>\n");
|
||||
|
||||
for (size_t i = 0; Trace[i] != 0; ++i) {
|
||||
for (size_t i = 0; i < TraceLength; ++i) {
|
||||
Printf(" #%zu 0x%zx in <unknown>\n", i, Trace[i]);
|
||||
}
|
||||
Printf("\n");
|
||||
@ -68,12 +69,18 @@ void GuardedPoolAllocator::AllocationMetadata::RecordAllocation(
|
||||
// TODO(hctim): Ask the caller to provide the thread ID, so we don't waste
|
||||
// other thread's time getting the thread ID under lock.
|
||||
AllocationTrace.ThreadID = getThreadID();
|
||||
AllocationTrace.TraceSize = 0;
|
||||
DeallocationTrace.TraceSize = 0;
|
||||
DeallocationTrace.ThreadID = kInvalidThreadID;
|
||||
if (Backtrace)
|
||||
Backtrace(AllocationTrace.Trace, kMaximumStackFrames);
|
||||
else
|
||||
AllocationTrace.Trace[0] = 0;
|
||||
DeallocationTrace.Trace[0] = 0;
|
||||
|
||||
if (Backtrace) {
|
||||
uintptr_t UncompressedBuffer[kMaxTraceLengthToCollect];
|
||||
size_t BacktraceLength =
|
||||
Backtrace(UncompressedBuffer, kMaxTraceLengthToCollect);
|
||||
AllocationTrace.TraceSize = compression::pack(
|
||||
UncompressedBuffer, BacktraceLength, AllocationTrace.CompressedTrace,
|
||||
kStackFrameStorageBytes);
|
||||
}
|
||||
}
|
||||
|
||||
void GuardedPoolAllocator::AllocationMetadata::RecordDeallocation(
|
||||
@ -81,11 +88,16 @@ void GuardedPoolAllocator::AllocationMetadata::RecordDeallocation(
|
||||
IsDeallocated = true;
|
||||
// Ensure that the unwinder is not called if the recursive flag is set,
|
||||
// otherwise non-reentrant unwinders may deadlock.
|
||||
DeallocationTrace.TraceSize = 0;
|
||||
if (Backtrace && !ThreadLocals.RecursiveGuard) {
|
||||
ScopedBoolean B(ThreadLocals.RecursiveGuard);
|
||||
Backtrace(DeallocationTrace.Trace, kMaximumStackFrames);
|
||||
} else {
|
||||
DeallocationTrace.Trace[0] = 0;
|
||||
|
||||
uintptr_t UncompressedBuffer[kMaxTraceLengthToCollect];
|
||||
size_t BacktraceLength =
|
||||
Backtrace(UncompressedBuffer, kMaxTraceLengthToCollect);
|
||||
DeallocationTrace.TraceSize = compression::pack(
|
||||
UncompressedBuffer, BacktraceLength, DeallocationTrace.CompressedTrace,
|
||||
kStackFrameStorageBytes);
|
||||
}
|
||||
DeallocationTrace.ThreadID = getThreadID();
|
||||
}
|
||||
@ -161,7 +173,7 @@ void GuardedPoolAllocator::init(const options::Options &Opts) {
|
||||
|
||||
// Ensure that signal handlers are installed as late as possible, as the class
|
||||
// is not thread-safe until init() is finished, and thus a SIGSEGV may cause a
|
||||
// race to members if recieved during init().
|
||||
// race to members if received during init().
|
||||
if (Opts.InstallSignalHandlers)
|
||||
installSignalHandlers();
|
||||
}
|
||||
@ -373,7 +385,7 @@ void printErrorType(Error E, uintptr_t AccessPtr, AllocationMetadata *Meta,
|
||||
case Error::UNKNOWN:
|
||||
ErrorString = "GWP-ASan couldn't automatically determine the source of "
|
||||
"the memory error. It was likely caused by a wild memory "
|
||||
"access into the GWP-ASan pool. The error occured";
|
||||
"access into the GWP-ASan pool. The error occurred";
|
||||
break;
|
||||
case Error::USE_AFTER_FREE:
|
||||
ErrorString = "Use after free";
|
||||
@ -442,7 +454,13 @@ void printAllocDeallocTraces(uintptr_t AccessPtr, AllocationMetadata *Meta,
|
||||
Printf("0x%zx was deallocated by thread %zu here:\n", AccessPtr,
|
||||
Meta->DeallocationTrace.ThreadID);
|
||||
|
||||
PrintBacktrace(Meta->DeallocationTrace.Trace, Printf);
|
||||
uintptr_t UncompressedTrace[AllocationMetadata::kMaxTraceLengthToCollect];
|
||||
size_t UncompressedLength = compression::unpack(
|
||||
Meta->DeallocationTrace.CompressedTrace,
|
||||
Meta->DeallocationTrace.TraceSize, UncompressedTrace,
|
||||
AllocationMetadata::kMaxTraceLengthToCollect);
|
||||
|
||||
PrintBacktrace(UncompressedTrace, UncompressedLength, Printf);
|
||||
}
|
||||
|
||||
if (Meta->AllocationTrace.ThreadID == GuardedPoolAllocator::kInvalidThreadID)
|
||||
@ -451,7 +469,12 @@ void printAllocDeallocTraces(uintptr_t AccessPtr, AllocationMetadata *Meta,
|
||||
Printf("0x%zx was allocated by thread %zu here:\n", Meta->Addr,
|
||||
Meta->AllocationTrace.ThreadID);
|
||||
|
||||
PrintBacktrace(Meta->AllocationTrace.Trace, Printf);
|
||||
uintptr_t UncompressedTrace[AllocationMetadata::kMaxTraceLengthToCollect];
|
||||
size_t UncompressedLength = compression::unpack(
|
||||
Meta->AllocationTrace.CompressedTrace, Meta->AllocationTrace.TraceSize,
|
||||
UncompressedTrace, AllocationMetadata::kMaxTraceLengthToCollect);
|
||||
|
||||
PrintBacktrace(UncompressedTrace, UncompressedLength, Printf);
|
||||
}
|
||||
|
||||
struct ScopedEndOfReportDecorator {
|
||||
@ -491,11 +514,11 @@ void GuardedPoolAllocator::reportErrorInternal(uintptr_t AccessPtr, Error E) {
|
||||
uint64_t ThreadID = getThreadID();
|
||||
printErrorType(E, AccessPtr, Meta, Printf, ThreadID);
|
||||
if (Backtrace) {
|
||||
static constexpr unsigned kMaximumStackFramesForCrashTrace = 128;
|
||||
static constexpr unsigned kMaximumStackFramesForCrashTrace = 512;
|
||||
uintptr_t Trace[kMaximumStackFramesForCrashTrace];
|
||||
Backtrace(Trace, kMaximumStackFramesForCrashTrace);
|
||||
size_t TraceLength = Backtrace(Trace, kMaximumStackFramesForCrashTrace);
|
||||
|
||||
PrintBacktrace(Trace, Printf);
|
||||
PrintBacktrace(Trace, TraceLength, Printf);
|
||||
} else {
|
||||
Printf(" <unknown (does your allocator support backtracing?)>\n\n");
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "gwp_asan/mutex.h"
|
||||
#include "gwp_asan/options.h"
|
||||
#include "gwp_asan/random.h"
|
||||
#include "gwp_asan/stack_trace_compressor.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
@ -39,9 +40,15 @@ class GuardedPoolAllocator {
|
||||
};
|
||||
|
||||
struct AllocationMetadata {
|
||||
// Maximum number of stack trace frames to collect for allocations + frees.
|
||||
// TODO(hctim): Implement stack frame compression, a-la Chromium.
|
||||
static constexpr size_t kMaximumStackFrames = 64;
|
||||
// The number of bytes used to store a compressed stack frame. On 64-bit
|
||||
// platforms, assuming a compression ratio of 50%, this should allow us to
|
||||
// store ~64 frames per trace.
|
||||
static constexpr size_t kStackFrameStorageBytes = 256;
|
||||
|
||||
// Maximum number of stack frames to collect on allocation/deallocation. The
|
||||
// actual number of collected frames may be less than this as the stack
|
||||
// frames are compressed into a fixed memory range.
|
||||
static constexpr size_t kMaxTraceLengthToCollect = 128;
|
||||
|
||||
// Records the given allocation metadata into this struct.
|
||||
void RecordAllocation(uintptr_t Addr, size_t Size,
|
||||
@ -51,11 +58,13 @@ class GuardedPoolAllocator {
|
||||
void RecordDeallocation(options::Backtrace_t Backtrace);
|
||||
|
||||
struct CallSiteInfo {
|
||||
// The backtrace to the allocation/deallocation. If the first value is
|
||||
// zero, we did not collect a trace.
|
||||
uintptr_t Trace[kMaximumStackFrames] = {};
|
||||
// The compressed backtrace to the allocation/deallocation.
|
||||
uint8_t CompressedTrace[kStackFrameStorageBytes];
|
||||
// The thread ID for this trace, or kInvalidThreadID if not available.
|
||||
uint64_t ThreadID = kInvalidThreadID;
|
||||
// The size of the compressed trace (in bytes). Zero indicates that no
|
||||
// trace was collected.
|
||||
size_t TraceSize = 0;
|
||||
};
|
||||
|
||||
// The address of this allocation.
|
||||
|
@ -14,7 +14,12 @@
|
||||
namespace gwp_asan {
|
||||
namespace options {
|
||||
// Functions to get the platform-specific and implementation-specific backtrace
|
||||
// and backtrace printing functions.
|
||||
// and backtrace printing functions when RTGwpAsanBacktraceLibc or
|
||||
// RTGwpAsanBacktraceSanitizerCommon are linked. Use these functions to get the
|
||||
// backtrace function for populating the Options::Backtrace and
|
||||
// Options::PrintBacktrace when initialising the GuardedPoolAllocator. Please
|
||||
// note any thread-safety descriptions for the implementation of these functions
|
||||
// that you use.
|
||||
Backtrace_t getBacktraceFunction();
|
||||
PrintBacktrace_t getPrintBacktraceFunction();
|
||||
} // namespace options
|
||||
|
@ -17,33 +17,23 @@
|
||||
#include "gwp_asan/options.h"
|
||||
|
||||
namespace {
|
||||
void Backtrace(uintptr_t *TraceBuffer, size_t Size) {
|
||||
// Grab (what seems to be) one more trace than we need. TraceBuffer needs to
|
||||
// be null-terminated, but we wish to remove the frame of this function call.
|
||||
size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) {
|
||||
static_assert(sizeof(uintptr_t) == sizeof(void *), "uintptr_t is not void*");
|
||||
int NumTraces =
|
||||
backtrace(reinterpret_cast<void **>(TraceBuffer), Size);
|
||||
|
||||
// Now shift the entire trace one place to the left and null-terminate.
|
||||
memmove(TraceBuffer, TraceBuffer + 1, NumTraces * sizeof(void *));
|
||||
TraceBuffer[NumTraces - 1] = 0;
|
||||
return backtrace(reinterpret_cast<void **>(TraceBuffer), Size);
|
||||
}
|
||||
|
||||
static void PrintBacktrace(uintptr_t *Trace,
|
||||
static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
|
||||
gwp_asan::options::Printf_t Printf) {
|
||||
size_t NumTraces = 0;
|
||||
for (; Trace[NumTraces] != 0; ++NumTraces) {
|
||||
}
|
||||
|
||||
if (NumTraces == 0) {
|
||||
if (TraceLength == 0) {
|
||||
Printf(" <not found (does your allocator support backtracing?)>\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char **BacktraceSymbols =
|
||||
backtrace_symbols(reinterpret_cast<void **>(Trace), NumTraces);
|
||||
backtrace_symbols(reinterpret_cast<void **>(Trace), TraceLength);
|
||||
|
||||
for (size_t i = 0; i < NumTraces; ++i) {
|
||||
for (size_t i = 0; i < TraceLength; ++i) {
|
||||
if (!BacktraceSymbols)
|
||||
Printf(" #%zu %p\n", i, Trace[i]);
|
||||
else
|
||||
|
@ -13,6 +13,9 @@
|
||||
|
||||
#include "gwp_asan/optional/backtrace.h"
|
||||
#include "gwp_asan/options.h"
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "sanitizer_common/sanitizer_flag_parser.h"
|
||||
#include "sanitizer_common/sanitizer_flags.h"
|
||||
#include "sanitizer_common/sanitizer_stacktrace.h"
|
||||
|
||||
void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
|
||||
@ -26,7 +29,7 @@ void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
|
||||
}
|
||||
|
||||
namespace {
|
||||
void Backtrace(uintptr_t *TraceBuffer, size_t Size) {
|
||||
size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) {
|
||||
__sanitizer::BufferedStackTrace Trace;
|
||||
Trace.Reset();
|
||||
if (Size > __sanitizer::kStackTraceMax)
|
||||
@ -38,19 +41,14 @@ void Backtrace(uintptr_t *TraceBuffer, size_t Size) {
|
||||
/* fast unwind */ true, Size - 1);
|
||||
|
||||
memcpy(TraceBuffer, Trace.trace, Trace.size * sizeof(uintptr_t));
|
||||
TraceBuffer[Trace.size] = 0;
|
||||
return Trace.size;
|
||||
}
|
||||
|
||||
static void PrintBacktrace(uintptr_t *Trace,
|
||||
static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
|
||||
gwp_asan::options::Printf_t Printf) {
|
||||
__sanitizer::StackTrace StackTrace;
|
||||
StackTrace.trace = reinterpret_cast<__sanitizer::uptr *>(Trace);
|
||||
|
||||
for (StackTrace.size = 0; StackTrace.size < __sanitizer::kStackTraceMax;
|
||||
++StackTrace.size) {
|
||||
if (Trace[StackTrace.size] == 0)
|
||||
break;
|
||||
}
|
||||
StackTrace.size = TraceLength;
|
||||
|
||||
if (StackTrace.size == 0) {
|
||||
Printf(" <unknown (does your allocator support backtracing?)>\n\n");
|
||||
@ -63,7 +61,18 @@ static void PrintBacktrace(uintptr_t *Trace,
|
||||
|
||||
namespace gwp_asan {
|
||||
namespace options {
|
||||
Backtrace_t getBacktraceFunction() { return Backtrace; }
|
||||
// This function is thread-compatible. It must be synchronised in respect to any
|
||||
// other calls to getBacktraceFunction(), calls to getPrintBacktraceFunction(),
|
||||
// and calls to either of the functions that they return. Furthermore, this may
|
||||
// require synchronisation with any calls to sanitizer_common that use flags.
|
||||
// Generally, this function will be called during the initialisation of the
|
||||
// allocator, which is done in a thread-compatible manner.
|
||||
Backtrace_t getBacktraceFunction() {
|
||||
// The unwinder requires the default flags to be set.
|
||||
__sanitizer::SetCommonFlagsDefaults();
|
||||
__sanitizer::InitializeCommonFlags();
|
||||
return Backtrace;
|
||||
}
|
||||
PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; }
|
||||
} // namespace options
|
||||
} // namespace gwp_asan
|
||||
|
@ -14,22 +14,63 @@
|
||||
|
||||
namespace gwp_asan {
|
||||
namespace options {
|
||||
// The function pointer type for printf(). Follows the standard format from the
|
||||
// sanitizers library. If the supported allocator exposes printing via a
|
||||
// different function signature, please provide a wrapper which has this
|
||||
// printf() signature, and pass the wrapper instead.
|
||||
// ================================ Requirements ===============================
|
||||
// This function is required to be implemented by the supporting allocator. The
|
||||
// sanitizer::Printf() function can be simply used here.
|
||||
// ================================ Description ================================
|
||||
// This function shall produce output according to a strict subset of the C
|
||||
// standard library's printf() family. This function must support printing the
|
||||
// following formats:
|
||||
// 1. integers: "%([0-9]*)?(z|ll)?{d,u,x,X}"
|
||||
// 2. pointers: "%p"
|
||||
// 3. strings: "%[-]([0-9]*)?(\\.\\*)?s"
|
||||
// 4. chars: "%c"
|
||||
// This function must be implemented in a signal-safe manner.
|
||||
// =================================== Notes ===================================
|
||||
// This function has a slightly different signature than the C standard
|
||||
// library's printf(). Notably, it returns 'void' rather than 'int'.
|
||||
typedef void (*Printf_t)(const char *Format, ...);
|
||||
|
||||
// The function pointer type for backtrace information. Required to be
|
||||
// implemented by the supporting allocator. The callee should elide itself and
|
||||
// all frames below itself from TraceBuffer, i.e. the caller's frame should be
|
||||
// in TraceBuffer[0], and subsequent frames 1..n into TraceBuffer[1..n], where a
|
||||
// maximum of `MaximumDepth - 1` frames are stored. TraceBuffer should be
|
||||
// nullptr-terminated (i.e. if there are 5 frames; TraceBuffer[5] == nullptr).
|
||||
// If the allocator cannot supply backtrace information, it should set
|
||||
// TraceBuffer[0] == nullptr.
|
||||
typedef void (*Backtrace_t)(uintptr_t *TraceBuffer, size_t Size);
|
||||
typedef void (*PrintBacktrace_t)(uintptr_t *TraceBuffer, Printf_t Print);
|
||||
// ================================ Requirements ===============================
|
||||
// This function is required to be either implemented by the supporting
|
||||
// allocator, or one of the two provided implementations may be used
|
||||
// (RTGwpAsanBacktraceLibc or RTGwpAsanBacktraceSanitizerCommon).
|
||||
// ================================ Description ================================
|
||||
// This function shall collect the backtrace for the calling thread and place
|
||||
// the result in `TraceBuffer`. This function should elide itself and all frames
|
||||
// below itself from `TraceBuffer`, i.e. the caller's frame should be in
|
||||
// TraceBuffer[0], and subsequent frames 1..n into TraceBuffer[1..n], where a
|
||||
// maximum of `Size` frames are stored. Returns the number of frames stored into
|
||||
// `TraceBuffer`, and zero on failure. If the return value of this function is
|
||||
// equal to `Size`, it may indicate that the backtrace is truncated.
|
||||
// =================================== Notes ===================================
|
||||
// This function may directly or indirectly call malloc(), as the
|
||||
// GuardedPoolAllocator contains a reentrancy barrier to prevent infinite
|
||||
// recursion. Any allocation made inside this function will be served by the
|
||||
// supporting allocator, and will not have GWP-ASan protections.
|
||||
typedef size_t (*Backtrace_t)(uintptr_t *TraceBuffer, size_t Size);
|
||||
|
||||
// ================================ Requirements ===============================
|
||||
// This function is optional for the supporting allocator, but one of the two
|
||||
// provided implementations may be used (RTGwpAsanBacktraceLibc or
|
||||
// RTGwpAsanBacktraceSanitizerCommon). If not provided, a default implementation
|
||||
// is used which prints the raw pointers only.
|
||||
// ================================ Description ================================
|
||||
// This function shall take the backtrace provided in `TraceBuffer`, and print
|
||||
// it in a human-readable format using `Print`. Generally, this function shall
|
||||
// resolve raw pointers to section offsets and print them with the following
|
||||
// sanitizer-common format:
|
||||
// " #{frame_number} {pointer} in {function name} ({binary name}+{offset}"
|
||||
// e.g. " #5 0x420459 in _start (/tmp/uaf+0x420459)"
|
||||
// This format allows the backtrace to be symbolized offline successfully using
|
||||
// llvm-symbolizer.
|
||||
// =================================== Notes ===================================
|
||||
// This function may directly or indirectly call malloc(), as the
|
||||
// GuardedPoolAllocator contains a reentrancy barrier to prevent infinite
|
||||
// recursion. Any allocation made inside this function will be served by the
|
||||
// supporting allocator, and will not have GWP-ASan protections.
|
||||
typedef void (*PrintBacktrace_t)(uintptr_t *TraceBuffer, size_t TraceLength,
|
||||
Printf_t Print);
|
||||
|
||||
struct Options {
|
||||
Printf_t Printf = nullptr;
|
||||
|
@ -21,9 +21,9 @@ GWP_ASAN_OPTION(
|
||||
"byte buffer-overflows for multibyte allocations at the cost of "
|
||||
"performance, and may be incompatible with some architectures.")
|
||||
|
||||
GWP_ASAN_OPTION(
|
||||
int, MaxSimultaneousAllocations, 16,
|
||||
"Number of usable guarded slots in the allocation pool. Defaults to 16.")
|
||||
GWP_ASAN_OPTION(int, MaxSimultaneousAllocations, 16,
|
||||
"Number of simultaneously-guarded allocations available in the "
|
||||
"pool. Defaults to 16.")
|
||||
|
||||
GWP_ASAN_OPTION(int, SampleRate, 5000,
|
||||
"The probability (1 / SampleRate) that an allocation is "
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user