Home | History | Annotate | Line # | Download | only in sanitizer_common
      1 //===-- sanitizer_symbolizer.cc -------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is shared between AddressSanitizer and ThreadSanitizer
     11 // run-time libraries.
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "sanitizer_allocator_internal.h"
     15 #include "sanitizer_platform.h"
     16 #include "sanitizer_internal_defs.h"
     17 #include "sanitizer_libc.h"
     18 #include "sanitizer_placement_new.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 }
     35 
     36 void AddressInfo::FillModuleInfo(const char *mod_name, uptr mod_offset,
     37                                  ModuleArch mod_arch) {
     38   module = internal_strdup(mod_name);
     39   module_offset = mod_offset;
     40   module_arch = mod_arch;
     41 }
     42 
     43 SymbolizedStack::SymbolizedStack() : next(nullptr), info() {}
     44 
     45 SymbolizedStack *SymbolizedStack::New(uptr addr) {
     46   void *mem = InternalAlloc(sizeof(SymbolizedStack));
     47   SymbolizedStack *res = new(mem) SymbolizedStack();
     48   res->info.address = addr;
     49   return res;
     50 }
     51 
     52 void SymbolizedStack::ClearAll() {
     53   info.Clear();
     54   if (next)
     55     next->ClearAll();
     56   InternalFree(this);
     57 }
     58 
     59 DataInfo::DataInfo() {
     60   internal_memset(this, 0, sizeof(DataInfo));
     61 }
     62 
     63 void DataInfo::Clear() {
     64   InternalFree(module);
     65   InternalFree(file);
     66   InternalFree(name);
     67   internal_memset(this, 0, sizeof(DataInfo));
     68 }
     69 
     70 Symbolizer *Symbolizer::symbolizer_;
     71 StaticSpinMutex Symbolizer::init_mu_;
     72 LowLevelAllocator Symbolizer::symbolizer_allocator_;
     73 
     74 void Symbolizer::InvalidateModuleList() {
     75   modules_fresh_ = false;
     76 }
     77 
     78 void Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook,
     79                           Symbolizer::EndSymbolizationHook end_hook) {
     80   CHECK(start_hook_ == 0 && end_hook_ == 0);
     81   start_hook_ = start_hook;
     82   end_hook_ = end_hook;
     83 }
     84 
     85 const char *Symbolizer::ModuleNameOwner::GetOwnedCopy(const char *str) {
     86   mu_->CheckLocked();
     87 
     88   // 'str' will be the same string multiple times in a row, optimize this case.
     89   if (last_match_ && !internal_strcmp(last_match_, str))
     90     return last_match_;
     91 
     92   // FIXME: this is linear search.
     93   // We should optimize this further if this turns out to be a bottleneck later.
     94   for (uptr i = 0; i < storage_.size(); ++i) {
     95     if (!internal_strcmp(storage_[i], str)) {
     96       last_match_ = storage_[i];
     97       return last_match_;
     98     }
     99   }
    100   last_match_ = internal_strdup(str);
    101   storage_.push_back(last_match_);
    102   return last_match_;
    103 }
    104 
    105 Symbolizer::Symbolizer(IntrusiveList<SymbolizerTool> tools)
    106     : module_names_(&mu_), modules_(), modules_fresh_(false), tools_(tools),
    107       start_hook_(0), end_hook_(0) {}
    108 
    109 Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym)
    110     : sym_(sym) {
    111   if (sym_->start_hook_)
    112     sym_->start_hook_();
    113 }
    114 
    115 Symbolizer::SymbolizerScope::~SymbolizerScope() {
    116   if (sym_->end_hook_)
    117     sym_->end_hook_();
    118 }
    119 
    120 }  // namespace __sanitizer
    121