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" 1590b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov#include "sanitizer_flags.h" 16230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov#include "sanitizer_libc.h" 172fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov#include "sanitizer_stacktrace.h" 182fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov#include "sanitizer_symbolizer.h" 194c49666e611f06241bb8462cea7674d877241492Alexey Samsonov 20230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonovnamespace __sanitizer { 21230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov 22859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryanyconst char *SanitizerToolName = "SanitizerTool"; 23859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany 24f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryanyuptr GetPageSizeCached() { 25f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany static uptr PageSize; 26f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany if (!PageSize) 27f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany PageSize = GetPageSize(); 28f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany return PageSize; 29f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany} 30f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany 31dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko 32dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko// By default, dump to stderr. If |log_to_file| is true and |report_fd_pid| 33dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko// isn't equal to the current PID, try to obtain file descriptor by opening 34dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko// file "report_path_prefix.<PID>". 350c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbournefd_t report_fd = kStderrFd; 36923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckner 37923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckner// Set via __sanitizer_set_report_path. 38923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Klecknerbool log_to_file = false; 39923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Klecknerchar report_path_prefix[sizeof(report_path_prefix)]; 40923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckner 41dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko// PID of process that opened |report_fd|. If a fork() occurs, the PID of the 42dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko// child thread will be different from |report_fd_pid|. 43923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckneruptr report_fd_pid = 0; 4481dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany 452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// PID of the tracer task in StopTheWorld. It shares the address space with the 462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// main process, but has a different PID and thus requires special handling. 472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr stoptheworld_tracer_pid = 0; 482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Cached pid of parent process - if the parent process dies, we want to keep 492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// writing to the same log file. 502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr stoptheworld_tracer_ppid = 0; 512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 5290629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveevstatic DieCallbackType DieCallback; 5390629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveevvoid SetDieCallback(DieCallbackType callback) { 54591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov DieCallback = callback; 55591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov} 56591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 5790629fb8072efc95e46a0cbc641293511fbaba2eSergey MatveevDieCallbackType GetDieCallback() { 5890629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev return DieCallback; 5990629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev} 6090629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev 61591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid NORETURN Die() { 62591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov if (DieCallback) { 63591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov DieCallback(); 64591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov } 65f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov internal__exit(1); 66591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov} 67591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 68591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovstatic CheckFailedCallbackType CheckFailedCallback; 69591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid SetCheckFailedCallback(CheckFailedCallbackType callback) { 70591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov CheckFailedCallback = callback; 71591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov} 72591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 73591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid NORETURN CheckFailed(const char *file, int line, const char *cond, 74591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov u64 v1, u64 v2) { 75591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov if (CheckFailedCallback) { 76591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov CheckFailedCallback(file, line, cond, v1, v2); 77591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov } 78e3c35c7e30ce24b76f1e67eb049cf9e84c9b89d8Dmitry Vyukov Report("Sanitizer CHECK failed: %s:%d %s (%lld, %lld)\n", file, line, cond, 79e3c35c7e30ce24b76f1e67eb049cf9e84c9b89d8Dmitry Vyukov v1, v2); 80591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov Die(); 81591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov} 82591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 83cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonovuptr ReadFileToBuffer(const char *file_name, char **buff, 84cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov uptr *buff_size, uptr max_len) { 85f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany uptr PageSize = GetPageSizeCached(); 86f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany uptr kMinFileLen = PageSize; 87cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov uptr read_len = 0; 88cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov *buff = 0; 89cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov *buff_size = 0; 90cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov // The files we usually open are not seekable, so try different buffer sizes. 91cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov for (uptr size = kMinFileLen; size <= max_len; size *= 2) { 929578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne uptr openrv = OpenFile(file_name, /*write*/ false); 939578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne if (internal_iserror(openrv)) return 0; 949578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne fd_t fd = openrv; 95cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov UnmapOrDie(*buff, *buff_size); 962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines *buff = (char*)MmapOrDie(size, __func__); 97cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov *buff_size = size; 98cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov // Read up to one page at a time. 99cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov read_len = 0; 100cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov bool reached_eof = false; 101f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany while (read_len + PageSize <= size) { 102f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany uptr just_read = internal_read(fd, *buff + read_len, PageSize); 103cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov if (just_read == 0) { 104cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov reached_eof = true; 105cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov break; 106cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov } 107cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov read_len += just_read; 108cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov } 109cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov internal_close(fd); 110cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov if (reached_eof) // We've read the whole file. 111cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov break; 112cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov } 113cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov return read_len; 114cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov} 115cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov 11615bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveevtypedef bool UptrComparisonFunction(const uptr &a, const uptr &b); 11715bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev 11815bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveevtemplate<class T> 11915bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveevstatic inline bool CompareLess(const T &a, const T &b) { 12015bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev return a < b; 12115bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev} 12215bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev 1234c49666e611f06241bb8462cea7674d877241492Alexey Samsonovvoid SortArray(uptr *array, uptr size) { 12415bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev InternalSort<uptr*, UptrComparisonFunction>(&array, size, CompareLess); 1254c49666e611f06241bb8462cea7674d877241492Alexey Samsonov} 1264c49666e611f06241bb8462cea7674d877241492Alexey Samsonov 127cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany// We want to map a chunk of address space aligned to 'alignment'. 128cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany// We do it by maping a bit more and then unmaping redundant pieces. 129cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany// We probably can do it with fewer syscalls in some OS-dependent way. 130cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryanyvoid *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type) { 1312dae63aea3589fded1ef17b5a6c7f0c9352559a2Bill Wendling// uptr PageSize = GetPageSizeCached(); 132cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany CHECK(IsPowerOfTwo(size)); 133cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany CHECK(IsPowerOfTwo(alignment)); 134cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany uptr map_size = size + alignment; 135cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany uptr map_res = (uptr)MmapOrDie(map_size, mem_type); 136cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany uptr map_end = map_res + map_size; 137cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany uptr res = map_res; 138cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany if (res & (alignment - 1)) // Not aligned. 1393617ad70f3ade71b944b35fa3faaadfb97700deaDmitry Vyukov res = (map_res + alignment) & ~(alignment - 1); 140cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany uptr end = res + size; 141cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany if (res != map_res) 142cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany UnmapOrDie((void*)map_res, res - map_res); 143cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany if (end != map_end) 144cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany UnmapOrDie((void*)end, map_end - end); 145cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany return (void*)res; 146cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany} 147cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany 14890b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonovconst char *StripPathPrefix(const char *filepath, 14990b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov const char *strip_path_prefix) { 15090b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov if (filepath == 0) return 0; 15190b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov if (strip_path_prefix == 0) return filepath; 15290b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov const char *pos = internal_strstr(filepath, strip_path_prefix); 15390b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov if (pos == 0) return filepath; 15490b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov pos += internal_strlen(strip_path_prefix); 15590b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov if (pos[0] == '.' && pos[1] == '/') 15690b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov pos += 2; 15790b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov return pos; 15890b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov} 15990b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov 160bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonovvoid PrintSourceLocation(InternalScopedString *buffer, const char *file, 161bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov int line, int column) { 16290b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov CHECK(file); 163bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov buffer->append("%s", 164bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov StripPathPrefix(file, common_flags()->strip_path_prefix)); 16590b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov if (line > 0) { 166bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov buffer->append(":%d", line); 16790b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov if (column > 0) 168bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov buffer->append(":%d", column); 16990b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov } 17090b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov} 17190b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov 172bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonovvoid PrintModuleAndOffset(InternalScopedString *buffer, const char *module, 173bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov uptr offset) { 174bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov buffer->append("(%s+0x%zx)", 175bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov StripPathPrefix(module, common_flags()->strip_path_prefix), 176bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov offset); 17790b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov} 17890b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov 1792fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonovvoid ReportErrorSummary(const char *error_message) { 180694d85636b148dfcac37e5c23639baa8fe9abce9Alexey Samsonov if (!common_flags()->print_summary) 181694d85636b148dfcac37e5c23639baa8fe9abce9Alexey Samsonov return; 1822fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov InternalScopedBuffer<char> buff(kMaxSummaryLength); 1832fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov internal_snprintf(buff.data(), buff.size(), 1842fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov "SUMMARY: %s: %s", SanitizerToolName, error_message); 1852fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov __sanitizer_report_error_summary(buff.data()); 1862fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov} 1872fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov 1882673fd8406197c42f16cede6d287f72169298c2eKostya Serebryanyvoid ReportErrorSummary(const char *error_type, const char *file, 1892673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany int line, const char *function) { 190694d85636b148dfcac37e5c23639baa8fe9abce9Alexey Samsonov if (!common_flags()->print_summary) 191694d85636b148dfcac37e5c23639baa8fe9abce9Alexey Samsonov return; 1922fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov InternalScopedBuffer<char> buff(kMaxSummaryLength); 19390b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov internal_snprintf( 1942fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov buff.data(), buff.size(), "%s %s:%d %s", error_type, 19590b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov file ? StripPathPrefix(file, common_flags()->strip_path_prefix) : "??", 19690b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov line, function ? function : "??"); 1972fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov ReportErrorSummary(buff.data()); 1982fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov} 1992fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov 2002fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonovvoid ReportErrorSummary(const char *error_type, StackTrace *stack) { 201694d85636b148dfcac37e5c23639baa8fe9abce9Alexey Samsonov if (!common_flags()->print_summary) 202694d85636b148dfcac37e5c23639baa8fe9abce9Alexey Samsonov return; 2032fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov AddressInfo ai; 20450cdc5a0d78f400183bd9dc7c23a2ed6e733e48bAlexey Samsonov#if !SANITIZER_GO 2052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (stack->size > 0 && Symbolizer::Get()->CanReturnFileLineInfo()) { 2062fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov // Currently, we include the first stack frame into the report summary. 2072fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc). 2082fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]); 2092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Symbolizer::Get()->SymbolizePC(pc, &ai, 1); 2102fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov } 21150cdc5a0d78f400183bd9dc7c23a2ed6e733e48bAlexey Samsonov#endif 2122fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov ReportErrorSummary(error_type, ai.file, ai.line, ai.function); 2132673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany} 2142673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany 2157847d77b246635211c3bf465421d49d7af5226c1Alexey SamsonovLoadedModule::LoadedModule(const char *module_name, uptr base_address) { 2167847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov full_name_ = internal_strdup(module_name); 2177847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov base_address_ = base_address; 2187847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov n_ranges_ = 0; 2197847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov} 2207847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 2215d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hinesvoid LoadedModule::addAddressRange(uptr beg, uptr end, bool executable) { 2227847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov CHECK_LT(n_ranges_, kMaxNumberOfAddressRanges); 2237847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov ranges_[n_ranges_].beg = beg; 2247847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov ranges_[n_ranges_].end = end; 2255d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines exec_[n_ranges_] = executable; 2267847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov n_ranges_++; 2277847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov} 2287847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 2297847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovbool LoadedModule::containsAddress(uptr address) const { 2307847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov for (uptr i = 0; i < n_ranges_; i++) { 2317847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov if (ranges_[i].beg <= address && address < ranges_[i].end) 2327847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov return true; 2337847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov } 2347847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov return false; 2357847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov} 2367847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 237dbd69cc9ccda50efd0305cd0ce9bad50defe4b42Bob Wilsonchar *StripModuleName(const char *module) { 238dbd69cc9ccda50efd0305cd0ce9bad50defe4b42Bob Wilson if (module == 0) 239dbd69cc9ccda50efd0305cd0ce9bad50defe4b42Bob Wilson return 0; 240dbd69cc9ccda50efd0305cd0ce9bad50defe4b42Bob Wilson const char *short_module_name = internal_strrchr(module, '/'); 241dbd69cc9ccda50efd0305cd0ce9bad50defe4b42Bob Wilson if (short_module_name) 242dbd69cc9ccda50efd0305cd0ce9bad50defe4b42Bob Wilson short_module_name += 1; 243dbd69cc9ccda50efd0305cd0ce9bad50defe4b42Bob Wilson else 244dbd69cc9ccda50efd0305cd0ce9bad50defe4b42Bob Wilson short_module_name = module; 245dbd69cc9ccda50efd0305cd0ce9bad50defe4b42Bob Wilson return internal_strdup(short_module_name); 246dbd69cc9ccda50efd0305cd0ce9bad50defe4b42Bob Wilson} 247dbd69cc9ccda50efd0305cd0ce9bad50defe4b42Bob Wilson 2482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic atomic_uintptr_t g_total_mmaped; 2492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid IncreaseTotalMmap(uptr size) { 2512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!common_flags()->mmap_limit_mb) return; 2522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr total_mmaped = 2532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines atomic_fetch_add(&g_total_mmaped, size, memory_order_relaxed) + size; 2542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if ((total_mmaped >> 20) > common_flags()->mmap_limit_mb) { 2552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Since for now mmap_limit_mb is not a user-facing flag, just CHECK. 2562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr mmap_limit_mb = common_flags()->mmap_limit_mb; 2572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines common_flags()->mmap_limit_mb = 0; // Allow mmap in CHECK. 2582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines RAW_CHECK(total_mmaped >> 20 < mmap_limit_mb); 2592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 2602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 2612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid DecreaseTotalMmap(uptr size) { 2632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!common_flags()->mmap_limit_mb) return; 2642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines atomic_fetch_sub(&g_total_mmaped, size, memory_order_relaxed); 2652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 2662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 267230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov} // namespace __sanitizer 26881dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany 269ac8564e7ce11e31b1d29e92dbbcfa1a5d36bc596Alexey Samsonovusing namespace __sanitizer; // NOLINT 270ac8564e7ce11e31b1d29e92dbbcfa1a5d36bc596Alexey Samsonov 271ac8564e7ce11e31b1d29e92dbbcfa1a5d36bc596Alexey Samsonovextern "C" { 27281dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryanyvoid __sanitizer_set_report_path(const char *path) { 273b48c2b2072c8cc17dc1579a6b20ce6c2a575821dDmitry Vyukov if (!path) 274b48c2b2072c8cc17dc1579a6b20ce6c2a575821dDmitry Vyukov return; 27581dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany uptr len = internal_strlen(path); 276dedba5d6b0664218b1b1109f024a1ab151642776Alexander Potapenko if (len > sizeof(report_path_prefix) - 100) { 27781dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", 27881dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany path[0], path[1], path[2], path[3], 27981dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany path[4], path[5], path[6], path[7]); 28081dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany Die(); 28181dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany } 282f3457cb9c3e1ddbbea07ee97b22ca387687b72e0Alexey Samsonov if (report_fd != kStdoutFd && 283f3457cb9c3e1ddbbea07ee97b22ca387687b72e0Alexey Samsonov report_fd != kStderrFd && 284f3457cb9c3e1ddbbea07ee97b22ca387687b72e0Alexey Samsonov report_fd != kInvalidFd) 285f3457cb9c3e1ddbbea07ee97b22ca387687b72e0Alexey Samsonov internal_close(report_fd); 286b48c2b2072c8cc17dc1579a6b20ce6c2a575821dDmitry Vyukov report_fd = kInvalidFd; 287b48c2b2072c8cc17dc1579a6b20ce6c2a575821dDmitry Vyukov log_to_file = false; 288b48c2b2072c8cc17dc1579a6b20ce6c2a575821dDmitry Vyukov if (internal_strcmp(path, "stdout") == 0) { 289b48c2b2072c8cc17dc1579a6b20ce6c2a575821dDmitry Vyukov report_fd = kStdoutFd; 290b48c2b2072c8cc17dc1579a6b20ce6c2a575821dDmitry Vyukov } else if (internal_strcmp(path, "stderr") == 0) { 291b48c2b2072c8cc17dc1579a6b20ce6c2a575821dDmitry Vyukov report_fd = kStderrFd; 292b48c2b2072c8cc17dc1579a6b20ce6c2a575821dDmitry Vyukov } else { 293b48c2b2072c8cc17dc1579a6b20ce6c2a575821dDmitry Vyukov internal_strncpy(report_path_prefix, path, sizeof(report_path_prefix)); 294b48c2b2072c8cc17dc1579a6b20ce6c2a575821dDmitry Vyukov report_path_prefix[len] = '\0'; 295b48c2b2072c8cc17dc1579a6b20ce6c2a575821dDmitry Vyukov log_to_file = true; 296b48c2b2072c8cc17dc1579a6b20ce6c2a575821dDmitry Vyukov } 297ac8564e7ce11e31b1d29e92dbbcfa1a5d36bc596Alexey Samsonov} 29825742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko 2992673fd8406197c42f16cede6d287f72169298c2eKostya Serebryanyvoid __sanitizer_report_error_summary(const char *error_summary) { 30047fcd76474fc6b6c963ae4eeeeea15d465bd6a3cNick Lewycky Printf("%s\n", error_summary); 3012673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany} 302ac8564e7ce11e31b1d29e92dbbcfa1a5d36bc596Alexey Samsonov} // extern "C" 303