From 5c761256265b1ec48d02c462212d1238ddc0d6e2 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Fri, 19 Jun 2015 03:25:18 +0300 Subject: add call stacks to errors --- cxx/include/aesnixx/debug.hpp | 123 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 cxx/include/aesnixx/debug.hpp (limited to 'cxx/include/aesnixx/debug.hpp') diff --git a/cxx/include/aesnixx/debug.hpp b/cxx/include/aesnixx/debug.hpp new file mode 100644 index 0000000..f87942d --- /dev/null +++ b/cxx/include/aesnixx/debug.hpp @@ -0,0 +1,123 @@ +/** + * \file + * \author Egor Tensin + * \date 2015 + * \copyright This file is licensed under the terms of the MIT License. + * See LICENSE.txt for details. + */ + +#pragma once + +#ifdef WIN32 +#include +#include +#pragma comment(lib, "dbghelp.lib") +#endif + +#include + +#include +#include + +namespace aesni +{ + namespace aux + { + class CallStackFormatter + { + public: + CallStackFormatter() + { + #ifdef WIN32 + m_valid = SymInitialize(GetCurrentProcess(), NULL, TRUE) ? true : false; + #endif + } + + std::string format(void* addr) const + { + #ifdef WIN32 + if (!m_valid) + return format_fallback(addr); + + DWORD64 symbol_info_buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; + PSYMBOL_INFO symbol_info = (PSYMBOL_INFO) symbol_info_buf; + symbol_info->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol_info->MaxNameLen = MAX_SYM_NAME; + + IMAGEHLP_MODULE64 module_info; + module_info.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); + + DWORD64 displacement_within_symbol; + + if (!SymFromAddr(GetCurrentProcess(), reinterpret_cast(addr), &displacement_within_symbol, symbol_info)) + { + if (!SymGetModuleInfo64(GetCurrentProcess(), reinterpret_cast(addr), &module_info)) + return format_fallback(addr); + + void* const displacement_within_module = reinterpret_cast(addr) - module_info.BaseOfImage; + return format_with_module(module_info.ModuleName, displacement_within_module); + } + + if (!SymGetModuleInfo64(GetCurrentProcess(), symbol_info->ModBase, &module_info)) + return format_with_symbol(symbol_info->Name, addr); + + return format_with_symbol_and_module(symbol_info->Name, module_info.ModuleName, reinterpret_cast(displacement_within_symbol)); + #else + return format_fallback(addr); + #endif + } + + ~CallStackFormatter() + { + #ifdef WIN32 + if (m_valid) + SymCleanup(GetCurrentProcess()); + #endif + } + + private: + template + static std::string put_between_brackets(const T& x) + { + std::ostringstream oss; + oss << "[" << x << "]"; + return oss.str(); + } + + template + static std::string stringify(const T& x) + { + std::ostringstream oss; + oss << x; + return oss.str(); + } + + std::string format_fallback(void* addr) const + { + return put_between_brackets(addr); + } + + std::string format_with_module(const std::string& module_name, void* displacement) const + { + if (displacement == NULL) + return put_between_brackets(module_name); + else + return put_between_brackets(module_name + "+" + stringify(displacement)); + } + + std::string format_with_symbol(const std::string& symbol_name, void* displacement) const + { + return format_with_module(symbol_name, displacement); + } + + std::string format_with_symbol_and_module(const std::string& symbol_name, const std::string& module_name, void* displacement) const + { + return format_with_symbol(module_name + "!" + symbol_name, displacement); + } + + #ifdef WIN32 + bool m_valid = false; + #endif + }; + } +} -- cgit v1.2.3