+/*
+ * Memory Mappings Functions:
+ */
+
+/*
+ * Function: iterate_over_mappings
+ *
+ * Call a callback function once for each mapping, passing it the mapping,
+ * an optional secondary callback function, and some optional opaque data.
+ * Quit and return the first non-zero value returned from the callback.
+ *
+ * Arguments:
+ * pi -- procinfo struct for the process to be mapped.
+ * func -- callback function to be called by this iterator.
+ * data -- optional opaque data to be passed to the callback function.
+ * child_func -- optional secondary function pointer to be passed
+ * to the child function.
+ *
+ * Return: First non-zero return value from the callback function,
+ * or zero.
+ */
+
+static int
+iterate_over_mappings (procinfo *pi, int (*child_func) (), void *data,
+ int (*func) (struct prmap *map,
+ int (*child_func) (),
+ void *data))
+{
+ char pathname[MAX_PROC_NAME_SIZE];
+ struct prmap *prmaps;
+ struct prmap *prmap;
+ int funcstat;
+ int map_fd;
+ int nmap;
+#ifdef NEW_PROC_API
+ struct stat sbuf;
+#endif
+
+ /* Get the number of mappings, allocate space,
+ and read the mappings into prmaps. */
+#ifdef NEW_PROC_API
+ /* Open map fd. */
+ sprintf (pathname, "/proc/%d/map", pi->pid);
+ if ((map_fd = open (pathname, O_RDONLY)) < 0)
+ proc_error (pi, "iterate_over_mappings (open)", __LINE__);
+
+ /* Make sure it gets closed again. */
+ make_cleanup_close (map_fd);
+
+ /* Use stat to determine the file size, and compute
+ the number of prmap_t objects it contains. */
+ if (fstat (map_fd, &sbuf) != 0)
+ proc_error (pi, "iterate_over_mappings (fstat)", __LINE__);
+
+ nmap = sbuf.st_size / sizeof (prmap_t);
+ prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
+ if (read (map_fd, (char *) prmaps, nmap * sizeof (*prmaps))
+ != (nmap * sizeof (*prmaps)))
+ proc_error (pi, "iterate_over_mappings (read)", __LINE__);
+#else
+ /* Use ioctl command PIOCNMAP to get number of mappings. */
+ if (ioctl (pi->ctl_fd, PIOCNMAP, &nmap) != 0)
+ proc_error (pi, "iterate_over_mappings (PIOCNMAP)", __LINE__);
+
+ prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
+ if (ioctl (pi->ctl_fd, PIOCMAP, prmaps) != 0)
+ proc_error (pi, "iterate_over_mappings (PIOCMAP)", __LINE__);
+#endif
+
+ for (prmap = prmaps; nmap > 0; prmap++, nmap--)
+ if ((funcstat = (*func) (prmap, child_func, data)) != 0)
+ return funcstat;
+
+ return 0;
+}
+
+/*
+ * Function: solib_mappings_callback
+ *
+ * Calls the supplied callback function once for each mapped address
+ * space in the process. The callback function receives an open
+ * file descriptor for the file corresponding to that mapped
+ * address space (if there is one), and the base address of the
+ * mapped space. Quit when the callback function returns a
+ * nonzero value, or at teh end of the mappings.
+ *
+ * Returns: the first non-zero return value of the callback function,
+ * or zero.
+ */
+
+int solib_mappings_callback (struct prmap *map,
+ int (*func) (int, CORE_ADDR),
+ void *data)
+{
+ procinfo *pi = data;
+ int fd;
+
+#ifdef NEW_PROC_API
+ char name[MAX_PROC_NAME_SIZE + sizeof (map->pr_mapname)];
+
+ if (map->pr_vaddr == 0 && map->pr_size == 0)
+ return -1; /* sanity */
+
+ if (map->pr_mapname[0] == 0)
+ {
+ fd = -1; /* no map file */
+ }
+ else
+ {
+ sprintf (name, "/proc/%d/object/%s", pi->pid, map->pr_mapname);
+ /* Note: caller's responsibility to close this fd! */
+ fd = open_with_retry (name, O_RDONLY);
+ /* Note: we don't test the above call for failure;
+ we just pass the FD on as given. Sometimes there is
+ no file, so the open may return failure, but that's
+ not a problem. */
+ }
+#else
+ fd = ioctl (pi->ctl_fd, PIOCOPENM, &map->pr_vaddr);
+ /* Note: we don't test the above call for failure;
+ we just pass the FD on as given. Sometimes there is
+ no file, so the ioctl may return failure, but that's
+ not a problem. */
+#endif
+ return (*func) (fd, (CORE_ADDR) map->pr_vaddr);
+}
+
+/*
+ * Function: proc_iterate_over_mappings
+ *
+ * Uses the unified "iterate_over_mappings" function
+ * to implement the exported interface to solib-svr4.c.
+ *
+ * Given a pointer to a function, call that function once for every
+ * mapped address space in the process. The callback function
+ * receives an open file descriptor for the file corresponding to
+ * that mapped address space (if there is one), and the base address
+ * of the mapped space. Quit when the callback function returns a
+ * nonzero value, or at teh end of the mappings.
+ *
+ * Returns: the first non-zero return value of the callback function,
+ * or zero.
+ */
+
+int
+proc_iterate_over_mappings (int (*func) (int, CORE_ADDR))
+{
+ procinfo *pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
+
+ return iterate_over_mappings (pi, func, pi, solib_mappings_callback);
+}
+
+/*
+ * Function: find_memory_regions_callback
+ *
+ * Implements the to_find_memory_regions method.
+ * Calls an external function for each memory region.
+ * External function will have the signiture:
+ *
+ * int callback (CORE_ADDR vaddr,
+ * unsigned long size,
+ * int read, int write, int execute,
+ * void *data);
+ *
+ * Returns the integer value returned by the callback.
+ */
+
+static int
+find_memory_regions_callback (struct prmap *map,
+ int (*func) (CORE_ADDR,
+ unsigned long,
+ int, int, int,
+ void *),
+ void *data)
+{
+ return (*func) ((CORE_ADDR) map->pr_vaddr,
+ map->pr_size,
+ (map->pr_mflags & MA_READ) != 0,
+ (map->pr_mflags & MA_WRITE) != 0,
+ (map->pr_mflags & MA_EXEC) != 0,
+ data);
+}
+
+/*
+ * Function: proc_find_memory_regions
+ *
+ * External interface. Calls a callback function once for each
+ * mapped memory region in the child process, passing as arguments
+ * CORE_ADDR virtual_address,
+ * unsigned long size,
+ * int read, TRUE if region is readable by the child
+ * int write, TRUE if region is writable by the child
+ * int execute TRUE if region is executable by the child.
+ *
+ * Stops iterating and returns the first non-zero value
+ * returned by the callback.
+ */
+
+static int
+proc_find_memory_regions (int (*func) (CORE_ADDR,
+ unsigned long,
+ int, int, int,
+ void *),
+ void *data)
+{
+ procinfo *pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
+
+ return iterate_over_mappings (pi, func, data,
+ find_memory_regions_callback);
+}
+
+/* Remove the breakpoint that we inserted in __dbx_link().
+ Does nothing if the breakpoint hasn't been inserted or has already
+ been removed. */
+
+static void
+remove_dbx_link_breakpoint (void)
+{
+ if (dbx_link_bpt_addr == 0)
+ return;
+
+ if (deprecated_remove_raw_breakpoint (dbx_link_bpt) != 0)
+ warning (_("Unable to remove __dbx_link breakpoint."));
+
+ dbx_link_bpt_addr = 0;
+ dbx_link_bpt = NULL;
+}
+
+/* Return the address of the __dbx_link() function in the file
+ refernced by ABFD by scanning its symbol table. Return 0 if
+ the symbol was not found. */
+
+static CORE_ADDR
+dbx_link_addr (bfd *abfd)
+{
+ long storage_needed;
+ asymbol **symbol_table;
+ long number_of_symbols;
+ long i;
+
+ storage_needed = bfd_get_symtab_upper_bound (abfd);
+ if (storage_needed <= 0)
+ return 0;
+
+ symbol_table = (asymbol **) xmalloc (storage_needed);
+ make_cleanup (xfree, symbol_table);
+
+ number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
+
+ for (i = 0; i < number_of_symbols; i++)
+ {
+ asymbol *sym = symbol_table[i];
+
+ if ((sym->flags & BSF_GLOBAL)
+ && sym->name != NULL && strcmp (sym->name, "__dbx_link") == 0)
+ return (sym->value + sym->section->vma);
+ }
+
+ /* Symbol not found, return NULL. */
+ return 0;
+}
+
+/* Search the symbol table of the file referenced by FD for a symbol
+ named __dbx_link(). If found, then insert a breakpoint at this location,
+ and return nonzero. Return zero otherwise. */
+
+static int
+insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
+{
+ bfd *abfd;
+ long storage_needed;
+ CORE_ADDR sym_addr;
+
+ abfd = bfd_fdopenr ("unamed", 0, fd);
+ if (abfd == NULL)
+ {
+ warning (_("Failed to create a bfd: %s."), bfd_errmsg (bfd_get_error ()));
+ return 0;
+ }