size_t GetModuleNameFromStack(size_t skip, char* moduleName, size_t size) { void* address = NULL; GetStackFrames(skip + 1, &address, 1); if (address) { return GetModuleNameFromAddress(address, moduleName, size); } return 0; }
size_t GetDescriptionFromAddress(void* address, const char* format, char* buffer, size_t size) { char*const begin = buffer; char*const end = buffer + size; size_t line_number = 0; if (size) { *buffer = 0; } buffer += GetFileLineFromAddress(address, buffer, size, &line_number, NULL); size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer; if (line_number) { char str[128]; wsprintf(str, "(%d) : ", (int)line_number); if (size) { strncpy(buffer, str, size)[size - 1] = 0; } buffer += strlen(str); size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer; } if (size) { strncpy(buffer, "at ", size)[size - 1] = 0; } buffer += strlen("at "); size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer; buffer += GetSymbolNameFromAddress(address, buffer, size, NULL); size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer; if (size) { strncpy(buffer, " in ", size)[size - 1] = 0; } buffer += strlen(" in "); size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer; buffer += GetModuleNameFromAddress(address, buffer, size); return buffer - begin; }
// Get source file name and line number from IP address // The output format is: "sourcefile(linenumber)" or // "modulename!address" or // "address" static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo ) { BOOL ret = FALSE; IMAGEHLP_LINE lineInfo; DWORD dwDisp; TCHAR lpszFileName[BUFFERSIZE] = _T(""); TCHAR lpModuleInfo[BUFFERSIZE] = _T(""); _tcscpy( lpszSourceInfo, _T("?(?)") ); ::ZeroMemory( &lineInfo, sizeof( lineInfo ) ); lineInfo.SizeOfStruct = sizeof( lineInfo ); if ( SymGetLineFromAddr( GetCurrentProcess(), address, &dwDisp, &lineInfo ) ) { // Got it. Let's use "sourcefile(linenumber)" format PCSTR2LPTSTR( lineInfo.FileName, lpszFileName ); TCHAR fname[_MAX_FNAME]; TCHAR ext[_MAX_EXT]; _tsplitpath(lpszFileName, nullptr, nullptr, fname, ext); _stprintf( lpszSourceInfo, _T("%s%s(%d)"), fname, ext, lineInfo.LineNumber ); ret = TRUE; } else { // There is no source file information. :( // Let's use the "modulename!address" format GetModuleNameFromAddress( address, lpModuleInfo ); if ( lpModuleInfo[0] == _T('?') || lpModuleInfo[0] == _T('\0')) // There is no modulename information. :(( // Let's use the "address" format _stprintf( lpszSourceInfo, _T("0x%08X"), address ); else _stprintf( lpszSourceInfo, _T("%s!0x%08X"), lpModuleInfo, address ); ret = FALSE; } return ret; }