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