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