yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
1b539d890
master
1#include "common.h" 2 3#include <inttypes.h> 4#include <string> 5#include <vector> 6#include <windows.h> 7 8// dbghelp.h needs to be included after windows.h 9#include <dbghelp.h> 10 11#define SLANG_EXAMPLE_LOG_ERROR (...) \ 12 fprintf(file, "error: %s: %d: ", __FILE__, __LINE__); \ 13 print(file, __VA_ARGS__); \ 14 fprintf(file, "\n"); 15 16static void FILE * /* file */ ) {} 17static void FILE * file ,unsigned int n ) 18{ 19fprintf (file ,"%u" ,n ); 20} 21 22 23static bool getModuleFileNameAtAddress (FILE * file ,DWORD64 const address , std::string & fileName ) 24{ 25HMODULE module = NULL ; 26 { 27BOOL result = GetModuleHandleEx ( 28GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT , 29 (LPCTSTR )address , 30& module ); 31if (result == 0 ) 32 { 33SLANG_EXAMPLE_LOG_ERROR (GetLastError ()); 34return false; 35 } 36if (module == NULL ) 37 { 38SLANG_EXAMPLE_LOG_ERROR (); 39return false; 40 } 41 } 42 43 std::vector < char > buffer (1U <<8U ); 44uint32_t constexpr maxBufferSize = 1U <<20 ; 45while (buffer .size ()< maxBufferSize ) 46 { 47DWORD result = GetModuleFileNameA (module ,buffer .data (),buffer .size ()); 48if (result == 0 ) 49 { 50SLANG_EXAMPLE_LOG_ERROR (GetLastError ()); 51return false; 52 } 53else if (result == ERROR_INSUFFICIENT_BUFFER ) 54 { 55buffer .resize (buffer .size () <<1U ); 56 } 57else 58 { 59break ; 60 } 61 } 62if (buffer .size ()== maxBufferSize ) 63 { 64SLANG_EXAMPLE_LOG_ERROR (); 65return false; 66 } 67 68fileName = std::string (buffer .data (),buffer .data ()+ buffer .size ()); 69return true; 70} 71 72// NOTE: This function is not thread-safe, due to usage of StackWalk64 and static buffers. 73static bool printStack (FILE * file ,HANDLE process ,HANDLE thread ,CONTEXT const & context ) 74{ 75#if defined(_M_AMD64 ) 76DWORD constexpr machineType = IMAGE_FILE_MACHINE_AMD64 ; 77#elif defined(_M_ARM64 ) 78DWORD constexpr machineType = IMAGE_FILE_MACHINE_ARM64 ; 79#else 80#error Unsupported machine type 81#endif 82 83static char symbolBuffer [sizeof (SYMBOL_INFO )+ MAX_SYM_NAME * sizeof (TCHAR )]; 84 85// StackWalk64 may modify the context record 86CONTEXT contextCopy ; 87memcpy (& contextCopy ,& context ,sizeof (CONTEXT )); 88 89STACKFRAME64 frame = {}; 90constexpr uint32_t maxFrameCount = 1U <<10 ; 91uint32_t frameIndex = 0U ; 92while (frameIndex < maxFrameCount ) 93 { 94// Use the default routine 95PREAD_PROCESS_MEMORY_ROUTINE64 readMemoryRoutine = NULL ; 96// Not sure what this is for, but documentation says most callers can pass NULL 97PTRANSLATE_ADDRESS_ROUTINE64 translateAddressRoutine = NULL ; 98 { 99BOOL result = StackWalk64 ( 100machineType , 101process , 102thread , 103& frame , 104& contextCopy , 105readMemoryRoutine , 106SymFunctionTableAccess64 , 107SymGetModuleBase64 , 108translateAddressRoutine ); 109if (result == FALSE) 110break ; 111 } 112 113PSYMBOL_INFO maybeSymbol = (PSYMBOL_INFO )symbolBuffer ; 114 { 115maybeSymbol -> SizeOfStruct = sizeof (SYMBOL_INFO ); 116maybeSymbol -> MaxNameLen = MAX_SYM_NAME ; 117DWORD64 address = frame .AddrPC .Offset ; 118// Not required, we want to look up the symbol exactly at the address 119PDWORD64 displacement = NULL ; 120BOOL result = SymFromAddr (process ,address ,displacement ,maybeSymbol ); 121if (result == FALSE) 122 { 123SLANG_EXAMPLE_LOG_ERROR (GetLastError ()); 124maybeSymbol = NULL ; 125 } 126 } 127 128fprintf (file ,"%u" ,frameIndex ); 129 130 std::string moduleFileName ; 131if (getModuleFileNameAtAddress (file ,frame .AddrPC .Offset ,moduleFileName )) 132fprintf (file ,": %s" ,moduleFileName .c_str ()); 133 134if (maybeSymbol ) 135 { 136PSYMBOL_INFO & symbol = maybeSymbol ; 137 138IMAGEHLP_LINE64 line = {}; 139line .SizeOfStruct = sizeof (IMAGEHLP_LINE64 ); 140 141DWORD displacement ; 142if (SymGetLineFromAddr64 (process ,frame .AddrPC .Offset ,& displacement ,& line )) 143 { 144fprintf (file ,": %s: %s: %lu" ,symbol -> Name ,line .FileName ,line .LineNumber ); 145 } 146else 147 { 148fprintf (file ,": %s" ,symbol -> Name ); 149 } 150 151fprintf (file ,": 0x%.16" PRIXPTR ,symbol -> Address ); 152 } 153fprintf (file ,"\n" ); 154 155frameIndex ++ ; 156 } 157 158return frameIndex < maxFrameCount ; 159} 160 161int exceptionFilter (FILE * logFile ,_EXCEPTION_POINTERS * exception ) 162{ 163FILE * file = logFile ?logFile :stdout ; 164fprintf ( 165file , 166"error: Exception 0x%lx occurred. Stack trace:\n" , 167exception -> ExceptionRecord -> ExceptionCode ); 168 169HANDLE process = GetCurrentProcess (); 170HANDLE thread = GetCurrentThread (); 171 172bool symbolsLoaded = false; 173 { 174// The default search paths should suffice 175PCSTR symbolFileSearchPath = NULL ; 176BOOL loadSymbolsOfLoadedModules = TRUE; 177BOOL result = SymInitialize (process ,symbolFileSearchPath ,loadSymbolsOfLoadedModules ); 178if (result == FALSE) 179 { 180fprintf (file ,"warning: Failed to load symbols\n" ); 181 } 182else 183 { 184symbolsLoaded = true; 185 } 186 } 187 188if (!printStack (file ,process ,thread ,* exception -> ContextRecord )) 189 { 190fprintf (file ,"warning: Failed to print complete stack trace!\n" ); 191 } 192 193if (symbolsLoaded ) 194 { 195BOOL result = SymCleanup (process ); 196if (result == FALSE) 197 { 198SLANG_EXAMPLE_LOG_ERROR (GetLastError ()); 199 } 200 } 201 202return EXCEPTION_EXECUTE_HANDLER ; 203}