Index: compiler-rt/cmake/config-ix.cmake =================================================================== --- compiler-rt/cmake/config-ix.cmake +++ compiler-rt/cmake/config-ix.cmake @@ -612,7 +612,7 @@ endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND XRAY_SUPPORTED_ARCH AND - OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|OpenBSD") + OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|OpenBSD|Fuchsia") set(COMPILER_RT_HAS_XRAY TRUE) else() set(COMPILER_RT_HAS_XRAY FALSE) Index: compiler-rt/lib/xray/xray_allocator.h =================================================================== --- compiler-rt/lib/xray/xray_allocator.h +++ compiler-rt/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 +#include +#include +#else #include "sanitizer_common/sanitizer_posix.h" +#endif #include "xray_defs.h" #include "xray_utils.h" #include @@ -32,6 +38,27 @@ // internal allocator. This allows us to manage the memory directly, using // mmap'ed memory to back the allocators. template T *allocate() XRAY_NEVER_INSTRUMENT { +#if SANITIZER_FUCHSIA + zx_handle_t Vmo; + zx_status_t Status = _zx_vmo_create(sizeof(T), 0, &Vmo); + if (Status != ZX_OK) { + if (Verbosity()) + Report("XRay Profiling: Failed to create VM object of size %d: %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); + if (Status != ZX_OK) { + if (Verbosity()) + Report("XRay Profiling: Failed to create memory mapping of size %d: %s\n", + sizeof(T), _zx_status_get_string(Status)); + return nullptr; + } + return reinterpret_cast(B); +#else auto B = reinterpret_cast( internal_mmap(NULL, sizeof(T), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); @@ -41,16 +68,42 @@ sizeof(T)); return nullptr; } +#endif return reinterpret_cast(B); } template void deallocate(T *B) XRAY_NEVER_INSTRUMENT { if (B == nullptr) return; +#if SANITIZER_FUCHSIA + _zx_vmar_unmap(_zx_vmar_root_self(), + reinterpret_cast(B), sizeof(T)); +#else internal_munmap(B, sizeof(T)); +#endif } template T *allocateBuffer(size_t S) XRAY_NEVER_INSTRUMENT { +#if SANITIZER_FUCHSIA + zx_handle_t Vmo; + zx_status_t Status = _zx_vmo_create(S, 0, &Vmo); + if (Status != ZX_OK) { + if (Verbosity()) + Report("XRay Profiling: Failed to create VM object of size %d: %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); + if (Status != ZX_OK) { + if (Verbosity()) + Report("XRay Profiling: Failed to create memory mapping of size %d: %s\n", + S, _zx_status_get_string(Status)); + return nullptr; + } +#else auto B = reinterpret_cast( internal_mmap(NULL, S * sizeof(T), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); @@ -59,13 +112,18 @@ Report("XRay Profiling: Failed to allocate memory of size %d.\n", S); return nullptr; } +#endif return reinterpret_cast(B); } template void deallocateBuffer(T *B, size_t S) XRAY_NEVER_INSTRUMENT { if (B == nullptr) return; +#if SANITIZER_FUCHSIA + _zx_vmar_unmap(_zx_vmar_root_self(), reinterpret_cast(B), S); +#else internal_munmap(B, S); +#endif } template @@ -112,11 +170,8 @@ void *Alloc() XRAY_NEVER_INSTRUMENT { SpinMutexLock Lock(&Mutex); if (UNLIKELY(BackingStore == nullptr)) { - BackingStore = reinterpret_cast( - internal_mmap(NULL, MaxMemory, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); - if (BackingStore == MAP_FAILED) { - BackingStore = nullptr; + BackingStore = allocateBuffer(MaxMemory); + if (BackingStore == nullptr) { if (Verbosity()) Report("XRay Profiling: Failed to allocate memory for allocator.\n"); return nullptr; @@ -129,7 +184,7 @@ auto AlignedNextBlockNum = nearest_boundary( reinterpret_cast(AlignedNextBlock), kCacheLineSize); if (diff(AlignedNextBlockNum, BackingStoreNum) > ptrdiff_t(MaxMemory)) { - munmap(BackingStore, MaxMemory); + deallocateBuffer(BackingStore, MaxMemory); AlignedNextBlock = BackingStore = nullptr; if (Verbosity()) Report("XRay Profiling: Cannot obtain enough memory from " @@ -164,7 +219,7 @@ ~Allocator() NOEXCEPT XRAY_NEVER_INSTRUMENT { if (BackingStore != nullptr) { - internal_munmap(BackingStore, MaxMemory); + deallocateBuffer(BackingStore, MaxMemory); } } }; Index: compiler-rt/lib/xray/xray_basic_logging.cc =================================================================== --- compiler-rt/lib/xray/xray_basic_logging.cc +++ compiler-rt/lib/xray/xray_basic_logging.cc @@ -19,7 +19,9 @@ #include #include #include +#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD || SANITIZER_MAC #include +#endif #include #include #include Index: compiler-rt/lib/xray/xray_buffer_queue.cc =================================================================== --- compiler-rt/lib/xray/xray_buffer_queue.cc +++ compiler-rt/lib/xray/xray_buffer_queue.cc @@ -15,7 +15,12 @@ #include "xray_buffer_queue.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" +#if SANITIZER_FUCHSIA +#include +#include +#else #include "sanitizer_common/sanitizer_posix.h" +#endif #include "xray_allocator.h" #include "xray_defs.h" #include Index: compiler-rt/lib/xray/xray_fdr_logging.cc =================================================================== --- compiler-rt/lib/xray/xray_fdr_logging.cc +++ compiler-rt/lib/xray/xray_fdr_logging.cc @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include Index: compiler-rt/lib/xray/xray_init.cc =================================================================== --- compiler-rt/lib/xray/xray_init.cc +++ compiler-rt/lib/xray/xray_init.cc @@ -17,6 +17,7 @@ #include #include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_platform.h" #include "xray_defs.h" #include "xray_flags.h" #include "xray_interface_internal.h" Index: compiler-rt/lib/xray/xray_interface.cc =================================================================== --- compiler-rt/lib/xray/xray_interface.cc +++ compiler-rt/lib/xray/xray_interface.cc @@ -22,6 +22,12 @@ #include #include +#if SANITIZER_FUCHSIA +#include +#include +#include +#endif + #include "sanitizer_common/sanitizer_addrhashmap.h" #include "sanitizer_common/sanitizer_common.h" @@ -98,16 +104,41 @@ MustCleanup(false) {} int MakeWriteable() XRAY_NEVER_INSTRUMENT { +#if SANITIZER_FUCHSIA + zx_handle_t Handle = __sanitizer_address_mapping(PageAlignedAddr); + if (Handle == ZX_HANDLE_INVALID) { + Report("XRay: cannot retrieve address mapping for %p\n", PageAlignedAddr); + return -1; + } + uintptr_t Addr = reinterpret_cast(PageAlignedAddr); + auto R = _zx_vmar_protect(Handle, + ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_PERM_EXECUTE, + Addr, MProtectLen); + if (R != ZX_OK) { + Report("XRay: cannot set VMAR 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 + uintptr_t Addr = reinterpret_cast(PageAlignedAddr); + _zx_vmar_protect(_zx_vmar_root_self(), + ZX_VM_PERM_READ | ZX_VM_PERM_EXECUTE, + Addr, MProtectLen); +#else mprotect(PageAlignedAddr, MProtectLen, PROT_READ | PROT_EXEC); +#endif } } }; @@ -254,6 +285,9 @@ reinterpret_cast(MinSled.Address & ~(PageSize - 1)); size_t MProtectLen = (MaxSled.Address - reinterpret_cast(PageAlignedAddr)) + cSledLength; +#if SANITIZER_FUCHSIA + MProtectLen = RoundUpTo(MProtectLen, PageSize); +#endif MProtectHelper Protector(PageAlignedAddr, MProtectLen); if (Protector.MakeWriteable() == -1) { Report("Failed mprotect: %d\n", errno); Index: compiler-rt/lib/xray/xray_profile_collector.cc =================================================================== --- compiler-rt/lib/xray/xray_profile_collector.cc +++ compiler-rt/lib/xray/xray_profile_collector.cc @@ -18,6 +18,7 @@ #include "xray_defs.h" #include "xray_profiling_flags.h" #include "xray_segmented_array.h" +#include "xray_utils.h" #include #include #include Index: compiler-rt/lib/xray/xray_utils.h =================================================================== --- compiler-rt/lib/xray/xray_utils.h +++ compiler-rt/lib/xray/xray_utils.h @@ -20,8 +20,29 @@ #include #include +#include "sanitizer_common/sanitizer_common.h" +#if SANITIZER_FUCHSIA +#include +#endif + namespace __xray { +#if SANITIZER_FUCHSIA +class LogWriter { +public: + LogWriter(zx_handle_t Vmo) : Vmo(Vmo) {} + ~LogWriter(); + + // Write a character range into a log. + void WriteAll(const char *Begin, const char *End); + + void Flush(); + +private: + zx_handle_t Vmo = ZX_HANDLE_INVALID; + uint64_t Offset = 0; +}; +#else class LogWriter { public: LogWriter(int Fd) : Fd(Fd) {} @@ -35,6 +56,7 @@ private: int Fd = -1; }; +#endif // Default implementation of the reporting interface for sanitizer errors. void printToStdErr(const char *Buffer); Index: compiler-rt/lib/xray/xray_utils.cc =================================================================== --- compiler-rt/lib/xray/xray_utils.cc +++ compiler-rt/lib/xray/xray_utils.cc @@ -26,8 +26,101 @@ #include #include +#if SANITIZER_FUCHSIA +#include +#include +#include +#include +#include +#endif + namespace __xray { +#if SANITIZER_FUCHSIA +static const char ProfileSinkName[] = "llvm-xray"; + +void printToStdErr(const char *Buffer) XRAY_NEVER_INSTRUMENT { + __sanitizer_log_write(Buffer, strlen(Buffer)); +} + +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); + + // 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. + 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 { +} + +LogWriter *openLog() XRAY_NEVER_INSTRUMENT { + // Get information about the current process. + zx_info_handle_basic_t Info; + zx_status_t 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 information about the current process: %s\n", + _zx_status_get_string(Status)); + return nullptr; + } + + // Create VMO to hold the profile data. + zx_handle_t Vmo; + 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; + } + + // 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. + zx_handle_t Handle; + Status =_zx_handle_duplicate(Vmo, ZX_RIGHT_SAME_RIGHTS, &Handle); + if (Status != ZX_OK) { + Report("XRay: cannot duplicate VMO: %s\n", _zx_status_get_string(Status)); + return nullptr; + } + + // Publish the VMO which contains profile data to the system. + __sanitizer_publish_data(ProfileSinkName, Handle); + + // Use the dumpfile symbolizer markup element to write the name of VMO. + Report("XRay: {{{dumpfile:%s:%s}}}\n", ProfileSinkName, VmoName); + + LogWriter *LW = reinterpret_cast(InternalAlloc(sizeof(LogWriter))); + new (LW) LogWriter(Vmo); + return LW; +} + +void closeLog(LogWriter *LW) { + LW->~LogWriter(); + InternalFree(LW); +} +#else void printToStdErr(const char *Buffer) XRAY_NEVER_INSTRUMENT { fprintf(stderr, "%s", Buffer); } @@ -95,5 +188,6 @@ LW->~LogWriter(); InternalFree(LW); } +#endif } // namespace __xray Index: compiler-rt/lib/xray/xray_x86_64.cc =================================================================== --- compiler-rt/lib/xray/xray_x86_64.cc +++ compiler-rt/lib/xray/xray_x86_64.cc @@ -10,6 +10,8 @@ #include #endif #include +#elif SANITIZER_FUCHSIA +#include #endif #include @@ -103,6 +105,10 @@ return 0; } +#elif SANITIZER_FUCHSIA +uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT { + return static_cast(zx_ticks_per_second()); +} #else uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT { /* Not supported */