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