From 35c2fab7c6364453c5847ba5fccd68dded16d7a6 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Fri, 20 Jan 2012 09:59:15 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 14 ++++++++ gdb/gcore.c | 10 ++++-- gdb/gdbarch.c | 33 +++++++++++++++++++ gdb/gdbarch.h | 8 +++++ gdb/gdbarch.sh | 3 ++ gdb/linux-nat.c | 85 ------------------------------------------------ gdb/linux-tdep.c | 48 +++++++++++++++++++++++++++ 7 files changed, 114 insertions(+), 87 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ab0407e00a1..3f7669d1612 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,17 @@ +2012-01-20 Ulrich Weigand + + * 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 * gdbarch.sh (make_corefile_notes): New architecture callback. diff --git a/gdb/gcore.c b/gdb/gcore.c index 2a769d3b49c..aedda412eb6 100644 --- a/gdb/gcore.c +++ b/gdb/gcore.c @@ -561,8 +561,14 @@ gcore_copy_callback (bfd *obfd, asection *osec, void *ignored) 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); diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 7a1db102234..1bd2341ac4d 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -240,6 +240,7 @@ struct gdbarch 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; @@ -397,6 +398,7 @@ struct gdbarch startup_gdbarch = 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 */ @@ -686,6 +688,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* 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. */ @@ -927,6 +930,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) 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)); @@ -3277,6 +3286,30 @@ set_gdbarch_make_corefile_notes (struct gdbarch *gdbarch, 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) { diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index b6117601e0b..044281c9099 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -717,6 +717,14 @@ typedef char * (gdbarch_make_corefile_notes_ftype) (struct gdbarch *gdbarch, bfd 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. */ diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index c4ff5d1cceb..37281bac77d 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -634,6 +634,9 @@ v:struct core_regset_section *:core_regset_sections:const char *name, int 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 diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 3a40c033ea6..50d4efde176 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -4396,90 +4396,6 @@ linux_child_pid_to_exec_file (int pid) 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. */ @@ -4827,7 +4743,6 @@ linux_target_install_ops (struct target_ops *t) 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; diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index 60fe8b65f51..421518a89ad 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -530,6 +530,53 @@ linux_info_proc (struct gdbarch *gdbarch, char *args, } } +/* 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 @@ -807,6 +854,7 @@ linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { 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); } -- 2.30.2