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