1bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov//===-- tsan_symbolize.cc -------------------------------------------------===// 2bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov// 3bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov// The LLVM Compiler Infrastructure 4bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov// 5bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov// This file is distributed under the University of Illinois Open Source 6bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov// License. See LICENSE.TXT for details. 7bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov// 8bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov//===----------------------------------------------------------------------===// 9bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov// 10bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov// This file is a part of ThreadSanitizer (TSan), a race detector. 11bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov// 12bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov//===----------------------------------------------------------------------===// 13bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov 14bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov#include "tsan_symbolize.h" 15bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov 16bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov#include "sanitizer_common/sanitizer_common.h" 17bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov#include "sanitizer_common/sanitizer_placement_new.h" 18bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov#include "sanitizer_common/sanitizer_symbolizer.h" 19bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov#include "tsan_flags.h" 20bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov#include "tsan_report.h" 214e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov#include "tsan_rtl.h" 22bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov 23bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonovnamespace __tsan { 24bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov 2566d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonovvoid EnterSymbolizer() { 2666d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov ThreadState *thr = cur_thread(); 2766d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov CHECK(!thr->in_symbolizer); 2866d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov thr->in_symbolizer = true; 292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->ignore_interceptors++; 3066d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov} 314e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov 3266d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonovvoid ExitSymbolizer() { 3366d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov ThreadState *thr = cur_thread(); 3466d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov CHECK(thr->in_symbolizer); 3566d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov thr->in_symbolizer = false; 362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->ignore_interceptors--; 3766d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov} 384e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov 39bc12f5d836b161b881de91e29548cfbc014243a3Alexey SamsonovReportStack *NewReportStackEntry(uptr addr) { 40bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack, 41bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov sizeof(ReportStack)); 42bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov internal_memset(ent, 0, sizeof(*ent)); 43bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ent->pc = addr; 44bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov return ent; 45bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov} 46bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov 47bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonovstatic ReportStack *NewReportStackEntry(const AddressInfo &info) { 48bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ReportStack *ent = NewReportStackEntry(info.address); 495a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->module = StripModuleName(info.module); 50bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ent->offset = info.module_offset; 515a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov if (info.function) 52bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ent->func = internal_strdup(info.function); 53bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov if (info.file) 54bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ent->file = internal_strdup(info.file); 55bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ent->line = info.line; 56bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ent->col = info.column; 57bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov return ent; 58bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov} 59bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov 602d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov 612d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov ReportStack *next; 622d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov char *module; 632d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov uptr offset; 642d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov uptr pc; 652d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov char *func; 662d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov char *file; 672d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov int line; 682d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov int col; 692d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov 702d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov 712d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov// Denotes fake PC values that come from JIT/JAVA/etc. 722d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov// For such PC values __tsan_symbolize_external() will be called. 732d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukovconst uptr kExternalPCBit = 1ULL << 60; 742d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov 752d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov// May be overriden by JIT/JAVA/etc, 762d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov// whatever produces PCs marked with kExternalPCBit. 772d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukovextern "C" bool __tsan_symbolize_external(uptr pc, 782d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov char *func_buf, uptr func_siz, 792d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov char *file_buf, uptr file_siz, 802d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov int *line, int *col) 812d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov SANITIZER_WEAK_ATTRIBUTE; 822d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov 832d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukovbool __tsan_symbolize_external(uptr pc, 842d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov char *func_buf, uptr func_siz, 852d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov char *file_buf, uptr file_siz, 862d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov int *line, int *col) { 872d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov return false; 882d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov} 892d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov 90bc12f5d836b161b881de91e29548cfbc014243a3Alexey SamsonovReportStack *SymbolizeCode(uptr addr) { 912d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov // Check if PC comes from non-native land. 922d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov if (addr & kExternalPCBit) { 932d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov // Declare static to not consume too much stack space. 942d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov // We symbolize reports in a single thread, so this is fine. 952d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov static char func_buf[1024]; 962d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov static char file_buf[1024]; 972d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov int line, col; 982d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov if (!__tsan_symbolize_external(addr, func_buf, sizeof(func_buf), 992d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov file_buf, sizeof(file_buf), &line, &col)) 1002d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov return NewReportStackEntry(addr); 1012d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov ReportStack *ent = NewReportStackEntry(addr); 1022d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov ent->module = 0; 1032d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov ent->offset = 0; 1042d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov ent->func = internal_strdup(func_buf); 1052d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov ent->file = internal_strdup(file_buf); 1062d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov ent->line = line; 1072d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov ent->col = col; 1082d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov return ent; 1092d2dc4606e66974a69fb53a66f5b1e5501523686Dmitry Vyukov } 11090a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov static const uptr kMaxAddrFrames = 16; 11190a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames); 11290a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov for (uptr i = 0; i < kMaxAddrFrames; i++) 11390a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov new(&addr_frames[i]) AddressInfo(); 1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr addr_frames_num = Symbolizer::Get()->SymbolizePC( 115c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne addr, addr_frames.data(), kMaxAddrFrames); 11690a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov if (addr_frames_num == 0) 11790a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov return NewReportStackEntry(addr); 11890a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov ReportStack *top = 0; 11990a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov ReportStack *bottom = 0; 12090a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov for (uptr i = 0; i < addr_frames_num; i++) { 12190a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov ReportStack *cur_entry = NewReportStackEntry(addr_frames[i]); 12290a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov CHECK(cur_entry); 12390a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov addr_frames[i].Clear(); 12490a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov if (i == 0) 12590a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov top = cur_entry; 12690a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov else 12790a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov bottom->next = cur_entry; 12890a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov bottom = cur_entry; 129bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov } 13090a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov return top; 131bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov} 132bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov 1335a1f23310cc4a1debae8741653defe620518e612Dmitry VyukovReportLocation *SymbolizeData(uptr addr) { 1345a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov DataInfo info; 135c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne if (!Symbolizer::Get()->SymbolizeData(addr, &info)) 1365a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov return 0; 1375a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ReportLocation *ent = (ReportLocation*)internal_alloc(MBlockReportStack, 1385a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov sizeof(ReportLocation)); 1395a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov internal_memset(ent, 0, sizeof(*ent)); 1405a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->type = ReportLocationGlobal; 1415a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->module = StripModuleName(info.module); 1425a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->offset = info.module_offset; 1435a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov if (info.name) 1445a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->name = internal_strdup(info.name); 1455a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->addr = info.start; 1465a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->size = info.size; 1475a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov return ent; 148bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov} 149bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov 150723e24f768f5b32c38283ee8d2c4219267af2b4dDmitry Vyukovvoid SymbolizeFlush() { 151c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne Symbolizer::Get()->Flush(); 152723e24f768f5b32c38283ee8d2c4219267af2b4dDmitry Vyukov} 153723e24f768f5b32c38283ee8d2c4219267af2b4dDmitry Vyukov 154bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov} // namespace __tsan 155