/*
- * Copyright 2012 Facebook, Inc.
+ * Copyright 2014 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 ::facebook::symbolizer;
-using namespace __cxxabiv1;
-
+namespace folly {
namespace exception_tracer {
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);
+ ssize_t frameCount = info.frames.size();
+ // Skip our own internal frames
+ static constexpr size_t skip = 3;
+
+ if (frameCount > skip) {
+ auto addresses = info.frames.data() + skip;
+ frameCount -= skip;
+
+ std::vector<SymbolizedFrame> frames;
+ frames.resize(frameCount);
+
+ Symbolizer symbolizer;
+ symbolizer.symbolize(addresses, frames.data(), frameCount);
+
+ OStreamSymbolizePrinter osp(out, SymbolizePrinter::COLOR_IF_TTY);
+ osp.println(addresses, frames.data(), frameCount);
}
} catch (const std::exception& e) {
out << "\n !! caught " << folly::exceptionStr(e) << "\n";
return exceptions;
}
- bool hasTraceStack = false;
- const StackTraceStack* traceStack = nullptr;
+ StackTraceStack* traceStack = nullptr;
if (!getExceptionStackTraceStackFn) {
static bool logged = false;
if (!logged) {
<< "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
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;
}
}
} // namespace exception_tracer
-
+} // namespace folly