[compiler-rt] r209653 - [asancov] Write coverage directly to a memory-mapped file.
Evgeniy Stepanov
eugeni.stepanov at gmail.com
Tue May 27 05:37:52 PDT 2014
Author: eugenis
Date: Tue May 27 07:37:52 2014
New Revision: 209653
URL: http://llvm.org/viewvc/llvm-project?rev=209653&view=rev
Log:
[asancov] Write coverage directly to a memory-mapped file.
This way does not require a __sanitizer_cov_dump() call. That's
important on Android, where apps can be killed at arbitrary time.
We write raw PCs to disk instead of module offsets; we also write
memory layout to a separate file. This increases dump size by the
factor of 2 on 64-bit systems.
Added:
compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
- copied, changed from r209626, compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc (with props)
compiler-rt/trunk/test/asan/TestCases/Linux/coverage-direct-large.cc (with props)
compiler-rt/trunk/test/asan/TestCases/Linux/coverage-direct.cc (with props)
Removed:
compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage.cc
Modified:
compiler-rt/trunk/lib/asan/asan_interceptors.cc
compiler-rt/trunk/lib/msan/msan_interceptors.cc
compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h
compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h
compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h
compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc
compiler-rt/trunk/lib/sanitizer_common/scripts/sancov.py
compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Tue May 27 07:37:52 2014
@@ -146,6 +146,8 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free,
} while (false)
#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
+#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res) CovUpdateMapping()
+#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CovUpdateMapping()
#include "sanitizer_common/sanitizer_common_interceptors.inc"
#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s)
Modified: compiler-rt/trunk/lib/msan/msan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_interceptors.cc?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_interceptors.cc Tue May 27 07:37:52 2014
@@ -886,25 +886,6 @@ INTERCEPTOR(char *, dlerror, int fake) {
return res;
}
-// dlopen() ultimately calls mmap() down inside the loader, which generally
-// doesn't participate in dynamic symbol resolution. Therefore we won't
-// intercept its calls to mmap, and we have to hook it here. The loader
-// initializes the module before returning, so without the dynamic component, we
-// won't be able to clear the shadow before the initializers. Fixing this would
-// require putting our own initializer first to clear the shadow.
-INTERCEPTOR(void *, dlopen, const char *filename, int flag) {
- ENSURE_MSAN_INITED();
- EnterLoader();
- link_map *map = (link_map *)REAL(dlopen)(filename, flag);
- ExitLoader();
- if (!__msan_has_dynamic_component() && map) {
- // If msandr didn't clear the shadow before the initializers ran, we do it
- // ourselves afterwards.
- ForEachMappedRegion(map, __msan_unpoison);
- }
- return (void *)map;
-}
-
typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size,
void *data);
struct dl_iterate_phdr_data {
@@ -1234,6 +1215,13 @@ int OnExit() {
} while (false) // FIXME
#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
+#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, map) \
+ if (!__msan_has_dynamic_component() && map) { \
+ /* If msandr didn't clear the shadow before the initializers ran, we do */ \
+ /* it ourselves afterwards. */ \
+ ForEachMappedRegion((link_map *)map, __msan_unpoison); \
+ }
+
#include "sanitizer_common/sanitizer_common_interceptors.inc"
#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
@@ -1559,7 +1547,6 @@ void InitializeInterceptors() {
INTERCEPT_FUNCTION(recvfrom);
INTERCEPT_FUNCTION(dladdr);
INTERCEPT_FUNCTION(dlerror);
- INTERCEPT_FUNCTION(dlopen);
INTERCEPT_FUNCTION(dl_iterate_phdr);
INTERCEPT_FUNCTION(getrusage);
INTERCEPT_FUNCTION(sigaction);
Modified: compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt Tue May 27 07:37:52 2014
@@ -4,7 +4,6 @@
set(SANITIZER_SOURCES
sanitizer_allocator.cc
sanitizer_common.cc
- sanitizer_coverage.cc
sanitizer_deadlock_detector1.cc
sanitizer_deadlock_detector2.cc
sanitizer_flags.cc
@@ -31,6 +30,8 @@ set(SANITIZER_SOURCES
set(SANITIZER_LIBCDEP_SOURCES
sanitizer_common_libcdep.cc
+ sanitizer_coverage_libcdep.cc
+ sanitizer_coverage_mapping_libcdep.cc
sanitizer_linux_libcdep.cc
sanitizer_posix_libcdep.cc
sanitizer_stacktrace_libcdep.cc
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc Tue May 27 07:37:52 2014
@@ -263,11 +263,6 @@ void DecreaseTotalMmap(uptr size) {
atomic_fetch_sub(&g_total_mmaped, size, memory_order_relaxed);
}
-static void (*sandboxing_callback)();
-void SetSandboxingCallback(void (*f)()) {
- sandboxing_callback = f;
-}
-
} // namespace __sanitizer
using namespace __sanitizer; // NOLINT
@@ -300,13 +295,6 @@ void __sanitizer_set_report_path(const c
}
}
-void NOINLINE
-__sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args) {
- PrepareForSandboxing(args);
- if (sandboxing_callback)
- sandboxing_callback();
-}
-
void __sanitizer_report_error_summary(const char *error_summary) {
Printf("%s\n", error_summary);
}
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Tue May 27 07:37:52 2014
@@ -161,6 +161,7 @@ uptr ReadFileToBuffer(const char *file_n
// (or NULL if the mapping failes). Stores the size of mmaped region
// in '*buff_size'.
void *MapFileToMemory(const char *file_name, uptr *buff_size);
+void *MapWritableFileToMemory(void *addr, uptr size, uptr fd, uptr offset);
// Error report formatting.
const char *StripPathPrefix(const char *filepath,
@@ -187,6 +188,8 @@ void PrepareForSandboxing(__sanitizer_sa
void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args);
void SetSandboxingCallback(void (*f)());
+void CovUpdateMapping();
+
void InitTlsSize();
uptr GetTlsSize();
@@ -479,6 +482,10 @@ class LoadedModule {
const char *full_name() const { return full_name_; }
uptr base_address() const { return base_address_; }
+ uptr n_ranges() const { return n_ranges_; }
+ uptr address_range_start(int i) const { return ranges_[i].beg; }
+ uptr address_range_end(int i) const { return ranges_[i].end; }
+
private:
struct AddressRange {
uptr beg;
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Tue May 27 07:37:52 2014
@@ -75,6 +75,19 @@
#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) {}
#endif
+#ifndef COMMON_INTERCEPTOR_LIBRARY_LOADED
+#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, map) {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_LIBRARY_UNLOADED
+#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_ENTER_NOIGNORE
+#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, ...) \
+ COMMON_INTERCEPTOR_ENTER(ctx, __VA_ARGS__)
+#endif
+
struct FileMetadata {
// For open_memstream().
char **addr;
@@ -4036,6 +4049,29 @@ INTERCEPTOR(int, fclose, __sanitizer_FIL
#define INIT_FCLOSE
#endif
+#if SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
+INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag);
+ void *res = REAL(dlopen)(filename, flag);
+ COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res);
+ return res;
+}
+
+INTERCEPTOR(int, dlclose, void *handle) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlclose, handle);
+ int res = REAL(dlclose)(handle);
+ COMMON_INTERCEPTOR_LIBRARY_UNLOADED();
+ return res;
+}
+#define INIT_DLOPEN_DLCLOSE \
+ COMMON_INTERCEPT_FUNCTION(dlopen); \
+ COMMON_INTERCEPT_FUNCTION(dlclose);
+#else
+#define INIT_DLOPEN_DLCLOSE
+#endif
+
static void InitializeCommonInterceptors() {
static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap();
@@ -4177,4 +4213,5 @@ static void InitializeCommonInterceptors
INIT_OBSTACK;
INIT_FFLUSH;
INIT_FCLOSE;
+ INIT_DLOPEN_DLCLOSE;
}
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc Tue May 27 07:37:52 2014
@@ -41,4 +41,17 @@ bool ColorizeReports() {
return internal_strcmp(flag, "always") == 0 ||
(internal_strcmp(flag, "auto") == 0 && PrintsToTtyCached());
}
+
+static void (*sandboxing_callback)();
+void SetSandboxingCallback(void (*f)()) {
+ sandboxing_callback = f;
+}
+
} // namespace __sanitizer
+
+void NOINLINE
+__sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args) {
+ PrepareForSandboxing(args);
+ if (sandboxing_callback)
+ sandboxing_callback();
+}
Removed: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage.cc?rev=209652&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage.cc (removed)
@@ -1,238 +0,0 @@
-//===-- sanitizer_coverage.cc ---------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Sanitizer Coverage.
-// This file implements run-time support for a poor man's coverage tool.
-//
-// Compiler instrumentation:
-// For every interesting basic block the compiler injects the following code:
-// if (*Guard) {
-// __sanitizer_cov();
-// *Guard = 1;
-// }
-// It's fine to call __sanitizer_cov more than once for a given block.
-//
-// Run-time:
-// - __sanitizer_cov(): record that we've executed the PC (GET_CALLER_PC).
-// - __sanitizer_cov_dump: dump the coverage data to disk.
-// For every module of the current process that has coverage data
-// this will create a file module_name.PID.sancov. The file format is simple:
-// it's just a sorted sequence of 4-byte offsets in the module.
-//
-// Eventually, this coverage implementation should be obsoleted by a more
-// powerful general purpose Clang/LLVM coverage instrumentation.
-// Consider this implementation as prototype.
-//
-// FIXME: support (or at least test with) dlclose.
-//===----------------------------------------------------------------------===//
-
-#include "sanitizer_allocator_internal.h"
-#include "sanitizer_common.h"
-#include "sanitizer_libc.h"
-#include "sanitizer_mutex.h"
-#include "sanitizer_procmaps.h"
-#include "sanitizer_stacktrace.h"
-#include "sanitizer_flags.h"
-
-atomic_uint32_t dump_once_guard; // Ensure that CovDump runs only once.
-
-// 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.
-// 128M counters "ought to be enough for anybody" (4M on 32-bit).
-// pc_array is allocated with MmapNoReserveOrDie and so it uses only as
-// much RAM as it really needs.
-static const uptr kPcArraySize = FIRST_32_SECOND_64(1 << 22, 1 << 27);
-static uptr *pc_array;
-static atomic_uintptr_t pc_array_index;
-
-static bool cov_sandboxed = false;
-static int cov_fd = kInvalidFd;
-static unsigned int cov_max_block_size = 0;
-
-namespace __sanitizer {
-
-// Simply add the pc into the vector under lock. If the function is called more
-// than once for a given PC it will be inserted multiple times, which is fine.
-static void CovAdd(uptr pc) {
- if (!pc_array) return;
- uptr idx = atomic_fetch_add(&pc_array_index, 1, memory_order_relaxed);
- CHECK_LT(idx, kPcArraySize);
- pc_array[idx] = pc;
-}
-
-void CovInit() {
- pc_array = reinterpret_cast<uptr *>(
- MmapNoReserveOrDie(sizeof(uptr) * kPcArraySize, "CovInit"));
-}
-
-static inline bool CompareLess(const uptr &a, const uptr &b) {
- return a < b;
-}
-
-// Block layout for packed file format: header, followed by module name (no
-// trailing zero), followed by data blob.
-struct CovHeader {
- int pid;
- unsigned int module_name_length;
- unsigned int data_length;
-};
-
-static void CovWritePacked(int pid, const char *module, const void *blob,
- unsigned int blob_size) {
- if (cov_fd < 0) return;
- unsigned module_name_length = internal_strlen(module);
- CovHeader header = {pid, module_name_length, blob_size};
-
- if (cov_max_block_size == 0) {
- // Writing to a file. Just go ahead.
- internal_write(cov_fd, &header, sizeof(header));
- internal_write(cov_fd, module, module_name_length);
- internal_write(cov_fd, blob, blob_size);
- } else {
- // Writing to a socket. We want to split the data into appropriately sized
- // blocks.
- InternalScopedBuffer<char> block(cov_max_block_size);
- CHECK_EQ((uptr)block.data(), (uptr)(CovHeader *)block.data());
- uptr header_size_with_module = sizeof(header) + module_name_length;
- CHECK_LT(header_size_with_module, cov_max_block_size);
- unsigned int max_payload_size =
- cov_max_block_size - header_size_with_module;
- char *block_pos = block.data();
- internal_memcpy(block_pos, &header, sizeof(header));
- block_pos += sizeof(header);
- internal_memcpy(block_pos, module, module_name_length);
- block_pos += module_name_length;
- char *block_data_begin = block_pos;
- char *blob_pos = (char *)blob;
- while (blob_size > 0) {
- unsigned int payload_size = Min(blob_size, max_payload_size);
- blob_size -= payload_size;
- internal_memcpy(block_data_begin, blob_pos, payload_size);
- blob_pos += payload_size;
- ((CovHeader *)block.data())->data_length = payload_size;
- internal_write(cov_fd, block.data(),
- header_size_with_module + payload_size);
- }
- }
-}
-
-// If packed = false: <name>.<pid>.<sancov> (name = module name).
-// If packed = true and name == 0: <pid>.<sancov>.<packed>.
-// If packed = true and name != 0: <name>.<sancov>.<packed> (name is
-// user-supplied).
-static int CovOpenFile(bool packed, const char* name) {
- InternalScopedBuffer<char> path(1024);
- if (!packed) {
- CHECK(name);
- internal_snprintf((char *)path.data(), path.size(), "%s.%zd.sancov",
- name, internal_getpid());
- } else {
- if (!name)
- internal_snprintf((char *)path.data(), path.size(), "%zd.sancov.packed",
- internal_getpid());
- else
- internal_snprintf((char *)path.data(), path.size(), "%s.sancov.packed",
- name);
- }
- uptr fd = OpenFile(path.data(), true);
- if (internal_iserror(fd)) {
- Report(" SanitizerCoverage: failed to open %s for writing\n", path.data());
- return -1;
- }
- return fd;
-}
-
-// Dump the coverage on disk.
-static void CovDump() {
- if (!common_flags()->coverage) return;
-#if !SANITIZER_WINDOWS
- if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed))
- return;
- uptr size = atomic_load(&pc_array_index, memory_order_relaxed);
- InternalSort(&pc_array, size, CompareLess);
- InternalMmapVector<u32> offsets(size);
- const uptr *vb = pc_array;
- const uptr *ve = vb + size;
- MemoryMappingLayout proc_maps(/*cache_enabled*/true);
- uptr mb, me, off, prot;
- InternalScopedBuffer<char> module(4096);
- InternalScopedBuffer<char> path(4096 * 2);
- for (int i = 0;
- proc_maps.Next(&mb, &me, &off, module.data(), module.size(), &prot);
- i++) {
- if ((prot & MemoryMappingLayout::kProtectionExecute) == 0)
- continue;
- while (vb < ve && *vb < mb) vb++;
- if (vb >= ve) break;
- if (*vb < me) {
- offsets.clear();
- const uptr *old_vb = vb;
- CHECK_LE(off, *vb);
- for (; vb < ve && *vb < me; vb++) {
- uptr diff = *vb - (i ? mb : 0) + off;
- CHECK_LE(diff, 0xffffffffU);
- offsets.push_back(static_cast<u32>(diff));
- }
- char *module_name = StripModuleName(module.data());
- if (cov_sandboxed) {
- if (cov_fd >= 0) {
- CovWritePacked(internal_getpid(), module_name, offsets.data(),
- offsets.size() * sizeof(u32));
- VReport(1, " CovDump: %zd PCs written to packed file\n", vb - old_vb);
- }
- } else {
- // One file per module per process.
- internal_snprintf((char *)path.data(), path.size(), "%s.%zd.sancov",
- module_name, internal_getpid());
- int fd = CovOpenFile(false /* packed */, module_name);
- if (fd > 0) {
- internal_write(fd, offsets.data(), offsets.size() * sizeof(u32));
- internal_close(fd);
- VReport(1, " CovDump: %s: %zd PCs written\n", path.data(),
- vb - old_vb);
- }
- }
- InternalFree(module_name);
- }
- }
- if (cov_fd >= 0)
- internal_close(cov_fd);
-#endif // !SANITIZER_WINDOWS
-}
-
-void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
- if (!args) return;
- if (!common_flags()->coverage) return;
- cov_sandboxed = args->coverage_sandboxed;
- if (!cov_sandboxed) return;
- cov_fd = args->coverage_fd;
- cov_max_block_size = args->coverage_max_block_size;
- if (cov_fd < 0)
- // Pre-open the file now. The sandbox won't allow us to do it later.
- cov_fd = CovOpenFile(true /* packed */, 0);
-}
-
-int MaybeOpenCovFile(const char *name) {
- CHECK(name);
- if (!common_flags()->coverage) return -1;
- return CovOpenFile(true /* packed */, name);
-}
-} // namespace __sanitizer
-
-extern "C" {
-SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov() {
- CovAdd(StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()));
-}
-SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { CovDump(); }
-SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init() { CovInit(); }
-SANITIZER_INTERFACE_ATTRIBUTE
-sptr __sanitizer_maybe_open_cov_file(const char *name) {
- return MaybeOpenCovFile(name);
-}
-} // extern "C"
Copied: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc (from r209626, compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage.cc)
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc?p2=compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc&p1=compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage.cc&r1=209626&r2=209653&rev=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc Tue May 27 07:37:52 2014
@@ -45,11 +45,10 @@ atomic_uint32_t dump_once_guard; // Ens
// 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.
// 128M counters "ought to be enough for anybody" (4M on 32-bit).
-// pc_array is allocated with MmapNoReserveOrDie and so it uses only as
-// much RAM as it really needs.
-static const uptr kPcArraySize = FIRST_32_SECOND_64(1 << 22, 1 << 27);
-static uptr *pc_array;
-static atomic_uintptr_t pc_array_index;
+
+// With coverage_direct=1 in ASAN_OPTIONS, pc_array memory is mapped to a file.
+// In this mode, __sanitizer_cov_dump does nothing, and CovUpdateMapping()
+// dump current memory layout to another file.
static bool cov_sandboxed = false;
static int cov_fd = kInvalidFd;
@@ -57,22 +56,114 @@ static unsigned int cov_max_block_size =
namespace __sanitizer {
+class CoverageData {
+ public:
+ void Init();
+ void Extend(uptr npcs);
+ void Add(uptr pc);
+
+ uptr *data();
+ uptr size();
+
+ private:
+ // Maximal size pc array may ever grow.
+ // We MmapNoReserve this space to ensure that the array is contiguous.
+ static const uptr kPcArrayMaxSize = FIRST_32_SECOND_64(1 << 22, 1 << 27);
+ // The amount file mapping for the pc array is grown by.
+ static const uptr kPcArrayMmapSize = 64 * 1024;
+
+ // pc_array is allocated with MmapNoReserveOrDie and so it uses only as
+ // much RAM as it really needs.
+ uptr *pc_array;
+ // Index of the first available pc_array slot.
+ atomic_uintptr_t pc_array_index;
+ // Array size.
+ atomic_uintptr_t pc_array_size;
+ // Current file mapped size of the pc array.
+ uptr pc_array_mapped_size;
+ // Descriptor of the file mapped pc array.
+ int pc_fd;
+ StaticSpinMutex mu;
+
+ void DirectInit();
+};
+
+static CoverageData coverage_data;
+
+void CoverageData::DirectInit() {
+ InternalScopedString path(64);
+ internal_snprintf((char *)path.data(), path.size(), "%zd.sancov.raw",
+ internal_getpid());
+ pc_fd = OpenFile(path.data(), true);
+ if (internal_iserror(pc_fd)) {
+ Report(" Coverage: failed to open %s for writing\n", path.data());
+ Die();
+ }
+
+ atomic_store(&pc_array_size, 0, memory_order_relaxed);
+ pc_array_mapped_size = 0;
+
+ CovUpdateMapping();
+}
+
+void CoverageData::Init() {
+ pc_array = reinterpret_cast<uptr *>(
+ MmapNoReserveOrDie(sizeof(uptr) * kPcArrayMaxSize, "CovInit"));
+ if (common_flags()->coverage_direct) {
+ DirectInit();
+ } else {
+ pc_fd = 0;
+ atomic_store(&pc_array_size, kPcArrayMaxSize, memory_order_relaxed);
+ }
+}
+
+// Extend coverage PC array to fit additional npcs elements.
+void CoverageData::Extend(uptr npcs) {
+ // If pc_fd=0, pc array is a huge anonymous mapping that does not need to be
+ // resized.
+ if (!pc_fd) return;
+ SpinMutexLock l(&mu);
+
+ uptr size = atomic_load(&pc_array_size, memory_order_relaxed);
+ size += npcs * sizeof(uptr);
+
+ if (size > pc_array_mapped_size) {
+ uptr new_mapped_size = pc_array_mapped_size;
+ while (size > new_mapped_size) new_mapped_size += kPcArrayMmapSize;
+
+ // Extend the file and map the new space at the end of pc_array.
+ uptr res = internal_ftruncate(pc_fd, new_mapped_size);
+ int err;
+ if (internal_iserror(res, &err)) {
+ Printf("failed to extend raw coverage file: %d\n", err);
+ Die();
+ }
+ void *p = MapWritableFileToMemory(pc_array + pc_array_mapped_size,
+ new_mapped_size - pc_array_mapped_size,
+ pc_fd, pc_array_mapped_size);
+ CHECK_EQ(p, pc_array + pc_array_mapped_size);
+ pc_array_mapped_size = new_mapped_size;
+ }
+
+ atomic_store(&pc_array_size, size, memory_order_release);
+}
+
// Simply add the pc into the vector under lock. If the function is called more
// than once for a given PC it will be inserted multiple times, which is fine.
-static void CovAdd(uptr pc) {
+void CoverageData::Add(uptr pc) {
if (!pc_array) return;
uptr idx = atomic_fetch_add(&pc_array_index, 1, memory_order_relaxed);
- CHECK_LT(idx, kPcArraySize);
+ CHECK_LT(idx * sizeof(uptr),
+ atomic_load(&pc_array_size, memory_order_acquire));
pc_array[idx] = pc;
}
-void CovInit() {
- pc_array = reinterpret_cast<uptr *>(
- MmapNoReserveOrDie(sizeof(uptr) * kPcArraySize, "CovInit"));
+uptr *CoverageData::data() {
+ return pc_array;
}
-static inline bool CompareLess(const uptr &a, const uptr &b) {
- return a < b;
+uptr CoverageData::size() {
+ return atomic_load(&pc_array_index, memory_order_relaxed);
}
// Block layout for packed file format: header, followed by module name (no
@@ -150,15 +241,15 @@ static int CovOpenFile(bool packed, cons
// Dump the coverage on disk.
static void CovDump() {
- if (!common_flags()->coverage) return;
+ if (!common_flags()->coverage || common_flags()->coverage_direct) return;
#if !SANITIZER_WINDOWS
if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed))
return;
- uptr size = atomic_load(&pc_array_index, memory_order_relaxed);
- InternalSort(&pc_array, size, CompareLess);
+ uptr size = coverage_data.size();
InternalMmapVector<u32> offsets(size);
- const uptr *vb = pc_array;
- const uptr *ve = vb + size;
+ uptr *vb = coverage_data.data();
+ uptr *ve = vb + size;
+ SortArray(vb, size);
MemoryMappingLayout proc_maps(/*cache_enabled*/true);
uptr mb, me, off, prot;
InternalScopedBuffer<char> module(4096);
@@ -227,10 +318,15 @@ int MaybeOpenCovFile(const char *name) {
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov() {
- CovAdd(StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()));
+ coverage_data.Add(StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()));
}
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { CovDump(); }
-SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init() { CovInit(); }
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init() {
+ coverage_data.Init();
+}
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_module_init(uptr npcs) {
+ coverage_data.Extend(npcs);
+}
SANITIZER_INTERFACE_ATTRIBUTE
sptr __sanitizer_maybe_open_cov_file(const char *name) {
return MaybeOpenCovFile(name);
Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc?rev=209653&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc Tue May 27 07:37:52 2014
@@ -0,0 +1,97 @@
+//===-- sanitizer_coverage_mapping.cc -------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Mmap-based implementation of sanitizer coverage.
+//
+// This is part of the implementation of code coverage that does not require
+// __sanitizer_cov_dump() call. Data is stored in 2 files per process.
+//
+// $pid.sancov.map describes process memory layout in the following text-based
+// format:
+// <pointer size in bits> // 1 line, 32 or 64
+// <mapping start> <mapping end> <base address> <dso name> // repeated
+// ...
+// Mapping lines are NOT sorted. This file is updated every time memory layout
+// is changed (i.e. in dlopen() and dlclose() interceptors).
+//
+// $pid.sancov.raw is a binary dump of PC values, sizeof(uptr) each. Again, not
+// sorted. This file is extended by 64Kb at a time and mapped into memory. It
+// contains one or more 0 words at the end, up to the next 64Kb aligned offset.
+//
+// To convert these 2 files to the usual .sancov format, run sancov.py rawunpack
+// $pid.sancov.raw.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_procmaps.h"
+
+namespace __sanitizer {
+
+static const uptr kMaxNumberOfModules = 1 << 14;
+
+void CovUpdateMapping() {
+ if (!common_flags()->coverage || !common_flags()->coverage_direct) return;
+
+ int err;
+ InternalScopedString tmp_path(64);
+ internal_snprintf((char *)tmp_path.data(), tmp_path.size(),
+ "%zd.sancov.map.tmp", internal_getpid());
+ uptr map_fd = OpenFile(tmp_path.data(), true);
+ if (internal_iserror(map_fd)) {
+ Report(" Coverage: failed to open %s for writing\n", tmp_path.data());
+ Die();
+ }
+
+ InternalScopedBuffer<char> modules_data(kMaxNumberOfModules *
+ sizeof(LoadedModule));
+ LoadedModule *modules = (LoadedModule *)modules_data.data();
+ CHECK(modules);
+ int n_modules = GetListOfModules(modules, kMaxNumberOfModules,
+ /* filter */ 0);
+
+ InternalScopedString line(4096);
+ line.append("%d\n", sizeof(uptr) * 8);
+ uptr res = internal_write(map_fd, line.data(), line.length());
+ if (internal_iserror(res, &err)) {
+ Printf("sancov.map write failed: %d\n", err);
+ Die();
+ }
+ line.clear();
+
+ for (int i = 0; i < n_modules; ++i) {
+ char *module_name = StripModuleName(modules[i].full_name());
+ for (unsigned j = 0; j < modules[i].n_ranges(); ++j) {
+ line.append("%zx %zx %zx %s\n", modules[i].address_range_start(j),
+ modules[i].address_range_end(j), modules[i].base_address(),
+ module_name);
+ res = internal_write(map_fd, line.data(), line.length());
+ if (internal_iserror(res, &err)) {
+ Printf("sancov.map write failed: %d\n", err);
+ Die();
+ }
+ line.clear();
+ }
+ InternalFree(module_name);
+ }
+
+ internal_close(map_fd);
+
+ InternalScopedString path(64);
+ internal_snprintf((char *)path.data(), path.size(), "%zd.sancov.map",
+ internal_getpid());
+ res = internal_rename(tmp_path.data(), path.data());
+ if (internal_iserror(res, &err)) {
+ Printf("sancov.map rename failed: %d\n", err);
+ Die();
+ }
+}
+
+} // namespace __sanitizer
Propchange: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc
------------------------------------------------------------------------------
svn:eol-style = LF
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc Tue May 27 07:37:52 2014
@@ -55,6 +55,7 @@ void SetCommonFlagsDefaults(CommonFlags
f->legacy_pthread_cond = false;
f->intercept_tls_get_addr = false;
f->coverage = false;
+ f->coverage_direct = false;
f->full_address_space = false;
}
@@ -127,6 +128,10 @@ void ParseCommonFlagsFromString(CommonFl
ParseFlag(str, &f->coverage, "coverage",
"If set, coverage information will be dumped at program shutdown (if the "
"coverage instrumentation was enabled at compile time).");
+ ParseFlag(str, &f->coverage_direct, "coverage_direct",
+ "If set, coverage information will be dumped directly to a memory "
+ "mapped file. This way data is not lost even if the process is "
+ "suddenly killed.");
ParseFlag(str, &f->full_address_space, "full_address_space",
"Sanitize complete address space; "
"by default kernel area on 32-bit platforms will not be sanitized");
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h Tue May 27 07:37:52 2014
@@ -54,6 +54,7 @@ struct CommonFlags {
bool help;
uptr mmap_limit_mb;
bool coverage;
+ bool coverage_direct;
bool full_address_space;
};
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h Tue May 27 07:37:52 2014
@@ -74,6 +74,7 @@ uptr internal_open(const char *filename,
uptr internal_read(fd_t fd, void *buf, uptr count);
uptr internal_write(fd_t fd, const void *buf, uptr count);
+uptr internal_ftruncate(fd_t fd, uptr size);
// OS
uptr internal_filesize(fd_t fd); // -1 on error.
@@ -83,6 +84,7 @@ uptr internal_fstat(fd_t fd, void *buf);
uptr internal_dup2(int oldfd, int newfd);
uptr internal_readlink(const char *path, char *buf, uptr bufsize);
uptr internal_unlink(const char *path);
+uptr internal_rename(const char *oldpath, const char *newpath);
void NORETURN internal__exit(int exitcode);
uptr internal_lseek(fd_t fd, OFF_T offset, int whence);
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc Tue May 27 07:37:52 2014
@@ -134,7 +134,7 @@ uptr internal_open(const char *filename,
uptr OpenFile(const char *filename, bool write) {
return internal_open(filename,
- write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
+ write ? O_RDWR | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
}
uptr internal_read(fd_t fd, void *buf, uptr count) {
@@ -151,6 +151,12 @@ uptr internal_write(fd_t fd, const void
return res;
}
+uptr internal_ftruncate(fd_t fd, uptr size) {
+ sptr res;
+ HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd, size));
+ return res;
+}
+
#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && !SANITIZER_FREEBSD
static void stat64_to_stat(struct stat64 *in, struct stat *out) {
internal_memset(out, 0, sizeof(*out));
@@ -246,6 +252,15 @@ uptr internal_unlink(const char *path) {
#endif
}
+uptr internal_rename(const char *oldpath, const char *newpath) {
+#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+ return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
+ (uptr)newpath);
+#else
+ return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath);
+#endif
+}
+
uptr internal_sched_yield() {
return internal_syscall(SYSCALL(sched_yield));
}
@@ -390,20 +405,6 @@ void GetThreadStackAndTls(bool main, upt
}
#endif // SANITIZER_GO
-void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
- // Some kinds of sandboxes may forbid filesystem access, so we won't be able
- // to read the file mappings from /proc/self/maps. Luckily, neither the
- // process will be able to load additional libraries, so it's fine to use the
- // cached mappings.
- MemoryMappingLayout::CacheMemoryMappings();
- // Same for /proc/self/exe in the symbolizer.
-#if !SANITIZER_GO
- if (Symbolizer *sym = Symbolizer::GetOrNull())
- sym->PrepareForSandboxing();
- CovPrepareForSandboxing(args);
-#endif
-}
-
enum MutexState {
MtxUnlocked = 0,
MtxLocked = 1,
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc Tue May 27 07:37:52 2014
@@ -22,6 +22,7 @@
#include "sanitizer_procmaps.h"
#include "sanitizer_stacktrace.h"
#include "sanitizer_atomic.h"
+#include "sanitizer_symbolizer.h"
#include <dlfcn.h>
#include <pthread.h>
@@ -529,6 +530,20 @@ void SetIndirectCallWrapper(uptr wrapper
indirect_call_wrapper = wrapper;
}
+void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
+ // Some kinds of sandboxes may forbid filesystem access, so we won't be able
+ // to read the file mappings from /proc/self/maps. Luckily, neither the
+ // process will be able to load additional libraries, so it's fine to use the
+ // cached mappings.
+ MemoryMappingLayout::CacheMemoryMappings();
+ // Same for /proc/self/exe in the symbolizer.
+#if !SANITIZER_GO
+ if (Symbolizer *sym = Symbolizer::GetOrNull())
+ sym->PrepareForSandboxing();
+ CovPrepareForSandboxing(args);
+#endif
+}
+
} // namespace __sanitizer
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc Tue May 27 07:37:52 2014
@@ -131,6 +131,14 @@ int internal_fork() {
return fork();
}
+uptr internal_rename(const char *oldpath, const char *newpath) {
+ return rename(oldpath, newpath);
+}
+
+uptr internal_ftruncate(fd_t fd, uptr size) {
+ return ftruncate(fd, size);
+}
+
// ----------------- sanitizer_common.h
bool FileExists(const char *filename) {
struct stat st;
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h Tue May 27 07:37:52 2014
@@ -203,5 +203,6 @@
#define SANITIZER_INTERCEPT_OBSTACK SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_FFLUSH SI_NOT_WINDOWS
#define SANITIZER_INTERCEPT_FCLOSE SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_DLOPEN_DLCLOSE SI_NOT_WINDOWS
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc Tue May 27 07:37:52 2014
@@ -206,6 +206,17 @@ void *MapFileToMemory(const char *file_n
return internal_iserror(map) ? 0 : (void *)map;
}
+void *MapWritableFileToMemory(void *addr, uptr size, uptr fd, uptr offset) {
+ uptr flags = MAP_SHARED;
+ if (addr) flags |= MAP_FIXED;
+ uptr p = internal_mmap(addr, size, PROT_READ | PROT_WRITE, flags, fd, offset);
+ if (internal_iserror(p)) {
+ Printf("could not map writable file (%zd, %zu, %zu): %zd\n", fd, offset,
+ size, p);
+ return 0;
+ }
+ return (void *)p;
+}
static inline bool IntervalsAreSeparate(uptr start1, uptr end1,
uptr start2, uptr end2) {
Modified: compiler-rt/trunk/lib/sanitizer_common/scripts/sancov.py
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/scripts/sancov.py?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/scripts/sancov.py (original)
+++ compiler-rt/trunk/lib/sanitizer_common/scripts/sancov.py Tue May 27 07:37:52 2014
@@ -6,6 +6,8 @@
import array
import struct
import sys
+import bisect
+import os.path
prog_name = "";
@@ -74,6 +76,63 @@ def Unpack(files):
for f in files:
UnpackOneFile(f)
+def UnpackOneRawFile(path, map_path):
+ mem_map = []
+ with open(map_path, mode="rt") as f_map:
+ print >> sys.stderr, "%s: reading map %s" % (prog_name, map_path)
+ bits = int(f_map.readline())
+ for line in f_map:
+ parts = line.rstrip().split()
+ assert len(parts) == 4
+ mem_map.append((int(parts[0], 16),
+ int(parts[1], 16),
+ int(parts[2], 16),
+ parts[3]))
+ mem_map.sort(key=lambda m : m[0])
+ mem_map_keys = [m[0] for m in mem_map]
+
+ print mem_map
+ with open(path, mode="rb") as f:
+ print >> sys.stderr, "%s: unpacking %s" % (prog_name, path)
+
+ f.seek(0, 2)
+ size = f.tell()
+ f.seek(0, 0)
+ if bits == 64:
+ typecode = 'L'
+ else:
+ typecode = 'I'
+ pcs = array.array(typecode, f.read(size))
+ mem_map_pcs = [[] for i in range(0, len(mem_map))]
+
+ for pc in pcs:
+ if pc == 0: continue
+ map_idx = bisect.bisect(mem_map_keys, pc) - 1
+ (start, end, base, module_path) = mem_map[map_idx]
+ print pc
+ print start, end, base, module_path
+ assert pc >= start
+ if pc >= end:
+ print >> sys.stderr, "warning: %s: pc %x outside of any known mapping" % (prog_name, pc)
+ continue
+ mem_map_pcs[map_idx].append(pc - base)
+
+ for ((start, end, base, module_path), pc_list) in zip(mem_map, mem_map_pcs):
+ if len(pc_list) == 0: continue
+ assert path.endswith('.sancov.raw')
+ dst_path = module_path + '.' + os.path.basename(path)[:-4]
+ print "writing %d PCs to %s" % (len(pc_list), dst_path)
+ arr = array.array('I')
+ arr.fromlist(sorted(pc_list))
+ with open(dst_path, 'ab') as f2:
+ arr.tofile(f2)
+
+def RawUnpack(files):
+ for f in files:
+ if not f.endswith('.sancov.raw'):
+ raise Exception('Unexpected raw file name %s' % f)
+ f_map = f[:-3] + 'map'
+ UnpackOneRawFile(f, f_map)
if __name__ == '__main__':
prog_name = sys.argv[0]
@@ -85,5 +144,7 @@ if __name__ == '__main__':
MergeAndPrint(sys.argv[2:])
elif sys.argv[1] == "unpack":
Unpack(sys.argv[2:])
+ elif sys.argv[1] == "rawunpack":
+ RawUnpack(sys.argv[2:])
else:
Usage()
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=209653&r1=209652&r2=209653&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Tue May 27 07:37:52 2014
@@ -207,7 +207,7 @@ ScopedInterceptor::~ScopedInterceptor()
if (REAL(func) == 0) { \
Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \
Die(); \
- } \
+ } \
if (thr->ignore_interceptors || thr->in_ignored_lib) \
return REAL(func)(__VA_ARGS__); \
/**/
@@ -259,20 +259,6 @@ TSAN_INTERCEPTOR(int, nanosleep, void *r
return res;
}
-TSAN_INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
- SCOPED_INTERCEPTOR_RAW(dlopen, filename, flag);
- void *res = REAL(dlopen)(filename, flag);
- libignore()->OnLibraryLoaded(filename);
- return res;
-}
-
-TSAN_INTERCEPTOR(int, dlclose, void *handle) {
- SCOPED_INTERCEPTOR_RAW(dlclose, handle);
- int res = REAL(dlclose)(handle);
- libignore()->OnLibraryUnloaded();
- return res;
-}
-
class AtExitContext {
public:
AtExitContext()
@@ -2021,6 +2007,12 @@ static void HandleRecvmsg(ThreadState *t
ctx = (void *)&_ctx; \
(void) ctx;
+#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, func, ...) \
+ SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
+ TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
+ ctx = (void *)&_ctx; \
+ (void) ctx;
+
#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) \
Acquire(thr, pc, File2addr(path)); \
if (file) { \
@@ -2034,6 +2026,12 @@ static void HandleRecvmsg(ThreadState *t
if (fd >= 0) FdClose(thr, pc, fd); \
}
+#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res) \
+ libignore()->OnLibraryLoaded(filename)
+
+#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() \
+ libignore()->OnLibraryUnloaded()
+
#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
FdAcquire(((TsanInterceptorContext *) ctx)->thr, pc, fd)
@@ -2376,8 +2374,6 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(fork);
TSAN_INTERCEPT(vfork);
- TSAN_INTERCEPT(dlopen);
- TSAN_INTERCEPT(dlclose);
TSAN_INTERCEPT(on_exit);
TSAN_INTERCEPT(__cxa_atexit);
TSAN_INTERCEPT(_exit);
Added: compiler-rt/trunk/test/asan/TestCases/Linux/coverage-direct-large.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/coverage-direct-large.cc?rev=209653&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/coverage-direct-large.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/coverage-direct-large.cc Tue May 27 07:37:52 2014
@@ -0,0 +1,45 @@
+// Test for direct coverage writing with lots of data.
+// Current implementation maps output file in chunks of 64K. This test overflows
+// 1 chunk.
+// RUN: %clangxx_asan -mllvm -asan-coverage=1 -O0 %s -o %t
+
+// RUN: rm -rf %T/coverage-direct-large
+
+// RUN: mkdir -p %T/coverage-direct-large/normal && cd %T/coverage-direct-large/normal
+// RUN: ASAN_OPTIONS=coverage=1:coverage_direct=0:verbosity=1 %run %t
+// RUN: %sancov print *.sancov >out.txt
+// RUN: cd ../..
+
+// RUN: mkdir -p %T/coverage-direct-large/direct && cd %T/coverage-direct-large/direct
+// RUN: ASAN_OPTIONS=coverage=1:coverage_direct=1:verbosity=1 %run %t
+// RUN: %sancov rawunpack *.sancov.raw
+// RUN: %sancov print *.sancov >out.txt
+// RUN: cd ../..
+
+// RUN: diff -u coverage-direct-large/normal/out.txt coverage-direct-large/direct/out.txt
+//
+// XFAIL: android
+
+#define F0(Q, x) Q(x)
+#define F1(Q, x) \
+ F0(Q, x##0) F0(Q, x##1) F0(Q, x##2) F0(Q, x##3) F0(Q, x##4) F0(Q, x##5) \
+ F0(Q, x##6) F0(Q, x##7) F0(Q, x##8) F0(Q, x##9)
+#define F2(Q, x) \
+ F1(Q, x##0) F1(Q, x##1) F1(Q, x##2) F1(Q, x##3) F1(Q, x##4) F1(Q, x##5) \
+ F1(Q, x##6) F1(Q, x##7) F1(Q, x##8) F1(Q, x##9)
+#define F3(Q, x) \
+ F2(Q, x##0) F2(Q, x##1) F2(Q, x##2) F2(Q, x##3) F2(Q, x##4) F2(Q, x##5) \
+ F2(Q, x##6) F2(Q, x##7) F2(Q, x##8) F2(Q, x##9)
+#define F4(Q, x) \
+ F3(Q, x##0) F3(Q, x##1) F3(Q, x##2) F3(Q, x##3) F3(Q, x##4) F3(Q, x##5) \
+ F3(Q, x##6) F3(Q, x##7) F3(Q, x##8) F3(Q, x##9)
+
+#define DECL(x) __attribute__((noinline)) void x() {}
+#define CALL(x) x();
+
+F4(DECL, f)
+
+int main(void) {
+ F4(CALL, f)
+ return 0;
+}
Propchange: compiler-rt/trunk/test/asan/TestCases/Linux/coverage-direct-large.cc
------------------------------------------------------------------------------
svn:eol-style = LF
Added: compiler-rt/trunk/test/asan/TestCases/Linux/coverage-direct.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/coverage-direct.cc?rev=209653&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/coverage-direct.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/coverage-direct.cc Tue May 27 07:37:52 2014
@@ -0,0 +1,44 @@
+// Test for direct coverage writing with dlopen.
+// RUN: %clangxx_asan -mllvm -asan-coverage=1 -DSHARED %s -shared -o %T/libcoverage_direct_test_1.so -fPIC
+// RUN: %clangxx_asan -mllvm -asan-coverage=1 -DSO_DIR=\"%T\" %s -o %t
+
+// RUN: rm -rf %T/coverage-direct
+
+// RUN: mkdir -p %T/coverage-direct/normal && cd %T/coverage-direct/normal
+// RUN: ASAN_OPTIONS=coverage=1:coverage_direct=0:verbosity=1 %run %t
+// RUN: %sancov print *.sancov >out.txt
+// RUN: cd ../..
+
+// RUN: mkdir -p %T/coverage-direct/direct && cd %T/coverage-direct/direct
+// RUN: ASAN_OPTIONS=coverage=1:coverage_direct=1:verbosity=1 %run %t
+// RUN: %sancov rawunpack *.sancov.raw
+// RUN: %sancov print *.sancov >out.txt
+// RUN: cd ../..
+
+// RUN: diff -u coverage-direct/normal/out.txt coverage-direct/direct/out.txt
+//
+// XFAIL: android
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#ifdef SHARED
+extern "C" {
+void bar() { printf("bar\n"); }
+}
+#else
+
+int main(int argc, char **argv) {
+ fprintf(stderr, "PID: %d\n", getpid());
+ void *handle1 =
+ dlopen(SO_DIR "/libcoverage_direct_test_1.so", RTLD_LAZY);
+ assert(handle1);
+ void (*bar1)() = (void (*)())dlsym(handle1, "bar");
+ assert(bar1);
+ bar1();
+
+ return 0;
+}
+#endif
Propchange: compiler-rt/trunk/test/asan/TestCases/Linux/coverage-direct.cc
------------------------------------------------------------------------------
svn:eol-style = LF
More information about the llvm-commits
mailing list