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