• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- sanitizer_common.cc -----------------------------------------------===//
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 shared between AddressSanitizer and ThreadSanitizer
11 // run-time libraries.
12 //===----------------------------------------------------------------------===//
13 
14 #include "sanitizer_common.h"
15 #include "sanitizer_libc.h"
16 
17 namespace __sanitizer {
18 
19 const char *SanitizerToolName = "SanitizerTool";
20 uptr SanitizerVerbosity = 0;
21 
GetPageSizeCached()22 uptr GetPageSizeCached() {
23   static uptr PageSize;
24   if (!PageSize)
25     PageSize = GetPageSize();
26   return PageSize;
27 }
28 
29 static bool log_to_file = false;  // Set to true by __sanitizer_set_report_path
30 
31 // By default, dump to stderr. If |log_to_file| is true and |report_fd_pid|
32 // isn't equal to the current PID, try to obtain file descriptor by opening
33 // file "report_path_prefix.<PID>".
34 fd_t report_fd = kStderrFd;
35 static char report_path_prefix[4096];  // Set via __sanitizer_set_report_path.
36 // PID of process that opened |report_fd|. If a fork() occurs, the PID of the
37 // child thread will be different from |report_fd_pid|.
38 static uptr report_fd_pid = 0;
39 
40 static void (*DieCallback)(void);
SetDieCallback(void (* callback)(void))41 void SetDieCallback(void (*callback)(void)) {
42   DieCallback = callback;
43 }
44 
Die()45 void NORETURN Die() {
46   if (DieCallback) {
47     DieCallback();
48   }
49   internal__exit(1);
50 }
51 
52 static CheckFailedCallbackType CheckFailedCallback;
SetCheckFailedCallback(CheckFailedCallbackType callback)53 void SetCheckFailedCallback(CheckFailedCallbackType callback) {
54   CheckFailedCallback = callback;
55 }
56 
CheckFailed(const char * file,int line,const char * cond,u64 v1,u64 v2)57 void NORETURN CheckFailed(const char *file, int line, const char *cond,
58                           u64 v1, u64 v2) {
59   if (CheckFailedCallback) {
60     CheckFailedCallback(file, line, cond, v1, v2);
61   }
62   Report("Sanitizer CHECK failed: %s:%d %s (%lld, %lld)\n", file, line, cond,
63                                                             v1, v2);
64   Die();
65 }
66 
MaybeOpenReportFile()67 void MaybeOpenReportFile() {
68   if (!log_to_file || (report_fd_pid == internal_getpid())) return;
69   InternalScopedBuffer<char> report_path_full(4096);
70   internal_snprintf(report_path_full.data(), report_path_full.size(),
71                     "%s.%d", report_path_prefix, internal_getpid());
72   uptr openrv = OpenFile(report_path_full.data(), true);
73   if (internal_iserror(openrv)) {
74     report_fd = kStderrFd;
75     log_to_file = false;
76     Report("ERROR: Can't open file: %s\n", report_path_full.data());
77     Die();
78   }
79   if (report_fd != kInvalidFd) {
80     // We're in the child. Close the parent's log.
81     internal_close(report_fd);
82   }
83   report_fd = openrv;
84   report_fd_pid = internal_getpid();
85 }
86 
RawWrite(const char * buffer)87 void RawWrite(const char *buffer) {
88   static const char *kRawWriteError = "RawWrite can't output requested buffer!";
89   uptr length = (uptr)internal_strlen(buffer);
90   MaybeOpenReportFile();
91   if (length != internal_write(report_fd, buffer, length)) {
92     internal_write(report_fd, kRawWriteError, internal_strlen(kRawWriteError));
93     Die();
94   }
95 }
96 
ReadFileToBuffer(const char * file_name,char ** buff,uptr * buff_size,uptr max_len)97 uptr ReadFileToBuffer(const char *file_name, char **buff,
98                       uptr *buff_size, uptr max_len) {
99   uptr PageSize = GetPageSizeCached();
100   uptr kMinFileLen = PageSize;
101   uptr read_len = 0;
102   *buff = 0;
103   *buff_size = 0;
104   // The files we usually open are not seekable, so try different buffer sizes.
105   for (uptr size = kMinFileLen; size <= max_len; size *= 2) {
106     uptr openrv = OpenFile(file_name, /*write*/ false);
107     if (internal_iserror(openrv)) return 0;
108     fd_t fd = openrv;
109     UnmapOrDie(*buff, *buff_size);
110     *buff = (char*)MmapOrDie(size, __FUNCTION__);
111     *buff_size = size;
112     // Read up to one page at a time.
113     read_len = 0;
114     bool reached_eof = false;
115     while (read_len + PageSize <= size) {
116       uptr just_read = internal_read(fd, *buff + read_len, PageSize);
117       if (just_read == 0) {
118         reached_eof = true;
119         break;
120       }
121       read_len += just_read;
122     }
123     internal_close(fd);
124     if (reached_eof)  // We've read the whole file.
125       break;
126   }
127   return read_len;
128 }
129 
130 typedef bool UptrComparisonFunction(const uptr &a, const uptr &b);
131 
132 template<class T>
CompareLess(const T & a,const T & b)133 static inline bool CompareLess(const T &a, const T &b) {
134   return a < b;
135 }
136 
SortArray(uptr * array,uptr size)137 void SortArray(uptr *array, uptr size) {
138   InternalSort<uptr*, UptrComparisonFunction>(&array, size, CompareLess);
139 }
140 
141 // We want to map a chunk of address space aligned to 'alignment'.
142 // We do it by maping a bit more and then unmaping redundant pieces.
143 // We probably can do it with fewer syscalls in some OS-dependent way.
MmapAlignedOrDie(uptr size,uptr alignment,const char * mem_type)144 void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type) {
145 // uptr PageSize = GetPageSizeCached();
146   CHECK(IsPowerOfTwo(size));
147   CHECK(IsPowerOfTwo(alignment));
148   uptr map_size = size + alignment;
149   uptr map_res = (uptr)MmapOrDie(map_size, mem_type);
150   uptr map_end = map_res + map_size;
151   uptr res = map_res;
152   if (res & (alignment - 1))  // Not aligned.
153     res = (map_res + alignment) & ~(alignment - 1);
154   uptr end = res + size;
155   if (res != map_res)
156     UnmapOrDie((void*)map_res, res - map_res);
157   if (end != map_end)
158     UnmapOrDie((void*)end, map_end - end);
159   return (void*)res;
160 }
161 
ReportErrorSummary(const char * error_type,const char * file,int line,const char * function)162 void ReportErrorSummary(const char *error_type, const char *file,
163                         int line, const char *function) {
164   const int kMaxSize = 1024;  // We don't want a summary too long.
165   InternalScopedBuffer<char> buff(kMaxSize);
166   internal_snprintf(buff.data(), kMaxSize, "%s: %s %s:%d %s",
167                     SanitizerToolName, error_type,
168                     file ? file : "??", line, function ? function : "??");
169   __sanitizer_report_error_summary(buff.data());
170 }
171 
172 }  // namespace __sanitizer
173 
174 using namespace __sanitizer;  // NOLINT
175 
176 extern "C" {
__sanitizer_set_report_path(const char * path)177 void __sanitizer_set_report_path(const char *path) {
178   if (!path) return;
179   uptr len = internal_strlen(path);
180   if (len > sizeof(report_path_prefix) - 100) {
181     Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n",
182            path[0], path[1], path[2], path[3],
183            path[4], path[5], path[6], path[7]);
184     Die();
185   }
186   internal_strncpy(report_path_prefix, path, sizeof(report_path_prefix));
187   report_path_prefix[len] = '\0';
188   report_fd = kInvalidFd;
189   log_to_file = true;
190 }
191 
__sanitizer_set_report_fd(int fd)192 void __sanitizer_set_report_fd(int fd) {
193   if (report_fd != kStdoutFd &&
194       report_fd != kStderrFd &&
195       report_fd != kInvalidFd)
196     internal_close(report_fd);
197   report_fd = fd;
198 }
199 
__sanitizer_sandbox_on_notify(void * reserved)200 void NOINLINE __sanitizer_sandbox_on_notify(void *reserved) {
201   (void)reserved;
202   PrepareForSandboxing();
203 }
204 
__sanitizer_report_error_summary(const char * error_summary)205 void __sanitizer_report_error_summary(const char *error_summary) {
206   Printf("SUMMARY: %s\n", error_summary);
207 }
208 }  // extern "C"
209