/*
- * Copyright 2013 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.
#include "folly/experimental/symbolizer/Symbolizer.h"
#include <limits.h>
+#include <cstdio>
+#include <iostream>
+#include <map>
+
+#ifdef __GNUC__
+#include <ext/stdio_filebuf.h>
+#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/experimental/symbolizer/Elf.h"
#include "folly/experimental/symbolizer/Dwarf.h"
#include "folly/experimental/symbolizer/LineReader.h"
+
namespace folly {
namespace symbolizer {
namespace {
const char kHexChars[] = "0123456789abcdef";
+const SymbolizePrinter::Color kAddressColor = SymbolizePrinter::Color::BLUE;
+const SymbolizePrinter::Color kFunctionColor = SymbolizePrinter::Color::PURPLE;
+const SymbolizePrinter::Color kFileColor = SymbolizePrinter::Color::DEFAULT;
} // namespace
void SymbolizePrinter::print(uintptr_t address, const SymbolizedFrame& frame) {
return;
}
+ 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";
}
doPrint(folly::StringPiece(buf, end));
+ color(kFunctionColor);
char mangledBuf[1024];
if (!frame.found) {
doPrint(" (not found)");
}
if (!(options_ & NO_FILE_AND_LINE)) {
+ color(kFileColor);
char fileBuf[PATH_MAX];
fileBuf[0] = '\0';
if (frame.location.hasFileAndLine) {
}
}
+namespace {
+
+const std::map<SymbolizePrinter::Color, std::string> kColorMap = {
+ { SymbolizePrinter::Color::DEFAULT, "\x1B[0m" },
+ { SymbolizePrinter::Color::RED, "\x1B[31m" },
+ { SymbolizePrinter::Color::GREEN, "\x1B[32m" },
+ { SymbolizePrinter::Color::YELLOW, "\x1B[33m" },
+ { SymbolizePrinter::Color::BLUE, "\x1B[34m" },
+ { SymbolizePrinter::Color::CYAN, "\x1B[36m" },
+ { SymbolizePrinter::Color::WHITE, "\x1B[37m" },
+ { SymbolizePrinter::Color::PURPLE, "\x1B[35m" },
+};
+
+}
+
+void SymbolizePrinter::color(SymbolizePrinter::Color color) {
+ if ((options_ & COLOR) == 0 &&
+ ((options_ & COLOR_IF_TTY) == 0 || !isTty_)) {
+ return;
+ }
+ auto it = kColorMap.find(color);
+ if (it == kColorMap.end()) {
+ return;
+ }
+ doPrint(it->second);
+}
+
void SymbolizePrinter::println(uintptr_t address,
const SymbolizedFrame& frame) {
print(address, frame);
memcpy(mangledBuf, frame.name.data(), frame.name.size());
mangledBuf[frame.name.size()] = '\0';
- char demangledBuf[1024];
+ char demangledBuf[1024] = {0};
demangle(mangledBuf, demangledBuf, sizeof(demangledBuf));
- doPrint(demangledBuf);
+ doPrint(strlen(demangledBuf) == 0 ? "(unknown)" : demangledBuf);
} else {
// Can't use sprintf, not async-signal-safe
static_assert(sizeof(uintptr_t) <= 8, "huge uintptr_t?");
}
}
+namespace {
+
+int getFD(const std::ios& stream) {
+#ifdef __GNUC__
+ std::streambuf* buf = stream.rdbuf();
+ using namespace __gnu_cxx;
+
+ {
+ auto sbuf = dynamic_cast<stdio_sync_filebuf<char>*>(buf);
+ if (sbuf) {
+ return fileno(sbuf->file());
+ }
+ }
+ {
+ auto sbuf = dynamic_cast<stdio_filebuf<char>*>(buf);
+ if (sbuf) {
+ return sbuf->fd();
+ }
+ }
+#endif // __GNUC__
+ return -1;
+}
+
+bool isTty(int options, int fd) {
+ return ((options & SymbolizePrinter::TERSE) == 0 &&
+ (options & SymbolizePrinter::COLOR_IF_TTY) != 0 &&
+ fd >= 0 && ::isatty(fd));
+}
+
+} // anonymous namespace
+
+OStreamSymbolizePrinter::OStreamSymbolizePrinter(std::ostream& out, int options)
+ : SymbolizePrinter(options, isTty(options, getFD(out))),
+ out_(out) {
+}
+
void OStreamSymbolizePrinter::doPrint(StringPiece sp) {
out_ << sp;
}
+FDSymbolizePrinter::FDSymbolizePrinter(int fd, int options)
+ : SymbolizePrinter(options, isTty(options, fd)),
+ fd_(fd) {
+}
+
void FDSymbolizePrinter::doPrint(StringPiece sp) {
writeFull(fd_, sp.data(), sp.size());
}
+FILESymbolizePrinter::FILESymbolizePrinter(FILE* file, int options)
+ : SymbolizePrinter(options, isTty(options, fileno(file))),
+ file_(file) {
+}
+
void FILESymbolizePrinter::doPrint(StringPiece sp) {
fwrite(sp.data(), 1, sp.size(), file_);
}
/*
- * Copyright 2013 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.
*/
-
#ifndef FOLLY_EXPERIMENTAL_SYMBOLIZER_SYMBOLIZER_H_
#define FOLLY_EXPERIMENTAL_SYMBOLIZER_SYMBOLIZER_H_
// As terse as it gets: function name if found, address otherwise
TERSE = 1 << 1,
+
+ // Always colorize output (ANSI escape code)
+ COLOR = 1 << 2,
+
+ // Colorize output only if output is printed to a TTY (ANSI escape code)
+ COLOR_IF_TTY = 1 << 3,
};
+ enum Color { DEFAULT, RED, GREEN, YELLOW, BLUE, CYAN, WHITE, PURPLE };
+ void color(Color c);
+
protected:
- explicit SymbolizePrinter(int options) : options_(options) { }
+ explicit SymbolizePrinter(int options, bool isTty = false)
+ : options_(options),
+ isTty_(isTty) {
+ }
+
const int options_;
+ const bool isTty_;
private:
void printTerse(uintptr_t address, const SymbolizedFrame& frame);
*/
class OStreamSymbolizePrinter : public SymbolizePrinter {
public:
- explicit OStreamSymbolizePrinter(std::ostream& out, int options=0)
- : SymbolizePrinter(options),
- out_(out) { }
+ explicit OStreamSymbolizePrinter(std::ostream& out, int options=0);
private:
void doPrint(StringPiece sp) override;
std::ostream& out_;
*/
class FDSymbolizePrinter : public SymbolizePrinter {
public:
- explicit FDSymbolizePrinter(int fd, int options=0)
- : SymbolizePrinter(options),
- fd_(fd) { }
+ explicit FDSymbolizePrinter(int fd, int options=0);
private:
void doPrint(StringPiece sp) override;
int fd_;
*/
class FILESymbolizePrinter : public SymbolizePrinter {
public:
- explicit FILESymbolizePrinter(FILE* file, int options=0)
- : SymbolizePrinter(options),
- file_(file) { }
+ explicit FILESymbolizePrinter(FILE* file, int options=0);
private:
void doPrint(StringPiece sp) override;
FILE* file_;
} // namespace folly
#endif /* FOLLY_EXPERIMENTAL_SYMBOLIZER_SYMBOLIZER_H_ */
-