Пример #1
0
static void getStack(CONTEXT& context, char* out, int max_size)
{
	BOOL result;
	HANDLE process;
	HANDLE thread;
	STACKFRAME64 stack;
	char symbol_mem[sizeof(IMAGEHLP_SYMBOL64) + 256];
	IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)symbol_mem;
	DWORD64 displacement;
	char name[256];
	copyString(out, max_size, "Crash callstack:\n");
	memset(&stack, 0, sizeof(STACKFRAME64));

	process = GetCurrentProcess();
	thread = GetCurrentThread();
	displacement = 0;
	DWORD machineType;
#ifdef _WIN64
	machineType = IMAGE_FILE_MACHINE_IA64;
	stack.AddrPC.Offset = context.Rip;
	stack.AddrPC.Mode = AddrModeFlat;
	stack.AddrStack.Offset = context.Rsp;
	stack.AddrStack.Mode = AddrModeFlat;
	stack.AddrFrame.Offset = context.Rbp;
	stack.AddrFrame.Mode = AddrModeFlat;
#else
	machineType = IMAGE_FILE_MACHINE_I386;
	stack.AddrPC.Offset = context.Eip;
	stack.AddrPC.Mode = AddrModeFlat;
	stack.AddrStack.Offset = context.Esp;
	stack.AddrStack.Mode = AddrModeFlat;
	stack.AddrFrame.Offset = context.Ebp;
	stack.AddrFrame.Mode = AddrModeFlat;
#endif

	do
	{
		result = StackWalk64(machineType,
			process,
			thread,
			&stack,
			&context,
			NULL,
			SymFunctionTableAccess64,
			SymGetModuleBase64,
			NULL);

		symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
		symbol->MaxNameLength = 255;

		SymGetSymFromAddr64(process, (ULONG64)stack.AddrPC.Offset, &displacement, symbol);
		UnDecorateSymbolName(symbol->Name, (PSTR)name, 256, UNDNAME_COMPLETE);

		catString(out, max_size, symbol->Name);
		catString(out, max_size, "\n");

	} while (result);
}
Пример #2
0
	void PlatformStack::ProgramAddressToSymbolInfo(uint64 address, SymbolInfo& oSymbolInfo)
	{
		InitSysStack();

		oSymbolInfo.Address = address;

		uint32 lastError = 0;
		HANDLE processHandle = GetCurrentProcess();

		ansichar symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + SymbolInfo::MAX_NAME_LENGHT] = { 0 };
		IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)symbolBuffer;
		symbol->SizeOfStruct = sizeof(symbolBuffer);
		symbol->MaxNameLength = SymbolInfo::MAX_NAME_LENGHT;

		if (SymGetSymFromAddr64(processHandle, address, nullptr, symbol))
		{
			int32 offset = 0;
			while (symbol->Name[offset] < 32 || symbol->Name[offset] > 127)
			{
				offset++;
			}

			strncpy(oSymbolInfo.FunctionName, symbol->Name + offset, SymbolInfo::MAX_NAME_LENGHT);
			strncat(oSymbolInfo.FunctionName, "()", SymbolInfo::MAX_NAME_LENGHT);
		}
		else
		{
			lastError = GetLastError();
		}

		IMAGEHLP_LINE64	imageHelpLine = { 0 };
		imageHelpLine.SizeOfStruct = sizeof(imageHelpLine);
		if (SymGetLineFromAddr64(processHandle, address, (::DWORD *)&oSymbolInfo.SymbolDisplacement, &imageHelpLine))
		{
			strncpy(oSymbolInfo.FileName, imageHelpLine.FileName, SymbolInfo::MAX_NAME_LENGHT);
			oSymbolInfo.LineNumber = imageHelpLine.LineNumber;
		}
		else
		{
			lastError = GetLastError();
		}

		IMAGEHLP_MODULE64 imageHelpModule = { 0 };
		imageHelpModule.SizeOfStruct = sizeof(imageHelpModule);
		if (SymGetModuleInfo64(processHandle, address, &imageHelpModule))
		{
			strncpy(oSymbolInfo.ModuleName, imageHelpModule.ImageName, SymbolInfo::MAX_NAME_LENGHT);
		}
		else
		{
			lastError = GetLastError();
		}
	}
Пример #3
0
void CallStack::getFuncInfo(LPVOID dwFunc, FuncInfo& info)
{
    memset(szBuffer, 0, sizeof(szBuffer));
#ifdef WIN32
#ifdef X64
    PIMAGEHLP_SYMBOL64 symbol = (PIMAGEHLP_SYMBOL64)szBuffer;
    symbol->SizeOfStruct  = sizeof(szBuffer);
    symbol->MaxNameLength = sizeof(szBuffer) - sizeof(IMAGEHLP_SYMBOL64);

    DWORD64 dwDisplacement = 0;

    if (SymGetSymFromAddr64(hProcess, (DWORD)dwFunc, &dwDisplacement, symbol))
    {
        strncpy(info.szFuncName, symbol->Name, min(sizeof(info.szFuncName) - 1, strlen(symbol->Name)));
        info.szFuncName[min(sizeof(info.szFuncName) - 1, strlen(symbol->Name))] = 0;
    }

    IMAGEHLP_LINE64 imageHelpLine;
    imageHelpLine.SizeOfStruct = sizeof(imageHelpLine);

    if (SymGetLineFromAddr64(hProcess, (DWORD)dwFunc, (PDWORD)&dwDisplacement, &imageHelpLine))
    {
        strncpy(info.szFilePath, imageHelpLine.FileName, min(sizeof(info.szFilePath) - 1, strlen(imageHelpLine.FileName)));
        info.szFilePath[min(sizeof(info.szFilePath) - 1, strlen(imageHelpLine.FileName))] = 0;
        info.dwLineNumber = imageHelpLine.LineNumber;
    }
#else
    PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL)szBuffer;
    symbol->SizeOfStruct  = sizeof(szBuffer);
    symbol->MaxNameLength = sizeof(szBuffer) - sizeof(IMAGEHLP_SYMBOL);

    DWORD dwDisplacement = 0;

    if (SymGetSymFromAddr(hProcess, (DWORD)dwFunc, &dwDisplacement, symbol))
    {
        strncpy(info.szFuncName, symbol->Name, min(sizeof(info.szFuncName) - 1, strlen(symbol->Name)));
        info.szFuncName[min(sizeof(info.szFuncName) - 1, strlen(symbol->Name))] = 0;
    }

    IMAGEHLP_LINE imageHelpLine;
    imageHelpLine.SizeOfStruct = sizeof(imageHelpLine);

    if (SymGetLineFromAddr(hProcess, (DWORD)dwFunc, &dwDisplacement, &imageHelpLine))
    {
        strncpy(info.szFilePath, imageHelpLine.FileName, min(sizeof(info.szFilePath) - 1, strlen(imageHelpLine.FileName)));
        info.szFilePath[min(sizeof(info.szFilePath) - 1, strlen(imageHelpLine.FileName))] = 0;
        info.dwLineNumber = imageHelpLine.LineNumber;
    }
#endif
#endif
}
// ------------------------------------------------------------------
bool win32_platform::get_backtrace_frame_info(void* frame, char* function,
	char* filename, int* line_number)
{
	IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)malloc(
		sizeof(IMAGEHLP_SYMBOL64) + DEREFEREE_MAX_FUNCTION_LEN);

	symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
	symbol->MaxNameLength = DEREFEREE_MAX_FUNCTION_LEN;
	memset((char*)symbol + sizeof(IMAGEHLP_SYMBOL64), 0,
		DEREFEREE_MAX_FUNCTION_LEN);

	DWORD64 displacement = 0;
	BOOL res = SymGetSymFromAddr64(GetCurrentProcess(), (DWORD64)frame,
		&displacement, symbol);

	if(res)
	{
		strncpy(function, (char*)symbol->Name,
			DEREFEREE_MAX_FUNCTION_LEN - 1);

		IMAGEHLP_LINE64 line_info = { 0 };
		line_info.SizeOfStruct = sizeof(line_info);
		DWORD displacement2 = 0;
		
		res = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)frame,
			&displacement2, &line_info);

		if(res)
		{
			strncpy(filename, (char*)line_info.FileName,
				DEREFEREE_MAX_FILENAME_LEN - 1);
			*line_number = (int)line_info.LineNumber;
		}
		else
		{
			filename[0] = '\0';
			*line_number = 0;
		}

		free(symbol);
		return true;
	}
	else
	{
		free(symbol);
		return false;
	}
}
Пример #5
0
int KDumpModuleAnalyzer::GetModuleInfo(KDumpModuleInfo *pRetDumpModuleInfo)
{
	int nResult = false;
	int nRetCode = false;

#ifdef _DEBUG
	struct IMAGEHLP_SYMBOL64_EX : IMAGEHLP_SYMBOL64
	{
		TCHAR _EX[MAX_PATH];
	};

	DWORD64 dwDisplacement;
	IMAGEHLP_SYMBOL64_EX Symbol;
	Symbol.MaxNameLength = sizeof(Symbol._EX) / sizeof(Symbol._EX[0]);
	nRetCode = SymGetSymFromAddr64(m_hProcess, m_Stackframe.AddrPC.Offset, &dwDisplacement, &Symbol);
	if (nRetCode)
	{
#ifdef OPEN_LOG_AND_BREAK
		KLogPrintf("%s\t%d\t%x\n", Symbol.Name, 0, m_Stackframe.AddrPC.Offset);
#endif
		printf("%s\t%d\t%x\n", Symbol.Name, 0, m_Stackframe.AddrPC.Offset);
	}
#endif

	KG_PROCESS_ERROR(pRetDumpModuleInfo);
	memset(pRetDumpModuleInfo, 0, sizeof(KDumpModuleInfo));
	
	pRetDumpModuleInfo->dwStackAddress = m_dwStackAddress;
	nRetCode = EnumerateLoadedModules64(m_hProcess, KDumpModuleAnalyzer::FindExceptionModule, (void *)pRetDumpModuleInfo);
	KG_PROCESS_ERROR(nRetCode);//EnumerateLoadedModules64 执行失败
	KG_PROCESS_ERROR(pRetDumpModuleInfo->nFindDumpModuleFlag);//FindExceptionModule 没有查找到
	
#ifdef OPEN_LOG_AND_BREAK
	KLogPrintf(
		"Name:%s\tBase:%llp\tOffset:%llp\tStack:%llp", 
		pRetDumpModuleInfo->szModuleName, 
		pRetDumpModuleInfo->dwModuleBase, 
		pRetDumpModuleInfo->dwStackAddress,
		m_dwStackAddress
	);
#endif

	nResult = true;
Exit0:
	return nResult;
}
Пример #6
0
char* LookupAddressSymbolName(DWORD64 dw64Address)
{
	static bool bHasFailed = false;  // for debugging purposes (so we only output the first time symbol lookup fails)

	if( dw64Address == 0 )
	{
		return nullptr;
	}

	PIMAGEHLP_SYMBOL64 pSymbol;
	pSymbol = (PIMAGEHLP_SYMBOL64)SymbolBuffer;
	pSymbol->SizeOfStruct = sizeof(SymbolBuffer);
	pSymbol->MaxNameLength = MAX_SYM_NAME;

	DWORD64 SymbolDisplacement64 = 0;

	//NOTE: Symbols that contain "dynamic initializer for" are for static initializers and can be REALLY slow to load

	if( SymGetSymFromAddr64(hApplicationProcess, dw64Address, &SymbolDisplacement64, pSymbol) )
	{
		char* p = pSymbol->Name;
		while( (*p < 32) || (*p > 127) )  // skip any strange characters at the beginning of the symbol name
		{
			p++;
		}

		return p;
	}
	else if( !bHasFailed )  // only output error message once (to prevent massive spam)
	{
		bHasFailed = true;

		DWORD error = GetLastError();
		DebugLog("SymGetSymFromAddr64 failed: error = %d", error);
	}

	return nullptr;
}
PRAGMA_ENABLE_OPTIMIZATION

void FWindowsPlatformStackWalk::ProgramCounterToSymbolInfo( uint64 ProgramCounter, FProgramCounterSymbolInfo& out_SymbolInfo )
{
	// Initialize stack walking as it loads up symbol information which we require.
	InitStackWalking();

	// Set the program counter.
	out_SymbolInfo.ProgramCounter = ProgramCounter;

	uint32 LastError = 0;
	HANDLE ProcessHandle = GetCurrentProcess();

	// Initialize symbol.
	ANSICHAR SymbolBuffer[sizeof( IMAGEHLP_SYMBOL64 ) + FProgramCounterSymbolInfo::MAX_NAME_LENGHT] = {0};
	IMAGEHLP_SYMBOL64* Symbol = (IMAGEHLP_SYMBOL64*)SymbolBuffer;
	Symbol->SizeOfStruct = sizeof(SymbolBuffer);
	Symbol->MaxNameLength = FProgramCounterSymbolInfo::MAX_NAME_LENGHT;

	// Get function name.
	if( SymGetSymFromAddr64( ProcessHandle, ProgramCounter, nullptr, Symbol ) )
	{
		// Skip any funky chars in the beginning of a function name.
		int32 Offset = 0;
		while( Symbol->Name[Offset] < 32 || Symbol->Name[Offset] > 127 )
		{
			Offset++;
		}

		// Write out function name.
		FCStringAnsi::Strncpy( out_SymbolInfo.FunctionName, Symbol->Name + Offset, FProgramCounterSymbolInfo::MAX_NAME_LENGHT ); 
		FCStringAnsi::Strncat( out_SymbolInfo.FunctionName, "()", FProgramCounterSymbolInfo::MAX_NAME_LENGHT );
	}
	else
	{
		// No symbol found for this address.
		LastError = GetLastError();
	}

	// Get filename and line number.
	IMAGEHLP_LINE64	ImageHelpLine = {0};
	ImageHelpLine.SizeOfStruct = sizeof( ImageHelpLine );
	if( SymGetLineFromAddr64( ProcessHandle, ProgramCounter, (::DWORD *)&out_SymbolInfo.SymbolDisplacement, &ImageHelpLine ) )
	{
		FCStringAnsi::Strncpy( out_SymbolInfo.Filename, ImageHelpLine.FileName, FProgramCounterSymbolInfo::MAX_NAME_LENGHT );
		out_SymbolInfo.LineNumber = ImageHelpLine.LineNumber;
	}
	else
	{
		LastError = GetLastError();
	}

	// Get module name.
	IMAGEHLP_MODULE64 ImageHelpModule = {0};
	ImageHelpModule.SizeOfStruct = sizeof( ImageHelpModule );
	if( SymGetModuleInfo64( ProcessHandle, ProgramCounter, &ImageHelpModule) )
	{
		// Write out module information.
		FCStringAnsi::Strncpy( out_SymbolInfo.ModuleName, ImageHelpModule.ImageName, FProgramCounterSymbolInfo::MAX_NAME_LENGHT );
	}
	else
	{
		LastError = GetLastError();
	}
}
Пример #8
0
void printStackTrace(MemoryAllocationRecord* rec)
{
    const unsigned int bufferSize = 512;

    // Resolve the program counter to the corresponding function names.
    unsigned int pc;
    for (int i = 0; i < MAX_STACK_FRAMES; i++)
    {
        // Check to see if we are at the end of the stack trace.
        pc = rec->pc[i];
        if (pc == 0)
            break;

        // Get the function name.
        unsigned char buffer[sizeof(IMAGEHLP_SYMBOL64) + bufferSize];
        IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)buffer;
        DWORD64 displacement;
        memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + bufferSize);
        symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
        symbol->MaxNameLength = bufferSize;
        if (!SymGetSymFromAddr64(GetCurrentProcess(), pc, &displacement, symbol))
        {
            gameplay::print("[memory] STACK TRACE: <unknown location>\n");
        }
        else
        {
            symbol->Name[bufferSize - 1] = '\0';

            // Check if we need to go further up the stack.
            if (strncmp(symbol->Name, "operator new", 12) == 0)
            {
                // In operator new or new[], keep going...
            }
            else
            {
                // Get the file and line number.
                if (pc != 0)
                {
                    IMAGEHLP_LINE64 line;
                    DWORD displacement;
                    memset(&line, 0, sizeof(line));
                    line.SizeOfStruct = sizeof(line);
                    if (!SymGetLineFromAddr64(GetCurrentProcess(), pc, &displacement, &line))
                    {
                        gameplay::print("[memory] STACK TRACE: %s - <unknown file>:<unknown line number>\n", symbol->Name);
                    }
                    else
                    {
                        const char* file = strrchr(line.FileName, '\\');
                        if(!file) 
                            file = line.FileName;
                        else
                            file++;
                        
                        gameplay::print("[memory] STACK TRACE: %s - %s:%d\n", symbol->Name, file, line.LineNumber);
                    }
                }
            }
        }
    }
}
Пример #9
0
static std::list<stack_info> get_stack_list(
  void* bp, void* sp, void* ip,
  size_t max_depth, size_t offset, bool module, bool symbol, bool brief
)
{
  QWORD trace[33];
  CONTEXT context;

  ZeroMemory(&context, sizeof(context));
  context.ContextFlags = CONTEXT_FULL;
#ifdef _WIN64
  context.Rbp = (DWORD64)bp;
  context.Rsp = (DWORD64)sp;
  context.Rip = (DWORD64)ip;
#else
  context.Ebp = (DWORD)bp;
  context.Esp = (DWORD)sp;
  context.Eip = (DWORD)ip;
#endif
  size_t depths = stack_walk(trace, max_depth, &context);

  std::list<stack_info> image_list;
  HANDLE hProcess = GetCurrentProcess();
  for (size_t i = offset; i < depths; i++)
  {
    stack_info stack_result(brief);

    {
      DWORD symbolDisplacement = 0;
      IMAGEHLP_LINE64 imageHelpLine;
      imageHelpLine.SizeOfStruct = sizeof(imageHelpLine);

      if (SymGetLineFromAddr64(hProcess, trace[i], &symbolDisplacement, &imageHelpLine))
      {
        stack_result.file_ = std::string(imageHelpLine.FileName, check_file_name(imageHelpLine.FileName));
        std::memset(imageHelpLine.FileName, 0, stack_result.file_.size() + 1);
        stack_result.line_ = (int)imageHelpLine.LineNumber;
      }
      else
      {
        stack_result.line_ = -1;
      }
    }
    if (symbol)
    {
      static const int max_name_length = 1024;
      char symbolBf[sizeof(IMAGEHLP_SYMBOL64) + max_name_length] = { 0 };
      PIMAGEHLP_SYMBOL64 symbol;
      DWORD64 symbolDisplacement64 = 0;

      symbol = (PIMAGEHLP_SYMBOL64)symbolBf;
      symbol->SizeOfStruct = sizeof(symbolBf);
      symbol->MaxNameLength = max_name_length;

      if (SymGetSymFromAddr64(
        hProcess,
        trace[i],
        &symbolDisplacement64,
        symbol)
        )
      {
        stack_result.symbol_ = symbol->Name;
      }
      else
      {
        stack_result.symbol_ = "unknow...";
      }
    }
    if (module)
    {
      IMAGEHLP_MODULE64 imageHelpModule;
      imageHelpModule.SizeOfStruct = sizeof(imageHelpModule);

      if (SymGetModuleInfo64(hProcess, trace[i], &imageHelpModule))
      {
        stack_result.module_ = std::string(imageHelpModule.ImageName, check_file_name(imageHelpModule.ImageName));
        std::memset(imageHelpModule.ImageName, 0, stack_result.module_.size() + 1);
      }
    }
    image_list.push_back(std::move(stack_result));
  }
  return image_list;
}
Пример #10
0
        static LONG WINAPI handler(EXCEPTION_POINTERS* e) {
            const DWORD code = e->ExceptionRecord->ExceptionCode;
            SkDebugf("\nCaught exception %u", code);
            for (size_t i = 0; i < SK_ARRAY_COUNT(kExceptions); i++) {
                if (kExceptions[i].code == code) {
                    SkDebugf(" %s", kExceptions[i].name);
                }
            }
            SkDebugf("\n");

            // We need to run SymInitialize before doing any of the stack walking below.
            HANDLE hProcess = GetCurrentProcess();
            SymInitialize(hProcess, 0, true);

            STACKFRAME64 frame;
            sk_bzero(&frame, sizeof(frame));
            // Start frame off from the frame that triggered the exception.
            CONTEXT* c = e->ContextRecord;
            frame.AddrPC.Mode      = AddrModeFlat;
            frame.AddrStack.Mode   = AddrModeFlat;
            frame.AddrFrame.Mode   = AddrModeFlat;
        #if defined(_X86_)
            frame.AddrPC.Offset    = c->Eip;
            frame.AddrStack.Offset = c->Esp;
            frame.AddrFrame.Offset = c->Ebp;
            const DWORD machineType = IMAGE_FILE_MACHINE_I386;
        #elif defined(_AMD64_)
            frame.AddrPC.Offset    = c->Rip;
            frame.AddrStack.Offset = c->Rsp;
            frame.AddrFrame.Offset = c->Rbp;
            const DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
        #endif

            while (StackWalk64(machineType,
                               GetCurrentProcess(),
                               GetCurrentThread(),
                               &frame,
                               c,
                               nullptr,
                               SymFunctionTableAccess64,
                               SymGetModuleBase64,
                               nullptr)) {
                // Buffer to store symbol name in.
                static const int kMaxNameLength = 1024;
                uint8_t buffer[sizeof(IMAGEHLP_SYMBOL64) + kMaxNameLength];
                sk_bzero(buffer, sizeof(buffer));

                // We have to place IMAGEHLP_SYMBOL64 at the front, and fill in
                // how much space it can use.
                IMAGEHLP_SYMBOL64* symbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(&buffer);
                symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
                symbol->MaxNameLength = kMaxNameLength - 1;

                // Translate the current PC into a symbol and byte offset from the symbol.
                DWORD64 offset;
                SymGetSymFromAddr64(hProcess, frame.AddrPC.Offset, &offset, symbol);

                SkDebugf("%s +%x\n", symbol->Name, offset);
            }

            // Exit NOW.  Don't notify other threads, don't call anything registered with atexit().
            _exit(1);

            // The compiler wants us to return something.  This is what we'd do
            // if we didn't _exit().
            return EXCEPTION_EXECUTE_HANDLER;
        }
Пример #11
0
std::vector<CallStackInfo> GetCallStack(const CONTEXT* pContext)
{
	HANDLE hProcess = GetCurrentProcess();
	SymInitialize(hProcess, NULL, TRUE);
	vector<CallStackInfo> arrCallStackInfo;
	CONTEXT c = *pContext;

	STACKFRAME64 sf;
	memset(&sf, 0, sizeof(STACKFRAME64));
	DWORD dwImageType = IMAGE_FILE_MACHINE_I386;
#ifdef _M_IX86
	sf.AddrPC.Offset = c.Eip;
	sf.AddrPC.Mode = AddrModeFlat;
	sf.AddrStack.Offset = c.Esp;
	sf.AddrStack.Mode = AddrModeFlat;
	sf.AddrFrame.Offset = c.Ebp;
	sf.AddrFrame.Mode = AddrModeFlat;
#elif _M_X64
	dwImageType = IMAGE_FILE_MACHINE_AMD64;
	sf.AddrPC.Offset = c.Rip;
	sf.AddrPC.Mode = AddrModeFlat;
	sf.AddrFrame.Offset = c.Rsp;
	sf.AddrFrame.Mode = AddrModeFlat;
	sf.AddrStack.Offset = c.Rsp;
	sf.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
	dwImageType = IMAGE_FILE_MACHINE_IA64;
	sf.AddrPC.Offset = c.StIIP;
	sf.AddrPC.Mode = AddrModeFlat;
	sf.AddrFrame.Offset = c.IntSp;
	sf.AddrFrame.Mode = AddrModeFlat;
	sf.AddrBStore.Offset = c.RsBSP;
	sf.AddrBStore.Mode = AddrModeFlat;
	sf.AddrStack.Offset = c.IntSp;
	sf.AddrStack.Mode = AddrModeFlat;
#else
#error "Platform not supported!"
#endif

	HANDLE hThread = GetCurrentThread();
	while (true)
	{
		if (!StackWalk64(dwImageType, hProcess, hThread, &sf, &c,
			NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
			break;
		if (sf.AddrFrame.Offset == 0)
			break;

		CallStackInfo callstackinfo;
		strcpy_s(callstackinfo.MethodName, MAX_NAME_LENGTH, "N/A");
		strcpy_s(callstackinfo.FileName, MAX_NAME_LENGTH, "N/A");
		strcpy_s(callstackinfo.ModuleName, MAX_NAME_LENGTH, "N/A");
		strcpy_s(callstackinfo.LineNumber, MAX_NAME_LENGTH, "N/A");

		BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + MAX_NAME_LENGTH];
		IMAGEHLP_SYMBOL64 *pSymbol = (IMAGEHLP_SYMBOL64*)symbolBuffer;
		memset(pSymbol, 0, sizeof(IMAGEHLP_SYMBOL64) + MAX_NAME_LENGTH);

		pSymbol->SizeOfStruct = sizeof(symbolBuffer);
		pSymbol->MaxNameLength = MAX_NAME_LENGTH;

		DWORD symDisplacement = 0;

		// 得到函数名  
		if (SymGetSymFromAddr64(hProcess, sf.AddrPC.Offset, NULL, pSymbol))  
			strcpy_s(callstackinfo.MethodName, MAX_NAME_LENGTH, pSymbol->Name);  

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

		DWORD dwLineDisplacement;

		// 得到文件名和所在的代码行
		if (SymGetLineFromAddr64(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo))
		{
			strcpy_s(callstackinfo.FileName, MAX_NAME_LENGTH, lineInfo.FileName);
			sprintf_s(callstackinfo.LineNumber, "%d", lineInfo.LineNumber);
		}

		IMAGEHLP_MODULE64 moduleInfo;
		memset(&moduleInfo, 0, sizeof(IMAGEHLP_MODULE64));

		moduleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);

		// 得到模块名
		if (SymGetModuleInfo64(hProcess, sf.AddrPC.Offset, &moduleInfo))
		{
			strcpy_s(callstackinfo.ModuleName, MAX_NAME_LENGTH, moduleInfo.ModuleName);
		}

		arrCallStackInfo.push_back(callstackinfo);
	}

	SymCleanup(hProcess);
	return arrCallStackInfo;
}
Пример #12
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);
}
Пример #13
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;
		}
	}
}
Пример #14
0
int diag_backtrace(diag_output_t *o, diag_backtrace_param_t *p, diag_context_t *c)
{
    int cur = 0, count;
    STACKFRAME64 stackframe;
    CONTEXT context;
    HANDLE process = GetCurrentProcess();
    HANDLE thread = GetCurrentThread();
    DWORD bytes_written;

    if (c) {
        context = *c->context;
    }
    else {
        RtlCaptureContext(&context);
    }

    if (p->backtrace_count && p->backtrace_count < DIAG_BT_LIMIT) {
        count = p->backtrace_count;
    }
    else {
        count = DIAG_BT_LIMIT;
    }

    memset(&stackframe, 0, sizeof stackframe);
    stackframe.AddrPC.Mode = 
        stackframe.AddrFrame.Mode =
            stackframe.AddrStack.Mode = AddrModeFlat;

#ifdef DIAG_BITS_64
    stackframe.AddrPC.Offset    = context.Rip;
    stackframe.AddrFrame.Offset = context.Rbp;
    stackframe.AddrStack.Offset = context.Rsp;
#else
    stackframe.AddrPC.Offset    = context.Eip;
    stackframe.AddrFrame.Offset = context.Ebp;
    stackframe.AddrStack.Offset = context.Esp;
#endif

    if (!p->symbols_initialized) {
        SymInitialize(process, NULL, TRUE);
    }

    while (StackWalk64(
#ifdef DIAG_BITS_64
                       IMAGE_FILE_MACHINE_AMD64,
#else
                       IMAGE_FILE_MACHINE_I386,
#endif
                       process, thread,
                       &stackframe,
                       &context,
                       NULL,                       /* ReadMemoryRoutine */
                       SymFunctionTableAccess64,   /* FunctionTableAccessRoutine */
                       SymGetModuleBase64,         /* GetModuleBaseRoutine */
                       NULL)                       /* TranslateAddress */
           == TRUE) {
        char symbol_buffer[128] = {0};
        IMAGEHLP_SYMBOL64 *symbol = (IMAGEHLP_SYMBOL64 *)&symbol_buffer;
        DWORD64 ignored;
        const char *function;
        const char *offset;
        char address_buf[20], offset_buf[20];
        char buf[128];
        char *outch = buf;
        char *lastoutch = buf + sizeof buf - 1;

        if (cur + 1 > count) { /* avoid loop on corrupted chain, respect caller's wishes */
            break;
        }
        symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
        symbol->MaxNameLength = sizeof(symbol_buffer) - sizeof(IMAGEHLP_SYMBOL64);
        ignored = 0;
        if (SymGetSymFromAddr64(process, stackframe.AddrPC.Offset, &ignored, symbol) != TRUE) {
            function = NULL;
            offset = NULL;
        }
        else {
            function = symbol->Name;
            add_int(offset_buf, offset_buf + sizeof offset_buf - 1,
                    stackframe.AddrPC.Offset - symbol->Address, 16);
            offset = offset_buf;
        }

        add_int(address_buf, address_buf + sizeof address_buf - 1,
                stackframe.AddrPC.Offset, 16);

        if (function && !strcmp(function, "diag_backtrace")) {
            /* filter outselves out */
            continue;
        }

        cur++; /* gonna keep this frame, so count it */

        output_frame(outch, lastoutch, p->backtrace_fields,
                     NULL, /* no module path */
                     NULL, /* no module */
                     function,
                     offset,
                     address_buf);

        if (o->output_mode == DIAG_CALL_FN) {
            o->output_fn(o->user_data, buf);
        }
        else {
            WriteFile(o->outfile, buf, strlen(buf), &bytes_written, NULL);
            WriteFile(o->outfile, "\r\n", 2, &bytes_written, NULL);
        }
    }

    return 0;
}
Пример #15
0
const char* MemoryManager::GetCallerForAllocation(AllocHeader* pAllocation)
{
#ifdef USE_STACKTRACE
	const size_t cnBufferSize=512;
	char szFile[cnBufferSize];
	char szFunc[cnBufferSize];
	unsigned int nLine;
	static char szBuff[cnBufferSize*3];

	strcpy(szFile,"??");
	nLine=0;

	DWORD64 nPC;
	for(int i=0;i<AllocHeader::cnMaxStackFrames;++i) {
		nPC=pAllocation->nPC[i];
		if(nPC==0)
			break;

		unsigned char byBuffer[sizeof(IMAGEHLP_SYMBOL64)+cnBufferSize];
		IMAGEHLP_SYMBOL64* pSymbol=(IMAGEHLP_SYMBOL64*)byBuffer;
		DWORD64 dwDisplacement;
		memset(pSymbol,0,sizeof(IMAGEHLP_SYMBOL64)+cnBufferSize);
		pSymbol->SizeOfStruct=sizeof(IMAGEHLP_SYMBOL64);
		pSymbol->MaxNameLength=cnBufferSize;
		if(!SymGetSymFromAddr64(GetCurrentProcess(),nPC,&dwDisplacement,pSymbol))
			strcpy(szFunc,"??");
		else {
			pSymbol->Name[cnBufferSize-1]='\0';
			if(strncmp(pSymbol->Name,"MemMgr::",8)==0) {
				// In MemMgr,keep going...
			} else if(strncmp(pSymbol->Name,"operator new",12)==0) {
				// In operator new or new[],keep going...
			} else if(strncmp(pSymbol->Name,"std::",5)==0) {
				// In STL code,keep going...
			} else {
				// Found the allocator (Or near to it)
				strcpy(szFunc,pSymbol->Name);
				break;
			}
		}
	}

	if(nPC!=0) {
		IMAGEHLP_LINE64 theLine;
		DWORD dwDisplacement;
		memset(&theLine,0,sizeof(theLine));
		theLine.SizeOfStruct=sizeof(theLine);
		if(!SymGetLineFromAddr64(GetCurrentProcess(),nPC,&dwDisplacement,&theLine)) {
			strcpy(szFile,"??");
			nLine=0;
		} else {
			const char* pszFile=strrchr(theLine.FileName,'\\');
			if(!pszFile) pszFile=theLine.FileName;
			else ++pszFile;
			strncpy(szFile,pszFile,cnBufferSize);
			nLine=theLine.LineNumber;
		}
	}

	sprintf(szBuff,"%s:%d (%s)",szFile,nLine,szFunc);
	return szBuff;
#else
	UNREFERENCED_PARAMETER(pAllocation);
	return "Stack trace unavailable";
#endif
}
Пример #16
0
bool ll_get_stack_trace(std::vector<std::string>& lines)
{
	const S32 MAX_STACK_DEPTH = 32;
	const S32 STRING_NAME_LENGTH = 200;
	const S32 FRAME_SKIP = 2;
	static BOOL symbolsLoaded = false;
	static BOOL firstCall = true;

	HANDLE hProc = GetCurrentProcess();

	// load the symbols if they're not loaded
	if(!symbolsLoaded && firstCall)
	{
		symbolsLoaded = SymInitialize(hProc, NULL, true);
		firstCall = false;
	}

	// if loaded, get the call stack
	if(symbolsLoaded)
	{
		// create the frames to hold the addresses
		void* frames[MAX_STACK_DEPTH];
		memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH);
		S32 depth = 0;

		// get the addresses
		depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL);

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

		// create something to hold address info
		PIMAGEHLP_SYMBOL64 pSym;
		pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
		memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
		pSym->MaxNameLength = STRING_NAME_LENGTH;
		pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);

		// get address info for each address frame
		// and store
		for(S32 i=0; i < depth; i++)
		{
			std::stringstream stack_line;
			BOOL ret;

			DWORD64 addr = (DWORD64)frames[i];
			ret = SymGetSymFromAddr64(hProc, addr, 0, pSym);
			if(ret)
			{
				stack_line << pSym->Name << " ";
			}

			DWORD dummy;
			ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line);
			if(ret)
			{
				std::string file_name = line.FileName;
				std::string::size_type index = file_name.rfind("\\");
				stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber; 
			}

			lines.push_back(stack_line.str());
		}
		
		free(pSym);

		// TODO: figure out a way to cleanup symbol loading
		// Not hugely necessary, however.
		//SymCleanup(hProc);
		return true;
	}
	else
	{
		lines.push_back("Stack Trace Failed.  PDB symbol info not loaded");
	}

	return false;
}
Пример #17
0
int StackTrace::GetSymbolInfo(Address address, char* symbol, int maxSymbolLen)
{
    if (!InitSymbols())
        return 0;

    // Start with address.
    int charsAdded = 
        _snprintf_s(symbol, maxSymbolLen, _TRUNCATE, "%p ", address);
    symbol += charsAdded;
    maxSymbolLen -= charsAdded;
    if (maxSymbolLen < 0)
        return charsAdded;

    const DWORD64 address64 = (DWORD64)address;
    // Module name
    IMAGEHLP_MODULE64 moduleInfo;
    ZeroMemory(&moduleInfo, sizeof(moduleInfo));
    moduleInfo.SizeOfStruct = sizeof(moduleInfo);
    const HANDLE hCurrentProcess = GetCurrentProcess();
    if (SymGetModuleInfo64(hCurrentProcess, address64, &moduleInfo))
    {
        char moduleName[_MAX_PATH + 1];
        GetFileFromPath(moduleInfo.ImageName, moduleName, _MAX_PATH);
        const int moduleLen = (int)strlen(moduleName);
        strncpy_s(symbol, maxSymbolLen, moduleName, _TRUNCATE);
        symbol += moduleLen;
        charsAdded += moduleLen;
        maxSymbolLen -= moduleLen;
    }
    if (maxSymbolLen <= 0)
        return charsAdded;

    // Symbol name
    ULONG64 symbolBuffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME*sizeof(TCHAR) +
            sizeof(ULONG64) - 1) / sizeof(ULONG64)] = { 0 };
    IMAGEHLP_SYMBOL64* symbolInfo = reinterpret_cast<IMAGEHLP_SYMBOL64*>(symbolBuffer);
    symbolInfo->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
    symbolInfo->MaxNameLength = MAX_SYM_NAME;
    DWORD64 disp(0);
    if (SymGetSymFromAddr64(hCurrentProcess, address64, &disp, symbolInfo))
    {
        const int symbolChars =
            _snprintf_s(symbol, maxSymbolLen, _TRUNCATE, " %s + 0x%X", symbolInfo->Name, disp);
        symbol += symbolChars;
        maxSymbolLen -= symbolChars;
        charsAdded += symbolChars;
    }
    if (maxSymbolLen <= 0)
        return charsAdded;

    // File + line
    DWORD displacementLine;
    IMAGEHLP_LINE64 lineInfo;
    ZeroMemory(&lineInfo, sizeof(lineInfo));
    lineInfo.SizeOfStruct = sizeof(lineInfo);
    if (SymGetLineFromAddr64(hCurrentProcess, address64, &displacementLine, &lineInfo))
    {
        char fileName[_MAX_PATH + 1];
        GetFileFromPath(lineInfo.FileName, fileName, _MAX_PATH);
        int fileLineChars(0);
        if (displacementLine > 0)
        {
            fileLineChars = _snprintf_s(symbol, maxSymbolLen, _TRUNCATE, 
                " %s(%d+%04d byte(s))", fileName, lineInfo.LineNumber, displacementLine);
        }
        else
        {
            fileLineChars = _snprintf_s(symbol, maxSymbolLen, _TRUNCATE,
                " %s(%d)", fileName, lineInfo.LineNumber);
        }
        symbol += fileLineChars;
        maxSymbolLen -= fileLineChars;
        charsAdded += fileLineChars;
    }
    return charsAdded;
}
Пример #18
0
std::vector<CL_String> CL_System::get_stack_frames_text(void **frames, int num_frames)
{
#ifdef WIN32
	static CL_Mutex mutex;
	CL_MutexSection mutex_lock(&mutex);

	BOOL result = SymInitialize(GetCurrentProcess(), NULL, TRUE);
	if (!result)
		return std::vector<CL_String>();

	std::vector<CL_String> backtrace_text;
	for (unsigned short i = 0; i < num_frames; i++)
	{
		unsigned char buffer[sizeof(IMAGEHLP_SYMBOL64) + 128];
		IMAGEHLP_SYMBOL64 *symbol64 = reinterpret_cast<IMAGEHLP_SYMBOL64*>(buffer);
		memset(symbol64, 0, sizeof(IMAGEHLP_SYMBOL64) + 128);
		symbol64->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
		symbol64->MaxNameLength = 128;
		
		DWORD64 displacement = 0;
		BOOL result = SymGetSymFromAddr64(GetCurrentProcess(), (DWORD64) frames[i], &displacement, symbol64);
		if (result)
		{
			IMAGEHLP_LINE64 line64;
			DWORD displacement = 0;
			memset(&line64, 0, sizeof(IMAGEHLP_LINE64));
			line64.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
			result = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64) frames[i], &displacement, &line64);
			if (result)
			{
				backtrace_text.push_back(
					cl_format(
						"%1 (%2, line %3)",
						CL_StringHelp::local8_to_text(symbol64->Name),
						CL_StringHelp::local8_to_text(line64.FileName),
						(int) line64.LineNumber));
			}
			else
			{
				backtrace_text.push_back(symbol64->Name);
			}
		}
	}

	SymCleanup(GetCurrentProcess());
	return backtrace_text;

#elif !defined(__APPLE__)

	char **strings;
 	strings = backtrace_symbols(frames, num_frames);
	if (!strings)
	{
		return std::vector<CL_String>();
	}

	std::vector<CL_String> backtrace_text;
     
	for (int cnt = 0; cnt < num_frames; cnt++)
	{
		// Decode the strings
		char *ptr = strings[cnt];
		char *filename = ptr;
		const char *function = "";

		// Find function name
		while(*ptr)
		{
			if (*ptr=='(')	// Found function name
			{
				*(ptr++) = 0;
				function = ptr;
				break;
			}
			ptr++;
		}
		
		// Find offset
		if (function[0])	// Only if function was found
		{
			while(*ptr)	
			{
				if (*ptr=='+')	// Found function offset
				{
					*(ptr++) = 0;
					break;
				}
				if (*ptr==')')	// Not found function offset, but found, end of function
				{
					*(ptr++) = 0;
					break;
				}
				ptr++;
			}
		}

		int status;
		char *new_function = abi::__cxa_demangle(function, 0, 0, &status);
		if (new_function)	// Was correctly decoded
		{
			function = new_function;
		}

		backtrace_text.push_back( cl_format("%1 (%2)", function, filename));

		if (new_function)
		{
			free(new_function);
		}
	}

	free (strings);
	return backtrace_text;
#else
    return std::vector<CL_String>();
#endif
}
Пример #19
0
/**
 * Find symbol by address (nearest).
 *
 * @returns VBox status.
 * @param   pVM                 VM handle.
 * @param   Address             Address.
 * @param   poffDisplacement    Where to store the symbol displacement from Address.
 * @param   pSymbol             Where to store the symbol info.
 */
VMMR3DECL(int) DBGFR3SymbolByAddr(PVM pVM, RTGCUINTPTR Address, PRTGCINTPTR poffDisplacement, PDBGFSYMBOL pSymbol)
{
    /*
     * Lazy init.
     */
    if (!pVM->dbgf.s.fSymInited)
    {
        int rc = dbgfR3SymLazyInit(pVM);
        if (RT_FAILURE(rc))
            return rc;
    }

    /*
     * Look it up.
     */
#ifdef HAVE_DBGHELP
    char                achBuffer[sizeof(IMAGEHLP_SYMBOL64) + DBGF_SYMBOL_NAME_LENGTH * sizeof(TCHAR) + sizeof(ULONG64)];
    PIMAGEHLP_SYMBOL64  pSym = (PIMAGEHLP_SYMBOL64)&achBuffer[0];
    pSym->SizeOfStruct      = sizeof(IMAGEHLP_SYMBOL64);
    pSym->MaxNameLength     = DBGF_SYMBOL_NAME_LENGTH;

    if (SymGetSymFromAddr64(pVM, Address, (PDWORD64)poffDisplacement, pSym))
    {
        pSymbol->Value  = (RTGCUINTPTR)pSym->Address;
        pSymbol->cb     = pSym->Size;
        pSymbol->fFlags = pSym->Flags;
        strcpy(pSymbol->szName, pSym->Name);
        return VINF_SUCCESS;
    }
    //return win32Error(pVM);

#else

    PDBGFSYM pSym = dbgfR3SymbolGetAddr(pVM, Address);
    if (pSym)
    {
        pSymbol->Value = pSym->Core.Key;
        pSymbol->cb = pSym->Core.KeyLast - pSym->Core.Key + 1;
        pSymbol->fFlags = 0;
        pSymbol->szName[0] = '\0';
        strncat(pSymbol->szName, pSym->szName,  sizeof(pSymbol->szName) - 1);
        if (poffDisplacement)
            *poffDisplacement = Address - pSymbol->Value;
        return VINF_SUCCESS;
    }

#endif

    /*
     * Try PDM.
     */
    if (MMHyperIsInsideArea(pVM, Address))
    {
        char        szModName[64];
        RTRCPTR     RCPtrMod;
        char        szNearSym1[260];
        RTRCPTR     RCPtrNearSym1;
        char        szNearSym2[260];
        RTRCPTR     RCPtrNearSym2;
        int rc = PDMR3LdrQueryRCModFromPC(pVM, Address,
                                          &szModName[0],  sizeof(szModName),  &RCPtrMod,
                                          &szNearSym1[0], sizeof(szNearSym1), &RCPtrNearSym1,
                                          &szNearSym2[0], sizeof(szNearSym2), &RCPtrNearSym2);
        if (RT_SUCCESS(rc) && szNearSym1[0])
        {
            pSymbol->Value = RCPtrNearSym1;
            pSymbol->cb = RCPtrNearSym2 > RCPtrNearSym1 ? RCPtrNearSym2 - RCPtrNearSym1 : 0;
            pSymbol->fFlags = 0;
            pSymbol->szName[0] = '\0';
            strncat(pSymbol->szName, szNearSym1,  sizeof(pSymbol->szName) - 1);
            if (poffDisplacement)
                *poffDisplacement = Address - pSymbol->Value;
            return VINF_SUCCESS;
        }
    }

    return VERR_SYMBOL_NOT_FOUND;
}