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