sanitizer_common.cc revision 81dfbb76f858fbc4084771fce4967ede04ed5f44
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 17namespace __sanitizer { 18 19static fd_t report_fd = 2; // By default, dump to stderr. 20static char report_path[4096]; // Set via __sanitizer_set_report_path. 21 22static void (*DieCallback)(void); 23void SetDieCallback(void (*callback)(void)) { 24 DieCallback = callback; 25} 26 27void NORETURN Die() { 28 if (DieCallback) { 29 DieCallback(); 30 } 31 Exit(1); 32} 33 34static CheckFailedCallbackType CheckFailedCallback; 35void SetCheckFailedCallback(CheckFailedCallbackType callback) { 36 CheckFailedCallback = callback; 37} 38 39void NORETURN CheckFailed(const char *file, int line, const char *cond, 40 u64 v1, u64 v2) { 41 if (CheckFailedCallback) { 42 CheckFailedCallback(file, line, cond, v1, v2); 43 } 44 Report("Sanitizer CHECK failed: %s:%d %s (%zd, %zd)\n", file, line, cond, 45 v1, v2); 46 Die(); 47} 48 49void RawWrite(const char *buffer) { 50 static const char *kRawWriteError = "RawWrite can't output requested buffer!"; 51 uptr length = (uptr)internal_strlen(buffer); 52 if (report_fd == kInvalidFd) { 53 fd_t fd = internal_open(report_path, true); 54 if (fd == kInvalidFd) { 55 report_fd = 2; 56 Report("ERROR: Can't open file: %s\n", report_path); 57 Die(); 58 } 59 report_fd = fd; 60 } 61 if (length != internal_write(report_fd, buffer, length)) { 62 internal_write(report_fd, kRawWriteError, internal_strlen(kRawWriteError)); 63 Die(); 64 } 65} 66 67uptr ReadFileToBuffer(const char *file_name, char **buff, 68 uptr *buff_size, uptr max_len) { 69 const uptr kMinFileLen = kPageSize; 70 uptr read_len = 0; 71 *buff = 0; 72 *buff_size = 0; 73 // The files we usually open are not seekable, so try different buffer sizes. 74 for (uptr size = kMinFileLen; size <= max_len; size *= 2) { 75 fd_t fd = internal_open(file_name, /*write*/ false); 76 if (fd == kInvalidFd) return 0; 77 UnmapOrDie(*buff, *buff_size); 78 *buff = (char*)MmapOrDie(size, __FUNCTION__); 79 *buff_size = size; 80 // Read up to one page at a time. 81 read_len = 0; 82 bool reached_eof = false; 83 while (read_len + kPageSize <= size) { 84 uptr just_read = internal_read(fd, *buff + read_len, kPageSize); 85 if (just_read == 0) { 86 reached_eof = true; 87 break; 88 } 89 read_len += just_read; 90 } 91 internal_close(fd); 92 if (reached_eof) // We've read the whole file. 93 break; 94 } 95 return read_len; 96} 97 98// We don't want to use std::sort to avoid including <algorithm>, as 99// we may end up with two implementation of std::sort - one in instrumented 100// code, and the other in runtime. 101// qsort() from stdlib won't work as it calls malloc(), which results 102// in deadlock in ASan allocator. 103// We re-implement in-place sorting w/o recursion as straightforward heapsort. 104void SortArray(uptr *array, uptr size) { 105 if (size < 2) 106 return; 107 // Stage 1: insert elements to the heap. 108 for (uptr i = 1; i < size; i++) { 109 uptr j, p; 110 for (j = i; j > 0; j = p) { 111 p = (j - 1) / 2; 112 if (array[j] > array[p]) 113 Swap(array[j], array[p]); 114 else 115 break; 116 } 117 } 118 // Stage 2: swap largest element with the last one, 119 // and sink the new top. 120 for (uptr i = size - 1; i > 0; i--) { 121 Swap(array[0], array[i]); 122 uptr j, max_ind; 123 for (j = 0; j < i; j = max_ind) { 124 uptr left = 2 * j + 1; 125 uptr right = 2 * j + 2; 126 max_ind = j; 127 if (left < i && array[left] > array[max_ind]) 128 max_ind = left; 129 if (right < i && array[right] > array[max_ind]) 130 max_ind = right; 131 if (max_ind != j) 132 Swap(array[j], array[max_ind]); 133 else 134 break; 135 } 136 } 137} 138 139} // namespace __sanitizer 140 141void __sanitizer_set_report_path(const char *path) { 142 if (!path) return; 143 uptr len = internal_strlen(path); 144 if (len > sizeof(__sanitizer::report_path) - 100) { 145 Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", 146 path[0], path[1], path[2], path[3], 147 path[4], path[5], path[6], path[7]); 148 Die(); 149 } 150 internal_snprintf(__sanitizer::report_path, 151 sizeof(__sanitizer::report_path), "%s.%d", path, GetPid()); 152 __sanitizer::report_fd = kInvalidFd; 153} 154