* gdbarch.c, gdbarch.h: Regenerate.
* gcore.c (gcore_memory_sections): Try gdbarch find_memory_regions
callback before falling back to target method.
* linux-nat.c (read_mapping, linux_nat_find_memory_regions): Remove.
(linux_target_install_ops): No longer install it.
* linux-tdep.c (linux_find_memory_regions): New function.
(linux_init_abi): Install it.
+2012-01-20 Ulrich Weigand <ulrich.weigand@linaro.org>
+
+ * gdbarch.sh (find_memory_regions): New callback.
+ * gdbarch.c, gdbarch.h: Regenerate.
+
+ * gcore.c (gcore_memory_sections): Try gdbarch find_memory_regions
+ callback before falling back to target method.
+
+ * linux-nat.c (read_mapping, linux_nat_find_memory_regions): Remove.
+ (linux_target_install_ops): No longer install it.
+
+ * linux-tdep.c (linux_find_memory_regions): New function.
+ (linux_init_abi): Install it.
+
2012-01-20 Ulrich Weigand <ulrich.weigand@linaro.org>
* gdbarch.sh (make_corefile_notes): New architecture callback.
static int
gcore_memory_sections (bfd *obfd)
{
- if (target_find_memory_regions (gcore_create_callback, obfd) != 0)
- return 0; /* FIXME: error return/msg? */
+ /* Try gdbarch method first, then fall back to target method. */
+ if (!gdbarch_find_memory_regions_p (target_gdbarch)
+ || gdbarch_find_memory_regions (target_gdbarch,
+ gcore_create_callback, obfd) != 0)
+ {
+ if (target_find_memory_regions (gcore_create_callback, obfd) != 0)
+ return 0; /* FIXME: error return/msg? */
+ }
/* Record phdrs for section-to-segment mapping. */
bfd_map_over_sections (obfd, make_output_phdrs, NULL);
gdbarch_regset_from_core_section_ftype *regset_from_core_section;
struct core_regset_section * core_regset_sections;
gdbarch_make_corefile_notes_ftype *make_corefile_notes;
+ gdbarch_find_memory_regions_ftype *find_memory_regions;
gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries;
gdbarch_core_pid_to_str_ftype *core_pid_to_str;
const char * gcore_bfd_target;
0, /* regset_from_core_section */
0, /* core_regset_sections */
0, /* make_corefile_notes */
+ 0, /* find_memory_regions */
0, /* core_xfer_shared_libraries */
0, /* core_pid_to_str */
0, /* gcore_bfd_target */
/* Skip verify of fetch_pointer_argument, has predicate. */
/* Skip verify of regset_from_core_section, has predicate. */
/* Skip verify of make_corefile_notes, has predicate. */
+ /* Skip verify of find_memory_regions, has predicate. */
/* Skip verify of core_xfer_shared_libraries, has predicate. */
/* Skip verify of core_pid_to_str, has predicate. */
/* Skip verify of gcore_bfd_target, has predicate. */
fprintf_unfiltered (file,
"gdbarch_dump: fetch_tls_load_module_address = <%s>\n",
host_address_to_string (gdbarch->fetch_tls_load_module_address));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_find_memory_regions_p() = %d\n",
+ gdbarch_find_memory_regions_p (gdbarch));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: find_memory_regions = <%s>\n",
+ host_address_to_string (gdbarch->find_memory_regions));
fprintf_unfiltered (file,
"gdbarch_dump: float_bit = %s\n",
plongest (gdbarch->float_bit));
gdbarch->make_corefile_notes = make_corefile_notes;
}
+int
+gdbarch_find_memory_regions_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->find_memory_regions != NULL;
+}
+
+int
+gdbarch_find_memory_regions (struct gdbarch *gdbarch, find_memory_region_ftype func, void *data)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->find_memory_regions != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_find_memory_regions called\n");
+ return gdbarch->find_memory_regions (gdbarch, func, data);
+}
+
+void
+set_gdbarch_find_memory_regions (struct gdbarch *gdbarch,
+ gdbarch_find_memory_regions_ftype find_memory_regions)
+{
+ gdbarch->find_memory_regions = find_memory_regions;
+}
+
int
gdbarch_core_xfer_shared_libraries_p (struct gdbarch *gdbarch)
{
extern char * gdbarch_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size);
extern void set_gdbarch_make_corefile_notes (struct gdbarch *gdbarch, gdbarch_make_corefile_notes_ftype *make_corefile_notes);
+/* Find core file memory regions */
+
+extern int gdbarch_find_memory_regions_p (struct gdbarch *gdbarch);
+
+typedef int (gdbarch_find_memory_regions_ftype) (struct gdbarch *gdbarch, find_memory_region_ftype func, void *data);
+extern int gdbarch_find_memory_regions (struct gdbarch *gdbarch, find_memory_region_ftype func, void *data);
+extern void set_gdbarch_find_memory_regions (struct gdbarch *gdbarch, gdbarch_find_memory_regions_ftype *find_memory_regions);
+
/* Read offset OFFSET of TARGET_OBJECT_LIBRARIES formatted shared libraries list from
core file into buffer READBUF with length LEN. */
# Create core file notes
M:char *:make_corefile_notes:bfd *obfd, int *note_size:obfd, note_size
+# Find core file memory regions
+M:int:find_memory_regions:find_memory_region_ftype func, void *data:func, data
+
# Read offset OFFSET of TARGET_OBJECT_LIBRARIES formatted shared libraries list from
# core file into buffer READBUF with length LEN.
M:LONGEST:core_xfer_shared_libraries:gdb_byte *readbuf, ULONGEST offset, LONGEST len:readbuf, offset, len
return name1;
}
-/* Service function for corefiles and info proc. */
-
-static int
-read_mapping (FILE *mapfile,
- long long *addr,
- long long *endaddr,
- char *permissions,
- long long *offset,
- char *device, long long *inode, char *filename)
-{
- int ret = fscanf (mapfile, "%llx-%llx %s %llx %s %llx",
- addr, endaddr, permissions, offset, device, inode);
-
- filename[0] = '\0';
- if (ret > 0 && ret != EOF)
- {
- /* Eat everything up to EOL for the filename. This will prevent
- weird filenames (such as one with embedded whitespace) from
- confusing this code. It also makes this code more robust in
- respect to annotations the kernel may add after the filename.
-
- Note the filename is used for informational purposes
- only. */
- ret += fscanf (mapfile, "%[^\n]\n", filename);
- }
-
- return (ret != 0 && ret != EOF);
-}
-
-/* Fills the "to_find_memory_regions" target vector. Lists the memory
- regions in the inferior for a corefile. */
-
-static int
-linux_nat_find_memory_regions (find_memory_region_ftype func, void *obfd)
-{
- int pid = PIDGET (inferior_ptid);
- char mapsfilename[MAXPATHLEN];
- FILE *mapsfile;
- long long addr, endaddr, size, offset, inode;
- char permissions[8], device[8], filename[MAXPATHLEN];
- int read, write, exec;
- struct cleanup *cleanup;
-
- /* Compose the filename for the /proc memory map, and open it. */
- sprintf (mapsfilename, "/proc/%d/maps", pid);
- if ((mapsfile = fopen (mapsfilename, "r")) == NULL)
- error (_("Could not open %s."), mapsfilename);
- cleanup = make_cleanup_fclose (mapsfile);
-
- if (info_verbose)
- fprintf_filtered (gdb_stdout,
- "Reading memory regions from %s\n", mapsfilename);
-
- /* Now iterate until end-of-file. */
- while (read_mapping (mapsfile, &addr, &endaddr, &permissions[0],
- &offset, &device[0], &inode, &filename[0]))
- {
- size = endaddr - addr;
-
- /* Get the segment's permissions. */
- read = (strchr (permissions, 'r') != 0);
- write = (strchr (permissions, 'w') != 0);
- exec = (strchr (permissions, 'x') != 0);
-
- if (info_verbose)
- {
- fprintf_filtered (gdb_stdout,
- "Save segment, %s bytes at %s (%c%c%c)",
- plongest (size), paddress (target_gdbarch, addr),
- read ? 'r' : ' ',
- write ? 'w' : ' ', exec ? 'x' : ' ');
- if (filename[0])
- fprintf_filtered (gdb_stdout, " for %s", filename);
- fprintf_filtered (gdb_stdout, "\n");
- }
-
- /* Invoke the callback function to create the corefile
- segment. */
- func (addr, size, read, write, exec, obfd);
- }
- do_cleanups (cleanup);
- return 0;
-}
-
/* Records the thread's register state for the corefile note
section. */
t->to_post_startup_inferior = linux_child_post_startup_inferior;
t->to_post_attach = linux_child_post_attach;
t->to_follow_fork = linux_child_follow_fork;
- t->to_find_memory_regions = linux_nat_find_memory_regions;
t->to_make_corefile_notes = linux_nat_make_corefile_notes;
super_xfer_partial = t->to_xfer_partial;
}
}
+/* List memory regions in the inferior for a corefile. */
+
+static int
+linux_find_memory_regions (struct gdbarch *gdbarch,
+ find_memory_region_ftype func, void *obfd)
+{
+ char filename[100];
+ gdb_byte *data;
+
+ /* We need to know the real target PID to access /proc. */
+ if (current_inferior ()->fake_pid_p)
+ return 1;
+
+ xsnprintf (filename, sizeof filename,
+ "/proc/%d/maps", current_inferior ()->pid);
+ data = target_fileio_read_stralloc (filename);
+ if (data)
+ {
+ struct cleanup *cleanup = make_cleanup (xfree, data);
+ char *line;
+
+ for (line = strtok (data, "\n"); line; line = strtok (NULL, "\n"))
+ {
+ ULONGEST addr, endaddr, offset, inode;
+ const char *permissions, *device, *filename;
+ size_t permissions_len, device_len;
+ int read, write, exec;
+
+ read_mapping (line, &addr, &endaddr, &permissions, &permissions_len,
+ &offset, &device, &device_len, &inode, &filename);
+
+ /* Decode permissions. */
+ read = (memchr (permissions, 'r', permissions_len) != 0);
+ write = (memchr (permissions, 'w', permissions_len) != 0);
+ exec = (memchr (permissions, 'x', permissions_len) != 0);
+
+ /* Invoke the callback function to create the corefile segment. */
+ func (addr, endaddr - addr, read, write, exec, obfd);
+ }
+
+ do_cleanups (cleanup);
+ return 0;
+ }
+
+ return 1;
+}
+
/* Determine which signal stopped execution. */
static int
{
set_gdbarch_core_pid_to_str (gdbarch, linux_core_pid_to_str);
set_gdbarch_info_proc (gdbarch, linux_info_proc);
+ set_gdbarch_find_memory_regions (gdbarch, linux_find_memory_regions);
set_gdbarch_make_corefile_notes (gdbarch, linux_make_corefile_notes_1);
}