blob: 5d6390c802a0c14ddf8bd3f52efd66cebb6e38b6 [file] [log] [blame]
Dean Michael Berrise7dbebf2017-01-25 03:50:46 +00001//===-- xray_utils.cc -------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of XRay, a dynamic runtime instrumentation system.
11//
12//===----------------------------------------------------------------------===//
13#include "xray_utils.h"
14
15#include "sanitizer_common/sanitizer_common.h"
16#include "xray_defs.h"
17#include "xray_flags.h"
Dean Michael Berris601afaf2017-03-14 23:49:12 +000018#include <stdlib.h>
Dean Michael Berrise7dbebf2017-01-25 03:50:46 +000019#include <cstdio>
Krzysztof Parzyszek520e51d2017-01-25 14:20:30 +000020#include <errno.h>
Dean Michael Berrise7dbebf2017-01-25 03:50:46 +000021#include <fcntl.h>
22#include <iterator>
23#include <sys/types.h>
24#include <tuple>
25#include <unistd.h>
26#include <utility>
27
Dean Michael Berrise7dbebf2017-01-25 03:50:46 +000028namespace __xray {
29
Dean Michael Berrisea9042c2017-02-07 23:35:34 +000030void printToStdErr(const char *Buffer) XRAY_NEVER_INSTRUMENT {
Dean Michael Berrise7dbebf2017-01-25 03:50:46 +000031 fprintf(stderr, "%s", Buffer);
32}
33
34void retryingWriteAll(int Fd, char *Begin, char *End) XRAY_NEVER_INSTRUMENT {
35 if (Begin == End)
36 return;
37 auto TotalBytes = std::distance(Begin, End);
38 while (auto Written = write(Fd, Begin, TotalBytes)) {
39 if (Written < 0) {
40 if (errno == EINTR)
41 continue; // Try again.
42 Report("Failed to write; errno = %d\n", errno);
43 return;
44 }
45 TotalBytes -= Written;
46 if (TotalBytes == 0)
47 break;
48 Begin += Written;
49 }
50}
51
52std::pair<ssize_t, bool> retryingReadSome(int Fd, char *Begin,
53 char *End) XRAY_NEVER_INSTRUMENT {
54 auto BytesToRead = std::distance(Begin, End);
55 ssize_t BytesRead;
56 ssize_t TotalBytesRead = 0;
57 while (BytesToRead && (BytesRead = read(Fd, Begin, BytesToRead))) {
58 if (BytesRead == -1) {
59 if (errno == EINTR)
60 continue;
61 Report("Read error; errno = %d\n", errno);
62 return std::make_pair(TotalBytesRead, false);
63 }
64
65 TotalBytesRead += BytesRead;
66 BytesToRead -= BytesRead;
67 Begin += BytesRead;
68 }
69 return std::make_pair(TotalBytesRead, true);
70}
71
72bool readValueFromFile(const char *Filename,
73 long long *Value) XRAY_NEVER_INSTRUMENT {
74 int Fd = open(Filename, O_RDONLY | O_CLOEXEC);
75 if (Fd == -1)
76 return false;
77 static constexpr size_t BufSize = 256;
78 char Line[BufSize] = {};
79 ssize_t BytesRead;
80 bool Success;
81 std::tie(BytesRead, Success) = retryingReadSome(Fd, Line, Line + BufSize);
82 if (!Success)
83 return false;
84 close(Fd);
85 char *End = nullptr;
86 long long Tmp = internal_simple_strtoll(Line, &End, 10);
87 bool Result = false;
88 if (Line[0] != '\0' && (*End == '\n' || *End == '\0')) {
89 *Value = Tmp;
90 Result = true;
91 }
92 return Result;
93}
94
Dean Michael Berrise7dbebf2017-01-25 03:50:46 +000095int getLogFD() XRAY_NEVER_INSTRUMENT {
96 // FIXME: Figure out how to make this less stderr-dependent.
Dean Michael Berrisea9042c2017-02-07 23:35:34 +000097 SetPrintfAndReportCallback(printToStdErr);
Dean Michael Berrise7dbebf2017-01-25 03:50:46 +000098 // Open a temporary file once for the log.
99 static char TmpFilename[256] = {};
100 static char TmpWildcardPattern[] = "XXXXXX";
101 auto Argv = GetArgv();
102 const char *Progname = Argv[0] == nullptr ? "(unknown)" : Argv[0];
103 const char *LastSlash = internal_strrchr(Progname, '/');
104
105 if (LastSlash != nullptr)
106 Progname = LastSlash + 1;
107
108 const int HalfLength = sizeof(TmpFilename) / 2 - sizeof(TmpWildcardPattern);
109 int NeededLength = internal_snprintf(
110 TmpFilename, sizeof(TmpFilename), "%.*s%.*s.%s", HalfLength,
111 flags()->xray_logfile_base, HalfLength, Progname, TmpWildcardPattern);
112 if (NeededLength > int(sizeof(TmpFilename))) {
113 Report("XRay log file name too long (%d): %s\n", NeededLength, TmpFilename);
114 return -1;
115 }
116 int Fd = mkstemp(TmpFilename);
117 if (Fd == -1) {
118 Report("XRay: Failed opening temporary file '%s'; not logging events.\n",
119 TmpFilename);
120 return -1;
121 }
122 if (Verbosity())
123 fprintf(stderr, "XRay: Log file in '%s'\n", TmpFilename);
124
125 return Fd;
126}
127
128} // namespace __xray