Alexey Samsonov | 230c3be | 2012-06-06 09:26:25 +0000 | [diff] [blame] | 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" |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 15 | #include "sanitizer_allocator_internal.h" |
Alexey Samsonov | 90b0f1e | 2013-10-04 08:55:03 +0000 | [diff] [blame] | 16 | #include "sanitizer_flags.h" |
Alexey Samsonov | 230c3be | 2012-06-06 09:26:25 +0000 | [diff] [blame] | 17 | #include "sanitizer_libc.h" |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 18 | #include "sanitizer_placement_new.h" |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 19 | #include "sanitizer_stacktrace_printer.h" |
| 20 | #include "sanitizer_symbolizer.h" |
Alexey Samsonov | 4c49666 | 2012-06-15 07:00:31 +0000 | [diff] [blame] | 21 | |
Alexey Samsonov | 230c3be | 2012-06-06 09:26:25 +0000 | [diff] [blame] | 22 | namespace __sanitizer { |
| 23 | |
Kostya Serebryany | 859778a | 2013-01-31 14:11:21 +0000 | [diff] [blame] | 24 | const char *SanitizerToolName = "SanitizerTool"; |
| 25 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 26 | atomic_uint32_t current_verbosity; |
| 27 | |
Kostya Serebryany | f67ec2b | 2012-11-23 15:38:49 +0000 | [diff] [blame] | 28 | uptr GetPageSizeCached() { |
| 29 | static uptr PageSize; |
| 30 | if (!PageSize) |
| 31 | PageSize = GetPageSize(); |
| 32 | return PageSize; |
| 33 | } |
| 34 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 35 | StaticSpinMutex report_file_mu; |
| 36 | ReportFile report_file = {&report_file_mu, kStderrFd, "", "", 0}; |
Alexander Potapenko | dedba5d | 2013-01-18 16:44:27 +0000 | [diff] [blame] | 37 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 38 | void RawWrite(const char *buffer) { |
| 39 | report_file.Write(buffer, internal_strlen(buffer)); |
| 40 | } |
Reid Kleckner | 923bac7 | 2013-09-05 03:19:57 +0000 | [diff] [blame] | 41 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 42 | void ReportFile::ReopenIfNecessary() { |
| 43 | mu->CheckLocked(); |
| 44 | if (fd == kStdoutFd || fd == kStderrFd) return; |
Reid Kleckner | 923bac7 | 2013-09-05 03:19:57 +0000 | [diff] [blame] | 45 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 46 | uptr pid = internal_getpid(); |
| 47 | // If in tracer, use the parent's file. |
| 48 | if (pid == stoptheworld_tracer_pid) |
| 49 | pid = stoptheworld_tracer_ppid; |
| 50 | if (fd != kInvalidFd) { |
| 51 | // If the report file is already opened by the current process, |
| 52 | // do nothing. Otherwise the report file was opened by the parent |
| 53 | // process, close it now. |
| 54 | if (fd_pid == pid) |
| 55 | return; |
| 56 | else |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 57 | CloseFile(fd); |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 58 | } |
| 59 | |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 60 | const char *exe_name = GetBinaryBasename(); |
| 61 | if (common_flags()->log_exe_name && exe_name) { |
| 62 | internal_snprintf(full_path, kMaxPathLength, "%s.%s.%zu", path_prefix, |
| 63 | exe_name, pid); |
| 64 | } else { |
| 65 | internal_snprintf(full_path, kMaxPathLength, "%s.%zu", path_prefix, pid); |
| 66 | } |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 67 | fd = OpenFile(full_path, WrOnly); |
| 68 | if (fd == kInvalidFd) { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 69 | const char *ErrorMsgPrefix = "ERROR: Can't open file: "; |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 70 | WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix)); |
| 71 | WriteToFile(kStderrFd, full_path, internal_strlen(full_path)); |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 72 | Die(); |
| 73 | } |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 74 | fd_pid = pid; |
| 75 | } |
| 76 | |
| 77 | void ReportFile::SetReportPath(const char *path) { |
| 78 | if (!path) |
| 79 | return; |
| 80 | uptr len = internal_strlen(path); |
| 81 | if (len > sizeof(path_prefix) - 100) { |
| 82 | Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", |
| 83 | path[0], path[1], path[2], path[3], |
| 84 | path[4], path[5], path[6], path[7]); |
| 85 | Die(); |
| 86 | } |
| 87 | |
| 88 | SpinMutexLock l(mu); |
| 89 | if (fd != kStdoutFd && fd != kStderrFd && fd != kInvalidFd) |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 90 | CloseFile(fd); |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 91 | fd = kInvalidFd; |
| 92 | if (internal_strcmp(path, "stdout") == 0) { |
| 93 | fd = kStdoutFd; |
| 94 | } else if (internal_strcmp(path, "stderr") == 0) { |
| 95 | fd = kStderrFd; |
| 96 | } else { |
| 97 | internal_snprintf(path_prefix, kMaxPathLength, "%s", path); |
| 98 | } |
| 99 | } |
Kostya Serebryany | 81dfbb7 | 2012-09-14 04:35:14 +0000 | [diff] [blame] | 100 | |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 101 | // PID of the tracer task in StopTheWorld. It shares the address space with the |
| 102 | // main process, but has a different PID and thus requires special handling. |
| 103 | uptr stoptheworld_tracer_pid = 0; |
| 104 | // Cached pid of parent process - if the parent process dies, we want to keep |
| 105 | // writing to the same log file. |
| 106 | uptr stoptheworld_tracer_ppid = 0; |
| 107 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 108 | static DieCallbackType InternalDieCallback, UserDieCallback; |
Sergey Matveev | 90629fb | 2013-08-26 13:20:31 +0000 | [diff] [blame] | 109 | void SetDieCallback(DieCallbackType callback) { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 110 | InternalDieCallback = callback; |
| 111 | } |
| 112 | void SetUserDieCallback(DieCallbackType callback) { |
| 113 | UserDieCallback = callback; |
Alexey Samsonov | 591616d | 2012-09-11 09:44:48 +0000 | [diff] [blame] | 114 | } |
| 115 | |
Sergey Matveev | 90629fb | 2013-08-26 13:20:31 +0000 | [diff] [blame] | 116 | DieCallbackType GetDieCallback() { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 117 | return InternalDieCallback; |
Sergey Matveev | 90629fb | 2013-08-26 13:20:31 +0000 | [diff] [blame] | 118 | } |
| 119 | |
Alexey Samsonov | 591616d | 2012-09-11 09:44:48 +0000 | [diff] [blame] | 120 | void NORETURN Die() { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 121 | if (UserDieCallback) |
| 122 | UserDieCallback(); |
| 123 | if (InternalDieCallback) |
| 124 | InternalDieCallback(); |
Alexey Samsonov | f882247 | 2013-02-20 13:54:32 +0000 | [diff] [blame] | 125 | internal__exit(1); |
Alexey Samsonov | 591616d | 2012-09-11 09:44:48 +0000 | [diff] [blame] | 126 | } |
| 127 | |
| 128 | static CheckFailedCallbackType CheckFailedCallback; |
| 129 | void SetCheckFailedCallback(CheckFailedCallbackType callback) { |
| 130 | CheckFailedCallback = callback; |
| 131 | } |
| 132 | |
| 133 | void NORETURN CheckFailed(const char *file, int line, const char *cond, |
| 134 | u64 v1, u64 v2) { |
| 135 | if (CheckFailedCallback) { |
| 136 | CheckFailedCallback(file, line, cond, v1, v2); |
| 137 | } |
Dmitry Vyukov | e3c35c7 | 2013-01-11 15:07:49 +0000 | [diff] [blame] | 138 | Report("Sanitizer CHECK failed: %s:%d %s (%lld, %lld)\n", file, line, cond, |
| 139 | v1, v2); |
Alexey Samsonov | 591616d | 2012-09-11 09:44:48 +0000 | [diff] [blame] | 140 | Die(); |
| 141 | } |
| 142 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 143 | uptr ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size, |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 144 | uptr max_len, error_t *errno_p) { |
Kostya Serebryany | f67ec2b | 2012-11-23 15:38:49 +0000 | [diff] [blame] | 145 | uptr PageSize = GetPageSizeCached(); |
| 146 | uptr kMinFileLen = PageSize; |
Alexey Samsonov | cffe2f5 | 2012-06-07 05:38:26 +0000 | [diff] [blame] | 147 | uptr read_len = 0; |
| 148 | *buff = 0; |
| 149 | *buff_size = 0; |
| 150 | // The files we usually open are not seekable, so try different buffer sizes. |
| 151 | for (uptr size = kMinFileLen; size <= max_len; size *= 2) { |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 152 | fd_t fd = OpenFile(file_name, RdOnly, errno_p); |
| 153 | if (fd == kInvalidFd) return 0; |
Alexey Samsonov | cffe2f5 | 2012-06-07 05:38:26 +0000 | [diff] [blame] | 154 | UnmapOrDie(*buff, *buff_size); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 155 | *buff = (char*)MmapOrDie(size, __func__); |
Alexey Samsonov | cffe2f5 | 2012-06-07 05:38:26 +0000 | [diff] [blame] | 156 | *buff_size = size; |
| 157 | // Read up to one page at a time. |
| 158 | read_len = 0; |
| 159 | bool reached_eof = false; |
Kostya Serebryany | f67ec2b | 2012-11-23 15:38:49 +0000 | [diff] [blame] | 160 | while (read_len + PageSize <= size) { |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 161 | uptr just_read; |
| 162 | if (!ReadFromFile(fd, *buff + read_len, PageSize, &just_read, errno_p)) { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 163 | UnmapOrDie(*buff, *buff_size); |
| 164 | return 0; |
| 165 | } |
Alexey Samsonov | cffe2f5 | 2012-06-07 05:38:26 +0000 | [diff] [blame] | 166 | if (just_read == 0) { |
| 167 | reached_eof = true; |
| 168 | break; |
| 169 | } |
| 170 | read_len += just_read; |
| 171 | } |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 172 | CloseFile(fd); |
Alexey Samsonov | cffe2f5 | 2012-06-07 05:38:26 +0000 | [diff] [blame] | 173 | if (reached_eof) // We've read the whole file. |
| 174 | break; |
| 175 | } |
| 176 | return read_len; |
| 177 | } |
| 178 | |
Sergey Matveev | 15bb32b | 2013-05-13 11:58:48 +0000 | [diff] [blame] | 179 | typedef bool UptrComparisonFunction(const uptr &a, const uptr &b); |
| 180 | |
| 181 | template<class T> |
| 182 | static inline bool CompareLess(const T &a, const T &b) { |
| 183 | return a < b; |
| 184 | } |
| 185 | |
Alexey Samsonov | 4c49666 | 2012-06-15 07:00:31 +0000 | [diff] [blame] | 186 | void SortArray(uptr *array, uptr size) { |
Sergey Matveev | 15bb32b | 2013-05-13 11:58:48 +0000 | [diff] [blame] | 187 | InternalSort<uptr*, UptrComparisonFunction>(&array, size, CompareLess); |
Alexey Samsonov | 4c49666 | 2012-06-15 07:00:31 +0000 | [diff] [blame] | 188 | } |
| 189 | |
Kostya Serebryany | cc75259 | 2012-12-06 06:10:31 +0000 | [diff] [blame] | 190 | // We want to map a chunk of address space aligned to 'alignment'. |
| 191 | // We do it by maping a bit more and then unmaping redundant pieces. |
| 192 | // We probably can do it with fewer syscalls in some OS-dependent way. |
| 193 | void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type) { |
Bill Wendling | 2dae63a | 2012-12-06 07:43:17 +0000 | [diff] [blame] | 194 | // uptr PageSize = GetPageSizeCached(); |
Kostya Serebryany | cc75259 | 2012-12-06 06:10:31 +0000 | [diff] [blame] | 195 | CHECK(IsPowerOfTwo(size)); |
| 196 | CHECK(IsPowerOfTwo(alignment)); |
| 197 | uptr map_size = size + alignment; |
| 198 | uptr map_res = (uptr)MmapOrDie(map_size, mem_type); |
| 199 | uptr map_end = map_res + map_size; |
| 200 | uptr res = map_res; |
| 201 | if (res & (alignment - 1)) // Not aligned. |
Dmitry Vyukov | 3617ad7 | 2012-12-06 15:42:54 +0000 | [diff] [blame] | 202 | res = (map_res + alignment) & ~(alignment - 1); |
Kostya Serebryany | cc75259 | 2012-12-06 06:10:31 +0000 | [diff] [blame] | 203 | uptr end = res + size; |
| 204 | if (res != map_res) |
| 205 | UnmapOrDie((void*)map_res, res - map_res); |
| 206 | if (end != map_end) |
| 207 | UnmapOrDie((void*)end, map_end - end); |
| 208 | return (void*)res; |
| 209 | } |
| 210 | |
Alexey Samsonov | 90b0f1e | 2013-10-04 08:55:03 +0000 | [diff] [blame] | 211 | const char *StripPathPrefix(const char *filepath, |
| 212 | const char *strip_path_prefix) { |
| 213 | if (filepath == 0) return 0; |
| 214 | if (strip_path_prefix == 0) return filepath; |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 215 | const char *res = filepath; |
| 216 | if (const char *pos = internal_strstr(filepath, strip_path_prefix)) |
| 217 | res = pos + internal_strlen(strip_path_prefix); |
| 218 | if (res[0] == '.' && res[1] == '/') |
| 219 | res += 2; |
| 220 | return res; |
Alexey Samsonov | 90b0f1e | 2013-10-04 08:55:03 +0000 | [diff] [blame] | 221 | } |
| 222 | |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 223 | const char *StripModuleName(const char *module) { |
| 224 | if (module == 0) |
| 225 | return 0; |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 226 | if (SANITIZER_WINDOWS) { |
| 227 | // On Windows, both slash and backslash are possible. |
| 228 | // Pick the one that goes last. |
| 229 | if (const char *bslash_pos = internal_strrchr(module, '\\')) |
| 230 | return StripModuleName(bslash_pos + 1); |
| 231 | } |
| 232 | if (const char *slash_pos = internal_strrchr(module, '/')) { |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 233 | return slash_pos + 1; |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 234 | } |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 235 | return module; |
Alexey Samsonov | 90b0f1e | 2013-10-04 08:55:03 +0000 | [diff] [blame] | 236 | } |
| 237 | |
Alexey Samsonov | 2fb0872 | 2013-11-01 17:02:14 +0000 | [diff] [blame] | 238 | void ReportErrorSummary(const char *error_message) { |
Alexey Samsonov | 694d856 | 2013-11-14 08:56:59 +0000 | [diff] [blame] | 239 | if (!common_flags()->print_summary) |
| 240 | return; |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 241 | InternalScopedString buff(kMaxSummaryLength); |
| 242 | buff.append("SUMMARY: %s: %s", SanitizerToolName, error_message); |
Alexey Samsonov | 2fb0872 | 2013-11-01 17:02:14 +0000 | [diff] [blame] | 243 | __sanitizer_report_error_summary(buff.data()); |
| 244 | } |
| 245 | |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 246 | #ifndef SANITIZER_GO |
| 247 | void ReportErrorSummary(const char *error_type, const AddressInfo &info) { |
Alexey Samsonov | 694d856 | 2013-11-14 08:56:59 +0000 | [diff] [blame] | 248 | if (!common_flags()->print_summary) |
| 249 | return; |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 250 | InternalScopedString buff(kMaxSummaryLength); |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 251 | buff.append("%s ", error_type); |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 252 | RenderFrame(&buff, "%L %F", 0, info, common_flags()->symbolize_vs_style, |
| 253 | common_flags()->strip_path_prefix); |
Alexey Samsonov | 2fb0872 | 2013-11-01 17:02:14 +0000 | [diff] [blame] | 254 | ReportErrorSummary(buff.data()); |
| 255 | } |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 256 | #endif |
Alexey Samsonov | 2fb0872 | 2013-11-01 17:02:14 +0000 | [diff] [blame] | 257 | |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 258 | void LoadedModule::set(const char *module_name, uptr base_address) { |
| 259 | clear(); |
Alexey Samsonov | 7847d77 | 2013-09-10 14:36:16 +0000 | [diff] [blame] | 260 | full_name_ = internal_strdup(module_name); |
| 261 | base_address_ = base_address; |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 262 | } |
| 263 | |
| 264 | void LoadedModule::clear() { |
| 265 | InternalFree(full_name_); |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 266 | full_name_ = nullptr; |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 267 | while (!ranges_.empty()) { |
| 268 | AddressRange *r = ranges_.front(); |
| 269 | ranges_.pop_front(); |
| 270 | InternalFree(r); |
| 271 | } |
Alexey Samsonov | 7847d77 | 2013-09-10 14:36:16 +0000 | [diff] [blame] | 272 | } |
| 273 | |
Stephen Hines | 6a211c5 | 2014-07-21 00:49:56 -0700 | [diff] [blame] | 274 | void LoadedModule::addAddressRange(uptr beg, uptr end, bool executable) { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 275 | void *mem = InternalAlloc(sizeof(AddressRange)); |
| 276 | AddressRange *r = new(mem) AddressRange(beg, end, executable); |
| 277 | ranges_.push_back(r); |
Alexey Samsonov | 7847d77 | 2013-09-10 14:36:16 +0000 | [diff] [blame] | 278 | } |
| 279 | |
| 280 | bool LoadedModule::containsAddress(uptr address) const { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 281 | for (Iterator iter = ranges(); iter.hasNext();) { |
| 282 | const AddressRange *r = iter.next(); |
| 283 | if (r->beg <= address && address < r->end) |
Alexey Samsonov | 7847d77 | 2013-09-10 14:36:16 +0000 | [diff] [blame] | 284 | return true; |
| 285 | } |
| 286 | return false; |
| 287 | } |
| 288 | |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 289 | static atomic_uintptr_t g_total_mmaped; |
| 290 | |
| 291 | void IncreaseTotalMmap(uptr size) { |
| 292 | if (!common_flags()->mmap_limit_mb) return; |
| 293 | uptr total_mmaped = |
| 294 | atomic_fetch_add(&g_total_mmaped, size, memory_order_relaxed) + size; |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 295 | // Since for now mmap_limit_mb is not a user-facing flag, just kill |
| 296 | // a program. Use RAW_CHECK to avoid extra mmaps in reporting. |
| 297 | RAW_CHECK((total_mmaped >> 20) < common_flags()->mmap_limit_mb); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 298 | } |
| 299 | |
| 300 | void DecreaseTotalMmap(uptr size) { |
| 301 | if (!common_flags()->mmap_limit_mb) return; |
| 302 | atomic_fetch_sub(&g_total_mmaped, size, memory_order_relaxed); |
| 303 | } |
| 304 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 305 | bool TemplateMatch(const char *templ, const char *str) { |
| 306 | if (str == 0 || str[0] == 0) |
| 307 | return false; |
| 308 | bool start = false; |
| 309 | if (templ && templ[0] == '^') { |
| 310 | start = true; |
| 311 | templ++; |
| 312 | } |
| 313 | bool asterisk = false; |
| 314 | while (templ && templ[0]) { |
| 315 | if (templ[0] == '*') { |
| 316 | templ++; |
| 317 | start = false; |
| 318 | asterisk = true; |
| 319 | continue; |
| 320 | } |
| 321 | if (templ[0] == '$') |
| 322 | return str[0] == 0 || asterisk; |
| 323 | if (str[0] == 0) |
| 324 | return false; |
| 325 | char *tpos = (char*)internal_strchr(templ, '*'); |
| 326 | char *tpos1 = (char*)internal_strchr(templ, '$'); |
| 327 | if (tpos == 0 || (tpos1 && tpos1 < tpos)) |
| 328 | tpos = tpos1; |
| 329 | if (tpos != 0) |
| 330 | tpos[0] = 0; |
| 331 | const char *str0 = str; |
| 332 | const char *spos = internal_strstr(str, templ); |
| 333 | str = spos + internal_strlen(templ); |
| 334 | templ = tpos; |
| 335 | if (tpos) |
| 336 | tpos[0] = tpos == tpos1 ? '$' : '*'; |
| 337 | if (spos == 0) |
| 338 | return false; |
| 339 | if (start && spos != str0) |
| 340 | return false; |
| 341 | start = false; |
| 342 | asterisk = false; |
| 343 | } |
| 344 | return true; |
| 345 | } |
| 346 | |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 347 | static char binary_name_cache_str[kMaxPathLength]; |
| 348 | static const char *binary_basename_cache_str; |
| 349 | |
| 350 | const char *GetBinaryName() { |
| 351 | return binary_name_cache_str; |
| 352 | } |
| 353 | |
| 354 | const char *GetBinaryBasename() { |
| 355 | return binary_basename_cache_str; |
| 356 | } |
| 357 | |
| 358 | // Call once to make sure that binary_name_cache_str is initialized |
| 359 | void CacheBinaryName() { |
| 360 | CHECK_EQ('\0', binary_name_cache_str[0]); |
| 361 | ReadBinaryName(binary_name_cache_str, sizeof(binary_name_cache_str)); |
| 362 | binary_basename_cache_str = StripModuleName(binary_name_cache_str); |
| 363 | } |
| 364 | |
Alexey Samsonov | 230c3be | 2012-06-06 09:26:25 +0000 | [diff] [blame] | 365 | } // namespace __sanitizer |
Kostya Serebryany | 81dfbb7 | 2012-09-14 04:35:14 +0000 | [diff] [blame] | 366 | |
Alexey Samsonov | ac8564e | 2012-11-02 09:23:36 +0000 | [diff] [blame] | 367 | using namespace __sanitizer; // NOLINT |
| 368 | |
| 369 | extern "C" { |
Kostya Serebryany | 81dfbb7 | 2012-09-14 04:35:14 +0000 | [diff] [blame] | 370 | void __sanitizer_set_report_path(const char *path) { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 371 | report_file.SetReportPath(path); |
Alexey Samsonov | ac8564e | 2012-11-02 09:23:36 +0000 | [diff] [blame] | 372 | } |
Alexander Potapenko | 2574257 | 2012-12-10 13:10:40 +0000 | [diff] [blame] | 373 | |
Kostya Serebryany | 2673fd8 | 2013-02-06 12:36:49 +0000 | [diff] [blame] | 374 | void __sanitizer_report_error_summary(const char *error_summary) { |
Nick Lewycky | 47fcd76 | 2013-10-23 07:45:53 +0000 | [diff] [blame] | 375 | Printf("%s\n", error_summary); |
Kostya Serebryany | 2673fd8 | 2013-02-06 12:36:49 +0000 | [diff] [blame] | 376 | } |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 377 | |
| 378 | SANITIZER_INTERFACE_ATTRIBUTE |
| 379 | void __sanitizer_set_death_callback(void (*callback)(void)) { |
| 380 | SetUserDieCallback(callback); |
| 381 | } |
Alexey Samsonov | ac8564e | 2012-11-02 09:23:36 +0000 | [diff] [blame] | 382 | } // extern "C" |