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