sanitizer_symbolizer_internal.h 5.7 KB

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