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 20 namespace __sanitizer { 21 22 AddressInfo::AddressInfo() { 23 internal_memset(this, 0, sizeof(AddressInfo)); 24 function_offset = kUnknown; 25 } 26 27 void AddressInfo::Clear() { 28 InternalFree(module); 29 InternalFree(function); 30 InternalFree(file); 31 internal_memset(this, 0, sizeof(AddressInfo)); 32 function_offset = kUnknown; 33 } 34 35 void 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 42 SymbolizedStack::SymbolizedStack() : next(nullptr), info() {} 43 44 SymbolizedStack *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 51 void SymbolizedStack::ClearAll() { 52 info.Clear(); 53 if (next) 54 next->ClearAll(); 55 InternalFree(this); 56 } 57 58 DataInfo::DataInfo() { 59 internal_memset(this, 0, sizeof(DataInfo)); 60 } 61 62 void DataInfo::Clear() { 63 InternalFree(module); 64 InternalFree(file); 65 InternalFree(name); 66 internal_memset(this, 0, sizeof(DataInfo)); 67 } 68 69 void 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 79 Symbolizer *Symbolizer::symbolizer_; 80 StaticSpinMutex Symbolizer::init_mu_; 81 LowLevelAllocator Symbolizer::symbolizer_allocator_; 82 83 void Symbolizer::InvalidateModuleList() { 84 modules_fresh_ = false; 85 } 86 87 void 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 94 const 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 114 Symbolizer::Symbolizer(IntrusiveList<SymbolizerTool> tools) 115 : module_names_(&mu_), modules_(), modules_fresh_(false), tools_(tools), 116 start_hook_(0), end_hook_(0) {} 117 118 Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym) 119 : sym_(sym) { 120 if (sym_->start_hook_) 121 sym_->start_hook_(); 122 } 123 124 Symbolizer::SymbolizerScope::~SymbolizerScope() { 125 if (sym_->end_hook_) 126 sym_->end_hook_(); 127 } 128 129 void Symbolizer::LateInitializeTools() { 130 for (auto &tool : tools_) { 131 tool.LateInitialize(); 132 } 133 } 134 135 } // namespace __sanitizer 136