168d75effSDimitry Andric //===-- sanitizer_symbolizer.cpp ------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is shared between AddressSanitizer and ThreadSanitizer 1068d75effSDimitry Andric // run-time libraries. 1168d75effSDimitry Andric //===----------------------------------------------------------------------===// 1268d75effSDimitry Andric 1368d75effSDimitry Andric #include "sanitizer_allocator_internal.h" 14*0eae32dcSDimitry Andric #include "sanitizer_common.h" 1568d75effSDimitry Andric #include "sanitizer_internal_defs.h" 1668d75effSDimitry Andric #include "sanitizer_libc.h" 1768d75effSDimitry Andric #include "sanitizer_placement_new.h" 18*0eae32dcSDimitry Andric #include "sanitizer_platform.h" 1968d75effSDimitry Andric #include "sanitizer_symbolizer_internal.h" 2068d75effSDimitry Andric 2168d75effSDimitry Andric namespace __sanitizer { 2268d75effSDimitry Andric 2368d75effSDimitry Andric AddressInfo::AddressInfo() { 2468d75effSDimitry Andric internal_memset(this, 0, sizeof(AddressInfo)); 2568d75effSDimitry Andric function_offset = kUnknown; 2668d75effSDimitry Andric } 2768d75effSDimitry Andric 2868d75effSDimitry Andric void AddressInfo::Clear() { 2968d75effSDimitry Andric InternalFree(module); 3068d75effSDimitry Andric InternalFree(function); 3168d75effSDimitry Andric InternalFree(file); 3268d75effSDimitry Andric internal_memset(this, 0, sizeof(AddressInfo)); 3368d75effSDimitry Andric function_offset = kUnknown; 34*0eae32dcSDimitry Andric uuid_size = 0; 3568d75effSDimitry Andric } 3668d75effSDimitry Andric 3768d75effSDimitry Andric void AddressInfo::FillModuleInfo(const char *mod_name, uptr mod_offset, 3868d75effSDimitry Andric ModuleArch mod_arch) { 3968d75effSDimitry Andric module = internal_strdup(mod_name); 4068d75effSDimitry Andric module_offset = mod_offset; 4168d75effSDimitry Andric module_arch = mod_arch; 42*0eae32dcSDimitry Andric uuid_size = 0; 43*0eae32dcSDimitry Andric } 44*0eae32dcSDimitry Andric 45*0eae32dcSDimitry Andric void AddressInfo::FillModuleInfo(const LoadedModule &mod) { 46*0eae32dcSDimitry Andric module = internal_strdup(mod.full_name()); 47*0eae32dcSDimitry Andric module_offset = address - mod.base_address(); 48*0eae32dcSDimitry Andric module_arch = mod.arch(); 49*0eae32dcSDimitry Andric if (mod.uuid_size()) 50*0eae32dcSDimitry Andric internal_memcpy(uuid, mod.uuid(), mod.uuid_size()); 51*0eae32dcSDimitry Andric uuid_size = mod.uuid_size(); 5268d75effSDimitry Andric } 5368d75effSDimitry Andric 5468d75effSDimitry Andric SymbolizedStack::SymbolizedStack() : next(nullptr), info() {} 5568d75effSDimitry Andric 5668d75effSDimitry Andric SymbolizedStack *SymbolizedStack::New(uptr addr) { 5768d75effSDimitry Andric void *mem = InternalAlloc(sizeof(SymbolizedStack)); 5868d75effSDimitry Andric SymbolizedStack *res = new(mem) SymbolizedStack(); 5968d75effSDimitry Andric res->info.address = addr; 6068d75effSDimitry Andric return res; 6168d75effSDimitry Andric } 6268d75effSDimitry Andric 6368d75effSDimitry Andric void SymbolizedStack::ClearAll() { 6468d75effSDimitry Andric info.Clear(); 6568d75effSDimitry Andric if (next) 6668d75effSDimitry Andric next->ClearAll(); 6768d75effSDimitry Andric InternalFree(this); 6868d75effSDimitry Andric } 6968d75effSDimitry Andric 7068d75effSDimitry Andric DataInfo::DataInfo() { 7168d75effSDimitry Andric internal_memset(this, 0, sizeof(DataInfo)); 7268d75effSDimitry Andric } 7368d75effSDimitry Andric 7468d75effSDimitry Andric void DataInfo::Clear() { 7568d75effSDimitry Andric InternalFree(module); 7668d75effSDimitry Andric InternalFree(file); 7768d75effSDimitry Andric InternalFree(name); 7868d75effSDimitry Andric internal_memset(this, 0, sizeof(DataInfo)); 7968d75effSDimitry Andric } 8068d75effSDimitry Andric 8168d75effSDimitry Andric void FrameInfo::Clear() { 8268d75effSDimitry Andric InternalFree(module); 8368d75effSDimitry Andric for (LocalInfo &local : locals) { 8468d75effSDimitry Andric InternalFree(local.function_name); 8568d75effSDimitry Andric InternalFree(local.name); 8668d75effSDimitry Andric InternalFree(local.decl_file); 8768d75effSDimitry Andric } 8868d75effSDimitry Andric locals.clear(); 8968d75effSDimitry Andric } 9068d75effSDimitry Andric 9168d75effSDimitry Andric Symbolizer *Symbolizer::symbolizer_; 9268d75effSDimitry Andric StaticSpinMutex Symbolizer::init_mu_; 9368d75effSDimitry Andric LowLevelAllocator Symbolizer::symbolizer_allocator_; 9468d75effSDimitry Andric 9568d75effSDimitry Andric void Symbolizer::InvalidateModuleList() { 9668d75effSDimitry Andric modules_fresh_ = false; 9768d75effSDimitry Andric } 9868d75effSDimitry Andric 9968d75effSDimitry Andric void Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook, 10068d75effSDimitry Andric Symbolizer::EndSymbolizationHook end_hook) { 10168d75effSDimitry Andric CHECK(start_hook_ == 0 && end_hook_ == 0); 10268d75effSDimitry Andric start_hook_ = start_hook; 10368d75effSDimitry Andric end_hook_ = end_hook; 10468d75effSDimitry Andric } 10568d75effSDimitry Andric 10668d75effSDimitry Andric const char *Symbolizer::ModuleNameOwner::GetOwnedCopy(const char *str) { 10768d75effSDimitry Andric mu_->CheckLocked(); 10868d75effSDimitry Andric 10968d75effSDimitry Andric // 'str' will be the same string multiple times in a row, optimize this case. 11068d75effSDimitry Andric if (last_match_ && !internal_strcmp(last_match_, str)) 11168d75effSDimitry Andric return last_match_; 11268d75effSDimitry Andric 11368d75effSDimitry Andric // FIXME: this is linear search. 11468d75effSDimitry Andric // We should optimize this further if this turns out to be a bottleneck later. 11568d75effSDimitry Andric for (uptr i = 0; i < storage_.size(); ++i) { 11668d75effSDimitry Andric if (!internal_strcmp(storage_[i], str)) { 11768d75effSDimitry Andric last_match_ = storage_[i]; 11868d75effSDimitry Andric return last_match_; 11968d75effSDimitry Andric } 12068d75effSDimitry Andric } 12168d75effSDimitry Andric last_match_ = internal_strdup(str); 12268d75effSDimitry Andric storage_.push_back(last_match_); 12368d75effSDimitry Andric return last_match_; 12468d75effSDimitry Andric } 12568d75effSDimitry Andric 12668d75effSDimitry Andric Symbolizer::Symbolizer(IntrusiveList<SymbolizerTool> tools) 12768d75effSDimitry Andric : module_names_(&mu_), modules_(), modules_fresh_(false), tools_(tools), 12868d75effSDimitry Andric start_hook_(0), end_hook_(0) {} 12968d75effSDimitry Andric 13068d75effSDimitry Andric Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym) 13168d75effSDimitry Andric : sym_(sym) { 13268d75effSDimitry Andric if (sym_->start_hook_) 13368d75effSDimitry Andric sym_->start_hook_(); 13468d75effSDimitry Andric } 13568d75effSDimitry Andric 13668d75effSDimitry Andric Symbolizer::SymbolizerScope::~SymbolizerScope() { 13768d75effSDimitry Andric if (sym_->end_hook_) 13868d75effSDimitry Andric sym_->end_hook_(); 13968d75effSDimitry Andric } 14068d75effSDimitry Andric 14168d75effSDimitry Andric } // namespace __sanitizer 142