Use StringUtils instead of strrchr, some code cleanup.

This commit is contained in:
hiker 2017-08-21 08:47:28 +10:00
parent 5a35bb6195
commit 6d61ef7fb9
2 changed files with 72 additions and 86 deletions

View File

@ -17,7 +17,10 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "crash_reporting.hpp" #include "crash_reporting.hpp"
#include "log.hpp"
#include "utils/log.hpp"
#include "utils/string_utils.hpp"
#include <string.h> #include <string.h>
#if defined(WIN32) && !defined(DEBUG) && !defined(__MINGW32__) #if defined(WIN32) && !defined(DEBUG) && !defined(__MINGW32__)
@ -161,8 +164,8 @@
// ----- Per-thread handlers ----- // ----- Per-thread handlers -----
// TODO // TODO
} // installHandlers } // installHandlers
// --------------------------------------------------------------------
// --------------------------------------------------------------------
void getCallStackWithContext(std::string& callstack, PCONTEXT pContext) void getCallStackWithContext(std::string& callstack, PCONTEXT pContext)
{ {
HINSTANCE hDbgHelpDll = LoadLibraryA("DbgHelp.dll"); HINSTANCE hDbgHelpDll = LoadLibraryA("DbgHelp.dll");
@ -176,10 +179,12 @@
// Retrieve the DLL functions // Retrieve the DLL functions
#define GET_FUNC_PTR(FuncName) \ #define GET_FUNC_PTR(FuncName) \
t##FuncName _##FuncName = (t##FuncName)GetProcAddress(hDbgHelpDll, #FuncName); \ t##FuncName _##FuncName = (t##FuncName)GetProcAddress(hDbgHelpDll, #FuncName); \
if(!_##FuncName) { \ if(!_##FuncName) \
Log::warn("CrashReporting", "Failed to import symbol " #FuncName " from hDbgHelpDll"); \ { \
FreeLibrary(hDbgHelpDll); \ Log::warn("CrashReporting", "Failed to import symbol " #FuncName \
return; \ " from hDbgHelpDll"); \
FreeLibrary(hDbgHelpDll); \
return; \
} }
GET_FUNC_PTR(SymCleanup) GET_FUNC_PTR(SymCleanup)
@ -192,50 +197,45 @@
GET_FUNC_PTR(UnDecorateSymbolName) GET_FUNC_PTR(UnDecorateSymbolName)
GET_FUNC_PTR(SymFromAddr); GET_FUNC_PTR(SymFromAddr);
GET_FUNC_PTR(StackWalk64); GET_FUNC_PTR(StackWalk64);
#undef GET_FUNC_PTR #undef GET_FUNC_PTR
const HANDLE hProcess = GetCurrentProcess(); const HANDLE hProcess = GetCurrentProcess();
const HANDLE hThread = GetCurrentThread(); const HANDLE hThread = GetCurrentThread();
// Since the stack trace can also be used for leak checks, don't
// initialise this all the time.
static bool first_time = true;
// Initialize the symbol hander for the process // Initialize the symbol hander for the process
if (first_time)
{ {
// Get the file path of the executable // Get the file path of the executable
char filepath[512]; char filepath[512];
GetModuleFileNameA(NULL, filepath, sizeof(filepath)); GetModuleFileNameA(NULL, filepath, sizeof(filepath));
if(!filepath) if (!filepath)
{ {
Log::warn("CrashReporting", "GetModuleFileNameA failed"); Log::warn("CrashReporting", "GetModuleFileNameA failed");
FreeLibrary(hDbgHelpDll); FreeLibrary(hDbgHelpDll);
return; return;
} }
// Only keep the directory // Only keep the directory
char* last_separator = strrchr(filepath, '/'); std::string s(filepath);
if(!last_separator) last_separator = strrchr(filepath, '\\'); std::string path = StringUtils::getPath(s);
if(last_separator)
last_separator[0] = '\0';
// Since the stack trace can also be used for leak checks, don't // Finally initialize the symbol handler.
// initialise this all the time. BOOL bOk = _SymInitialize(hProcess,
static bool first_time = true; path.empty() ? NULL : path.c_str(),
TRUE);
if (first_time) if (!bOk)
{ {
// Finally initialize the symbol handler. Log::warn("CrashReporting", "SymInitialize() failed");
BOOL bOk = _SymInitialize(hProcess, filepath ? filepath : NULL, TRUE); FreeLibrary(hDbgHelpDll);
if (!bOk) return;
{
Log::warn("CrashReporting", "SymInitialize() failed");
FreeLibrary(hDbgHelpDll);
return;
}
_SymSetOptions(SYMOPT_LOAD_LINES);
first_time = false;
} }
}
_SymSetOptions(SYMOPT_LOAD_LINES);
first_time = false;
} // if first_time
// Get the stack trace // Get the stack trace
{ {
@ -263,63 +263,43 @@
const int max_nb_calls = 32; const int max_nb_calls = 32;
for(int i=0 ; i < max_nb_calls ; i++) for(int i=0 ; i < max_nb_calls ; i++)
{ {
const BOOL stackframe_ok = _StackWalk64( machine_type, const BOOL stackframe_ok =
hProcess, _StackWalk64(machine_type, hProcess, hThread,
hThread, &stackframe, pContext, NULL,
&stackframe, _SymFunctionTableAccess64,
pContext, _SymGetModuleBase64, NULL );
NULL, if (!stackframe_ok) break;
_SymFunctionTableAccess64,
_SymGetModuleBase64, // Decode the symbol and add it to the call stack
NULL); DWORD64 sym_displacement;
if(stackframe_ok) char buffer[ sizeof(SYMBOL_INFO) +
MAX_SYM_NAME * sizeof(TCHAR) ];
PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
symbol->MaxNameLen = MAX_SYM_NAME;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
if (!_SymFromAddr(hProcess, stackframe.AddrPC.Offset,
&sym_displacement, symbol))
{ {
// Decode the symbol and add it to the call stack callstack += "\n <no symbol available>";
DWORD64 sym_displacement; continue;
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
symbol->MaxNameLen = MAX_SYM_NAME;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
if(_SymFromAddr(hProcess, stackframe.AddrPC.Offset,
&sym_displacement, symbol) )
{
IMAGEHLP_LINE64 line64;
DWORD dwDisplacement = (DWORD)sym_displacement;
if(_SymGetLineFromAddr64(hProcess, stackframe.AddrPC.Offset, &dwDisplacement, &line64))
{
callstack += "\n ";
// Directory + filename -> filename only
const char* filename = line64.FileName;
const char* ptr = line64.FileName;
while(*ptr)
{
if(*ptr == '\\' || *ptr == '/')
filename = ptr+1;
ptr++;
}
callstack += filename;
callstack += ":";
callstack += symbol->Name;
char str[128];
_itoa(line64.LineNumber, str, 10);
callstack += ":";
callstack += str;
}
else
{
callstack += "\n ";
callstack += symbol->Name;
}
}
else
callstack += "\n <no symbol available>";
} }
IMAGEHLP_LINE64 line64;
DWORD dwDisplacement = (DWORD)sym_displacement;
if (_SymGetLineFromAddr64(hProcess,
stackframe.AddrPC.Offset,
&dwDisplacement, &line64))
{
std::string s(line64.FileName);
callstack += "\n " + StringUtils::getBasename(s)
+ ":" + symbol->Name + ":"
+ StringUtils::toString(line64.LineNumber);
} // if SymGetLineFromAddr64
else else
break; // done {
} callstack += std::string("\n ") + symbol->Name;
} }
} // for i < max_calls
} // get the stack trace
FreeLibrary(hDbgHelpDll); FreeLibrary(hDbgHelpDll);
} // // getCallStackWithContext } // // getCallStackWithContext

View File

@ -21,6 +21,12 @@
#include <string> #include <string>
#include <Windows.h>
#include <DbgHelp.h>
#include <stdlib.h>
#include <signal.h>
#include <new.h>
namespace CrashReporting namespace CrashReporting
{ {
void installHandlers(); void installHandlers();