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