2 * Copyright 2013 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #ifndef FOLLY_EXPERIMENTAL_SYMBOLIZER_SYMBOLIZER_H_
19 #define FOLLY_EXPERIMENTAL_SYMBOLIZER_SYMBOLIZER_H_
23 #include <unordered_map>
25 #include "folly/FBString.h"
26 #include "folly/Range.h"
27 #include "folly/experimental/symbolizer/Elf.h"
28 #include "folly/experimental/symbolizer/Dwarf.h"
29 #include "folly/experimental/symbolizer/StackTrace.h"
32 namespace symbolizer {
35 * Frame information: symbol name and location.
37 * Note that both name and location are references in the Symbolizer object,
38 * which must outlive this SymbolizedFrame object.
40 struct SymbolizedFrame {
41 SymbolizedFrame() : found(false) { }
45 Dwarf::LocationInfo location;
50 FrameArray() : frameCount(0) { }
53 uintptr_t addresses[N];
54 SymbolizedFrame frames[N];
58 * Get stack trace into a given FrameArray, return true on success (and
59 * set frameCount to the actual frame count, which may be > N) and false
64 bool fixFrameArray(FrameArray<N>& fa, ssize_t n) {
67 for (size_t i = 0; i < fa.frameCount; ++i) {
68 fa.frames[i].found = false;
79 bool getStackTrace(FrameArray<N>& fa) {
80 return detail::fixFrameArray(fa, getStackTrace(fa.addresses, N));
84 bool getStackTraceSafe(FrameArray<N>& fa) {
85 return detail::fixFrameArray(fa, getStackTraceSafe(fa.addresses, N));
90 Symbolizer() : fileCount_(0) { }
93 * Symbolize given addresses.
95 void symbolize(const uintptr_t* addresses,
96 SymbolizedFrame* frames,
100 void symbolize(FrameArray<N>& fa) {
101 symbolize(fa.addresses, fa.frames, fa.frameCount);
105 * Shortcut to symbolize one address.
107 bool symbolize(uintptr_t address, SymbolizedFrame& frame) {
108 symbolize(&address, &frame, 1);
113 // We can't allocate memory, so we'll preallocate room.
114 // "1023 shared libraries should be enough for everyone"
115 static constexpr size_t kMaxFiles = 1024;
117 ElfFile files_[kMaxFiles];
121 * Print a list of symbolized addresses. Base class.
123 class SymbolizePrinter {
126 * Print one address, no ending newline.
128 void print(uintptr_t address, const SymbolizedFrame& frame);
131 * Print one address with ending newline.
133 void println(uintptr_t address, const SymbolizedFrame& frame);
136 * Print multiple addresses on separate lines.
138 void println(const uintptr_t* addresses,
139 const SymbolizedFrame* frames,
143 * Print multiple addresses on separate lines, skipping the first
147 void println(const FrameArray<N>& fa, size_t skip=0) {
148 if (skip < fa.frameCount) {
149 println(fa.addresses + skip, fa.frames + skip, fa.frameCount - skip);
153 virtual ~SymbolizePrinter() { }
156 // Skip file and line information
157 NO_FILE_AND_LINE = 1 << 0,
159 // As terse as it gets: function name if found, address otherwise
164 explicit SymbolizePrinter(int options) : options_(options) { }
168 void printTerse(uintptr_t address, const SymbolizedFrame& frame);
169 virtual void doPrint(StringPiece sp) = 0;
173 * Print a list of symbolized addresses to a stream.
174 * Not reentrant. Do not use from signal handling code.
176 class OStreamSymbolizePrinter : public SymbolizePrinter {
178 explicit OStreamSymbolizePrinter(std::ostream& out, int options=0)
179 : SymbolizePrinter(options),
182 void doPrint(StringPiece sp) override;
187 * Print a list of symbolized addresses to a file descriptor.
188 * Ignores errors. Async-signal-safe.
190 class FDSymbolizePrinter : public SymbolizePrinter {
192 explicit FDSymbolizePrinter(int fd, int options=0)
193 : SymbolizePrinter(options),
196 void doPrint(StringPiece sp) override;
201 * Print a list of symbolized addresses to a FILE*.
202 * Ignores errors. Not reentrant. Do not use from signal handling code.
204 class FILESymbolizePrinter : public SymbolizePrinter {
206 explicit FILESymbolizePrinter(FILE* file, int options=0)
207 : SymbolizePrinter(options),
210 void doPrint(StringPiece sp) override;
215 * Print a list of symbolized addresses to a std::string.
216 * Not reentrant. Do not use from signal handling code.
218 class StringSymbolizePrinter : public SymbolizePrinter {
220 explicit StringSymbolizePrinter(int options=0) : SymbolizePrinter(options) { }
222 std::string str() const { return buf_.toStdString(); }
223 const fbstring& fbstr() const { return buf_; }
224 fbstring moveFbString() { return std::move(buf_); }
227 void doPrint(StringPiece sp) override;
231 } // namespace symbolizer
234 #endif /* FOLLY_EXPERIMENTAL_SYMBOLIZER_SYMBOLIZER_H_ */