brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.3 KiB · bd89dc4 Raw
248 lines · c
1//===-- sanitizer_symbolizer.h ----------------------------------*- C++ -*-===//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-exception6//7//===----------------------------------------------------------------------===//8//9// Symbolizer is used by sanitizers to map instruction address to a location in10// source code at run-time. Symbolizer either uses __sanitizer_symbolize_*11// defined in the program, or (if they are missing) tries to find and12// launch "llvm-symbolizer" commandline tool in a separate process and13// communicate with it.14//15// Generally we should try to avoid calling system library functions during16// symbolization (and use their replacements from sanitizer_libc.h instead).17//===----------------------------------------------------------------------===//18#ifndef SANITIZER_SYMBOLIZER_H19#define SANITIZER_SYMBOLIZER_H20 21#include "sanitizer_common.h"22#include "sanitizer_mutex.h"23#include "sanitizer_vector.h"24 25namespace __sanitizer {26 27struct AddressInfo {28  // Owns all the string members. Storage for them is29  // (de)allocated using sanitizer internal allocator.30  uptr address;31 32  char *module;33  uptr module_offset;34  ModuleArch module_arch;35  u8 uuid[kModuleUUIDSize];36  uptr uuid_size;37 38  static const uptr kUnknown = ~(uptr)0;39  char *function;40  uptr function_offset;41 42  char *file;43  int line;44  int column;45 46  AddressInfo();47  // Deletes all strings and resets all fields.48  void Clear();49  void FillModuleInfo(const char *mod_name, uptr mod_offset, ModuleArch arch);50  void FillModuleInfo(const LoadedModule &mod);51  uptr module_base() const { return address - module_offset; }52};53 54// Linked list of symbolized frames (each frame is described by AddressInfo).55struct SymbolizedStack {56  SymbolizedStack *next;57  AddressInfo info;58  static SymbolizedStack *New(uptr addr);59  // Deletes current, and all subsequent frames in the linked list.60  // The object cannot be accessed after the call to this function.61  void ClearAll();62 63 private:64  SymbolizedStack();65};66 67class SymbolizedStackHolder {68  SymbolizedStack *Stack;69 70  void clear() {71    if (Stack)72      Stack->ClearAll();73  }74 75 public:76  explicit SymbolizedStackHolder(SymbolizedStack *Stack = nullptr)77      : Stack(Stack) {}78  ~SymbolizedStackHolder() { clear(); }79  void reset(SymbolizedStack *S = nullptr) {80    if (Stack != S)81      clear();82    Stack = S;83  }84  const SymbolizedStack *get() const { return Stack; }85};86 87// For now, DataInfo is used to describe global variable.88struct DataInfo {89  // Owns all the string members. Storage for them is90  // (de)allocated using sanitizer internal allocator.91  char *module;92  uptr module_offset;93  ModuleArch module_arch;94 95  char *file;96  uptr line;97  char *name;98  uptr start;99  uptr size;100 101  DataInfo();102  void Clear();103};104 105struct LocalInfo {106  char *function_name = nullptr;107  char *name = nullptr;108  char *decl_file = nullptr;109  unsigned decl_line = 0;110 111  bool has_frame_offset = false;112  bool has_size = false;113  bool has_tag_offset = false;114 115  sptr frame_offset;116  uptr size;117  uptr tag_offset;118 119  void Clear();120};121 122struct FrameInfo {123  char *module;124  uptr module_offset;125  ModuleArch module_arch;126 127  InternalMmapVector<LocalInfo> locals;128  void Clear();129};130 131class SymbolizerTool;132 133class Symbolizer final {134 public:135  /// Initialize and return platform-specific implementation of symbolizer136  /// (if it wasn't already initialized).137  static Symbolizer *GetOrInit();138  static void LateInitialize();139  // Returns a list of symbolized frames for a given address (containing140  // all inlined functions, if necessary).141  SymbolizedStack *SymbolizePC(uptr address);142  bool SymbolizeData(uptr address, DataInfo *info);143  bool SymbolizeFrame(uptr address, FrameInfo *info);144 145  // The module names Symbolizer returns are stable and unique for every given146  // module.  It is safe to store and compare them as pointers.147  bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,148                                   uptr *module_address);149  const char *GetModuleNameForPc(uptr pc) {150    const char *module_name = nullptr;151    uptr unused;152    if (GetModuleNameAndOffsetForPC(pc, &module_name, &unused))153      return module_name;154    return nullptr;155  }156 157  // Release internal caches (if any).158  void Flush();159  // Attempts to demangle the provided C++ mangled name. Never returns nullptr.160  const char *Demangle(const char *name);161 162  // Allow user to install hooks that would be called before/after Symbolizer163  // does the actual file/line info fetching. Specific sanitizers may need this164  // to distinguish system library calls made in user code from calls made165  // during in-process symbolization.166  typedef void (*StartSymbolizationHook)();167  typedef void (*EndSymbolizationHook)();168  // May be called at most once.169  void AddHooks(StartSymbolizationHook start_hook,170                EndSymbolizationHook end_hook);171 172  void RefreshModules();173  const LoadedModule *FindModuleForAddress(uptr address);174 175  void InvalidateModuleList();176 177  const ListOfModules &GetRefreshedListOfModules();178 179 private:180  // GetModuleNameAndOffsetForPC has to return a string to the caller.181  // Since the corresponding module might get unloaded later, we should create182  // our owned copies of the strings that we can safely return.183  // ModuleNameOwner does not provide any synchronization, thus calls to184  // its method should be protected by |mu_|.185  class ModuleNameOwner {186   public:187    explicit ModuleNameOwner(Mutex *synchronized_by)188        : mu_(synchronized_by), last_match_(nullptr) {189      storage_.reserve(kInitialCapacity);190    }191    const char *GetOwnedCopy(const char *str);192 193   private:194    static const uptr kInitialCapacity = 1000;195 196    Mutex *mu_;197    const char *last_match_ SANITIZER_GUARDED_BY(mu_);198    InternalMmapVector<const char *> storage_ SANITIZER_GUARDED_BY(*mu_);199  } module_names_;200 201  /// Platform-specific function for creating a Symbolizer object.202  static Symbolizer *PlatformInit();203 204  bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name,205                                         uptr *module_offset,206                                         ModuleArch *module_arch);207  ListOfModules modules_;208  ListOfModules fallback_modules_;209  // If stale, need to reload the modules before looking up addresses.210  bool modules_fresh_;211 212  // Platform-specific default demangler, returns nullptr on failure.213  const char *PlatformDemangle(const char *name);214 215  static Symbolizer *symbolizer_;216  static StaticSpinMutex init_mu_;217 218  // Mutex locked from public methods of |Symbolizer|, so that the internals219  // (including individual symbolizer tools and platform-specific methods) are220  // always synchronized.221  Mutex mu_;222 223  IntrusiveList<SymbolizerTool> tools_ SANITIZER_GUARDED_BY(mu_);224 225  explicit Symbolizer(IntrusiveList<SymbolizerTool> tools);226 227  static LowLevelAllocator symbolizer_allocator_;228 229  StartSymbolizationHook start_hook_;230  EndSymbolizationHook end_hook_;231  class SymbolizerScope {232   public:233    explicit SymbolizerScope(const Symbolizer *sym);234    ~SymbolizerScope();235   private:236    const Symbolizer *sym_;237    int errno_;  // Backup errno in case symbolizer change the value.238  };239};240 241#ifdef SANITIZER_WINDOWS242void InitializeDbgHelpIfNeeded();243#endif244 245}  // namespace __sanitizer246 247#endif  // SANITIZER_SYMBOLIZER_H248