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.
This commit is contained in:
Andreas Arnez 2014-09-04 15:26:43 +00:00 committed by Andreas Krebbel
parent 6a5f3f4353
commit 5aa82d050d
12 changed files with 312 additions and 328 deletions

View File

@ -1,3 +1,55 @@
2014-09-30 Andreas Arnez <arnez@linux.vnet.ibm.com>
* 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 <jan.kratochvil@redhat.com>
* solib-svr4.c (svr4_parse_libraries): Use "library-list-svr4.dtd".

View File

@ -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);

View File

@ -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. */

View File

@ -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,

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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 *,

View File

@ -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;
}