+/*
+ * We need to check if there could be a problem if the dtrace probes are being removed and the code is being
+ * executed at the same time. This sequence may leave us with no-execute turned on temporarily when we execute
+ * through it.
+ */
+
+ if (!(info.protection & VM_PROT_WRITE)) {
+ /* Save the original protection values for restoration later */
+ reprotect = info.protection;
+
+ if (info.max_protection & VM_PROT_WRITE) {
+ /* The memory is not currently writable, but can be made writable. */
+ ret = mach_vm_protect(map, (mach_vm_offset_t)vaddr, (mach_vm_size_t)4, 0, reprotect | VM_PROT_WRITE);
+ }
+ else {
+ /*
+ * The memory is not currently writable, and cannot be made writable. We need to COW this memory.
+ *
+ * Strange, we can't just say "reprotect | VM_PROT_COPY", that fails.
+ */
+ ret = mach_vm_protect(map, (mach_vm_offset_t)vaddr, (mach_vm_size_t)4, 0, VM_PROT_COPY | VM_PROT_READ | VM_PROT_WRITE);
+ }
+
+ if (ret != KERN_SUCCESS) {
+ vm_map_deallocate(map); /* Drop reference on map */
+ return (-1);
+ }
+
+ }
+ else {
+ /* The memory was already writable. */
+ reprotect = VM_PROT_NONE;
+ }
+
+ instr = inst; /* Place instruction in local memory */
+ ret = vm_map_write_user(map, &inst, (vm_map_address_t)vaddr, (vm_size_t)4); /* Write the instruction */
+ if (ret != KERN_SUCCESS) { /* Leave if it didn't work */
+
+ if (reprotect != VM_PROT_NONE) {
+ ret = mach_vm_protect (map, (mach_vm_offset_t)vaddr, (mach_vm_size_t)4, 0, reprotect);
+ }
+
+ vm_map_deallocate(map); /* Drop reference on map */
+ return (-1);
+ }
+
+ paddr = (addr64_t)pmap_find_phys(map->pmap, vaddr) << 12; /* Find the physical address of the patched address */
+ if(!paddr) { /* Is address mapped now? */
+ vm_map_deallocate(map); /* Drop reference on map */
+ return 0; /* Leave... */
+ }
+ paddr = paddr | (vaddr & 4095); /* Construct physical address */
+ invalidate_icache64(paddr, 4, 1); /* Flush out the instruction cache here */
+
+ if (reprotect != VM_PROT_NONE) {
+ ret = mach_vm_protect(map, (mach_vm_offset_t)vaddr, (mach_vm_size_t)4, 0, reprotect);
+ }
+
+ vm_map_deallocate(map);
+
+ return (0);