From 96db8d3be7553b8e0639d6b2555b518c67618b29 Mon Sep 17 00:00:00 2001 From: Prcuvu Date: Sat, 5 Oct 2019 05:08:06 +0800 Subject: [PATCH] Update VDI format for Windows x64 Update VDI format to utilize 64-bit pointer types for stack tracing. Revise mapconv and CrashHandlerChild. Tested on both 32-bit and 64-bit builds to be working properly. --- src/LuaManager.h | 3 +- src/archutils/Win32/Crash.cpp | 17 +-- src/archutils/Win32/CrashHandlerChild.cpp | 67 ++++++----- src/archutils/Win32/mapconv.cpp | 137 +++++++++++++--------- 4 files changed, 128 insertions(+), 96 deletions(-) diff --git a/src/LuaManager.h b/src/LuaManager.h index 0b352b5ae6..b69d24e865 100644 --- a/src/LuaManager.h +++ b/src/LuaManager.h @@ -224,8 +224,7 @@ inline bool MyLua_checkintboolean( lua_State *L, int iArg ) int iType = lua_type( L, iArg ); if( iType == LUA_TNUMBER ) { - int iValue = lua_tointeger( L, iArg ); - return iValue != 0; + return lua_tointeger(L, iArg) != 0; } return MyLua_checkboolean( L, iArg ); diff --git a/src/archutils/Win32/Crash.cpp b/src/archutils/Win32/Crash.cpp index 2363afacd1..9ff63b4de1 100644 --- a/src/archutils/Win32/Crash.cpp +++ b/src/archutils/Win32/Crash.cpp @@ -85,7 +85,7 @@ void WriteToChild( HANDLE hPipe, const void *pData, size_t iSize ) while( iSize ) { DWORD iActual; - if( !WriteFile(hPipe, pData, iSize, &iActual, nullptr) ) + if( !WriteFile(hPipe, pData, static_cast(iSize), &iActual, nullptr) ) return; iSize -= iActual; } @@ -114,7 +114,7 @@ bool StartChild( HANDLE &hProcess, HANDLE &hToStdin, HANDLE &hFromStdout ) SetHandleInformation( hFromStdout, HANDLE_FLAG_INHERIT, 0 ); } - char szBuf[256] = ""; + char szBuf[MAX_PATH] = ""; GetModuleFileName( nullptr, szBuf, MAX_PATH ); strcat( szBuf, " " ); strcat( szBuf, CHILD_MAGIC_PARAMETER ); @@ -144,6 +144,7 @@ bool StartChild( HANDLE &hProcess, HANDLE &hToStdin, HANDLE &hFromStdout ) } hProcess = pi.hProcess; + CloseHandle(pi.hThread); return true; } @@ -209,13 +210,13 @@ void RunChild() // 2. Write info. const TCHAR *p = RageLog::GetInfo(); - int iSize = strlen( p ); + int iSize = static_cast(strlen( p )); WriteToChild( hToStdin, &iSize, sizeof(iSize) ); WriteToChild( hToStdin, p, iSize ); // 3. Write AdditionalLog. p = RageLog::GetAdditionalLog(); - iSize = strlen( p ); + iSize = static_cast(strlen( p )); WriteToChild( hToStdin, &iSize, sizeof(iSize) ); WriteToChild( hToStdin, p, iSize ); @@ -228,7 +229,7 @@ void RunChild() WriteToChild(hToStdin, &cnt, sizeof(cnt)); for( int i = 0; i < cnt; ++i ) { - iSize = strlen(ps[i])+1; + iSize = static_cast(strlen(ps[i])) + 1; WriteToChild( hToStdin, &iSize, sizeof(iSize) ); WriteToChild( hToStdin, ps[i], iSize ); } @@ -236,13 +237,13 @@ void RunChild() // 5. Write CHECKPOINTs. static TCHAR buf[1024*32]; Checkpoints::GetLogs( buf, sizeof(buf), "$$" ); - iSize = strlen( buf )+1; + iSize = static_cast(strlen( buf )) + 1; WriteToChild( hToStdin, &iSize, sizeof(iSize) ); WriteToChild( hToStdin, buf, iSize ); // 6. Write the crashed thread's name. p = RageThread::GetCurrentThreadName(); - iSize = strlen( p )+1; + iSize = static_cast(strlen( p )) + 1; WriteToChild( hToStdin, &iSize, sizeof(iSize) ); WriteToChild( hToStdin, p, iSize ); @@ -260,7 +261,7 @@ void RunChild() TCHAR szName[MAX_PATH]; if( !CrashGetModuleBaseName(hMod, szName) ) strcpy( szName, "???" ); - iSize = strlen( szName ); + iSize = static_cast(strlen( szName )); WriteToChild( hToStdin, &iSize, sizeof(iSize) ); WriteToChild( hToStdin, szName, iSize ); } diff --git a/src/archutils/Win32/CrashHandlerChild.cpp b/src/archutils/Win32/CrashHandlerChild.cpp index 1e4008a544..508a8e29b6 100644 --- a/src/archutils/Win32/CrashHandlerChild.cpp +++ b/src/archutils/Win32/CrashHandlerChild.cpp @@ -36,6 +36,12 @@ // XXX: What happens when we *don't* have version info? Does that ever actually happen? #include "ver.h" +#if _WIN64 +#define ADDRESS_ZEROS "016" +#else +#define ADDRESS_ZEROS "08" +#endif + // VDI symbol lookup: namespace VDDebugInfo { @@ -98,13 +104,18 @@ namespace VDDebugInfo // Extract fields src += 64; + const int* pVer = reinterpret_cast(src); + const size_t* pRVASize = reinterpret_cast(src + sizeof(int)); + const size_t* pFNamSize = reinterpret_cast(src + sizeof(int) + sizeof(size_t)); + const int* pSegCnt = reinterpret_cast(src + sizeof(int) + 2 * sizeof(size_t)); + src += 2 * (sizeof(int) + sizeof(size_t)); - pctx->nBuildNumber = *(int *)src; - pctx->pRVAHeap = (const unsigned char *)(src + 20); - pctx->nFirstRVA = *(const long *)(src + 16); - pctx->pFuncNameHeap = (const char *)pctx->pRVAHeap - 4 + *(const long *)(src + 4); - pctx->pSegments = (uintptr_t (*)[2])(pctx->pFuncNameHeap + *(const long *)(src + 8)); - pctx->nSegments = *(const long *)(src + 12); + pctx->nBuildNumber = *pVer; + pctx->pRVAHeap = reinterpret_cast(src + sizeof(uintptr_t)); + pctx->nFirstRVA = *reinterpret_cast(src); + pctx->pFuncNameHeap = reinterpret_cast(src + *pRVASize); + pctx->pSegments = reinterpret_cast(src + *pRVASize + *pFNamSize); + pctx->nSegments = *pSegCnt; return true; } @@ -137,7 +148,7 @@ namespace VDDebugInfo if( dwFileSize == INVALID_FILE_SIZE ) break; - char *buffer = new char[dwFileSize + 1]; + char *buffer = new char[static_cast(dwFileSize) + 1]; std::fill(buffer, buffer + dwFileSize + 1, '\0' ); DWORD dwActual; @@ -168,7 +179,7 @@ namespace VDDebugInfo return false; } - static const char *GetNameFromHeap(const char *heap, int idx) + static const char *GetNameFromHeap(const char *heap, size_t idx) { while(idx--) while(*heap++); @@ -176,19 +187,19 @@ namespace VDDebugInfo return heap; } - uintptr_t VDDebugInfoLookupRVA( const Context *pctx, uintptr_t rva, char *buf, int buflen ) + intptr_t VDDebugInfoLookupRVA( const Context *pctx, uintptr_t rva, char *buf, int buflen ) { if( !PointerIsInAnySegment(pctx, rva) ) return -1; const unsigned char *pr = pctx->pRVAHeap; const unsigned char *pr_limit = (const unsigned char *)pctx->pFuncNameHeap; - int idx = 0; + size_t idx = 0; // Linearly unpack RVA deltas and find lower_bound rva -= pctx->nFirstRVA; - if( (signed)rva < 0 ) + if( static_cast(rva) < 0 ) return -1; while( pr < pr_limit ) @@ -205,7 +216,7 @@ namespace VDDebugInfo rva -= diff; - if ((signed)rva < 0) { + if (static_cast(rva) < 0) { rva += diff; break; } @@ -224,7 +235,7 @@ namespace VDDebugInfo strncpy( buf, fn_name, buflen ); buf[buflen-1] = 0; - return rva; + return static_cast(rva); } } @@ -234,7 +245,7 @@ bool ReadFromParent( int fd, void *p, int size ) int got = 0; while( got < size ) { - int ret = read( fd, buf+got, size-got ); + int ret = _read( fd, buf+got, size-got ); if( ret == -1 ) { if( errno == EINTR ) @@ -322,16 +333,16 @@ namespace SymbolLookup RString CrashChildGetModuleBaseName( HMODULE hMod ) { - write( _fileno(stdout), &hMod, sizeof(hMod) ); + _write( _fileno(stdout), &hMod, sizeof(hMod) ); - int iFD = fileno(stdin); + int iFD = _fileno(stdin); int iSize; if (!ReadFromParent(iFD, &iSize, sizeof(iSize))) { return "???"; } RString sName; - char *buffer = new char[iSize + 1]; + char *buffer = new char[static_cast(iSize) + 1]; std::fill(buffer, buffer + iSize + 1, '\0'); if (!ReadFromParent(iFD, buffer, iSize)) { @@ -357,11 +368,11 @@ namespace SymbolLookup VirtualQueryEx( g_hParent, ptr, &meminfo, sizeof meminfo ); char tmp[512]; - uintptr_t iAddress = VDDebugInfo::VDDebugInfoLookupRVA(pctx, reinterpret_cast(ptr), tmp, sizeof(tmp)); + intptr_t iAddress = VDDebugInfo::VDDebugInfoLookupRVA(pctx, reinterpret_cast(ptr), tmp, sizeof(tmp)); if( iAddress >= 0 ) { - wsprintf( buf, "%p: %s [%p+%Ix+%Ix]", ptr, Demangle(tmp), - reinterpret_cast(pctx->nFirstRVA), + wsprintf( buf, "%" ADDRESS_ZEROS "Ix: %s [%" ADDRESS_ZEROS "Ix+%Ix+%Ix]", reinterpret_cast(ptr), Demangle(tmp), + pctx->nFirstRVA, reinterpret_cast(ptr) - pctx->nFirstRVA - iAddress, iAddress ); return; @@ -374,17 +385,17 @@ namespace SymbolLookup if( pSymbol ) { - wsprintf( buf, "%p: %s!%s [%p+%Ix+%Ix]", - ptr, sName.c_str(), pSymbol->Name, - meminfo.AllocationBase, + wsprintf( buf, "%" ADDRESS_ZEROS "Ix: %s!%s [%" ADDRESS_ZEROS "Ix+%Ix+%Ix]", + reinterpret_cast(ptr), sName.c_str(), pSymbol->Name, + reinterpret_cast(meminfo.AllocationBase), static_cast(pSymbol->Address) - reinterpret_cast(meminfo.AllocationBase), static_cast(disp)); return; } - wsprintf( buf, "%p: %s!%p", - ptr, sName.c_str(), - meminfo.AllocationBase ); + wsprintf( buf, "%" ADDRESS_ZEROS "Ix: %s!%" ADDRESS_ZEROS "Ix", + reinterpret_cast(ptr), sName.c_str(), + reinterpret_cast(meminfo.AllocationBase) ); } } @@ -518,7 +529,7 @@ bool ReadCrashDataFromParent( int iFD, CompleteCrashData &Data ) if( !ReadFromParent(iFD, &iSize, sizeof(iSize)) ) return false; - char *buffer = new char[iSize + 1]; + char *buffer = new char[static_cast(iSize) + 1]; std::fill(buffer, buffer + iSize + 1, '\0'); bool wasReadSuccessful = ReadFromParent(iFD, buffer, iSize); RString tmp = buffer; @@ -861,7 +872,7 @@ void ChildProcess() { // Read the crash data from the crashed parent. CompleteCrashData Data; - ReadCrashDataFromParent( fileno(stdin), Data ); + ReadCrashDataFromParent( _fileno(stdin), Data ); RString sCrashReport; VDDebugInfo::VDDebugInfoInitFromFile( &g_debugInfo ); diff --git a/src/archutils/Win32/mapconv.cpp b/src/archutils/Win32/mapconv.cpp index 3a5e142592..8d7efd5b05 100644 --- a/src/archutils/Win32/mapconv.cpp +++ b/src/archutils/Win32/mapconv.cpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include #include @@ -13,7 +15,7 @@ #define MAX_GROUPS (64) struct RVAEnt { - long rva; + uintptr_t rva; char *line; }; @@ -22,10 +24,10 @@ std::vector rvabuf; char fnambuf[MAX_FNAMBUF]; char *fnamptr = fnambuf; -long segbuf[MAX_SEGMENTS][2]; -int segcnt=0; -int seggrp[MAX_SEGMENTS]; -long grpstart[MAX_GROUPS]; +uintptr_t segbuf[MAX_SEGMENTS][2]; +int segcnt = 0; +uint16_t seggrp[MAX_SEGMENTS]; +uintptr_t grpstart[MAX_GROUPS]; char line[8192]; long codeseg_flags = 0; @@ -91,7 +93,7 @@ void RemoveAnonymousNamespaces( char *p ) } -void parsename(long rva, char *func_name) { +void parsename(uintptr_t rva, char *func_name) { RemoveAnonymousNamespaces( func_name ); fnamptr = strtack(fnamptr, func_name, fnambuf+MAX_FNAMBUF); @@ -106,16 +108,13 @@ struct RVASorter { }; int main(int argc, char **argv) { - int i; - long load_addr; - - if (argc<3) { + if (argc < 3) { printf("mapconv \n"); return 0; } // TODO: Choose a better default for the vdi file. - int ver = 20151002; + int ver = 20191004; if (!(f=fopen(argv[1], "r"))) { printf("can't open listing file \"%s\"\n", argv[1]); @@ -139,19 +138,21 @@ int main(int argc, char **argv) { // printf("Reading in segment list.\n"); - while(readline()) { - long grp, start, len; + while (readline()) { + uint16_t grp; + uint32_t start; + uint32_t len; - if (3!=sscanf(line, "%lx:%lx %lx", &grp, &start, &len)) + if (sscanf(line, "%" SCNx16 ":%" SCNx32 " %" SCNx32, &grp, &start, &len) != 3) break; - if (strstr(line+49, "CODE")) { -// printf("%04x:%08lx %08lx type code\n", grp, start, len); + if (strstr(line + 49, "CODE")) { +// printf("%04" PRIx16 ":%08" PRIx32 " %08" PRIx32 " type code\n", grp, start, len); - codeseg_flags |= 1<(start); + segbuf[segcnt][1] = static_cast(len); seggrp[segcnt] = grp; ++segcnt; } @@ -166,22 +167,27 @@ int main(int argc, char **argv) { // printf("Found public symbol list.\n"); - while(readline()) { - long grp, start, rva; + while (readline()) { + uint16_t grp; + uint32_t start; + uintptr_t rva; char symname[2048]; - int i; - if (4!=sscanf(line, "%lx:%lx %s %lx", &grp, &start, symname, &rva)) + if (sscanf(line, "%" SCNx16 ":%" SCNx32 " %s %" SCNxPTR, &grp, &start, symname, &rva) != 4) break; - if (!(codeseg_flags & (1<(start); parsename(rva, symname); } // printf("Processing segment entries...\n"); - for(i=0; i(segbuf[i][0]), reinterpret_cast(segbuf[i][0] + segbuf[i][1] - 1)); } /* printf("Raw statistics:\n"); - printf("\tRVA bytes: %ld\n", rvabuf.size()*4); - printf("\tFunc name bytes: %ld\n", fnamptr - fnambuf); + printf("\tRVA bytes: %zu\n", rvabuf.size() * 4); + printf("\tFunc name bytes: %" PRIdPTR "\n", static_cast(fnamptr - fnambuf)); printf("\nPacking RVA data..."); fflush(stdout); */ std::vector::iterator itRVA = rvabuf.begin(), itRVAEnd = rvabuf.end(); std::vector rvaout; - long firstrva = (*itRVA++).rva; - long lastrva = firstrva; + uintptr_t firstrva = (*itRVA++).rva; + uintptr_t lastrva = firstrva; for(; itRVA != itRVAEnd; ++itRVA) { - long rvadiff = (*itRVA).rva - lastrva; + ptrdiff_t rvadiff = (*itRVA).rva - lastrva; lastrva += rvadiff; - if (rvadiff & 0xF0000000) rvaout.push_back((char)(0x80 | ((rvadiff>>28) & 0x7F))); - if (rvadiff & 0xFFE00000) rvaout.push_back((char)(0x80 | ((rvadiff>>21) & 0x7F))); - if (rvadiff & 0xFFFFC000) rvaout.push_back((char)(0x80 | ((rvadiff>>14) & 0x7F))); - if (rvadiff & 0xFFFFFF80) rvaout.push_back((char)(0x80 | ((rvadiff>> 7) & 0x7F))); +#if _WIN64 + if (rvadiff & 0x8000000000000000) rvaout.push_back((char)(0x80 | ((rvadiff >> 63) & 0x7F))); + if (rvadiff & 0xFF00000000000000) rvaout.push_back((char)(0x80 | ((rvadiff >> 56) & 0x7F))); + if (rvadiff & 0xFFFE000000000000) rvaout.push_back((char)(0x80 | ((rvadiff >> 49) & 0x7F))); + if (rvadiff & 0xFFFFFC0000000000) rvaout.push_back((char)(0x80 | ((rvadiff >> 42) & 0x7F))); + if (rvadiff & 0xFFFFFFF800000000) rvaout.push_back((char)(0x80 | ((rvadiff >> 35) & 0x7F))); + if (rvadiff & 0xFFFFFFFFF0000000) rvaout.push_back((char)(0x80 | ((rvadiff >> 28) & 0x7F))); + if (rvadiff & 0xFFFFFFFFFFE00000) rvaout.push_back((char)(0x80 | ((rvadiff >> 21) & 0x7F))); + if (rvadiff & 0xFFFFFFFFFFFFC000) rvaout.push_back((char)(0x80 | ((rvadiff >> 14) & 0x7F))); + if (rvadiff & 0xFFFFFFFFFFFFFF80) rvaout.push_back((char)(0x80 | ((rvadiff >> 7) & 0x7F))); +#else + if (rvadiff & 0xF0000000) rvaout.push_back((char)(0x80 | ((rvadiff >> 28) & 0x7F))); + if (rvadiff & 0xFFE00000) rvaout.push_back((char)(0x80 | ((rvadiff >> 21) & 0x7F))); + if (rvadiff & 0xFFFFC000) rvaout.push_back((char)(0x80 | ((rvadiff >> 14) & 0x7F))); + if (rvadiff & 0xFFFFFF80) rvaout.push_back((char)(0x80 | ((rvadiff >> 7) & 0x7F))); +#endif rvaout.push_back((char)(rvadiff & 0x7F)); } -// printf("%ld bytes\n", rvaout.size()); +// printf("%zu bytes\n", rvaout.size()); // dump data - static const char header[64]="symbolic debug information\r\n\x1A"; + static const char header[64] = "symbolic debug information\r\n\x1A"; fwrite(header, 64, 1, fo); - long t; + size_t t; - t = ver; - fwrite(&t, 4, 1, fo); + fwrite(&ver, sizeof ver, 1, fo); - t = rvaout.size() + 4; - fwrite(&t, 4, 1, fo); + t = rvaout.size() + sizeof firstrva; + fwrite(&t, sizeof t, 1, fo); t = fnamptr - fnambuf; - fwrite(&t, 4, 1, fo); + fwrite(&t, sizeof t, 1, fo); - t = segcnt; - fwrite(&t, 4, 1, fo); + fwrite(&segcnt, sizeof segcnt, 1, fo); - fwrite(&firstrva, 4, 1, fo); + fwrite(&firstrva, sizeof firstrva, 1, fo); fwrite(&rvaout[0], rvaout.size(), 1, fo); fwrite(fnambuf, fnamptr - fnambuf, 1, fo); - fwrite(segbuf, segcnt*8, 1, fo); + fwrite(segbuf, segcnt * 2 * sizeof(uintptr_t), 1, fo); // really all done if (fclose(fo)) throw "output file close failed"; - } catch(const char *s) { + } catch (const char *s) { fprintf(stderr, "%s: %s\n", argv[1], s); }