Do not barf on invalid ELF files
[folly.git] / folly / experimental / symbolizer / Symbolizer.cpp
index ac30db8c7013ad382199804b78212eee6eee5629..535193324fa0fa328838376d7dcef7c8b3508220 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "folly/experimental/symbolizer/Symbolizer.h"
+#include <folly/experimental/symbolizer/Symbolizer.h>
 
 #include <limits.h>
 #include <cstdio>
 #include <ext/stdio_sync_filebuf.h>
 #endif
 
-#include "folly/Conv.h"
-#include "folly/FileUtil.h"
-#include "folly/ScopeGuard.h"
-#include "folly/String.h"
+#include <folly/Conv.h>
+#include <folly/FileUtil.h>
+#include <folly/ScopeGuard.h>
+#include <folly/String.h>
 
-#include "folly/experimental/symbolizer/Elf.h"
-#include "folly/experimental/symbolizer/Dwarf.h"
-#include "folly/experimental/symbolizer/LineReader.h"
+#include <folly/experimental/symbolizer/Elf.h>
+#include <folly/experimental/symbolizer/Dwarf.h>
+#include <folly/experimental/symbolizer/LineReader.h>
 
 
 namespace folly {
@@ -172,10 +172,7 @@ void SymbolizedFrame::set(const std::shared_ptr<ElfFile>& file,
   }
 
   file_ = file;
-  auto name = file->getSymbolName(sym);
-  if (name) {
-    this->name = name;
-  }
+  name = file->getSymbolName(sym);
 
   Dwarf(file.get()).findAddress(address, location);
 }
@@ -306,25 +303,18 @@ void SymbolizePrinter::print(uintptr_t address, const SymbolizedFrame& frame) {
                          sizeof(padBuf) - 1 - (16 - 2 * sizeof(uintptr_t)));
 
   color(kFunctionColor);
-  char mangledBuf[1024];
   if (!frame.found) {
     doPrint(" (not found)");
     return;
   }
 
-  if (frame.name.empty()) {
+  if (!frame.name || frame.name[0] == '\0') {
     doPrint(" (unknown)");
-  } else if (frame.name.size() >= sizeof(mangledBuf)) {
-    doPrint(" ");
-    doPrint(frame.name);
   } else {
-    memcpy(mangledBuf, frame.name.data(), frame.name.size());
-    mangledBuf[frame.name.size()] = '\0';
-
     char demangledBuf[1024];
-    demangle(mangledBuf, demangledBuf, sizeof(demangledBuf));
+    demangle(frame.name, demangledBuf, sizeof(demangledBuf));
     doPrint(" ");
-    doPrint(demangledBuf);
+    doPrint(demangledBuf[0] == '\0' ? frame.name : demangledBuf);
   }
 
   if (!(options_ & NO_FILE_AND_LINE)) {
@@ -392,14 +382,10 @@ void SymbolizePrinter::println(uintptr_t address,
 
 void SymbolizePrinter::printTerse(uintptr_t address,
                                   const SymbolizedFrame& frame) {
-  if (frame.found) {
-    char mangledBuf[1024];
-    memcpy(mangledBuf, frame.name.data(), frame.name.size());
-    mangledBuf[frame.name.size()] = '\0';
-
+  if (frame.found && frame.name && frame.name[0] != '\0') {
     char demangledBuf[1024] = {0};
-    demangle(mangledBuf, demangledBuf, sizeof(demangledBuf));
-    doPrint(strlen(demangledBuf) == 0 ? "(unknown)" : demangledBuf);
+    demangle(frame.name, demangledBuf, sizeof(demangledBuf));
+    doPrint(demangledBuf[0] == '\0' ? frame.name : demangledBuf);
   } else {
     // Can't use sprintf, not async-signal-safe
     static_assert(sizeof(uintptr_t) <= 8, "huge uintptr_t?");
@@ -463,13 +449,35 @@ void OStreamSymbolizePrinter::doPrint(StringPiece sp) {
   out_ << sp;
 }
 
-FDSymbolizePrinter::FDSymbolizePrinter(int fd, int options)
+FDSymbolizePrinter::FDSymbolizePrinter(int fd, int options, size_t bufferSize)
   : SymbolizePrinter(options, isTty(options, fd)),
-    fd_(fd) {
+    fd_(fd),
+    buffer_(bufferSize ? IOBuf::create(bufferSize) : nullptr) {
+}
+
+FDSymbolizePrinter::~FDSymbolizePrinter() {
+  flush();
 }
 
 void FDSymbolizePrinter::doPrint(StringPiece sp) {
-  writeFull(fd_, sp.data(), sp.size());
+  if (buffer_) {
+    if (sp.size() > buffer_->tailroom()) {
+      flush();
+      writeFull(fd_, sp.data(), sp.size());
+    } else {
+      memcpy(buffer_->writableTail(), sp.data(), sp.size());
+      buffer_->append(sp.size());
+    }
+  } else {
+    writeFull(fd_, sp.data(), sp.size());
+  }
+}
+
+void FDSymbolizePrinter::flush() {
+  if (buffer_ && !buffer_->empty()) {
+    writeFull(fd_, buffer_->data(), buffer_->length());
+    buffer_->clear();
+  }
 }
 
 FILESymbolizePrinter::FILESymbolizePrinter(FILE* file, int options)