1//===-- sanitizer_symbolizer.cc -------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is shared between AddressSanitizer and ThreadSanitizer
11// run-time libraries.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_allocator_internal.h"
15#include "sanitizer_platform.h"
16#include "sanitizer_internal_defs.h"
17#include "sanitizer_libc.h"
18#include "sanitizer_placement_new.h"
19#include "sanitizer_symbolizer_internal.h"
20
21namespace __sanitizer {
22
23AddressInfo::AddressInfo() {
24  internal_memset(this, 0, sizeof(AddressInfo));
25  function_offset = kUnknown;
26}
27
28void AddressInfo::Clear() {
29  InternalFree(module);
30  InternalFree(function);
31  InternalFree(file);
32  internal_memset(this, 0, sizeof(AddressInfo));
33  function_offset = kUnknown;
34}
35
36void AddressInfo::FillModuleInfo(const char *mod_name, uptr mod_offset) {
37  module = internal_strdup(mod_name);
38  module_offset = mod_offset;
39}
40
41SymbolizedStack::SymbolizedStack() : next(nullptr), info() {}
42
43SymbolizedStack *SymbolizedStack::New(uptr addr) {
44  void *mem = InternalAlloc(sizeof(SymbolizedStack));
45  SymbolizedStack *res = new(mem) SymbolizedStack();
46  res->info.address = addr;
47  return res;
48}
49
50void SymbolizedStack::ClearAll() {
51  info.Clear();
52  if (next)
53    next->ClearAll();
54  InternalFree(this);
55}
56
57DataInfo::DataInfo() {
58  internal_memset(this, 0, sizeof(DataInfo));
59}
60
61void DataInfo::Clear() {
62  InternalFree(module);
63  InternalFree(name);
64  internal_memset(this, 0, sizeof(DataInfo));
65}
66
67Symbolizer *Symbolizer::symbolizer_;
68StaticSpinMutex Symbolizer::init_mu_;
69LowLevelAllocator Symbolizer::symbolizer_allocator_;
70
71void Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook,
72                          Symbolizer::EndSymbolizationHook end_hook) {
73  CHECK(start_hook_ == 0 && end_hook_ == 0);
74  start_hook_ = start_hook;
75  end_hook_ = end_hook;
76}
77
78const char *Symbolizer::ModuleNameOwner::GetOwnedCopy(const char *str) {
79  mu_->CheckLocked();
80
81  // 'str' will be the same string multiple times in a row, optimize this case.
82  if (last_match_ && !internal_strcmp(last_match_, str))
83    return last_match_;
84
85  // FIXME: this is linear search.
86  // We should optimize this further if this turns out to be a bottleneck later.
87  for (uptr i = 0; i < storage_.size(); ++i) {
88    if (!internal_strcmp(storage_[i], str)) {
89      last_match_ = storage_[i];
90      return last_match_;
91    }
92  }
93  last_match_ = internal_strdup(str);
94  storage_.push_back(last_match_);
95  return last_match_;
96}
97
98Symbolizer::Symbolizer(IntrusiveList<SymbolizerTool> tools)
99    : module_names_(&mu_), n_modules_(0), modules_fresh_(false), tools_(tools),
100      start_hook_(0), end_hook_(0) {}
101
102Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym)
103    : sym_(sym) {
104  if (sym_->start_hook_)
105    sym_->start_hook_();
106}
107
108Symbolizer::SymbolizerScope::~SymbolizerScope() {
109  if (sym_->end_hook_)
110    sym_->end_hook_();
111}
112
113}  // namespace __sanitizer
114