2008-05-07 Carlos Eduardo Seo * gdbarch.sh: Added new gdbarch struct core_regset_sections. * gdbarch.c: Refreshed. * gdbarch.h: Refreshed. * regset.h (core_regset_section): Declared. * linux-nat.c (linux_nat_do_thread_registers): Added support to the new gdbarch struct core_regset_sections. * utils.c (host_address_to_string): New function. * defs.h (host_address_to_string): New prototype. Index: src/gdb/gdbarch.sh =================================================================== --- src.orig/gdb/gdbarch.sh +++ src/gdb/gdbarch.sh @@ -600,6 +600,9 @@ F:CORE_ADDR:fetch_pointer_argument:struc # name SECT_NAME and size SECT_SIZE. M:const struct regset *:regset_from_core_section:const char *sect_name, size_t sect_size:sect_name, sect_size +# Supported register notes in a core file +v:struct core_regset_section *:core_regset_sections:const char *name, int len::::::host_address_to_string (gdbarch->core_regset_sections) + # 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 @@ -815,6 +818,7 @@ struct obstack; struct bp_target_info; struct target_desc; struct displaced_step_closure; +struct core_regset_section; extern struct gdbarch *current_gdbarch; EOF Index: src/gdb/gdbarch.c =================================================================== --- src.orig/gdb/gdbarch.c +++ src/gdb/gdbarch.c @@ -222,6 +222,7 @@ struct gdbarch gdbarch_register_reggroup_p_ftype *register_reggroup_p; gdbarch_fetch_pointer_argument_ftype *fetch_pointer_argument; gdbarch_regset_from_core_section_ftype *regset_from_core_section; + struct core_regset_section * core_regset_sections; gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries; int vtable_function_descriptors; int vbit_in_delta; @@ -352,6 +353,7 @@ struct gdbarch startup_gdbarch = default_register_reggroup_p, /* register_reggroup_p */ 0, /* fetch_pointer_argument */ 0, /* regset_from_core_section */ + 0, /* core_regset_sections */ 0, /* core_xfer_shared_libraries */ 0, /* vtable_function_descriptors */ 0, /* vbit_in_delta */ @@ -725,6 +727,9 @@ gdbarch_dump (struct gdbarch *gdbarch, s "gdbarch_dump: core_read_description = <0x%lx>\n", (long) gdbarch->core_read_description); fprintf_unfiltered (file, + "gdbarch_dump: core_regset_sections = %s\n", + host_address_to_string (gdbarch->core_regset_sections)); + fprintf_unfiltered (file, "gdbarch_dump: gdbarch_core_xfer_shared_libraries_p() = %d\n", gdbarch_core_xfer_shared_libraries_p (gdbarch)); fprintf_unfiltered (file, @@ -2877,6 +2882,22 @@ set_gdbarch_regset_from_core_section (st gdbarch->regset_from_core_section = regset_from_core_section; } +struct core_regset_section * +gdbarch_core_regset_sections (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_core_regset_sections called\n"); + return gdbarch->core_regset_sections; +} + +void +set_gdbarch_core_regset_sections (struct gdbarch *gdbarch, + struct core_regset_section * core_regset_sections) +{ + gdbarch->core_regset_sections = core_regset_sections; +} + int gdbarch_core_xfer_shared_libraries_p (struct gdbarch *gdbarch) { Index: src/gdb/gdbarch.h =================================================================== --- src.orig/gdb/gdbarch.h +++ src/gdb/gdbarch.h @@ -51,6 +51,7 @@ struct obstack; struct bp_target_info; struct target_desc; struct displaced_step_closure; +struct core_regset_section; extern struct gdbarch *current_gdbarch; @@ -634,6 +635,11 @@ typedef const struct regset * (gdbarch_r extern const struct regset * gdbarch_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name, size_t sect_size); extern void set_gdbarch_regset_from_core_section (struct gdbarch *gdbarch, gdbarch_regset_from_core_section_ftype *regset_from_core_section); +/* Supported register notes in a core file */ + +extern struct core_regset_section * gdbarch_core_regset_sections (struct gdbarch *gdbarch); +extern void set_gdbarch_core_regset_sections (struct gdbarch *gdbarch, struct core_regset_section * core_regset_sections); + /* Read offset OFFSET of TARGET_OBJECT_LIBRARIES formatted shared libraries list from core file into buffer READBUF with length LEN. */ Index: src/gdb/regset.h =================================================================== --- src.orig/gdb/regset.h +++ src/gdb/regset.h @@ -23,6 +23,13 @@ struct gdbarch; struct regcache; +/* Data structure for the supported register notes in a core file */ +struct core_regset_section +{ + const char *sect_name; + int size; +}; + /* Data structure describing a register set. */ typedef void (supply_regset_ftype) (const struct regset *, struct regcache *, Index: src/gdb/linux-nat.c =================================================================== --- src.orig/gdb/linux-nat.c +++ src/gdb/linux-nat.c @@ -3124,15 +3124,14 @@ linux_nat_do_thread_registers (bfd *obfd { gdb_gregset_t gregs; gdb_fpregset_t fpregs; -#ifdef FILL_FPXREGSET - gdb_fpxregset_t fpxregs; -#endif unsigned long lwp = ptid_get_lwp (ptid); struct regcache *regcache = get_thread_regcache (ptid); struct gdbarch *gdbarch = get_regcache_arch (regcache); const struct regset *regset; int core_regset_p; struct cleanup *old_chain; + struct core_regset_section *sect_list; + char *gdb_regset; old_chain = save_inferior_ptid (); inferior_ptid = ptid; @@ -3140,6 +3139,8 @@ linux_nat_do_thread_registers (bfd *obfd do_cleanups (old_chain); core_regset_p = gdbarch_regset_from_core_section_p (gdbarch); + sect_list = gdbarch_core_regset_sections (gdbarch); + if (core_regset_p && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg", sizeof (gregs))) != NULL @@ -3155,35 +3156,59 @@ linux_nat_do_thread_registers (bfd *obfd lwp, stop_signal, &gregs); - if (core_regset_p - && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg2", - sizeof (fpregs))) != NULL - && regset->collect_regset != NULL) - regset->collect_regset (regset, regcache, -1, - &fpregs, sizeof (fpregs)); + /* The loop below uses the new struct core_regset_section, which stores + the supported section names and sizes for the core file. Note that + note PRSTATUS needs to be treated specially. But the other notes are + structurally the same, so they can benefit from the new struct. */ + if (core_regset_p && sect_list != NULL) + while (sect_list->sect_name != NULL) + { + /* .reg was already handled above */ + if (strcmp (sect_list->sect_name, ".reg") == 0) + { + sect_list++; + continue; + } + if ((regset = gdbarch_regset_from_core_section (gdbarch, + sect_list->sect_name, + sect_list->size)) + != NULL && regset->collect_regset != NULL) + { + gdb_regset = xmalloc (sect_list->size); + regset->collect_regset (regset, regcache, -1, + gdb_regset, sect_list->size); + note_data = (char *) elfcore_write_register_note (obfd, + note_data, + note_size, + sect_list->sect_name, + gdb_regset, + sect_list->size); + xfree (gdb_regset); + } + sect_list++; + } + + /* For architectures that does not have the struct core_regset_section implemented, + we use the old method. When all the architectures have the new support, the code + below should be deprecated. The FILL_FPXREGSET fallback was removed since i386 + has the new method implemented. */ else - fill_fpregset (regcache, &fpregs, -1); - - note_data = (char *) elfcore_write_prfpreg (obfd, - note_data, - note_size, - &fpregs, sizeof (fpregs)); + { + if (core_regset_p + && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg2", + sizeof (fpregs))) != NULL + && regset->collect_regset != NULL) + regset->collect_regset (regset, regcache, -1, + &fpregs, sizeof (fpregs)); + else + fill_fpregset (regcache, &fpregs, -1); -#ifdef FILL_FPXREGSET - if (core_regset_p - && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg-xfp", - sizeof (fpxregs))) != NULL - && regset->collect_regset != NULL) - regset->collect_regset (regset, regcache, -1, - &fpxregs, sizeof (fpxregs)); - else - fill_fpxregset (regcache, &fpxregs, -1); + note_data = (char *) elfcore_write_prfpreg (obfd, + note_data, + note_size, + &fpregs, sizeof (fpregs)); + } - note_data = (char *) elfcore_write_prxfpreg (obfd, - note_data, - note_size, - &fpxregs, sizeof (fpxregs)); -#endif return note_data; } Index: src/gdb/utils.c =================================================================== --- src.orig/gdb/utils.c +++ src/gdb/utils.c @@ -1075,7 +1075,6 @@ gdb_print_host_address (const void *addr fprintf_filtered (stream, "0x%lx", (unsigned long) addr); } - /* This function supports the query, nquery, and yquery functions. Ask user a y-or-n question and return 0 if answer is no, 1 if @@ -2869,6 +2868,14 @@ string_to_core_addr (const char *my_stri return addr; } +const char * +host_address_to_string (const void *addr) +{ + char *str = get_cell (); + sprintf (str, "0x%lx", (unsigned long) addr); + return str; +} + char * gdb_realpath (const char *filename) { Index: src/gdb/defs.h =================================================================== --- src.orig/gdb/defs.h +++ src/gdb/defs.h @@ -470,6 +470,8 @@ extern void fputstrn_unfiltered (const c /* Display the host ADDR on STREAM formatted as ``0x%x''. */ extern void gdb_print_host_address (const void *addr, struct ui_file *stream); +extern const char *host_address_to_string (const void *addr); + /* Convert a CORE_ADDR into a HEX string. paddr() is like %08lx. paddr_nz() is like %lx. paddr_u() is like %lu. paddr_width() is for ``%*''. */