summaryrefslogtreecommitdiff
path: root/lib/xray
diff options
context:
space:
mode:
authorPetr Hosek <phosek@chromium.org>2018-11-22 02:00:44 +0000
committerPetr Hosek <phosek@chromium.org>2018-11-22 02:00:44 +0000
commite1ce357dc819e000debd58baa6d65faf240f3468 (patch)
tree4421ef4bbe4ad3819d1d102c393535dbcddc39e9 /lib/xray
parentc0061a2c69ad2189d33bd07cbbc409205f7af5ab (diff)
downloadcompiler-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.h60
-rw-r--r--lib/xray/xray_basic_logging.cc2
-rw-r--r--lib/xray/xray_buffer_queue.cc2
-rw-r--r--lib/xray/xray_fdr_logging.cc1
-rw-r--r--lib/xray/xray_interface.cc41
-rw-r--r--lib/xray/xray_tsc.h23
-rw-r--r--lib/xray/xray_utils.cc101
-rw-r--r--lib/xray/xray_utils.h35
-rw-r--r--lib/xray/xray_x86_64.cc8
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