sanitizer_common.cc revision 923bac7a85d8bd37219b440a6b4c0800ea4bcd21
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 19859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryanyconst char *SanitizerToolName = "SanitizerTool"; 203614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenkouptr SanitizerVerbosity = 0; 21859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany 22f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryanyuptr GetPageSizeCached() { 23f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany static uptr PageSize; 24f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany if (!PageSize) 25f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany PageSize = GetPageSize(); 26f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany return PageSize; 27f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany} 28f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany 29dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko 30dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko// By default, dump to stderr. If |log_to_file| is true and |report_fd_pid| 31dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko// isn't equal to the current PID, try to obtain file descriptor by opening 32dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko// file "report_path_prefix.<PID>". 330c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbournefd_t report_fd = kStderrFd; 34923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckner 35923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckner// Set via __sanitizer_set_report_path. 36923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Klecknerbool log_to_file = false; 37923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Klecknerchar report_path_prefix[sizeof(report_path_prefix)]; 38923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckner 39dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko// PID of process that opened |report_fd|. If a fork() occurs, the PID of the 40dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko// child thread will be different from |report_fd_pid|. 41923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckneruptr report_fd_pid = 0; 4281dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany 4390629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveevstatic DieCallbackType DieCallback; 4490629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveevvoid SetDieCallback(DieCallbackType callback) { 45591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov DieCallback = callback; 46591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov} 47591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 4890629fb8072efc95e46a0cbc641293511fbaba2eSergey MatveevDieCallbackType GetDieCallback() { 4990629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev return DieCallback; 5090629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev} 5190629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev 52591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid NORETURN Die() { 53591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov if (DieCallback) { 54591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov DieCallback(); 55591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov } 56f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov internal__exit(1); 57591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov} 58591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 59591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovstatic CheckFailedCallbackType CheckFailedCallback; 60591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid SetCheckFailedCallback(CheckFailedCallbackType callback) { 61591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov CheckFailedCallback = callback; 62591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov} 63591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 64591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid NORETURN CheckFailed(const char *file, int line, const char *cond, 65591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov u64 v1, u64 v2) { 66591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov if (CheckFailedCallback) { 67591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov CheckFailedCallback(file, line, cond, v1, v2); 68591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov } 69e3c35c7e30ce24b76f1e67eb049cf9e84c9b89d8Dmitry Vyukov Report("Sanitizer CHECK failed: %s:%d %s (%lld, %lld)\n", file, line, cond, 70e3c35c7e30ce24b76f1e67eb049cf9e84c9b89d8Dmitry Vyukov v1, v2); 71591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov Die(); 72591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov} 73591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 74cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonovuptr ReadFileToBuffer(const char *file_name, char **buff, 75cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov uptr *buff_size, uptr max_len) { 76f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany uptr PageSize = GetPageSizeCached(); 77f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany uptr kMinFileLen = PageSize; 78cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov uptr read_len = 0; 79cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov *buff = 0; 80cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov *buff_size = 0; 81cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov // The files we usually open are not seekable, so try different buffer sizes. 82cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov for (uptr size = kMinFileLen; size <= max_len; size *= 2) { 839578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne uptr openrv = OpenFile(file_name, /*write*/ false); 849578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne if (internal_iserror(openrv)) return 0; 859578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne fd_t fd = openrv; 86cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov UnmapOrDie(*buff, *buff_size); 87cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov *buff = (char*)MmapOrDie(size, __FUNCTION__); 88cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov *buff_size = size; 89cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov // Read up to one page at a time. 90cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov read_len = 0; 91cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov bool reached_eof = false; 92f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany while (read_len + PageSize <= size) { 93f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany uptr just_read = internal_read(fd, *buff + read_len, PageSize); 94cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov if (just_read == 0) { 95cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov reached_eof = true; 96cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov break; 97cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov } 98cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov read_len += just_read; 99cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov } 100cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov internal_close(fd); 101cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov if (reached_eof) // We've read the whole file. 102cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov break; 103cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov } 104cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov return read_len; 105cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov} 106cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov 10715bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveevtypedef bool UptrComparisonFunction(const uptr &a, const uptr &b); 10815bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev 10915bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveevtemplate<class T> 11015bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveevstatic inline bool CompareLess(const T &a, const T &b) { 11115bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev return a < b; 11215bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev} 11315bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev 1144c49666e611f06241bb8462cea7674d877241492Alexey Samsonovvoid SortArray(uptr *array, uptr size) { 11515bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev InternalSort<uptr*, UptrComparisonFunction>(&array, size, CompareLess); 1164c49666e611f06241bb8462cea7674d877241492Alexey Samsonov} 1174c49666e611f06241bb8462cea7674d877241492Alexey Samsonov 118cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany// We want to map a chunk of address space aligned to 'alignment'. 119cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany// We do it by maping a bit more and then unmaping redundant pieces. 120cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany// We probably can do it with fewer syscalls in some OS-dependent way. 121cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryanyvoid *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type) { 1222dae63aea3589fded1ef17b5a6c7f0c9352559a2Bill Wendling// uptr PageSize = GetPageSizeCached(); 123cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany CHECK(IsPowerOfTwo(size)); 124cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany CHECK(IsPowerOfTwo(alignment)); 125cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany uptr map_size = size + alignment; 126cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany uptr map_res = (uptr)MmapOrDie(map_size, mem_type); 127cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany uptr map_end = map_res + map_size; 128cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany uptr res = map_res; 129cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany if (res & (alignment - 1)) // Not aligned. 1303617ad70f3ade71b944b35fa3faaadfb97700deaDmitry Vyukov res = (map_res + alignment) & ~(alignment - 1); 131cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany uptr end = res + size; 132cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany if (res != map_res) 133cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany UnmapOrDie((void*)map_res, res - map_res); 134cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany if (end != map_end) 135cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany UnmapOrDie((void*)end, map_end - end); 136cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany return (void*)res; 137cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany} 138cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany 1392673fd8406197c42f16cede6d287f72169298c2eKostya Serebryanyvoid ReportErrorSummary(const char *error_type, const char *file, 1402673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany int line, const char *function) { 1412673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany const int kMaxSize = 1024; // We don't want a summary too long. 1422673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany InternalScopedBuffer<char> buff(kMaxSize); 1432f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany internal_snprintf(buff.data(), kMaxSize, "%s: %s %s:%d %s", 1442673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany SanitizerToolName, error_type, 1451d333c5a34d896f239001e3fe69a660e40d15301Kostya Serebryany file ? file : "??", line, function ? function : "??"); 1462673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany __sanitizer_report_error_summary(buff.data()); 1472673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany} 1482673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany 149230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov} // namespace __sanitizer 15081dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany 151ac8564e7ce11e31b1d29e92dbbcfa1a5d36bc596Alexey Samsonovusing namespace __sanitizer; // NOLINT 152ac8564e7ce11e31b1d29e92dbbcfa1a5d36bc596Alexey Samsonov 153ac8564e7ce11e31b1d29e92dbbcfa1a5d36bc596Alexey Samsonovextern "C" { 15481dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryanyvoid __sanitizer_set_report_path(const char *path) { 15581dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany if (!path) return; 15681dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany uptr len = internal_strlen(path); 157dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko if (len > sizeof(report_path_prefix) - 100) { 15881dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", 15981dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany path[0], path[1], path[2], path[3], 16081dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany path[4], path[5], path[6], path[7]); 16181dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany Die(); 16281dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany } 163dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko internal_strncpy(report_path_prefix, path, sizeof(report_path_prefix)); 164dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko report_path_prefix[len] = '\0'; 165f3457cb9c3e1ddbbea07ee97b22ca387687b72e0Alexey Samsonov report_fd = kInvalidFd; 166dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko log_to_file = true; 16781dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany} 168ac8564e7ce11e31b1d29e92dbbcfa1a5d36bc596Alexey Samsonov 169ac8564e7ce11e31b1d29e92dbbcfa1a5d36bc596Alexey Samsonovvoid __sanitizer_set_report_fd(int fd) { 170f3457cb9c3e1ddbbea07ee97b22ca387687b72e0Alexey Samsonov if (report_fd != kStdoutFd && 171f3457cb9c3e1ddbbea07ee97b22ca387687b72e0Alexey Samsonov report_fd != kStderrFd && 172f3457cb9c3e1ddbbea07ee97b22ca387687b72e0Alexey Samsonov report_fd != kInvalidFd) 173f3457cb9c3e1ddbbea07ee97b22ca387687b72e0Alexey Samsonov internal_close(report_fd); 174f3457cb9c3e1ddbbea07ee97b22ca387687b72e0Alexey Samsonov report_fd = fd; 175ac8564e7ce11e31b1d29e92dbbcfa1a5d36bc596Alexey Samsonov} 17625742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko 17725742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenkovoid NOINLINE __sanitizer_sandbox_on_notify(void *reserved) { 17825742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko (void)reserved; 17925742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko PrepareForSandboxing(); 18025742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko} 1812673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany 1822673fd8406197c42f16cede6d287f72169298c2eKostya Serebryanyvoid __sanitizer_report_error_summary(const char *error_summary) { 1832673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany Printf("SUMMARY: %s\n", error_summary); 1842673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany} 185ac8564e7ce11e31b1d29e92dbbcfa1a5d36bc596Alexey Samsonov} // extern "C" 186