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 254e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukovstruct ScopedInSymbolizer { 264e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov ScopedInSymbolizer() { 274e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov ThreadState *thr = cur_thread(); 284e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov CHECK(!thr->in_symbolizer); 294e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov thr->in_symbolizer = true; 304e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov } 314e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov 324e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov ~ScopedInSymbolizer() { 334e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov ThreadState *thr = cur_thread(); 344e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov CHECK(thr->in_symbolizer); 354e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov thr->in_symbolizer = false; 364e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov } 374e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov}; 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 475a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov// Strip module path to make output shorter. 485a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukovstatic char *StripModuleName(const char *module) { 495a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov if (module == 0) 505a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov return 0; 515a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov const char *short_module_name = internal_strrchr(module, '/'); 525a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov if (short_module_name) 535a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov short_module_name += 1; 545a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov else 555a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov short_module_name = module; 565a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov return internal_strdup(short_module_name); 575a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov} 585a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov 59bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonovstatic ReportStack *NewReportStackEntry(const AddressInfo &info) { 60bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ReportStack *ent = NewReportStackEntry(info.address); 615a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->module = StripModuleName(info.module); 62bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ent->offset = info.module_offset; 635a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov if (info.function) 64bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ent->func = internal_strdup(info.function); 65bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov if (info.file) 66bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ent->file = internal_strdup(info.file); 67bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ent->line = info.line; 68bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov ent->col = info.column; 69bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov return ent; 70bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov} 71bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov 72bc12f5d836b161b881de91e29548cfbc014243a3Alexey SamsonovReportStack *SymbolizeCode(uptr addr) { 7390a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov if (!IsSymbolizerAvailable()) 7490a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov return SymbolizeCodeAddr2Line(addr); 754e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov ScopedInSymbolizer in_symbolizer; 7690a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov static const uptr kMaxAddrFrames = 16; 7790a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames); 7890a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov for (uptr i = 0; i < kMaxAddrFrames; i++) 7990a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov new(&addr_frames[i]) AddressInfo(); 8090a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov uptr addr_frames_num = __sanitizer::SymbolizeCode(addr, addr_frames.data(), 8190a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov kMaxAddrFrames); 8290a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov if (addr_frames_num == 0) 8390a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov return NewReportStackEntry(addr); 8490a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov ReportStack *top = 0; 8590a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov ReportStack *bottom = 0; 8690a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov for (uptr i = 0; i < addr_frames_num; i++) { 8790a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov ReportStack *cur_entry = NewReportStackEntry(addr_frames[i]); 8890a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov CHECK(cur_entry); 8990a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov addr_frames[i].Clear(); 9090a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov if (i == 0) 9190a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov top = cur_entry; 9290a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov else 9390a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov bottom->next = cur_entry; 9490a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov bottom = cur_entry; 95bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov } 9690a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov return top; 97bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov} 98bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov 995a1f23310cc4a1debae8741653defe620518e612Dmitry VyukovReportLocation *SymbolizeData(uptr addr) { 10090a2467c0a0722dcc9443229b8805f0a878ccb56Dmitry Vyukov if (!IsSymbolizerAvailable()) 1015a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov return 0; 1024e81d0e82a4a327987644a57b6103052a974824fDmitry Vyukov ScopedInSymbolizer in_symbolizer; 1035a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov DataInfo info; 1045a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov if (!__sanitizer::SymbolizeData(addr, &info)) 1055a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov return 0; 1065a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ReportLocation *ent = (ReportLocation*)internal_alloc(MBlockReportStack, 1075a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov sizeof(ReportLocation)); 1085a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov internal_memset(ent, 0, sizeof(*ent)); 1095a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->type = ReportLocationGlobal; 1105a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->module = StripModuleName(info.module); 1115a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->offset = info.module_offset; 1125a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov if (info.name) 1135a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->name = internal_strdup(info.name); 1145a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->addr = info.start; 1155a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov ent->size = info.size; 1165a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov return ent; 117bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov} 118bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov 119bc12f5d836b161b881de91e29548cfbc014243a3Alexey Samsonov} // namespace __tsan 120