Codemod: use #include angle brackets in folly and thrift
[folly.git] / folly / experimental / symbolizer / Symbolizer.h
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef FOLLY_EXPERIMENTAL_SYMBOLIZER_SYMBOLIZER_H_
18 #define FOLLY_EXPERIMENTAL_SYMBOLIZER_SYMBOLIZER_H_
19
20 #include <cstdint>
21 #include <string>
22 #include <unordered_map>
23
24 #include <folly/FBString.h>
25 #include <folly/Range.h>
26 #include <folly/String.h>
27 #include <folly/io/IOBuf.h>
28 #include <folly/experimental/symbolizer/Elf.h>
29 #include <folly/experimental/symbolizer/ElfCache.h>
30 #include <folly/experimental/symbolizer/Dwarf.h>
31 #include <folly/experimental/symbolizer/StackTrace.h>
32
33 namespace folly {
34 namespace symbolizer {
35
36 class Symbolizer;
37
38 /**
39  * Frame information: symbol name and location.
40  */
41 struct SymbolizedFrame {
42   SymbolizedFrame() : found(false), name(nullptr) { }
43
44   void set(const std::shared_ptr<ElfFile>& file, uintptr_t address);
45   void clear() { *this = SymbolizedFrame(); }
46
47   bool isSignalFrame;
48   bool found;
49   const char* name;
50   Dwarf::LocationInfo location;
51
52   /**
53    * Demangle the name and return it. Not async-signal-safe; allocates memory.
54    */
55   fbstring demangledName() const {
56     return name ? demangle(name) : fbstring();
57   }
58  private:
59   std::shared_ptr<ElfFile> file_;
60 };
61
62 template <size_t N>
63 struct FrameArray {
64   FrameArray() : frameCount(0) { }
65
66   size_t frameCount;
67   uintptr_t addresses[N];
68   SymbolizedFrame frames[N];
69 };
70
71 /**
72  * Get stack trace into a given FrameArray, return true on success (and
73  * set frameCount to the actual frame count, which may be > N) and false
74  * on failure.
75  */
76 namespace detail {
77 template <size_t N>
78 bool fixFrameArray(FrameArray<N>& fa, ssize_t n) {
79   if (n != -1) {
80     fa.frameCount = n;
81     for (size_t i = 0; i < fa.frameCount; ++i) {
82       fa.frames[i].found = false;
83     }
84     return true;
85   } else {
86     fa.frameCount = 0;
87     return false;
88   }
89 }
90 }  // namespace detail
91
92 // Always inline these functions; they don't do much, and unittests rely
93 // on them never showing up in a stack trace.
94 template <size_t N>
95 FOLLY_ALWAYS_INLINE bool getStackTrace(FrameArray<N>& fa);
96
97 template <size_t N>
98 inline bool getStackTrace(FrameArray<N>& fa) {
99   return detail::fixFrameArray(fa, getStackTrace(fa.addresses, N));
100 }
101 template <size_t N>
102 FOLLY_ALWAYS_INLINE bool getStackTraceSafe(FrameArray<N>& fa);
103
104 template <size_t N>
105 inline bool getStackTraceSafe(FrameArray<N>& fa) {
106   return detail::fixFrameArray(fa, getStackTraceSafe(fa.addresses, N));
107 }
108
109 class Symbolizer {
110  public:
111   explicit Symbolizer(ElfCacheBase* cache = nullptr);
112
113   /**
114    * Symbolize given addresses.
115    */
116   void symbolize(const uintptr_t* addresses,
117                  SymbolizedFrame* frames,
118                  size_t frameCount);
119
120   template <size_t N>
121   void symbolize(FrameArray<N>& fa) {
122     symbolize(fa.addresses, fa.frames, fa.frameCount);
123   }
124
125   /**
126    * Shortcut to symbolize one address.
127    */
128   bool symbolize(uintptr_t address, SymbolizedFrame& frame) {
129     symbolize(&address, &frame, 1);
130     return frame.found;
131   }
132
133  private:
134   ElfCacheBase* cache_;
135 };
136
137 /**
138  * Format one address in the way it's usually printer by SymbolizePrinter.
139  * Async-signal-safe.
140  */
141 class AddressFormatter {
142  public:
143   AddressFormatter();
144
145   /**
146    * Format the address. Returns an internal buffer.
147    */
148   StringPiece format(uintptr_t address);
149
150  private:
151   static constexpr char bufTemplate[] = "    @ 0000000000000000";
152   char buf_[sizeof(bufTemplate)];
153 };
154
155 /**
156  * Print a list of symbolized addresses. Base class.
157  */
158 class SymbolizePrinter {
159  public:
160   /**
161    * Print one address, no ending newline.
162    */
163   void print(uintptr_t address, const SymbolizedFrame& frame);
164
165   /**
166    * Print one address with ending newline.
167    */
168   void println(uintptr_t address, const SymbolizedFrame& frame);
169
170   /**
171    * Print multiple addresses on separate lines.
172    */
173   void println(const uintptr_t* addresses,
174                const SymbolizedFrame* frames,
175                size_t frameCount);
176
177   /**
178    * Print a string, no endling newline.
179    */
180   void print(StringPiece sp) { doPrint(sp); }
181
182   /**
183    * Print multiple addresses on separate lines, skipping the first
184    * skip addresses.
185    */
186   template <size_t N>
187   void println(const FrameArray<N>& fa, size_t skip=0) {
188     if (skip < fa.frameCount) {
189       println(fa.addresses + skip, fa.frames + skip, fa.frameCount - skip);
190     }
191   }
192
193   virtual ~SymbolizePrinter() { }
194
195   enum Options {
196     // Skip file and line information
197     NO_FILE_AND_LINE = 1 << 0,
198
199     // As terse as it gets: function name if found, address otherwise
200     TERSE = 1 << 1,
201
202     // Always colorize output (ANSI escape code)
203     COLOR = 1 << 2,
204
205     // Colorize output only if output is printed to a TTY (ANSI escape code)
206     COLOR_IF_TTY = 1 << 3,
207   };
208
209   enum Color { DEFAULT, RED, GREEN, YELLOW, BLUE, CYAN, WHITE, PURPLE };
210   void color(Color c);
211
212  protected:
213   explicit SymbolizePrinter(int options, bool isTty = false)
214     : options_(options),
215       isTty_(isTty) {
216   }
217
218   const int options_;
219   const bool isTty_;
220
221  private:
222   void printTerse(uintptr_t address, const SymbolizedFrame& frame);
223   virtual void doPrint(StringPiece sp) = 0;
224 };
225
226 /**
227  * Print a list of symbolized addresses to a stream.
228  * Not reentrant. Do not use from signal handling code.
229  */
230 class OStreamSymbolizePrinter : public SymbolizePrinter {
231  public:
232   explicit OStreamSymbolizePrinter(std::ostream& out, int options=0);
233  private:
234   void doPrint(StringPiece sp) override;
235   std::ostream& out_;
236 };
237
238 /**
239  * Print a list of symbolized addresses to a file descriptor.
240  * Ignores errors. Async-signal-safe.
241  */
242 class FDSymbolizePrinter : public SymbolizePrinter {
243  public:
244   explicit FDSymbolizePrinter(int fd, int options=0,
245                               size_t bufferSize=0);
246   ~FDSymbolizePrinter();
247   void flush();
248  private:
249   void doPrint(StringPiece sp) override;
250
251   int fd_;
252   std::unique_ptr<IOBuf> buffer_;
253 };
254
255 /**
256  * Print a list of symbolized addresses to a FILE*.
257  * Ignores errors. Not reentrant. Do not use from signal handling code.
258  */
259 class FILESymbolizePrinter : public SymbolizePrinter {
260  public:
261   explicit FILESymbolizePrinter(FILE* file, int options=0);
262  private:
263   void doPrint(StringPiece sp) override;
264   FILE* file_;
265 };
266
267 /**
268  * Print a list of symbolized addresses to a std::string.
269  * Not reentrant. Do not use from signal handling code.
270  */
271 class StringSymbolizePrinter : public SymbolizePrinter {
272  public:
273   explicit StringSymbolizePrinter(int options=0) : SymbolizePrinter(options) { }
274
275   std::string str() const { return buf_.toStdString(); }
276   const fbstring& fbstr() const { return buf_; }
277   fbstring moveFbString() { return std::move(buf_); }
278
279  private:
280   void doPrint(StringPiece sp) override;
281   fbstring buf_;
282 };
283
284 }  // namespace symbolizer
285 }  // namespace folly
286
287 #endif /* FOLLY_EXPERIMENTAL_SYMBOLIZER_SYMBOLIZER_H_ */