From d0fd3198b9b5e12a93160958427bc17ef0d2fa69 Mon Sep 17 00:00:00 2001 From: Dmitriy Nikiforov Date: Thu, 11 May 2017 17:37:27 +0300 Subject: [PATCH] [sanitizer-coverage] Add new coverage dump interface libsanitizer/ * include/santizer/coverage_interface.h (__sanitizer_dump_coverage): New function. * sanitizer_common/sanitizer_interface_internal.h (__sanitizer_dump_coverage): Likewise. * sanitizer_common/sanitizer_coverage_libcdep_new.cc: New file. * sanitizer/Makefile.am: Updated. * sanitzer/Makefile.in: Updated. Partially backported from LLVM mainline r289498, r291267, r291736, r289851. Change-Id: I6c13ca8e6e7cfb3c98596970c8ba243296464eeb Signed-off-by: Dmitriy Nikiforov --- .../include/sanitizer/coverage_interface.h | 3 + libsanitizer/sanitizer_common/Makefile.am | 1 + libsanitizer/sanitizer_common/Makefile.in | 3 + .../sanitizer_coverage_libcdep_new.cc | 113 +++++++++++++++++++++ .../sanitizer_interface_internal.h | 3 + 5 files changed, 123 insertions(+) create mode 100644 libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cc diff --git a/libsanitizer/include/sanitizer/coverage_interface.h b/libsanitizer/include/sanitizer/coverage_interface.h index 37c133a..d6e83d6 100644 --- a/libsanitizer/include/sanitizer/coverage_interface.h +++ b/libsanitizer/include/sanitizer/coverage_interface.h @@ -21,6 +21,9 @@ extern "C" { void __sanitizer_cov_init(); // Record and dump coverage info. void __sanitizer_cov_dump(); + // Dump collected coverage info. Sorts pcs by module into individual + // .sancov files. + void __sanitizer_dump_coverage(const uintptr_t *pcs, uintptr_t len); // Open .sancov.packed in the coverage directory and return the file // descriptor. Returns -1 on failure, or if coverage dumping is disabled. // This is intended for use by sandboxing code. diff --git a/libsanitizer/sanitizer_common/Makefile.am b/libsanitizer/sanitizer_common/Makefile.am index ee7a3f1..e66295f 100644 --- a/libsanitizer/sanitizer_common/Makefile.am +++ b/libsanitizer/sanitizer_common/Makefile.am @@ -23,6 +23,7 @@ sanitizer_common_files = \ sanitizer_common.cc \ sanitizer_common_libcdep.cc \ sanitizer_coverage_libcdep.cc \ + sanitizer_coverage_libcdep_new.cc \ sanitizer_coverage_mapping_libcdep.cc \ sanitizer_deadlock_detector1.cc \ sanitizer_deadlock_detector2.cc \ diff --git a/libsanitizer/sanitizer_common/Makefile.in b/libsanitizer/sanitizer_common/Makefile.in index 765efd1..8924f20 100644 --- a/libsanitizer/sanitizer_common/Makefile.in +++ b/libsanitizer/sanitizer_common/Makefile.in @@ -82,6 +82,7 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) libsanitizer_common_la_LIBADD = am__objects_1 = sanitizer_allocator.lo sanitizer_common.lo \ sanitizer_common_libcdep.lo sanitizer_coverage_libcdep.lo \ + sanitizer_coverage_libcdep_new.lo \ sanitizer_coverage_mapping_libcdep.lo \ sanitizer_deadlock_detector1.lo \ sanitizer_deadlock_detector2.lo sanitizer_flags.lo \ @@ -288,6 +289,7 @@ sanitizer_common_files = \ sanitizer_common.cc \ sanitizer_common_libcdep.cc \ sanitizer_coverage_libcdep.cc \ + sanitizer_coverage_libcdep_new.cc \ sanitizer_coverage_mapping_libcdep.cc \ sanitizer_deadlock_detector1.cc \ sanitizer_deadlock_detector2.cc \ @@ -422,6 +424,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_common_libcdep.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_coverage_libcdep.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_coverage_libcdep_new.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_coverage_mapping_libcdep.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_deadlock_detector1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_deadlock_detector2.Plo@am__quote@ diff --git a/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cc b/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cc new file mode 100644 index 0000000..dcb305c --- /dev/null +++ b/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cc @@ -0,0 +1,113 @@ +//===-- sanitizer_coverage_libcdep_new.cc ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Sanitizer Coverage Controller for Trace PC Guard. + +#include "sanitizer_allocator_internal.h" +#include "sanitizer_atomic.h" +#include "sanitizer_common.h" +#include "sanitizer_flags.h" +#include "sanitizer_symbolizer.h" + +using namespace __sanitizer; + +using AddressRange = LoadedModule::AddressRange; + +namespace __sancov { +namespace { + +static const u64 Magic64 = 0xC0BFFFFFFFFFFF64ULL; +static const u64 Magic32 = 0xC0BFFFFFFFFFFF32ULL; +static const u64 Magic = SANITIZER_WORDSIZE == 64 ? Magic64 : Magic32; + +static fd_t OpenFile(const char *path) { + error_t err; + fd_t fd = OpenFile(path, WrOnly, &err); + if (fd == kInvalidFd) + Report("SanitizerCoverage: failed to open %s for writing (reason: %d)\n", + path, err); + return fd; +} + +static void GetCoverageFilename(char *path, const char *name, + const char *extension) { + CHECK(name); + internal_snprintf(path, kMaxPathLength, "%s/%s.%zd.%s", + common_flags()->coverage_dir, name, internal_getpid(), + extension); +} + +static void WriteModuleCoverage(char *file_path, const char *module_name, + const uptr *pcs, uptr len) { + GetCoverageFilename(file_path, StripModuleName(module_name), "sancov"); + fd_t fd = OpenFile(file_path); + WriteToFile(fd, &Magic, sizeof(Magic)); + WriteToFile(fd, pcs, len * sizeof(*pcs)); + CloseFile(fd); + Printf("SanitizerCoverage: %s %zd PCs written\n", file_path, len); +} + +static void SanitizerDumpCoverage(const uptr *unsorted_pcs, uptr len) { + if (!len) + return; + + char *file_path = static_cast(InternalAlloc(kMaxPathLength)); + char *module_name = static_cast(InternalAlloc(kMaxPathLength)); + uptr *pcs = static_cast(InternalAlloc(len * sizeof(uptr))); + + internal_memcpy(pcs, unsorted_pcs, len * sizeof(uptr)); + SortArray(pcs, len); + + bool module_found = false; + uptr last_base = 0; + uptr module_start_idx = 0; + + for (uptr i = 0; i < len; ++i) { + const uptr pc = pcs[i]; + if (!pc) + continue; + + if (!__sanitizer_get_module_and_offset_for_pc(pc, nullptr, 0, &pcs[i])) { + Printf("ERROR: bad pc %x\n", pc); + continue; + } + uptr module_base = pc - pcs[i]; + + if (module_base != last_base || !module_found) { + if (module_found) { + WriteModuleCoverage(file_path, module_name, &pcs[module_start_idx], + i - module_start_idx); + } + + last_base = module_base; + module_start_idx = i; + module_found = true; + __sanitizer_get_module_and_offset_for_pc(pc, module_name, kMaxPathLength, + &pcs[i]); + } + } + + if (module_found) { + WriteModuleCoverage(file_path, module_name, &pcs[module_start_idx], + len - module_start_idx); + } + + InternalFree(file_path); + InternalFree(module_name); + InternalFree(pcs); +} + +} // namespace +} // namespace __sancov + +extern "C" { +SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage( // NOLINT + const uptr *pcs, uptr len) { + return __sancov::SanitizerDumpCoverage(pcs, len); +} +} // extern "C" diff --git a/libsanitizer/sanitizer_common/sanitizer_interface_internal.h b/libsanitizer/sanitizer_common/sanitizer_interface_internal.h index 9d2d3d0..fe740c9 100644 --- a/libsanitizer/sanitizer_common/sanitizer_interface_internal.h +++ b/libsanitizer/sanitizer_common/sanitizer_interface_internal.h @@ -41,6 +41,9 @@ extern "C" { void __sanitizer_report_error_summary(const char *error_summary); SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump(); + SANITIZER_INTERFACE_ATTRIBUTE + void __sanitizer_dump_coverage(const __sanitizer::uptr *pcs, + const __sanitizer::uptr len); SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init(); SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(__sanitizer::u32 *guard); SANITIZER_INTERFACE_ATTRIBUTE -- 2.7.4