fall back to .debug_info scan in fatal signal handler
[folly.git] / folly / experimental / exception_tracer / ExceptionTracer.cpp
index d79eab853522fe4628b7593c6fe9e653f0cae0af..d2ec8f64a6b2d0e22d93def0c413b569c134866f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013 Facebook, Inc.
+ * Copyright 2016 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  */
 
-
-#include "folly/experimental/exception_tracer/ExceptionTracer.h"
+#include <folly/experimental/exception_tracer/ExceptionTracer.h>
 
 #include <dlfcn.h>
 #include <exception>
+#include <iostream>
 #include <glog/logging.h>
 
-#include "folly/experimental/exception_tracer/ExceptionAbi.h"
-#include "folly/experimental/exception_tracer/StackTrace.h"
-#include "folly/experimental/symbolizer/Symbolizer.h"
-#include "folly/String.h"
+#include <folly/experimental/exception_tracer/ExceptionAbi.h>
+#include <folly/experimental/exception_tracer/StackTrace.h>
+#include <folly/experimental/symbolizer/Symbolizer.h>
+#include <folly/String.h>
 
 namespace {
 
+using namespace ::folly::exception_tracer;
+using namespace ::folly::symbolizer;
+using namespace __cxxabiv1;
+
 extern "C" {
-const StackTraceStack* getExceptionStackTraceStack(void) __attribute__((weak));
-typedef const StackTraceStack* (*GetExceptionStackTraceStackType)(void);
+StackTraceStack* getExceptionStackTraceStack(void) __attribute__((__weak__));
+typedef StackTraceStack* (*GetExceptionStackTraceStackType)(void);
 GetExceptionStackTraceStackType getExceptionStackTraceStackFn;
 }
 
 }  // namespace
 
-using namespace ::folly::symbolizer;
-using namespace __cxxabiv1;
-
 namespace folly {
 namespace exception_tracer {
 
 std::ostream& operator<<(std::ostream& out, const ExceptionInfo& info) {
+  printExceptionInfo(out, info, SymbolizePrinter::COLOR_IF_TTY);
+  return out;
+}
+
+void printExceptionInfo(
+    std::ostream& out,
+    const ExceptionInfo& info,
+    int options) {
   out << "Exception type: ";
   if (info.type) {
     out << folly::demangle(*info.type);
@@ -53,21 +62,31 @@ std::ostream& operator<<(std::ostream& out, const ExceptionInfo& info) {
       << (info.frames.size() == 1 ? " frame" : " frames")
       << ")\n";
   try {
-    Symbolizer symbolizer;
-    folly::StringPiece symbolName;
-    Dwarf::LocationInfo location;
-    for (auto ip : info.frames) {
-      // Symbolize the previous address because the IP might be in the
-      // next function, per glog/src/signalhandler.cc
-      symbolizer.symbolize(ip-1, symbolName, location);
-      Symbolizer::write(out, ip, symbolName, location);
+    size_t frameCount = info.frames.size();
+
+    // Skip our own internal frames
+    static constexpr size_t kInternalFramesNumber = 3;
+    if (frameCount > kInternalFramesNumber) {
+      auto addresses = info.frames.data() + kInternalFramesNumber;
+      frameCount -= kInternalFramesNumber;
+
+      std::vector<SymbolizedFrame> frames;
+      frames.resize(frameCount);
+
+      Symbolizer symbolizer(
+          (options & SymbolizePrinter::NO_FILE_AND_LINE)
+              ? Dwarf::LocationInfoMode::DISABLED
+              : Symbolizer::kDefaultLocationInfoMode);
+      symbolizer.symbolize(addresses, frames.data(), frameCount);
+
+      OStreamSymbolizePrinter osp(out, options);
+      osp.println(addresses, frames.data(), frameCount);
     }
   } catch (const std::exception& e) {
     out << "\n !! caught " << folly::exceptionStr(e) << "\n";
   } catch (...) {
     out << "\n !!! caught unexpected exception\n";
   }
-  return out;
 }
 
 namespace {
@@ -113,8 +132,7 @@ std::vector<ExceptionInfo> getCurrentExceptions() {
     return exceptions;
   }
 
-  bool hasTraceStack = false;
-  const StackTraceStack* traceStack = nullptr;
+  StackTraceStack* traceStack = nullptr;
   if (!getExceptionStackTraceStackFn) {
     static bool logged = false;
     if (!logged) {
@@ -129,10 +147,9 @@ std::vector<ExceptionInfo> getCurrentExceptions() {
         << "Exception stack trace invalid, stack traces not available";
       logged = true;
     }
-  } else {
-    hasTraceStack = true;
   }
 
+  StackTrace* trace = traceStack ? traceStack->top() : nullptr;
   while (currentException) {
     ExceptionInfo info;
     // Dependent exceptions (thrown via std::rethrow_exception) aren't
@@ -143,18 +160,16 @@ std::vector<ExceptionInfo> getCurrentExceptions() {
       isAbiCppException(currentException) ?
       currentException->exceptionType :
       nullptr;
-    if (hasTraceStack) {
-      CHECK(traceStack) << "Invalid trace stack!";
-      info.frames.assign(
-          traceStack->trace.frameIPs,
-          traceStack->trace.frameIPs + traceStack->trace.frameCount);
-      traceStack = traceStack->next;
+    if (traceStack) {
+      CHECK(trace) << "Invalid trace stack!";
+      info.frames.assign(trace->addresses,
+                         trace->addresses + trace->frameCount);
+      trace = traceStack->next(trace);
     }
     currentException = currentException->nextException;
     exceptions.push_back(std::move(info));
   }
-
-  CHECK(!traceStack) << "Invalid trace stack!";
+  CHECK(!trace) << "Invalid trace stack!";
 
   return exceptions;
 }
@@ -200,4 +215,3 @@ void installHandlers() {
 
 }  // namespace exception_tracer
 }  // namespace folly
-