Home | History | Annotate | Download | only in sanitizer_common
      1 //===-- sanitizer_symbolizer_internal.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 // Header for internal classes and functions to be used by implementations of
     11 // symbolizers.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 #ifndef SANITIZER_SYMBOLIZER_INTERNAL_H
     15 #define SANITIZER_SYMBOLIZER_INTERNAL_H
     16 
     17 #include "sanitizer_symbolizer.h"
     18 
     19 namespace __sanitizer {
     20 
     21 // Parsing helpers, 'str' is searched for delimiter(s) and a string or uptr
     22 // is extracted. When extracting a string, a newly allocated (using
     23 // InternalAlloc) and null-terminataed buffer is returned. They return a pointer
     24 // to the next characted after the found delimiter.
     25 const char *ExtractToken(const char *str, const char *delims, char **result);
     26 const char *ExtractInt(const char *str, const char *delims, int *result);
     27 const char *ExtractUptr(const char *str, const char *delims, uptr *result);
     28 const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
     29                                       char **result);
     30 
     31 const char *DemangleSwiftAndCXX(const char *name);
     32 
     33 // SymbolizerTool is an interface that is implemented by individual "tools"
     34 // that can perform symbolication (external llvm-symbolizer, libbacktrace,
     35 // Windows DbgHelp symbolizer, etc.).
     36 class SymbolizerTool {
     37  public:
     38   // The main |Symbolizer| class implements a "fallback chain" of symbolizer
     39   // tools. In a request to symbolize an address, if one tool returns false,
     40   // the next tool in the chain will be tried.
     41   SymbolizerTool *next;
     42 
     43   SymbolizerTool() : next(nullptr) { }
     44 
     45   // Can't declare pure virtual functions in sanitizer runtimes:
     46   // __cxa_pure_virtual might be unavailable.
     47 
     48   // The |stack| parameter is inout. It is pre-filled with the address,
     49   // module base and module offset values and is to be used to construct
     50   // other stack frames.
     51   virtual bool SymbolizePC(uptr addr, SymbolizedStack *stack) {
     52     UNIMPLEMENTED();
     53   }
     54 
     55   // The |info| parameter is inout. It is pre-filled with the module base
     56   // and module offset values.
     57   virtual bool SymbolizeData(uptr addr, DataInfo *info) {
     58     UNIMPLEMENTED();
     59   }
     60 
     61   virtual void Flush() {}
     62 
     63   // Return nullptr to fallback to the default platform-specific demangler.
     64   virtual const char *Demangle(const char *name) {
     65     return nullptr;
     66   }
     67 };
     68 
     69 // SymbolizerProcess encapsulates communication between the tool and
     70 // external symbolizer program, running in a different subprocess.
     71 // SymbolizerProcess may not be used from two threads simultaneously.
     72 class SymbolizerProcess {
     73  public:
     74   explicit SymbolizerProcess(const char *path, bool use_forkpty = false);
     75   const char *SendCommand(const char *command);
     76 
     77  protected:
     78   virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const {
     79     UNIMPLEMENTED();
     80   }
     81 
     82   /// The maximum number of arguments required to invoke a tool process.
     83   enum { kArgVMax = 6 };
     84 
     85   /// Fill in an argv array to invoke the child process.
     86   virtual void GetArgV(const char *path_to_binary,
     87                        const char *(&argv)[kArgVMax]) const {
     88     UNIMPLEMENTED();
     89   }
     90 
     91   virtual bool ReadFromSymbolizer(char *buffer, uptr max_length);
     92 
     93  private:
     94   bool Restart();
     95   const char *SendCommandImpl(const char *command);
     96   bool WriteToSymbolizer(const char *buffer, uptr length);
     97   bool StartSymbolizerSubprocess();
     98 
     99   const char *path_;
    100   fd_t input_fd_;
    101   fd_t output_fd_;
    102 
    103   static const uptr kBufferSize = 16 * 1024;
    104   char buffer_[kBufferSize];
    105 
    106   static const uptr kMaxTimesRestarted = 5;
    107   static const int kSymbolizerStartupTimeMillis = 10;
    108   uptr times_restarted_;
    109   bool failed_to_start_;
    110   bool reported_invalid_path_;
    111   bool use_forkpty_;
    112 };
    113 
    114 class LLVMSymbolizerProcess;
    115 
    116 // This tool invokes llvm-symbolizer in a subprocess. It should be as portable
    117 // as the llvm-symbolizer tool is.
    118 class LLVMSymbolizer : public SymbolizerTool {
    119  public:
    120   explicit LLVMSymbolizer(const char *path, LowLevelAllocator *allocator);
    121 
    122   bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
    123 
    124   bool SymbolizeData(uptr addr, DataInfo *info) override;
    125 
    126  private:
    127   const char *SendCommand(bool is_data, const char *module_name,
    128                           uptr module_offset);
    129 
    130   LLVMSymbolizerProcess *symbolizer_process_;
    131   static const uptr kBufferSize = 16 * 1024;
    132   char buffer_[kBufferSize];
    133 };
    134 
    135 // Parses one or more two-line strings in the following format:
    136 //   <function_name>
    137 //   <file_name>:<line_number>[:<column_number>]
    138 // Used by LLVMSymbolizer, Addr2LinePool and InternalSymbolizer, since all of
    139 // them use the same output format.  Returns true if any useful debug
    140 // information was found.
    141 void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res);
    142 
    143 // Parses a two-line string in the following format:
    144 //   <symbol_name>
    145 //   <start_address> <size>
    146 // Used by LLVMSymbolizer and InternalSymbolizer.
    147 void ParseSymbolizeDataOutput(const char *str, DataInfo *info);
    148 
    149 }  // namespace __sanitizer
    150 
    151 #endif  // SANITIZER_SYMBOLIZER_INTERNAL_H
    152