1c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne//===-- sanitizer_symbolizer.cc -------------------------------------------===//
2c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne//
3c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne//                     The LLVM Compiler Infrastructure
4c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne//
5c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne// This file is distributed under the University of Illinois Open Source
6c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne// License. See LICENSE.TXT for details.
7c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne//
8c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne//===----------------------------------------------------------------------===//
9c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne//
10c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne// This file is shared between AddressSanitizer and ThreadSanitizer
11c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne// run-time libraries.
12c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne//===----------------------------------------------------------------------===//
13c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne
1486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_allocator_internal.h"
15c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne#include "sanitizer_platform.h"
16c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne#include "sanitizer_internal_defs.h"
1786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_libc.h"
18c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne#include "sanitizer_placement_new.h"
197c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include "sanitizer_symbolizer_internal.h"
20c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne
21c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbournenamespace __sanitizer {
22c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne
2386277eb844c4983c81de62d7c050e92fe7155788Stephen HinesAddressInfo::AddressInfo() {
2486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_memset(this, 0, sizeof(AddressInfo));
2586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  function_offset = kUnknown;
2686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
2786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
2886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid AddressInfo::Clear() {
2986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  InternalFree(module);
3086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  InternalFree(function);
3186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  InternalFree(file);
3286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_memset(this, 0, sizeof(AddressInfo));
3386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  function_offset = kUnknown;
3486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
3586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarvoid AddressInfo::FillModuleInfo(const char *mod_name, uptr mod_offset) {
3786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  module = internal_strdup(mod_name);
3886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  module_offset = mod_offset;
3986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
4086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
4186277eb844c4983c81de62d7c050e92fe7155788Stephen HinesSymbolizedStack::SymbolizedStack() : next(nullptr), info() {}
4286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
4386277eb844c4983c81de62d7c050e92fe7155788Stephen HinesSymbolizedStack *SymbolizedStack::New(uptr addr) {
4486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *mem = InternalAlloc(sizeof(SymbolizedStack));
4586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  SymbolizedStack *res = new(mem) SymbolizedStack();
4686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  res->info.address = addr;
4786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return res;
4886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
4986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
5086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid SymbolizedStack::ClearAll() {
5186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  info.Clear();
5286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (next)
5386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    next->ClearAll();
5486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  InternalFree(this);
5586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
5686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
5786277eb844c4983c81de62d7c050e92fe7155788Stephen HinesDataInfo::DataInfo() {
5886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_memset(this, 0, sizeof(DataInfo));
5986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
6086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
6186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid DataInfo::Clear() {
6286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  InternalFree(module);
6386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  InternalFree(name);
6486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_memset(this, 0, sizeof(DataInfo));
6586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
6686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
67e00495aa0f3b114c7b764769d9450e5d2efb8e64Alexey SamsonovSymbolizer *Symbolizer::symbolizer_;
68e00495aa0f3b114c7b764769d9450e5d2efb8e64Alexey SamsonovStaticSpinMutex Symbolizer::init_mu_;
69c1a1ed62228288155459d39194995a36aca4a8a6Peter CollingbourneLowLevelAllocator Symbolizer::symbolizer_allocator_;
70c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne
7166d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonovvoid Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook,
7266d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov                          Symbolizer::EndSymbolizationHook end_hook) {
7366d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov  CHECK(start_hook_ == 0 && end_hook_ == 0);
7466d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov  start_hook_ = start_hook;
7566d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov  end_hook_ = end_hook;
7666d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov}
7766d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov
78909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainarconst char *Symbolizer::ModuleNameOwner::GetOwnedCopy(const char *str) {
79909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  mu_->CheckLocked();
80909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar
81909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  // 'str' will be the same string multiple times in a row, optimize this case.
82909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  if (last_match_ && !internal_strcmp(last_match_, str))
83909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar    return last_match_;
84909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar
85909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  // FIXME: this is linear search.
86909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  // We should optimize this further if this turns out to be a bottleneck later.
87909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  for (uptr i = 0; i < storage_.size(); ++i) {
88909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar    if (!internal_strcmp(storage_[i], str)) {
89909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar      last_match_ = storage_[i];
90909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar      return last_match_;
91909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar    }
92909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  }
93909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  last_match_ = internal_strdup(str);
94909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  storage_.push_back(last_match_);
95909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  return last_match_;
96909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar}
97909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar
987c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga NainarSymbolizer::Symbolizer(IntrusiveList<SymbolizerTool> tools)
99909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar    : module_names_(&mu_), n_modules_(0), modules_fresh_(false), tools_(tools),
100909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar      start_hook_(0), end_hook_(0) {}
10166d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov
10266d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey SamsonovSymbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym)
10366d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov    : sym_(sym) {
10466d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov  if (sym_->start_hook_)
10566d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov    sym_->start_hook_();
10666d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov}
10766d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov
10866d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey SamsonovSymbolizer::SymbolizerScope::~SymbolizerScope() {
10966d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov  if (sym_->end_hook_)
11066d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov    sym_->end_hook_();
11166d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov}
11266d91e3356a0c4d7aff3beaaaff3e87bbaec805cAlexey Samsonov
113c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne}  // namespace __sanitizer
114