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