mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-14 18:37:27 +00:00
util: Provide stack-trace utilities
This commit is contained in:
parent
b960ce1426
commit
1244044647
144
Utilities/stack_trace.cpp
Normal file
144
Utilities/stack_trace.cpp
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "stack_trace.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
#define DBGHELP_TRANSLATE_TCHAR
|
||||||
|
#include <DbgHelp.h>
|
||||||
|
#include <codecvt>
|
||||||
|
#else
|
||||||
|
#include <execinfo.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
std::string wstr_to_utf8(LPWSTR data, int str_len)
|
||||||
|
{
|
||||||
|
if (!str_len)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate size
|
||||||
|
const auto length = WideCharToMultiByte(CP_UTF8, 0, data, str_len, NULL, 0, NULL, NULL);
|
||||||
|
|
||||||
|
// Convert
|
||||||
|
std::vector<char> out(length + 1, 0);
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, data, str_len, out.data(), length, NULL, NULL);
|
||||||
|
return out.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<void*> backtrace(int max_depth)
|
||||||
|
{
|
||||||
|
std::vector<void*> result = {};
|
||||||
|
|
||||||
|
const auto hProcess = ::GetCurrentProcess();
|
||||||
|
const auto hThread = ::GetCurrentThread();
|
||||||
|
|
||||||
|
CONTEXT context{};
|
||||||
|
RtlCaptureContext(&context);
|
||||||
|
|
||||||
|
STACKFRAME64 stack = {};
|
||||||
|
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;
|
||||||
|
|
||||||
|
while (max_depth--)
|
||||||
|
{
|
||||||
|
if (!StackWalk64(
|
||||||
|
IMAGE_FILE_MACHINE_AMD64,
|
||||||
|
hProcess,
|
||||||
|
hThread,
|
||||||
|
&stack,
|
||||||
|
&context,
|
||||||
|
NULL,
|
||||||
|
SymFunctionTableAccess64,
|
||||||
|
SymGetModuleBase64,
|
||||||
|
NULL))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push_back(reinterpret_cast<void*>(stack.AddrPC.Offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> backtrace_symbols(const std::vector<void*>& stack)
|
||||||
|
{
|
||||||
|
std::vector<std::string> result = {};
|
||||||
|
std::vector<u8> symbol_buf(sizeof(SYMBOL_INFO) + sizeof(TCHAR) * 256);
|
||||||
|
|
||||||
|
const auto hProcess = ::GetCurrentProcess();
|
||||||
|
|
||||||
|
auto sym = reinterpret_cast<SYMBOL_INFO*>(symbol_buf.data());
|
||||||
|
sym->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||||
|
sym->MaxNameLen = 256;
|
||||||
|
|
||||||
|
IMAGEHLP_LINEW64 line_info{};
|
||||||
|
line_info.SizeOfStruct = sizeof(IMAGEHLP_LINEW64);
|
||||||
|
|
||||||
|
SymInitialize(hProcess, NULL, TRUE);
|
||||||
|
SymSetOptions(SYMOPT_LOAD_LINES);
|
||||||
|
|
||||||
|
for (const auto& pointer : stack)
|
||||||
|
{
|
||||||
|
DWORD64 unused;
|
||||||
|
SymFromAddr(hProcess, reinterpret_cast<DWORD64>(pointer), &unused, sym);
|
||||||
|
|
||||||
|
if (sym->NameLen)
|
||||||
|
{
|
||||||
|
const auto function_name = wstr_to_utf8(sym->Name, static_cast<int>(sym->NameLen));
|
||||||
|
|
||||||
|
// Attempt to get file and line information if available
|
||||||
|
DWORD unused2;
|
||||||
|
if (SymGetLineFromAddrW(hProcess, reinterpret_cast<DWORD64>(pointer), &unused2, &line_info))
|
||||||
|
{
|
||||||
|
const auto full_path = fmt::format("%s:%u %s", wstr_to_utf8(line_info.FileName, -1), line_info.LineNumber, function_name);
|
||||||
|
result.push_back(full_path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.push_back(function_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.push_back(fmt::format("rpcs3@0xp", pointer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::vector<void*> backtrace(int max_depth)
|
||||||
|
{
|
||||||
|
std::vector<void*> result(max_depth);
|
||||||
|
int depth = backtrace(result.data(), max_depth);
|
||||||
|
|
||||||
|
result.resize(depth);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> backtrace_symbols(const std::vector<void*>& stack)
|
||||||
|
{
|
||||||
|
std::vector<std::string> result;
|
||||||
|
result.reserve(stack.size());
|
||||||
|
|
||||||
|
const auto symbols = backtrace_symbols(stack.data(), static_cast<int>(stack.size()));
|
||||||
|
for (usz i = 0; i < stack.size(); ++i)
|
||||||
|
{
|
||||||
|
result.push_back(symbols[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(symbols);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
20
Utilities/stack_trace.h
Normal file
20
Utilities/stack_trace.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <util/types.hpp>
|
||||||
|
#include <util/logs.hpp>
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
std::vector<void*> backtrace(int max_depth = 255);
|
||||||
|
std::vector<std::string> backtrace_symbols(const std::vector<void*>& stack);
|
||||||
|
|
||||||
|
FORCE_INLINE void print_trace(logs::channel& logger, int max_depth = 255)
|
||||||
|
{
|
||||||
|
const auto trace = backtrace(max_depth);
|
||||||
|
const auto lines = backtrace_symbols(trace);
|
||||||
|
|
||||||
|
for (const auto& line : lines)
|
||||||
|
{
|
||||||
|
logger.error("%s", line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -52,6 +52,7 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\Utilities\cheat_info.cpp" />
|
<ClCompile Include="..\Utilities\cheat_info.cpp" />
|
||||||
|
<ClCompile Include="..\Utilities\stack_trace.cpp" />
|
||||||
<ClCompile Include="Crypto\decrypt_binaries.cpp" />
|
<ClCompile Include="Crypto\decrypt_binaries.cpp" />
|
||||||
<ClCompile Include="Emu\Audio\audio_resampler.cpp" />
|
<ClCompile Include="Emu\Audio\audio_resampler.cpp" />
|
||||||
<ClCompile Include="Emu\Audio\FAudio\FAudioBackend.cpp">
|
<ClCompile Include="Emu\Audio\FAudio\FAudioBackend.cpp">
|
||||||
@ -458,6 +459,7 @@
|
|||||||
<ClInclude Include="..\Utilities\address_range.h" />
|
<ClInclude Include="..\Utilities\address_range.h" />
|
||||||
<ClInclude Include="..\Utilities\cheat_info.h" />
|
<ClInclude Include="..\Utilities\cheat_info.h" />
|
||||||
<ClInclude Include="..\Utilities\simple_ringbuf.h" />
|
<ClInclude Include="..\Utilities\simple_ringbuf.h" />
|
||||||
|
<ClInclude Include="..\Utilities\stack_trace.h" />
|
||||||
<ClInclude Include="..\Utilities\transactional_storage.h" />
|
<ClInclude Include="..\Utilities\transactional_storage.h" />
|
||||||
<ClInclude Include="Crypto\decrypt_binaries.h" />
|
<ClInclude Include="Crypto\decrypt_binaries.h" />
|
||||||
<ClInclude Include="Emu\Audio\audio_resampler.h" />
|
<ClInclude Include="Emu\Audio\audio_resampler.h" />
|
||||||
|
@ -1090,6 +1090,9 @@
|
|||||||
<ClCompile Include="Emu\Cell\Modules\cellMusicSelectionContext.cpp">
|
<ClCompile Include="Emu\Cell\Modules\cellMusicSelectionContext.cpp">
|
||||||
<Filter>Emu\Cell\Modules</Filter>
|
<Filter>Emu\Cell\Modules</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\Utilities\stack_trace.cpp">
|
||||||
|
<Filter>Utilities</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Crypto\aes.h">
|
<ClInclude Include="Crypto\aes.h">
|
||||||
@ -2173,6 +2176,9 @@
|
|||||||
<ClInclude Include="Emu\Cell\Modules\cellMusicDecode.h">
|
<ClInclude Include="Emu\Cell\Modules\cellMusicDecode.h">
|
||||||
<Filter>Emu\Cell\Modules</Filter>
|
<Filter>Emu\Cell\Modules</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\Utilities\stack_trace.h">
|
||||||
|
<Filter>Utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Emu\RSX\Program\GLSLSnippets\GPUDeswizzle.glsl">
|
<None Include="Emu\RSX\Program\GLSLSnippets\GPUDeswizzle.glsl">
|
||||||
|
@ -88,7 +88,7 @@
|
|||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>Ole32.lib;gdi32.lib;..\hidapi.lib;..\libusb-1.0.lib;winmm.lib;ksuser.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;MachineIndependent.lib;GenericCodeGen.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmain.lib;shell32.lib;$(QTDIR)\lib\Qt5Widgets.lib;$(QTDIR)\lib\Qt5Gui.lib;$(QTDIR)\lib\Qt5Core.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5WinExtras.lib;Qt5Concurrent.lib;7zlib.lib;SPIRV-Tools.lib;SPIRV-Tools-opt.lib;Qt5Multimedia.lib;Qt5MultimediaWidgets.lib;Qt5Svg.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>DbgHelp.lib;Ole32.lib;gdi32.lib;..\hidapi.lib;..\libusb-1.0.lib;winmm.lib;ksuser.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;MachineIndependent.lib;GenericCodeGen.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmain.lib;shell32.lib;$(QTDIR)\lib\Qt5Widgets.lib;$(QTDIR)\lib\Qt5Gui.lib;$(QTDIR)\lib\Qt5Core.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5WinExtras.lib;Qt5Concurrent.lib;7zlib.lib;SPIRV-Tools.lib;SPIRV-Tools-opt.lib;Qt5Multimedia.lib;Qt5MultimediaWidgets.lib;Qt5Svg.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\3rdparty\glslang\build\hlsl\Release;..\3rdparty\glslang\build\SPIRV\Release;..\3rdparty\glslang\build\OGLCompilersDLL\Release;..\3rdparty\glslang\build\glslang\OSDependent\Windows\Release;..\3rdparty\glslang\build\glslang\Release;..\3rdparty\SPIRV\build\source\Release;..\3rdparty\SPIRV\build\source\opt\Release;..\lib\$(CONFIGURATION)-$(PLATFORM);..\3rdparty\XAudio2Redist\libs;..\3rdparty\discord-rpc\lib;$(QTDIR)\lib;%(AdditionalLibraryDirectories);$(VULKAN_SDK)\Lib</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\3rdparty\glslang\build\hlsl\Release;..\3rdparty\glslang\build\SPIRV\Release;..\3rdparty\glslang\build\OGLCompilersDLL\Release;..\3rdparty\glslang\build\glslang\OSDependent\Windows\Release;..\3rdparty\glslang\build\glslang\Release;..\3rdparty\SPIRV\build\source\Release;..\3rdparty\SPIRV\build\source\opt\Release;..\lib\$(CONFIGURATION)-$(PLATFORM);..\3rdparty\XAudio2Redist\libs;..\3rdparty\discord-rpc\lib;$(QTDIR)\lib;%(AdditionalLibraryDirectories);$(VULKAN_SDK)\Lib</AdditionalLibraryDirectories>
|
||||||
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
|
||||||
<DataExecutionPrevention>true</DataExecutionPrevention>
|
<DataExecutionPrevention>true</DataExecutionPrevention>
|
||||||
@ -139,7 +139,7 @@
|
|||||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>Ole32.lib;gdi32.lib;..\hidapi.lib;..\libusb-1.0.lib;winmm.lib;ksuser.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslangd.lib;OSDependentd.lib;OGLCompilerd.lib;SPIRVd.lib;MachineIndependentd.lib;GenericCodeGend.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmaind.lib;shell32.lib;$(QTDIR)\lib\Qt5Widgetsd.lib;$(QTDIR)\lib\Qt5Guid.lib;$(QTDIR)\lib\Qt5Cored.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5WinExtrasd.lib;Qt5Concurrentd.lib;7zlib.lib;SPIRV-Tools.lib;SPIRV-Tools-opt.lib;Qt5Multimediad.lib;Qt5MultimediaWidgetsd.lib;Qt5Svgd.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>DbgHelp.lib;Ole32.lib;gdi32.lib;..\hidapi.lib;..\libusb-1.0.lib;winmm.lib;ksuser.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslangd.lib;OSDependentd.lib;OGLCompilerd.lib;SPIRVd.lib;MachineIndependentd.lib;GenericCodeGend.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmaind.lib;shell32.lib;$(QTDIR)\lib\Qt5Widgetsd.lib;$(QTDIR)\lib\Qt5Guid.lib;$(QTDIR)\lib\Qt5Cored.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5WinExtrasd.lib;Qt5Concurrentd.lib;7zlib.lib;SPIRV-Tools.lib;SPIRV-Tools-opt.lib;Qt5Multimediad.lib;Qt5MultimediaWidgetsd.lib;Qt5Svgd.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\3rdparty\glslang\build\hlsl\Debug;..\3rdparty\glslang\build\SPIRV\Debug;..\3rdparty\glslang\build\OGLCompilersDLL\Debug;..\3rdparty\glslang\build\glslang\OSDependent\Windows\Debug;..\3rdparty\glslang\build\glslang\Debug;..\3rdparty\SPIRV\build\source\opt\Debug;..\3rdparty\XAudio2Redist\libs;..\3rdparty\discord-rpc\lib;..\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;%(AdditionalLibraryDirectories);$(VULKAN_SDK)\Lib</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\3rdparty\glslang\build\hlsl\Debug;..\3rdparty\glslang\build\SPIRV\Debug;..\3rdparty\glslang\build\OGLCompilersDLL\Debug;..\3rdparty\glslang\build\glslang\OSDependent\Windows\Debug;..\3rdparty\glslang\build\glslang\Debug;..\3rdparty\SPIRV\build\source\opt\Debug;..\3rdparty\XAudio2Redist\libs;..\3rdparty\discord-rpc\lib;..\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;%(AdditionalLibraryDirectories);$(VULKAN_SDK)\Lib</AdditionalLibraryDirectories>
|
||||||
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /VERBOSE %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /VERBOSE %(AdditionalOptions)</AdditionalOptions>
|
||||||
<DataExecutionPrevention>true</DataExecutionPrevention>
|
<DataExecutionPrevention>true</DataExecutionPrevention>
|
||||||
|
Loading…
Reference in New Issue
Block a user