Codemod: use #include angle brackets in folly and thrift
[folly.git] / folly / experimental / symbolizer / Symbolizer.h
index c9341f4f9a169be491b88352894cc83741b0e71b..d3b0f03a1eaa7824791ad7275ab0819cdc60b99b 100644 (file)
 #include <string>
 #include <unordered_map>
 
-#include "folly/FBString.h"
-#include "folly/Range.h"
-#include "folly/experimental/symbolizer/Elf.h"
-#include "folly/experimental/symbolizer/Dwarf.h"
-#include "folly/experimental/symbolizer/StackTrace.h"
+#include <folly/FBString.h>
+#include <folly/Range.h>
+#include <folly/String.h>
+#include <folly/io/IOBuf.h>
+#include <folly/experimental/symbolizer/Elf.h>
+#include <folly/experimental/symbolizer/ElfCache.h>
+#include <folly/experimental/symbolizer/Dwarf.h>
+#include <folly/experimental/symbolizer/StackTrace.h>
 
 namespace folly {
 namespace symbolizer {
 
+class Symbolizer;
+
 /**
  * Frame information: symbol name and location.
- *
- * Note that both name and location are references in the Symbolizer object,
- * which must outlive this SymbolizedFrame object.
  */
 struct SymbolizedFrame {
-  SymbolizedFrame() : found(false) { }
+  SymbolizedFrame() : found(false), name(nullptr) { }
+
+  void set(const std::shared_ptr<ElfFile>& file, uintptr_t address);
+  void clear() { *this = SymbolizedFrame(); }
+
   bool isSignalFrame;
   bool found;
-  StringPiece name;
+  const char* name;
   Dwarf::LocationInfo location;
+
+  /**
+   * Demangle the name and return it. Not async-signal-safe; allocates memory.
+   */
+  fbstring demangledName() const {
+    return name ? demangle(name) : fbstring();
+  }
+ private:
+  std::shared_ptr<ElfFile> file_;
 };
 
 template <size_t N>
@@ -77,14 +92,14 @@ bool fixFrameArray(FrameArray<N>& fa, ssize_t n) {
 // Always inline these functions; they don't do much, and unittests rely
 // on them never showing up in a stack trace.
 template <size_t N>
-inline bool getStackTrace(FrameArray<N>& fa) __attribute__((always_inline));
+FOLLY_ALWAYS_INLINE bool getStackTrace(FrameArray<N>& fa);
 
 template <size_t N>
 inline bool getStackTrace(FrameArray<N>& fa) {
   return detail::fixFrameArray(fa, getStackTrace(fa.addresses, N));
 }
 template <size_t N>
-inline bool getStackTraceSafe(FrameArray<N>& fa) __attribute__((always_inline));
+FOLLY_ALWAYS_INLINE bool getStackTraceSafe(FrameArray<N>& fa);
 
 template <size_t N>
 inline bool getStackTraceSafe(FrameArray<N>& fa) {
@@ -93,7 +108,7 @@ inline bool getStackTraceSafe(FrameArray<N>& fa) {
 
 class Symbolizer {
  public:
-  Symbolizer() : fileCount_(0) { }
+  explicit Symbolizer(ElfCacheBase* cache = nullptr);
 
   /**
    * Symbolize given addresses.
@@ -116,11 +131,25 @@ class Symbolizer {
   }
 
  private:
-  // We can't allocate memory, so we'll preallocate room.
-  // "1023 shared libraries should be enough for everyone"
-  static constexpr size_t kMaxFiles = 1024;
-  size_t fileCount_;
-  ElfFile files_[kMaxFiles];
+  ElfCacheBase* cache_;
+};
+
+/**
+ * Format one address in the way it's usually printer by SymbolizePrinter.
+ * Async-signal-safe.
+ */
+class AddressFormatter {
+ public:
+  AddressFormatter();
+
+  /**
+   * Format the address. Returns an internal buffer.
+   */
+  StringPiece format(uintptr_t address);
+
+ private:
+  static constexpr char bufTemplate[] = "    @ 0000000000000000";
+  char buf_[sizeof(bufTemplate)];
 };
 
 /**
@@ -145,6 +174,11 @@ class SymbolizePrinter {
                const SymbolizedFrame* frames,
                size_t frameCount);
 
+  /**
+   * Print a string, no endling newline.
+   */
+  void print(StringPiece sp) { doPrint(sp); }
+
   /**
    * Print multiple addresses on separate lines, skipping the first
    * skip addresses.
@@ -207,10 +241,15 @@ class OStreamSymbolizePrinter : public SymbolizePrinter {
  */
 class FDSymbolizePrinter : public SymbolizePrinter {
  public:
-  explicit FDSymbolizePrinter(int fd, int options=0);
+  explicit FDSymbolizePrinter(int fd, int options=0,
+                              size_t bufferSize=0);
+  ~FDSymbolizePrinter();
+  void flush();
  private:
   void doPrint(StringPiece sp) override;
+
   int fd_;
+  std::unique_ptr<IOBuf> buffer_;
 };
 
 /**