Add the debug header to the function-common print debugging on Windows

Source: Internet
Author: User
Tags strtok

I used this tool on two common platforms: vs2008 and vc6.0, and found that vc6.0 does not support the _ function _ macro, which is implemented here by a user-defined _ function.

Pay attention to the following issues:

1. An error is reported in the MFC environment:

① # Error windows. h already embedded. MFC APPs must not # include <windows. h>. The helpless solution is to add the debugging header file # include statement automatically added to the header file related to afx.

② Unexpected endif: You need to add the stafx. h pre-compiled header file, and then remove # If defined (_ Debug) & defined (win32) and the corresponding # endif in xtrace. cpp.

2. errors reported in the Unicode environment:

Add forced conversion


The final xtrace. cpp file code is as follows:

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * xtrace.cpp by Hector J. Rivas, torjo2k@hotmail.com from "ExtendedTrace" * by Zoltan Csizmadia, zoltan_csizmadia@yahoo.com *  * A Win32 VC++ 6.0 implementation of the __FUNCTION__ macro that works for me. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */#include "StdAfx.h"#include <stdio.h>#include <windows.h>#include <tchar.h>#include <ImageHlp.h>#include "xtrace.h"// Unicode safe char* -> TCHAR* conversionvoid PCSTR2LPTSTR(PCSTR lpszIn, LPTSTR lpszOut){#if defined(UNICODE) || defined(_UNICODE)ULONG index = 0; PCSTR lpAct = lpszIn;for(;; lpAct++){lpszOut[index++] = (TCHAR)(*lpAct);if (*lpAct == 0) break;} #elsestrcpy(lpszOut, lpszIn);#endif}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * InitSymPath(): figure  out  the  path for the symbol files; the search path is: * * . + *__FILE__ (path) + Debug + * %_NT_SYMBOL_PATH% + * %_NT_ALTERNATE_SYMBOL_PATH% + * %SYSTEMROOT% + * %SYSTEMROOT%\System32 + * lpszIniPath * * NOTES: There is no size check for lpszSymbolPath. If you want to limit the macro to * symbols in your debug executable, you can omit the environment variables (default). * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */void InitSymPath(PSTR lpszSymbolPath, PCSTR lpszIniPath, BOOL bSysPath){CHAR lpszPath[BUFFERSIZE] = "";CHAR lpszTemp[BUFFERSIZE] = "";// create the default pathstrcpy(lpszSymbolPath, ".;");// get the current pathsprintf(lpszTemp, __FILE__);strcpy(lpszPath, strrev(strchr(strrev(lpszTemp), '\\')));strcat(lpszPath, "Debug");strcat(lpszSymbolPath, lpszPath);if (bSysPath){// environment variable _NT_SYMBOL_PATHif (GetEnvironmentVariableA("_NT_SYMBOL_PATH", lpszPath, BUFFERSIZE)){strcat(lpszSymbolPath, ";");strcat(lpszSymbolPath, lpszPath);}// environment variable _NT_ALTERNATE_SYMBOL_PATHif (GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", lpszPath, BUFFERSIZE)){strcat(lpszSymbolPath, ";");strcat(lpszSymbolPath, lpszPath);}// environment variable SYSTEMROOTif (GetEnvironmentVariableA("SYSTEMROOT", lpszPath, BUFFERSIZE)){strcat(lpszSymbolPath, ";");strcat(lpszSymbolPath, lpszPath);// SYSTEMROOT\System32strcat(lpszSymbolPath, ";");strcat(lpszSymbolPath, lpszPath);strcat(lpszSymbolPath, "\\System32");}}// Add any user defined pathif (lpszIniPath != NULL){if (lpszIniPath[0] != '\0'){strcat(lpszSymbolPath, ";");strcat(lpszSymbolPath, lpszIniPath);}}}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * InitSymInfo(): initializes the symbol files * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */BOOL InitSymInfo(PCSTR lpszInitialSymbolPath, BOOL bSysPath){CHARlpszSymbolPath[BUFFERSIZE];DWORDsymOptions = SymGetOptions();// set current image help API options; according to the SDK docs, with// SYMOPT_DEFERRED_LOADS: "Symbols are not loaded until a reference is made// requiring the symbols be loaded. This is the fastest, most efficient way to use// the symbol handler.". SYMOPT_UNDNAME is excluded to do the undecoration// ourselves.symOptions |= SYMOPT_DEFERRED_LOADS; symOptions &= ~SYMOPT_UNDNAME;SymSetOptions(symOptions);// get the search path for the symbol filesInitSymPath(lpszSymbolPath, lpszInitialSymbolPath, bSysPath);return SymInitialize(GetCurrentProcess(), lpszSymbolPath, TRUE);}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * GetFuncInfo(): Get function prototype from address and stack address * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */BOOL GetFuncInfo(ULONG fnAddress, ULONG stackAddress, LPTSTR lpszSymbol){BOOL ret = FALSE;DWORD dwDisp = 0, dwSymSize = 10000;TCHAR lpszUDSymbol[BUFFERSIZE] = _T("?");CHAR lpszANSIUDSymbol[BUFFERSIZE] = "?";PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc(GMEM_FIXED, dwSymSize);ZeroMemory(pSym, dwSymSize);pSym->SizeOfStruct  = dwSymSize;pSym->MaxNameLength = dwSymSize - sizeof(IMAGEHLP_SYMBOL);// Set the default to unknown_tcscpy(lpszSymbol, _T("?"));// Get symbol infoif (SymGetSymFromAddr(GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym)){// Make the symbol readable for humansUnDecorateSymbolName(pSym->Name, lpszANSIUDSymbol, BUFFERSIZE, UNDNAME_COMPLETE  | UNDNAME_NO_THISTYPE  | UNDNAME_NO_SPECIAL_SYMS  | UNDNAME_NO_MEMBER_TYPE  | UNDNAME_NO_MS_KEYWORDS  | UNDNAME_NO_ACCESS_SPECIFIERS | UNDNAME_NO_ARGUMENTS);// Symbol information is ANSI stringPCSTR2LPTSTR(lpszANSIUDSymbol, lpszUDSymbol);lpszSymbol[0] = _T('\0');_tcscat(lpszSymbol, lpszUDSymbol);   ret = TRUE;}GlobalFree(pSym);return ret;}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * GetFuncName(): return the undecorated function name * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */LPCTSTR GetFuncName(){BOOL           bResult = FALSE;STACKFRAME     callStack;CONTEXT        context;TCHAR          lpszFnInfo[BUFFERSIZE];HANDLE         hProcess = GetCurrentProcess();HANDLE         hThread  = GetCurrentThread();// initialize a context struct to retrieve processor-specific register dataZeroMemory(&context, sizeof(context));context.ContextFlags = CONTEXT_FULL;if (!GetThreadContext(hThread, &context))return L"";// initialize a stack frame struct in preparation to walk the stackZeroMemory(&callStack, sizeof(callStack));callStack.AddrPC.Offset    = context.Eip;callStack.AddrStack.Offset = context.Esp;callStack.AddrFrame.Offset = context.Ebp;callStack.AddrPC.Mode      = AddrModeFlat;callStack.AddrStack.Mode   = AddrModeFlat;callStack.AddrFrame.Mode   = AddrModeFlat;// obtain a stack trace of the calling function (i.e., omit this one)for (ULONG n = 0; n < 2; n++) {bResult = StackWalk(IMAGE_FILE_MACHINE_I386,hProcess,hThread,&callStack,NULL,NULL,SymFunctionTableAccess,SymGetModuleBase,NULL);}if (bResult && callStack.AddrFrame.Offset != 0) {GetFuncInfo(callStack.AddrPC.Offset, callStack.AddrFrame.Offset, lpszFnInfo);// from now on its all personal display preferences with string manipulation// tokenize the undecorated returned symbol to omit the class nameCHAR* lpszToken = strtok((char *)lpszFnInfo, "::");CHAR  lpszLast[BUFFERSIZE] = "";while (lpszToken != NULL){strcpy(lpszLast, lpszToken);lpszToken = strtok(NULL, "::");}// append a delimiter, so that our display in printf instructions is // 'functionname: message' for debug builds and 'message' for release builds,// using the format string "%smessage" and __FUNCTION__ as an argumentstrcat(lpszLast, ": ");return (const unsigned short *)lpszLast;}return L"";}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * KillSymInfo(): uninitialize the loaded symbol files * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */BOOL KillSymInfo() { return SymCleanup(GetCurrentProcess()); }

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.