17c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar//===-- sanitizer_symbolizer_internal.h -------------------------*- C++ -*-===//
27c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar//
37c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar//                     The LLVM Compiler Infrastructure
47c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar//
57c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source
67c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// License. See LICENSE.TXT for details.
77c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar//
87c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar//===----------------------------------------------------------------------===//
97c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar//
107c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// Header for internal classes and functions to be used by implementations of
117c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// symbolizers.
127c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar//
137c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar//===----------------------------------------------------------------------===//
147c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#ifndef SANITIZER_SYMBOLIZER_INTERNAL_H
157c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#define SANITIZER_SYMBOLIZER_INTERNAL_H
167c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
177c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include "sanitizer_symbolizer.h"
187c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
197c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarnamespace __sanitizer {
207c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
217c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// Parsing helpers, 'str' is searched for delimiter(s) and a string or uptr
227c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// is extracted. When extracting a string, a newly allocated (using
237c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// InternalAlloc) and null-terminataed buffer is returned. They return a pointer
247c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// to the next characted after the found delimiter.
257c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarconst char *ExtractToken(const char *str, const char *delims, char **result);
267c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarconst char *ExtractInt(const char *str, const char *delims, int *result);
277c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarconst char *ExtractUptr(const char *str, const char *delims, uptr *result);
287c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarconst char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
297c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar                                      char **result);
307c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
31c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarconst char *DemangleSwiftAndCXX(const char *name);
327c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
337c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// SymbolizerTool is an interface that is implemented by individual "tools"
347c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// that can perform symbolication (external llvm-symbolizer, libbacktrace,
357c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// Windows DbgHelp symbolizer, etc.).
367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarclass SymbolizerTool {
377c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar public:
387c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // The main |Symbolizer| class implements a "fallback chain" of symbolizer
397c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // tools. In a request to symbolize an address, if one tool returns false,
407c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // the next tool in the chain will be tried.
417c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  SymbolizerTool *next;
427c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
437c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  SymbolizerTool() : next(nullptr) { }
447c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
457c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // Can't declare pure virtual functions in sanitizer runtimes:
467c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // __cxa_pure_virtual might be unavailable.
477c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
487c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // The |stack| parameter is inout. It is pre-filled with the address,
497c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // module base and module offset values and is to be used to construct
507c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // other stack frames.
517c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  virtual bool SymbolizePC(uptr addr, SymbolizedStack *stack) {
527c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    UNIMPLEMENTED();
537c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
547c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
557c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // The |info| parameter is inout. It is pre-filled with the module base
567c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // and module offset values.
577c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  virtual bool SymbolizeData(uptr addr, DataInfo *info) {
587c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    UNIMPLEMENTED();
597c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
607c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
617c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  virtual void Flush() {}
627c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
637c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // Return nullptr to fallback to the default platform-specific demangler.
647c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  virtual const char *Demangle(const char *name) {
657c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return nullptr;
667c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
677c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar};
687c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
697c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// SymbolizerProcess encapsulates communication between the tool and
707c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// external symbolizer program, running in a different subprocess.
717c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// SymbolizerProcess may not be used from two threads simultaneously.
727c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarclass SymbolizerProcess {
737c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar public:
747c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  explicit SymbolizerProcess(const char *path, bool use_forkpty = false);
757c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  const char *SendCommand(const char *command);
767c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
77799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar protected:
787c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const {
797c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    UNIMPLEMENTED();
807c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
817c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
82799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  /// The maximum number of arguments required to invoke a tool process.
83799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  enum { kArgVMax = 6 };
84799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
85799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  /// Fill in an argv array to invoke the child process.
86799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  virtual void GetArgV(const char *path_to_binary,
87799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       const char *(&argv)[kArgVMax]) const {
887c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    UNIMPLEMENTED();
897c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
907c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
91799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  virtual bool ReadFromSymbolizer(char *buffer, uptr max_length);
92799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
93799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar private:
94799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  bool Restart();
95799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  const char *SendCommandImpl(const char *command);
96799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  bool WriteToSymbolizer(const char *buffer, uptr length);
97799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  bool StartSymbolizerSubprocess();
98799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
997c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  const char *path_;
100799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  fd_t input_fd_;
101799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  fd_t output_fd_;
1027c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
1037c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  static const uptr kBufferSize = 16 * 1024;
1047c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  char buffer_[kBufferSize];
1057c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
1067c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  static const uptr kMaxTimesRestarted = 5;
1077c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  static const int kSymbolizerStartupTimeMillis = 10;
1087c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr times_restarted_;
1097c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  bool failed_to_start_;
1107c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  bool reported_invalid_path_;
1117c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  bool use_forkpty_;
1127c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar};
1137c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
114799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarclass LLVMSymbolizerProcess;
115799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
116799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// This tool invokes llvm-symbolizer in a subprocess. It should be as portable
117799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// as the llvm-symbolizer tool is.
118799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarclass LLVMSymbolizer : public SymbolizerTool {
119799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar public:
120799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  explicit LLVMSymbolizer(const char *path, LowLevelAllocator *allocator);
121799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
122799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
123799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
124799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  bool SymbolizeData(uptr addr, DataInfo *info) override;
125799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
126799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar private:
127799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  const char *SendCommand(bool is_data, const char *module_name,
128799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                          uptr module_offset);
129799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
130799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  LLVMSymbolizerProcess *symbolizer_process_;
131799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  static const uptr kBufferSize = 16 * 1024;
132799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  char buffer_[kBufferSize];
133799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar};
134799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
135799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Parses one or more two-line strings in the following format:
136799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar//   <function_name>
137799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar//   <file_name>:<line_number>[:<column_number>]
138799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Used by LLVMSymbolizer, Addr2LinePool and InternalSymbolizer, since all of
139799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// them use the same output format.  Returns true if any useful debug
140799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// information was found.
141799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid ParseSymbolizePCOutput(const char *str, SymbolizedStack *res);
142799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
143799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Parses a two-line string in the following format:
144799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar//   <symbol_name>
145799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar//   <start_address> <size>
146799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Used by LLVMSymbolizer and InternalSymbolizer.
147799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid ParseSymbolizeDataOutput(const char *str, DataInfo *info);
148799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
1497c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar}  // namespace __sanitizer
1507c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
1517c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#endif  // SANITIZER_SYMBOLIZER_INTERNAL_H
152