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/Range.h"
26 #include "folly/experimental/symbolizer/Elf.h"
27 #include "folly/experimental/symbolizer/Dwarf.h"
30 namespace symbolizer {
33 * Frame information: symbol name and location.
35 * Note that both name and location are references in the Symbolizer object,
36 * which must outlive this FrameInfo object.
39 /* implicit */ FrameInfo(uintptr_t a=0, bool sf=false)
47 Dwarf::LocationInfo location;
52 FrameArray() : frameCount(0) { }
59 * Get the current stack trace into addresses, which has room for at least
60 * maxAddresses frames. Skip the first (topmost) skip entries.
62 * Returns the number of frames in the stack trace. Just like snprintf,
63 * if the number of frames is greater than maxAddresses, it will return
64 * the actual number of frames, so the stack trace was truncated iff
65 * the return value > maxAddresses.
67 * Returns -1 on failure.
69 ssize_t getStackTrace(FrameInfo* addresses,
74 * Get stack trace into a given FrameArray, return true on success (and
75 * set frameCount to the actual frame count, which may be > N) and false
79 bool getStackTrace(FrameArray<N>& fa, size_t skip=0) {
80 ssize_t n = getStackTrace(fa.frames, N, skip);
92 Symbolizer() : fileCount_(0) { }
95 * Symbolize given addresses.
97 void symbolize(FrameInfo* addresses, size_t addressCount);
100 void symbolize(FrameArray<N>& fa) {
101 symbolize(fa.frames, std::min(fa.frameCount, N));
105 * Shortcut to symbolize one address.
107 bool symbolize(FrameInfo& address) {
108 symbolize(&address, 1);
109 return address.found;
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 {
125 void print(const FrameInfo& ainfo);
126 void print(const FrameInfo* addresses,
127 size_t addressesSize,
131 void print(const FrameArray<N>& fa) {
132 print(fa.frames, N, fa.frameCount);
135 virtual ~SymbolizePrinter() { }
137 virtual void doPrint(StringPiece sp) = 0;
141 * Print a list of symbolized addresses to a stream.
142 * Not reentrant. Do not use from signal handling code.
144 class OStreamSymbolizePrinter : public SymbolizePrinter {
146 explicit OStreamSymbolizePrinter(std::ostream& out) : out_(out) { }
148 void doPrint(StringPiece sp) override;
153 * Print a list of symbolized addresses to a file descriptor.
154 * Ignores errors. Async-signal-safe.
156 class FDSymbolizePrinter : public SymbolizePrinter {
158 explicit FDSymbolizePrinter(int fd) : fd_(fd) { }
160 void doPrint(StringPiece sp) override;
165 * Print an FrameInfo to a stream. Note that the Symbolizer that
166 * symbolized the address must outlive the FrameInfo. Just like
167 * OStreamSymbolizePrinter (which it uses internally), this is not
168 * reentrant; do not use from signal handling code.
170 std::ostream& operator<<(std::ostream& out, const FrameInfo& ainfo);
172 } // namespace symbolizer
175 #endif /* FOLLY_EXPERIMENTAL_SYMBOLIZER_SYMBOLIZER_H_ */