svn commit: r317222 - in vendor/compiler-rt/dist: include/sanitizer lib/asan lib/asan/tests lib/dfsan lib/lsan lib/sanitizer_common lib/scudo lib/tsan/rtl lib/ubsan lib/xray test/asan/TestCases tes...
Dimitry Andric
dim at FreeBSD.org
Thu Apr 20 21:21:02 UTC 2017
Author: dim
Date: Thu Apr 20 21:20:59 2017
New Revision: 317222
URL: https://svnweb.freebsd.org/changeset/base/317222
Log:
Vendor import of compiler-rt trunk r300890:
https://llvm.org/svn/llvm-project/compiler-rt/trunk@300890
Added:
vendor/compiler-rt/dist/test/asan/TestCases/Posix/strchr.c (contents, props changed)
Deleted:
vendor/compiler-rt/dist/test/asan/TestCases/Posix/coverage-caller-callee.cc
vendor/compiler-rt/dist/test/asan/TestCases/coverage-caller-callee-total-count.cc
vendor/compiler-rt/dist/test/asan/TestCases/coverage-reset.cc
vendor/compiler-rt/dist/test/asan/TestCases/coverage-tracing.cc
Modified:
vendor/compiler-rt/dist/include/sanitizer/coverage_interface.h
vendor/compiler-rt/dist/lib/asan/asan_thread.cc
vendor/compiler-rt/dist/lib/asan/asan_thread.h
vendor/compiler-rt/dist/lib/asan/tests/asan_test_main.cc
vendor/compiler-rt/dist/lib/dfsan/done_abilist.txt
vendor/compiler-rt/dist/lib/lsan/lsan_common.cc
vendor/compiler-rt/dist/lib/lsan/lsan_common.h
vendor/compiler-rt/dist/lib/lsan/lsan_common_linux.cc
vendor/compiler-rt/dist/lib/lsan/lsan_common_mac.cc
vendor/compiler-rt/dist/lib/lsan/lsan_thread.cc
vendor/compiler-rt/dist/lib/lsan/lsan_thread.h
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_common.cc
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_common.h
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_common_interceptors.inc
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_coverage_interface.inc
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_internal_defs.h
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_linux.cc
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_linux_libcdep.cc
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_mac.cc
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_platform.h
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_procmaps_common.cc
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_procmaps_mac.cc
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_stoptheworld.h
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_stoptheworld_mac.cc
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_thread_registry.cc
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_thread_registry.h
vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_win.cc
vendor/compiler-rt/dist/lib/scudo/scudo_allocator.cpp
vendor/compiler-rt/dist/lib/scudo/scudo_allocator.h
vendor/compiler-rt/dist/lib/scudo/scudo_allocator_secondary.h
vendor/compiler-rt/dist/lib/scudo/scudo_utils.cpp
vendor/compiler-rt/dist/lib/scudo/scudo_utils.h
vendor/compiler-rt/dist/lib/tsan/rtl/tsan_debugging.cc
vendor/compiler-rt/dist/lib/tsan/rtl/tsan_interface.h
vendor/compiler-rt/dist/lib/tsan/rtl/tsan_report.h
vendor/compiler-rt/dist/lib/tsan/rtl/tsan_rtl.h
vendor/compiler-rt/dist/lib/tsan/rtl/tsan_rtl_thread.cc
vendor/compiler-rt/dist/lib/ubsan/ubsan_flags.cc
vendor/compiler-rt/dist/lib/xray/xray_fdr_logging.cc
vendor/compiler-rt/dist/lib/xray/xray_inmemory_log.cc
vendor/compiler-rt/dist/lib/xray/xray_trampoline_x86_64.S
vendor/compiler-rt/dist/lib/xray/xray_x86_64.cc
vendor/compiler-rt/dist/test/asan/TestCases/coverage-levels.cc
vendor/compiler-rt/dist/test/lsan/TestCases/Linux/cleanup_in_tsd_destructor.c
vendor/compiler-rt/dist/test/lsan/TestCases/Linux/disabler_in_tsd_destructor.c
vendor/compiler-rt/dist/test/lsan/TestCases/Linux/use_tls_dynamic.cc
vendor/compiler-rt/dist/test/lsan/TestCases/Linux/use_tls_pthread_specific_dynamic.cc
vendor/compiler-rt/dist/test/lsan/TestCases/Linux/use_tls_pthread_specific_static.cc
vendor/compiler-rt/dist/test/lsan/TestCases/Linux/use_tls_static.cc
vendor/compiler-rt/dist/test/lsan/TestCases/disabler.c
vendor/compiler-rt/dist/test/lsan/TestCases/disabler.cc
vendor/compiler-rt/dist/test/lsan/TestCases/do_leak_check_override.cc
vendor/compiler-rt/dist/test/lsan/TestCases/high_allocator_contention.cc
vendor/compiler-rt/dist/test/lsan/TestCases/ignore_object.c
vendor/compiler-rt/dist/test/lsan/TestCases/ignore_object_errors.cc
vendor/compiler-rt/dist/test/lsan/TestCases/large_allocation_leak.cc
vendor/compiler-rt/dist/test/lsan/TestCases/leak_check_at_exit.cc
vendor/compiler-rt/dist/test/lsan/TestCases/leak_check_before_thread_started.cc
vendor/compiler-rt/dist/test/lsan/TestCases/link_turned_off.cc
vendor/compiler-rt/dist/test/lsan/TestCases/pointer_to_self.cc
vendor/compiler-rt/dist/test/lsan/TestCases/print_suppressions.cc
vendor/compiler-rt/dist/test/lsan/TestCases/recoverable_leak_check.cc
vendor/compiler-rt/dist/test/lsan/TestCases/register_root_region.cc
vendor/compiler-rt/dist/test/lsan/TestCases/stale_stack_leak.cc
vendor/compiler-rt/dist/test/lsan/TestCases/suppressions_default.cc
vendor/compiler-rt/dist/test/lsan/TestCases/suppressions_file.cc
vendor/compiler-rt/dist/test/lsan/TestCases/swapcontext.cc
vendor/compiler-rt/dist/test/lsan/TestCases/use_after_return.cc
vendor/compiler-rt/dist/test/lsan/TestCases/use_globals_initialized.cc
vendor/compiler-rt/dist/test/lsan/TestCases/use_globals_uninitialized.cc
vendor/compiler-rt/dist/test/lsan/TestCases/use_poisoned_asan.cc
vendor/compiler-rt/dist/test/lsan/TestCases/use_registers.cc
vendor/compiler-rt/dist/test/lsan/TestCases/use_stacks.cc
vendor/compiler-rt/dist/test/lsan/TestCases/use_stacks_threaded.cc
vendor/compiler-rt/dist/test/lsan/TestCases/use_unaligned.cc
vendor/compiler-rt/dist/test/lsan/lit.common.cfg
vendor/compiler-rt/dist/test/sanitizer_common/lit.common.cfg
vendor/compiler-rt/dist/test/tsan/Darwin/main_tid.mm
vendor/compiler-rt/dist/test/tsan/debug_alloc_stack.cc
vendor/compiler-rt/dist/test/tsan/debugging.cc
vendor/compiler-rt/dist/test/xray/TestCases/Linux/fdr-mode.cc
vendor/compiler-rt/dist/test/xray/TestCases/Linux/fdr-thread-order.cc
vendor/compiler-rt/dist/test/xray/lit.site.cfg.in
Modified: vendor/compiler-rt/dist/include/sanitizer/coverage_interface.h
==============================================================================
--- vendor/compiler-rt/dist/include/sanitizer/coverage_interface.h Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/include/sanitizer/coverage_interface.h Thu Apr 20 21:20:59 2017 (r317222)
@@ -35,35 +35,6 @@ extern "C" {
// Get the number of unique covered blocks (or edges).
// This can be useful for coverage-directed in-process fuzzers.
uintptr_t __sanitizer_get_total_unique_coverage();
- // Get the number of unique indirect caller-callee pairs.
- uintptr_t __sanitizer_get_total_unique_caller_callee_pairs();
-
- // Reset the basic-block (edge) coverage to the initial state.
- // Useful for in-process fuzzing to start collecting coverage from scratch.
- // Experimental, will likely not work for multi-threaded process.
- void __sanitizer_reset_coverage();
- // Set *data to the array of covered PCs and return the size of that array.
- // Some of the entries in *data will be zero.
- uintptr_t __sanitizer_get_coverage_guards(uintptr_t **data);
-
- // The coverage instrumentation may optionally provide imprecise counters.
- // Rather than exposing the counter values to the user we instead map
- // the counters to a bitset.
- // Every counter is associated with 8 bits in the bitset.
- // We define 8 value ranges: 1, 2, 3, 4-7, 8-15, 16-31, 32-127, 128+
- // The i-th bit is set to 1 if the counter value is in the i-th range.
- // This counter-based coverage implementation is *not* thread-safe.
-
- // Returns the number of registered coverage counters.
- uintptr_t __sanitizer_get_number_of_counters();
- // Updates the counter 'bitset', clears the counters and returns the number of
- // new bits in 'bitset'.
- // If 'bitset' is nullptr, only clears the counters.
- // Otherwise 'bitset' should be at least
- // __sanitizer_get_number_of_counters bytes long and 8-aligned.
- uintptr_t
- __sanitizer_update_counter_bitset_and_clear_counters(uint8_t *bitset);
-
#ifdef __cplusplus
} // extern "C"
#endif
Modified: vendor/compiler-rt/dist/lib/asan/asan_thread.cc
==============================================================================
--- vendor/compiler-rt/dist/lib/asan/asan_thread.cc Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/asan/asan_thread.cc Thu Apr 20 21:20:59 2017 (r317222)
@@ -237,7 +237,7 @@ void AsanThread::Init() {
}
thread_return_t AsanThread::ThreadStart(
- uptr os_id, atomic_uintptr_t *signal_thread_is_registered) {
+ tid_t os_id, atomic_uintptr_t *signal_thread_is_registered) {
Init();
asanThreadRegistry().StartThread(tid(), os_id, /*workerthread*/ false,
nullptr);
@@ -395,7 +395,7 @@ void EnsureMainThreadIDIsCorrect() {
context->os_id = GetTid();
}
-__asan::AsanThread *GetAsanThreadByOsIDLocked(uptr os_id) {
+__asan::AsanThread *GetAsanThreadByOsIDLocked(tid_t os_id) {
__asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>(
__asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id));
if (!context) return nullptr;
@@ -405,7 +405,7 @@ __asan::AsanThread *GetAsanThreadByOsIDL
// --- Implementation of LSan-specific functions --- {{{1
namespace __lsan {
-bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
+bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
uptr *cache_end, DTLS **dtls) {
__asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
@@ -421,7 +421,7 @@ bool GetThreadRangesLocked(uptr os_id, u
return true;
}
-void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback,
+void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback,
void *arg) {
__asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
if (t && t->has_fake_stack())
Modified: vendor/compiler-rt/dist/lib/asan/asan_thread.h
==============================================================================
--- vendor/compiler-rt/dist/lib/asan/asan_thread.h Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/asan/asan_thread.h Thu Apr 20 21:20:59 2017 (r317222)
@@ -63,7 +63,7 @@ class AsanThread {
void Destroy();
void Init(); // Should be called from the thread itself.
- thread_return_t ThreadStart(uptr os_id,
+ thread_return_t ThreadStart(tid_t os_id,
atomic_uintptr_t *signal_thread_is_registered);
uptr stack_top();
Modified: vendor/compiler-rt/dist/lib/asan/tests/asan_test_main.cc
==============================================================================
--- vendor/compiler-rt/dist/lib/asan/tests/asan_test_main.cc Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/asan/tests/asan_test_main.cc Thu Apr 20 21:20:59 2017 (r317222)
@@ -13,15 +13,23 @@
#include "asan_test_utils.h"
#include "sanitizer_common/sanitizer_platform.h"
-// Default ASAN_OPTIONS for the unit tests. Let's turn symbolication off to
-// speed up testing (unit tests don't use it anyway).
+// Default ASAN_OPTIONS for the unit tests.
extern "C" const char* __asan_default_options() {
#if SANITIZER_MAC
// On Darwin, we default to `abort_on_error=1`, which would make tests run
- // much slower. Let's override this and run lit tests with 'abort_on_error=0'.
- // Also, make sure we do not overwhelm the syslog while testing.
+ // much slower. Let's override this and run lit tests with 'abort_on_error=0'
+ // and make sure we do not overwhelm the syslog while testing. Also, let's
+ // turn symbolization off to speed up testing, especially when not running
+ // with llvm-symbolizer but with atos.
return "symbolize=false:abort_on_error=0:log_to_syslog=0";
+#elif SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT
+ // On PowerPC and ARM Thumb, a couple tests involving pthread_exit fail due to
+ // leaks detected by LSan. Symbolized leak report is required to apply a
+ // suppression for this known problem.
+ return "";
#else
+ // Let's turn symbolization off to speed up testing (more than 3 times speedup
+ // observed).
return "symbolize=false";
#endif
}
Modified: vendor/compiler-rt/dist/lib/dfsan/done_abilist.txt
==============================================================================
--- vendor/compiler-rt/dist/lib/dfsan/done_abilist.txt Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/dfsan/done_abilist.txt Thu Apr 20 21:20:59 2017 (r317222)
@@ -285,22 +285,8 @@ fun:__sanitizer_cov_module_init=uninstru
fun:__sanitizer_cov_module_init=discard
fun:__sanitizer_cov_with_check=uninstrumented
fun:__sanitizer_cov_with_check=discard
-fun:__sanitizer_cov_indir_call16=uninstrumented
-fun:__sanitizer_cov_indir_call16=discard
-fun:__sanitizer_cov_indir_call16=uninstrumented
-fun:__sanitizer_cov_indir_call16=discard
-fun:__sanitizer_reset_coverage=uninstrumented
-fun:__sanitizer_reset_coverage=discard
fun:__sanitizer_set_death_callback=uninstrumented
fun:__sanitizer_set_death_callback=discard
-fun:__sanitizer_get_coverage_guards=uninstrumented
-fun:__sanitizer_get_coverage_guards=discard
-fun:__sanitizer_get_number_of_counters=uninstrumented
-fun:__sanitizer_get_number_of_counters=discard
-fun:__sanitizer_update_counter_bitset_and_clear_counters=uninstrumented
-fun:__sanitizer_update_counter_bitset_and_clear_counters=discard
-fun:__sanitizer_get_total_unique_coverage=uninstrumented
-fun:__sanitizer_get_total_unique_coverage=discard
fun:__sanitizer_get_total_unique_coverage=uninstrumented
fun:__sanitizer_get_total_unique_coverage=discard
fun:__sanitizer_update_counter_bitset_and_clear_counters=uninstrumented
Modified: vendor/compiler-rt/dist/lib/lsan/lsan_common.cc
==============================================================================
--- vendor/compiler-rt/dist/lib/lsan/lsan_common.cc Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/lsan/lsan_common.cc Thu Apr 20 21:20:59 2017 (r317222)
@@ -68,6 +68,14 @@ ALIGNED(64) static char suppression_plac
static SuppressionContext *suppression_ctx = nullptr;
static const char kSuppressionLeak[] = "leak";
static const char *kSuppressionTypes[] = { kSuppressionLeak };
+static const char kStdSuppressions[] =
+#if SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT
+ // The actual string allocation happens here (for more details refer to the
+ // SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT definition).
+ "leak:*_dl_map_object_deps*";
+#else
+ "";
+#endif // SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT
void InitializeSuppressions() {
CHECK_EQ(nullptr, suppression_ctx);
@@ -76,6 +84,7 @@ void InitializeSuppressions() {
suppression_ctx->ParseFromFile(flags()->suppressions);
if (&__lsan_default_suppressions)
suppression_ctx->Parse(__lsan_default_suppressions());
+ suppression_ctx->Parse(kStdSuppressions);
}
static SuppressionContext *GetSuppressionContext() {
@@ -83,12 +92,9 @@ static SuppressionContext *GetSuppressio
return suppression_ctx;
}
-struct RootRegion {
- const void *begin;
- uptr size;
-};
+static InternalMmapVector<RootRegion> *root_regions;
-InternalMmapVector<RootRegion> *root_regions;
+InternalMmapVector<RootRegion> const *GetRootRegions() { return root_regions; }
void InitializeRootRegions() {
CHECK(!root_regions);
@@ -200,11 +206,11 @@ void ForEachExtraStackRangeCb(uptr begin
// Scans thread data (stacks and TLS) for heap pointers.
static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
Frontier *frontier) {
- InternalScopedBuffer<uptr> registers(SuspendedThreadsList::RegisterCount());
+ InternalScopedBuffer<uptr> registers(suspended_threads.RegisterCount());
uptr registers_begin = reinterpret_cast<uptr>(registers.data());
uptr registers_end = registers_begin + registers.size();
- for (uptr i = 0; i < suspended_threads.thread_count(); i++) {
- uptr os_id = static_cast<uptr>(suspended_threads.GetThreadID(i));
+ for (uptr i = 0; i < suspended_threads.ThreadCount(); i++) {
+ tid_t os_id = static_cast<tid_t>(suspended_threads.GetThreadID(i));
LOG_THREADS("Processing thread %d.\n", os_id);
uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end;
DTLS *dtls;
@@ -291,23 +297,29 @@ static void ProcessThreads(SuspendedThre
}
}
-static void ProcessRootRegion(Frontier *frontier, uptr root_begin,
- uptr root_end) {
- MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+void ScanRootRegion(Frontier *frontier, const RootRegion &root_region,
+ uptr region_begin, uptr region_end, uptr prot) {
+ uptr intersection_begin = Max(root_region.begin, region_begin);
+ uptr intersection_end = Min(region_end, root_region.begin + root_region.size);
+ if (intersection_begin >= intersection_end) return;
+ bool is_readable = prot & MemoryMappingLayout::kProtectionRead;
+ LOG_POINTERS("Root region %p-%p intersects with mapped region %p-%p (%s)\n",
+ root_region.begin, root_region.begin + root_region.size,
+ region_begin, region_end,
+ is_readable ? "readable" : "unreadable");
+ if (is_readable)
+ ScanRangeForPointers(intersection_begin, intersection_end, frontier, "ROOT",
+ kReachable);
+}
+
+static void ProcessRootRegion(Frontier *frontier,
+ const RootRegion &root_region) {
+ MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
uptr begin, end, prot;
while (proc_maps.Next(&begin, &end,
/*offset*/ nullptr, /*filename*/ nullptr,
/*filename_size*/ 0, &prot)) {
- uptr intersection_begin = Max(root_begin, begin);
- uptr intersection_end = Min(end, root_end);
- if (intersection_begin >= intersection_end) continue;
- bool is_readable = prot & MemoryMappingLayout::kProtectionRead;
- LOG_POINTERS("Root region %p-%p intersects with mapped region %p-%p (%s)\n",
- root_begin, root_end, begin, end,
- is_readable ? "readable" : "unreadable");
- if (is_readable)
- ScanRangeForPointers(intersection_begin, intersection_end, frontier,
- "ROOT", kReachable);
+ ScanRootRegion(frontier, root_region, begin, end, prot);
}
}
@@ -316,9 +328,7 @@ static void ProcessRootRegions(Frontier
if (!flags()->use_root_regions) return;
CHECK(root_regions);
for (uptr i = 0; i < root_regions->size(); i++) {
- RootRegion region = (*root_regions)[i];
- uptr begin_addr = reinterpret_cast<uptr>(region.begin);
- ProcessRootRegion(frontier, begin_addr, begin_addr + region.size);
+ ProcessRootRegion(frontier, (*root_regions)[i]);
}
}
@@ -356,6 +366,72 @@ static void CollectIgnoredCb(uptr chunk,
}
}
+static uptr GetCallerPC(u32 stack_id, StackDepotReverseMap *map) {
+ CHECK(stack_id);
+ StackTrace stack = map->Get(stack_id);
+ // The top frame is our malloc/calloc/etc. The next frame is the caller.
+ if (stack.size >= 2)
+ return stack.trace[1];
+ return 0;
+}
+
+struct InvalidPCParam {
+ Frontier *frontier;
+ StackDepotReverseMap *stack_depot_reverse_map;
+ bool skip_linker_allocations;
+};
+
+// ForEachChunk callback. If the caller pc is invalid or is within the linker,
+// mark as reachable. Called by ProcessPlatformSpecificAllocations.
+static void MarkInvalidPCCb(uptr chunk, void *arg) {
+ CHECK(arg);
+ InvalidPCParam *param = reinterpret_cast<InvalidPCParam *>(arg);
+ chunk = GetUserBegin(chunk);
+ LsanMetadata m(chunk);
+ if (m.allocated() && m.tag() != kReachable && m.tag() != kIgnored) {
+ u32 stack_id = m.stack_trace_id();
+ uptr caller_pc = 0;
+ if (stack_id > 0)
+ caller_pc = GetCallerPC(stack_id, param->stack_depot_reverse_map);
+ // If caller_pc is unknown, this chunk may be allocated in a coroutine. Mark
+ // it as reachable, as we can't properly report its allocation stack anyway.
+ if (caller_pc == 0 || (param->skip_linker_allocations &&
+ GetLinker()->containsAddress(caller_pc))) {
+ m.set_tag(kReachable);
+ param->frontier->push_back(chunk);
+ }
+ }
+}
+
+// On Linux, handles dynamically allocated TLS blocks by treating all chunks
+// allocated from ld-linux.so as reachable.
+// Dynamic TLS blocks contain the TLS variables of dynamically loaded modules.
+// They are allocated with a __libc_memalign() call in allocate_and_init()
+// (elf/dl-tls.c). Glibc won't tell us the address ranges occupied by those
+// blocks, but we can make sure they come from our own allocator by intercepting
+// __libc_memalign(). On top of that, there is no easy way to reach them. Their
+// addresses are stored in a dynamically allocated array (the DTV) which is
+// referenced from the static TLS. Unfortunately, we can't just rely on the DTV
+// being reachable from the static TLS, and the dynamic TLS being reachable from
+// the DTV. This is because the initial DTV is allocated before our interception
+// mechanism kicks in, and thus we don't recognize it as allocated memory. We
+// can't special-case it either, since we don't know its size.
+// Our solution is to include in the root set all allocations made from
+// ld-linux.so (which is where allocate_and_init() is implemented). This is
+// guaranteed to include all dynamic TLS blocks (and possibly other allocations
+// which we don't care about).
+// On all other platforms, this simply checks to ensure that the caller pc is
+// valid before reporting chunks as leaked.
+void ProcessPC(Frontier *frontier) {
+ StackDepotReverseMap stack_depot_reverse_map;
+ InvalidPCParam arg;
+ arg.frontier = frontier;
+ arg.stack_depot_reverse_map = &stack_depot_reverse_map;
+ arg.skip_linker_allocations =
+ flags()->use_tls && flags()->use_ld_allocations && GetLinker() != nullptr;
+ ForEachChunk(MarkInvalidPCCb, &arg);
+}
+
// Sets the appropriate tag on each chunk.
static void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads) {
// Holds the flood fill frontier.
@@ -367,11 +443,13 @@ static void ClassifyAllChunks(SuspendedT
ProcessRootRegions(&frontier);
FloodFillTag(&frontier, kReachable);
+ CHECK_EQ(0, frontier.size());
+ ProcessPC(&frontier);
+
// The check here is relatively expensive, so we do this in a separate flood
// fill. That way we can skip the check for chunks that are reachable
// otherwise.
LOG_POINTERS("Processing platform-specific allocations.\n");
- CHECK_EQ(0, frontier.size());
ProcessPlatformSpecificAllocations(&frontier);
FloodFillTag(&frontier, kReachable);
@@ -707,7 +785,7 @@ void __lsan_register_root_region(const v
#if CAN_SANITIZE_LEAKS
BlockingMutexLock l(&global_mutex);
CHECK(root_regions);
- RootRegion region = {begin, size};
+ RootRegion region = {reinterpret_cast<uptr>(begin), size};
root_regions->push_back(region);
VReport(1, "Registered root region at %p of size %llu\n", begin, size);
#endif // CAN_SANITIZE_LEAKS
@@ -721,7 +799,7 @@ void __lsan_unregister_root_region(const
bool removed = false;
for (uptr i = 0; i < root_regions->size(); i++) {
RootRegion region = (*root_regions)[i];
- if (region.begin == begin && region.size == size) {
+ if (region.begin == reinterpret_cast<uptr>(begin) && region.size == size) {
removed = true;
uptr last_index = root_regions->size() - 1;
(*root_regions)[i] = (*root_regions)[last_index];
Modified: vendor/compiler-rt/dist/lib/lsan/lsan_common.h
==============================================================================
--- vendor/compiler-rt/dist/lib/lsan/lsan_common.h Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/lsan/lsan_common.h Thu Apr 20 21:20:59 2017 (r317222)
@@ -118,6 +118,15 @@ typedef InternalMmapVector<uptr> Frontie
void InitializePlatformSpecificModules();
void ProcessGlobalRegions(Frontier *frontier);
void ProcessPlatformSpecificAllocations(Frontier *frontier);
+
+struct RootRegion {
+ uptr begin;
+ uptr size;
+};
+
+InternalMmapVector<RootRegion> const *GetRootRegions();
+void ScanRootRegion(Frontier *frontier, RootRegion const ®ion,
+ uptr region_begin, uptr region_end, uptr prot);
// Run stoptheworld while holding any platform-specific locks.
void DoStopTheWorld(StopTheWorldCallback callback, void* argument);
@@ -193,10 +202,10 @@ bool WordIsPoisoned(uptr addr);
// Wrappers for ThreadRegistry access.
void LockThreadRegistry();
void UnlockThreadRegistry();
-bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
+bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
uptr *cache_end, DTLS **dtls);
-void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback,
+void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback,
void *arg);
// If called from the main thread, updates the main thread's TID in the thread
// registry. We need this to handle processes that fork() without a subsequent
@@ -212,6 +221,10 @@ uptr PointsIntoChunk(void *p);
uptr GetUserBegin(uptr chunk);
// Helper for __lsan_ignore_object().
IgnoreObjectResult IgnoreObjectLocked(const void *p);
+
+// Return the linker module, if valid for the platform.
+LoadedModule *GetLinker();
+
// Wrapper for chunk metadata operations.
class LsanMetadata {
public:
Modified: vendor/compiler-rt/dist/lib/lsan/lsan_common_linux.cc
==============================================================================
--- vendor/compiler-rt/dist/lib/lsan/lsan_common_linux.cc Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/lsan/lsan_common_linux.cc Thu Apr 20 21:20:59 2017 (r317222)
@@ -89,70 +89,9 @@ void ProcessGlobalRegions(Frontier *fron
dl_iterate_phdr(ProcessGlobalRegionsCallback, frontier);
}
-static uptr GetCallerPC(u32 stack_id, StackDepotReverseMap *map) {
- CHECK(stack_id);
- StackTrace stack = map->Get(stack_id);
- // The top frame is our malloc/calloc/etc. The next frame is the caller.
- if (stack.size >= 2)
- return stack.trace[1];
- return 0;
-}
-
-struct ProcessPlatformAllocParam {
- Frontier *frontier;
- StackDepotReverseMap *stack_depot_reverse_map;
- bool skip_linker_allocations;
-};
+LoadedModule *GetLinker() { return linker; }
-// ForEachChunk callback. Identifies unreachable chunks which must be treated as
-// reachable. Marks them as reachable and adds them to the frontier.
-static void ProcessPlatformSpecificAllocationsCb(uptr chunk, void *arg) {
- CHECK(arg);
- ProcessPlatformAllocParam *param =
- reinterpret_cast<ProcessPlatformAllocParam *>(arg);
- chunk = GetUserBegin(chunk);
- LsanMetadata m(chunk);
- if (m.allocated() && m.tag() != kReachable && m.tag() != kIgnored) {
- u32 stack_id = m.stack_trace_id();
- uptr caller_pc = 0;
- if (stack_id > 0)
- caller_pc = GetCallerPC(stack_id, param->stack_depot_reverse_map);
- // If caller_pc is unknown, this chunk may be allocated in a coroutine. Mark
- // it as reachable, as we can't properly report its allocation stack anyway.
- if (caller_pc == 0 || (param->skip_linker_allocations &&
- linker->containsAddress(caller_pc))) {
- m.set_tag(kReachable);
- param->frontier->push_back(chunk);
- }
- }
-}
-
-// Handles dynamically allocated TLS blocks by treating all chunks allocated
-// from ld-linux.so as reachable.
-// Dynamic TLS blocks contain the TLS variables of dynamically loaded modules.
-// They are allocated with a __libc_memalign() call in allocate_and_init()
-// (elf/dl-tls.c). Glibc won't tell us the address ranges occupied by those
-// blocks, but we can make sure they come from our own allocator by intercepting
-// __libc_memalign(). On top of that, there is no easy way to reach them. Their
-// addresses are stored in a dynamically allocated array (the DTV) which is
-// referenced from the static TLS. Unfortunately, we can't just rely on the DTV
-// being reachable from the static TLS, and the dynamic TLS being reachable from
-// the DTV. This is because the initial DTV is allocated before our interception
-// mechanism kicks in, and thus we don't recognize it as allocated memory. We
-// can't special-case it either, since we don't know its size.
-// Our solution is to include in the root set all allocations made from
-// ld-linux.so (which is where allocate_and_init() is implemented). This is
-// guaranteed to include all dynamic TLS blocks (and possibly other allocations
-// which we don't care about).
-void ProcessPlatformSpecificAllocations(Frontier *frontier) {
- StackDepotReverseMap stack_depot_reverse_map;
- ProcessPlatformAllocParam arg;
- arg.frontier = frontier;
- arg.stack_depot_reverse_map = &stack_depot_reverse_map;
- arg.skip_linker_allocations =
- flags()->use_tls && flags()->use_ld_allocations && linker != nullptr;
- ForEachChunk(ProcessPlatformSpecificAllocationsCb, &arg);
-}
+void ProcessPlatformSpecificAllocations(Frontier *frontier) {}
struct DoStopTheWorldParam {
StopTheWorldCallback callback;
Modified: vendor/compiler-rt/dist/lib/lsan/lsan_common_mac.cc
==============================================================================
--- vendor/compiler-rt/dist/lib/lsan/lsan_common_mac.cc Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/lsan/lsan_common_mac.cc Thu Apr 20 21:20:59 2017 (r317222)
@@ -22,6 +22,8 @@
#include <pthread.h>
+#include <mach/mach.h>
+
namespace __lsan {
typedef struct {
@@ -85,6 +87,8 @@ void SetCurrentThread(u32 tid) { get_tls
AllocatorCache *GetAllocatorCache() { return &get_tls_val(true)->cache; }
+LoadedModule *GetLinker() { return nullptr; }
+
// Required on Linux for initialization of TLS behavior, but should not be
// required on Darwin.
void InitializePlatformSpecificModules() {
@@ -106,7 +110,7 @@ void ProcessGlobalRegions(Frontier *fron
for (const __sanitizer::LoadedModule::AddressRange &range :
modules[i].ranges()) {
- if (range.executable) continue;
+ if (range.executable || !range.readable) continue;
ScanGlobalRange(range.beg, range.end, frontier);
}
@@ -114,11 +118,54 @@ void ProcessGlobalRegions(Frontier *fron
}
void ProcessPlatformSpecificAllocations(Frontier *frontier) {
- CHECK(0 && "unimplemented");
+ mach_port_name_t port;
+ if (task_for_pid(mach_task_self(), internal_getpid(), &port)
+ != KERN_SUCCESS) {
+ return;
+ }
+
+ unsigned depth = 1;
+ vm_size_t size = 0;
+ vm_address_t address = 0;
+ kern_return_t err = KERN_SUCCESS;
+ mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
+
+ InternalMmapVector<RootRegion> const *root_regions = GetRootRegions();
+
+ while (err == KERN_SUCCESS) {
+ struct vm_region_submap_info_64 info;
+ err = vm_region_recurse_64(port, &address, &size, &depth,
+ (vm_region_info_t)&info, &count);
+
+ uptr end_address = address + size;
+
+ // libxpc stashes some pointers in the Kernel Alloc Once page,
+ // make sure not to report those as leaks.
+ if (info.user_tag == VM_MEMORY_OS_ALLOC_ONCE) {
+ ScanRangeForPointers(address, end_address, frontier, "GLOBAL",
+ kReachable);
+ }
+
+ // This additional root region scan is required on Darwin in order to
+ // detect root regions contained within mmap'd memory regions, because
+ // the Darwin implementation of sanitizer_procmaps traverses images
+ // as loaded by dyld, and not the complete set of all memory regions.
+ //
+ // TODO(fjricci) - remove this once sanitizer_procmaps_mac has the same
+ // behavior as sanitizer_procmaps_linux and traverses all memory regions
+ if (flags()->use_root_regions) {
+ for (uptr i = 0; i < root_regions->size(); i++) {
+ ScanRootRegion(frontier, (*root_regions)[i], address, end_address,
+ info.protection);
+ }
+ }
+
+ address = end_address;
+ }
}
void DoStopTheWorld(StopTheWorldCallback callback, void *argument) {
- CHECK(0 && "unimplemented");
+ StopTheWorld(callback, argument);
}
} // namespace __lsan
Modified: vendor/compiler-rt/dist/lib/lsan/lsan_thread.cc
==============================================================================
--- vendor/compiler-rt/dist/lib/lsan/lsan_thread.cc Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/lsan/lsan_thread.cc Thu Apr 20 21:20:59 2017 (r317222)
@@ -77,7 +77,7 @@ u32 ThreadCreate(u32 parent_tid, uptr us
/* arg */ nullptr);
}
-void ThreadStart(u32 tid, uptr os_id) {
+void ThreadStart(u32 tid, tid_t os_id) {
OnStartedArgs args;
uptr stack_size = 0;
uptr tls_size = 0;
@@ -127,7 +127,7 @@ void EnsureMainThreadIDIsCorrect() {
///// Interface to the common LSan module. /////
-bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
+bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
uptr *cache_end, DTLS **dtls) {
ThreadContext *context = static_cast<ThreadContext *>(
@@ -143,7 +143,7 @@ bool GetThreadRangesLocked(uptr os_id, u
return true;
}
-void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback,
+void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback,
void *arg) {
}
Modified: vendor/compiler-rt/dist/lib/lsan/lsan_thread.h
==============================================================================
--- vendor/compiler-rt/dist/lib/lsan/lsan_thread.h Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/lsan/lsan_thread.h Thu Apr 20 21:20:59 2017 (r317222)
@@ -45,7 +45,7 @@ class ThreadContext : public ThreadConte
void InitializeThreadRegistry();
-void ThreadStart(u32 tid, uptr os_id);
+void ThreadStart(u32 tid, tid_t os_id);
void ThreadFinish();
u32 ThreadCreate(u32 tid, uptr uid, bool detached);
void ThreadJoin(u32 tid);
Modified: vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_common.cc
==============================================================================
--- vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_common.cc Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_common.cc Thu Apr 20 21:20:59 2017 (r317222)
@@ -284,9 +284,10 @@ void LoadedModule::clear() {
}
}
-void LoadedModule::addAddressRange(uptr beg, uptr end, bool executable) {
+void LoadedModule::addAddressRange(uptr beg, uptr end, bool executable,
+ bool readable) {
void *mem = InternalAlloc(sizeof(AddressRange));
- AddressRange *r = new(mem) AddressRange(beg, end, executable);
+ AddressRange *r = new(mem) AddressRange(beg, end, executable, readable);
ranges_.push_back(r);
if (executable && end > max_executable_address_)
max_executable_address_ = end;
Modified: vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_common.h
==============================================================================
--- vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_common.h Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_common.h Thu Apr 20 21:20:59 2017 (r317222)
@@ -72,7 +72,7 @@ INLINE uptr GetPageSizeCached() {
uptr GetMmapGranularity();
uptr GetMaxVirtualAddress();
// Threads
-uptr GetTid();
+tid_t GetTid();
uptr GetThreadSelf();
void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
uptr *stack_bottom);
@@ -717,7 +717,7 @@ class LoadedModule {
void set(const char *module_name, uptr base_address, ModuleArch arch,
u8 uuid[kModuleUUIDSize], bool instrumented);
void clear();
- void addAddressRange(uptr beg, uptr end, bool executable);
+ void addAddressRange(uptr beg, uptr end, bool executable, bool readable);
bool containsAddress(uptr address) const;
const char *full_name() const { return full_name_; }
@@ -732,9 +732,14 @@ class LoadedModule {
uptr beg;
uptr end;
bool executable;
+ bool readable;
- AddressRange(uptr beg, uptr end, bool executable)
- : next(nullptr), beg(beg), end(end), executable(executable) {}
+ AddressRange(uptr beg, uptr end, bool executable, bool readable)
+ : next(nullptr),
+ beg(beg),
+ end(end),
+ executable(executable),
+ readable(readable) {}
};
const IntrusiveList<AddressRange> &ranges() const { return ranges_; }
Modified: vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_common_interceptors.inc
==============================================================================
--- vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_common_interceptors.inc Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_common_interceptors.inc Thu Apr 20 21:20:59 2017 (r317222)
@@ -139,12 +139,9 @@ bool PlatformHasDifferentMemcpyAndMemmov
#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (0)
#endif
-#define COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, n) \
- COMMON_INTERCEPTOR_READ_RANGE((ctx), (s), \
- common_flags()->strict_string_checks ? (len) + 1 : (n) )
-
#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n) \
- COMMON_INTERCEPTOR_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
+ COMMON_INTERCEPTOR_READ_RANGE((ctx), (s), \
+ common_flags()->strict_string_checks ? (REAL(strlen)(s)) + 1 : (n) )
#ifndef COMMON_INTERCEPTOR_ON_DLOPEN
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
@@ -450,8 +447,7 @@ static inline void StrstrCheck(void *ctx
const char *s2) {
uptr len1 = REAL(strlen)(s1);
uptr len2 = REAL(strlen)(s2);
- COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s1, len1,
- r ? r - s1 + len2 : len1 + 1);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1);
COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2 + 1);
}
#endif
@@ -577,10 +573,11 @@ INTERCEPTOR(char*, strchr, const char *s
return internal_strchr(s, c);
COMMON_INTERCEPTOR_ENTER(ctx, strchr, s, c);
char *result = REAL(strchr)(s, c);
- uptr len = internal_strlen(s);
- uptr n = result ? result - s + 1 : len + 1;
- if (common_flags()->intercept_strchr)
- COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, n);
+ if (common_flags()->intercept_strchr) {
+ // Keep strlen as macro argument, as macro may ignore it.
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s,
+ (result ? result - s : REAL(strlen)(s)) + 1);
+ }
return result;
}
#define INIT_STRCHR COMMON_INTERCEPT_FUNCTION(strchr)
@@ -609,9 +606,8 @@ INTERCEPTOR(char*, strrchr, const char *
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
return internal_strrchr(s, c);
COMMON_INTERCEPTOR_ENTER(ctx, strrchr, s, c);
- uptr len = internal_strlen(s);
if (common_flags()->intercept_strchr)
- COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, len + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
return REAL(strrchr)(s, c);
}
#define INIT_STRRCHR COMMON_INTERCEPT_FUNCTION(strrchr)
Modified: vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_coverage_interface.inc
==============================================================================
--- vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_coverage_interface.inc Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_coverage_interface.inc Thu Apr 20 21:20:59 2017 (r317222)
@@ -10,21 +10,13 @@
//===----------------------------------------------------------------------===//
INTERFACE_FUNCTION(__sanitizer_cov)
INTERFACE_FUNCTION(__sanitizer_cov_dump)
-INTERFACE_FUNCTION(__sanitizer_cov_indir_call16)
INTERFACE_FUNCTION(__sanitizer_cov_init)
INTERFACE_FUNCTION(__sanitizer_cov_module_init)
-INTERFACE_FUNCTION(__sanitizer_cov_trace_basic_block)
-INTERFACE_FUNCTION(__sanitizer_cov_trace_func_enter)
INTERFACE_FUNCTION(__sanitizer_cov_with_check)
INTERFACE_FUNCTION(__sanitizer_dump_coverage)
INTERFACE_FUNCTION(__sanitizer_dump_trace_pc_guard_coverage)
-INTERFACE_FUNCTION(__sanitizer_get_coverage_guards)
-INTERFACE_FUNCTION(__sanitizer_get_number_of_counters)
-INTERFACE_FUNCTION(__sanitizer_get_total_unique_caller_callee_pairs)
INTERFACE_FUNCTION(__sanitizer_get_total_unique_coverage)
INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file)
-INTERFACE_FUNCTION(__sanitizer_reset_coverage)
-INTERFACE_FUNCTION(__sanitizer_update_counter_bitset_and_clear_counters)
INTERFACE_WEAK_FUNCTION(__sancov_default_options)
INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp)
INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp1)
Modified: vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
==============================================================================
--- vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_coverage_libcdep.cc Thu Apr 20 21:20:56 2017 (r317221)
+++ vendor/compiler-rt/dist/lib/sanitizer_common/sanitizer_coverage_libcdep.cc Thu Apr 20 21:20:59 2017 (r317222)
@@ -57,12 +57,6 @@ static const u64 kMagic = SANITIZER_WORD
static atomic_uint32_t dump_once_guard; // Ensure that CovDump runs only once.
static atomic_uintptr_t coverage_counter;
-static atomic_uintptr_t caller_callee_counter;
-
-static void ResetGlobalCounters() {
- return atomic_store(&coverage_counter, 0, memory_order_relaxed);
- return atomic_store(&caller_callee_counter, 0, memory_order_relaxed);
-}
// pc_array is the array containing the covered PCs.
// To make the pc_array thread- and async-signal-safe it has to be large enough.
@@ -90,25 +84,14 @@ class CoverageData {
void AfterFork(int child_pid);
void Extend(uptr npcs);
void Add(uptr pc, u32 *guard);
- void IndirCall(uptr caller, uptr callee, uptr callee_cache[],
- uptr cache_size);
- void DumpCallerCalleePairs();
- void DumpTrace();
void DumpAsBitSet();
- void DumpCounters();
void DumpOffsets();
void DumpAll();
- ALWAYS_INLINE
- void TraceBasicBlock(u32 *id);
-
void InitializeGuardArray(s32 *guards);
void InitializeGuards(s32 *guards, uptr n, const char *module_name,
uptr caller_pc);
- void InitializeCounters(u8 *counters, uptr n);
void ReinitializeGuards();
- uptr GetNumberOf8bitCounters();
- uptr Update8bitCounterBitsetAndClearCounters(u8 *bitset);
uptr *data();
uptr size() const;
@@ -150,37 +133,6 @@ class CoverageData {
InternalMmapVectorNoCtor<NamedPcRange> comp_unit_name_vec;
InternalMmapVectorNoCtor<NamedPcRange> module_name_vec;
- struct CounterAndSize {
- u8 *counters;
- uptr n;
- };
-
- InternalMmapVectorNoCtor<CounterAndSize> counters_vec;
- uptr num_8bit_counters;
-
- // Caller-Callee (cc) array, size and current index.
- static const uptr kCcArrayMaxSize = FIRST_32_SECOND_64(1 << 18, 1 << 24);
- uptr **cc_array;
- atomic_uintptr_t cc_array_index;
- atomic_uintptr_t cc_array_size;
-
- // Tracing event array, size and current pointer.
- // We record all events (basic block entries) in a global buffer of u32
- // values. Each such value is the index in pc_array.
- // So far the tracing is highly experimental:
- // - not thread-safe;
- // - does not support long traces;
- // - not tuned for performance.
- // Windows doesn't do overcommit (committed virtual memory costs swap), so
- // programs can't reliably map such large amounts of virtual memory.
- // TODO(etienneb): Find a way to support coverage of larger executable
-static const uptr kTrEventArrayMaxSize =
- (SANITIZER_WORDSIZE == 32 || SANITIZER_WINDOWS) ? 1 << 22 : 1 << 30;
- u32 *tr_event_array;
- uptr tr_event_array_size;
- u32 *tr_event_pointer;
- static const uptr kTrPcArrayMaxSize = FIRST_32_SECOND_64(1 << 22, 1 << 27);
-
StaticSpinMutex mu;
};
@@ -217,23 +169,6 @@ void CoverageData::Enable() {
} else {
atomic_store(&pc_array_size, kPcArrayMaxSize, memory_order_relaxed);
}
-
- cc_array = reinterpret_cast<uptr **>(MmapNoReserveOrDie(
- sizeof(uptr *) * kCcArrayMaxSize, "CovInit::cc_array"));
- atomic_store(&cc_array_size, kCcArrayMaxSize, memory_order_relaxed);
- atomic_store(&cc_array_index, 0, memory_order_relaxed);
-
- // Allocate tr_event_array with a guard page at the end.
- tr_event_array = reinterpret_cast<u32 *>(MmapNoReserveOrDie(
- sizeof(tr_event_array[0]) * kTrEventArrayMaxSize + GetMmapGranularity(),
- "CovInit::tr_event_array"));
- MprotectNoAccess(
- reinterpret_cast<uptr>(&tr_event_array[kTrEventArrayMaxSize]),
- GetMmapGranularity());
- tr_event_array_size = kTrEventArrayMaxSize;
- tr_event_pointer = tr_event_array;
-
- num_8bit_counters = 0;
}
void CoverageData::InitializeGuardArray(s32 *guards) {
@@ -251,17 +186,6 @@ void CoverageData::Disable() {
UnmapOrDie(pc_array, sizeof(uptr) * kPcArrayMaxSize);
pc_array = nullptr;
}
- if (cc_array) {
- UnmapOrDie(cc_array, sizeof(uptr *) * kCcArrayMaxSize);
- cc_array = nullptr;
- }
- if (tr_event_array) {
- UnmapOrDie(tr_event_array,
- sizeof(tr_event_array[0]) * kTrEventArrayMaxSize +
- GetMmapGranularity());
- tr_event_array = nullptr;
- tr_event_pointer = nullptr;
- }
if (pc_fd != kInvalidFd) {
CloseFile(pc_fd);
pc_fd = kInvalidFd;
@@ -341,15 +265,6 @@ void CoverageData::Extend(uptr npcs) {
atomic_store(&pc_array_size, size, memory_order_release);
}
-void CoverageData::InitializeCounters(u8 *counters, uptr n) {
- if (!counters) return;
- CHECK_EQ(reinterpret_cast<uptr>(counters) % 16, 0);
- n = RoundUpTo(n, 16); // The compiler must ensure that counters is 16-aligned.
- SpinMutexLock l(&mu);
- counters_vec.push_back({counters, n});
- num_8bit_counters += n;
-}
-
void CoverageData::UpdateModuleNameVec(uptr caller_pc, uptr range_beg,
uptr range_end) {
auto sym = Symbolizer::GetOrInit();
@@ -424,98 +339,6 @@ void CoverageData::Add(uptr pc, u32 *gua
pc_array[idx] = BundlePcAndCounter(pc, counter);
}
-// Registers a pair caller=>callee.
-// When a given caller is seen for the first time, the callee_cache is added
-// to the global array cc_array, callee_cache[0] is set to caller and
-// callee_cache[1] is set to cache_size.
-// Then we are trying to add callee to callee_cache [2,cache_size) if it is
-// not there yet.
-// If the cache is full we drop the callee (may want to fix this later).
-void CoverageData::IndirCall(uptr caller, uptr callee, uptr callee_cache[],
- uptr cache_size) {
- if (!cc_array) return;
- atomic_uintptr_t *atomic_callee_cache =
- reinterpret_cast<atomic_uintptr_t *>(callee_cache);
- uptr zero = 0;
- if (atomic_compare_exchange_strong(&atomic_callee_cache[0], &zero, caller,
- memory_order_seq_cst)) {
- uptr idx = atomic_fetch_add(&cc_array_index, 1, memory_order_relaxed);
- CHECK_LT(idx * sizeof(uptr),
- atomic_load(&cc_array_size, memory_order_acquire));
- callee_cache[1] = cache_size;
- cc_array[idx] = callee_cache;
- }
- CHECK_EQ(atomic_load(&atomic_callee_cache[0], memory_order_relaxed), caller);
- for (uptr i = 2; i < cache_size; i++) {
- uptr was = 0;
- if (atomic_compare_exchange_strong(&atomic_callee_cache[i], &was, callee,
- memory_order_seq_cst)) {
- atomic_fetch_add(&caller_callee_counter, 1, memory_order_relaxed);
- return;
- }
- if (was == callee) // Already have this callee.
- return;
- }
-}
-
-uptr CoverageData::GetNumberOf8bitCounters() {
- return num_8bit_counters;
-}
-
-// Map every 8bit counter to a 8-bit bitset and clear the counter.
-uptr CoverageData::Update8bitCounterBitsetAndClearCounters(u8 *bitset) {
- uptr num_new_bits = 0;
- uptr cur = 0;
- // For better speed we map 8 counters to 8 bytes of bitset at once.
- static const uptr kBatchSize = 8;
- CHECK_EQ(reinterpret_cast<uptr>(bitset) % kBatchSize, 0);
- for (uptr i = 0, len = counters_vec.size(); i < len; i++) {
- u8 *c = counters_vec[i].counters;
- uptr n = counters_vec[i].n;
- CHECK_EQ(n % 16, 0);
- CHECK_EQ(cur % kBatchSize, 0);
- CHECK_EQ(reinterpret_cast<uptr>(c) % kBatchSize, 0);
- if (!bitset) {
- internal_bzero_aligned16(c, n);
- cur += n;
- continue;
- }
- for (uptr j = 0; j < n; j += kBatchSize, cur += kBatchSize) {
- CHECK_LT(cur, num_8bit_counters);
- u64 *pc64 = reinterpret_cast<u64*>(c + j);
- u64 *pb64 = reinterpret_cast<u64*>(bitset + cur);
- u64 c64 = *pc64;
- u64 old_bits_64 = *pb64;
- u64 new_bits_64 = old_bits_64;
- if (c64) {
- *pc64 = 0;
- for (uptr k = 0; k < kBatchSize; k++) {
- u64 x = (c64 >> (8 * k)) & 0xff;
- if (x) {
- u64 bit = 0;
- /**/ if (x >= 128) bit = 128;
- else if (x >= 32) bit = 64;
- else if (x >= 16) bit = 32;
- else if (x >= 8) bit = 16;
- else if (x >= 4) bit = 8;
- else if (x >= 3) bit = 4;
- else if (x >= 2) bit = 2;
- else if (x >= 1) bit = 1;
- u64 mask = bit << (8 * k);
- if (!(new_bits_64 & mask)) {
- num_new_bits++;
- new_bits_64 |= mask;
- }
- }
- }
- *pb64 = new_bits_64;
- }
- }
- }
- CHECK_EQ(cur, num_8bit_counters);
- return num_new_bits;
-}
-
uptr *CoverageData::data() {
return pc_array;
}
@@ -596,132 +419,6 @@ static fd_t CovOpenFile(InternalScopedSt
return fd;
}
-// Dump trace PCs and trace events into two separate files.
-void CoverageData::DumpTrace() {
- uptr max_idx = tr_event_pointer - tr_event_array;
- if (!max_idx) return;
- auto sym = Symbolizer::GetOrInit();
- if (!sym)
- return;
- InternalScopedString out(32 << 20);
- for (uptr i = 0, n = size(); i < n; i++) {
- const char *module_name = "<unknown>";
- uptr module_address = 0;
- sym->GetModuleNameAndOffsetForPC(UnbundlePc(pc_array[i]), &module_name,
- &module_address);
- out.append("%s 0x%zx\n", module_name, module_address);
- }
- InternalScopedString path(kMaxPathLength);
- fd_t fd = CovOpenFile(&path, false, "trace-points");
- if (fd == kInvalidFd) return;
- WriteToFile(fd, out.data(), out.length());
- CloseFile(fd);
-
- fd = CovOpenFile(&path, false, "trace-compunits");
- if (fd == kInvalidFd) return;
- out.clear();
- for (uptr i = 0; i < comp_unit_name_vec.size(); i++)
- out.append("%s\n", comp_unit_name_vec[i].copied_module_name);
- WriteToFile(fd, out.data(), out.length());
- CloseFile(fd);
-
- fd = CovOpenFile(&path, false, "trace-events");
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-vendor
mailing list