summaryrefslogtreecommitdiff
path: root/lib/xray/xray_utils.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/xray/xray_utils.cc')
-rw-r--r--lib/xray/xray_utils.cc172
1 files changed, 121 insertions, 51 deletions
diff --git a/lib/xray/xray_utils.cc b/lib/xray/xray_utils.cc
index 68f4e8c10..59ba6c308 100644
--- a/lib/xray/xray_utils.cc
+++ b/lib/xray/xray_utils.cc
@@ -12,7 +12,9 @@
//===----------------------------------------------------------------------===//
#include "xray_utils.h"
+#include "sanitizer_common/sanitizer_allocator_internal.h"
#include "sanitizer_common/sanitizer_common.h"
+#include "xray_allocator.h"
#include "xray_defs.h"
#include "xray_flags.h"
#include <cstdio>
@@ -25,13 +27,113 @@
#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);
}
-void retryingWriteAll(int Fd, const char *Begin, const char *End) XRAY_NEVER_INSTRUMENT {
+void LogWriter::WriteAll(const char *Begin, const char *End) XRAY_NEVER_INSTRUMENT {
if (Begin == End)
return;
auto TotalBytes = std::distance(Begin, End);
@@ -49,50 +151,11 @@ void retryingWriteAll(int Fd, const char *Begin, const char *End) XRAY_NEVER_INS
}
}
-std::pair<ssize_t, bool> retryingReadSome(int Fd, char *Begin,
- char *End) XRAY_NEVER_INSTRUMENT {
- auto BytesToRead = std::distance(Begin, End);
- ssize_t BytesRead;
- ssize_t TotalBytesRead = 0;
- while (BytesToRead && (BytesRead = read(Fd, Begin, BytesToRead))) {
- if (BytesRead == -1) {
- if (errno == EINTR)
- continue;
- Report("Read error; errno = %d\n", errno);
- return std::make_pair(TotalBytesRead, false);
- }
-
- TotalBytesRead += BytesRead;
- BytesToRead -= BytesRead;
- Begin += BytesRead;
- }
- return std::make_pair(TotalBytesRead, true);
-}
-
-bool readValueFromFile(const char *Filename,
- long long *Value) XRAY_NEVER_INSTRUMENT {
- int Fd = open(Filename, O_RDONLY | O_CLOEXEC);
- if (Fd == -1)
- return false;
- static constexpr size_t BufSize = 256;
- char Line[BufSize] = {};
- ssize_t BytesRead;
- bool Success;
- std::tie(BytesRead, Success) = retryingReadSome(Fd, Line, Line + BufSize);
- if (!Success)
- return false;
- close(Fd);
- const char *End = nullptr;
- long long Tmp = internal_simple_strtoll(Line, &End, 10);
- bool Result = false;
- if (Line[0] != '\0' && (*End == '\n' || *End == '\0')) {
- *Value = Tmp;
- Result = true;
- }
- return Result;
+void LogWriter::Flush() XRAY_NEVER_INSTRUMENT {
+ fsync(Fd);
}
-int getLogFD() XRAY_NEVER_INSTRUMENT {
+LogWriter *LogWriter::Open() XRAY_NEVER_INSTRUMENT {
// Open a temporary file once for the log.
char TmpFilename[256] = {};
char TmpWildcardPattern[] = "XXXXXX";
@@ -103,24 +166,31 @@ int getLogFD() XRAY_NEVER_INSTRUMENT {
if (LastSlash != nullptr)
Progname = LastSlash + 1;
- const int HalfLength = sizeof(TmpFilename) / 2 - sizeof(TmpWildcardPattern);
int NeededLength = internal_snprintf(
- TmpFilename, sizeof(TmpFilename), "%.*s%.*s.%s", HalfLength,
- flags()->xray_logfile_base, HalfLength, Progname, TmpWildcardPattern);
+ TmpFilename, sizeof(TmpFilename), "%s%s.%s",
+ flags()->xray_logfile_base, Progname, TmpWildcardPattern);
if (NeededLength > int(sizeof(TmpFilename))) {
Report("XRay log file name too long (%d): %s\n", NeededLength, TmpFilename);
- return -1;
+ return nullptr;
}
int Fd = mkstemp(TmpFilename);
if (Fd == -1) {
Report("XRay: Failed opening temporary file '%s'; not logging events.\n",
TmpFilename);
- return -1;
+ return nullptr;
}
if (Verbosity())
Report("XRay: Log file in '%s'\n", TmpFilename);
- return Fd;
+ LogWriter *LW = allocate<LogWriter>();
+ new (LW) LogWriter(Fd);
+ return LW;
+}
+
+void LogWriter::Close(LogWriter *LW) {
+ LW->~LogWriter();
+ deallocate(LW);
}
+#endif // SANITIZER_FUCHSIA
} // namespace __xray