Home | History | Annotate | Download | only in sanitizer_common
      1 //===-- sanitizer_symbolizer.h ----------------------------------*- C++ -*-===//
      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 // Symbolizer is used by sanitizers to map instruction address to a location in
     11 // source code at run-time. Symbolizer either uses __sanitizer_symbolize_*
     12 // defined in the program, or (if they are missing) tries to find and
     13 // launch "llvm-symbolizer" commandline tool in a separate process and
     14 // communicate with it.
     15 //
     16 // Generally we should try to avoid calling system library functions during
     17 // symbolization (and use their replacements from sanitizer_libc.h instead).
     18 //===----------------------------------------------------------------------===//
     19 #ifndef SANITIZER_SYMBOLIZER_H
     20 #define SANITIZER_SYMBOLIZER_H
     21 
     22 #include "sanitizer_allocator_internal.h"
     23 #include "sanitizer_internal_defs.h"
     24 #include "sanitizer_libc.h"
     25 
     26 namespace __sanitizer {
     27 
     28 struct AddressInfo {
     29   uptr address;
     30 
     31   char *module;
     32   uptr module_offset;
     33 
     34   static const uptr kUnknown = ~(uptr)0;
     35   char *function;
     36   uptr function_offset;
     37 
     38   char *file;
     39   int line;
     40   int column;
     41 
     42   AddressInfo() {
     43     internal_memset(this, 0, sizeof(AddressInfo));
     44     function_offset = kUnknown;
     45   }
     46 
     47   // Deletes all strings and resets all fields.
     48   void Clear() {
     49     InternalFree(module);
     50     InternalFree(function);
     51     InternalFree(file);
     52     internal_memset(this, 0, sizeof(AddressInfo));
     53     function_offset = kUnknown;
     54   }
     55 
     56   void FillAddressAndModuleInfo(uptr addr, const char *mod_name,
     57                                 uptr mod_offset) {
     58     address = addr;
     59     module = internal_strdup(mod_name);
     60     module_offset = mod_offset;
     61   }
     62 };
     63 
     64 struct DataInfo {
     65   uptr address;
     66   char *module;
     67   uptr module_offset;
     68   char *name;
     69   uptr start;
     70   uptr size;
     71 };
     72 
     73 class Symbolizer {
     74  public:
     75   /// Returns platform-specific implementation of Symbolizer. The symbolizer
     76   /// must be initialized (with init or disable) before calling this function.
     77   static Symbolizer *Get();
     78   /// Returns platform-specific implementation of Symbolizer, or null if not
     79   /// initialized.
     80   static Symbolizer *GetOrNull();
     81   /// Returns platform-specific implementation of Symbolizer.  Will
     82   /// automatically initialize symbolizer as if by calling Init(0) if needed.
     83   static Symbolizer *GetOrInit();
     84   /// Initialize and return the symbolizer, given an optional path to an
     85   /// external symbolizer.  The path argument is only required for legacy
     86   /// reasons as this function will check $PATH for an external symbolizer.  Not
     87   /// thread safe.
     88   static Symbolizer *Init(const char* path_to_external = 0);
     89   // Fills at most "max_frames" elements of "frames" with descriptions
     90   // for a given address (in all inlined functions). Returns the number
     91   // of descriptions actually filled.
     92   virtual uptr SymbolizePC(uptr address, AddressInfo *frames, uptr max_frames) {
     93     return 0;
     94   }
     95   virtual bool SymbolizeData(uptr address, DataInfo *info) {
     96     return false;
     97   }
     98   virtual bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
     99                                            uptr *module_address) {
    100     return false;
    101   }
    102   virtual bool CanReturnFileLineInfo() {
    103     return false;
    104   }
    105   // Release internal caches (if any).
    106   virtual void Flush() {}
    107   // Attempts to demangle the provided C++ mangled name.
    108   virtual const char *Demangle(const char *name) {
    109     return name;
    110   }
    111   virtual void PrepareForSandboxing() {}
    112 
    113   // Allow user to install hooks that would be called before/after Symbolizer
    114   // does the actual file/line info fetching. Specific sanitizers may need this
    115   // to distinguish system library calls made in user code from calls made
    116   // during in-process symbolization.
    117   typedef void (*StartSymbolizationHook)();
    118   typedef void (*EndSymbolizationHook)();
    119   // May be called at most once.
    120   void AddHooks(StartSymbolizationHook start_hook,
    121                 EndSymbolizationHook end_hook);
    122 
    123  private:
    124   /// Platform-specific function for creating a Symbolizer object.
    125   static Symbolizer *PlatformInit(const char *path_to_external);
    126   /// Create a symbolizer and store it to symbolizer_ without checking if one
    127   /// already exists.  Not thread safe.
    128   static Symbolizer *CreateAndStore(const char *path_to_external);
    129   /// Initialize the symbolizer in a disabled state.  Not thread safe.
    130   static Symbolizer *Disable();
    131 
    132   static Symbolizer *symbolizer_;
    133   static StaticSpinMutex init_mu_;
    134 
    135  protected:
    136   Symbolizer();
    137 
    138   static LowLevelAllocator symbolizer_allocator_;
    139 
    140   StartSymbolizationHook start_hook_;
    141   EndSymbolizationHook end_hook_;
    142   class SymbolizerScope {
    143    public:
    144     explicit SymbolizerScope(const Symbolizer *sym);
    145     ~SymbolizerScope();
    146    private:
    147     const Symbolizer *sym_;
    148   };
    149 };
    150 
    151 }  // namespace __sanitizer
    152 
    153 #endif  // SANITIZER_SYMBOLIZER_H
    154