master
  1//===-- sanitizer_symbolizer.cpp ------------------------------------------===//
  2//
  3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4// See https://llvm.org/LICENSE.txt for license information.
  5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6//
  7//===----------------------------------------------------------------------===//
  8//
  9// This file is shared between AddressSanitizer and ThreadSanitizer
 10// run-time libraries.
 11//===----------------------------------------------------------------------===//
 12
 13#include <errno.h>
 14
 15#include "sanitizer_allocator_internal.h"
 16#include "sanitizer_common.h"
 17#include "sanitizer_internal_defs.h"
 18#include "sanitizer_libc.h"
 19#include "sanitizer_placement_new.h"
 20#include "sanitizer_platform.h"
 21#include "sanitizer_symbolizer_internal.h"
 22
 23namespace __sanitizer {
 24
 25AddressInfo::AddressInfo() {
 26  internal_memset(this, 0, sizeof(AddressInfo));
 27  function_offset = kUnknown;
 28}
 29
 30void AddressInfo::Clear() {
 31  InternalFree(module);
 32  InternalFree(function);
 33  InternalFree(file);
 34  internal_memset(this, 0, sizeof(AddressInfo));
 35  function_offset = kUnknown;
 36  uuid_size = 0;
 37}
 38
 39void AddressInfo::FillModuleInfo(const char *mod_name, uptr mod_offset,
 40                                 ModuleArch mod_arch) {
 41  module = internal_strdup(mod_name);
 42  module_offset = mod_offset;
 43  module_arch = mod_arch;
 44  uuid_size = 0;
 45}
 46
 47void AddressInfo::FillModuleInfo(const LoadedModule &mod) {
 48  module = internal_strdup(mod.full_name());
 49  module_offset = address - mod.base_address();
 50  module_arch = mod.arch();
 51  if (mod.uuid_size())
 52    internal_memcpy(uuid, mod.uuid(), mod.uuid_size());
 53  uuid_size = mod.uuid_size();
 54}
 55
 56SymbolizedStack::SymbolizedStack() : next(nullptr), info() {}
 57
 58SymbolizedStack *SymbolizedStack::New(uptr addr) {
 59  void *mem = InternalAlloc(sizeof(SymbolizedStack));
 60  SymbolizedStack *res = new(mem) SymbolizedStack();
 61  res->info.address = addr;
 62  return res;
 63}
 64
 65void SymbolizedStack::ClearAll() {
 66  info.Clear();
 67  if (next)
 68    next->ClearAll();
 69  InternalFree(this);
 70}
 71
 72DataInfo::DataInfo() {
 73  internal_memset(this, 0, sizeof(DataInfo));
 74}
 75
 76void DataInfo::Clear() {
 77  InternalFree(module);
 78  InternalFree(file);
 79  InternalFree(name);
 80  internal_memset(this, 0, sizeof(DataInfo));
 81}
 82
 83void FrameInfo::Clear() {
 84  InternalFree(module);
 85  for (LocalInfo &local : locals) {
 86    InternalFree(local.function_name);
 87    InternalFree(local.name);
 88    InternalFree(local.decl_file);
 89  }
 90  locals.clear();
 91}
 92
 93Symbolizer *Symbolizer::symbolizer_;
 94StaticSpinMutex Symbolizer::init_mu_;
 95LowLevelAllocator Symbolizer::symbolizer_allocator_;
 96
 97void Symbolizer::InvalidateModuleList() {
 98  modules_fresh_ = false;
 99}
100
101void Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook,
102                          Symbolizer::EndSymbolizationHook end_hook) {
103  CHECK(start_hook_ == 0 && end_hook_ == 0);
104  start_hook_ = start_hook;
105  end_hook_ = end_hook;
106}
107
108const char *Symbolizer::ModuleNameOwner::GetOwnedCopy(const char *str) {
109  mu_->CheckLocked();
110
111  // 'str' will be the same string multiple times in a row, optimize this case.
112  if (last_match_ && !internal_strcmp(last_match_, str))
113    return last_match_;
114
115  // FIXME: this is linear search.
116  // We should optimize this further if this turns out to be a bottleneck later.
117  for (uptr i = 0; i < storage_.size(); ++i) {
118    if (!internal_strcmp(storage_[i], str)) {
119      last_match_ = storage_[i];
120      return last_match_;
121    }
122  }
123  last_match_ = internal_strdup(str);
124  storage_.push_back(last_match_);
125  return last_match_;
126}
127
128Symbolizer::Symbolizer(IntrusiveList<SymbolizerTool> tools)
129    : module_names_(&mu_), modules_(), modules_fresh_(false), tools_(tools),
130      start_hook_(0), end_hook_(0) {}
131
132Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym)
133    : sym_(sym), errno_(errno) {
134  if (sym_->start_hook_)
135    sym_->start_hook_();
136}
137
138Symbolizer::SymbolizerScope::~SymbolizerScope() {
139  if (sym_->end_hook_)
140    sym_->end_hook_();
141  errno = errno_;
142}
143
144}  // namespace __sanitizer