+/* Call FUNC on each memory region in the task. */
+static int
+gnu_find_memory_regions (int (*func) (CORE_ADDR,
+ unsigned long,
+ int, int, int,
+ void *),
+ void *data)
+{
+ error_t err;
+ task_t task;
+ vm_address_t region_address, last_region_address, last_region_end;
+ vm_prot_t last_protection;
+
+ if (gnu_current_inf == 0 || gnu_current_inf->task == 0)
+ return 0;
+ task = gnu_current_inf->task->port;
+ if (task == MACH_PORT_NULL)
+ return 0;
+
+ region_address = last_region_address = last_region_end = VM_MIN_ADDRESS;
+ last_protection = VM_PROT_NONE;
+ while (region_address < VM_MAX_ADDRESS)
+ {
+ vm_prot_t protection;
+ vm_prot_t max_protection;
+ vm_inherit_t inheritance;
+ boolean_t shared;
+ mach_port_t object_name;
+ vm_offset_t offset;
+ vm_size_t region_length = VM_MAX_ADDRESS - region_address;
+ vm_address_t old_address = region_address;
+
+ err = vm_region (task,
+ ®ion_address,
+ ®ion_length,
+ &protection,
+ &max_protection,
+ &inheritance,
+ &shared,
+ &object_name,
+ &offset);
+ if (err == KERN_NO_SPACE)
+ break;
+ if (err != KERN_SUCCESS)
+ {
+ warning (_("vm_region failed: %s"), mach_error_string (err));
+ return -1;
+ }
+
+ if (protection == last_protection && region_address == last_region_end)
+ /* This region is contiguous with and indistinguishable from
+ the previous one, so we just extend that one. */
+ last_region_end = region_address += region_length;
+ else
+ {
+ /* This region is distinct from the last one we saw, so report
+ that previous one. */
+ if (last_protection != VM_PROT_NONE)
+ (*func) (last_region_address,
+ last_region_end - last_region_address,
+ last_protection & VM_PROT_READ,
+ last_protection & VM_PROT_WRITE,
+ last_protection & VM_PROT_EXECUTE,
+ data);
+ last_region_address = region_address;
+ last_region_end = region_address += region_length;
+ last_protection = protection;
+ }
+ }
+
+ /* Report the final region. */
+ if (last_region_end > last_region_address && last_protection != VM_PROT_NONE)
+ (*func) (last_region_address, last_region_end - last_region_address,
+ last_protection & VM_PROT_READ,
+ last_protection & VM_PROT_WRITE,
+ last_protection & VM_PROT_EXECUTE,
+ data);
+
+ return 0;
+}