/* * Read a section from a file and write data to a corresponding memory region */ int loadMemoryRange(std::ifstream& infile, Memory& memory,const std::string name, uint16_t size){ uint16_t addr = 0; char byte = 0; uint16_t cnt = 0; MemoryRange* range = memory.getRangeByName(name); if (range == nullptr){ return 1; } addr = range->getStart(); MemoryTransaction req = MemoryTransaction(addr, (uint32_t*)&byte, 1, 0, 1); // read and write to memory byte by byte because why not, overall size is not that big anyways while (cnt < size){ if (infile.get(byte)){ req.addr = addr; range->directAccess(&req); addr++; cnt++; } else{ break; } } if (size != cnt) return 2; return 0; }
// RegValueHome::GetEnregisteredValue // Gets an enregistered value and returns it to the caller (see EnregisteredValueHome::GetEnregisteredValue // for full header comment) void RegValueHome::GetEnregisteredValue(MemoryRange valueOutBuffer) { UINT_PTR* reg = m_pFrame->GetAddressOfRegister(m_reg1Info.m_kRegNumber); PREFIX_ASSUME(reg != NULL); _ASSERTE(sizeof(*reg) == valueOutBuffer.Size()); memcpy(valueOutBuffer.StartAddress(), reg, sizeof(*reg)); } // RegValueHome::GetEnregisteredValue
HRESULT DacReplacePatchesInHostMemory(MemoryRange range, PVOID pBuffer) { SUPPORTS_DAC; // If the patch table is invalid, then there is no patch to replace. if (!DebuggerController::GetPatchTableValid()) { return S_OK; } HASHFIND info; DebuggerPatchTable * pTable = DebuggerController::GetPatchTable(); DebuggerControllerPatch * pPatch = pTable->GetFirstPatch(&info); // <PERF> // The unwinder needs to read the stack very often to restore pushed registers, retrieve the // return addres, etc. However, stack addresses should never be patched. // One way to optimize this code is to pass the stack base and the stack limit of the thread to this // function and use those two values to filter out stack addresses. // // Another thing we can do is instead of enumerating the patches, we could enumerate the address. // This is more efficient when we have a large number of patches and a small memory range. Perhaps // we could do a hybrid approach, i.e. use the size of the range and the number of patches to dynamically // determine which enumeration is more efficient. // </PERF> while (pPatch != NULL) { CORDB_ADDRESS patchAddress = (CORDB_ADDRESS)dac_cast<TADDR>(pPatch->address); if (patchAddress != NULL) { PRD_TYPE opcode = pPatch->opcode; CORDB_ADDRESS address = (CORDB_ADDRESS)(dac_cast<TADDR>(range.StartAddress())); SIZE_T cbSize = range.Size(); // Check if the address of the patch is in the specified memory range. if (IsPatchInRequestedRange(address, cbSize, patchAddress)) { // Replace the patch in the buffer with the original opcode. CORDbgSetInstructionEx(reinterpret_cast<PBYTE>(pBuffer), address, patchAddress, opcode, cbSize); } } pPatch = pTable->GetNextPatch(&info); } return S_OK; }
// RegRegValueHome::GetEnregisteredValue // Gets an enregistered value and returns it to the caller (see EnregisteredValueHome::GetEnregisteredValue // for full header comment) void RegRegValueHome::GetEnregisteredValue(MemoryRange valueOutBuffer) { UINT_PTR* highWordAddr = m_pFrame->GetAddressOfRegister(m_reg1Info.m_kRegNumber); PREFIX_ASSUME(highWordAddr != NULL); UINT_PTR* lowWordAddr = m_pFrame->GetAddressOfRegister(m_reg2Info.m_kRegNumber); PREFIX_ASSUME(lowWordAddr != NULL); _ASSERTE(sizeof(*highWordAddr) + sizeof(*lowWordAddr) == valueOutBuffer.Size()); memcpy(valueOutBuffer.StartAddress(), lowWordAddr, sizeof(*lowWordAddr)); memcpy((BYTE *)valueOutBuffer.StartAddress() + sizeof(*lowWordAddr), highWordAddr, sizeof(*highWordAddr)); } // RegRegValueHome::GetEnregisteredValue
// RegValueHome::SetEnregisteredValue // set a remote enregistered location to a new value (see code:EnregisteredValueHome::SetEnregisteredValue // for full header comment) void RegValueHome::SetEnregisteredValue(MemoryRange newValue, DT_CONTEXT * pContext, bool fIsSigned) { SIZE_T extendedVal = 0; // If the value is in a reg, then it's going to be a register's width (regardless of // the actual width of the data). // For signed types, like i2, i1, make sure we sign extend. if (fIsSigned) { // Sign extend. SSIZE_T is a register size signed value. // Casting switch(newValue.Size()) { case 1: _ASSERTE(sizeof( BYTE) == 1); extendedVal = (SSIZE_T) *(char*)newValue.StartAddress(); break; case 2: _ASSERTE(sizeof( WORD) == 2); extendedVal = (SSIZE_T) *(short*)newValue.StartAddress(); break; case 4: _ASSERTE(sizeof(DWORD) == 4); extendedVal = (SSIZE_T) *(int*)newValue.StartAddress(); break; #if defined(DBG_TARGET_WIN64) case 8: _ASSERTE(sizeof(ULONGLONG) == 8); extendedVal = (SSIZE_T) *(ULONGLONG*)newValue.StartAddress(); break; #endif // DBG_TARGET_WIN64 default: _ASSERTE(!"bad size"); } } else { // Zero extend. switch(newValue.Size()) { case 1: _ASSERTE(sizeof( BYTE) == 1); extendedVal = *( BYTE*)newValue.StartAddress(); break; case 2: _ASSERTE(sizeof( WORD) == 2); extendedVal = *( WORD*)newValue.StartAddress(); break; case 4: _ASSERTE(sizeof(DWORD) == 4); extendedVal = *(DWORD*)newValue.StartAddress(); break; #if defined(DBG_TARGET_WIN64) case 8: _ASSERTE(sizeof(ULONGLONG) == 8); extendedVal = *(ULONGLONG*)newValue.StartAddress(); break; #endif // DBG_TARGET_WIN64 default: _ASSERTE(!"bad size"); } } SetContextRegister(pContext, m_reg1Info.m_kRegNumber, extendedVal); // throws } // RegValueHome::SetEnregisteredValue
// RegRegValueHome::SetEnregisteredValue // set a remote enregistered location to a new value (see EnregisteredValueHome::SetEnregisteredValue // for full header comment) void RegRegValueHome::SetEnregisteredValue(MemoryRange newValue, DT_CONTEXT * pContext, bool fIsSigned) { _ASSERTE(newValue.Size() == 8); _ASSERTE(REG_SIZE == sizeof(void*)); // Split the new value into high and low parts. SIZE_T highPart; SIZE_T lowPart; memcpy(&lowPart, newValue.StartAddress(), REG_SIZE); memcpy(&highPart, (BYTE *)newValue.StartAddress() + REG_SIZE, REG_SIZE); // Update the proper registers. SetContextRegister(pContext, m_reg1Info.m_kRegNumber, highPart); // throws SetContextRegister(pContext, m_reg2Info.m_kRegNumber, lowPart); // throws // update the frame's register display void * valueAddress = (void *)(m_pFrame->GetAddressOfRegister(m_reg1Info.m_kRegNumber)); memcpy(valueAddress, newValue.StartAddress(), newValue.Size()); } // RegRegValueHome::SetEnregisteredValue
// initialize an instance of RemoteAddress for use in an IPC event buffer with values from this // instance of a derived class of EnregisteredValueHome (see EnregisteredValueHome::CopyToIPCEType for full // header comment) void RegMemValueHome::CopyToIPCEType(RemoteAddress * pRegAddr) { pRegAddr->kind = RAK_REGMEM; pRegAddr->reg1 = m_reg1Info.m_kRegNumber; pRegAddr->reg1Addr = CORDB_ADDRESS_TO_PTR(m_reg1Info.m_regAddr); pRegAddr->reg1Value = m_reg1Info.m_regValue; pRegAddr->addr = m_memAddr; } // RegMemValueHome::CopyToIPCEType // RegMemValueHome::SetEnregisteredValue // set a remote enregistered location to a new value (see EnregisteredValueHome::SetEnregisteredValue // for full header comment) void RegMemValueHome::SetEnregisteredValue(MemoryRange newValue, DT_CONTEXT * pContext, bool fIsSigned) { _ASSERTE(newValue.Size() == REG_SIZE >> 1); // make sure we have bytes for two registers _ASSERTE(REG_SIZE == sizeof(void*)); // Split the new value into high and low parts. SIZE_T highPart; SIZE_T lowPart; memcpy(&lowPart, newValue.StartAddress(), REG_SIZE); memcpy(&highPart, (BYTE *)newValue.StartAddress() + REG_SIZE, REG_SIZE); // Update the proper registers. SetContextRegister(pContext, m_reg1Info.m_kRegNumber, highPart); // throws _ASSERTE(REG_SIZE == sizeof(lowPart));