brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.1 KiB · 5d51df9 Raw
201 lines · cpp
1//===-- xray_utils.cpp ------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of XRay, a dynamic runtime instrumentation system.10//11//===----------------------------------------------------------------------===//12#include "xray_utils.h"13 14#include "sanitizer_common/sanitizer_allocator_internal.h"15#include "sanitizer_common/sanitizer_common.h"16#include "xray_allocator.h"17#include "xray_defs.h"18#include "xray_flags.h"19#include <cstdio>20#include <errno.h>21#include <fcntl.h>22#include <iterator>23#include <new>24#include <stdlib.h>25#include <sys/types.h>26#include <tuple>27#include <unistd.h>28#include <utility>29 30#if SANITIZER_FUCHSIA31#include "sanitizer_common/sanitizer_symbolizer_markup_constants.h"32 33#include <inttypes.h>34#include <zircon/process.h>35#include <zircon/sanitizer.h>36#include <zircon/status.h>37#include <zircon/syscalls.h>38#endif39 40namespace __xray {41 42#if SANITIZER_FUCHSIA43constexpr const char* ProfileSinkName = "llvm-xray";44 45LogWriter::~LogWriter() {46  _zx_handle_close(Vmo);47}48 49void LogWriter::WriteAll(const char *Begin, const char *End) XRAY_NEVER_INSTRUMENT {50  if (Begin == End)51    return;52  auto TotalBytes = std::distance(Begin, End);53 54  const size_t PageSize = flags()->xray_page_size_override > 055                              ? flags()->xray_page_size_override56                              : GetPageSizeCached();57  if (RoundUpTo(Offset, PageSize) != RoundUpTo(Offset + TotalBytes, PageSize)) {58    // Resize the VMO to ensure there's sufficient space for the data.59    zx_status_t Status = _zx_vmo_set_size(Vmo, Offset + TotalBytes);60    if (Status != ZX_OK) {61      Report("Failed to resize VMO: %s\n", _zx_status_get_string(Status));62      return;63    }64  }65 66  // Write the data into VMO.67  zx_status_t Status = _zx_vmo_write(Vmo, Begin, Offset, TotalBytes);68  if (Status != ZX_OK) {69    Report("Failed to write: %s\n", _zx_status_get_string(Status));70    return;71  }72  Offset += TotalBytes;73 74  // Record the data size as a property of the VMO.75  _zx_object_set_property(Vmo, ZX_PROP_VMO_CONTENT_SIZE,76                          &Offset, sizeof(Offset));77}78 79void LogWriter::Flush() XRAY_NEVER_INSTRUMENT {80  // Nothing to do here since WriteAll writes directly into the VMO.81}82 83LogWriter *LogWriter::Open() XRAY_NEVER_INSTRUMENT {84  // Create VMO to hold the profile data.85  zx_handle_t Vmo;86  zx_status_t Status = _zx_vmo_create(0, ZX_VMO_RESIZABLE, &Vmo);87  if (Status != ZX_OK) {88    Report("XRay: cannot create VMO: %s\n", _zx_status_get_string(Status));89    return nullptr;90  }91 92  // Get the KOID of the current process to use in the VMO name.93  zx_info_handle_basic_t Info;94  Status = _zx_object_get_info(_zx_process_self(), ZX_INFO_HANDLE_BASIC, &Info,95                               sizeof(Info), NULL, NULL);96  if (Status != ZX_OK) {97    Report("XRay: cannot get basic info about current process handle: %s\n",98           _zx_status_get_string(Status));99    return nullptr;100  }101 102  // Give the VMO a name including our process KOID so it's easy to spot.103  char VmoName[ZX_MAX_NAME_LEN];104  internal_snprintf(VmoName, sizeof(VmoName), "%s.%zu", ProfileSinkName,105                    Info.koid);106  _zx_object_set_property(Vmo, ZX_PROP_NAME, VmoName, strlen(VmoName));107 108  // Duplicate the handle since __sanitizer_publish_data consumes it and109  // LogWriter needs to hold onto it.110  zx_handle_t Handle;111  Status =_zx_handle_duplicate(Vmo, ZX_RIGHT_SAME_RIGHTS, &Handle);112  if (Status != ZX_OK) {113    Report("XRay: cannot duplicate VMO handle: %s\n",114           _zx_status_get_string(Status));115    return nullptr;116  }117 118  // Publish the VMO that receives the logging. Note the VMO's contents can119  // grow and change after publication. The contents won't be read out until120  // after the process exits.121  __sanitizer_publish_data(ProfileSinkName, Handle);122 123  // Use the dumpfile symbolizer markup element to write the name of the VMO.124  Report("XRay: " FORMAT_DUMPFILE "\n", ProfileSinkName, VmoName);125 126  LogWriter *LW = reinterpret_cast<LogWriter *>(InternalAlloc(sizeof(LogWriter)));127  new (LW) LogWriter(Vmo);128  return LW;129}130 131void LogWriter::Close(LogWriter *LW) {132  LW->~LogWriter();133  InternalFree(LW);134}135#else // SANITIZER_FUCHSIA136LogWriter::~LogWriter() {137  internal_close(Fd);138}139 140void LogWriter::WriteAll(const char *Begin, const char *End) XRAY_NEVER_INSTRUMENT {141  if (Begin == End)142    return;143  auto TotalBytes = std::distance(Begin, End);144  while (auto Written = write(Fd, Begin, TotalBytes)) {145    if (Written < 0) {146      if (errno == EINTR)147        continue; // Try again.148      Report("Failed to write; errno = %d\n", errno);149      return;150    }151    TotalBytes -= Written;152    if (TotalBytes == 0)153      break;154    Begin += Written;155  }156}157 158void LogWriter::Flush() XRAY_NEVER_INSTRUMENT {159  fsync(Fd);160}161 162LogWriter *LogWriter::Open() XRAY_NEVER_INSTRUMENT {163  // Open a temporary file once for the log.164  char TmpFilename[256] = {};165  char TmpWildcardPattern[] = "XXXXXX";166  auto **Argv = GetArgv();167  const char *Progname = !Argv ? "(unknown)" : Argv[0];168  const char *LastSlash = internal_strrchr(Progname, '/');169 170  if (LastSlash != nullptr)171    Progname = LastSlash + 1;172 173  int NeededLength = internal_snprintf(174      TmpFilename, sizeof(TmpFilename), "%s%s.%s",175      flags()->xray_logfile_base, Progname, TmpWildcardPattern);176  if (NeededLength > int(sizeof(TmpFilename))) {177    Report("XRay log file name too long (%d): %s\n", NeededLength, TmpFilename);178    return nullptr;179  }180  int Fd = mkstemp(TmpFilename);181  if (Fd == -1) {182    Report("XRay: Failed opening temporary file '%s'; not logging events.\n",183           TmpFilename);184    return nullptr;185  }186  if (Verbosity())187    Report("XRay: Log file in '%s'\n", TmpFilename);188 189  LogWriter *LW = allocate<LogWriter>();190  new (LW) LogWriter(Fd);191  return LW;192}193 194void LogWriter::Close(LogWriter *LW) {195  LW->~LogWriter();196  deallocate(LW);197}198#endif // SANITIZER_FUCHSIA199 200} // namespace __xray201