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 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); 41 void SetDieCallback(void (*callback)(void)) { 42 DieCallback = callback; 43 } 44 45 void NORETURN Die() { 46 if (DieCallback) { 47 DieCallback(); 48 } 49 internal__exit(1); 50 } 51 52 static CheckFailedCallbackType CheckFailedCallback; 53 void SetCheckFailedCallback(CheckFailedCallbackType callback) { 54 CheckFailedCallback = callback; 55 } 56 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 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 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 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> 133 static inline bool CompareLess(const T &a, const T &b) { 134 return a < b; 135 } 136 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. 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 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" { 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 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 200 void NOINLINE __sanitizer_sandbox_on_notify(void *reserved) { 201 (void)reserved; 202 PrepareForSandboxing(); 203 } 204 205 void __sanitizer_report_error_summary(const char *error_summary) { 206 Printf("SUMMARY: %s\n", error_summary); 207 } 208 } // extern "C" 209