[compiler-rt] r209653 - [asancov] Write coverage directly to a memory-mapped file.

Timur Iskhodzhanov timurrrr at google.com
Wed May 28 01:04:32 PDT 2014


Looks like this has broken the build on Windows:

clang_rt.asan-i386.lib(sanitizer_coverage_libcdep.cc.obj) : error
LNK2019: unresolved external symbol "unsigned long __cdecl
__sanitizer::internal_ftruncate(int,unsigned long)"
(?internal_ftruncate at __sanitizer@@YAKHK at Z) referenced in function
"public: void __thiscall __sanitizer::CoverageData::Extend(unsigned
long)" (?Extend at CoverageData@__sanitizer@@QAEXK at Z)
clang_rt.asan-i386.lib(sanitizer_coverage_libcdep.cc.obj) : error
LNK2019: unresolved external symbol "void * __cdecl
__sanitizer::MapWritableFileToMemory(void *,unsigned long,unsigned
long,unsigned long)"
(?MapWritableFileToMemory at __sanitizer@@YAPAXPAXKKK at Z) referenced in
function "public: void __thiscall
__sanitizer::CoverageData::Extend(unsigned long)"
(?Extend at CoverageData@__sanitizer@@QAEXK at Z)
clang_rt.asan-i386.lib(sanitizer_coverage_mapping_libcdep.cc.obj) :
error LNK2019: unresolved external symbol "unsigned long __cdecl
__sanitizer::internal_rename(char const *,char const *)"
(?internal_rename at __sanitizer@@YAKPBD0 at Z) referenced in function "void
__cdecl __sanitizer::CovUpdateMapping(void)"
(?CovUpdateMapping at __sanitizer@@YAXXZ)

2014-05-27 16:37 GMT+04:00 Evgeniy Stepanov <eugeni.stepanov at gmail.com>:
> 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
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list