From 22c9cb17f3ce62ce719ebe57f0801c7208907d5c Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Wed, 1 Oct 2003 20:54:37 +0000 Subject: [PATCH] simplify --- stepmania/src/StepMania.dsp | 62 ++++----- stepmania/src/StepMania.vcproj | 4 +- stepmania/src/archutils/Win32/Crash.cpp | 170 +++++++++--------------- stepmania/src/disasm/mapconv.cpp | 134 +------------------ stepmania/src/disasm/mapconv.exe | Bin 61440 -> 61440 bytes 5 files changed, 105 insertions(+), 265 deletions(-) diff --git a/stepmania/src/StepMania.dsp b/stepmania/src/StepMania.dsp index 8bb3c46b5d..7c3a724765 100644 --- a/stepmania/src/StepMania.dsp +++ b/stepmania/src/StepMania.dsp @@ -65,8 +65,8 @@ IntDir=.\../Debug6 TargetDir=\temp\stepmania TargetName=StepMania-debug SOURCE="$(InputPath)" -PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ -PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi +PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ +PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi # End Special Build Tool !ELSEIF "$(CFG)" == "StepMania - Xbox Debug" @@ -82,23 +82,23 @@ PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" -XBCP=xbecopy.exe -# ADD BASE XBCP /NOLOGO -# ADD XBCP /NOLOGO -XBE=imagebld.exe -# ADD BASE XBE /nologo /stack:0x10000 /debug -# ADD XBE /nologo /stack:0x10000 /debug /out:"../default.xbe" -LINK32=link.exe -# ADD BASE LINK32 xapilibd.lib d3d8d.lib d3dx8d.lib xgraphicsd.lib dsoundd.lib dmusicd.lib xnetd.lib xboxkrnl.lib /nologo /incremental:no /debug /machine:I386 /subsystem:xbox /fixed:no /TMP -# ADD LINK32 xapilibd.lib d3d8d.lib d3dx8d.lib xgraphicsd.lib dsoundd.lib dmusicd.lib xnetd.lib xboxkrnl.lib /nologo /incremental:no /debug /machine:I386 /nodefaultlib:"libcd" /nodefaultlib:"libcmt" /out:"../StepManiaXbox-debug.exe" /subsystem:xbox /fixed:no /TMP -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo CPP=cl.exe # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_XBOX" /D "_DEBUG" /YX /FD /G6 /Ztmp /c # ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "." /I "SDL-1.2.5\include" /I "SDL_image-1.2" /I "plib-1.6.0" /I "SDL_sound-1.0.0" /D "WIN32" /D "_XBOX" /D "_DEBUG" /D "OGG_ONLY" /YX /FD /G6 /Ztmp /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 xapilibd.lib d3d8d.lib d3dx8d.lib xgraphicsd.lib dsoundd.lib dmusicd.lib xnetd.lib xboxkrnl.lib /nologo /incremental:no /debug /machine:I386 /subsystem:xbox /fixed:no /TMP +# ADD LINK32 xapilibd.lib d3d8d.lib d3dx8d.lib xgraphicsd.lib dsoundd.lib dmusicd.lib xnetd.lib xboxkrnl.lib /nologo /incremental:no /debug /machine:I386 /nodefaultlib:"libcd" /nodefaultlib:"libcmt" /out:"../StepManiaXbox-debug.exe" /subsystem:xbox /fixed:no /TMP +XBE=imagebld.exe +# ADD BASE XBE /nologo /stack:0x10000 /debug +# ADD XBE /nologo /stack:0x10000 /debug /out:"../default.xbe" +XBCP=xbecopy.exe +# ADD BASE XBCP /NOLOGO +# ADD XBCP /NOLOGO # Begin Special Build Tool -PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ +PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi # End Special Build Tool @@ -138,8 +138,8 @@ IntDir=.\../Release6 TargetDir=\temp\stepmania TargetName=StepMania SOURCE="$(InputPath)" -PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ -PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi +PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ +PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi # End Special Build Tool !ELSEIF "$(CFG)" == "StepMania - Xbox Release" @@ -156,26 +156,26 @@ PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania # PROP Intermediate_Dir "StepMania___Xbox_Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" -XBCP=xbecopy.exe -# ADD BASE XBCP /NOLOGO -# ADD XBCP /NOLOGO -XBE=imagebld.exe -# ADD BASE XBE /nologo /stack:0x10000 /debug -# ADD XBE /nologo /testid:"123456" /stack:0x10000 /debug /out:"../default.xbe" +CPP=cl.exe +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "." /I "SDL-1.2.5\include" /I "SDL_image-1.2" /I "plib-1.6.0" /D "WIN32" /D "_XBOX" /D "_DEBUG" /Fr /YX"global.h" /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I "SDL-1.2.5\include" /I "SDL_image-1.2" /I "plib-1.6.0" /I "SDL_sound-1.0.0" /D "WIN32" /D "_XBOX" /D "NDEBUG" /YX"global.h" /FD /c +# SUBTRACT CPP /Fr +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 $(intdir)\verstub.obj xapilibd.lib d3d8d.lib d3dx8d.lib xgraphicsd.lib dsoundd.lib dmusicd.lib xnetd.lib xboxkrnl.lib /nologo /pdb:"../debug6/StepMania-debug.pdb" /map /debug /machine:IX86 /nodefaultlib:"libcmtd.lib" /out:"../StepMania-debug.exe" # SUBTRACT BASE LINK32 /verbose /profile /pdb:none /incremental:no /nodefaultlib # ADD LINK32 $(intdir)\verstub.obj xapilib.lib d3d8.lib d3dx8.lib xgraphics.lib dsound.lib dmusic.lib xnet.lib xboxkrnl.lib libcmt.lib /nologo /incremental:no /pdb:"../release6xbox/StepMania.pdb" /machine:I386 /nodefaultlib:"libc" /nodefaultlib:"libcmtd" /out:"../StepManiaXbox.exe" /subsystem:xbox /fixed:no /TMP /OPT:REF # SUBTRACT LINK32 /pdb:none /map /debug -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -CPP=cl.exe -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "." /I "SDL-1.2.5\include" /I "SDL_image-1.2" /I "plib-1.6.0" /D "WIN32" /D "_XBOX" /D "_DEBUG" /Fr /YX"global.h" /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I "SDL-1.2.5\include" /I "SDL_image-1.2" /I "plib-1.6.0" /I "SDL_sound-1.0.0" /D "WIN32" /D "_XBOX" /D "NDEBUG" /YX"global.h" /FD /c -# SUBTRACT CPP /Fr +XBE=imagebld.exe +# ADD BASE XBE /nologo /stack:0x10000 /debug +# ADD XBE /nologo /testid:"123456" /stack:0x10000 /debug /out:"../default.xbe" +XBCP=xbecopy.exe +# ADD BASE XBCP /NOLOGO +# ADD XBCP /NOLOGO # Begin Special Build Tool -PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ +PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi # End Special Build Tool diff --git a/stepmania/src/StepMania.vcproj b/stepmania/src/StepMania.vcproj index c22dd1b58c..708301bac9 100644 --- a/stepmania/src/StepMania.vcproj +++ b/stepmania/src/StepMania.vcproj @@ -63,7 +63,7 @@ TypeLibraryName=".\../StepMania.tlb"/> + CommandLine="disasm\mapconv "$(IntDir)\$(TargetName).map" "$(TargetDir)\StepMania.vdi""/> + CommandLine="disasm\mapconv "$(IntDir)\$(TargetName).map" "$(TargetDir)\StepMania.vdi""/> ExceptionCode); + char buf[256] = ""; - if (hFile) - Report(hwnd, hFile, "Crash reason: unknown exception 0x%08lx", pRecord->ExceptionCode); - } else { - if (hwndReason) - SetWindowTitlef(hwndReason, "Crash reason: %s", pel->name); - - if (hFile) - Report(hwnd, hFile, "Crash reason: %s", pel->name); + if (!pel->code) + wsprintf( buf, "Crash reason: unknown exception 0x%08lx", pRecord->ExceptionCode ); + else + { + strcpy( buf, "Crash reason: " ); + strcat( buf, pel->name ); } + + if( hwndReason ) + SetWindowText( hwndReason, buf ); + + if( hFile ) + Report( NULL, hFile, buf ); } static const char *GetNameFromHeap(const char *heap, int idx) { @@ -348,13 +339,6 @@ static bool IsValidCall(char *buf, int len) { return false; } -/////////////////////////////////////////////////////////////////////////// -// -// info from Portable Executable/Common Object File Format (PE/COFF) spec - -typedef unsigned short ushort; -typedef unsigned long ulong; - /////////////////////////////////////////////////////////////////////////// static bool IsExecutableProtection(DWORD dwProtect) { @@ -422,36 +406,19 @@ bool VDDebugInfoInitFromMemory(VDDebugInfoContext *pctx, const void *_src) { pctx->pRVAHeap = NULL; - // Check type string - - if (!memcmp((char *)src + 6, "] StepMania disasm", 18)) - src += *(long *)(src + 64) + 72; - - if (src[0] != '[' || src[3] != '|') + if (memcmp((char *)src, "StepMania symbolic debug information", 36)) return false; - if (memcmp((char *)src + 6, "] StepMania symbolic debug information", 38)) - return false; - - // Check version number - -// int write_version = (src[1]-'0')*10 + (src[2] - '0'); - int compat_version = (src[4]-'0')*10 + (src[5] - '0'); - - if (compat_version > 1) - return false; // resource is too new for us to load - // Extract fields src += 64; pctx->nBuildNumber = *(int *)src; - pctx->pRVAHeap = (const unsigned char *)(src + 24); - pctx->nFirstRVA = *(const long *)(src + 20); - pctx->pClassNameHeap = (const char *)pctx->pRVAHeap - 4 + *(const long *)(src + 4); - pctx->pFuncNameHeap = pctx->pClassNameHeap + *(const long *)(src + 8); - pctx->pSegments = (unsigned long (*)[2])(pctx->pFuncNameHeap + *(const long *)(src + 12)); - pctx->nSegments = *(const long *)(src + 16); + 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 = (unsigned long (*)[2])(pctx->pFuncNameHeap + *(const long *)(src + 8)); + pctx->nSegments = *(const long *)(src + 12); return true; } @@ -501,19 +468,24 @@ bool VDDebugInfoInitFromFile(VDDebugInfoContext *pctx, const char *pszFilename) return false; } -long VDDebugInfoLookupRVA(VDDebugInfoContext *pctx, unsigned rva, char *buf, int buflen) { - int i; - - for(i=0; inSegments; ++i) { +static bool PointerIsInAnySegment( const VDDebugInfoContext *pctx, unsigned rva ) +{ + for( int i=0; inSegments; ++i ) + { if (rva >= pctx->pSegments[i][0] && rva < pctx->pSegments[i][0] + pctx->pSegments[i][1]) - break; + return true; } - if (i >= pctx->nSegments) + return false; +} + +long VDDebugInfoLookupRVA(VDDebugInfoContext *pctx, unsigned 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->pClassNameHeap; + const unsigned char *pr_limit = (const unsigned char *)pctx->pFuncNameHeap; int idx = 0; // Linearly unpack RVA deltas and find lower_bound @@ -542,22 +514,19 @@ long VDDebugInfoLookupRVA(VDDebugInfoContext *pctx, unsigned rva, char *buf, int ++idx; } + if (pr >= pr_limit) + return -1; // Decompress name for RVA + const char *fn_name = GetNameFromHeap(pctx->pFuncNameHeap, idx); - if (pr < pr_limit) { - const char *fn_name = GetNameFromHeap(pctx->pFuncNameHeap, idx); + if (!*fn_name) + fn_name = "(special)"; - if (!*fn_name) - fn_name = "(special)"; + strncpy( buf, fn_name, buflen ); + buf[buflen-1]=0; - // ehh... where's my wsnprintf? _snprintf() might allocate memory or locks.... - return wsprintf(buf, "%s", fn_name) >= 0 - ? rva - : -1; - } - - return -1; + return rva; } /////////////////////////////////////////////////////////////////////////// @@ -622,15 +591,21 @@ static const char *Demangle( const char *buf ) return obuf; } +static bool PointsToValidCall( unsigned long ptr ) +{ + char buf[7]; + int len = 7; + + memset( buf, 0, sizeof(buf) ); + + while(len > 0 && !ReadProcessMemory(GetCurrentProcess(), (void *)(ptr-len), buf+7-len, len, NULL)) + --len; + + return IsValidCall(buf+7, len); +} + static bool ReportCrashCallStack(HWND hwnd, HANDLE hFile, const EXCEPTION_POINTERS *const pExc) { - const CONTEXT *const pContext = (const CONTEXT *)pExc->ContextRecord; - HANDLE hprMe = GetCurrentProcess(); - char *lpAddr = (char *)pContext->Esp; - int limit = 100; - unsigned long data; - char buf[512]; - if (!g_debugInfo.pRVAHeap) { Report(hwnd, hFile, "Could not open debug resource file (StepMania.vdi)."); return false; @@ -641,11 +616,6 @@ static bool ReportCrashCallStack(HWND hwnd, HANDLE hFile, const EXCEPTION_POINTE return false; } - // Get some module names. - - void *pModuleMem; -// ModuleInfo *pModules = CrashGetModules(pModuleMem); - // Retrieve stack pointers. // Not sure if NtCurrentTeb() is available on Win95.... @@ -658,33 +628,28 @@ static bool ReportCrashCallStack(HWND hwnd, HANDLE hFile, const EXCEPTION_POINTE char *pStackBase = (char *)pTib->StackBase; + const CONTEXT *const pContext = (const CONTEXT *)pExc->ContextRecord; + const HANDLE hprMe = GetCurrentProcess(); + const char *lpAddr = (const char *)pContext->Esp; + int limit = 100; + // Walk up the stack. Hopefully it wasn't fscked. - data = pContext->Eip; + unsigned long data = pContext->Eip; do { bool fValid = true; - int len; MEMORY_BASIC_INFORMATION meminfo; VirtualQuery((void *)data, &meminfo, sizeof meminfo); - if (!IsExecutableProtection(meminfo.Protect) || meminfo.State!=MEM_COMMIT) { -// Report(NULL, hFile, "Rejected: %08lx (%08lx)", data, meminfo.Protect); + if (!IsExecutableProtection(meminfo.Protect) || meminfo.State!=MEM_COMMIT) fValid = false; - } - if (data != pContext->Eip) { - len = 7; - - *(long *)(buf + 0) = *(long *)(buf + 4) = 0; - - while(len > 0 && !ReadProcessMemory(GetCurrentProcess(), (void *)(data-len), buf+7-len, len, NULL)) - --len; - - fValid &= IsValidCall(buf+7, len); - } + if ( data != pContext->Eip && !PointsToValidCall(data) ) + fValid = false; if (fValid) { + char buf[512]; if (VDDebugInfoLookupRVA(&g_debugInfo, data, buf, sizeof buf) >= 0) { Report(hwnd, hFile, "%08lx: %s", data, Demangle(buf)); --limit; @@ -718,11 +683,6 @@ static bool ReportCrashCallStack(HWND hwnd, HANDLE hFile, const EXCEPTION_POINTE lpAddr += 4; } while(limit > 0 && ReadProcessMemory(hprMe, lpAddr-4, &data, 4, NULL)); - // All done, close up shop and exit. - - if (pModuleMem) - VirtualFree(pModuleMem, 0, MEM_RELEASE); - return true; } @@ -747,7 +707,7 @@ static void DoSave(const EXCEPTION_POINTERS *pExc) "--------------------------------------" "\r\n", PRODUCT_NAME_VER, version_num); - ReportReason(NULL, NULL, hFile, pExc); + ReportReason(NULL, hFile, pExc); Report(NULL, hFile, ""); // Dump thread stacks @@ -816,7 +776,7 @@ BOOL APIENTRY CrashDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { if (hFontMono) SendMessage(hwndList, WM_SETFONT, (WPARAM)hFontMono, MAKELPARAM(TRUE, 0)); - ReportReason(NULL, hwndReason, NULL, pExc); + ReportReason(hwndReason, NULL, pExc); s_bHaveCallstack = ReportCrashCallStack(hwndList, NULL, pExc); } return TRUE; diff --git a/stepmania/src/disasm/mapconv.cpp b/stepmania/src/disasm/mapconv.cpp index 1704504e0b..b19e49fcfc 100644 --- a/stepmania/src/disasm/mapconv.cpp +++ b/stepmania/src/disasm/mapconv.cpp @@ -37,9 +37,6 @@ std::vector rvabuf; char fnambuf[MAX_FNAMBUF]; char *fnamptr = fnambuf; -char cnambuf[MAX_CNAMBUF]; -char *cnamptr = cnambuf; - long segbuf[MAX_SEGMENTS][2]; int segcnt=0; int seggrp[MAX_SEGMENTS]; @@ -82,98 +79,8 @@ bool findline(const char *searchstr) { /////////////////////////////////////////////////////////////////////////// -void parsename(long rva, char *buf) { - char *func_name = NULL; -// char *class_name = NULL; -// char c; -// int special_func = 0; - -// if (*buf++ != '?') { - func_name = buf; -/* } else { - - if (*buf == '?') { - // ??0 - // ??1 - // ??_G - // ??_E - - ++buf; - c=*buf++; - - special_func = 31; - if (c=='0') - special_func = 1; // constructor - else if (c=='1') - special_func = 2; // destructor - else if (c=='_') { - c = *buf++; - - if (c == 'G') - special_func = 3; // scalar deleting destructor - else if (c == 'E') - special_func = 4; // vector deleting destructor? - } - } else { - func_name = buf; - - while(*buf != '@') { - if (!*buf) - throw "bad decorated name"; - - ++buf; - } - - *buf++ = 0; - } - - // Look for a class name. - - if (*buf != '@') { - if (!*buf) - throw "bad decorated name"; - - class_name = buf; - - while(*buf != '@') { - if (!*buf) - throw "bad decorated name (class)"; - - ++buf; - } - - *buf++ = 0; - } - } - // write out to buffers - - if (class_name) { - char *csptr = cnambuf; - int idx = 0; - - while(csptr < cnamptr) { - if (!strcmp(csptr, class_name)) { - break; - } - while(*csptr++); - ++idx; - } - - if (csptr >= cnamptr && strcmp(csptr, class_name) ) { - cnamptr = strtack(cnamptr, class_name, cnambuf+MAX_CNAMBUF); - if(!cnambuf) - throw "Too many class names; increase MAX_CNAMBUF."; - } - - *fnamptr++ = 1 + (idx / 128); - *fnamptr++ = 1 + (idx % 128); - - if (special_func) - *fnamptr++ = special_func; - } -*/ - - fnamptr = strtack(fnamptr, func_name? func_name:"", fnambuf+MAX_FNAMBUF); +void parsename(long rva, char *func_name) { + fnamptr = strtack(fnamptr, func_name, fnambuf+MAX_FNAMBUF); if(!fnamptr) throw "Too many func names; increase MAX_FNAMBUF."; } @@ -189,8 +96,8 @@ int main(int argc, char **argv) { int i; long load_addr; - if (argc<4) { - printf("mapconv \n"); + if (argc<3) { + printf("mapconv \n"); return 0; } @@ -212,27 +119,6 @@ int main(int argc, char **argv) { return 20; } - int disasm_size = 0; - { - FILE *fd; - - if (!(fd=fopen(argv[3], "rb"))) { - printf("can't open disassembler module \"%s\"\n", argv[3]); - return 20; - } - - void *buf = malloc(32768); - int act; - - while((act = fread(buf, 1, 32768, fd)) > 0) { - disasm_size += act; - fwrite(buf, act, 1, fo); - } - - free(buf); - fclose(fd); - } - // Begin parsing file try { @@ -340,9 +226,7 @@ int main(int argc, char **argv) { } /* printf("Raw statistics:\n"); - printf("\tDisassembler: %ld bytes\n", disasm_size); printf("\tRVA bytes: %ld\n", rvabuf.size()*4); - printf("\tClass name bytes: %ld\n", cnamptr - cnambuf); printf("\tFunc name bytes: %ld\n", fnamptr - fnambuf); printf("\nPacking RVA data..."); fflush(stdout); @@ -368,21 +252,18 @@ int main(int argc, char **argv) { // dump data - long t; - - static const char header[64]="[01|01] StepMania symbolic debug information\r\n\x1A"; + static const char header[64]="StepMania symbolic debug information\r\n\x1A"; fwrite(header, 64, 1, fo); + long t; + t = ver; fwrite(&t, 4, 1, fo); t = rvaout.size() + 4; fwrite(&t, 4, 1, fo); - t = cnamptr - cnambuf; - fwrite(&t, 4, 1, fo); - t = fnamptr - fnambuf; fwrite(&t, 4, 1, fo); @@ -391,7 +272,6 @@ int main(int argc, char **argv) { fwrite(&firstrva, 4, 1, fo); fwrite(&rvaout[0], rvaout.size(), 1, fo); - fwrite(cnambuf, cnamptr - cnambuf, 1, fo); fwrite(fnambuf, fnamptr - fnambuf, 1, fo); fwrite(segbuf, segcnt*8, 1, fo); diff --git a/stepmania/src/disasm/mapconv.exe b/stepmania/src/disasm/mapconv.exe index ad8d113b54234abcc77f8ee3d821f74fb48e16de..10a8ec11f275f881feb5d72f90313ad72d5751cc 100644 GIT binary patch delta 14142 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 delta 14337 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