Exemplo n.º 1
0
size_t GetSymbolNameFromAddress(void* address, char* symbolName, size_t size,
                                size_t* offsetBytes)
{
    if (size) *symbolName = 0;
    if (offsetBytes) *offsetBytes = 0;
    __try {
        ULONG_ADDR dwOffset = 0;
        union {
            IMAGEHLP_SYMBOL sym;
            char symNameBuffer[sizeof(IMAGEHLP_SYMBOL) + MAX_SYM_NAME];
        } u;
        u.sym.SizeOfStruct  = sizeof(u.sym);
        u.sym.MaxNameLength = sizeof(u.symNameBuffer) - sizeof(u.sym);

        if (!SymGetSymFromAddr(GetSymHandle(), CheckAddress(address), &dwOffset,
                               &u.sym)) {
            return 0;
        } else {
            const char* sourceName = u.sym.Name;
            char undName[1024];
            if (UnDecorateSymbolName(u.sym.Name, undName, sizeof(undName),
                                     UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS)) {
                sourceName = undName;
            } else if (SymUnDName(&u.sym, undName, sizeof(undName))) {
                sourceName = undName;
            }
            if (offsetBytes) {
                *offsetBytes = dwOffset;
            }
            if (size) {
                strncpy(symbolName, sourceName, size)[size - 1] = 0;
            }
            return strlen(sourceName);
        }
    } __except (EXCEPTION_EXECUTE_HANDLER) {
        SetLastError(GetExceptionCode());
    }
    return 0;
}
Exemplo n.º 2
0
void GetFunctionInfo(DWORD64 dw64Address, FILE * fw) {
	DWORD64 dw64Displacement = 0;

    char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
    PSYMBOL_INFO pSym = (PSYMBOL_INFO)buffer;

    pSym->SizeOfStruct = sizeof(SYMBOL_INFO);
    pSym->MaxNameLen = MAX_SYM_NAME;

	if(SymFromAddr(GetCurrentProcess(), dw64Address, &dw64Displacement, pSym) == TRUE) {
        // We have decorated name, try to make it readable
        if(UnDecorateSymbolName(pSym->Name, sDebugBuf, 512, UNDNAME_COMPLETE | UNDNAME_NO_THISTYPE | UNDNAME_NO_SPECIAL_SYMS | UNDNAME_NO_MEMBER_TYPE |
            UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS) > 0) {
            // We have readable name, write it
            fprintf(fw, "%s\n", sDebugBuf);
            return;
        }
	}

    // We don't found any info, write '?'
    fprintf(fw, "?\n");
}
Exemplo n.º 3
0
GCallStack::GCallStack(HANDLE hThread, CONTEXT& c)
{
	if (!_bLockInit) // only init the single instance of the CRITICAL_SECTION 1 time for the many instances of GCallStack
	{
		InitializeCriticalSection(&_DbgHelpLock);
		_bLockInit = true;
	}

	DWORD imageType = IMAGE_FILE_MACHINE_I386;
	HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
	int frameNum = 0; // counts walked frames
	int MAX_STACK_FRAMES = 7777; // in C# the maximum stack frames imposed by the language is 1000.  Arbitrary limit to guarantee no condition of infinate walking in corrupted memory.
	DWORD offsetFromLine; // tells us line number in the source file
#if defined(_LINUX64) || defined(_WIN64) || defined(_IOS)
	unsigned __int64 offsetFromSymbol; // tells us how far from the symbol we were
#else
	DWORD offsetFromSymbol; // tells us how far from the symbol we were
#endif

	DWORD symOptions; // symbol handler settings
	IMAGEHLP_SYMBOL *pSym = (IMAGEHLP_SYMBOL *) malloc( IMGSYMLEN + MAXNAMELEN );

	GString strStackName(MAXNAMELEN + 512); // undecorated method/function name + Source file and line number

	IMAGEHLP_MODULE Module;
	IMAGEHLP_LINE Line;
	STACKFRAME64 s; // in/out stackframe
	memset( &s, '\0', sizeof s );

//  note: converted code from [std::string symSearchPath] to [GString symSearchPath] so it will compile with the _UNICODE build flag - 8/18/2014
	GString symSearchPath;

#ifdef _UNICODE
	wchar_t *tt = 0, *p;
	tt = new wchar_t[TTBUFLEN];
#else
	char *tt = 0, *p;
	tt = new char[TTBUFLEN];
#endif

	// build symbol search path from:
	symSearchPath = "";
	// current directory
	if (GetCurrentDirectory(TTBUFLEN, tt))
		symSearchPath << tt << "; ";
	// dir with executable
	if ( GetModuleFileName( 0, tt, TTBUFLEN ) )
	{
#ifdef _UNICODE
		for (p = tt + wcslen(tt) - 1; p >= tt; --p)
#else
		for (p = tt + strlen(tt) - 1; p >= tt; --p)	// VC6 does not have a _tcsclen() and we still support VC6
#endif
		{
			// locate the rightmost path separator
			if ( *p == '\\' || *p == '/' || *p == ':' )
				break;
		}
		// if we found one, p is pointing at it; if not, tt only contains an exe name (no path), and p points before its first byte
		if ( p != tt ) // path sep found?
		{
			if ( *p == ':' ) // we leave colons in place
				++ p;
			*p = '\0'; // eliminate the exe name and last path sep
			symSearchPath << tt << "; "; 
		}
	}
	// environment variable _NT_SYMBOL_PATH
	GString g("_NT_SYMBOL_PATH");
	if (GetEnvironmentVariable(g, tt, TTBUFLEN))
		symSearchPath << tt << "; ";
	// environment variable _NT_ALTERNATE_SYMBOL_PATH
	g = "_NT_ALTERNATE_SYMBOL_PATH";
	if (GetEnvironmentVariable(g, tt, TTBUFLEN))
		symSearchPath << tt << "; ";
	// environment variable SYSTEMROOT
	g = "SYSTEMROOT";
	if (GetEnvironmentVariable(g, tt, TTBUFLEN))
		symSearchPath << tt << "; ";

	if ( symSearchPath.size() > 0 ) // if we added anything, we have a trailing semicolon
		symSearchPath = symSearchPath.substr( 0, symSearchPath.size() - 1 );

	// 8/20/2014 note: In older Windows API's SymInitialize()'s 2nd argument was not defined as "const char *", it was only "char *" 
	// Although "const" was not defined, the API call is "const" in behavior.  In newer versions of the Windows API this has been fixed.
	// In newer versions - SymInitialize's 2nd argument may resolve to either "const char *" OR "const wchar_t *", and in those builds the
	// GString has a default conversion to the correct string type, however in the older build configurations, GString does not (and should not)
	// know how to resolve to a "char *" by default, so in that case the preprocessor directive isolates the code needed to convert to "char *" 

#if defined(_MSC_VER) && _MSC_VER <= 1200
	if (!SymInitialize(hProcess, symSearchPath.Buf(),	false))	// symSearchPath == (char *)
#else
	if (!SymInitialize(hProcess, symSearchPath,			true))  // symSearchPath == (const char *)  --OR--  (const wchar_t *) depending on the _UNICODE preprocessor definition
#endif
	{
		goto tagCleanUp;
	}

	symOptions = SymGetOptions();
	symOptions |= SYMOPT_LOAD_LINES;
	symOptions &= ~SYMOPT_UNDNAME;
	SymSetOptions( symOptions );

	enumAndLoadModuleSymbols( hProcess, GetCurrentProcessId() );

	// init STACKFRAME for first call, definitions found in ImageHlp.h
#ifdef _M_IX86
	imageType = IMAGE_FILE_MACHINE_I386;
	s.AddrPC.Offset = c.Eip;
	s.AddrPC.Mode = AddrModeFlat;
	s.AddrFrame.Offset = c.Ebp;
	s.AddrFrame.Mode = AddrModeFlat;
	s.AddrStack.Offset = c.Esp;
	s.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
	imageType = IMAGE_FILE_MACHINE_AMD64;
	s.AddrPC.Offset = c.Rip;
	s.AddrPC.Mode = AddrModeFlat;
	s.AddrFrame.Offset = c.Rsp;
	s.AddrFrame.Mode = AddrModeFlat;
	s.AddrStack.Offset = c.Rsp;
	s.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
	imageType = IMAGE_FILE_MACHINE_IA64;
	s.AddrPC.Offset = c.StIIP;
	s.AddrPC.Mode = AddrModeFlat;
	s.AddrFrame.Offset = c.IntSp;
	s.AddrFrame.Mode = AddrModeFlat;
	s.AddrBStore.Offset = c.RsBSP;
	s.AddrBStore.Mode = AddrModeFlat;
	s.AddrStack.Offset = c.IntSp;
	s.AddrStack.Mode = AddrModeFlat;
#endif

	memset( pSym, '\0', IMGSYMLEN + MAXNAMELEN );
	pSym->SizeOfStruct = IMGSYMLEN;
	pSym->MaxNameLength = MAXNAMELEN;

	memset( &Line, '\0', sizeof Line );
	Line.SizeOfStruct = sizeof Line;

	memset( &Module, '\0', sizeof Module );
	Module.SizeOfStruct = sizeof Module;

	offsetFromSymbol = 0;

	
	//	DbgHelp is single threaded, so acquire a lock.
	EnterCriticalSection(&_DbgHelpLock);

	while ( frameNum < MAX_STACK_FRAMES )
	{
		// get next stack frame (StackWalk(), SymFunctionTableAccess(), SymGetModuleBase())
		// if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can
		// assume that either you are done, or that the stack is so hosed that the next deeper frame could not be found.
#ifdef _WIN64
		if (!StackWalk64(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
#else
		if (!StackWalk(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL))
#endif
			break;  // Maybe it failed, maybe we have finished walking the stack

		if ( s.AddrPC.Offset != 0 )
		{ 
			// Most likely a valid stack rame
			
			// show procedure info 
			if ( ! SymGetSymFromAddr64( hProcess, s.AddrPC.Offset, &offsetFromSymbol, pSym ) )
			{
				break;
			}
			else
			{
				// UnDecorateSymbolName() to get the Class::Method or function() name in tyhe callstack
				strStackName.Empty();
 				UnDecorateSymbolName(pSym->Name, strStackName._str, MAXNAMELEN, UNDNAME_COMPLETE);
				strStackName.SetLength(strlen(strStackName._str));

				// SymGetLineFromAddr() to get the source.cpp and the line number 
				IMAGEHLP_LINE64 Line;
				if (SymGetLineFromAddr64(hProcess, s.AddrPC.Offset, &offsetFromLine, &Line) != FALSE)
				{
					GString g(Line.FileName);  // Line.FileName conains the "c:\Full\Path\TO\Source.cpp"
					
					// Builds string "Foo::Bar[Source.cpp]@777"
					strStackName << "[" << g.StartingAt(g.ReverseFind("\\") + 1) << "]@" << Line.LineNumber; 
				}

				// add the GString to the GStringList, do not add frame 0 because it will always be GException::GSeception where we divided by 0
				if (frameNum > 0)
					_stk += strStackName;
			}
		}
		else
		{
			// base reached
			SetLastError(0);
			break;
		}

		++frameNum;
	}
	
	LeaveCriticalSection(&_DbgHelpLock);


	// de-init symbol handler etc. (SymCleanup())
	SymCleanup( hProcess );
	free( pSym );
tagCleanUp:;	
	delete [] tt;
	CloseHandle(hProcess);
}
Exemplo n.º 4
0
/**
 * Loads the elements of the call stack in a list
 * @param exceptionInfos are useful information on the exception
 */
void LoadCallStack(EXCEPTION_POINTERS* exceptionInfos, HANDLE &hProcess, std::list<std::string> &callStack,
                   std::list<std::string> &fileStack)
{
    STACKFRAME64 tempStackFrame;
    CONTEXT context = *(exceptionInfos->ContextRecord);
    memset( &tempStackFrame, 0, sizeof(STACKFRAME64) );
    DWORD machineType;

#ifdef _M_IX86
    machineType                     = IMAGE_FILE_MACHINE_I386;
    tempStackFrame.AddrPC.Offset    = context.Eip;
    tempStackFrame.AddrPC.Mode      = AddrModeFlat;
    tempStackFrame.AddrStack.Offset = context.Esp;
    tempStackFrame.AddrStack.Mode   = AddrModeFlat;
    tempStackFrame.AddrFrame.Offset = context.Ebp;
    tempStackFrame.AddrFrame.Mode   = AddrModeFlat;
#elif _M_X64
    machineType                     = IMAGE_FILE_MACHINE_AMD64;
    tempStackFrame.AddrPC.Offset    = context.Rip;
    tempStackFrame.AddrPC.Mode      = AddrModeFlat;
    tempStackFrame.AddrFrame.Offset = context.Rsp;
    tempStackFrame.AddrFrame.Mode   = AddrModeFlat;
    tempStackFrame.AddrStack.Offset = context.Rsp;
    tempStackFrame.AddrStack.Mode   = AddrModeFlat;
#elif _M_IA64
    machineType                      = IMAGE_FILE_MACHINE_IA64;
    tempStackFrame.AddrPC.Offset     = context.StIIP;
    tempStackFrame.AddrPC.Mode       = AddrModeFlat;
    tempStackFrame.AddrFrame.Offset  = context.IntSp;
    tempStackFrame.AddrFrame.Mode    = AddrModeFlat;
    tempStackFrame.AddrBStore.Offset = context.RsBSP;
    tempStackFrame.AddrBStore.Mode   = AddrModeFlat;
    tempStackFrame.AddrStack.Offset  = context.IntSp;
    tempStackFrame.AddrStack.Mode    = AddrModeFlat;
#else
#error "Platform not supported!"
#endif

    ULONG64 buffer[(sizeof(SYMBOL_INFO) + nbChar*sizeof(TCHAR) + sizeof(ULONG64) + 1) / sizeof(ULONG64)];
    PSYMBOL_INFO pSymbol = reinterpret_cast<PSYMBOL_INFO>(buffer);
    PSTR undecoratedName = (PSTR)malloc(sizeof(TCHAR) * nbChar);

    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    pSymbol->MaxNameLen   = nbChar;
    DWORD lineDisplacement;
    IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) };

    while(StackWalk64(machineType, hProcess, GetCurrentThread(), &tempStackFrame, &context, NULL,
                      SymFunctionTableAccess64, SymGetModuleBase64, NULL))
    {
        // Sanity stack check
        if(tempStackFrame.AddrPC.Offset == 0)
        {
            break;
        }

        DWORD64 symDisplacement = 0;
        // Try to get the symbol name
        if(SymFromAddr(hProcess, tempStackFrame.AddrPC.Offset, &symDisplacement, pSymbol))
        {
            UnDecorateSymbolName(pSymbol->Name, undecoratedName, MAX_SYM_NAME, UNDNAME_COMPLETE);
            callStack.push_back(std::string((char*)undecoratedName) + "+" +
                                ::boost::lexical_cast<std::string>(symDisplacement));

            if(SymGetLineFromAddr64(hProcess, tempStackFrame.AddrPC.Offset, &lineDisplacement, &lineInfo))
            {
                fileStack.push_back(std::string(lineInfo.FileName) + "\tl:" +
                                    ::boost::lexical_cast<std::string>(lineInfo.LineNumber));
            }
            else
            {
                fileStack.push_back("No info");
            }
        }
        else
        {
        }
    }
    free(undecoratedName);
}
Exemplo n.º 5
0
//----------------------------------------------------------------------------//
static void dumpBacktrace(size_t frames)
{
#if defined(_DEBUG) || defined(DEBUG)
#if defined(_MSC_VER)
    SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES);

    if (!SymInitialize(GetCurrentProcess(), 0, TRUE))
        return;

    HANDLE thread = GetCurrentThread();

    CONTEXT context;
    RtlCaptureContext(&context);

    STACKFRAME64 stackframe;
    ZeroMemory(&stackframe, sizeof(stackframe));
    stackframe.AddrPC.Mode = AddrModeFlat;
    stackframe.AddrStack.Mode = AddrModeFlat;
    stackframe.AddrFrame.Mode = AddrModeFlat;

#if _M_IX86
    stackframe.AddrPC.Offset = context.Eip;
    stackframe.AddrStack.Offset = context.Esp;
    stackframe.AddrFrame.Offset = context.Ebp;
    DWORD machine_arch = IMAGE_FILE_MACHINE_I386;
#elif _M_X64
    stackframe.AddrPC.Offset = context.Rip;
    stackframe.AddrStack.Offset = context.Rsp;
    stackframe.AddrFrame.Offset = context.Rbp;
    DWORD machine_arch = IMAGE_FILE_MACHINE_AMD64;
#endif

    char symbol_buffer[1024];
    ZeroMemory(symbol_buffer, sizeof(symbol_buffer));
    PSYMBOL_INFO symbol = reinterpret_cast<PSYMBOL_INFO>(symbol_buffer);
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    symbol->MaxNameLen = sizeof(symbol_buffer) - sizeof(SYMBOL_INFO);

    Logger& logger(Logger::getSingleton());
    logger.logEvent("========== Start of Backtrace ==========", Errors);

    size_t frame_no = 0;
    while (StackWalk64(machine_arch, GetCurrentProcess(), thread, &stackframe,
                       &context, 0, SymFunctionTableAccess64, SymGetModuleBase64, 0) &&
           stackframe.AddrPC.Offset)
    {
        symbol->Address = stackframe.AddrPC.Offset;
        DWORD64 displacement = 0;
        char signature[256];

        if (SymFromAddr(GetCurrentProcess(), symbol->Address, &displacement, symbol))
            UnDecorateSymbolName(symbol->Name, signature, sizeof(signature), UNDNAME_COMPLETE);
        else
            sprintf_s(signature, sizeof(signature), "%p", symbol->Address);
 
        IMAGEHLP_MODULE64 modinfo;
        modinfo.SizeOfStruct = sizeof(modinfo);

        const BOOL have_image_name =
            SymGetModuleInfo64(GetCurrentProcess(), symbol->Address, &modinfo);

        char outstr[512];
        sprintf_s(outstr, sizeof(outstr), "#%d %s +%#llx (%s)",
                  frame_no, signature, displacement,
                  (have_image_name ? modinfo.LoadedImageName : "????"));

        logger.logEvent(outstr, Errors);

        if (++frame_no >= frames)
            break;

        if (!stackframe.AddrReturn.Offset)
            break;
    }

    logger.logEvent("==========  End of Backtrace  ==========", Errors);

    SymCleanup(GetCurrentProcess());
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__HAIKU__)
    void* buffer[frames];
    const int received = backtrace(&buffer[0], frames);

    Logger& logger(Logger::getSingleton());

    logger.logEvent("========== Start of Backtrace ==========", Errors);

    for (int i = 0; i < received; ++i)
    {
        char outstr[512];
        Dl_info info;
        if (dladdr(buffer[i], &info))
        {
            if (!info.dli_sname)
                snprintf(outstr, 512, "#%d %p (%s)", i, buffer[i], info.dli_fname);
            else
            {
                ptrdiff_t offset = static_cast<char*>(buffer[i]) -
                                   static_cast<char*>(info.dli_saddr);

                int demangle_result = 0;
                char* demangle_name = abi::__cxa_demangle(info.dli_sname, 0, 0, &demangle_result);
                snprintf(outstr, 512, "#%d %s +%#tx (%s)",
                         i, demangle_name ? demangle_name : info.dli_sname, offset, info.dli_fname);
                std::free(demangle_name);
            }
        }
        else
            snprintf(outstr, 512, "#%d --- error ---", i);

        logger.logEvent(outstr, Errors);
    }

    logger.logEvent("==========  End of Backtrace  ==========", Errors);
#endif
#endif
}
Exemplo n.º 6
0
static BOOL ResolveSymbol(HANDLE hProcess, DWORD dwAddress,
	SYMBOL_INFO &siSymbol)
{
	BOOL fRetval = TRUE;

	siSymbol.dwAddress = dwAddress;

	union {
		CHAR rgchSymbol[sizeof(IMAGEHLP_SYMBOL) + 255];
		IMAGEHLP_SYMBOL  sym;
	};

	CHAR szUndec[256];
	CHAR szWithOffset[256];
	LPSTR pszSymbol = NULL;
	IMAGEHLP_MODULE mi;

	memset(&siSymbol, 0, sizeof(SYMBOL_INFO));
	mi.SizeOfStruct = sizeof(IMAGEHLP_MODULE);

	if (!SymGetModuleInfo(hProcess, dwAddress, &mi))
		lstrcpyA(siSymbol.szModule, "<no module>");
	else
	{
		LPSTR pszModule = strchr(mi.ImageName, '\\');
		if (pszModule == NULL)
			pszModule = mi.ImageName;
		else
			pszModule++;

		lstrcpynA(siSymbol.szModule, pszModule, _countof(siSymbol.szModule));
	   lstrcatA(siSymbol.szModule, "! ");
	}

	__try
	{
		sym.SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
		sym.Address = dwAddress;
		sym.MaxNameLength = 255;

		if (SymGetSymFromAddr(hProcess, dwAddress, &(siSymbol.dwOffset), &sym))
		{
			pszSymbol = sym.Name;

			if (UnDecorateSymbolName(sym.Name, szUndec, _countof(szUndec),
				UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS))
			{
				pszSymbol = szUndec;
			}
			else if (SymUnDName(&sym, szUndec, _countof(szUndec)))
			{
				pszSymbol = szUndec;
			}

			if (siSymbol.dwOffset != 0)
			{
				wsprintfA(szWithOffset, "%s + %d bytes", pszSymbol, siSymbol.dwOffset);
				pszSymbol = szWithOffset;
			}
	  }
	  else
		  pszSymbol = "<no symbol>";
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		pszSymbol = "<EX: no symbol>";
		siSymbol.dwOffset = dwAddress - mi.BaseOfImage;
	}

	lstrcpynA(siSymbol.szSymbol, pszSymbol, _countof(siSymbol.szSymbol));
	return fRetval;
}
Exemplo n.º 7
0
int
main(int argc, char **argv)
{
    BOOL bRet;
    DWORD dwRet;
    bool debug = false;
    char *szModule = nullptr;
    bool functions = false;
    bool demangle = false;
    bool pretty = false;

    while (1) {
        int opt = getopt(argc, argv, "?CDe:fHp");

        switch (opt) {
        case 'C':
            demangle = true;
            break;
        case 'D':
            debug = true;
            break;
        case 'e':
            szModule = optarg;
            break;
        case 'f':
            functions = true;
            break;
        case 'H':
            usage(argv[0]);
            return EXIT_SUCCESS;
        case 'p':
            pretty = true;
            break;
        case '?':
            fprintf(stderr, "error: invalid option `%c`\n", optopt);
            /* pass-through */
        default:
            usage(argv[0]);
            return EXIT_FAILURE;
        case -1:
            break;
        }
        if (opt == -1) {
            break;
        }
    }

    if (szModule == nullptr) {
        usage(argv[0]);
        return EXIT_FAILURE;
    }

    // Load the module
    HMODULE hModule = nullptr;
#ifdef _WIN64
    hModule = LoadLibraryExA(szModule, NULL, LOAD_LIBRARY_AS_DATAFILE);
#endif
    if (!hModule) {
        hModule = LoadLibraryExA(szModule, NULL, DONT_RESOLVE_DLL_REFERENCES);
    }
    if (!hModule) {
        fprintf(stderr, "error: failed to load %s\n", szModule);
        return EXIT_FAILURE;
    }

    DWORD dwSymOptions = SymGetOptions();

    dwSymOptions |= SYMOPT_LOAD_LINES;

#ifndef NDEBUG
    dwSymOptions |= SYMOPT_DEBUG;
#endif

    // We can get more information by calling UnDecorateSymbolName() ourselves.
    dwSymOptions &= ~SYMOPT_UNDNAME;
    
    SymSetOptions(dwSymOptions);

    HANDLE hProcess = GetCurrentProcess();
    bRet = InitializeSym(hProcess, FALSE);
    assert(bRet);

    if (debug) {
        SymRegisterCallback64(hProcess, &callback, 0);
    }

    dwRet = SymLoadModuleEx(hProcess, NULL, szModule, NULL, (DWORD64)(UINT_PTR)hModule, 0, NULL, 0);
    if (!dwRet) {
        fprintf(stderr, "warning: failed to load module symbols\n");
    }

    if (!GetModuleHandleA("symsrv.dll")) {
        fprintf(stderr, "warning: symbol server not loaded\n");
    }

    while (optind < argc) {
        const char *arg = argv[optind++];

        DWORD64 dwRelAddr;
        if (arg[0] == '0' && arg[1] == 'x') {
            sscanf(&arg[2], "%08" PRIX64, &dwRelAddr);
        } else {
            dwRelAddr = atol(arg);
        }

        UINT_PTR dwAddr = (UINT_PTR)hModule + dwRelAddr;

        if (functions) {
            struct {
                SYMBOL_INFO Symbol;
                CHAR Name[512];
            } sym;
            char UnDecoratedName[512];
            const char *function = "??";
            ZeroMemory(&sym, sizeof sym);
            sym.Symbol.SizeOfStruct = sizeof sym.Symbol;
            sym.Symbol.MaxNameLen = sizeof sym.Symbol.Name + sizeof sym.Name;
            DWORD64 dwSymDisplacement = 0;
            bRet = SymFromAddr(hProcess, dwAddr, &dwSymDisplacement, &sym.Symbol);
            if (bRet) {
                function = sym.Symbol.Name;
                if (demangle) {
                    if (UnDecorateSymbolName( sym.Symbol.Name, UnDecoratedName, sizeof UnDecoratedName, UNDNAME_COMPLETE)) {
                        function = UnDecoratedName;
                    }
                }
            }
            fputs(function, stdout);
            fputs(pretty ? " at " : "\n", stdout);
        }

        IMAGEHLP_LINE64 line;
        ZeroMemory(&line, sizeof line);
        line.SizeOfStruct = sizeof line;
        DWORD dwLineDisplacement = 0;
        bRet = SymGetLineFromAddr64(hProcess, dwAddr, &dwLineDisplacement, &line);
        if (bRet) {
            fprintf(stdout, "%s:%lu\n", line.FileName, line.LineNumber);
        } else {
            fputs("??:?\n", stdout);
        }
        fflush(stdout);
    }


    SymCleanup(hProcess);


    FreeLibrary(hModule);


    return 0;
}
Exemplo n.º 8
0
void CDebugMgr::RecordException(PEXCEPTION_POINTERS pExceptionInfo)
{
    PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
    // First print information about the type of fault
    m_pchBuffer += wsprintf(m_pchBuffer,  "Exception code: %08X\n",
		pExceptionRecord->ExceptionCode);
    // Now print information about where the fault occured
    TCHAR szFaultingModule[MAX_PATH];    DWORD section, offset;
    FindLogicalAddress(  pExceptionRecord->ExceptionAddress,
                        szFaultingModule,
                        sizeof( szFaultingModule ),
                        section, offset );
    m_pchBuffer += wsprintf(m_pchBuffer,"Fault address:  %08X %02X:%08X %s",
              pExceptionRecord->ExceptionAddress,
              section, offset, szFaultingModule );

	TCHAR szMap[MAX_PATH] = "";
	wsprintf(szMap, szFaultingModule);
	wsprintf(&szMap[lstrlen(szMap)-3], "MAP");
	TCHAR szSymbol[256] = "<unknown>";
	TCHAR szUnmangledSymbol[1024] = "<unknown>";
	TCHAR szObject[128] = "<unknown>";

	if ( m_dwOptions & DEBUGMGR_RESOLVESYMBOLS )
	{
		if ( FindSymbol(szMap, section, offset, szSymbol, szObject) )
		{
			if ( m_dwOptions & DEBUGMGR_UNMANGLESYMBOLS && *szSymbol == '?' )
			{
				UnDecorateSymbolName(szSymbol, szUnmangledSymbol, 1024, UNDNAME_COMPLETE);
			}
			else
			{
				wsprintf(szUnmangledSymbol, szSymbol);
			}

			m_pchBuffer += wsprintf(m_pchBuffer, " in function %s in object file %s", szUnmangledSymbol, szObject);

			if ( m_dwOptions & DEBUGMGR_RESOLVESOURCELINE )
			{
				TCHAR szSource[256];
				TCHAR szLine[256];

				if ( FindSourceLine(szMap, szObject, section, offset, szSource, szLine) )
				{
					m_pchBuffer += wsprintf(m_pchBuffer, " at Line %s of %s\n", szLine, szSource);
				}
				else
				{
					m_pchBuffer += wsprintf(m_pchBuffer, " at Line ??? of ???\n");
				}
			}
			else
			{
				m_pchBuffer += wsprintf(m_pchBuffer, "\n\n");
			}
		}
		else
		{
			m_pchBuffer += wsprintf(m_pchBuffer, "\n");
		}
	}
	else
	{
		m_pchBuffer += wsprintf(m_pchBuffer, "\n");
	}

    PCONTEXT pCtx = pExceptionInfo->ContextRecord;    // Show the registers
    m_pchBuffer += wsprintf(m_pchBuffer, "EAX:%08X\nEBX:%08X\nECX:%08X\nEDX:%08X\nESI:%08X\nEDI:%08X\n",
             pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx, pCtx->Esi, pCtx->Edi );
    m_pchBuffer += wsprintf(m_pchBuffer,"CS:EIP:%04X:%08X\n", pCtx->SegCs, pCtx->Eip );
    m_pchBuffer += wsprintf(m_pchBuffer,"SS:ESP:%04X:%08X  EBP:%08X\n",
              pCtx->SegSs, pCtx->Esp, pCtx->Ebp );
    m_pchBuffer += wsprintf(m_pchBuffer,"DS:%04X  ES:%04X  FS:%04X  GS:%04X\n",
              pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs );
    m_pchBuffer += wsprintf(m_pchBuffer,"Flags:%08X\n", pCtx->EFlags );
}
Exemplo n.º 9
0
/**
 stdcall:
   * C Naming - Name prefixed by a '_', followed by the name, then an '@',
     followed by number of bytes in arguments.  
     i.e. foo(int a, double b) = _foo@12
   * C++ Naming - __stdcall
   * Args - Arguments are passed on the stack.
   * Cleanup - Callee cleans up the stack before returning
 cdecl:
   * C Naming - Name prefixed by a '_'
   * C++ Naming - __cdecl in demangled name
   * Args - Arguments are passed on the stack.
   * Cleanup - Caller cleans up the stack after the return
 fastcall:
   * C Naming - Name prefixed by a '@', followed by the func name, then 
     another '@', followed by the number of bytes in the arguments.  i.e.
     foo(double a, int b, int c, int d) = @foo@20
   * C++ Naming - __fastcall in the mangled name
   * Args - First two arguments that are less than DWORD size are passed in ECX & EDX
   * Cleanup - Callee cleans up the stack before returning
 thiscall:
   * C Naming - NA
   * C++ Naming - __thiscall in the demangled name
   * 'this' parameter is passed in ECX, others are passed in the stack
   * Cleanup Callee cleans up the stack before returning
 **/
callType func_instance::getCallingConvention() {
	std::cerr << "symtab name (c++): " << symTabName() << std::endl;
    //const char *name = symTabName().c_str();
    const int buffer_size = 1024;
    char buffer[buffer_size];
    int pos;

    if (callingConv != unknown_call)
        return callingConv;

    if (symTabName().empty()) {
		assert(0);
        //Umm...
        return unknown_call;
    }
    switch(symTabName()[0]) {
        case '?':
            //C++ Encoded symbol. Everything is stored in the C++ name 
            // mangling scheme
            UnDecorateSymbolName(symTabName().c_str(), buffer, buffer_size, 
                UNDNAME_NO_ARGUMENTS | UNDNAME_NO_FUNCTION_RETURNS);
			printf("undecorated name: %s\n", buffer);
            if (strstr(buffer, "__thiscall")) {
                callingConv = thiscall_call;
                return callingConv;
            }
            if (strstr(buffer, "__fastcall")) {
                callingConv = fastcall_call;
                return callingConv;
            }
            if (strstr(buffer, "__stdcall")) {
                callingConv = stdcall_call;
                return callingConv;
            }
            if (strstr(buffer, "__cdecl")) {
                callingConv = cdecl_call;
                return callingConv;
            }
            break;
        case '_':
          //Check for stdcall or cdecl
          pos = symTabName().find('@');
          if (pos != std::string::npos) {
            callingConv = stdcall_call;
            return callingConv;
          }
          else {
            callingConv = cdecl_call;
            return callingConv;
          }
          break;
        case '@':
          //Should be a fast call
          pos = symTabName().find('@');
          if (pos != std::string::npos) {
             callingConv = fastcall_call;
             return callingConv;
          }
          break;
    }

    //We have no idea what this call is.  We probably got an undecorated
    // name.  If the function doesn't clean up it's own stack (doesn't 
    // have a ret #) instruction, then it must be a cdecl call, as that's
    // the only type that doesn't clean its own stack.
    //If the function is part of a class, then it's most likely a thiscall,
    // although that could be incorrect for a static function.  
    //Otherwise let's guess that it's a stdcall.
    if (!ifunc()->cleansOwnStack()) {
        callingConv = cdecl_call;
    }
    else if (symTabName().find("::") != std::string::npos) {
        callingConv = thiscall_call;
    }
    else {
        callingConv = stdcall_call;
    }
    return callingConv;
}
Exemplo n.º 10
0
void mrpt::system::getCallStackBackTrace(TCallStackBackTrace& out_bt)
{
	out_bt.backtrace_levels.clear();
	const unsigned int framesToSkip =
		1;  // skip *this* function from the backtrace
	const unsigned int framesToCapture = 64;

#ifdef _WIN32
	void* backTrace[framesToCapture]{};

	SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
	const HANDLE hProcess = GetCurrentProcess();
	if (!SymInitialize(
			hProcess, nullptr /* UserSearchPath  */, TRUE /*fInvadeProcess*/))
	{
		std::cerr
			<< "[mrpt::system::getCallStackBackTrace] Error in SymInitialize()!"
			<< std::endl;
		return;
	}

	char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
	PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
	pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
	pSymbol->MaxNameLen = MAX_SYM_NAME;

	const USHORT nFrames = CaptureStackBackTrace(
		framesToSkip, framesToCapture, backTrace, nullptr);
	for (unsigned int i = 0; i < nFrames; i++)
	{
		TCallStackEntry cse;
		cse.address = backTrace[i];

		if (!SymFromAddr(hProcess, (DWORD64)cse.address, nullptr, pSymbol))
		{
			cse.symbolName = "???";
			cse.symbolNameOriginal = "???";
			out_bt.backtrace_levels.emplace_back(cse);
			continue;
		}
		SYMBOL_INFO& si = *pSymbol;

		cse.symbolNameOriginal = si.Name;
		char undecorated_name[1024];
		if (!UnDecorateSymbolName(
				si.Name, undecorated_name, sizeof(undecorated_name),
				UNDNAME_COMPLETE))
		{
			cse.symbolName = cse.symbolNameOriginal;
		}
		else
		{
			cse.symbolName = std::string(undecorated_name);
		}

		out_bt.backtrace_levels.emplace_back(cse);
	}
#else
	// Based on: https://gist.github.com/fmela/591333
	void* callstack[framesToCapture];
	const int nMaxFrames = sizeof(callstack) / sizeof(callstack[0]);
	int nFrames = ::backtrace(callstack, nMaxFrames);
	char** symbols = ::backtrace_symbols(callstack, nFrames);

	for (int i = (int)framesToSkip; i < nFrames; i++)
	{
		TCallStackEntry cse;
		cse.address = callstack[i];

		Dl_info info;
		if (dladdr(callstack[i], &info) && info.dli_sname)
		{
			char* demangled = nullptr;
			int status = -1;
			if (info.dli_sname[0] == '_')
			{
				demangled = abi::__cxa_demangle(
					info.dli_sname, nullptr, nullptr, &status);
			}
			cse.symbolNameOriginal =
				info.dli_sname == nullptr ? symbols[i] : info.dli_sname;
			cse.symbolName =
				status == 0 ? std::string(demangled) : cse.symbolNameOriginal;
			free(demangled);
		}
		out_bt.backtrace_levels.emplace_back(cse);
	}
	free(symbols);
#endif
}
Exemplo n.º 11
0
void write_stack_trace(PCONTEXT pContext, TextOutputStream& outputStream)
{
  HANDLE m_hProcess = GetCurrentProcess();
  DWORD dwMachineType = 0;

  CONTEXT context = *pContext;

  // Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag
  if ( !SymInitialize( m_hProcess, (PSTR)environment_get_app_path(), TRUE ) )
  {
    return;
  }

  STACKFRAME sf;
  memset( &sf, 0, sizeof(sf) );

#ifdef _M_IX86
  // Initialize the STACKFRAME structure for the first call.  This is only
  // necessary for Intel CPUs, and isn't mentioned in the documentation.
  sf.AddrPC.Offset       = context.Eip;
  sf.AddrPC.Mode         = AddrModeFlat;
  sf.AddrStack.Offset    = context.Esp;
  sf.AddrStack.Mode      = AddrModeFlat;
  sf.AddrFrame.Offset    = context.Ebp;
  sf.AddrFrame.Mode      = AddrModeFlat;

  dwMachineType = IMAGE_FILE_MACHINE_I386;
#endif

  while ( 1 )
  {
    // Get the next stack frame
    if ( ! StackWalk(  dwMachineType,
                        m_hProcess,
                        GetCurrentThread(),
                        &sf,
                        &context,
                        0,
                        SymFunctionTableAccess,
                        SymGetModuleBase,
                        0 ) )
        break;

    if ( 0 == sf.AddrFrame.Offset ) // Basic sanity check to make sure
      break;                      // the frame is OK.  Bail if not.

    // Get the name of the function for this stack frame entry
    BYTE symbolBuffer[ sizeof(SYMBOL_INFO) + MAX_SYM_NAME ];
    PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    pSymbol->MaxNameLen = MAX_SYM_NAME;
                    
    DWORD64 symDisplacement = 0;    // Displacement of the input address,
                                    // relative to the start of the symbol

    IMAGEHLP_MODULE module = { sizeof(IMAGEHLP_MODULE) };
    if(SymGetModuleInfo(m_hProcess, sf.AddrPC.Offset, &module))
    {
      outputStream << module.ModuleName << "!";

      if ( SymFromAddr(m_hProcess, sf.AddrPC.Offset, &symDisplacement, pSymbol))
      {
        char undecoratedName[MAX_SYM_NAME];
        UnDecorateSymbolName(pSymbol->Name, undecoratedName, MAX_SYM_NAME, UNDNAME_COMPLETE);

        outputStream << undecoratedName;

        outputStream << "(";
        // Use SymSetContext to get just the locals/params for this frame
        IMAGEHLP_STACK_FRAME imagehlpStackFrame;
        imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset;
        SymSetContext( m_hProcess, &imagehlpStackFrame, 0 );

        // Enumerate the locals/parameters
        EnumerateSymbolsContext context(sf, outputStream);
        SymEnumSymbols( m_hProcess, 0, 0, EnumerateSymbolsCallback, &context );
        outputStream << ")";

        outputStream << " + " << Offset(reinterpret_cast<void*>(symDisplacement));

        // Get the source line for this stack frame entry
        IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
        DWORD dwLineDisplacement;
        if ( SymGetLineFromAddr( m_hProcess, sf.AddrPC.Offset,
                                &dwLineDisplacement, &lineInfo ) )
        {
          outputStream << " " << lineInfo.FileName << " line " << Unsigned(lineInfo.LineNumber); 
        }
      }
      else
      {
        outputStream << Address(reinterpret_cast<void*>(sf.AddrPC.Offset));
      }
    }

    outputStream << "\n";
  }

  SymCleanup(m_hProcess);

  return;
}
Exemplo n.º 12
0
GCallStack::GCallStack(HANDLE hThread, CONTEXT& c)
{
	DWORD imageType = IMAGE_FILE_MACHINE_I386;
	HANDLE hProcess = GetCurrentProcess();

	int frameNum; // counts walked frames

#if defined(_LINUX64) || defined(_WIN64) || defined(_IOS)
	unsigned __int64 offsetFromSymbol; // tells us how far from the symbol we were
#else
	DWORD offsetFromSymbol; // tells us how far from the symbol we were
#endif



	DWORD symOptions; // symbol handler settings
	IMAGEHLP_SYMBOL *pSym = (IMAGEHLP_SYMBOL *) malloc( IMGSYMLEN + MAXNAMELEN );
	char undFullName[MAXNAMELEN]; // undecorated name with all shenanigans

	IMAGEHLP_MODULE Module;
	IMAGEHLP_LINE Line;
	std::string symSearchPath;
	char *tt = 0, *p;

	STACKFRAME s; // in/out stackframe
	memset( &s, '\0', sizeof s );

	tt = new char[TTBUFLEN];

	// build symbol search path from:
	symSearchPath = "";
	// current directory
	if ( GetCurrentDirectory( TTBUFLEN, tt ) )
		symSearchPath += tt + std::string( ";" );
	// dir with executable
	if ( GetModuleFileName( 0, tt, TTBUFLEN ) )
	{
		for ( p = tt + strlen( tt ) - 1; p >= tt; -- p )
		{
			// locate the rightmost path separator
			if ( *p == '\\' || *p == '/' || *p == ':' )
				break;
		}
		// if we found one, p is pointing at it; if not, tt only contains
		// an exe name (no path), and p points before its first byte
		if ( p != tt ) // path sep found?
		{
			if ( *p == ':' ) // we leave colons in place
				++ p;
			*p = '\0'; // eliminate the exe name and last path sep
			symSearchPath += tt + std::string( ";" );
		}
	}
	// environment variable _NT_SYMBOL_PATH
	if ( GetEnvironmentVariable( "_NT_SYMBOL_PATH", tt, TTBUFLEN ) )
		symSearchPath += tt + std::string( ";" );
	// environment variable _NT_ALTERNATE_SYMBOL_PATH
	if ( GetEnvironmentVariable( "_NT_ALTERNATE_SYMBOL_PATH", tt, TTBUFLEN ) )
		symSearchPath += tt + std::string( ";" );
	// environment variable SYSTEMROOT
	if ( GetEnvironmentVariable( "SYSTEMROOT", tt, TTBUFLEN ) )
		symSearchPath += tt + std::string( ";" );

	if ( symSearchPath.size() > 0 ) // if we added anything, we have a trailing semicolon
		symSearchPath = symSearchPath.substr( 0, symSearchPath.size() - 1 );

	// why oh why does SymInitialize() want a writeable string?
	strncpy( tt, symSearchPath.c_str(), TTBUFLEN );
	tt[TTBUFLEN - 1] = '\0'; // if strncpy() overruns, it doesn't add the null terminator

	// init symbol handler stuff (SymInitialize())
	if ( ! SymInitialize( hProcess, tt, false ) )
	{
		goto tagCleanUp;
	}

	symOptions = SymGetOptions();
	symOptions |= SYMOPT_LOAD_LINES;
	symOptions &= ~SYMOPT_UNDNAME;
	SymSetOptions( symOptions ); // SymSetOptions()

	enumAndLoadModuleSymbols( hProcess, GetCurrentProcessId() );

	// init STACKFRAME for first call
	// Notes: will have to be #ifdef-ed for Alphas; MIPSes are dead anyway,
#ifndef _WIN64
	s.AddrPC.Offset = c.Eip;
	s.AddrPC.Mode = AddrModeFlat;
	s.AddrFrame.Offset = c.Ebp;
	s.AddrFrame.Mode = AddrModeFlat;
#endif

	memset( pSym, '\0', IMGSYMLEN + MAXNAMELEN );
	pSym->SizeOfStruct = IMGSYMLEN;
	pSym->MaxNameLength = MAXNAMELEN;

	memset( &Line, '\0', sizeof Line );
	Line.SizeOfStruct = sizeof Line;

	memset( &Module, '\0', sizeof Module );
	Module.SizeOfStruct = sizeof Module;

	offsetFromSymbol = 0;

	for ( frameNum = 0; ;)
	{
		// get next stack frame (StackWalk(), SymFunctionTableAccess(), SymGetModuleBase())
		// if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can
		// assume that either you are done, or that the stack is so hosed that the next
		// deeper frame could not be found.
		if ( ! StackWalk( imageType, hProcess, hThread, &s, &c, NULL,
			SymFunctionTableAccess, SymGetModuleBase, NULL ) )
			break;

		if ( s.AddrPC.Offset != 0 )
		{ // we seem to have a valid PC
			// show procedure info (SymGetSymFromAddr())
			if ( ! SymGetSymFromAddr( hProcess, s.AddrPC.Offset, &offsetFromSymbol, pSym ) )
			{
				break;
			}
			else
			{
				// UnDecorateSymbolName()
				UnDecorateSymbolName( pSym->Name, undFullName, MAXNAMELEN, UNDNAME_COMPLETE );
				if (!frameNum && strstr(undFullName, "Exception"))
					continue;
				_stk += undFullName;
			}
		} // we seem to have a valid PC

		// no return address means no deeper stackframe
		if ( s.AddrReturn.Offset == 0 )
		{
			// avoid misunderstandings in the printf() following the loop
			SetLastError( 0 );
			break;
		}
		++frameNum;
	}

	// de-init symbol handler etc. (SymCleanup())
	SymCleanup( hProcess );
	free( pSym );
tagCleanUp:;	
	delete [] tt;
}
Exemplo n.º 13
0
void StackDumper::ShowStackCore( HANDLE hThread, CONTEXT& c )
{
	// This makes this code custom for 32-bit windows. There is a technique to find out what
	// machine type we are running on, but this should do us for a good while.
	DWORD imageType = IMAGE_FILE_MACHINE_I386;

	HANDLE hProcess = GetCurrentProcess();
	int frameNum; // counts walked frames
	DWORD offsetFromSymbol; // tells us how far from the symbol we were
	DWORD symOptions; // symbol handler settings
	IMAGEHLP_SYMBOL *pSym = (IMAGEHLP_SYMBOL *) malloc( IMGSYMLEN + MAXNAMELEN );
	IMAGEHLP_MODULE Module;
	IMAGEHLP_LINE Line;
	StrApp strSearchPath; // path to search for symbol tables (I think...JT)
	achar *tt = 0;

	STACKFRAME s; // in/out stackframe
	memset( &s, '\0', sizeof s );

	tt = new achar[TTBUFLEN];
	if (!tt)
		return;

	// Build symbol search path.
	// Add current directory
	if (::GetCurrentDirectory( TTBUFLEN, tt ) )
		AppendToStaWithSep(strSearchPath, tt);
	// Add directory containing executable or DLL we are running in.
	if (::GetModuleFileName( 0, tt, TTBUFLEN ) )
	{
		StrUni stuPath = tt; // convert to Unicode if necessary, allows use of wchars
		const OLECHAR * pchPath =  stuPath.Chars();

		const OLECHAR * pch;
		for (pch = pchPath + wcslen(pchPath) - 1; pch >= pchPath; -- pch )
		{
			// locate the rightmost path separator
			if ( *pch == L'\\' || *pch == L'/' || *pch == L':' )
				break;
		}
		// if we found one, p is pointing at it; if not, tt only contains
		// an exe name (no path), and p points before its first byte
		if ( pch != pchPath ) // path sep found?
		{
			if ( *pch == L':' ) // we leave colons in place
				++ pch;
			if (strSearchPath.Length())
				strSearchPath.Append(";");
			strSearchPath.Append(pchPath, (pch - pchPath));
		}
	}
	// environment variable _NT_SYMBOL_PATH
	if (::GetEnvironmentVariable( _T("_NT_SYMBOL_PATH"), tt, TTBUFLEN ))
		AppendToStaWithSep(strSearchPath, tt);
	// environment variable _NT_ALTERNATE_SYMBOL_PATH
	if (::GetEnvironmentVariable( _T("_NT_ALTERNATE_SYMBOL_PATH"), tt, TTBUFLEN ))
		AppendToStaWithSep(strSearchPath, tt);
	// environment variable SYSTEMROOT
	if (::GetEnvironmentVariable( _T("SYSTEMROOT"), tt, TTBUFLEN ))
		AppendToStaWithSep(strSearchPath, tt);

	// Why oh why does SymInitialize() want a writeable string? Surely it doesn't modify it...
	// The doc clearly says it is an [in] parameter.
	// Also, there is not a wide character version of this function!
	StrAnsi staT(strSearchPath);
	if ( !::SymInitialize( hProcess, const_cast<char *>(staT.Chars()), false ) )
		goto LCleanup;

	// SymGetOptions()
	symOptions = SymGetOptions();
	symOptions |= SYMOPT_LOAD_LINES;
	symOptions &= ~SYMOPT_UNDNAME;
	SymSetOptions( symOptions ); // SymSetOptions()

	// Enumerate modules and tell imagehlp.dll about them.
	// On NT, this is not necessary, but it won't hurt.
	EnumAndLoadModuleSymbols( hProcess, GetCurrentProcessId() );

	// init STACKFRAME for first call
	// Notes: AddrModeFlat is just an assumption. I hate VDM debugging.
	// Notes: will have to be #ifdef-ed for Alphas; MIPSes are dead anyway,
	// and good riddance.
	s.AddrPC.Offset = c.Eip;
	s.AddrPC.Mode = AddrModeFlat;
	s.AddrFrame.Offset = c.Ebp;
	s.AddrFrame.Mode = AddrModeFlat;

	memset( pSym, '\0', IMGSYMLEN + MAXNAMELEN );
	pSym->SizeOfStruct = IMGSYMLEN;
	pSym->MaxNameLength = MAXNAMELEN;

	memset( &Line, '\0', sizeof Line );
	Line.SizeOfStruct = sizeof Line;

	memset( &Module, '\0', sizeof Module );
	Module.SizeOfStruct = sizeof Module;

	offsetFromSymbol = 0;

	if (!m_pstaDump)
	{
		try
		{
			m_pstaDump = NewObj StrAnsiBufHuge;
		}
		catch (...)
		{
			goto LCleanup;
		}
	}

	// If the stack dump gets too big, we remove some entries from near the
	// middle, and insert a marker. This counts the characters up to the
	// end of the marker.
	int ichEndLowHalf;
	ichEndLowHalf = 0;

	m_pstaDump->FormatAppend( "\r\n--# FV EIP----- RetAddr- FramePtr StackPtr Symbol\r\n" );
	// EberhardB: a stack of 1.000 frames should be enough in most cases; limiting it
	// prevents a mysterious infinite(?) loop on our build machine.
	for ( frameNum = 0; frameNum < 1000; ++ frameNum )
	{
		// get next stack frame (StackWalk(), SymFunctionTableAccess(), SymGetModuleBase())
		// if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can
		// assume that either you are done, or that the stack is so hosed that the next
		// deeper frame could not be found.
		if ( ! StackWalk( imageType, hProcess, hThread, &s, &c, NULL,
			SymFunctionTableAccess, SymGetModuleBase, NULL ) )
			break;

		// display its contents
		m_pstaDump->FormatAppend( "%3d %c%c %08x %08x %08x %08x ",
			frameNum, s.Far? 'F': '.', s.Virtual? 'V': '.',
			s.AddrPC.Offset, s.AddrReturn.Offset,
			s.AddrFrame.Offset, s.AddrStack.Offset );

		if ( s.AddrPC.Offset == 0 )
		{
			m_pstaDump->Append( "(-nosymbols- PC == 0)\r\n" );
		}
		else
		{ // we seem to have a valid PC
			char undName[MAXNAMELEN]; // undecorated name
			//char undFullName[MAXNAMELEN]; // undecorated name with all shenanigans
			// show procedure info (SymGetSymFromAddr())
			if ( ! SymGetSymFromAddr( hProcess, s.AddrPC.Offset, &offsetFromSymbol, pSym ) )
			{
				if ( gle != 487 )
					m_pstaDump->FormatAppend( "SymGetSymFromAddr(): gle = %u\r\n", gle );
			}
			else
			{
				UnDecorateSymbolName( pSym->Name, undName, MAXNAMELEN, UNDNAME_NAME_ONLY );
				//UnDecorateSymbolName( pSym->Name, undFullName, MAXNAMELEN, UNDNAME_COMPLETE );
				m_pstaDump->Append( undName );
				//if ( offsetFromSymbol != 0 )
				//	m_pstaDump->FormatAppend( " %+d bytes", offsetFromSymbol );
				//m_pstaDump->FormatAppend( "\r\n    Sig:  %s\r\n", pSym->Name );
				//m_pstaDump->FormatAppend( "\r\n    Decl: %s\r\n", undFullName );
			}

			// show line number info, NT5.0-method (SymGetLineFromAddr()). If we can't get this function,
			// or it doesn't work, leave out line number info.
			if (! g_pfnSymGetLineFromAddr)
			{
				StrApp staModName("IMAGEHLP.DLL");
				g_pfnSymGetLineFromAddr = (PFNSYMGETLINEFROMADDR) GetProcAddress(
					GetModuleHandle(staModName.Chars()), "SymGetLineFromAddr");
			}
			if (! g_pfnSymGetLineFromAddr ||
				! g_pfnSymGetLineFromAddr( hProcess, s.AddrPC.Offset, &offsetFromSymbol, &Line ) )
			{
				if ( g_pfnSymGetLineFromAddr && gle != 487 ) // apparently a magic number indicating not in symbol file.
					m_pstaDump->FormatAppend( "SymGetLineFromAddr(): gle = %u\r\n", gle );
				else
					m_pstaDump->FormatAppend( "   (no line # avail)\r\n");

			}
			else
			{
				m_pstaDump->FormatAppend( "   %s(%u)\r\n",
					Line.FileName, Line.LineNumber );
			}

#ifdef JT_20010626_WantModuleInfo
			// If we want this info adapt the printf and _snprintf in the following.

			// show module info (SymGetModuleInfo())
			if ( ! SymGetModuleInfo( hProcess, s.AddrPC.Offset, &Module ) )
			{
				m_pstaDump->FormatAppend( "SymGetModuleInfo): gle = %u\r\n", gle );
			}
			else
			{ // got module info OK
				m_pstaDump->FormatAppend( "    Mod:  %s[%s], base: 0x%x\r\n    Sym:  type: ",
					Module.ModuleName, Module.ImageName, Module.BaseOfImage );
				switch ( Module.SymType )
					{
					case SymNone:
						m_pstaDump->FormatAppend( "-nosymbols-");
						break;
					case SymCoff:
						m_pstaDump->FormatAppend( "COFF");
						break;
					case SymCv:
						m_pstaDump->FormatAppend( "CV");
						break;
					case SymPdb:
						m_pstaDump->FormatAppend( "PDB");
						break;
					case SymExport:
						m_pstaDump->FormatAppend( "-exported-");
						break;
					case SymDeferred:
						m_pstaDump->FormatAppend( "-deferred-");
						break;
					case SymSym:
						m_pstaDump->FormatAppend( "SYM");
						break;
					default:
						m_pstaDump->FormatAppend( "symtype=%d", (long) Module.SymType);
						break;
					}
				m_pstaDump->FormatAppend( ", file: %s\r\n", Module.LoadedImageName);
			} // got module info OK
#endif // JT_20010626_WantModuleInfo

			// We don't want to return more than about 10K of info (enough for an email).
			// This also serves to make sure there's enough room in the buffer for more.
			// The idea is that we'd like to keep both the top and bottom of the stack.
			// So we delete frames from the middle until we have less than 10K.
			if (m_pstaDump->Length() > MAXDUMPLEN)
			{
				if (!ichEndLowHalf)
				{
					static char * pszGap =
						"\r\n\r\n\r\n******************Frames skipped here***************\r\n\r\n\r\n";
					int cchGap = strlen(pszGap);
					ichEndLowHalf = FindStartOfFrame(MAXDUMPLEN / 2);
					// Overwrite some of what's there with the gap marker. The incomplete
					// frame will be part of what gets deleted.
					m_pstaDump->Replace(ichEndLowHalf, ichEndLowHalf + cchGap, pszGap, cchGap);
					ichEndLowHalf += cchGap;
				}
				int cchLeave = m_pstaDump->Length();
				int ichKeep = ichEndLowHalf;
				while (cchLeave > MAXDUMPLEN)
				{
					int ichKeepT = FindStartOfFrame(ichKeep + 1);
					cchLeave -= ichKeepT - ichKeep;
					ichKeep = ichKeepT;
				}
				m_pstaDump->Replace(ichEndLowHalf, ichKeep, (char *)NULL, 0);
			}

		} // we seem to have a valid PC

		// no return address means no deeper stackframe
		if ( s.AddrReturn.Offset == 0 )
		{
			// avoid misunderstandings in the printf() following the loop
			SetLastError( 0 );
			break;
		}

	} // for ( frameNum )

	if ( gle != 0 )
		printf( "\r\nStackWalk(): gle = %u\r\n", gle );

LCleanup:
	ResumeThread( hThread );
	// de-init symbol handler etc.
	SymCleanup( hProcess );
	free( pSym );
	delete [] tt;

#ifdef DEBUG
	::OutputDebugStringA(m_pstaDump->Chars());
#endif

}
Exemplo n.º 14
0
void PrintBacktrace(PCONTEXT context)
{
	HANDLE hProcess = GetCurrentProcess();
	HANDLE hThread = GetCurrentThread();

	char appDir[MAX_PATH + 1];
	GetModuleFileName(nullptr, appDir, sizeof(appDir));
	char* end = strrchr(appDir, PATH_SEPARATOR);
	if (end) *end = '\0';

	SymSetOptions(SymGetOptions() | SYMOPT_LOAD_LINES | SYMOPT_FAIL_CRITICAL_ERRORS);

	if (!SymInitialize(hProcess, appDir, TRUE))
	{
		warn("Could not obtain detailed exception information: SymInitialize failed");
		return;
	}

	const int MAX_NAMELEN = 1024;
	IMAGEHLP_SYMBOL64* sym = (IMAGEHLP_SYMBOL64 *) malloc(sizeof(IMAGEHLP_SYMBOL64) + MAX_NAMELEN);
	memset(sym, 0, sizeof(IMAGEHLP_SYMBOL64) + MAX_NAMELEN);
	sym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
	sym->MaxNameLength = MAX_NAMELEN;

	IMAGEHLP_LINE64 ilLine;
	memset(&ilLine, 0, sizeof(ilLine));
	ilLine.SizeOfStruct = sizeof(ilLine);

	STACKFRAME64 sfStackFrame;
	memset(&sfStackFrame, 0, sizeof(sfStackFrame));
	DWORD imageType;
#ifdef _M_IX86
	imageType = IMAGE_FILE_MACHINE_I386;
	sfStackFrame.AddrPC.Offset = context->Eip;
	sfStackFrame.AddrPC.Mode = AddrModeFlat;
	sfStackFrame.AddrFrame.Offset = context->Ebp;
	sfStackFrame.AddrFrame.Mode = AddrModeFlat;
	sfStackFrame.AddrStack.Offset = context->Esp;
	sfStackFrame.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
	imageType = IMAGE_FILE_MACHINE_AMD64;
	sfStackFrame.AddrPC.Offset = context->Rip;
	sfStackFrame.AddrPC.Mode = AddrModeFlat;
	sfStackFrame.AddrFrame.Offset = context->Rsp;
	sfStackFrame.AddrFrame.Mode = AddrModeFlat;
	sfStackFrame.AddrStack.Offset = context->Rsp;
	sfStackFrame.AddrStack.Mode = AddrModeFlat;
#else
	warn("Could not obtain detailed exception information: platform not supported");
	return;
#endif

	for (int frameNum = 0; ; frameNum++)
	{
		if (frameNum > 1000)
		{
			warn("Endless stack, abort tracing");
			return;
		}

		if (!StackWalk64(imageType, hProcess, hThread, &sfStackFrame, context, nullptr, SymFunctionTableAccess64, SymGetModuleBase64, nullptr))
		{
			warn("Could not obtain detailed exception information: StackWalk64 failed");
			return;
		}

		DWORD64 dwAddr = sfStackFrame.AddrPC.Offset;
		BString<1024> symName;
		BString<1024> srcFileName;
		int lineNumber = 0;

		DWORD64 dwSymbolDisplacement;
		if (SymGetSymFromAddr64(hProcess, dwAddr, &dwSymbolDisplacement, sym))
		{
			UnDecorateSymbolName(sym->Name, symName, symName.Capacity(), UNDNAME_COMPLETE);
			symName[sizeof(symName) - 1] = '\0';
		}
		else
		{
			symName = "<symbol not available>";
		}

		DWORD dwLineDisplacement;
		if (SymGetLineFromAddr64(hProcess, dwAddr, &dwLineDisplacement, &ilLine))
		{
			lineNumber = ilLine.LineNumber;
			char* useFileName = ilLine.FileName;
			char* root = strstr(useFileName, "\\daemon\\");
			if (root)
			{
				useFileName = root;
			}
			srcFileName = useFileName;
		}
		else
		{
			srcFileName = "<filename not available>";
		}

		info("%s (%i) : %s", *srcFileName, lineNumber, *symName);

		if (sfStackFrame.AddrReturn.Offset == 0)
		{
			break;
		}
	}
}
Exemplo n.º 15
0
bool CMapFile::LoadFile(LPCTSTR szFilePath, FuncInfoList& listFuncDatas)
{
    HANDLE hFile = ::CreateFile(szFilePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
    if(hFile == INVALID_HANDLE_VALUE)
        return false;

    const int pointerLength = 8;
    bool result = false;
    for(;;)
    {
        // Read File
        DWORD dwSize = ::GetFileSize(hFile, NULL);
        LPSTR pFileData = (LPSTR)::malloc(dwSize + 1);
        LPSTR pFileEnd = pFileData + dwSize;
        DWORD dwRead;
        if(!::ReadFile(hFile, (LPVOID)pFileData, dwSize, &dwRead, NULL) || dwRead != dwSize)
            break;

        pFileData[dwSize - 1] = 0;

        // Find begin of function datas
        LPSTR pLine = strstr(pFileData, "Lib:Object");
        if(pLine == NULL)
            break;

        // Replace \r\n with \0
        for(DWORD i=0; i<dwSize; ++ i)
        {
            if(pFileData[i] == '\r' || pFileData[i] == '\n')
                pFileData[i] = 0;
        }

        char buffer[1024];
        while((pLine = NextLine(pLine, pFileEnd)) != NULL)
        {
            stFuncData data;
            data.nFuncSize = 0;
            data.strFuncSize = "0";

            if(strstr(pLine, "entry point at") != NULL)
            {
                result = true;
                break;
            }

            // 0005:000002b0       __imp___CRT_RTC_INITW      004182b0     MSVCRTD:MSVCR90D.dll

            // Section No
            data.nSectionNo = atoi(pLine);

            pLine = strchr(pLine, ':');
            if(pLine == NULL)
                break;

            // FuncName
            pLine = strtok(pLine, " ");
            if(pLine == NULL)
                break;
            pLine = (LPSTR)strtok(NULL, " ");
            if(pLine == NULL)
                break;

            data.strFuncName = pLine;
            if(data.strFuncName == _T("__TI2PAD"))
                printf("");

            // DecodedFuncName
#ifdef UnDecorateSymbolName
#undef UnDecorateSymbolName
#endif // UnDecorateSymbolName
            if(UnDecorateSymbolName(pLine, buffer, _countof(buffer), 
                UNDNAME_NO_LEADING_UNDERSCORES | UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_FUNCTION_RETURNS | UNDNAME_NO_ALLOCATION_MODEL | UNDNAME_NO_ALLOCATION_LANGUAGE | UNDNAME_NO_THISTYPE | UNDNAME_NO_ACCESS_SPECIFIERS | UNDNAME_NO_THROW_SIGNATURES | UNDNAME_NO_MEMBER_TYPE | UNDNAME_NO_RETURN_UDT_MODEL | UNDNAME_32_BIT_DECODE | UNDNAME_NAME_ONLY))
            {
                data.strFuncName = buffer;
            }

            // RVA
            pLine = strtok(NULL, " ");
            if(pLine == NULL)
                break;

            // FuncAddr
            sscanf(pLine, "%x", &data.pFuncAddr);

            if(listFuncDatas.GetSize() > 0)
            {
                stFuncData& lastFuncData = listFuncDatas[listFuncDatas.GetSize() - 1];
                if(lastFuncData.nSectionNo == data.nSectionNo && lastFuncData.nFuncSize <= 0)
                {
                    lastFuncData.nFuncSize = data.pFuncAddr - lastFuncData.pFuncAddr;
                    lastFuncData.strFuncSize.Format(_T("%d"), lastFuncData.nFuncSize);
                }
            }

            // find last token
            LPSTR lastToken = pLine;
            while(pLine != NULL)
            {
                lastToken = pLine;
                pLine = strtok(NULL, " ");
            }
            pLine = lastToken;

            // Module:Obj
            LPCSTR pos = strchr(pLine, ':');
            if(pos == NULL)
            {
                data.strObjName = pLine;
            }
            else
            {
                CString tmp(pLine, pos - pLine);
                data.strModuleName = tmp;
                data.strObjName = pos + 1;
            }

            listFuncDatas.Add(data);
        }

        break;
    }
    ::CloseHandle(hFile);
    return result;
}
Exemplo n.º 16
0
	//*************************************************************************
	// Method:		GetStackInfo
	// Description: Gets the call stack for the specified thread
	//
	// Parameters:
	//	hThread - the handle to the target thread
	//	threadContext - the context of the target thread
	//
	// Return Value: (FrameInfo *) An array containing stack trace data
	//*************************************************************************
	SiUtils::SiArray <FrameInfo *> StackWalker::GetStackInfo(HANDLE hThread, CONTEXT &threadContext)
	{
		//Clear the frame array of any previous data
		frameArray.Clear();

		DWORD imageType = IMAGE_FILE_MACHINE_I386;
		HANDLE hProcess = GetCurrentProcess();
		
		int frameNum;						// counts walked frames
		DWORD offsetFromSymbol;				// tells us how far from the symbol we were
		DWORD symOptions;					// symbol handler settings
		IMAGEHLP_SYMBOL *pSym = (IMAGEHLP_SYMBOL *) malloc( IMGSYMLEN + MAXNAMELEN );
		char undName[MAXNAMELEN];			// undecorated name
		char undFullName[MAXNAMELEN];		// undecorated name with all shenanigans
		IMAGEHLP_MODULE Module;
		IMAGEHLP_LINE Line;
		std::string symSearchPath;
		char *tt = 0, *p;

		STACKFRAME s;						// in/out stackframe
		memset( &s, '\0', sizeof s );

		tt = new char[TTBUFLEN];
		// build symbol search path from:
		symSearchPath = "";
		// current directory
		if (GetCurrentDirectory(TTBUFLEN, tt ))
			symSearchPath += tt + std::string( ";" );
		
		// dir with executable
		if (GetModuleFileName(0, tt, TTBUFLEN))
		{
			for ( p = tt + strlen( tt ) - 1; p >= tt; -- p )
			{
				// locate the rightmost path separator
				if ( *p == '\\' || *p == '/' || *p == ':' )
					break;
			}
			
			if ( p != tt )
			{
				if ( *p == ':' ) // we leave colons in place
					++ p;
				*p = '\0'; // eliminate the exe name and last path sep
				symSearchPath += tt + std::string( ";" );
			}
		}
		
		// environment variable _NT_SYMBOL_PATH
		if ( GetEnvironmentVariable( "_NT_SYMBOL_PATH", tt, TTBUFLEN ) )
			symSearchPath += tt + std::string( ";" );
		// environment variable _NT_ALTERNATE_SYMBOL_PATH
		if ( GetEnvironmentVariable( "_NT_ALTERNATE_SYMBOL_PATH", tt, TTBUFLEN ) )
			symSearchPath += tt + std::string( ";" );
		// environment variable SYSTEMROOT
		if ( GetEnvironmentVariable( "SYSTEMROOT", tt, TTBUFLEN ) )
			symSearchPath += tt + std::string( ";" );

		if ( symSearchPath.size() > 0 ) // if we added anything, we have a trailing semicolon
			symSearchPath = symSearchPath.substr( 0, symSearchPath.size() - 1 );

		strncpy( tt, symSearchPath.c_str(), TTBUFLEN );
		tt[TTBUFLEN - 1] = '\0'; // if strncpy() overruns, it doesn't add the null terminator

		// init symbol handler stuff (SymInitialize())
		if (!SymInitialize(hProcess, tt, false ))
			goto cleanup;

		// SymGetOptions()
		symOptions = SymGetOptions();
		symOptions |= SYMOPT_LOAD_LINES;
		symOptions &= ~SYMOPT_UNDNAME;
		SymSetOptions( symOptions );

		// Enumerate modules and tell imagehlp.dll about them.
		enumAndLoadModuleSymbols( hProcess, GetCurrentProcessId() );

		// init STACKFRAME for first call
		// Notes: AddrModeFlat is just an assumption. I hate VDM debugging.
		// Notes: will have to be #ifdef-ed for Alphas; MIPSes are dead anyway,
		// and good riddance.
		s.AddrPC.Offset = threadContext.Eip;
		s.AddrPC.Mode = AddrModeFlat;
		s.AddrFrame.Offset = threadContext.Ebp;
		s.AddrFrame.Mode = AddrModeFlat;

		memset( pSym, '\0', IMGSYMLEN + MAXNAMELEN );
		pSym->SizeOfStruct = IMGSYMLEN;
		pSym->MaxNameLength = MAXNAMELEN;

		memset( &Line, '\0', sizeof Line );
		Line.SizeOfStruct = sizeof Line;

		memset( &Module, '\0', sizeof Module );
		Module.SizeOfStruct = sizeof Module;

		offsetFromSymbol = 0;

		for ( frameNum = 0; ; ++ frameNum )
		{
			FrameInfo * frameInfo = new FrameInfo();

			if (!StackWalk( imageType, hProcess, hThread, &s, &threadContext, NULL,
				SymFunctionTableAccess, SymGetModuleBase, NULL ) )
				break;

			frameInfo->frameNumber = frameNum;
			frameInfo->IsWOWFarCall = s.Far;
			frameInfo->IsVirtualFrame = s.Virtual;
			frameInfo->Eip = s.AddrPC.Offset;				//if 0, the no symbols
			frameInfo->ReturnAddr = s.AddrReturn.Offset;
			frameInfo->FramePtr = s.AddrFrame.Offset;
			frameInfo->StackPtr = s.AddrStack.Offset;

			if (s.AddrPC.Offset == 0)
			{
				//printf( "(-nosymbols- PC == 0)\n" );
			}
			else
			{ // we seem to have a valid PC
				// show procedure info (SymGetSymFromAddr())
				if ( ! SymGetSymFromAddr( hProcess, s.AddrPC.Offset, &offsetFromSymbol, pSym ) )
				{
					/*if ( GetLastError() != 487 )
						printf( "SymGetSymFromAddr(): GetLastError() = %lu\n", GetLastError() );*/
				}
				else
				{
					// UnDecorateSymbolName()
					UnDecorateSymbolName( pSym->Name, undName, MAXNAMELEN, UNDNAME_NAME_ONLY );
					UnDecorateSymbolName( pSym->Name, undFullName, MAXNAMELEN, UNDNAME_COMPLETE );

					strcpy (frameInfo->undecoratedName, undName);
					strcpy (frameInfo->undecoratedFullName, undFullName);
					strcpy (frameInfo->signature, pSym->Name );
					frameInfo->offsetFromSymbol = offsetFromSymbol;
				}

				// show module info (SymGetModuleInfo())
				if (SymGetModuleInfo( hProcess, s.AddrPC.Offset, &Module ) )
				{	
					strcpy (frameInfo->ModuleName, Module.ModuleName);
					strcpy (frameInfo->ImageName, Module.ImageName);
					frameInfo->BaseOfImage = Module.BaseOfImage;

				}

			} // we seem to have a valid PC

			// no return address means no deeper stackframe
			if ( s.AddrReturn.Offset == 0 )
			{
				// avoid misunderstandings in the printf() following the loop
				SetLastError( 0 );
				break;
			}
			
			this->frameArray.Add (frameInfo);

		} // for ( frameNum )

	cleanup:
		// de-init symbol handler etc. (SymCleanup())
		SymCleanup( hProcess );
		free( pSym );
		delete [] tt;
		return frameArray;
	}
Exemplo n.º 17
0
// Get function prototype and parameter info from ip address and stack address
static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, LPTSTR lpszSymbol )
{
	BOOL              ret = FALSE;
	DWORD             dwSymSize = 10000;
	TCHAR             lpszUnDSymbol[BUFFERSIZE]=_T("?");
	CHAR              lpszNonUnicodeUnDSymbol[BUFFERSIZE]="?";
	LPTSTR            lpszParamSep = nullptr;
	LPTSTR            lpszParsed = lpszUnDSymbol;
	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 info for IP
	DWORD64           dwDisp = 0;
	if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, (PDWORD64)&dwDisp, pSym ) )
	{
		// Make the symbol readable for humans
		UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE,
			UNDNAME_COMPLETE |
			UNDNAME_NO_THISTYPE |
			UNDNAME_NO_SPECIAL_SYMS |
			UNDNAME_NO_MEMBER_TYPE |
			UNDNAME_NO_MS_KEYWORDS |
			UNDNAME_NO_ACCESS_SPECIFIERS );

		// Symbol information is ANSI string
		PCSTR2LPTSTR( lpszNonUnicodeUnDSymbol, lpszUnDSymbol );

		// I am just smarter than the symbol file :)
		if ( _tcscmp(lpszUnDSymbol, _T("_WinMain@16")) == 0 )
			_tcscpy(lpszUnDSymbol, _T("WinMain(HINSTANCE,HINSTANCE,LPCTSTR,int)"));
		else
			if ( _tcscmp(lpszUnDSymbol, _T("_main")) == 0 )
				_tcscpy(lpszUnDSymbol, _T("main(int,TCHAR * *)"));
			else
				if ( _tcscmp(lpszUnDSymbol, _T("_mainCRTStartup")) == 0 )
					_tcscpy(lpszUnDSymbol, _T("mainCRTStartup()"));
				else
					if ( _tcscmp(lpszUnDSymbol, _T("_wmain")) == 0 )
						_tcscpy(lpszUnDSymbol, _T("wmain(int,TCHAR * *,TCHAR * *)"));
					else
						if ( _tcscmp(lpszUnDSymbol, _T("_wmainCRTStartup")) == 0 )
							_tcscpy(lpszUnDSymbol, _T("wmainCRTStartup()"));

		lpszSymbol[0] = _T('\0');

		// Let's go through the stack, and modify the function prototype, and insert the actual
		// parameter values from the stack
		if ( _tcsstr( lpszUnDSymbol, _T("(void)") ) == nullptr && _tcsstr( lpszUnDSymbol, _T("()") ) == nullptr)
		{
			ULONG index = 0;
			for ( ; ; index++ )
			{
				lpszParamSep = _tcschr( lpszParsed, _T(',') );
				if ( lpszParamSep == nullptr )
					break;

				*lpszParamSep = _T('\0');

				_tcscat( lpszSymbol, lpszParsed );
				_stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X,"), *((ULONG*)(stackAddress) + 2 + index) );

				lpszParsed = lpszParamSep + 1;
			}

			lpszParamSep = _tcschr( lpszParsed, _T(')') );
			if ( lpszParamSep != nullptr )
			{
				*lpszParamSep = _T('\0');

				_tcscat( lpszSymbol, lpszParsed );
				_stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X)"), *((ULONG*)(stackAddress) + 2 + index) );

				lpszParsed = lpszParamSep + 1;
			}
		}

		_tcscat( lpszSymbol, lpszParsed );

		ret = TRUE;
	}
	GlobalFree( pSym );

	return ret;
}
Exemplo n.º 18
0
void CDebugMgr::RecordStack(const CONTEXT* pContext)
{
    m_pchBuffer += wsprintf(m_pchBuffer,"\nCall stack:\n" );

    m_pchBuffer += wsprintf(m_pchBuffer,"Address   Frame     Logical addr  Module\n" );

    DWORD pc = pContext->Eip;
    PDWORD pFrame, pPrevFrame;
    
    pFrame = (PDWORD)pContext->Ebp;

    do
    {
        TCHAR szModule[MAX_PATH] = "";
        DWORD section = 0, offset = 0;

        FindLogicalAddress((PVOID)pc, szModule,sizeof(szModule),section,offset );

        m_pchBuffer += wsprintf(m_pchBuffer,"%08X  %08X  %04X:%08X %s",
                  pc, pFrame, section, offset, szModule );

		// See if we need to spit out symbol/source/line info

		if ( m_dwOptions & DEBUGMGR_RESOLVESYMBOLS )
		{
			// Generate the name of the map file

			TCHAR szMap[MAX_PATH] = "";
			wsprintf(szMap, szModule);
			wsprintf(&szMap[lstrlen(szMap)-3], "MAP");

			TCHAR szSymbol[256] = "<unknown>";
			TCHAR szUnmangledSymbol[1024] = "<unknown>";
			TCHAR szObject[128] = "<unknown>";

			if ( FindSymbol(szMap, section, offset, szSymbol, szObject) )
			{
				if ( m_dwOptions & DEBUGMGR_UNMANGLESYMBOLS && *szSymbol == '?' )
				{
					UnDecorateSymbolName(szSymbol, szUnmangledSymbol, 1024, UNDNAME_COMPLETE);
				}
				else
				{
					wsprintf(szUnmangledSymbol, szSymbol);
				}
			}

			m_pchBuffer += wsprintf(m_pchBuffer, " in function %s in object file %s", szUnmangledSymbol, szObject);

			if ( m_dwOptions & DEBUGMGR_RESOLVESOURCELINE )
			{
				TCHAR szSource[256];
				TCHAR szLine[256];

				if ( FindSourceLine(szMap, szObject, section, offset, szSource, szLine) )
				{
					m_pchBuffer += wsprintf(m_pchBuffer, " at Line %s of %s\n", szLine, szSource);
				}
				else
				{
					m_pchBuffer += wsprintf(m_pchBuffer, " at Line ??? of ???\n");
				}
			}
			else
			{
				m_pchBuffer += wsprintf(m_pchBuffer, "\n\n");
			}
		}
		else
		{
			m_pchBuffer += wsprintf(m_pchBuffer, "\n");
		}

		// Go on to the next stack frame

        pc = pFrame[1];

        pPrevFrame = pFrame;

        pFrame = (PDWORD)pFrame[0]; // proceed to next higher frame on stack

        if ( (DWORD)pFrame & 3 )    // Frame pointer must be aligned on a
            break;                  // DWORD boundary.  Bail if not so.

        if ( pFrame <= pPrevFrame )
            break;

        // Can two DWORDs be read from the supposed frame address?          
        if ( IsBadWritePtr(pFrame, sizeof(PVOID)*2) )
            break;

    } while ( 1 );
}