tsan_symbolize.cc revision c1a1ed62228288155459d39194995a36aca4a8a6
1caee0dccffb77a003681345ab3281bcf8684526cChris Lattner//===-- tsan_symbolize.cc -------------------------------------------------===//
2caee0dccffb77a003681345ab3281bcf8684526cChris Lattner//
3caee0dccffb77a003681345ab3281bcf8684526cChris Lattner//                     The LLVM Compiler Infrastructure
4caee0dccffb77a003681345ab3281bcf8684526cChris Lattner//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
7caee0dccffb77a003681345ab3281bcf8684526cChris Lattner//
8caee0dccffb77a003681345ab3281bcf8684526cChris Lattner//===----------------------------------------------------------------------===//
9caee0dccffb77a003681345ab3281bcf8684526cChris Lattner//
10caee0dccffb77a003681345ab3281bcf8684526cChris Lattner// This file is a part of ThreadSanitizer (TSan), a race detector.
11caee0dccffb77a003681345ab3281bcf8684526cChris Lattner//
12caee0dccffb77a003681345ab3281bcf8684526cChris Lattner//===----------------------------------------------------------------------===//
13caee0dccffb77a003681345ab3281bcf8684526cChris Lattner
14caee0dccffb77a003681345ab3281bcf8684526cChris Lattner#include "tsan_symbolize.h"
15caee0dccffb77a003681345ab3281bcf8684526cChris Lattner
16caee0dccffb77a003681345ab3281bcf8684526cChris Lattner#include "sanitizer_common/sanitizer_common.h"
17caee0dccffb77a003681345ab3281bcf8684526cChris Lattner#include "sanitizer_common/sanitizer_placement_new.h"
18eaf42abab6d465c38891345d999255871cf03943Devang Patel#include "sanitizer_common/sanitizer_symbolizer.h"
19522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner#include "tsan_flags.h"
20efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif#include "tsan_report.h"
2148f848716e80d01619b239111db48bfac77baad1Chris Lattner#include "tsan_rtl.h"
2247f96bf24687b5068aec7166cb8b3ac33ae964aeChris Lattner
2348f848716e80d01619b239111db48bfac77baad1Chris Lattnernamespace __tsan {
24caee0dccffb77a003681345ab3281bcf8684526cChris Lattner
25caee0dccffb77a003681345ab3281bcf8684526cChris Lattnerstruct ScopedInSymbolizer {
26caee0dccffb77a003681345ab3281bcf8684526cChris Lattner  ScopedInSymbolizer() {
27c453f76e2b4d7fd1e042b5b6d4c20556779186dfChris Lattner    ThreadState *thr = cur_thread();
28522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner    CHECK(!thr->in_symbolizer);
29efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif    thr->in_symbolizer = true;
30efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  }
31efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif
32efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  ~ScopedInSymbolizer() {
33522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner    ThreadState *thr = cur_thread();
34efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif    CHECK(thr->in_symbolizer);
35ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner    thr->in_symbolizer = false;
36ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner  }
37ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner};
38ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner
39ea693dfab48ee6fc07cc21abc20f487df5057a6bChris LattnerReportStack *NewReportStackEntry(uptr addr) {
40ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner  ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack,
41ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner                                                  sizeof(ReportStack));
42ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner  internal_memset(ent, 0, sizeof(*ent));
43ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner  ent->pc = addr;
44ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner  return ent;
45522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner}
46efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif
47efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif// Strip module path to make output shorter.
48ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattnerstatic char *StripModuleName(const char *module) {
49ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner  if (module == 0)
50ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner    return 0;
51efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  const char *short_module_name = internal_strrchr(module, '/');
52efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  if (short_module_name)
53efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif    short_module_name += 1;
54efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  else
55522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner    short_module_name = module;
56522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner  return internal_strdup(short_module_name);
57efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif}
58522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner
59efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greifstatic ReportStack *NewReportStackEntry(const AddressInfo &info) {
60efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  ReportStack *ent = NewReportStackEntry(info.address);
61efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  ent->module = StripModuleName(info.module);
62efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  ent->offset = info.module_offset;
63522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner  if (info.function)
64522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner    ent->func = internal_strdup(info.function);
65b348bb81253a1105d23ab1a1771f8d2a6546aa1bChris Lattner  if (info.file)
66ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner    ent->file = internal_strdup(info.file);
67efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  ent->line = info.line;
68efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  ent->col = info.column;
69b348bb81253a1105d23ab1a1771f8d2a6546aa1bChris Lattner  return ent;
70b348bb81253a1105d23ab1a1771f8d2a6546aa1bChris Lattner}
71522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner
72522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner
73efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  ReportStack *next;
74efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  char *module;
75522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner  uptr offset;
76198f34ac359c48018c6e1f784cf3770ead63b253Chris Lattner  uptr pc;
77980e5aad4cfaa32e13b297f4201eb1088ca96cc4Chris Lattner  char *func;
78efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  char *file;
79efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  int line;
80198f34ac359c48018c6e1f784cf3770ead63b253Chris Lattner  int col;
81522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner
82522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner
83522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner// Denotes fake PC values that come from JIT/JAVA/etc.
84a7c49aac984fafa5dfdfcc2762d4d51b26788e38Chris Lattner// For such PC values __tsan_symbolize_external() will be called.
85a7c49aac984fafa5dfdfcc2762d4d51b26788e38Chris Lattnerconst uptr kExternalPCBit = 1ULL << 60;
86a7c49aac984fafa5dfdfcc2762d4d51b26788e38Chris Lattner
87a7c49aac984fafa5dfdfcc2762d4d51b26788e38Chris Lattner// May be overriden by JIT/JAVA/etc,
88a7c49aac984fafa5dfdfcc2762d4d51b26788e38Chris Lattner// whatever produces PCs marked with kExternalPCBit.
89a7c49aac984fafa5dfdfcc2762d4d51b26788e38Chris Lattnerextern "C" bool __tsan_symbolize_external(uptr pc,
90ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner                               char *func_buf, uptr func_siz,
91ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner                               char *file_buf, uptr file_siz,
92ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner                               int *line, int *col)
93ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner                               SANITIZER_WEAK_ATTRIBUTE;
94ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner
95ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattnerbool __tsan_symbolize_external(uptr pc,
96ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner                               char *func_buf, uptr func_siz,
97ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner                               char *file_buf, uptr file_siz,
98ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner                               int *line, int *col) {
99ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner  return false;
100ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner}
101a7c49aac984fafa5dfdfcc2762d4d51b26788e38Chris Lattner
102a7c49aac984fafa5dfdfcc2762d4d51b26788e38Chris LattnerReportStack *SymbolizeCode(uptr addr) {
103a7c49aac984fafa5dfdfcc2762d4d51b26788e38Chris Lattner  // Check if PC comes from non-native land.
104a7c49aac984fafa5dfdfcc2762d4d51b26788e38Chris Lattner  if (addr & kExternalPCBit) {
105a7c49aac984fafa5dfdfcc2762d4d51b26788e38Chris Lattner    // Declare static to not consume too much stack space.
106ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner    // We symbolize reports in a single thread, so this is fine.
107ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner    static char func_buf[1024];
108ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner    static char file_buf[1024];
109ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner    int line, col;
110a7c49aac984fafa5dfdfcc2762d4d51b26788e38Chris Lattner    if (!__tsan_symbolize_external(addr, func_buf, sizeof(func_buf),
111522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner                                  file_buf, sizeof(file_buf), &line, &col))
112efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif      return NewReportStackEntry(addr);
113efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif    ReportStack *ent = NewReportStackEntry(addr);
114efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif    ent->module = 0;
115efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif    ent->offset = 0;
116efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif    ent->func = internal_strdup(func_buf);
1176c80c381601b17207b6b8f898cfe273a37584d52Gabor Greif    ent->file = internal_strdup(file_buf);
118522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner    ent->line = line;
119522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner    ent->col = col;
120efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif    return ent;
121efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  }
122ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner  if (!Symbolizer::Get()->IsAvailable())
123ea693dfab48ee6fc07cc21abc20f487df5057a6bChris Lattner    return SymbolizeCodeAddr2Line(addr);
124efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  ScopedInSymbolizer in_symbolizer;
125efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  static const uptr kMaxAddrFrames = 16;
126efe65369a74871c3140a540a6c95ce5d1f080954Gabor Greif  InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
127caee0dccffb77a003681345ab3281bcf8684526cChris Lattner  for (uptr i = 0; i < kMaxAddrFrames; i++)
128caee0dccffb77a003681345ab3281bcf8684526cChris Lattner    new(&addr_frames[i]) AddressInfo();
129c453f76e2b4d7fd1e042b5b6d4c20556779186dfChris Lattner  uptr addr_frames_num = Symbolizer::Get()->SymbolizeCode(
13048f848716e80d01619b239111db48bfac77baad1Chris Lattner      addr, addr_frames.data(), kMaxAddrFrames);
13148f848716e80d01619b239111db48bfac77baad1Chris Lattner  if (addr_frames_num == 0)
132caee0dccffb77a003681345ab3281bcf8684526cChris Lattner    return NewReportStackEntry(addr);
133caee0dccffb77a003681345ab3281bcf8684526cChris Lattner  ReportStack *top = 0;
134caee0dccffb77a003681345ab3281bcf8684526cChris Lattner  ReportStack *bottom = 0;
135522b7b104c864da81c19d8b16c43b7a1f6a2fc40Chris Lattner  for (uptr i = 0; i < addr_frames_num; i++) {
136e16504eb4ef8f09611cdf6e9a0be9eb886b4ed89Chris Lattner    ReportStack *cur_entry = NewReportStackEntry(addr_frames[i]);
13707d98b4afbdcbb4eed048400d9116de1ec83e866Chris Lattner    CHECK(cur_entry);
13848f848716e80d01619b239111db48bfac77baad1Chris Lattner    addr_frames[i].Clear();
13919c874638d9478a5d5028854817a5ee72293bb2bDevang Patel    if (i == 0)
14048c85b84c1b66fb6a1b0d2afddf33da5bd82960dChris Lattner      top = cur_entry;
14148c85b84c1b66fb6a1b0d2afddf33da5bd82960dChris Lattner    else
14219c874638d9478a5d5028854817a5ee72293bb2bDevang Patel      bottom->next = cur_entry;
14348c85b84c1b66fb6a1b0d2afddf33da5bd82960dChris Lattner    bottom = cur_entry;
144980e5aad4cfaa32e13b297f4201eb1088ca96cc4Chris Lattner  }
145980e5aad4cfaa32e13b297f4201eb1088ca96cc4Chris Lattner  return top;
146980e5aad4cfaa32e13b297f4201eb1088ca96cc4Chris Lattner}
147980e5aad4cfaa32e13b297f4201eb1088ca96cc4Chris Lattner
14848f848716e80d01619b239111db48bfac77baad1Chris LattnerReportLocation *SymbolizeData(uptr addr) {
14948f848716e80d01619b239111db48bfac77baad1Chris Lattner  if (!Symbolizer::Get()->IsAvailable())
15048f848716e80d01619b239111db48bfac77baad1Chris Lattner    return 0;
1516994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  ScopedInSymbolizer in_symbolizer;
1526994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  DataInfo info;
1536994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  if (!Symbolizer::Get()->SymbolizeData(addr, &info))
1546994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    return 0;
1556994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  ReportLocation *ent = (ReportLocation*)internal_alloc(MBlockReportStack,
15648f848716e80d01619b239111db48bfac77baad1Chris Lattner                                                        sizeof(ReportLocation));
15748f848716e80d01619b239111db48bfac77baad1Chris Lattner  internal_memset(ent, 0, sizeof(*ent));
15848f848716e80d01619b239111db48bfac77baad1Chris Lattner  ent->type = ReportLocationGlobal;
15948f848716e80d01619b239111db48bfac77baad1Chris Lattner  ent->module = StripModuleName(info.module);
16048f848716e80d01619b239111db48bfac77baad1Chris Lattner  ent->offset = info.module_offset;
16148f848716e80d01619b239111db48bfac77baad1Chris Lattner  if (info.name)
16248f848716e80d01619b239111db48bfac77baad1Chris Lattner    ent->name = internal_strdup(info.name);
16348f848716e80d01619b239111db48bfac77baad1Chris Lattner  ent->addr = info.start;
16448f848716e80d01619b239111db48bfac77baad1Chris Lattner  ent->size = info.size;
165caee0dccffb77a003681345ab3281bcf8684526cChris Lattner  return ent;
166950a4c40b823cd4f09dc71be635229246dfd6cacDan Gohman}
167950a4c40b823cd4f09dc71be635229246dfd6cacDan Gohman
16848f848716e80d01619b239111db48bfac77baad1Chris Lattnervoid SymbolizeFlush() {
16948f848716e80d01619b239111db48bfac77baad1Chris Lattner  if (!Symbolizer::Get()->IsAvailable())
170b348bb81253a1105d23ab1a1771f8d2a6546aa1bChris Lattner    return;
171b348bb81253a1105d23ab1a1771f8d2a6546aa1bChris Lattner  ScopedInSymbolizer in_symbolizer;
172b348bb81253a1105d23ab1a1771f8d2a6546aa1bChris Lattner  Symbolizer::Get()->Flush();
173caee0dccffb77a003681345ab3281bcf8684526cChris Lattner}
174b348bb81253a1105d23ab1a1771f8d2a6546aa1bChris Lattner
175c453f76e2b4d7fd1e042b5b6d4c20556779186dfChris Lattner}  // namespace __tsan
176c453f76e2b4d7fd1e042b5b6d4c20556779186dfChris Lattner