sanitizer_common.cc revision 81dfbb76f858fbc4084771fce4967ede04ed5f44
1230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov//===-- sanitizer_common.cc -----------------------------------------------===// 2230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov// 3230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov// The LLVM Compiler Infrastructure 4230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov// 5230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov// This file is distributed under the University of Illinois Open Source 6230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov// License. See LICENSE.TXT for details. 7230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov// 8230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov//===----------------------------------------------------------------------===// 9230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov// 10230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer 11230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov// run-time libraries. 12230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov//===----------------------------------------------------------------------===// 13230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov 14230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov#include "sanitizer_common.h" 15230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov#include "sanitizer_libc.h" 164c49666e611f06241bb8462cea7674d877241492Alexey Samsonov 17230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonovnamespace __sanitizer { 18230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov 1981dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryanystatic fd_t report_fd = 2; // By default, dump to stderr. 2081dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryanystatic char report_path[4096]; // Set via __sanitizer_set_report_path. 2181dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany 22591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovstatic void (*DieCallback)(void); 23591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid SetDieCallback(void (*callback)(void)) { 24591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov DieCallback = callback; 25591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov} 26591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 27591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid NORETURN Die() { 28591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov if (DieCallback) { 29591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov DieCallback(); 30591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov } 31591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov Exit(1); 32591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov} 33591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 34591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovstatic CheckFailedCallbackType CheckFailedCallback; 35591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid SetCheckFailedCallback(CheckFailedCallbackType callback) { 36591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov CheckFailedCallback = callback; 37591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov} 38591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 39591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid NORETURN CheckFailed(const char *file, int line, const char *cond, 40591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov u64 v1, u64 v2) { 41591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov if (CheckFailedCallback) { 42591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov CheckFailedCallback(file, line, cond, v1, v2); 43591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov } 44591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov Report("Sanitizer CHECK failed: %s:%d %s (%zd, %zd)\n", file, line, cond, 45591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov v1, v2); 46591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov Die(); 47591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov} 48591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 49230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonovvoid RawWrite(const char *buffer) { 50230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov static const char *kRawWriteError = "RawWrite can't output requested buffer!"; 51230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov uptr length = (uptr)internal_strlen(buffer); 5281dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany if (report_fd == kInvalidFd) { 5381dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany fd_t fd = internal_open(report_path, true); 5481dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany if (fd == kInvalidFd) { 5581dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany report_fd = 2; 5681dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany Report("ERROR: Can't open file: %s\n", report_path); 5781dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany Die(); 5881dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany } 5981dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany report_fd = fd; 6081dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany } 6181dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany if (length != internal_write(report_fd, buffer, length)) { 6281dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany internal_write(report_fd, kRawWriteError, internal_strlen(kRawWriteError)); 63230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov Die(); 64230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov } 65230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov} 66230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov 67cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonovuptr ReadFileToBuffer(const char *file_name, char **buff, 68cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov uptr *buff_size, uptr max_len) { 69cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov const uptr kMinFileLen = kPageSize; 70cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov uptr read_len = 0; 71cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov *buff = 0; 72cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov *buff_size = 0; 73cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov // The files we usually open are not seekable, so try different buffer sizes. 74cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov for (uptr size = kMinFileLen; size <= max_len; size *= 2) { 75cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov fd_t fd = internal_open(file_name, /*write*/ false); 76cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov if (fd == kInvalidFd) return 0; 77cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov UnmapOrDie(*buff, *buff_size); 78cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov *buff = (char*)MmapOrDie(size, __FUNCTION__); 79cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov *buff_size = size; 80cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov // Read up to one page at a time. 81cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov read_len = 0; 82cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov bool reached_eof = false; 83cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov while (read_len + kPageSize <= size) { 84cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov uptr just_read = internal_read(fd, *buff + read_len, kPageSize); 85cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov if (just_read == 0) { 86cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov reached_eof = true; 87cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov break; 88cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov } 89cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov read_len += just_read; 90cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov } 91cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov internal_close(fd); 92cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov if (reached_eof) // We've read the whole file. 93cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov break; 94cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov } 95cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov return read_len; 96cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov} 97cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov 980dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov// We don't want to use std::sort to avoid including <algorithm>, as 990dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov// we may end up with two implementation of std::sort - one in instrumented 1000dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov// code, and the other in runtime. 1010dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov// qsort() from stdlib won't work as it calls malloc(), which results 1020dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov// in deadlock in ASan allocator. 1030dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov// We re-implement in-place sorting w/o recursion as straightforward heapsort. 1044c49666e611f06241bb8462cea7674d877241492Alexey Samsonovvoid SortArray(uptr *array, uptr size) { 1050dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov if (size < 2) 1060dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov return; 1070dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov // Stage 1: insert elements to the heap. 1080dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov for (uptr i = 1; i < size; i++) { 1090dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov uptr j, p; 1100dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov for (j = i; j > 0; j = p) { 1110dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov p = (j - 1) / 2; 1120dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov if (array[j] > array[p]) 1130dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov Swap(array[j], array[p]); 1140dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov else 1150dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov break; 1160dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov } 1170dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov } 1180dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov // Stage 2: swap largest element with the last one, 1190dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov // and sink the new top. 1200dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov for (uptr i = size - 1; i > 0; i--) { 1210dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov Swap(array[0], array[i]); 1220dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov uptr j, max_ind; 1230dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov for (j = 0; j < i; j = max_ind) { 1240dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov uptr left = 2 * j + 1; 1250dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov uptr right = 2 * j + 2; 1260dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov max_ind = j; 1270dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov if (left < i && array[left] > array[max_ind]) 1280dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov max_ind = left; 1290dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov if (right < i && array[right] > array[max_ind]) 1300dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov max_ind = right; 1310dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov if (max_ind != j) 1320dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov Swap(array[j], array[max_ind]); 1330dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov else 1340dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov break; 1350dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov } 1360dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov } 1374c49666e611f06241bb8462cea7674d877241492Alexey Samsonov} 1384c49666e611f06241bb8462cea7674d877241492Alexey Samsonov 139230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov} // namespace __sanitizer 14081dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany 14181dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryanyvoid __sanitizer_set_report_path(const char *path) { 14281dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany if (!path) return; 14381dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany uptr len = internal_strlen(path); 14481dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany if (len > sizeof(__sanitizer::report_path) - 100) { 14581dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", 14681dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany path[0], path[1], path[2], path[3], 14781dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany path[4], path[5], path[6], path[7]); 14881dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany Die(); 14981dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany } 15081dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany internal_snprintf(__sanitizer::report_path, 15181dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany sizeof(__sanitizer::report_path), "%s.%d", path, GetPid()); 15281dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany __sanitizer::report_fd = kInvalidFd; 15381dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany} 154