From 5aa82d050d61784823767fe3c982b6862fa47391 Mon Sep 17 00:00:00 2001 From: Andreas Arnez Date: Thu, 4 Sep 2014 15:26:43 +0000 Subject: [PATCH] Replace 'core_regset_sections' by iterator method The core_regset_sections list in gdbarch (needed for multi-arch capable core file generation support) is replaced by an iterator method. Overall, this reduces the code a bit, and it allows for more flexibility. gdb/ChangeLog: * amd64-linux-tdep.c (amd64_linux_regset_sections): Remove. (amd64_linux_iterate_over_regset_sections): New. (amd64_linux_init_abi_common): Don't install the regset section list, but the new iterator in gdbarch. * arm-linux-tdep.c (arm_linux_fpa_regset_sections) (arm_linux_vfp_regset_sections): Remove. Move combined logic... (arm_linux_iterate_over_regset_sections): ...here. New function. (arm_linux_init_abi): Set iterator instead of section list. * corelow.c (get_core_registers_cb): New function, logic moved from... (get_core_registers): ...loop body here. Use new iterator method instead of walking through the regset section list. * gdbarch.sh: Remove 'core_regset_sections'. New method 'iterate_over_regset_sections'. New typedef 'iterate_over_regset_sections_cb'. * gdbarch.c: Regenerate. * gdbarch.h: Likewise. * i386-linux-tdep.c (i386_linux_regset_sections) (i386_linux_sse_regset_sections, i386_linux_avx_regset_sections): Remove. (i386_linux_iterate_over_regset_sections): New. (i386_linux_init_abi): Don't choose a regset section list, but install new iterator in gdbarch. * linux-tdep.c (struct linux_collect_regset_section_cb_data): New. (linux_collect_regset_section_cb): New function, logic moved from... (linux_collect_thread_registers): ...loop body here. Use iterator method instead of walking through list. (linux_make_corefile_notes_1): Check for presence of iterator method instead of regset section list. * ppc-linux-tdep.c (ppc_linux_vsx_regset_sections) (ppc_linux_vmx_regset_sections, ppc_linux_fp_regset_sections) (ppc64_linux_vsx_regset_sections, ppc64_linux_vmx_regset_sections) (ppc64_linux_fp_regset_sections): Remove. Move combined logic... (ppc_linux_iterate_over_regset_sections): ...here. New function. (ppc_linux_init_abi): Don't choose from above regset section lists, but install new iterator in gdbarch. * regset.h (struct core_regset_section): Remove. * s390-linux-tdep.c (struct gdbarch_tdep): Add new fields have_linux_v1, have_linux_v2, and have_tdb. (s390_linux32_regset_sections, s390_linux32v1_regset_sections) (s390_linux32v2_regset_sections, s390_linux64_regset_sections) (s390_linux64v1_regset_sections, s390_linux64v2_regset_sections) (s390x_linux64_regset_sections, s390x_linux64v1_regset_sections) (s390x_linux64v2_regset_sections): Remove. Move combined logic... (s390_iterate_over_regset_sections): ...here. New function. Use new tdep fields. (s390_gdbarch_init): Set new tdep fields. Don't choose from above regset section lists, but install new iterator. --- gdb/ChangeLog | 52 ++++++++++++++ gdb/amd64-linux-tdep.c | 27 ++++--- gdb/arm-linux-tdep.c | 34 ++++----- gdb/corelow.c | 40 ++++++----- gdb/gdbarch.c | 36 ++++++---- gdb/gdbarch.h | 17 ++++- gdb/gdbarch.sh | 12 +++- gdb/i386-linux-tdep.c | 54 ++++++-------- gdb/linux-tdep.c | 105 +++++++++++++++++---------- gdb/ppc-linux-tdep.c | 98 +++++++------------------ gdb/regset.h | 8 --- gdb/s390-linux-tdep.c | 157 +++++++++++------------------------------ 12 files changed, 312 insertions(+), 328 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index afaf056297..589c601178 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,55 @@ +2014-09-30 Andreas Arnez + + * amd64-linux-tdep.c (amd64_linux_regset_sections): Remove. + (amd64_linux_iterate_over_regset_sections): New. + (amd64_linux_init_abi_common): Don't install the regset section + list, but the new iterator in gdbarch. + * arm-linux-tdep.c (arm_linux_fpa_regset_sections) + (arm_linux_vfp_regset_sections): Remove. Move combined logic... + (arm_linux_iterate_over_regset_sections): ...here. New function. + (arm_linux_init_abi): Set iterator instead of section list. + * corelow.c (get_core_registers_cb): New function, logic moved + from... + (get_core_registers): ...loop body here. Use new iterator method + instead of walking through the regset section list. + * gdbarch.sh: Remove 'core_regset_sections'. New method + 'iterate_over_regset_sections'. New typedef + 'iterate_over_regset_sections_cb'. + * gdbarch.c: Regenerate. + * gdbarch.h: Likewise. + * i386-linux-tdep.c (i386_linux_regset_sections) + (i386_linux_sse_regset_sections, i386_linux_avx_regset_sections): + Remove. + (i386_linux_iterate_over_regset_sections): New. + (i386_linux_init_abi): Don't choose a regset section list, but + install new iterator in gdbarch. + * linux-tdep.c (struct linux_collect_regset_section_cb_data): New. + (linux_collect_regset_section_cb): New function, logic moved + from... + (linux_collect_thread_registers): ...loop body here. Use iterator + method instead of walking through list. + (linux_make_corefile_notes_1): Check for presence of iterator + method instead of regset section list. + * ppc-linux-tdep.c (ppc_linux_vsx_regset_sections) + (ppc_linux_vmx_regset_sections, ppc_linux_fp_regset_sections) + (ppc64_linux_vsx_regset_sections, ppc64_linux_vmx_regset_sections) + (ppc64_linux_fp_regset_sections): Remove. Move combined logic... + (ppc_linux_iterate_over_regset_sections): ...here. New function. + (ppc_linux_init_abi): Don't choose from above regset section + lists, but install new iterator in gdbarch. + * regset.h (struct core_regset_section): Remove. + * s390-linux-tdep.c (struct gdbarch_tdep): Add new fields + have_linux_v1, have_linux_v2, and have_tdb. + (s390_linux32_regset_sections, s390_linux32v1_regset_sections) + (s390_linux32v2_regset_sections, s390_linux64_regset_sections) + (s390_linux64v1_regset_sections, s390_linux64v2_regset_sections) + (s390x_linux64_regset_sections, s390x_linux64v1_regset_sections) + (s390x_linux64v2_regset_sections): Remove. Move combined logic... + (s390_iterate_over_regset_sections): ...here. New function. Use + new tdep fields. + (s390_gdbarch_init): Set new tdep fields. Don't choose from above + regset section lists, but install new iterator. + 2014-09-29 Jan Kratochvil * solib-svr4.c (svr4_parse_libraries): Use "library-list-svr4.dtd". diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index 850ca20cb9..2432bae350 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -53,15 +53,6 @@ #include "record-full.h" #include "linux-record.h" -/* Supported register note sections. */ -static struct core_regset_section amd64_linux_regset_sections[] = -{ - { ".reg", 27 * 8, "general-purpose" }, - { ".reg2", 512, "floating-point" }, - { ".reg-xstate", X86_XSTATE_MAX_SIZE, "XSAVE extended state" }, - { NULL, 0 } -}; - /* Mapping between the general-purpose registers in `struct user' format and GDB's register cache layout. */ @@ -1609,6 +1600,19 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch, } } +/* Iterate over core file register note sections. */ + +static void +amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", 27 * 8, "general-purpose", cb_data); + cb (".reg2", 512, "floating-point", cb_data); + cb (".reg-xstate", X86_XSTATE_MAX_SIZE, "XSAVE extended state", cb_data); +} + static void amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -1643,8 +1647,9 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch) /* GNU/Linux uses the dynamic linker included in the GNU C Library. */ set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); - /* Install supported register note sections. */ - set_gdbarch_core_regset_sections (gdbarch, amd64_linux_regset_sections); + /* Iterate over core file register note sections. */ + set_gdbarch_iterate_over_regset_sections + (gdbarch, amd64_linux_iterate_over_regset_sections); set_gdbarch_core_read_description (gdbarch, amd64_linux_core_read_description); diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c index 3d524c9b9d..22decd5a99 100644 --- a/gdb/arm-linux-tdep.c +++ b/gdb/arm-linux-tdep.c @@ -753,21 +753,24 @@ arm_linux_regset_from_core_section (struct gdbarch *gdbarch, return NULL; } -/* Core file register set sections. */ +/* Iterate over core file register note sections. */ -static struct core_regset_section arm_linux_fpa_regset_sections[] = +static void +arm_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) { - { ".reg", ARM_LINUX_SIZEOF_GREGSET, "general-purpose" }, - { ".reg2", ARM_LINUX_SIZEOF_NWFPE, "FPA floating-point" }, - { NULL, 0} -}; + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); -static struct core_regset_section arm_linux_vfp_regset_sections[] = -{ - { ".reg", ARM_LINUX_SIZEOF_GREGSET, "general-purpose" }, - { ".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, "VFP floating-point" }, - { NULL, 0} -}; + cb (".reg", ARM_LINUX_SIZEOF_GREGSET, "general-purpose", cb_data); + + if (tdep->have_vfp_registers) + cb (".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, "VFP floating-point", + cb_data); + else if (tdep->have_fpa_registers) + cb (".reg2", ARM_LINUX_SIZEOF_NWFPE, "FPA floating-point", cb_data); +} /* Determine target description from core file. */ @@ -1456,13 +1459,10 @@ arm_linux_init_abi (struct gdbarch_info info, /* Core file support. */ set_gdbarch_regset_from_core_section (gdbarch, arm_linux_regset_from_core_section); + set_gdbarch_iterate_over_regset_sections + (gdbarch, arm_linux_iterate_over_regset_sections); set_gdbarch_core_read_description (gdbarch, arm_linux_core_read_description); - if (tdep->have_vfp_registers) - set_gdbarch_core_regset_sections (gdbarch, arm_linux_vfp_regset_sections); - else if (tdep->have_fpa_registers) - set_gdbarch_core_regset_sections (gdbarch, arm_linux_fpa_regset_sections); - set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type); /* Displaced stepping. */ diff --git a/gdb/corelow.c b/gdb/corelow.c index ecd99f61ce..7e64e1d730 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -550,6 +550,22 @@ get_core_register_section (struct regcache *regcache, bfd_section_vma (core_bfd, section))); } +/* Callback for get_core_registers that handles a single core file + register note section. */ + +static void +get_core_registers_cb (const char *sect_name, int size, + const char *human_name, void *cb_data) +{ + struct regcache *regcache = (struct regcache *) cb_data; + + if (strcmp (sect_name, ".reg") == 0) + get_core_register_section (regcache, sect_name, 0, human_name, 1); + else if (strcmp (sect_name, ".reg2") == 0) + get_core_register_section (regcache, sect_name, 2, human_name, 0); + else + get_core_register_section (regcache, sect_name, 3, human_name, 0); +} /* Get the registers out of a core file. This is the machine- independent part. Fetch_core_registers is the machine-dependent @@ -562,8 +578,8 @@ static void get_core_registers (struct target_ops *ops, struct regcache *regcache, int regno) { - struct core_regset_section *sect_list; int i; + struct gdbarch *gdbarch; if (!(core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch)) && (core_vec == NULL || core_vec->core_read_registers == NULL)) @@ -573,23 +589,11 @@ get_core_registers (struct target_ops *ops, return; } - sect_list = gdbarch_core_regset_sections (get_regcache_arch (regcache)); - if (sect_list) - while (sect_list->sect_name != NULL) - { - if (strcmp (sect_list->sect_name, ".reg") == 0) - get_core_register_section (regcache, sect_list->sect_name, - 0, sect_list->human_name, 1); - else if (strcmp (sect_list->sect_name, ".reg2") == 0) - get_core_register_section (regcache, sect_list->sect_name, - 2, sect_list->human_name, 0); - else - get_core_register_section (regcache, sect_list->sect_name, - 3, sect_list->human_name, 0); - - sect_list++; - } - + gdbarch = get_regcache_arch (regcache); + if (gdbarch_iterate_over_regset_sections_p (gdbarch)) + gdbarch_iterate_over_regset_sections (gdbarch, + get_core_registers_cb, + (void *) regcache, NULL); else { get_core_register_section (regcache, diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index b0ee79d443..be4bb786bc 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -260,7 +260,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_iterate_over_regset_sections_ftype *iterate_over_regset_sections; gdbarch_make_corefile_notes_ftype *make_corefile_notes; gdbarch_elfcore_write_linux_prpsinfo_ftype *elfcore_write_linux_prpsinfo; gdbarch_find_memory_regions_ftype *find_memory_regions; @@ -571,6 +571,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of register_reggroup_p, invalid_p == 0 */ /* Skip verify of fetch_pointer_argument, has predicate. */ /* Skip verify of regset_from_core_section, has predicate. */ + /* Skip verify of iterate_over_regset_sections, has predicate. */ /* Skip verify of make_corefile_notes, has predicate. */ /* Skip verify of elfcore_write_linux_prpsinfo, has predicate. */ /* Skip verify of find_memory_regions, has predicate. */ @@ -767,9 +768,6 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) fprintf_unfiltered (file, "gdbarch_dump: core_read_description = <%s>\n", host_address_to_string (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)); @@ -986,6 +984,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) fprintf_unfiltered (file, "gdbarch_dump: iterate_over_objfiles_in_search_order = <%s>\n", host_address_to_string (gdbarch->iterate_over_objfiles_in_search_order)); + fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_iterate_over_regset_sections_p() = %d\n", + gdbarch_iterate_over_regset_sections_p (gdbarch)); + fprintf_unfiltered (file, + "gdbarch_dump: iterate_over_regset_sections = <%s>\n", + host_address_to_string (gdbarch->iterate_over_regset_sections)); fprintf_unfiltered (file, "gdbarch_dump: long_bit = %s\n", plongest (gdbarch->long_bit)); @@ -3260,20 +3264,28 @@ set_gdbarch_regset_from_core_section (struct gdbarch *gdbarch, gdbarch->regset_from_core_section = regset_from_core_section; } -struct core_regset_section * -gdbarch_core_regset_sections (struct gdbarch *gdbarch) +int +gdbarch_iterate_over_regset_sections_p (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; + return gdbarch->iterate_over_regset_sections != NULL; } void -set_gdbarch_core_regset_sections (struct gdbarch *gdbarch, - struct core_regset_section * core_regset_sections) +gdbarch_iterate_over_regset_sections (struct gdbarch *gdbarch, iterate_over_regset_sections_cb *cb, void *cb_data, const struct regcache *regcache) { - gdbarch->core_regset_sections = core_regset_sections; + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->iterate_over_regset_sections != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_iterate_over_regset_sections called\n"); + gdbarch->iterate_over_regset_sections (gdbarch, cb, cb_data, regcache); +} + +void +set_gdbarch_iterate_over_regset_sections (struct gdbarch *gdbarch, + gdbarch_iterate_over_regset_sections_ftype iterate_over_regset_sections) +{ + gdbarch->iterate_over_regset_sections = iterate_over_regset_sections; } int diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 0303b2e35a..bbda3da376 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -81,6 +81,9 @@ extern struct gdbarch *target_gdbarch (void); typedef int (iterate_over_objfiles_in_search_order_cb_ftype) (struct objfile *objfile, void *cb_data); +typedef void (iterate_over_regset_sections_cb) + (const char *sect_name, int size, const char *human_name, void *cb_data); + /* The following are pre-initialized by GDBARCH. */ @@ -741,10 +744,18 @@ typedef const struct regset * (gdbarch_regset_from_core_section_ftype) (struct g 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. */ +/* Iterate over all supported register notes in a core file. For each + supported register note section, the iterator must call CB and pass + CB_DATA unchanged. If REGCACHE is not NULL, the iterator can limit + the supported register note sections based on the current register + values. Otherwise it should enumerate all supported register note + sections. */ -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); +extern int gdbarch_iterate_over_regset_sections_p (struct gdbarch *gdbarch); + +typedef void (gdbarch_iterate_over_regset_sections_ftype) (struct gdbarch *gdbarch, iterate_over_regset_sections_cb *cb, void *cb_data, const struct regcache *regcache); +extern void gdbarch_iterate_over_regset_sections (struct gdbarch *gdbarch, iterate_over_regset_sections_cb *cb, void *cb_data, const struct regcache *regcache); +extern void set_gdbarch_iterate_over_regset_sections (struct gdbarch *gdbarch, gdbarch_iterate_over_regset_sections_ftype *iterate_over_regset_sections); /* Create core file notes */ diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 2a8bca87ce..80d3eec8db 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -655,8 +655,13 @@ F:CORE_ADDR:fetch_pointer_argument:struct frame_info *frame, int argi, struct ty # 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) +# Iterate over all supported register notes in a core file. For each +# supported register note section, the iterator must call CB and pass +# CB_DATA unchanged. If REGCACHE is not NULL, the iterator can limit +# the supported register note sections based on the current register +# values. Otherwise it should enumerate all supported register note +# sections. +M:void:iterate_over_regset_sections:iterate_over_regset_sections_cb *cb, void *cb_data, const struct regcache *regcache:cb, cb_data, regcache # Create core file notes M:char *:make_corefile_notes:bfd *obfd, int *note_size:obfd, note_size @@ -1169,6 +1174,9 @@ extern struct gdbarch *target_gdbarch (void); typedef int (iterate_over_objfiles_in_search_order_cb_ftype) (struct objfile *objfile, void *cb_data); + +typedef void (iterate_over_regset_sections_cb) + (const char *sect_name, int size, const char *human_name, void *cb_data); EOF # function typedef's diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c index b3707f7a7e..4ee6874a29 100644 --- a/gdb/i386-linux-tdep.c +++ b/gdb/i386-linux-tdep.c @@ -52,28 +52,6 @@ #include "features/i386/i386-avx-linux.c" #include "features/i386/i386-avx512-linux.c" -/* Supported register note sections. */ -static struct core_regset_section i386_linux_regset_sections[] = -{ - { ".reg", 68, "general-purpose" }, - { ".reg2", 108, "floating-point" }, - { NULL, 0 } -}; - -static struct core_regset_section i386_linux_sse_regset_sections[] = -{ - { ".reg", 68, "general-purpose" }, - { ".reg-xfp", 512, "extended floating-point" }, - { NULL, 0 } -}; - -static struct core_regset_section i386_linux_avx_regset_sections[] = -{ - { ".reg", 68, "general-purpose" }, - { ".reg-xstate", X86_XSTATE_MAX_SIZE, "XSAVE extended state" }, - { NULL, 0 } -}; - /* Return non-zero, when the register is in the corresponding register group. Put the LINUX_ORIG_EAX register in the system group. */ static int @@ -670,6 +648,26 @@ i386_linux_core_read_description (struct gdbarch *gdbarch, return tdesc_i386_mmx_linux; } +/* Iterate over core file register note sections. */ + +static void +i386_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + cb (".reg", 68, "general-purpose", cb_data); + + if (tdep->xcr0 & X86_XSTATE_AVX) + cb (".reg-xstate", X86_XSTATE_MAX_SIZE, "XSAVE extended state", cb_data); + else if (tdep->xcr0 & X86_XSTATE_SSE) + cb (".reg-xfp", 512, "extended floating-point", cb_data); + else + cb (".reg2", 108, "floating-point", cb_data); +} + /* Linux kernel shows PC value after the 'int $0x80' instruction even if inferior is still inside the syscall. On next PTRACE_SINGLESTEP it will finish the syscall but PC will not change. @@ -948,15 +946,9 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map); - /* Install supported register note sections. */ - if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx512") - || tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx")) - set_gdbarch_core_regset_sections (gdbarch, i386_linux_avx_regset_sections); - else if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.sse")) - set_gdbarch_core_regset_sections (gdbarch, i386_linux_sse_regset_sections); - else - set_gdbarch_core_regset_sections (gdbarch, i386_linux_regset_sections); - + /* Core file support. */ + set_gdbarch_iterate_over_regset_sections + (gdbarch, i386_linux_iterate_over_regset_sections); set_gdbarch_core_read_description (gdbarch, i386_linux_core_read_description); diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index dae59c50f1..3d8b1fc7af 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -1084,6 +1084,57 @@ linux_make_mappings_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, return note_data; } +/* Structure for passing information from + linux_collect_thread_registers via an iterator to + linux_collect_regset_section_cb. */ + +struct linux_collect_regset_section_cb_data +{ + struct gdbarch *gdbarch; + const struct regcache *regcache; + bfd *obfd; + char *note_data; + int *note_size; + unsigned long lwp; + enum gdb_signal stop_signal; + int abort_iteration; +}; + +/* Callback for iterate_over_regset_sections that records a single + regset in the corefile note section. */ + +static void +linux_collect_regset_section_cb (const char *sect_name, int size, + const char *human_name, void *cb_data) +{ + const struct regset *regset; + char *buf; + struct linux_collect_regset_section_cb_data *data = cb_data; + + if (data->abort_iteration) + return; + + regset = gdbarch_regset_from_core_section (data->gdbarch, sect_name, size); + gdb_assert (regset && regset->collect_regset); + + buf = xmalloc (size); + regset->collect_regset (regset, data->regcache, -1, buf, size); + + /* PRSTATUS still needs to be treated specially. */ + if (strcmp (sect_name, ".reg") == 0) + data->note_data = (char *) elfcore_write_prstatus + (data->obfd, data->note_data, data->note_size, data->lwp, + gdb_signal_to_host (data->stop_signal), buf); + else + data->note_data = (char *) elfcore_write_register_note + (data->obfd, data->note_data, data->note_size, + sect_name, buf, size); + xfree (buf); + + if (data->note_data == NULL) + data->abort_iteration = 1; +} + /* Records the thread's register state for the corefile note section. */ @@ -1094,47 +1145,25 @@ linux_collect_thread_registers (const struct regcache *regcache, enum gdb_signal stop_signal) { struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct core_regset_section *sect_list; - unsigned long lwp; + struct linux_collect_regset_section_cb_data data; - sect_list = gdbarch_core_regset_sections (gdbarch); - gdb_assert (sect_list); + data.gdbarch = gdbarch; + data.regcache = regcache; + data.obfd = obfd; + data.note_data = note_data; + data.note_size = note_size; + data.stop_signal = stop_signal; + data.abort_iteration = 0; /* For remote targets the LWP may not be available, so use the TID. */ - lwp = ptid_get_lwp (ptid); - if (!lwp) - lwp = ptid_get_tid (ptid); + data.lwp = ptid_get_lwp (ptid); + if (!data.lwp) + data.lwp = ptid_get_tid (ptid); - while (sect_list->sect_name != NULL) - { - const struct regset *regset; - char *buf; - - regset = gdbarch_regset_from_core_section (gdbarch, - sect_list->sect_name, - sect_list->size); - gdb_assert (regset && regset->collect_regset); - - buf = xmalloc (sect_list->size); - regset->collect_regset (regset, regcache, -1, buf, sect_list->size); - - /* PRSTATUS still needs to be treated specially. */ - if (strcmp (sect_list->sect_name, ".reg") == 0) - note_data = (char *) elfcore_write_prstatus - (obfd, note_data, note_size, lwp, - gdb_signal_to_host (stop_signal), buf); - else - note_data = (char *) elfcore_write_register_note - (obfd, note_data, note_size, - sect_list->sect_name, buf, sect_list->size); - xfree (buf); - sect_list++; - - if (!note_data) - return NULL; - } - - return note_data; + gdbarch_iterate_over_regset_sections (gdbarch, + linux_collect_regset_section_cb, + &data, regcache); + return data.note_data; } /* Fetch the siginfo data for the current thread, if it exists. If @@ -1524,7 +1553,7 @@ linux_make_corefile_notes_1 (struct gdbarch *gdbarch, bfd *obfd, int *note_size) converted to gdbarch_core_regset_sections, we no longer need to fall back to the target method at this point. */ - if (!gdbarch_core_regset_sections (gdbarch)) + if (!gdbarch_iterate_over_regset_sections_p (gdbarch)) return target_make_corefile_notes (obfd, note_size); else return linux_make_corefile_notes (gdbarch, obfd, note_size, diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 316b254093..7ab32553b8 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -257,54 +257,6 @@ ppc_linux_return_value (struct gdbarch *gdbarch, struct value *function, readbuf, writebuf); } -static struct core_regset_section ppc_linux_vsx_regset_sections[] = -{ - { ".reg", 48 * 4, "general-purpose" }, - { ".reg2", 264, "floating-point" }, - { ".reg-ppc-vmx", 544, "ppc Altivec" }, - { ".reg-ppc-vsx", 256, "POWER7 VSX" }, - { NULL, 0} -}; - -static struct core_regset_section ppc_linux_vmx_regset_sections[] = -{ - { ".reg", 48 * 4, "general-purpose" }, - { ".reg2", 264, "floating-point" }, - { ".reg-ppc-vmx", 544, "ppc Altivec" }, - { NULL, 0} -}; - -static struct core_regset_section ppc_linux_fp_regset_sections[] = -{ - { ".reg", 48 * 4, "general-purpose" }, - { ".reg2", 264, "floating-point" }, - { NULL, 0} -}; - -static struct core_regset_section ppc64_linux_vsx_regset_sections[] = -{ - { ".reg", 48 * 8, "general-purpose" }, - { ".reg2", 264, "floating-point" }, - { ".reg-ppc-vmx", 544, "ppc Altivec" }, - { ".reg-ppc-vsx", 256, "POWER7 VSX" }, - { NULL, 0} -}; - -static struct core_regset_section ppc64_linux_vmx_regset_sections[] = -{ - { ".reg", 48 * 8, "general-purpose" }, - { ".reg2", 264, "floating-point" }, - { ".reg-ppc-vmx", 544, "ppc Altivec" }, - { NULL, 0} -}; - -static struct core_regset_section ppc64_linux_fp_regset_sections[] = -{ - { ".reg", 48 * 8, "general-purpose" }, - { ".reg2", 264, "floating-point" }, - { NULL, 0} -}; - /* PLT stub in executable. */ static struct ppc_insn_pattern powerpc32_plt_stub[] = { @@ -558,6 +510,28 @@ ppc_linux_regset_from_core_section (struct gdbarch *core_arch, return NULL; } +/* Iterate over supported core file register note sections. */ + +static void +ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int have_altivec = tdep->ppc_vr0_regnum != -1; + int have_vsx = tdep->ppc_vsr0_upper_regnum != -1; + + cb (".reg", 48 * tdep->wordsize, "general-purpose", cb_data); + cb (".reg2", 264, "floating-point", cb_data); + + if (have_altivec) + cb (".reg-ppc-vmx", 544, "ppc Altivec", cb_data); + + if (have_vsx) + cb (".reg-ppc-vsx", 256, "POWER7 VSX", cb_data); +} + static void ppc_linux_sigtramp_cache (struct frame_info *this_frame, struct trad_frame_cache *this_cache, @@ -1352,19 +1326,6 @@ ppc_linux_init_abi (struct gdbarch_info info, else set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc"); - /* Supported register sections. */ - if (tdesc_find_feature (info.target_desc, - "org.gnu.gdb.power.vsx")) - set_gdbarch_core_regset_sections (gdbarch, - ppc_linux_vsx_regset_sections); - else if (tdesc_find_feature (info.target_desc, - "org.gnu.gdb.power.altivec")) - set_gdbarch_core_regset_sections (gdbarch, - ppc_linux_vmx_regset_sections); - else - set_gdbarch_core_regset_sections (gdbarch, - ppc_linux_fp_regset_sections); - if (powerpc_so_ops.in_dynsym_resolve_code == NULL) { powerpc_so_ops = svr4_so_ops; @@ -1416,19 +1377,6 @@ ppc_linux_init_abi (struct gdbarch_info info, set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpcle"); else set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc"); - - /* Supported register sections. */ - if (tdesc_find_feature (info.target_desc, - "org.gnu.gdb.power.vsx")) - set_gdbarch_core_regset_sections (gdbarch, - ppc64_linux_vsx_regset_sections); - else if (tdesc_find_feature (info.target_desc, - "org.gnu.gdb.power.altivec")) - set_gdbarch_core_regset_sections (gdbarch, - ppc64_linux_vmx_regset_sections); - else - set_gdbarch_core_regset_sections (gdbarch, - ppc64_linux_fp_regset_sections); } /* PPC32 uses a different prpsinfo32 compared to most other Linux @@ -1440,6 +1388,8 @@ ppc_linux_init_abi (struct gdbarch_info info, set_gdbarch_regset_from_core_section (gdbarch, ppc_linux_regset_from_core_section); set_gdbarch_core_read_description (gdbarch, ppc_linux_core_read_description); + set_gdbarch_iterate_over_regset_sections (gdbarch, + ppc_linux_iterate_over_regset_sections); /* Enable TLS support. */ set_gdbarch_fetch_tls_load_module_address (gdbarch, diff --git a/gdb/regset.h b/gdb/regset.h index 37ed99a3b6..68e19ee471 100644 --- a/gdb/regset.h +++ b/gdb/regset.h @@ -23,14 +23,6 @@ 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; - const char *human_name; -}; - /* Data structure describing a register set. */ typedef void (supply_regset_ftype) (const struct regset *, struct regcache *, diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c index ac8118b6cc..840431d513 100644 --- a/gdb/s390-linux-tdep.c +++ b/gdb/s390-linux-tdep.c @@ -88,6 +88,10 @@ struct gdbarch_tdep const struct regset *fpregset; int sizeof_fpregset; + + int have_linux_v1; + int have_linux_v2; + int have_tdb; }; @@ -532,84 +536,6 @@ const struct regset s390_tdb_regset = { regcache_collect_regset }; -static struct core_regset_section s390_linux32_regset_sections[] = -{ - { ".reg", s390_sizeof_gregset, "general-purpose" }, - { ".reg2", s390_sizeof_fpregset, "floating-point" }, - { NULL, 0} -}; - -static struct core_regset_section s390_linux32v1_regset_sections[] = -{ - { ".reg", s390_sizeof_gregset, "general-purpose" }, - { ".reg2", s390_sizeof_fpregset, "floating-point" }, - { ".reg-s390-last-break", 8, "s390 last-break address" }, - { NULL, 0} -}; - -static struct core_regset_section s390_linux32v2_regset_sections[] = -{ - { ".reg", s390_sizeof_gregset, "general-purpose" }, - { ".reg2", s390_sizeof_fpregset, "floating-point" }, - { ".reg-s390-last-break", 8, "s390 last-break address" }, - { ".reg-s390-system-call", 4, "s390 system-call" }, - { NULL, 0} -}; - -static struct core_regset_section s390_linux64_regset_sections[] = -{ - { ".reg", s390_sizeof_gregset, "general-purpose" }, - { ".reg2", s390_sizeof_fpregset, "floating-point" }, - { ".reg-s390-high-gprs", 16*4, "s390 GPR upper halves" }, - { NULL, 0} -}; - -static struct core_regset_section s390_linux64v1_regset_sections[] = -{ - { ".reg", s390_sizeof_gregset, "general-purpose" }, - { ".reg2", s390_sizeof_fpregset, "floating-point" }, - { ".reg-s390-high-gprs", 16*4, "s390 GPR upper halves" }, - { ".reg-s390-last-break", 8, "s930 last-break address" }, - { NULL, 0} -}; - -static struct core_regset_section s390_linux64v2_regset_sections[] = -{ - { ".reg", s390_sizeof_gregset, "general-purpose" }, - { ".reg2", s390_sizeof_fpregset, "floating-point" }, - { ".reg-s390-high-gprs", 16*4, "s390 GPR upper halves" }, - { ".reg-s390-last-break", 8, "s930 last-break address" }, - { ".reg-s390-system-call", 4, "s390 system-call" }, - { ".reg-s390-tdb", s390_sizeof_tdbregset, "s390 TDB" }, - { NULL, 0} -}; - -static struct core_regset_section s390x_linux64_regset_sections[] = -{ - { ".reg", s390x_sizeof_gregset, "general-purpose" }, - { ".reg2", s390_sizeof_fpregset, "floating-point" }, - { NULL, 0} -}; - -static struct core_regset_section s390x_linux64v1_regset_sections[] = -{ - { ".reg", s390x_sizeof_gregset, "general-purpose" }, - { ".reg2", s390_sizeof_fpregset, "floating-point" }, - { ".reg-s390-last-break", 8, "s930 last-break address" }, - { NULL, 0} -}; - -static struct core_regset_section s390x_linux64v2_regset_sections[] = -{ - { ".reg", s390x_sizeof_gregset, "general-purpose" }, - { ".reg2", s390_sizeof_fpregset, "floating-point" }, - { ".reg-s390-last-break", 8, "s930 last-break address" }, - { ".reg-s390-system-call", 4, "s390 system-call" }, - { ".reg-s390-tdb", s390_sizeof_tdbregset, "s390 TDB" }, - { NULL, 0} -}; - - /* Return the appropriate register set for the core section identified by SECT_NAME and SECT_SIZE. */ static const struct regset * @@ -640,6 +566,38 @@ s390_regset_from_core_section (struct gdbarch *gdbarch, return NULL; } +/* Iterate over supported core file register note sections. */ + +static void +s390_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + cb (".reg", tdep->sizeof_gregset, "general-purpose", cb_data); + cb (".reg2", s390_sizeof_fpregset, "floating-point", cb_data); + + if (tdep->abi == ABI_LINUX_S390 && tdep->gpr_full_regnum != -1) + cb (".reg-s390-high-gprs", 16 * 4, "s390 GPR upper halves", cb_data); + + if (tdep->have_linux_v1) + cb (".reg-s390-last-break", 8, "s930 last-break address", cb_data); + + if (tdep->have_linux_v2) + cb (".reg-s390-system-call", 4, "s390 system-call", cb_data); + + /* If regcache is set, we are in "write" (gcore) mode. In this + case, don't iterate over the TDB unless its registers are + available. */ + if (tdep->have_tdb + && (regcache == NULL + || REG_VALID == regcache_register_status (regcache, + S390_TDB_DWORD0_REGNUM))) + cb (".reg-s390-tdb", s390_sizeof_tdbregset, "s390 TDB", cb_data); +} + static const struct target_desc * s390_core_read_description (struct gdbarch *gdbarch, struct target_ops *target, bfd *abfd) @@ -2904,6 +2862,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) int have_upper = 0; int have_linux_v1 = 0; int have_linux_v2 = 0; + int have_tdb = 0; int first_pseudo_reg, last_pseudo_reg; static const char *const stap_register_prefixes[] = { "%", NULL }; static const char *const stap_register_indirection_prefixes[] = { "(", @@ -3048,6 +3007,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) valid_p &= tdesc_numbered_register (feature, tdesc_data, S390_TDB_DWORD0_REGNUM + i, tdb_regs[i]); + have_tdb = 1; } if (!valid_p) @@ -3077,6 +3037,9 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Otherwise create a new gdbarch for the specified machine type. */ tdep = XCNEW (struct gdbarch_tdep); tdep->abi = tdep_abi; + tdep->have_linux_v1 = have_linux_v1; + tdep->have_linux_v2 = have_linux_v2; + tdep->have_tdb = have_tdb; gdbarch = gdbarch_alloc (&info, tdep); set_gdbarch_believe_pcc_promotion (gdbarch, 0); @@ -3107,6 +3070,8 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_regset_from_core_section (gdbarch, s390_regset_from_core_section); set_gdbarch_core_read_description (gdbarch, s390_core_read_description); + set_gdbarch_iterate_over_regset_sections (gdbarch, + s390_iterate_over_regset_sections); set_gdbarch_cannot_store_register (gdbarch, s390_cannot_store_register); set_gdbarch_write_pc (gdbarch, s390_write_pc); set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read); @@ -3179,31 +3144,6 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) (gdbarch, svr4_ilp32_fetch_link_map_offsets); set_xml_syscall_file_name (XML_SYSCALL_FILENAME_S390); - - if (have_upper) - { - if (have_linux_v2) - set_gdbarch_core_regset_sections (gdbarch, - s390_linux64v2_regset_sections); - else if (have_linux_v1) - set_gdbarch_core_regset_sections (gdbarch, - s390_linux64v1_regset_sections); - else - set_gdbarch_core_regset_sections (gdbarch, - s390_linux64_regset_sections); - } - else - { - if (have_linux_v2) - set_gdbarch_core_regset_sections (gdbarch, - s390_linux32v2_regset_sections); - else if (have_linux_v1) - set_gdbarch_core_regset_sections (gdbarch, - s390_linux32v1_regset_sections); - else - set_gdbarch_core_regset_sections (gdbarch, - s390_linux32_regset_sections); - } break; case ABI_LINUX_ZSERIES: @@ -3223,18 +3163,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) s390_address_class_type_flags_to_name); set_gdbarch_address_class_name_to_type_flags (gdbarch, s390_address_class_name_to_type_flags); - set_xml_syscall_file_name (XML_SYSCALL_FILENAME_S390); - - if (have_linux_v2) - set_gdbarch_core_regset_sections (gdbarch, - s390x_linux64v2_regset_sections); - else if (have_linux_v1) - set_gdbarch_core_regset_sections (gdbarch, - s390x_linux64v1_regset_sections); - else - set_gdbarch_core_regset_sections (gdbarch, - s390x_linux64_regset_sections); break; }