diff options
author | Petr Hosek <phosek@chromium.org> | 2018-11-22 02:00:44 +0000 |
---|---|---|
committer | Petr Hosek <phosek@chromium.org> | 2018-11-22 02:00:44 +0000 |
commit | e1ce357dc819e000debd58baa6d65faf240f3468 (patch) | |
tree | 4421ef4bbe4ad3819d1d102c393535dbcddc39e9 /lib/xray | |
parent | c0061a2c69ad2189d33bd07cbbc409205f7af5ab (diff) | |
download | compiler-rt-e1ce357dc819e000debd58baa6d65faf240f3468.tar.gz |
[XRay] Support for Fuchsia
This extends XRay to support Fuchsia.
Differential Revision: https://reviews.llvm.org/D52162
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@347443 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/xray')
-rw-r--r-- | lib/xray/xray_allocator.h | 60 | ||||
-rw-r--r-- | lib/xray/xray_basic_logging.cc | 2 | ||||
-rw-r--r-- | lib/xray/xray_buffer_queue.cc | 2 | ||||
-rw-r--r-- | lib/xray/xray_fdr_logging.cc | 1 | ||||
-rw-r--r-- | lib/xray/xray_interface.cc | 41 | ||||
-rw-r--r-- | lib/xray/xray_tsc.h | 23 | ||||
-rw-r--r-- | lib/xray/xray_utils.cc | 101 | ||||
-rw-r--r-- | lib/xray/xray_utils.h | 35 | ||||
-rw-r--r-- | lib/xray/xray_x86_64.cc | 8 |
9 files changed, 253 insertions, 20 deletions
diff --git a/lib/xray/xray_allocator.h b/lib/xray/xray_allocator.h index af63d9d37..0abce3c6d 100644 --- a/lib/xray/xray_allocator.h +++ b/lib/xray/xray_allocator.h @@ -19,7 +19,13 @@ #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_mutex.h" +#if SANITIZER_FUCHSIA +#include <zircon/process.h> +#include <zircon/syscalls.h> +#include <zircon/status.h> +#else #include "sanitizer_common/sanitizer_posix.h" +#endif #include "xray_defs.h" #include "xray_utils.h" #include <cstddef> @@ -33,6 +39,28 @@ namespace __xray { // mmap'ed memory to back the allocators. template <class T> T *allocate() XRAY_NEVER_INSTRUMENT { uptr RoundedSize = RoundUpTo(sizeof(T), GetPageSizeCached()); +#if SANITIZER_FUCHSIA + zx_handle_t Vmo; + zx_status_t Status = _zx_vmo_create(RoundedSize, 0, &Vmo); + if (Status != ZX_OK) { + if (Verbosity()) + Report("XRay Profiling: Failed to create VMO of size %zu: %s\n", + sizeof(T), _zx_status_get_string(Status)); + return nullptr; + } + uintptr_t B; + Status = + _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0, + Vmo, 0, sizeof(T), &B); + _zx_handle_close(Vmo); + if (Status != ZX_OK) { + if (Verbosity()) + Report("XRay Profiling: Failed to map VMAR of size %zu: %s\n", + sizeof(T), _zx_status_get_string(Status)); + return nullptr; + } + return reinterpret_cast<T *>(B); +#else uptr B = internal_mmap(NULL, RoundedSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); int ErrNo; @@ -43,6 +71,7 @@ template <class T> T *allocate() XRAY_NEVER_INSTRUMENT { RoundedSize, B); return nullptr; } +#endif return reinterpret_cast<T *>(B); } @@ -50,12 +79,38 @@ template <class T> void deallocate(T *B) XRAY_NEVER_INSTRUMENT { if (B == nullptr) return; uptr RoundedSize = RoundUpTo(sizeof(T), GetPageSizeCached()); +#if SANITIZER_FUCHSIA + _zx_vmar_unmap(_zx_vmar_root_self(), + reinterpret_cast<uintptr_t>(B), RoundedSize); +#else internal_munmap(B, RoundedSize); +#endif } template <class T = unsigned char> T *allocateBuffer(size_t S) XRAY_NEVER_INSTRUMENT { uptr RoundedSize = RoundUpTo(S * sizeof(T), GetPageSizeCached()); +#if SANITIZER_FUCHSIA + zx_handle_t Vmo; + zx_status_t Status = _zx_vmo_create(RoundedSize, 0, &Vmo); + if (Status != ZX_OK) { + if (Verbosity()) + Report("XRay Profiling: Failed to create VMO of size %zu: %s\n", + S, _zx_status_get_string(Status)); + return nullptr; + } + uintptr_t B; + Status = + _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0, + Vmo, 0, S, &B); + _zx_handle_close(Vmo); + if (Status != ZX_OK) { + if (Verbosity()) + Report("XRay Profiling: Failed to map VMAR of size %zu: %s\n", + S, _zx_status_get_string(Status)); + return nullptr; + } +#else uptr B = internal_mmap(NULL, RoundedSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); int ErrNo; @@ -66,6 +121,7 @@ T *allocateBuffer(size_t S) XRAY_NEVER_INSTRUMENT { RoundedSize, B); return nullptr; } +#endif return reinterpret_cast<T *>(B); } @@ -73,7 +129,11 @@ template <class T> void deallocateBuffer(T *B, size_t S) XRAY_NEVER_INSTRUMENT { if (B == nullptr) return; uptr RoundedSize = RoundUpTo(S * sizeof(T), GetPageSizeCached()); +#if SANITIZER_FUCHSIA + _zx_vmar_unmap(_zx_vmar_root_self(), reinterpret_cast<uintptr_t>(B), RoundedSize); +#else internal_munmap(B, RoundedSize); +#endif } template <class T, class... U> diff --git a/lib/xray/xray_basic_logging.cc b/lib/xray/xray_basic_logging.cc index cd8ee8f3d..b65c0e43e 100644 --- a/lib/xray/xray_basic_logging.cc +++ b/lib/xray/xray_basic_logging.cc @@ -19,7 +19,9 @@ #include <fcntl.h> #include <pthread.h> #include <sys/stat.h> +#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD || SANITIZER_MAC #include <sys/syscall.h> +#endif #include <sys/types.h> #include <time.h> #include <unistd.h> diff --git a/lib/xray/xray_buffer_queue.cc b/lib/xray/xray_buffer_queue.cc index 9972beb4e..7d0e5a1f3 100644 --- a/lib/xray/xray_buffer_queue.cc +++ b/lib/xray/xray_buffer_queue.cc @@ -16,7 +16,9 @@ #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" +#if !SANITIZER_FUCHSIA #include "sanitizer_common/sanitizer_posix.h" +#endif #include "xray_allocator.h" #include "xray_defs.h" #include <memory> diff --git a/lib/xray/xray_fdr_logging.cc b/lib/xray/xray_fdr_logging.cc index 12bd8f5d1..3893b7a2a 100644 --- a/lib/xray/xray_fdr_logging.cc +++ b/lib/xray/xray_fdr_logging.cc @@ -20,7 +20,6 @@ #include <limits> #include <memory> #include <pthread.h> -#include <sys/syscall.h> #include <sys/time.h> #include <time.h> #include <unistd.h> diff --git a/lib/xray/xray_interface.cc b/lib/xray/xray_interface.cc index 01bf6ddc6..6f7b6615b 100644 --- a/lib/xray/xray_interface.cc +++ b/lib/xray/xray_interface.cc @@ -22,6 +22,13 @@ #include <string.h> #include <sys/mman.h> +#if SANITIZER_FUCHSIA +#include <zircon/process.h> +#include <zircon/sanitizer.h> +#include <zircon/status.h> +#include <zircon/syscalls.h> +#endif + #include "sanitizer_common/sanitizer_addrhashmap.h" #include "sanitizer_common/sanitizer_common.h" @@ -92,22 +99,48 @@ class MProtectHelper { public: explicit MProtectHelper(void *PageAlignedAddr, - std::size_t MProtectLen) XRAY_NEVER_INSTRUMENT + std::size_t MProtectLen, + std::size_t PageSize) XRAY_NEVER_INSTRUMENT : PageAlignedAddr(PageAlignedAddr), MProtectLen(MProtectLen), - MustCleanup(false) {} + MustCleanup(false) { +#if SANITIZER_FUCHSIA + MProtectLen = RoundUpTo(MProtectLen, PageSize); +#endif + } int MakeWriteable() XRAY_NEVER_INSTRUMENT { +#if SANITIZER_FUCHSIA + auto R = __sanitizer_change_code_protection( + reinterpret_cast<uintptr_t>(PageAlignedAddr), MProtectLen, true); + if (R != ZX_OK) { + Report("XRay: cannot change code protection: %s\n", + _zx_status_get_string(R)); + return -1; + } + MustCleanup = true; + return 0; +#else auto R = mprotect(PageAlignedAddr, MProtectLen, PROT_READ | PROT_WRITE | PROT_EXEC); if (R != -1) MustCleanup = true; return R; +#endif } ~MProtectHelper() XRAY_NEVER_INSTRUMENT { if (MustCleanup) { +#if SANITIZER_FUCHSIA + auto R = __sanitizer_change_code_protection( + reinterpret_cast<uintptr_t>(PageAlignedAddr), MProtectLen, false); + if (R != ZX_OK) { + Report("XRay: cannot change code protection: %s\n", + _zx_status_get_string(R)); + } +#else mprotect(PageAlignedAddr, MProtectLen, PROT_READ | PROT_EXEC); +#endif } } }; @@ -254,7 +287,7 @@ XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT { reinterpret_cast<void *>(MinSled.Address & ~(PageSize - 1)); size_t MProtectLen = (MaxSled.Address - reinterpret_cast<uptr>(PageAlignedAddr)) + cSledLength; - MProtectHelper Protector(PageAlignedAddr, MProtectLen); + MProtectHelper Protector(PageAlignedAddr, MProtectLen, PageSize); if (Protector.MakeWriteable() == -1) { Report("Failed mprotect: %d\n", errno); return XRayPatchingStatus::FAILED; @@ -319,7 +352,7 @@ XRayPatchingStatus mprotectAndPatchFunction(int32_t FuncId, reinterpret_cast<void *>(MinSled.Address & ~(PageSize - 1)); size_t MProtectLen = (MaxSled.Address - reinterpret_cast<uptr>(PageAlignedAddr)) + cSledLength; - MProtectHelper Protector(PageAlignedAddr, MProtectLen); + MProtectHelper Protector(PageAlignedAddr, MProtectLen, PageSize); if (Protector.MakeWriteable() == -1) { Report("Failed mprotect: %d\n", errno); return XRayPatchingStatus::FAILED; diff --git a/lib/xray/xray_tsc.h b/lib/xray/xray_tsc.h index 4507564e7..180d6df18 100644 --- a/lib/xray/xray_tsc.h +++ b/lib/xray/xray_tsc.h @@ -13,10 +13,32 @@ #ifndef XRAY_EMULATE_TSC_H #define XRAY_EMULATE_TSC_H +#include "sanitizer_common/sanitizer_common.h" + namespace __xray { static constexpr uint64_t NanosecondsPerSecond = 1000ULL * 1000 * 1000; } +#if SANITIZER_FUCHSIA +#include <zircon/syscalls.h> + +namespace __xray { + +inline bool probeRequiredCPUFeatures() XRAY_NEVER_INSTRUMENT { return true; } + +ALWAYS_INLINE uint64_t readTSC(uint8_t &CPU) XRAY_NEVER_INSTRUMENT { + CPU = 0; + return _zx_ticks_get(); +} + +inline uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT { + return _zx_ticks_per_second(); +} + +} // namespace __xray + +#else // SANITIZER_FUCHSIA + #if defined(__x86_64__) #include "xray_x86_64.inc" #elif defined(__powerpc64__) @@ -64,5 +86,6 @@ inline uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT { #else #error Target architecture is not supported. #endif // CPU architecture +#endif // SANITIZER_FUCHSIA #endif // XRAY_EMULATE_TSC_H diff --git a/lib/xray/xray_utils.cc b/lib/xray/xray_utils.cc index 22c0dfa70..59ba6c308 100644 --- a/lib/xray/xray_utils.cc +++ b/lib/xray/xray_utils.cc @@ -27,12 +27,108 @@ #include <unistd.h> #include <utility> +#if SANITIZER_FUCHSIA +#include "sanitizer_common/sanitizer_symbolizer_fuchsia.h" + +#include <inttypes.h> +#include <zircon/process.h> +#include <zircon/sanitizer.h> +#include <zircon/status.h> +#include <zircon/syscalls.h> +#endif + namespace __xray { -void printToStdErr(const char *Buffer) XRAY_NEVER_INSTRUMENT { - fprintf(stderr, "%s", Buffer); +#if SANITIZER_FUCHSIA +constexpr const char* ProfileSinkName = "llvm-xray"; + +LogWriter::~LogWriter() { + _zx_handle_close(Vmo); +} + +void LogWriter::WriteAll(const char *Begin, const char *End) XRAY_NEVER_INSTRUMENT { + if (Begin == End) + return; + auto TotalBytes = std::distance(Begin, End); + + const size_t PageSize = flags()->xray_page_size_override > 0 + ? flags()->xray_page_size_override + : GetPageSizeCached(); + if (RoundUpTo(Offset, PageSize) != RoundUpTo(Offset + TotalBytes, PageSize)) { + // Resize the VMO to ensure there's sufficient space for the data. + zx_status_t Status = _zx_vmo_set_size(Vmo, Offset + TotalBytes); + if (Status != ZX_OK) { + Report("Failed to resize VMO: %s\n", _zx_status_get_string(Status)); + return; + } + } + + // Write the data into VMO. + zx_status_t Status = _zx_vmo_write(Vmo, Begin, Offset, TotalBytes); + if (Status != ZX_OK) { + Report("Failed to write: %s\n", _zx_status_get_string(Status)); + return; + } + Offset += TotalBytes; +} + +void LogWriter::Flush() XRAY_NEVER_INSTRUMENT { + // Nothing to do here since WriteAll writes directly into the VMO. } +LogWriter *LogWriter::Open() XRAY_NEVER_INSTRUMENT { + // Create VMO to hold the profile data. + zx_handle_t Vmo; + zx_status_t Status = _zx_vmo_create(0, 0, &Vmo); + if (Status != ZX_OK) { + Report("XRay: cannot create VMO: %s\n", _zx_status_get_string(Status)); + return nullptr; + } + + // Get the KOID of the current process to use in the VMO name. + zx_info_handle_basic_t Info; + Status = _zx_object_get_info(_zx_process_self(), ZX_INFO_HANDLE_BASIC, &Info, + sizeof(Info), NULL, NULL); + if (Status != ZX_OK) { + Report("XRay: cannot get basic info about current process handle: %s\n", + _zx_status_get_string(Status)); + return nullptr; + } + + // Give the VMO a name including our process KOID so it's easy to spot. + char VmoName[ZX_MAX_NAME_LEN]; + internal_snprintf(VmoName, sizeof(VmoName), "%s.%zu", ProfileSinkName, + Info.koid); + _zx_object_set_property(Vmo, ZX_PROP_NAME, VmoName, strlen(VmoName)); + + // Duplicate the handle since __sanitizer_publish_data consumes it and + // LogWriter needs to hold onto it. + zx_handle_t Handle; + Status =_zx_handle_duplicate(Vmo, ZX_RIGHT_SAME_RIGHTS, &Handle); + if (Status != ZX_OK) { + Report("XRay: cannot duplicate VMO handle: %s\n", + _zx_status_get_string(Status)); + return nullptr; + } + + // Publish the VMO that receives the logging. Note the VMO's contents can + // grow and change after publication. The contents won't be read out until + // after the process exits. + __sanitizer_publish_data(ProfileSinkName, Handle); + + // Use the dumpfile symbolizer markup element to write the name of the VMO. + Report("XRay: " FORMAT_DUMPFILE "\n", ProfileSinkName, VmoName); + + LogWriter *LW = reinterpret_cast<LogWriter *>(InternalAlloc(sizeof(LogWriter))); + new (LW) LogWriter(Vmo); + return LW; +} + +void LogWriter::Close(LogWriter *LW) { + LW->~LogWriter(); + InternalFree(LW); +} +#else // SANITIZER_FUCHSIA LogWriter::~LogWriter() { internal_close(Fd); } @@ -95,5 +191,6 @@ void LogWriter::Close(LogWriter *LW) { LW->~LogWriter(); deallocate(LW); } +#endif // SANITIZER_FUCHSIA } // namespace __xray diff --git a/lib/xray/xray_utils.h b/lib/xray/xray_utils.h index 3e0d28287..60438973f 100644 --- a/lib/xray/xray_utils.h +++ b/lib/xray/xray_utils.h @@ -20,30 +20,41 @@ #include <sys/types.h> #include <utility> +#include "sanitizer_common/sanitizer_common.h" +#if SANITIZER_FUCHSIA +#include <zircon/types.h> +#endif + namespace __xray { class LogWriter { public: +#if SANITIZER_FUCHSIA + LogWriter(zx_handle_t Vmo) : Vmo(Vmo) {} +#else explicit LogWriter(int Fd) : Fd(Fd) {} - ~LogWriter(); +#endif + ~LogWriter(); - // Write a character range into a log. - void WriteAll(const char *Begin, const char *End); + // Write a character range into a log. + void WriteAll(const char *Begin, const char *End); - void Flush(); + void Flush(); - // Returns a new log instance initialized using the flag-provided values. - static LogWriter *Open(); - // Closes and deallocates the log instance. - static void Close(LogWriter *LogWriter); + // Returns a new log instance initialized using the flag-provided values. + static LogWriter *Open(); + // Closes and deallocates the log instance. + static void Close(LogWriter *LogWriter); private: - int Fd = -1; +#if SANITIZER_FUCHSIA + zx_handle_t Vmo = ZX_HANDLE_INVALID; + uint64_t Offset = 0; +#else + int Fd = -1; +#endif }; -// Default implementation of the reporting interface for sanitizer errors. -void printToStdErr(const char *Buffer); - constexpr size_t gcd(size_t a, size_t b) { return (b == 0) ? a : gcd(b, a % b); } diff --git a/lib/xray/xray_x86_64.cc b/lib/xray/xray_x86_64.cc index d0411d0fb..e63ee1b3b 100644 --- a/lib/xray/xray_x86_64.cc +++ b/lib/xray/xray_x86_64.cc @@ -1,6 +1,8 @@ #include "cpuid.h" #include "sanitizer_common/sanitizer_common.h" +#if !SANITIZER_FUCHSIA #include "sanitizer_common/sanitizer_posix.h" +#endif #include "xray_defs.h" #include "xray_interface_internal.h" @@ -11,6 +13,8 @@ #include <machine/cpu.h> #endif #include <sys/sysctl.h> +#elif SANITIZER_FUCHSIA +#include <zircon/syscalls.h> #endif #include <atomic> @@ -104,7 +108,7 @@ uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT { return 0; } -#else +#elif !SANITIZER_FUCHSIA uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT { /* Not supported */ return 0; @@ -321,6 +325,7 @@ bool patchTypedEvent(const bool Enable, const uint32_t FuncId, return false; } +#if !SANITIZER_FUCHSIA // We determine whether the CPU we're running on has the correct features we // need. In x86_64 this will be rdtscp support. bool probeRequiredCPUFeatures() XRAY_NEVER_INSTRUMENT { @@ -343,5 +348,6 @@ bool probeRequiredCPUFeatures() XRAY_NEVER_INSTRUMENT { } return true; } +#endif } // namespace __xray |