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