bool compareMonoSysex(uint8_t *buf, uint8_t *buf2) { uint8_t buftmp[8192]; uint8_t buftmp2[8192]; uint16_t len = 0x1978; MNMSysexDecoder decoder(DATA_ENCODER_INIT(buf + 10, len - 10)); decoder.get(buftmp + 1, len - 10); MNMSysexDecoder decoder2(DATA_ENCODER_INIT(buf2 + 10, - 10)); decoder2.get(buftmp2 + 1, len - 10); for (uint16_t i = 1; i < len - 10; i++) { if (buftmp[i] != buftmp2[i]) { printf("mono sysex different at 0x%x, %x != %x\n", i, buftmp[i], buftmp2[i]); return false; } } return true; }
GcInfoDumper::EnumerateStateChangesResults GcInfoDumper::EnumerateStateChanges ( InterruptibleStateChangeProc *pfnInterruptibleStateChange, RegisterStateChangeProc *pfnRegisterStateChange, StackSlotStateChangeProc *pfnStackSlotStateChange, OnSafePointProc *pfnSafePointFunc, PVOID pvData) { m_Error = SUCCESS; // // Save callback functions for use by helper functions // m_pfnRegisterStateChange = pfnRegisterStateChange; m_pfnStackSlotStateChange = pfnStackSlotStateChange; m_pvCallbackData = pvData; // // Decode header information // GcInfoDecoder hdrdecoder(m_pbGCInfo, (GcInfoDecoderFlags)( DECODE_SECURITY_OBJECT | DECODE_CODE_LENGTH | DECODE_GC_LIFETIMES | DECODE_VARARG), 0); UINT32 cbEncodedMethodSize = hdrdecoder.GetCodeLength(); m_StackBaseRegister = hdrdecoder.GetStackBaseRegister(); // // Set up a bogus REGDISPLAY to pass to EnumerateLiveSlots. This will // allow us to later identify registers or stack offsets passed to the // callback. // REGDISPLAY regdisp; ZeroMemory(®disp, sizeof(regdisp)); regdisp.pContext = ®disp.ctxOne; regdisp.IsCallerContextValid = TRUE; regdisp.pCurrentContext = ®disp.ctxOne; regdisp.pCallerContext = ®disp.ctxTwo; #define NEXT_ADDRESS() (UniqueAddress += ADDRESS_SPACING) UINT iReg; #ifdef _WIN64 ULONG64 UniqueAddress = ADDRESS_SPACING*2; ULONG64 *pReg; #else DWORD UniqueAddress = ADDRESS_SPACING*2; DWORD *pReg; #endif #define FILL_REGS(start, count) \ do { \ for (iReg = 0, pReg = ®disp.start; iReg < count; iReg++, pReg++) \ { \ *pReg = NEXT_ADDRESS(); \ } \ } while (0) #ifdef _TARGET_AMD64_ FILL_REGS(pCurrentContext->Rax, 16); FILL_REGS(pCallerContext->Rax, 16); regdisp.pCurrentContextPointers = ®disp.ctxPtrsOne; regdisp.pCallerContextPointers = ®disp.ctxPtrsTwo; ULONGLONG **ppCurrentRax = ®disp.pCurrentContextPointers->Rax; ULONGLONG **ppCallerRax = ®disp.pCallerContextPointers ->Rax; for (iReg = 0; iReg < 16; iReg++) { *(ppCurrentRax + iReg) = ®disp.pCurrentContext->Rax + iReg; *(ppCallerRax + iReg) = ®disp.pCallerContext ->Rax + iReg; } #elif defined(_TARGET_ARM_) FILL_REGS(pCurrentContext->R0, 16); FILL_REGS(pCallerContext->R0, 16); regdisp.pCurrentContextPointers = ®disp.ctxPtrsOne; regdisp.pCallerContextPointers = ®disp.ctxPtrsTwo; ULONG **ppCurrentReg = ®disp.pCurrentContextPointers->R4; ULONG **ppCallerReg = ®disp.pCallerContextPointers->R4; for (iReg = 0; iReg < 8; iReg++) { *(ppCurrentReg + iReg) = ®disp.pCurrentContext->R4 + iReg; *(ppCallerReg + iReg) = ®disp.pCallerContext->R4 + iReg; } /// Set Lr *(ppCurrentReg + 8) = ®disp.pCurrentContext->R4 + 10; *(ppCallerReg + 8) = ®disp.pCallerContext->R4 + 10; ULONG **ppVolatileReg = ®disp.volatileCurrContextPointers.R0; for (iReg = 0; iReg < 4; iReg++) { *(ppVolatileReg+iReg) = ®disp.pCurrentContext->R0 + iReg; } /// Set R12 *(ppVolatileReg+4) = ®disp.pCurrentContext->R0+12; #endif #undef FILL_REGS #undef NEXT_ADDRESS SyncRegDisplayToCurrentContext(®disp); // // Enumerate pointers at every possible offset. // #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED GcInfoDecoder safePointDecoder(m_pbGCInfo, (GcInfoDecoderFlags)0, 0); #endif { GcInfoDecoder untrackedDecoder(m_pbGCInfo, DECODE_GC_LIFETIMES, 0); untrackedDecoder.EnumerateUntrackedSlots(®disp, 0, &LivePointerCallback, this); BOOL fStop = ReportPointerDifferences( -2, ®disp, NULL); FreePointerRecords(m_pRecords); m_pRecords = NULL; if (fStop || m_Error) return m_Error; } LivePointerRecord *pLastState = NULL; BOOL fPrevInterruptible = FALSE; for (UINT32 offset = 0; offset <= cbEncodedMethodSize; offset++) { BOOL fNewInterruptible = FALSE; GcInfoDecoder decoder1(m_pbGCInfo, (GcInfoDecoderFlags)( DECODE_SECURITY_OBJECT | DECODE_CODE_LENGTH | DECODE_VARARG | DECODE_INTERRUPTIBILITY), offset); fNewInterruptible = decoder1.IsInterruptible(); if (fNewInterruptible != fPrevInterruptible) { if (pfnInterruptibleStateChange(offset, fNewInterruptible, pvData)) break; fPrevInterruptible = fNewInterruptible; } unsigned flags = ActiveStackFrame; #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED UINT32 safePointOffset = offset; #if defined(_TARGET_AMD64_) || defined(_TARGET_ARM_) safePointOffset++; #endif if(safePointDecoder.IsSafePoint(safePointOffset)) { _ASSERTE(!fNewInterruptible); if (pfnSafePointFunc(offset, pvData)) break; flags = 0; } #endif GcInfoDecoder decoder2(m_pbGCInfo, (GcInfoDecoderFlags)( DECODE_SECURITY_OBJECT | DECODE_CODE_LENGTH | DECODE_VARARG | DECODE_GC_LIFETIMES | DECODE_NO_VALIDATION), offset); _ASSERTE(!m_pRecords); if(!fNewInterruptible && (flags == ActiveStackFrame)) { // Decoding at non-interruptible offsets is only // valid in the ExecutionAborted case flags |= ExecutionAborted; } if (!decoder2.EnumerateLiveSlots( ®disp, true, flags | NoReportUntracked, &LivePointerCallback, this)) { m_Error = DECODER_FAILED; } if (m_Error) break; if (ReportPointerDifferences( offset, ®disp, pLastState)) { break; } if (m_Error) break; FreePointerRecords(pLastState); pLastState = m_pRecords; m_pRecords = NULL; size_t tempSize = decoder2.GetNumBytesRead(); if( m_gcInfoSize < tempSize ) m_gcInfoSize = tempSize; } FreePointerRecords(pLastState); FreePointerRecords(m_pRecords); m_pRecords = NULL; return m_Error; }