Harden failure signal handler in the face of memory corruptions
[folly.git] / folly / experimental / symbolizer / Symbolizer.cpp
index d7f4db96898eca2463630171be651e6bbc8193c2..e2e090adfa11b31ccb71f2320c162c103fec4cf9 100644 (file)
@@ -152,8 +152,18 @@ bool parseProcMapsLine(StringPiece line,
   return true;
 }
 
+ElfCache* defaultElfCache() {
+  static constexpr size_t defaultCapacity = 500;
+  static ElfCache cache(defaultCapacity);
+  return &cache;
+}
+
 }  // namespace
 
+Symbolizer::Symbolizer(ElfCacheBase* cache)
+  : cache_(cache ?: defaultElfCache()) {
+}
+
 void Symbolizer::symbolize(const uintptr_t* addresses,
                            SymbolizedFrame* frames,
                            size_t addressCount) {
@@ -196,7 +206,7 @@ void Symbolizer::symbolize(const uintptr_t* addresses,
     }
 
     bool first = true;
-    ElfFile* elfFile = nullptr;
+    std::shared_ptr<ElfFile> elfFile;
 
     // See if any addresses are here
     for (size_t i = 0; i < addressCount; ++i) {
@@ -218,16 +228,7 @@ void Symbolizer::symbolize(const uintptr_t* addresses,
       // Open the file on first use
       if (first) {
         first = false;
-        if (fileCount_ < kMaxFiles &&
-            !fileName.empty() &&
-            fileName.size() < sizeof(fileNameBuf)) {
-          memcpy(fileNameBuf, fileName.data(), fileName.size());
-          fileNameBuf[fileName.size()] = '\0';
-          auto& f = files_[fileCount_++];
-          if (f.openNoThrow(fileNameBuf) != -1) {
-            elfFile = &f;
-          }
-        }
+        elfFile = cache_->getFile(fileName);
       }
 
       if (!elfFile) {
@@ -245,7 +246,7 @@ void Symbolizer::symbolize(const uintptr_t* addresses,
         frame.name = name;
       }
 
-      Dwarf(elfFile).findAddress(fileAddress, frame.location);
+      Dwarf(elfFile.get()).findAddress(fileAddress, frame.location);
     }
   }
 
@@ -259,6 +260,26 @@ const SymbolizePrinter::Color kFunctionColor = SymbolizePrinter::Color::PURPLE;
 const SymbolizePrinter::Color kFileColor = SymbolizePrinter::Color::DEFAULT;
 }  // namespace
 
+constexpr char AddressFormatter::bufTemplate[];
+
+AddressFormatter::AddressFormatter() {
+  memcpy(buf_, bufTemplate, sizeof(buf_));
+}
+
+folly::StringPiece AddressFormatter::format(uintptr_t address) {
+  // Can't use sprintf, not async-signal-safe
+  static_assert(sizeof(uintptr_t) <= 8, "huge uintptr_t?");
+  char* end = buf_ + sizeof(buf_) - 1 - (16 - 2 * sizeof(uintptr_t));
+  char* p = end;
+  *p-- = '\0';
+  while (address != 0) {
+    *p-- = kHexChars[address & 0xf];
+    address >>= 4;
+  }
+
+  return folly::StringPiece(buf_, end);
+}
+
 void SymbolizePrinter::print(uintptr_t address, const SymbolizedFrame& frame) {
   if (options_ & TERSE) {
     printTerse(address, frame);
@@ -268,20 +289,13 @@ void SymbolizePrinter::print(uintptr_t address, const SymbolizedFrame& frame) {
   SCOPE_EXIT { color(Color::DEFAULT); };
 
   color(kAddressColor);
-  // Can't use sprintf, not async-signal-safe
-  static_assert(sizeof(uintptr_t) <= 8, "huge uintptr_t?");
-  char buf[] = "    @ 0000000000000000";
-  char* end = buf + sizeof(buf) - 1 - (16 - 2 * sizeof(uintptr_t));
+
+  AddressFormatter formatter;
+  doPrint(formatter.format(address));
+
   const char padBuf[] = "                       ";
   folly::StringPiece pad(padBuf,
                          sizeof(padBuf) - 1 - (16 - 2 * sizeof(uintptr_t)));
-  char* p = end;
-  *p-- = '\0';
-  while (address != 0) {
-    *p-- = kHexChars[address & 0xf];
-    address >>= 4;
-  }
-  doPrint(folly::StringPiece(buf, end));
 
   color(kFunctionColor);
   char mangledBuf[1024];