debugserver memory writes and instruction-cache flushes
Region-aware debugger writes: temporarily make mapped memory writable, write page-sized chunks with mach_vm_write, and flush the target instruction cache on non-x86 systems.
MachVMMemory::Write source
nub_size_t MachVMMemory::Write(task_t task, nub_addr_t address, const void *data, nub_size_t data_count) { MachVMRegion vmRegion(task); nub_size_t total_bytes_written = 0; nub_addr_t curr_addr = address; const uint8_t *curr_data = (const uint8_t *)data; while (total_bytes_written < data_count) { if (vmRegion.GetRegionForAddress(curr_addr)) { mach_vm_size_t curr_data_count = data_count - total_bytes_written; mach_vm_size_t region_bytes_left = vmRegion.BytesRemaining(curr_addr); if (region_bytes_left == 0) { break; } if (curr_data_count > region_bytes_left) curr_data_count = region_bytes_left; if (vmRegion.SetProtections(curr_addr, curr_data_count, VM_PROT_READ | VM_PROT_WRITE)) { nub_size_t bytes_written = WriteRegion(task, curr_addr, curr_data, curr_data_count); if (bytes_written <= 0) { // Status should have already be posted by WriteRegion... break; } else { total_bytes_written += bytes_written; curr_addr += bytes_written; curr_data += bytes_written; } … more in source
MachVMMemory::WriteRegion source
nub_size_t MachVMMemory::WriteRegion(task_t task, const nub_addr_t address, const void *data, const nub_size_t data_count) { if (data == NULL || data_count == 0) return 0; nub_size_t total_bytes_written = 0; nub_addr_t curr_addr = address; const uint8_t *curr_data = (const uint8_t *)data; while (total_bytes_written < data_count) { mach_msg_type_number_t curr_data_count = static_cast<mach_msg_type_number_t>(MaxBytesLeftInPage( task, curr_addr, data_count - total_bytes_written)); m_err = ::mach_vm_write(task, curr_addr, (pointer_t)curr_data, curr_data_count); if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) m_err.LogThreaded("::mach_vm_write ( task = 0x%4.4x, addr = 0x%8.8llx, " "data = %8.8p, dataCnt = %u )", task, (uint64_t)curr_addr, curr_data, curr_data_count); #if !defined(__i386__) && !defined(__x86_64__) vm_machine_attribute_val_t mattr_value = MATTR_VAL_CACHE_FLUSH; m_err = ::vm_machine_attribute(task, curr_addr, curr_data_count, MATTR_CACHE, &mattr_value); if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) m_err.LogThreaded("::vm_machine_attribute ( task = 0x%4.4x, addr = " "0x%8.8llx, size = %u, attr = MATTR_CACHE, mattr_value " "=> MATTR_VAL_CACHE_FLUSH )", task, (uint64_t)curr_addr, curr_data_count); … more in source