aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog7
-rw-r--r--gdb/gdbserver/ChangeLog352
-rw-r--r--gdb/gdbserver/Makefile.in7
-rw-r--r--gdb/gdbserver/ax.c2
-rw-r--r--gdb/gdbserver/i387-fp.c34
-rw-r--r--gdb/gdbserver/i387-fp.h2
-rw-r--r--gdb/gdbserver/inferiors.c1
-rw-r--r--gdb/gdbserver/linux-aarch64-low.c43
-rw-r--r--gdb/gdbserver/linux-amd64-ipa.c6
-rw-r--r--gdb/gdbserver/linux-arm-low.c91
-rw-r--r--gdb/gdbserver/linux-bfin-low.c38
-rw-r--r--gdb/gdbserver/linux-cris-low.c37
-rw-r--r--gdb/gdbserver/linux-crisv32-low.c52
-rw-r--r--gdb/gdbserver/linux-i386-ipa.c2
-rw-r--r--gdb/gdbserver/linux-ia64-low.c44
-rw-r--r--gdb/gdbserver/linux-low.c217
-rw-r--r--gdb/gdbserver/linux-low.h72
-rw-r--r--gdb/gdbserver/linux-m32r-low.c37
-rw-r--r--gdb/gdbserver/linux-m68k-low.c50
-rw-r--r--gdb/gdbserver/linux-mips-low.c193
-rw-r--r--gdb/gdbserver/linux-nios2-low.c43
-rw-r--r--gdb/gdbserver/linux-ppc-low.c181
-rw-r--r--gdb/gdbserver/linux-s390-low.c195
-rw-r--r--gdb/gdbserver/linux-sh-low.c49
-rw-r--r--gdb/gdbserver/linux-sparc-low.c60
-rw-r--r--gdb/gdbserver/linux-tic6x-low.c73
-rw-r--r--gdb/gdbserver/linux-tile-low.c48
-rw-r--r--gdb/gdbserver/linux-x86-low.c467
-rw-r--r--gdb/gdbserver/linux-xtensa-low.c61
-rw-r--r--gdb/gdbserver/lynx-i386-low.c2
-rw-r--r--gdb/gdbserver/lynx-low.c3
-rw-r--r--gdb/gdbserver/lynx-low.h4
-rw-r--r--gdb/gdbserver/lynx-ppc-low.c2
-rw-r--r--gdb/gdbserver/nto-low.c6
-rw-r--r--gdb/gdbserver/nto-low.h6
-rw-r--r--gdb/gdbserver/nto-x86-low.c2
-rw-r--r--gdb/gdbserver/proc-service.c10
-rw-r--r--gdb/gdbserver/regcache.c242
-rw-r--r--gdb/gdbserver/regcache.h33
-rw-r--r--gdb/gdbserver/remote-utils.c9
-rw-r--r--gdb/gdbserver/server.c25
-rw-r--r--gdb/gdbserver/server.h6
-rw-r--r--gdb/gdbserver/spu-low.c10
-rw-r--r--gdb/gdbserver/tdesc.c66
-rw-r--r--gdb/gdbserver/tdesc.h64
-rw-r--r--gdb/gdbserver/tracepoint.c35
-rw-r--r--gdb/gdbserver/win32-arm-low.c11
-rw-r--r--gdb/gdbserver/win32-i386-low.c8
-rw-r--r--gdb/gdbserver/win32-low.c10
-rw-r--r--gdb/gdbserver/win32-low.h6
-rwxr-xr-xgdb/regformats/regdat.sh30
51 files changed, 2343 insertions, 711 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6661193..1e0839f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,10 @@
+2013-06-07 Pedro Alves <palves@redhat.com>
+
+ * regformats/regdat.sh: Output #include tdesc.h. Make globals
+ static. Output a global target description pointer.
+ (init_registers_${name}): Adjust to initialize a
+ target description structure.
+
2013-06-07 Will Newton <will.newton@linaro.org>
* printcmd.c (build_address_symbolic): Call
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 563b48e..5bb05cd 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,355 @@
+2013-06-07 Pedro Alves <palves@redhat.com>
+
+ * Makefile.in (OBS): Add tdesc.o.
+ (IPA_OBJS): Add tdesc-ipa.o.
+ (tdesc-ipa.o): New rule.
+ * ax.c (gdb_eval_agent_expr): Adjust register_size call to new
+ interface.
+ * linux-low.c (new_inferior): Delete.
+ (disabled_regsets, num_regsets): Delete.
+ (linux_add_process): Adjust to set the new per-process
+ new_inferior flag.
+ (linux_detach_one_lwp): Adjust to call regcache_invalidate_thread.
+ (linux_wait_for_lwp): Adjust. Only call arch_setup if the event
+ was a stop. When calling arch_setup, switch the current inferior
+ to the thread that got an event.
+ (linux_resume_one_lwp): Adjust to call regcache_invalidate_thread.
+ (regsets_fetch_inferior_registers)
+ (regsets_store_inferior_registers): New regsets_info parameter.
+ Adjust to use it.
+ (linux_register_in_regsets): New regs_info parameter. Adjust to
+ use it.
+ (register_addr, fetch_register, store_register): New usrregs_info
+ parameter. Adjust to use it.
+ (usr_fetch_inferior_registers, usr_store_inferior_registers): New
+ parameter regs_info. Adjust to use it.
+ (linux_fetch_registers): Get the current inferior's regs_info, and
+ adjust to use it.
+ (linux_store_registers): Ditto.
+ [HAVE_LINUX_REGSETS] (initialize_regsets_info): New.
+ (initialize_low): Don't initialize the target_regsets here. Call
+ initialize_low_arch.
+ * linux-low.h (target_regsets): Delete declaration.
+ (struct regsets_info): New.
+ (struct usrregs_info): New.
+ (struct regs_info): New.
+ (struct process_info_private) <new_inferior>: New field.
+ (struct linux_target_ops): Delete the num_regs, regmap, and
+ regset_bitmap fields. New field regs_info.
+ [HAVE_LINUX_REGSETS] (initialize_regsets_info): Declare.
+ * i387-fp.c (num_xmm_registers): Delete.
+ (i387_cache_to_fsave, i387_fsave_to_cache): Adjust find_regno
+ calls to new interface.
+ (i387_cache_to_fxsave, i387_cache_to_xsave, i387_fxsave_to_cache)
+ (i387_xsave_to_cache): Adjust find_regno calls to new interface.
+ Infer the number of xmm registers from the regcache's target
+ description.
+ * i387-fp.h (num_xmm_registers): Delete.
+ * inferiors.c (add_thread): Don't install the thread's regcache
+ here.
+ * proc-service.c (gregset_info): Fetch the current inferior's
+ regs_info. Adjust to use it.
+ * regcache.c: Include tdesc.h.
+ (register_bytes, reg_defs, num_registers)
+ (gdbserver_expedite_regs): Delete.
+ (get_thread_regcache): If the thread doesn't have a regcache yet,
+ create one, instead of aborting gdbserver.
+ (regcache_invalidate_one): Rename to ...
+ (regcache_invalidate_thread): ... this.
+ (regcache_invalidate_one): New.
+ (regcache_invalidate): Only invalidate registers of the current
+ process.
+ (init_register_cache): Add target_desc parameter, and use it.
+ (new_register_cache): Ditto. Assert the target description has a
+ non zero registers_size.
+ (regcache_cpy): Add assertions. Adjust.
+ (realloc_register_cache, set_register_cache): Delete.
+ (registers_to_string, registers_from_string): Adjust.
+ (find_register_by_name, find_regno, find_register_by_number)
+ (register_cache_size): Add target_desc parameter, and use it.
+ (free_register_cache_thread, free_register_cache_thread_one)
+ (regcache_release, register_cache_size): New.
+ (register_size): Add target_desc parameter, and use it.
+ (register_data, supply_register, supply_register_zeroed)
+ (supply_regblock, supply_register_by_name, collect_register)
+ (collect_register_as_string, collect_register_by_name): Adjust.
+ * regcache.h (struct target_desc): Forward declare.
+ (struct regcache) <tdesc>: New field.
+ (init_register_cache, new_register_cache): Add target_desc
+ parameter.
+ (regcache_invalidate_thread): Declare.
+ (regcache_invalidate_one): Delete declaration.
+ (regcache_release): Declare.
+ (find_register_by_number, register_cache_size, register_size)
+ (find_regno): Add target_desc parameter.
+ (gdbserver_expedite_regs, gdbserver_xmltarget): Delete
+ declarations.
+ * remote-utils.c: Include tdesc.h.
+ (outreg, prepare_resume_reply): Adjust.
+ * server.c: Include tdesc.h.
+ (gdbserver_xmltarget): Delete declaration.
+ (get_features_xml, process_serial_event): Adjust.
+ * server.h [IN_PROCESS_AGENT] (struct target_desc): Forward
+ declare.
+ (struct process_info) <tdesc>: New field.
+ (ipa_tdesc): Declare.
+ * tdesc.c: New file.
+ * tdesc.h: New file.
+ * tracepoint.c: Include tdesc.h.
+ [IN_PROCESS_AGENT] (ipa_tdesc): Define.
+ (get_context_regcache): Adjust to pass ipa_tdesc down.
+ (do_action_at_tracepoint): Adjust to get the register cache size
+ from the context regcache's description.
+ (traceframe_walk_blocks): Adjust to get the register cache size
+ from the current trace frame's description.
+ (traceframe_get_pc): Adjust to get current trace frame's
+ description and pass it down.
+ (gdb_collect): Adjust to get the register cache size from the
+ IPA's description.
+ * linux-amd64-ipa.c (tdesc_amd64_linux): Declare.
+ (gdbserver_xmltarget): Delete.
+ (initialize_low_tracepoint): Set the ipa's target description.
+ * linux-i386-ipa.c (tdesc_i386_linux): Declare.
+ (initialize_low_tracepoint): Set the ipa's target description.
+ * linux-x86-low.c: Include tdesc.h.
+ [__x86_64__] (is_64bit_tdesc): New.
+ (ps_get_thread_area, x86_get_thread_area): Use it.
+ (i386_cannot_store_register): Rename to ...
+ (x86_cannot_store_register): ... this. Use is_64bit_tdesc.
+ (i386_cannot_fetch_register): Rename to ...
+ (x86_cannot_fetch_register): ... this. Use is_64bit_tdesc.
+ (x86_fill_gregset, x86_store_gregset): Adjust register_size calls
+ to new interface.
+ (target_regsets): Rename to ...
+ (x86_regsets): ... this.
+ (x86_get_pc, x86_set_pc): Adjust register_size calls to new
+ interface.
+ (x86_siginfo_fixup): Use is_64bit_tdesc.
+ [__x86_64__] (tdesc_amd64_linux, tdesc_amd64_avx_linux)
+ (tdesc_x32_avx_linux, tdesc_x32_linux)
+ (tdesc_i386_linux, tdesc_i386_mmx_linux, tdesc_i386_avx_linux):
+ Declare.
+ (x86_linux_update_xmltarget): Delete.
+ (I386_LINUX_XSAVE_XCR0_OFFSET): Define.
+ (have_ptrace_getfpxregs, have_ptrace_getregset): New.
+ (AMD64_LINUX_USER64_CS): New.
+ (x86_linux_read_description): New, based on
+ x86_linux_update_xmltarget.
+ (same_process_callback): New.
+ (x86_arch_setup_process_callback): New.
+ (x86_linux_update_xmltarget): New.
+ (x86_regsets_info): New.
+ (amd64_linux_regs_info): New.
+ (i386_linux_usrregs_info): New.
+ (i386_linux_regs_info): New.
+ (x86_linux_regs_info): New.
+ (x86_arch_setup): Reimplement.
+ (x86_install_fast_tracepoint_jump_pad): Use is_64bit_tdesc.
+ (x86_emit_ops): Ditto.
+ (the_low_target): Adjust. Install x86_linux_regs_info,
+ x86_cannot_fetch_register, and x86_cannot_store_register.
+ (initialize_low_arch): New.
+ * linux-ia64-low.c (tdesc_ia64): Declare.
+ (ia64_fetch_register): Adjust.
+ (ia64_usrregs_info, regs_info): New globals.
+ (ia64_regs_info): New function.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-sparc-low.c (tdesc_sparc64): Declare.
+ (sparc_fill_gregset_to_stack, sparc_store_gregset_from_stack):
+ Adjust.
+ (sparc_arch_setup): New function.
+ (sparc_regsets_info, sparc_usrregs_info, regs_info): New globals.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-ppc-low.c (tdesc_powerpc_32l, tdesc_powerpc_altivec32l)
+ (tdesc_powerpc_cell32l, tdesc_powerpc_vsx32l)
+ (tdesc_powerpc_isa205_32l, tdesc_powerpc_isa205_altivec32l)
+ (tdesc_powerpc_isa205_vsx32l, tdesc_powerpc_e500l)
+ (tdesc_powerpc_64l, tdesc_powerpc_altivec64l)
+ (tdesc_powerpc_cell64l, tdesc_powerpc_vsx64l)
+ (tdesc_powerpc_isa205_64l, tdesc_powerpc_isa205_altivec64l)
+ (tdesc_powerpc_isa205_vsx64l): Declare.
+ (ppc_cannot_store_register, ppc_collect_ptrace_register)
+ (ppc_supply_ptrace_register, parse_spufs_run, ppc_get_pc)
+ (ppc_set_pc, ppc_get_hwcap): Adjust.
+ (ppc_usrregs_info): Forward declare.
+ (!__powerpc64__) ppc_regmap_adjusted: New global.
+ (ppc_arch_setup): Adjust to the current process'es target
+ description.
+ (ppc_fill_vsxregset, ppc_store_vsxregset, ppc_fill_vrregset)
+ (ppc_store_vrregset, ppc_fill_evrregset, ppc_store_evrregse)
+ (ppc_store_evrregset): Adjust.
+ (target_regsets): Rename to ...
+ (ppc_regsets): ... this, and make static.
+ (ppc_usrregs_info, ppc_regsets_info, regs_info): New globals.
+ (ppc_regs_info): New function.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-s390-low.c (tdesc_s390_linux32, tdesc_s390_linux32v1)
+ (tdesc_s390_linux32v2, tdesc_s390_linux64, tdesc_s390_linux64v1)
+ (tdesc_s390_linux64v2, tdesc_s390x_linux64, tdesc_s390x_linux64v1)
+ (tdesc_s390x_linux64v2): Declare.
+ (s390_collect_ptrace_register, s390_supply_ptrace_register)
+ (s390_fill_gregset, s390_store_last_break): Adjust.
+ (target_regsets): Rename to ...
+ (s390_regsets): ... this, and make static.
+ (s390_get_pc, s390_set_pc): Adjust.
+ (s390_get_hwcap): New target_desc parameter, and use it.
+ [__s390x__] (have_hwcap_s390_high_gprs): New global.
+ (s390_arch_setup): Adjust to set the current process'es target
+ description. Don't adjust the regmap.
+ (s390_usrregs_info, s390_regsets_info, regs_info): New globals.
+ [__s390x__] (s390_usrregs_info_3264, s390_regsets_info_3264)
+ (regs_info_3264): New globals.
+ (s390_regs_info): New function.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-mips-low.c (tdesc_mips_linux, tdesc_mips_dsp_linux)
+ (tdesc_mips64_linux, tdesc_mips64_dsp_linux): Declare.
+ [__mips64] (init_registers_mips_linux)
+ (init_registers_mips_dsp_linux): Delete defines.
+ [__mips64] (tdesc_mips_linux, tdesc_mips_dsp_linux): New defines.
+ (have_dsp): New global.
+ (mips_read_description): New, based on mips_arch_setup.
+ (mips_arch_setup): Reimplement.
+ (get_usrregs_info): New function.
+ (mips_cannot_fetch_register, mips_cannot_store_register)
+ (mips_get_pc, mips_set_pc, mips_fill_gregset, mips_store_gregset)
+ (mips_fill_fpregset, mips_store_fpregset): Adjust.
+ (target_regsets): Rename to ...
+ (mips_regsets): ... this, and make static.
+ (mips_regsets_info, mips_dsp_usrregs_info, mips_usrregs_info)
+ (dsp_regs_info, regs_info): New globals.
+ (mips_regs_info): New function.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-arm-low.c (tdesc_arm, tdesc_arm_with_iwmmxt)
+ (tdesc_arm_with_vfpv2, tdesc_arm_with_vfpv3, tdesc_arm_with_neon):
+ Declare.
+ (arm_fill_vfpregset, arm_store_vfpregset): Adjust.
+ (arm_read_description): New, with bits factored from
+ arm_arch_setup.
+ (arm_arch_setup): Reimplement.
+ (target_regsets): Rename to ...
+ (arm_regsets): ... this, and make static.
+ (arm_regsets_info, arm_usrregs_info, regs_info): New globals.
+ (arm_regs_info): New function.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-m68k-low.c (tdesc_m68k): Declare.
+ (target_regsets): Rename to ...
+ (m68k_regsets): ... this, and make static.
+ (m68k_regsets_info, m68k_usrregs_info, regs_info): New globals.
+ (m68k_regs_info): New function.
+ (m68k_arch_setup): New function.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-sh-low.c (tdesc_sharch): Declare.
+ (target_regsets): Rename to ...
+ (sh_regsets): ... this, and make static.
+ (sh_regsets_info, sh_usrregs_info, regs_info): New globals.
+ (sh_regs_info, sh_arch_setup): New functions.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-bfin-low.c (tdesc_bfin): Declare.
+ (bfin_arch_setup): New function.
+ (bfin_usrregs_info, regs_info): New globals.
+ (bfin_regs_info): New function.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-cris-low.c (tdesc_cris): Declare.
+ (cris_arch_setup): New function.
+ (cris_usrregs_info, regs_info): New globals.
+ (cris_regs_info): New function.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-cris-low.c (tdesc_crisv32): Declare.
+ (cris_arch_setup): New function.
+ (cris_regsets_info, cris_usrregs_info, regs_info): New globals.
+ (cris_regs_info): New function.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-m32r-low.c (tdesc_m32r): Declare.
+ (m32r_arch_setup): New function.
+ (m32r_usrregs_info, regs_info): New globals.
+ (m32r_regs_info): Adjust.
+ (initialize_low_arch): New function.
+ * linux-tic6x-low.c (tdesc_tic6x_c64xp_linux)
+ (tdesc_tic6x_c64x_linux, tdesc_tic6x_c62x_linux): Declare.
+ (tic6x_usrregs_info): Forward declare.
+ (tic6x_read_description): New function, based on ...
+ (tic6x_arch_setup): ... this. Reimplement.
+ (target_regsets): Rename to ...
+ (tic6x_regsets): ... this, and make static.
+ (tic6x_regsets_info, tic6x_usrregs_info, regs_info): New globals.
+ (tic6x_regs_info): New function.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-xtensa-low.c (tdesc_xtensa): Declare.
+ (xtensa_fill_gregset, xtensa_store_gregset): Adjust.
+ (target_regsets): Rename to ...
+ (xtensa_regsets): ... this, and make static.
+ (xtensa_regsets_info, xtensa_usrregs_info, regs_info): New
+ globals.
+ (xtensa_arch_setup, xtensa_regs_info): New functions.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-nios2-low.c (tdesc_nios2_linux): Declare.
+ (nios2_arch_setup): Set the current process'es tdesc.
+ (target_regsets): Rename to ...
+ (nios2_regsets): ... this.
+ (nios2_regsets_info, nios2_usrregs_info, regs_info): New globals.
+ (nios2_regs_info): New function.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-aarch64-low.c (tdesc_aarch64): Declare.
+ (aarch64_arch_setup): Set the current process'es tdesc.
+ (target_regsets): Rename to ...
+ (aarch64_regsets): ... this.
+ (aarch64_regsets_info, aarch64_usrregs_info, regs_info): New globals.
+ (aarch64_regs_info): New function.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * linux-tile-low.c (tdesc_tilegx, tdesc_tilegx32): Declare
+ globals.
+ (target_regsets): Rename to ...
+ (tile_regsets): ... this.
+ (tile_regsets_info, tile_usrregs_info, regs_info): New globals.
+ (tile_regs_info): New function.
+ (tile_arch_setup): Set the current process'es tdesc.
+ (the_low_target): Adjust.
+ (initialize_low_arch): New function.
+ * spu-low.c (tdesc_spu): Declare.
+ (spu_create_inferior, spu_attach): Set the new process'es tdesc.
+ * win32-arm-low.c (tdesc_arm): Declare.
+ (arm_arch_setup): New function.
+ (the_low_target): Install arm_arch_setup instead of
+ init_registers_arm.
+ * win32-i386-low.c (tdesc_i386, tdesc_amd64): Declare.
+ (init_windows_x86): Rename to ...
+ (i386_arch_setup): ... this. Set `win32_tdesc'.
+ (the_low_target): Adjust.
+ * win32-low.c (win32_tdesc): New global.
+ (child_add_thread): Don't create the thread cache here.
+ (do_initial_child_stuff): Set the new process'es tdesc.
+ * win32-low.h (struct target_desc): Forward declare.
+ (win32_tdesc): Declare.
+ * lynx-i386-low.c (tdesc_i386): Declare global.
+ (lynx_i386_arch_setup): Set `lynx_tdesc'.
+ * lynx-low.c (lynx_tdesc): New global.
+ (lynx_add_process): Set the new process'es tdesc.
+ * lynx-low.h (struct target_desc): Forward declare.
+ (lynx_tdesc): Declare global.
+ * lynx-ppc-low.c (tdesc_powerpc_32): Declare global.
+ (lynx_ppc_arch_setup): Set `lynx_tdesc'.
+ * nto-low.c (nto_tdesc): New global.
+ (do_attach): Set the new process'es tdesc.
+ * nto-low.h (struct target_desc): Forward declare.
+ (nto_tdesc): Declare.
+ * nto-x86-low.c (tdesc_i386): Declare.
+ (nto_x86_arch_setup): Set `nto_tdesc'.
+
2013-06-04 Gary Benson <gbenson@redhat.com>
* server.c (handle_query): Add "augmented-libraries-svr4-read+"
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index c7ff4c6..e8470a8 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -170,7 +170,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o targ
utils.o version.o vec.o gdb_vecs.o \
mem-break.o hostio.o event-loop.o tracepoint.o \
xml-utils.o common-utils.o ptid.o buffer.o format.o filestuff.o \
- dll.o notif.o \
+ dll.o notif.o tdesc.o \
$(XML_BUILTIN) \
$(DEPFILES) $(LIBOBJS)
GDBREPLAY_OBS = gdbreplay.o version.o
@@ -287,7 +287,7 @@ gdbreplay$(EXEEXT): $(GDBREPLAY_OBS)
${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbreplay$(EXEEXT) $(GDBREPLAY_OBS) \
$(XM_CLIBS)
-IPA_OBJS=ax-ipa.o tracepoint-ipa.o format-ipa.o utils-ipa.o regcache-ipa.o remote-utils-ipa.o common-utils-ipa.o ${IPA_DEPFILES}
+IPA_OBJS=ax-ipa.o tracepoint-ipa.o format-ipa.o utils-ipa.o regcache-ipa.o remote-utils-ipa.o common-utils-ipa.o tdesc-ipa.o ${IPA_DEPFILES}
IPA_LIB=libinproctrace.so
@@ -505,6 +505,9 @@ linux-amd64-ipa.o: linux-amd64-ipa.c
amd64-linux-ipa.o: amd64-linux.c
$(IPAGENT_COMPILE) $<
$(POSTCOMPILE)
+tdesc-ipa.o: tdesc.c
+ $(IPAGENT_COMPILE) $<
+ $(POSTCOMPILE)
ax.o: ax.c
$(COMPILE) $(WARN_CFLAGS_NO_FORMAT) $<
diff --git a/gdb/gdbserver/ax.c b/gdb/gdbserver/ax.c
index cd5cf2b..b6824a2 100644
--- a/gdb/gdbserver/ax.c
+++ b/gdb/gdbserver/ax.c
@@ -1162,7 +1162,7 @@ gdb_eval_agent_expr (struct eval_agent_expr_context *ctx,
int regnum = arg;
struct regcache *regcache = ctx->regcache;
- switch (register_size (regnum))
+ switch (register_size (regcache->tdesc, regnum))
{
case 8:
collect_register (regcache, regnum, cnv.u64.bytes);
diff --git a/gdb/gdbserver/i387-fp.c b/gdb/gdbserver/i387-fp.c
index d2543b2..2886519 100644
--- a/gdb/gdbserver/i387-fp.c
+++ b/gdb/gdbserver/i387-fp.c
@@ -20,8 +20,6 @@
#include "i387-fp.h"
#include "i386-xstate.h"
-int num_xmm_registers = 8;
-
/* Note: These functions preserve the reserved bits in control registers.
However, gdbserver promptly throws away that information. */
@@ -117,7 +115,7 @@ i387_cache_to_fsave (struct regcache *regcache, void *buf)
{
struct i387_fsave *fp = (struct i387_fsave *) buf;
int i;
- int st0_regnum = find_regno ("st0");
+ int st0_regnum = find_regno (regcache->tdesc, "st0");
unsigned long val, val2;
for (i = 0; i < 8; i++)
@@ -157,7 +155,7 @@ i387_fsave_to_cache (struct regcache *regcache, const void *buf)
{
struct i387_fsave *fp = (struct i387_fsave *) buf;
int i;
- int st0_regnum = find_regno ("st0");
+ int st0_regnum = find_regno (regcache->tdesc, "st0");
unsigned long val;
for (i = 0; i < 8; i++)
@@ -193,9 +191,11 @@ i387_cache_to_fxsave (struct regcache *regcache, void *buf)
{
struct i387_fxsave *fp = (struct i387_fxsave *) buf;
int i;
- int st0_regnum = find_regno ("st0");
- int xmm0_regnum = find_regno ("xmm0");
+ int st0_regnum = find_regno (regcache->tdesc, "st0");
+ int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
unsigned long val, val2;
+ /* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
+ int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
for (i = 0; i < 8; i++)
collect_register (regcache, i + st0_regnum,
@@ -249,6 +249,8 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
unsigned long long xstate_bv = 0;
char raw[16];
char *p;
+ /* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
+ int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
/* The supported bits in `xstat_bv' are 1 byte. Clear part in
vector registers if its bit in xstat_bv is zero. */
@@ -274,7 +276,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
/* Check if any x87 registers are changed. */
if ((x86_xcr0 & I386_XSTATE_X87))
{
- int st0_regnum = find_regno ("st0");
+ int st0_regnum = find_regno (regcache->tdesc, "st0");
for (i = 0; i < 8; i++)
{
@@ -291,7 +293,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
/* Check if any SSE registers are changed. */
if ((x86_xcr0 & I386_XSTATE_SSE))
{
- int xmm0_regnum = find_regno ("xmm0");
+ int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
for (i = 0; i < num_xmm_registers; i++)
{
@@ -308,7 +310,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
/* Check if any AVX registers are changed. */
if ((x86_xcr0 & I386_XSTATE_AVX))
{
- int ymm0h_regnum = find_regno ("ymm0h");
+ int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h");
for (i = 0; i < num_xmm_registers; i++)
{
@@ -413,9 +415,11 @@ i387_fxsave_to_cache (struct regcache *regcache, const void *buf)
{
struct i387_fxsave *fp = (struct i387_fxsave *) buf;
int i, top;
- int st0_regnum = find_regno ("st0");
- int xmm0_regnum = find_regno ("xmm0");
+ int st0_regnum = find_regno (regcache->tdesc, "st0");
+ int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
unsigned long val;
+ /* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
+ int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
for (i = 0; i < 8; i++)
supply_register (regcache, i + st0_regnum,
@@ -468,6 +472,8 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
unsigned long val;
unsigned int clear_bv;
gdb_byte *p;
+ /* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
+ int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
/* The supported bits in `xstat_bv' are 1 byte. Clear part in
vector registers if its bit in xstat_bv is zero. */
@@ -476,7 +482,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
/* Check if any x87 registers are changed. */
if ((x86_xcr0 & I386_XSTATE_X87) != 0)
{
- int st0_regnum = find_regno ("st0");
+ int st0_regnum = find_regno (regcache->tdesc, "st0");
if ((clear_bv & I386_XSTATE_X87) != 0)
{
@@ -493,7 +499,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
if ((x86_xcr0 & I386_XSTATE_SSE) != 0)
{
- int xmm0_regnum = find_regno ("xmm0");
+ int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
if ((clear_bv & I386_XSTATE_SSE))
{
@@ -510,7 +516,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
if ((x86_xcr0 & I386_XSTATE_AVX) != 0)
{
- int ymm0h_regnum = find_regno ("ymm0h");
+ int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h");
if ((clear_bv & I386_XSTATE_AVX) != 0)
{
diff --git a/gdb/gdbserver/i387-fp.h b/gdb/gdbserver/i387-fp.h
index efc70ed..9473cda 100644
--- a/gdb/gdbserver/i387-fp.h
+++ b/gdb/gdbserver/i387-fp.h
@@ -30,6 +30,4 @@ void i387_xsave_to_cache (struct regcache *regcache, const void *buf);
extern unsigned long long x86_xcr0;
-extern int num_xmm_registers;
-
#endif /* I387_FP_H */
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 6953d0e..39eb52e 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -102,7 +102,6 @@ add_thread (ptid_t thread_id, void *target_data)
current_inferior = new_thread;
new_thread->target_data = target_data;
- set_inferior_regcache_data (new_thread, new_register_cache ());
}
ptid_t
diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index cdf9cfd..e37f602 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -32,6 +32,7 @@
/* Defined in auto-generated files. */
void init_registers_aarch64 (void);
+extern const struct target_desc *tdesc_aarch64;
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
@@ -1188,7 +1189,7 @@ aarch64_arch_setup (void)
struct iovec iov;
struct user_hwdebug_state dreg_state;
- init_registers_aarch64 ();
+ current_process ()->tdesc = tdesc_aarch64;
pid = lwpid_of (get_thread_lwp (current_inferior));
iov.iov_base = &dreg_state;
@@ -1235,7 +1236,7 @@ aarch64_arch_setup (void)
}
}
-struct regset_info target_regsets[] =
+static struct regset_info aarch64_regsets[] =
{
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS,
sizeof (struct user_pt_regs), GENERAL_REGS,
@@ -1247,12 +1248,36 @@ struct regset_info target_regsets[] =
{ 0, 0, 0, -1, -1, NULL, NULL }
};
+static struct regsets_info aarch64_regsets_info =
+ {
+ aarch64_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct usrregs_info aarch64_usrregs_info =
+ {
+ AARCH64_NUM_REGS,
+ aarch64_regmap,
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &aarch64_usrregs_info,
+ &aarch64_regsets_info,
+ };
+
+static const struct regs_info *
+aarch64_regs_info (void)
+{
+ return &regs_info;
+}
+
struct linux_target_ops the_low_target =
{
aarch64_arch_setup,
- AARCH64_NUM_REGS,
- aarch64_regmap,
- NULL,
+ aarch64_regs_info,
aarch64_cannot_fetch_register,
aarch64_cannot_store_register,
NULL,
@@ -1274,3 +1299,11 @@ struct linux_target_ops the_low_target =
aarch64_linux_new_thread,
aarch64_linux_prepare_to_resume,
};
+
+void
+initialize_low_arch (void)
+{
+ init_registers_aarch64 ();
+
+ initialize_regsets_info (&aarch64_regsets_info);
+}
diff --git a/gdb/gdbserver/linux-amd64-ipa.c b/gdb/gdbserver/linux-amd64-ipa.c
index dc20a15..34daedf 100644
--- a/gdb/gdbserver/linux-amd64-ipa.c
+++ b/gdb/gdbserver/linux-amd64-ipa.c
@@ -22,6 +22,7 @@
/* Defined in auto-generated file amd64-linux.c. */
void init_registers_amd64_linux (void);
+extern const struct target_desc *tdesc_amd64_linux;
/* fast tracepoints collect registers. */
@@ -164,12 +165,9 @@ supply_static_tracepoint_registers (struct regcache *regcache,
#endif /* HAVE_UST */
-/* This is only needed because reg-i386-linux-lib.o references it. We
- may use it proper at some point. */
-const char *gdbserver_xmltarget;
-
void
initialize_low_tracepoint (void)
{
init_registers_amd64_linux ();
+ ipa_tdesc = tdesc_amd64_linux;
}
diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c
index 8ddd90a..a6b745d 100644
--- a/gdb/gdbserver/linux-arm-low.c
+++ b/gdb/gdbserver/linux-arm-low.c
@@ -29,10 +29,19 @@
/* Defined in auto-generated files. */
void init_registers_arm (void);
+extern const struct target_desc *tdesc_arm;
+
void init_registers_arm_with_iwmmxt (void);
+extern const struct target_desc *tdesc_arm_with_iwmmxt;
+
void init_registers_arm_with_vfpv2 (void);
+extern const struct target_desc *tdesc_arm_with_vfpv2;
+
void init_registers_arm_with_vfpv3 (void);
+extern const struct target_desc *tdesc_arm_with_vfpv3;
+
void init_registers_arm_with_neon (void);
+extern const struct target_desc *tdesc_arm_with_neon;
#ifndef PTRACE_GET_THREAD_AREA
#define PTRACE_GET_THREAD_AREA 22
@@ -212,7 +221,7 @@ arm_fill_vfpregset (struct regcache *regcache, void *buf)
else
num = 16;
- base = find_regno ("d0");
+ base = find_regno (regcache->tdesc, "d0");
for (i = 0; i < num; i++)
collect_register (regcache, base + i, (char *) buf + i * 8);
@@ -232,7 +241,7 @@ arm_store_vfpregset (struct regcache *regcache, const void *buf)
else
num = 16;
- base = find_regno ("d0");
+ base = find_regno (regcache->tdesc, "d0");
for (i = 0; i < num; i++)
supply_register (regcache, base + i, (char *) buf + i * 8);
@@ -768,8 +777,8 @@ arm_get_hwcap (unsigned long *valp)
return 0;
}
-static void
-arm_arch_setup (void)
+static const struct target_desc *
+arm_read_description (void)
{
int pid = lwpid_of (get_thread_lwp (current_inferior));
@@ -778,29 +787,24 @@ arm_arch_setup (void)
arm_hwcap = 0;
if (arm_get_hwcap (&arm_hwcap) == 0)
- {
- init_registers_arm ();
- return;
- }
+ return tdesc_arm;
if (arm_hwcap & HWCAP_IWMMXT)
- {
- init_registers_arm_with_iwmmxt ();
- return;
- }
+ return tdesc_arm_with_iwmmxt;
if (arm_hwcap & HWCAP_VFP)
{
+ const struct target_desc *result;
char *buf;
/* NEON implies either no VFP, or VFPv3-D32. We only support
it with VFP. */
if (arm_hwcap & HWCAP_NEON)
- init_registers_arm_with_neon ();
+ result = tdesc_arm_with_neon;
else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
- init_registers_arm_with_vfpv3 ();
+ result = tdesc_arm_with_vfpv3;
else
- init_registers_arm_with_vfpv2 ();
+ result = tdesc_arm_with_vfpv2;
/* Now make sure that the kernel supports reading these
registers. Support was added in 2.6.30. */
@@ -810,19 +814,25 @@ arm_arch_setup (void)
&& errno == EIO)
{
arm_hwcap = 0;
- init_registers_arm ();
+ result = tdesc_arm;
}
free (buf);
- return;
+ return result;
}
/* The default configuration uses legacy FPA registers, probably
simulated. */
- init_registers_arm ();
+ return tdesc_arm;
}
-struct regset_info target_regsets[] = {
+static void
+arm_arch_setup (void)
+{
+ current_process ()->tdesc = arm_read_description ();
+}
+
+static struct regset_info arm_regsets[] = {
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, 18 * 4,
GENERAL_REGS,
arm_fill_gregset, arm_store_gregset },
@@ -835,11 +845,35 @@ struct regset_info target_regsets[] = {
{ 0, 0, 0, -1, -1, NULL, NULL }
};
+static struct regsets_info arm_regsets_info =
+ {
+ arm_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct usrregs_info arm_usrregs_info =
+ {
+ arm_num_regs,
+ arm_regmap,
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &arm_usrregs_info,
+ &arm_regsets_info
+ };
+
+static const struct regs_info *
+arm_regs_info (void)
+{
+ return &regs_info;
+}
+
struct linux_target_ops the_low_target = {
arm_arch_setup,
- arm_num_regs,
- arm_regmap,
- NULL,
+ arm_regs_info,
arm_cannot_fetch_register,
arm_cannot_store_register,
NULL, /* fetch_register */
@@ -871,3 +905,16 @@ struct linux_target_ops the_low_target = {
arm_new_thread,
arm_prepare_to_resume,
};
+
+void
+initialize_low_arch (void)
+{
+ /* Initialize the Linux target descriptions. */
+ init_registers_arm ();
+ init_registers_arm_with_iwmmxt ();
+ init_registers_arm_with_vfpv2 ();
+ init_registers_arm_with_vfpv3 ();
+ init_registers_arm_with_neon ();
+
+ initialize_regsets_info (&arm_regsets_info);
+}
diff --git a/gdb/gdbserver/linux-bfin-low.c b/gdb/gdbserver/linux-bfin-low.c
index 3295ffd..cced3e1 100644
--- a/gdb/gdbserver/linux-bfin-low.c
+++ b/gdb/gdbserver/linux-bfin-low.c
@@ -26,6 +26,7 @@
/* Defined in auto-generated file reg-bfin.c. */
void init_registers_bfin (void);
+extern const struct target_desc *tdesc_bfin;
static int bfin_regmap[] =
{
@@ -90,11 +91,33 @@ bfin_breakpoint_at (CORE_ADDR where)
return 0;
}
+static void
+bfin_arch_setup (void)
+{
+ current_process ()->tdesc = tdesc_bfin;
+}
+
+static struct usrregs_info bfin_usrregs_info =
+ {
+ bfin_num_regs,
+ bfin_regmap,
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &bfin_usrregs_info,
+ };
+
+static const struct regs_info *
+bfin_regs_info (void)
+{
+ return &regs_info;
+}
+
struct linux_target_ops the_low_target = {
- init_registers_bfin,
- bfin_num_regs,
- bfin_regmap,
- NULL,
+ bfin_arch_setup,
+ bfin_regs_info,
bfin_cannot_fetch_register,
bfin_cannot_store_register,
NULL, /* fetch_register */
@@ -106,3 +129,10 @@ struct linux_target_ops the_low_target = {
2,
bfin_breakpoint_at,
};
+
+
+void
+initialize_low_arch (void)
+{
+ init_registers_bfin ();
+}
diff --git a/gdb/gdbserver/linux-cris-low.c b/gdb/gdbserver/linux-cris-low.c
index b9217de..b548117 100644
--- a/gdb/gdbserver/linux-cris-low.c
+++ b/gdb/gdbserver/linux-cris-low.c
@@ -22,6 +22,7 @@
/* Defined in auto-generated file reg-cris.c. */
void init_registers_cris (void);
+extern const struct target_desc *tdesc_cris;
/* CRISv10 */
#define cris_num_regs 32
@@ -107,11 +108,33 @@ cris_reinsert_addr (void)
return pc;
}
+static void
+cris_arch_setup (void)
+{
+ current_process ()->tdesc = tdesc_cris;
+}
+
+static struct usrregs_info cris_usrregs_info =
+ {
+ cris_num_regs,
+ cris_regmap,
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &cris_usrregs_info,
+ };
+
+static const struct regs_info *
+cris_regs_info (void)
+{
+ return &regs_info;
+}
+
struct linux_target_ops the_low_target = {
- init_registers_cris,
- cris_num_regs,
- cris_regmap,
- NULL,
+ cris_arch_setup,
+ cris_regs_info,
cris_cannot_fetch_register,
cris_cannot_store_register,
NULL, /* fetch_register */
@@ -127,3 +150,9 @@ struct linux_target_ops the_low_target = {
0,
0,
};
+
+void
+initialize_low_arch (void)
+{
+ init_registers_cris ();
+}
diff --git a/gdb/gdbserver/linux-crisv32-low.c b/gdb/gdbserver/linux-crisv32-low.c
index ca0e276..efe50a7 100644
--- a/gdb/gdbserver/linux-crisv32-low.c
+++ b/gdb/gdbserver/linux-crisv32-low.c
@@ -22,6 +22,7 @@
/* Defined in auto-generated file reg-crisv32.c. */
void init_registers_crisv32 (void);
+extern const struct target_desc *tdesc_crisv32;
/* CRISv32 */
#define cris_num_regs 49
@@ -362,17 +363,50 @@ cris_store_gregset (struct regcache *regcache, const void *buf)
}
}
-struct regset_info target_regsets[] = {
+static void
+cris_arch_setup (void)
+{
+ current_process ()->tdesc = tdesc_crisv32;
+}
+
+typedef unsigned long elf_gregset_t[cris_num_regs];
+
+static struct regset_info cris_regsets[] = {
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, cris_num_regs * 4,
GENERAL_REGS, cris_fill_gregset, cris_store_gregset },
{ 0, 0, 0, -1, -1, NULL, NULL }
};
+
+static struct regsets_info cris_regsets_info =
+ {
+ cris_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct usrregs_info cris_usrregs_info =
+ {
+ cris_num_regs,
+ cris_regmap,
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &cris_usrregs_info,
+ &cris_regsets_info
+ };
+
+static const struct regs_info *
+cris_regs_info (void)
+{
+ return &regs_info;
+}
+
struct linux_target_ops the_low_target = {
- init_registers_crisv32,
- -1,
- NULL,
- NULL,
+ cris_arch_setup,
+ cris_regs_info,
NULL,
NULL,
NULL, /* fetch_register */
@@ -388,3 +422,11 @@ struct linux_target_ops the_low_target = {
cris_stopped_by_watchpoint,
cris_stopped_data_address,
};
+
+void
+initialize_low_arch (void)
+{
+ init_register_crisv32 ();
+
+ initialize_regsets_info (&cris_regsets_info);
+}
diff --git a/gdb/gdbserver/linux-i386-ipa.c b/gdb/gdbserver/linux-i386-ipa.c
index 1c52284..e0245c5 100644
--- a/gdb/gdbserver/linux-i386-ipa.c
+++ b/gdb/gdbserver/linux-i386-ipa.c
@@ -49,6 +49,7 @@ enum i386_gdb_regnum
/* Defined in auto-generated file i386-linux.c. */
void init_registers_i386_linux (void);
+extern const struct target_desc *tdesc_i386_linux;
#define FT_CR_EAX 15
#define FT_CR_ECX 14
@@ -250,5 +251,6 @@ void
initialize_low_tracepoint (void)
{
init_registers_i386_linux ();
+ ipa_tdesc = tdesc_i386_linux;
initialize_fast_tracepoint_trampoline_buffer ();
}
diff --git a/gdb/gdbserver/linux-ia64-low.c b/gdb/gdbserver/linux-ia64-low.c
index deedb21..8cd2da4 100644
--- a/gdb/gdbserver/linux-ia64-low.c
+++ b/gdb/gdbserver/linux-ia64-low.c
@@ -25,6 +25,7 @@
/* Defined in auto-generated file reg-ia64.c. */
void init_registers_ia64 (void);
+extern const struct target_desc *tdesc_ia64;
#define ia64_num_regs 462
@@ -290,7 +291,7 @@ ia64_fetch_register (struct regcache *regcache, int regnum)
{
const gdb_byte zero[8] = { 0 };
- gdb_assert (sizeof (zero) == register_size (regnum));
+ gdb_assert (sizeof (zero) == register_size (regcache->tdesc, regnum));
supply_register (regcache, regnum, zero);
return 1;
}
@@ -300,7 +301,7 @@ ia64_fetch_register (struct regcache *regcache, int regnum)
{
const gdb_byte f_zero[16] = { 0 };
- gdb_assert (sizeof (f_zero) == register_size (regnum));
+ gdb_assert (sizeof (f_zero) == register_size (regcache->tdesc, regnum));
supply_register (regcache, regnum, f_zero);
return 1;
}
@@ -311,7 +312,7 @@ ia64_fetch_register (struct regcache *regcache, int regnum)
const gdb_byte f_one[16] =
{ 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0 };
- gdb_assert (sizeof (f_one) == register_size (regnum));
+ gdb_assert (sizeof (f_one) == register_size (regcache->tdesc, regnum));
supply_register (regcache, regnum, f_one);
return 1;
}
@@ -319,12 +320,41 @@ ia64_fetch_register (struct regcache *regcache, int regnum)
return 0;
}
+static struct usrregs_info ia64_usrregs_info =
+ {
+ ia64_num_regs,
+ ia64_regmap,
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &ia64_usrregs_info
+ };
+
+static const struct regs_info *
+ia64_regs_info (void)
+{
+ return &regs_info;
+}
+
+static void
+ia64_arch_setup (void)
+{
+ current_process ()->tdesc = tdesc_ia64;
+}
+
+
struct linux_target_ops the_low_target = {
- init_registers_ia64,
- ia64_num_regs,
- ia64_regmap,
- NULL,
+ ia64_arch_setup,
+ ia64_regs_info,
ia64_cannot_fetch_register,
ia64_cannot_store_register,
ia64_fetch_register,
};
+
+void
+initialize_low_arch (void)
+{
+ init_registers_ia64 ();
+}
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 03ac469..4247b11 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -224,15 +224,6 @@ int using_threads = 1;
jump pads). */
static int stabilizing_threads;
-/* This flag is true iff we've just created or attached to our first
- inferior but it has not stopped yet. As soon as it does, we need
- to call the low target's arch_setup callback. Doing this only on
- the first inferior avoids reinializing the architecture on every
- inferior, and avoids messing with the register caches of the
- already running inferiors. NOTE: this assumes all inferiors under
- control of gdbserver have the same architecture. */
-static int new_inferior;
-
static void linux_resume_one_lwp (struct lwp_info *lwp,
int step, int signal, siginfo_t *info);
static void linux_resume (struct thread_resume *resume_info, size_t n);
@@ -293,11 +284,6 @@ struct pending_signals
struct pending_signals *prev;
};
-#ifdef HAVE_LINUX_REGSETS
-static char *disabled_regsets;
-static int num_regsets;
-#endif
-
/* The read/write ends of the pipe registered as waitable file in the
event loop. */
static int linux_event_pipe[2] = { -1, -1 };
@@ -379,13 +365,12 @@ linux_add_process (int pid, int attached)
{
struct process_info *proc;
- /* Is this the first process? If so, then set the arch. */
- if (all_processes.head == NULL)
- new_inferior = 1;
-
proc = add_process (pid, attached);
proc->private = xcalloc (1, sizeof (*proc->private));
+ /* Set the arch when the first LWP stops. */
+ proc->private->new_inferior = 1;
+
if (the_low_target.new_process != NULL)
proc->private->arch_private = the_low_target.new_process ();
@@ -1203,8 +1188,7 @@ linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
}
/* Flush any pending changes to the process's registers. */
- regcache_invalidate_one ((struct inferior_list_entry *)
- get_lwp_thread (lwp));
+ regcache_invalidate_thread (get_lwp_thread (lwp));
/* Pass on any pending signal for this thread. */
sig = get_detach_signal (thread);
@@ -1412,17 +1396,28 @@ retry:
child->last_status = *wstatp;
- /* Architecture-specific setup after inferior is running.
- This needs to happen after we have attached to the inferior
- and it is stopped for the first time, but before we access
- any inferior registers. */
- if (new_inferior)
+ if (WIFSTOPPED (*wstatp))
{
- the_low_target.arch_setup ();
-#ifdef HAVE_LINUX_REGSETS
- memset (disabled_regsets, 0, num_regsets);
-#endif
- new_inferior = 0;
+ struct process_info *proc;
+
+ /* Architecture-specific setup after inferior is running. This
+ needs to happen after we have attached to the inferior and it
+ is stopped for the first time, but before we access any
+ inferior registers. */
+ proc = find_process_pid (pid_of (child));
+ if (proc->private->new_inferior)
+ {
+ struct thread_info *saved_inferior;
+
+ saved_inferior = current_inferior;
+ current_inferior = get_lwp_thread (child);
+
+ the_low_target.arch_setup ();
+
+ current_inferior = saved_inferior;
+
+ proc->private->new_inferior = 0;
+ }
}
/* Fetch the possibly triggered data watchpoint info and store it in
@@ -3348,8 +3343,7 @@ lwp %ld wants to get out of fast tracepoint jump pad single-stepping\n",
if (the_low_target.prepare_to_resume != NULL)
the_low_target.prepare_to_resume (lwp);
- regcache_invalidate_one ((struct inferior_list_entry *)
- get_lwp_thread (lwp));
+ regcache_invalidate_thread (get_lwp_thread (lwp));
errno = 0;
lwp->stopped = 0;
lwp->stopped_by_watchpoint = 0;
@@ -4058,14 +4052,15 @@ unstop_all_lwps (int unsuspend, struct lwp_info *except)
#define use_linux_regsets 1
static int
-regsets_fetch_inferior_registers (struct regcache *regcache)
+regsets_fetch_inferior_registers (struct regsets_info *regsets_info,
+ struct regcache *regcache)
{
struct regset_info *regset;
int saw_general_regs = 0;
int pid;
struct iovec iov;
- regset = target_regsets;
+ regset = regsets_info->regsets;
pid = lwpid_of (get_thread_lwp (current_inferior));
while (regset->size >= 0)
@@ -4073,7 +4068,8 @@ regsets_fetch_inferior_registers (struct regcache *regcache)
void *buf, *data;
int nt_type, res;
- if (regset->size == 0 || disabled_regsets[regset - target_regsets])
+ if (regset->size == 0
+ || regsets_info->disabled_regsets[regset - regsets_info->regsets])
{
regset ++;
continue;
@@ -4101,9 +4097,12 @@ regsets_fetch_inferior_registers (struct regcache *regcache)
{
if (errno == EIO)
{
+ int dr_offset;
+
/* If we get EIO on a regset, do not try it again for
- this process. */
- disabled_regsets[regset - target_regsets] = 1;
+ this process mode. */
+ dr_offset = regset - regsets_info->regsets;
+ regsets_info->disabled_regsets[dr_offset] = 1;
free (buf);
continue;
}
@@ -4128,14 +4127,15 @@ regsets_fetch_inferior_registers (struct regcache *regcache)
}
static int
-regsets_store_inferior_registers (struct regcache *regcache)
+regsets_store_inferior_registers (struct regsets_info *regsets_info,
+ struct regcache *regcache)
{
struct regset_info *regset;
int saw_general_regs = 0;
int pid;
struct iovec iov;
- regset = target_regsets;
+ regset = regsets_info->regsets;
pid = lwpid_of (get_thread_lwp (current_inferior));
while (regset->size >= 0)
@@ -4143,7 +4143,8 @@ regsets_store_inferior_registers (struct regcache *regcache)
void *buf, *data;
int nt_type, res;
- if (regset->size == 0 || disabled_regsets[regset - target_regsets])
+ if (regset->size == 0
+ || regsets_info->disabled_regsets[regset - regsets_info->regsets])
{
regset ++;
continue;
@@ -4190,9 +4191,12 @@ regsets_store_inferior_registers (struct regcache *regcache)
{
if (errno == EIO)
{
+ int dr_offset;
+
/* If we get EIO on a regset, do not try it again for
- this process. */
- disabled_regsets[regset - target_regsets] = 1;
+ this process mode. */
+ dr_offset = regset - regsets_info->regsets;
+ regsets_info->disabled_regsets[dr_offset] = 1;
free (buf);
continue;
}
@@ -4224,8 +4228,8 @@ regsets_store_inferior_registers (struct regcache *regcache)
#else /* !HAVE_LINUX_REGSETS */
#define use_linux_regsets 0
-#define regsets_fetch_inferior_registers(regcache) 1
-#define regsets_store_inferior_registers(regcache) 1
+#define regsets_fetch_inferior_registers(regsets_info, regcache) 1
+#define regsets_store_inferior_registers(regsets_info, regcache) 1
#endif
@@ -4233,50 +4237,52 @@ regsets_store_inferior_registers (struct regcache *regcache)
calls or 0 if it has to be transferred individually. */
static int
-linux_register_in_regsets (int regno)
+linux_register_in_regsets (const struct regs_info *regs_info, int regno)
{
unsigned char mask = 1 << (regno % 8);
size_t index = regno / 8;
return (use_linux_regsets
- && (the_low_target.regset_bitmap == NULL
- || (the_low_target.regset_bitmap[index] & mask) != 0));
+ && (regs_info->regset_bitmap == NULL
+ || (regs_info->regset_bitmap[index] & mask) != 0));
}
#ifdef HAVE_LINUX_USRREGS
int
-register_addr (int regnum)
+register_addr (const struct usrregs_info *usrregs, int regnum)
{
int addr;
- if (regnum < 0 || regnum >= the_low_target.num_regs)
+ if (regnum < 0 || regnum >= usrregs->num_regs)
error ("Invalid register number %d.", regnum);
- addr = the_low_target.regmap[regnum];
+ addr = usrregs->regmap[regnum];
return addr;
}
/* Fetch one register. */
static void
-fetch_register (struct regcache *regcache, int regno)
+fetch_register (const struct usrregs_info *usrregs,
+ struct regcache *regcache, int regno)
{
CORE_ADDR regaddr;
int i, size;
char *buf;
int pid;
- if (regno >= the_low_target.num_regs)
+ if (regno >= usrregs->num_regs)
return;
if ((*the_low_target.cannot_fetch_register) (regno))
return;
- regaddr = register_addr (regno);
+ regaddr = register_addr (usrregs, regno);
if (regaddr == -1)
return;
- size = ((register_size (regno) + sizeof (PTRACE_XFER_TYPE) - 1)
+ size = ((register_size (regcache->tdesc, regno)
+ + sizeof (PTRACE_XFER_TYPE) - 1)
& -sizeof (PTRACE_XFER_TYPE));
buf = alloca (size);
@@ -4302,23 +4308,25 @@ fetch_register (struct regcache *regcache, int regno)
/* Store one register. */
static void
-store_register (struct regcache *regcache, int regno)
+store_register (const struct usrregs_info *usrregs,
+ struct regcache *regcache, int regno)
{
CORE_ADDR regaddr;
int i, size;
char *buf;
int pid;
- if (regno >= the_low_target.num_regs)
+ if (regno >= usrregs->num_regs)
return;
if ((*the_low_target.cannot_store_register) (regno))
return;
- regaddr = register_addr (regno);
+ regaddr = register_addr (usrregs, regno);
if (regaddr == -1)
return;
- size = ((register_size (regno) + sizeof (PTRACE_XFER_TYPE) - 1)
+ size = ((register_size (regcache->tdesc, regno)
+ + sizeof (PTRACE_XFER_TYPE) - 1)
& -sizeof (PTRACE_XFER_TYPE));
buf = alloca (size);
memset (buf, 0, size);
@@ -4359,16 +4367,19 @@ store_register (struct regcache *regcache, int regno)
unless ALL is non-zero.
Otherwise, REGNO specifies which register (so we can save time). */
static void
-usr_fetch_inferior_registers (struct regcache *regcache, int regno, int all)
+usr_fetch_inferior_registers (const struct regs_info *regs_info,
+ struct regcache *regcache, int regno, int all)
{
+ struct usrregs_info *usr = regs_info->usrregs;
+
if (regno == -1)
{
- for (regno = 0; regno < the_low_target.num_regs; regno++)
- if (all || !linux_register_in_regsets (regno))
- fetch_register (regcache, regno);
+ for (regno = 0; regno < usr->num_regs; regno++)
+ if (all || !linux_register_in_regsets (regs_info, regno))
+ fetch_register (usr, regcache, regno);
}
else
- fetch_register (regcache, regno);
+ fetch_register (usr, regcache, regno);
}
/* Store our register values back into the inferior.
@@ -4377,22 +4388,25 @@ usr_fetch_inferior_registers (struct regcache *regcache, int regno, int all)
unless ALL is non-zero.
Otherwise, REGNO specifies which register (so we can save time). */
static void
-usr_store_inferior_registers (struct regcache *regcache, int regno, int all)
+usr_store_inferior_registers (const struct regs_info *regs_info,
+ struct regcache *regcache, int regno, int all)
{
+ struct usrregs_info *usr = regs_info->usrregs;
+
if (regno == -1)
{
- for (regno = 0; regno < the_low_target.num_regs; regno++)
- if (all || !linux_register_in_regsets (regno))
- store_register (regcache, regno);
+ for (regno = 0; regno < usr->num_regs; regno++)
+ if (all || !linux_register_in_regsets (regs_info, regno))
+ store_register (usr, regcache, regno);
}
else
- store_register (regcache, regno);
+ store_register (usr, regcache, regno);
}
#else /* !HAVE_LINUX_USRREGS */
-#define usr_fetch_inferior_registers(regcache, regno, all) do {} while (0)
-#define usr_store_inferior_registers(regcache, regno, all) do {} while (0)
+#define usr_fetch_inferior_registers(regs_info, regcache, regno, all) do {} while (0)
+#define usr_store_inferior_registers(regs_info, regcache, regno, all) do {} while (0)
#endif
@@ -4402,15 +4416,18 @@ linux_fetch_registers (struct regcache *regcache, int regno)
{
int use_regsets;
int all = 0;
+ const struct regs_info *regs_info = (*the_low_target.regs_info) ();
if (regno == -1)
{
- if (the_low_target.fetch_register != NULL)
- for (regno = 0; regno < the_low_target.num_regs; regno++)
+ if (the_low_target.fetch_register != NULL
+ && regs_info->usrregs != NULL)
+ for (regno = 0; regno < regs_info->usrregs->num_regs; regno++)
(*the_low_target.fetch_register) (regcache, regno);
- all = regsets_fetch_inferior_registers (regcache);
- usr_fetch_inferior_registers (regcache, -1, all);
+ all = regsets_fetch_inferior_registers (regs_info->regsets_info, regcache);
+ if (regs_info->usrregs != NULL)
+ usr_fetch_inferior_registers (regs_info, regcache, -1, all);
}
else
{
@@ -4418,11 +4435,12 @@ linux_fetch_registers (struct regcache *regcache, int regno)
&& (*the_low_target.fetch_register) (regcache, regno))
return;
- use_regsets = linux_register_in_regsets (regno);
+ use_regsets = linux_register_in_regsets (regs_info, regno);
if (use_regsets)
- all = regsets_fetch_inferior_registers (regcache);
- if (!use_regsets || all)
- usr_fetch_inferior_registers (regcache, regno, 1);
+ all = regsets_fetch_inferior_registers (regs_info->regsets_info,
+ regcache);
+ if ((!use_regsets || all) && regs_info->usrregs != NULL)
+ usr_fetch_inferior_registers (regs_info, regcache, regno, 1);
}
}
@@ -4431,19 +4449,23 @@ linux_store_registers (struct regcache *regcache, int regno)
{
int use_regsets;
int all = 0;
+ const struct regs_info *regs_info = (*the_low_target.regs_info) ();
if (regno == -1)
{
- all = regsets_store_inferior_registers (regcache);
- usr_store_inferior_registers (regcache, regno, all);
+ all = regsets_store_inferior_registers (regs_info->regsets_info,
+ regcache);
+ if (regs_info->usrregs != NULL)
+ usr_store_inferior_registers (regs_info, regcache, regno, all);
}
else
{
- use_regsets = linux_register_in_regsets (regno);
+ use_regsets = linux_register_in_regsets (regs_info, regno);
if (use_regsets)
- all = regsets_store_inferior_registers (regcache);
- if (!use_regsets || all)
- usr_store_inferior_registers (regcache, regno, 1);
+ all = regsets_store_inferior_registers (regs_info->regsets_info,
+ regcache);
+ if ((!use_regsets || all) && regs_info->usrregs != NULL)
+ usr_store_inferior_registers (regs_info, regcache, regno, 1);
}
}
@@ -5906,8 +5928,14 @@ linux_low_enable_btrace (ptid_t ptid)
struct btrace_target_info *tinfo;
tinfo = linux_enable_btrace (ptid);
+
if (tinfo != NULL)
- tinfo->ptr_bits = register_size (0) * 8;
+ {
+ struct thread_info *thread = find_thread_ptid (ptid);
+ struct regcache *regcache = get_thread_regcache (thread, 0);
+
+ tinfo->ptr_bits = register_size (regcache->tdesc, 0) * 8;
+ }
return tinfo;
}
@@ -6027,6 +6055,18 @@ linux_init_signals ()
#endif
}
+#ifdef HAVE_LINUX_REGSETS
+void
+initialize_regsets_info (struct regsets_info *info)
+{
+ for (info->num_regsets = 0;
+ info->regsets[info->num_regsets].size >= 0;
+ info->num_regsets++)
+ ;
+ info->disabled_regsets = xmalloc (info->num_regsets);
+}
+#endif
+
void
initialize_low (void)
{
@@ -6038,14 +6078,11 @@ initialize_low (void)
linux_init_signals ();
linux_test_for_tracefork ();
linux_ptrace_init_warnings ();
-#ifdef HAVE_LINUX_REGSETS
- for (num_regsets = 0; target_regsets[num_regsets].size >= 0; num_regsets++)
- ;
- disabled_regsets = xmalloc (num_regsets);
-#endif
sigchld_action.sa_handler = sigchld_handler;
sigemptyset (&sigchld_action.sa_mask);
sigchld_action.sa_flags = SA_RESTART;
sigaction (SIGCHLD, &sigchld_action, NULL);
+
+ initialize_low_arch ();
}
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
index 4dd3c9c..bce0288 100644
--- a/gdb/gdbserver/linux-low.h
+++ b/gdb/gdbserver/linux-low.h
@@ -46,8 +46,58 @@ struct regset_info
regset_fill_func fill_function;
regset_store_func store_function;
};
-extern struct regset_info target_regsets[];
+
+/* Aggregation of all the supported regsets of a given
+ architecture/mode. */
+
+struct regsets_info
+{
+ /* The regsets array. */
+ struct regset_info *regsets;
+
+ /* The number of regsets in the REGSETS array. */
+ int num_regsets;
+
+ /* If we get EIO on a regset, do not try it again. Note the set of
+ supported regsets may depend on processor mode on biarch
+ machines. */
+ char *disabled_regsets;
+};
+
+#endif
+
+/* Mapping between the general-purpose registers in `struct user'
+ format and GDB's register array layout. */
+
+struct usrregs_info
+{
+ /* The number of registers accessible. */
+ int num_regs;
+
+ /* The registers map. */
+ int *regmap;
+};
+
+/* All info needed to access an architecture/mode's registers. */
+
+struct regs_info
+{
+ /* Regset support bitmap: 1 for registers that are transferred as a part
+ of a regset, 0 for ones that need to be handled individually. This
+ can be NULL if all registers are transferred with regsets or regsets
+ are not supported. */
+ unsigned char *regset_bitmap;
+
+ /* Info used when accessing registers with PTRACE_PEEKUSER /
+ PTRACE_POKEUSER. This can be NULL if all registers are
+ transferred with regsets .*/
+ struct usrregs_info *usrregs;
+
+#ifdef HAVE_LINUX_REGSETS
+ /* Info used when accessing registers with regsets. */
+ struct regsets_info *regsets_info;
#endif
+};
struct process_info_private
{
@@ -60,6 +110,11 @@ struct process_info_private
/* &_r_debug. 0 if not yet determined. -1 if no PT_DYNAMIC in Phdrs. */
CORE_ADDR r_debug;
+
+ /* This flag is true iff we've just created or attached to the first
+ LWP of this process but it has not stopped yet. As soon as it
+ does, we need to call the low target's arch_setup callback. */
+ int new_inferior;
};
struct lwp_info;
@@ -69,14 +124,7 @@ struct linux_target_ops
/* Architecture-specific setup. */
void (*arch_setup) (void);
- int num_regs;
- int *regmap;
-
- /* Regset support bitmap: 1 for registers that are transferred as a part
- of a regset, 0 for ones that need to be handled individually. This
- can be NULL if all registers are transferred with regsets or regsets
- are not supported. */
- unsigned char *regset_bitmap;
+ const struct regs_info *(*regs_info) (void);
int (*cannot_fetch_register) (int);
/* Returns 0 if we can store the register, 1 if we can not
@@ -294,6 +342,12 @@ void linux_attach_lwp (unsigned long pid);
struct lwp_info *find_lwp_pid (ptid_t ptid);
void linux_stop_lwp (struct lwp_info *lwp);
+#ifdef HAVE_LINUX_REGSETS
+void initialize_regsets_info (struct regsets_info *regsets_info);
+#endif
+
+void initialize_low_arch (void);
+
/* From thread-db.c */
int thread_db_init (int use_events);
void thread_db_detach (struct process_info *);
diff --git a/gdb/gdbserver/linux-m32r-low.c b/gdb/gdbserver/linux-m32r-low.c
index 58ee646..f8ddd3c 100644
--- a/gdb/gdbserver/linux-m32r-low.c
+++ b/gdb/gdbserver/linux-m32r-low.c
@@ -25,6 +25,7 @@
/* Defined in auto-generated file reg-m32r.c. */
void init_registers_m32r (void);
+extern const struct target_desc *tdesc_m32r;
#define m32r_num_regs 25
@@ -87,11 +88,33 @@ m32r_breakpoint_at (CORE_ADDR where)
return 0;
}
+static void
+m32r_arch_setup (void)
+{
+ current_process ()->tdesc = tdesc_m32r;
+}
+
+static struct usrregs_info m32r_usrregs_info =
+ {
+ m32r_num_regs,
+ m32r_regmap,
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &m32r_usrregs_info,
+ };
+
+static const struct regs_info *
+m32r_regs_info (void)
+{
+ return &regs_info;
+}
+
struct linux_target_ops the_low_target = {
- init_registers_m32r,
- m32r_num_regs,
- m32r_regmap,
- NULL,
+ m32r_arch_setup,
+ m32r_regs_info,
m32r_cannot_fetch_register,
m32r_cannot_store_register,
NULL, /* fetch_register */
@@ -103,3 +126,9 @@ struct linux_target_ops the_low_target = {
0,
m32r_breakpoint_at,
};
+
+void
+initialize_low_arch (void)
+{
+ init_registers_m32r ();
+}
diff --git a/gdb/gdbserver/linux-m68k-low.c b/gdb/gdbserver/linux-m68k-low.c
index bc59e3e..9a73a62 100644
--- a/gdb/gdbserver/linux-m68k-low.c
+++ b/gdb/gdbserver/linux-m68k-low.c
@@ -21,6 +21,7 @@
/* Defined in auto-generated file reg-m68k.c. */
void init_registers_m68k (void);
+extern const struct target_desc *tdesc_m68k;
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
@@ -109,7 +110,7 @@ m68k_store_fpregset (struct regcache *regcache, const void *buf)
#endif /* HAVE_PTRACE_GETREGS */
-struct regset_info target_regsets[] = {
+static struct regset_info m68k_regsets[] = {
#ifdef HAVE_PTRACE_GETREGS
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
GENERAL_REGS,
@@ -174,11 +175,41 @@ ps_get_thread_area (const struct ps_prochandle *ph,
}
#endif /* PTRACE_GET_THREAD_AREA */
+static struct regsets_info m68k_regsets_info =
+ {
+ m68k_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct usrregs_info m68k_usrregs_info =
+ {
+ m68k_num_regs,
+ m68k_regmap,
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &m68k_usrregs_info,
+ &m68k_regsets_info
+ };
+
+static const struct regs_info *
+m68k_regs_info (void)
+{
+ return &regs_info;
+}
+
+static void
+m68k_arch_setup (void)
+{
+ current_process ()->tdesc = tdesc_m68k;
+}
+
struct linux_target_ops the_low_target = {
- init_registers_m68k,
- m68k_num_regs,
- m68k_regmap,
- NULL,
+ m68k_arch_setup,
+ m68k_regs_info,
m68k_cannot_fetch_register,
m68k_cannot_store_register,
NULL, /* fetch_register */
@@ -190,3 +221,12 @@ struct linux_target_ops the_low_target = {
2,
m68k_breakpoint_at,
};
+
+void
+initialize_low_arch (void)
+{
+ /* Initialize the Linux target descriptions. */
+ init_registers_m68k ();
+
+ initialize_regsets_info (&m68k_regsets_info);
+}
diff --git a/gdb/gdbserver/linux-mips-low.c b/gdb/gdbserver/linux-mips-low.c
index 0cf83be..1010528 100644
--- a/gdb/gdbserver/linux-mips-low.c
+++ b/gdb/gdbserver/linux-mips-low.c
@@ -26,16 +26,23 @@
/* Defined in auto-generated file mips-linux.c. */
void init_registers_mips_linux (void);
+extern const struct target_desc *tdesc_mips_linux;
+
/* Defined in auto-generated file mips-dsp-linux.c. */
void init_registers_mips_dsp_linux (void);
+extern const struct target_desc *tdesc_mips_dsp_linux;
+
/* Defined in auto-generated file mips64-linux.c. */
void init_registers_mips64_linux (void);
+extern const struct target_desc *tdesc_mips64_linux;
+
/* Defined in auto-generated file mips64-dsp-linux.c. */
void init_registers_mips64_dsp_linux (void);
+extern const struct target_desc *tdesc_mips64_dsp_linux;
#ifdef __mips64
-#define init_registers_mips_linux init_registers_mips64_linux
-#define init_registers_mips_dsp_linux init_registers_mips64_dsp_linux
+#define tdesc_mips_linux tdesc_mips64_linux
+#define tdesc_mips_dsp_linux tdesc_mips64_dsp_linux
#endif
#ifndef PTRACE_GET_THREAD_AREA
@@ -108,17 +115,15 @@ static unsigned char mips_dsp_regset_bitmap[(mips_dsp_num_regs + 7) / 8] = {
0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x80
};
+static int have_dsp = -1;
+
/* Try peeking at an arbitrarily chosen DSP register and pick the available
user register set accordingly. */
-static void
-mips_arch_setup (void)
+static const struct target_desc *
+mips_read_description (void)
{
- static void (*init_registers) (void);
-
- gdb_assert (current_inferior);
-
- if (init_registers == NULL)
+ if (have_dsp < 0)
{
int pid = lwpid_of (get_thread_lwp (current_inferior));
@@ -126,23 +131,32 @@ mips_arch_setup (void)
switch (errno)
{
case 0:
- the_low_target.num_regs = mips_dsp_num_regs;
- the_low_target.regmap = mips_dsp_regmap;
- the_low_target.regset_bitmap = mips_dsp_regset_bitmap;
- init_registers = init_registers_mips_dsp_linux;
+ have_dsp = 1;
break;
case EIO:
- the_low_target.num_regs = mips_num_regs;
- the_low_target.regmap = mips_regmap;
- the_low_target.regset_bitmap = NULL;
- init_registers = init_registers_mips_linux;
+ have_dsp = 0;
break;
default:
perror_with_name ("ptrace");
break;
}
}
- init_registers ();
+
+ return have_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux;
+}
+
+static void
+mips_arch_setup (void)
+{
+ current_process ()->tdesc = mips_read_description ();
+}
+
+static struct usrregs_info *
+get_usrregs_info (void)
+{
+ const struct regs_info *regs_info = the_low_target.regs_info ();
+
+ return regs_info->usrregs;
}
/* From mips-linux-nat.c. */
@@ -155,10 +169,14 @@ mips_arch_setup (void)
static int
mips_cannot_fetch_register (int regno)
{
- if (the_low_target.regmap[regno] == -1)
+ const struct target_desc *tdesc;
+
+ if (get_usrregs_info ()->regmap[regno] == -1)
return 1;
- if (find_regno ("r0") == regno)
+ tdesc = current_process ()->tdesc;
+
+ if (find_regno (tdesc, "r0") == regno)
return 1;
return 0;
@@ -167,19 +185,23 @@ mips_cannot_fetch_register (int regno)
static int
mips_cannot_store_register (int regno)
{
- if (the_low_target.regmap[regno] == -1)
+ const struct target_desc *tdesc;
+
+ if (get_usrregs_info ()->regmap[regno] == -1)
return 1;
- if (find_regno ("r0") == regno)
+ tdesc = current_process ()->tdesc;
+
+ if (find_regno (tdesc, "r0") == regno)
return 1;
- if (find_regno ("cause") == regno)
+ if (find_regno (tdesc, "cause") == regno)
return 1;
- if (find_regno ("badvaddr") == regno)
+ if (find_regno (tdesc, "badvaddr") == regno)
return 1;
- if (find_regno ("fir") == regno)
+ if (find_regno (tdesc, "fir") == regno)
return 1;
return 0;
@@ -190,14 +212,14 @@ mips_get_pc (struct regcache *regcache)
{
union mips_register pc;
collect_register_by_name (regcache, "pc", pc.buf);
- return register_size (0) == 4 ? pc.reg32 : pc.reg64;
+ return register_size (regcache->tdesc, 0) == 4 ? pc.reg32 : pc.reg64;
}
static void
mips_set_pc (struct regcache *regcache, CORE_ADDR pc)
{
union mips_register newpc;
- if (register_size (0) == 4)
+ if (register_size (regcache->tdesc, 0) == 4)
newpc.reg32 = pc;
else
newpc.reg64 = pc;
@@ -218,7 +240,7 @@ mips_reinsert_addr (void)
struct regcache *regcache = get_thread_regcache (current_inferior, 1);
union mips_register ra;
collect_register_by_name (regcache, "r31", ra.buf);
- return register_size (0) == 4 ? ra.reg32 : ra.reg64;
+ return register_size (regcache->tdesc, 0) == 4 ? ra.reg32 : ra.reg64;
}
static int
@@ -315,27 +337,28 @@ mips_fill_gregset (struct regcache *regcache, void *buf)
{
union mips_register *regset = buf;
int i, use_64bit;
+ const struct target_desc *tdesc = regcache->tdesc;
- use_64bit = (register_size (0) == 8);
+ use_64bit = (register_size (tdesc, 0) == 8);
for (i = 1; i < 32; i++)
mips_collect_register (regcache, use_64bit, i, regset + i);
mips_collect_register (regcache, use_64bit,
- find_regno ("lo"), regset + 32);
+ find_regno (tdesc, "lo"), regset + 32);
mips_collect_register (regcache, use_64bit,
- find_regno ("hi"), regset + 33);
+ find_regno (tdesc, "hi"), regset + 33);
mips_collect_register (regcache, use_64bit,
- find_regno ("pc"), regset + 34);
+ find_regno (tdesc, "pc"), regset + 34);
mips_collect_register (regcache, use_64bit,
- find_regno ("badvaddr"), regset + 35);
+ find_regno (tdesc, "badvaddr"), regset + 35);
mips_collect_register (regcache, use_64bit,
- find_regno ("status"), regset + 36);
+ find_regno (tdesc, "status"), regset + 36);
mips_collect_register (regcache, use_64bit,
- find_regno ("cause"), regset + 37);
+ find_regno (tdesc, "cause"), regset + 37);
mips_collect_register (regcache, use_64bit,
- find_regno ("restart"), regset + 0);
+ find_regno (tdesc, "restart"), regset + 0);
}
static void
@@ -344,23 +367,26 @@ mips_store_gregset (struct regcache *regcache, const void *buf)
const union mips_register *regset = buf;
int i, use_64bit;
- use_64bit = (register_size (0) == 8);
+ use_64bit = (register_size (regcache->tdesc, 0) == 8);
for (i = 0; i < 32; i++)
mips_supply_register (regcache, use_64bit, i, regset + i);
- mips_supply_register (regcache, use_64bit, find_regno ("lo"), regset + 32);
- mips_supply_register (regcache, use_64bit, find_regno ("hi"), regset + 33);
- mips_supply_register (regcache, use_64bit, find_regno ("pc"), regset + 34);
mips_supply_register (regcache, use_64bit,
- find_regno ("badvaddr"), regset + 35);
+ find_regno (regcache->tdesc, "lo"), regset + 32);
+ mips_supply_register (regcache, use_64bit,
+ find_regno (regcache->tdesc, "hi"), regset + 33);
mips_supply_register (regcache, use_64bit,
- find_regno ("status"), regset + 36);
+ find_regno (regcache->tdesc, "pc"), regset + 34);
mips_supply_register (regcache, use_64bit,
- find_regno ("cause"), regset + 37);
+ find_regno (regcache->tdesc, "badvaddr"), regset + 35);
+ mips_supply_register (regcache, use_64bit,
+ find_regno (regcache->tdesc, "status"), regset + 36);
+ mips_supply_register (regcache, use_64bit,
+ find_regno (regcache->tdesc, "cause"), regset + 37);
mips_supply_register (regcache, use_64bit,
- find_regno ("restart"), regset + 0);
+ find_regno (regcache->tdesc, "restart"), regset + 0);
}
static void
@@ -369,8 +395,8 @@ mips_fill_fpregset (struct regcache *regcache, void *buf)
union mips_register *regset = buf;
int i, use_64bit, first_fp, big_endian;
- use_64bit = (register_size (0) == 8);
- first_fp = find_regno ("f0");
+ use_64bit = (register_size (regcache->tdesc, 0) == 8);
+ first_fp = find_regno (regcache->tdesc, "f0");
big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
/* See GDB for a discussion of this peculiar layout. */
@@ -382,8 +408,9 @@ mips_fill_fpregset (struct regcache *regcache, void *buf)
regset[i & ~1].buf + 4 * (big_endian != (i & 1)));
mips_collect_register_32bit (regcache, use_64bit,
- find_regno ("fcsr"), regset[32].buf);
- mips_collect_register_32bit (regcache, use_64bit, find_regno ("fir"),
+ find_regno (regcache->tdesc, "fcsr"), regset[32].buf);
+ mips_collect_register_32bit (regcache, use_64bit,
+ find_regno (regcache->tdesc, "fir"),
regset[32].buf + 4);
}
@@ -393,8 +420,8 @@ mips_store_fpregset (struct regcache *regcache, const void *buf)
const union mips_register *regset = buf;
int i, use_64bit, first_fp, big_endian;
- use_64bit = (register_size (0) == 8);
- first_fp = find_regno ("f0");
+ use_64bit = (register_size (regcache->tdesc, 0) == 8);
+ first_fp = find_regno (regcache->tdesc, "f0");
big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
/* See GDB for a discussion of this peculiar layout. */
@@ -406,13 +433,15 @@ mips_store_fpregset (struct regcache *regcache, const void *buf)
regset[i & ~1].buf + 4 * (big_endian != (i & 1)));
mips_supply_register_32bit (regcache, use_64bit,
- find_regno ("fcsr"), regset[32].buf);
- mips_supply_register_32bit (regcache, use_64bit, find_regno ("fir"),
+ find_regno (regcache->tdesc, "fcsr"),
+ regset[32].buf);
+ mips_supply_register_32bit (regcache, use_64bit,
+ find_regno (regcache->tdesc, "fir"),
regset[32].buf + 4);
}
#endif /* HAVE_PTRACE_GETREGS */
-struct regset_info target_regsets[] = {
+static struct regset_info mips_regsets[] = {
#ifdef HAVE_PTRACE_GETREGS
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, 38 * 8, GENERAL_REGS,
mips_fill_gregset, mips_store_gregset },
@@ -422,11 +451,51 @@ struct regset_info target_regsets[] = {
{ 0, 0, 0, -1, -1, NULL, NULL }
};
+static struct regsets_info mips_regsets_info =
+ {
+ mips_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct usrregs_info mips_dsp_usrregs_info =
+ {
+ mips_dsp_num_regs,
+ mips_dsp_regmap,
+ };
+
+static struct usrregs_info mips_usrregs_info =
+ {
+ mips_num_regs,
+ mips_regmap,
+ };
+
+static struct regs_info dsp_regs_info =
+ {
+ mips_dsp_regset_bitmap,
+ &mips_dsp_usrregs_info,
+ &mips_regsets_info
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &mips_usrregs_info,
+ &mips_regsets_info
+ };
+
+static const struct regs_info *
+mips_regs_info (void)
+{
+ if (have_dsp)
+ return &dsp_regs_info;
+ else
+ return &regs_info;
+}
+
struct linux_target_ops the_low_target = {
mips_arch_setup,
- -1,
- NULL,
- NULL,
+ mips_regs_info,
mips_cannot_fetch_register,
mips_cannot_store_register,
NULL, /* fetch_register */
@@ -438,3 +507,15 @@ struct linux_target_ops the_low_target = {
0,
mips_breakpoint_at,
};
+
+void
+initialize_low_arch (void)
+{
+ /* Initialize the Linux target descriptions. */
+ init_registers_mips_linux ();
+ init_registers_mips_dsp_linux ();
+ init_registers_mips64_linux ();
+ init_registers_mips64_dsp_linux ();
+
+ initialize_regsets_info (&mips_regsets_info);
+}
diff --git a/gdb/gdbserver/linux-nios2-low.c b/gdb/gdbserver/linux-nios2-low.c
index c41579f..8d97864 100644
--- a/gdb/gdbserver/linux-nios2-low.c
+++ b/gdb/gdbserver/linux-nios2-low.c
@@ -40,6 +40,7 @@
/* Defined in auto-generated file nios2-linux.c. */
void init_registers_nios2_linux (void);
+extern const struct target_desc *tdesc_nios2_linux;
/* This union is used to convert between int and byte buffer
representations of register contents. */
@@ -68,7 +69,7 @@ static int nios2_regmap[] = {
static void
nios2_arch_setup (void)
{
- init_registers_nios2_linux ();
+ current_process ()->tdesc = tdesc_nios2_linux;
}
/* Implement the cannot_fetch_register linux_target_ops method. */
@@ -206,7 +207,7 @@ nios2_store_gregset (struct regcache *regcache, const void *buf)
}
#endif /* HAVE_PTRACE_GETREGS */
-struct regset_info target_regsets[] =
+static struct regset_info nios2_regsets[] =
{
#ifdef HAVE_PTRACE_GETREGS
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, nios2_num_regs * 4, GENERAL_REGS,
@@ -215,12 +216,36 @@ struct regset_info target_regsets[] =
{ 0, 0, 0, -1, -1, NULL, NULL }
};
+static struct regsets_info nios2_regsets_info =
+ {
+ nios2_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct usrregs_info nios2_usrregs_info =
+ {
+ nios2_num_regs,
+ nios2_regmap,
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &nios2_usrregs_info,
+ &nios2_regsets_info
+ };
+
+static const struct regs_info *
+nios2_regs_info (void)
+{
+ return &regs_info;
+}
+
struct linux_target_ops the_low_target =
{
nios2_arch_setup,
- nios2_num_regs,
- nios2_regmap,
- NULL,
+ nios2_regs_info,
nios2_cannot_fetch_register,
nios2_cannot_store_register,
NULL,
@@ -232,3 +257,11 @@ struct linux_target_ops the_low_target =
0,
nios2_breakpoint_at,
};
+
+void
+initialize_low_arch (void)
+{
+ init_registers_nios2_linux ();
+
+ initialize_regsets_info (&nios2_regsets_info);
+}
diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index 1c81c79..aed1749 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -35,34 +35,63 @@ static unsigned long ppc_hwcap;
/* Defined in auto-generated file powerpc-32l.c. */
void init_registers_powerpc_32l (void);
+extern const struct target_desc *tdesc_powerpc_32l;
+
/* Defined in auto-generated file powerpc-altivec32l.c. */
void init_registers_powerpc_altivec32l (void);
+extern const struct target_desc *tdesc_powerpc_altivec32l;
+
/* Defined in auto-generated file powerpc-cell32l.c. */
void init_registers_powerpc_cell32l (void);
+extern const struct target_desc *tdesc_powerpc_cell32l;
+
/* Defined in auto-generated file powerpc-vsx32l.c. */
void init_registers_powerpc_vsx32l (void);
+extern const struct target_desc *tdesc_powerpc_vsx32l;
+
/* Defined in auto-generated file powerpc-isa205-32l.c. */
void init_registers_powerpc_isa205_32l (void);
+extern const struct target_desc *tdesc_powerpc_isa205_32l;
+
/* Defined in auto-generated file powerpc-isa205-altivec32l.c. */
void init_registers_powerpc_isa205_altivec32l (void);
+extern const struct target_desc *tdesc_powerpc_isa205_altivec32l;
+
/* Defined in auto-generated file powerpc-isa205-vsx32l.c. */
void init_registers_powerpc_isa205_vsx32l (void);
+extern const struct target_desc *tdesc_powerpc_isa205_vsx32l;
+
/* Defined in auto-generated file powerpc-e500l.c. */
void init_registers_powerpc_e500l (void);
+extern const struct target_desc *tdesc_powerpc_e500l;
+
/* Defined in auto-generated file powerpc-64l.c. */
void init_registers_powerpc_64l (void);
+extern const struct target_desc *tdesc_powerpc_64l;
+
/* Defined in auto-generated file powerpc-altivec64l.c. */
void init_registers_powerpc_altivec64l (void);
+extern const struct target_desc *tdesc_powerpc_altivec64l;
+
/* Defined in auto-generated file powerpc-cell64l.c. */
void init_registers_powerpc_cell64l (void);
+extern const struct target_desc *tdesc_powerpc_cell64l;
+
/* Defined in auto-generated file powerpc-vsx64l.c. */
void init_registers_powerpc_vsx64l (void);
+extern const struct target_desc *tdesc_powerpc_vsx64l;
+
/* Defined in auto-generated file powerpc-isa205-64l.c. */
void init_registers_powerpc_isa205_64l (void);
+extern const struct target_desc *tdesc_powerpc_isa205_64l;
+
/* Defined in auto-generated file powerpc-isa205-altivec64l.c. */
void init_registers_powerpc_isa205_altivec64l (void);
+extern const struct target_desc *tdesc_powerpc_isa205_altivec64l;
+
/* Defined in auto-generated file powerpc-isa205-vsx64l.c. */
void init_registers_powerpc_isa205_vsx64l (void);
+extern const struct target_desc *tdesc_powerpc_isa205_vsx64l;
#define ppc_num_regs 73
@@ -147,15 +176,18 @@ static int ppc_regmap_e500[] =
static int
ppc_cannot_store_register (int regno)
{
+ const struct target_desc *tdesc = current_process ()->tdesc;
+
#ifndef __powerpc64__
/* Some kernels do not allow us to store fpscr. */
- if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE) && regno == find_regno ("fpscr"))
+ if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE)
+ && regno == find_regno (tdesc, "fpscr"))
return 2;
#endif
/* Some kernels do not allow us to store orig_r3 or trap. */
- if (regno == find_regno ("orig_r3")
- || regno == find_regno ("trap"))
+ if (regno == find_regno (tdesc, "orig_r3")
+ || regno == find_regno (tdesc, "trap"))
return 2;
return 0;
@@ -170,7 +202,7 @@ ppc_cannot_fetch_register (int regno)
static void
ppc_collect_ptrace_register (struct regcache *regcache, int regno, char *buf)
{
- int size = register_size (regno);
+ int size = register_size (regcache->tdesc, regno);
memset (buf, 0, sizeof (long));
@@ -184,7 +216,7 @@ static void
ppc_supply_ptrace_register (struct regcache *regcache,
int regno, const char *buf)
{
- int size = register_size (regno);
+ int size = register_size (regcache->tdesc, regno);
if (size < sizeof (long))
supply_register (regcache, regno, buf + sizeof (long) - size);
else
@@ -205,7 +237,7 @@ parse_spufs_run (struct regcache *regcache, int *fd, CORE_ADDR *addr)
int curr_insn;
int curr_r0;
- if (register_size (0) == 4)
+ if (register_size (regcache->tdesc, 0) == 4)
{
unsigned int pc, r0, r3, r4;
collect_register_by_name (regcache, "pc", &pc);
@@ -257,7 +289,7 @@ ppc_get_pc (struct regcache *regcache)
return ((CORE_ADDR)1 << 63)
| ((CORE_ADDR)fd << 32) | (CORE_ADDR) (pc - 4);
}
- else if (register_size (0) == 4)
+ else if (register_size (regcache->tdesc, 0) == 4)
{
unsigned int pc;
collect_register_by_name (regcache, "pc", &pc);
@@ -282,7 +314,7 @@ ppc_set_pc (struct regcache *regcache, CORE_ADDR pc)
unsigned int newpc = pc;
(*the_target->write_memory) (addr, (unsigned char *) &newpc, 4);
}
- else if (register_size (0) == 4)
+ else if (register_size (regcache->tdesc, 0) == 4)
{
unsigned int newpc = pc;
supply_register_by_name (regcache, "pc", &newpc);
@@ -298,7 +330,8 @@ ppc_set_pc (struct regcache *regcache, CORE_ADDR pc)
static int
ppc_get_hwcap (unsigned long *valp)
{
- int wordsize = register_size (0);
+ const struct target_desc *tdesc = current_process ()->tdesc;
+ int wordsize = register_size (tdesc, 0);
unsigned char *data = alloca (2 * wordsize);
int offset = 0;
@@ -330,9 +363,16 @@ ppc_get_hwcap (unsigned long *valp)
return 0;
}
+/* Forward declaration. */
+static struct usrregs_info ppc_usrregs_info;
+#ifndef __powerpc64__
+static int ppc_regmap_adjusted;
+#endif
+
static void
ppc_arch_setup (void)
{
+ const struct target_desc *tdesc;
#ifdef __powerpc64__
long msr;
struct regcache *regcache;
@@ -340,20 +380,21 @@ ppc_arch_setup (void)
/* On a 64-bit host, assume 64-bit inferior process with no
AltiVec registers. Reset ppc_hwcap to ensure that the
collect_register call below does not fail. */
- init_registers_powerpc_64l ();
+ tdesc = tdesc_powerpc_64l;
+ current_process ()->tdesc = tdesc;
ppc_hwcap = 0;
/* Only if the high bit of the MSR is set, we actually have
a 64-bit inferior. */
- regcache = new_register_cache ();
- fetch_inferior_registers (regcache, find_regno ("msr"));
+ regcache = new_register_cache (tdesc);
+ fetch_inferior_registers (regcache, find_regno (tdesc, "msr"));
collect_register_by_name (regcache, "msr", &msr);
free_register_cache (regcache);
if (msr < 0)
{
ppc_get_hwcap (&ppc_hwcap);
if (ppc_hwcap & PPC_FEATURE_CELL)
- init_registers_powerpc_cell64l ();
+ tdesc = tdesc_powerpc_cell64l;
else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
{
/* Power ISA 2.05 (implemented by Power 6 and newer processors)
@@ -364,59 +405,67 @@ ppc_arch_setup (void)
Point, we check if that feature is available to decide the size
of the FPSCR. */
if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
- init_registers_powerpc_isa205_vsx64l ();
+ tdesc = tdesc_powerpc_isa205_vsx64l;
else
- init_registers_powerpc_vsx64l ();
+ tdesc = tdesc_powerpc_vsx64l;
}
else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
{
if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
- init_registers_powerpc_isa205_altivec64l ();
+ tdesc = tdesc_powerpc_isa205_altivec64l;
else
- init_registers_powerpc_altivec64l ();
+ tdesc = tdesc_powerpc_altivec64l;
}
+ current_process ()->tdesc = tdesc;
return;
}
#endif
/* OK, we have a 32-bit inferior. */
- init_registers_powerpc_32l ();
+ tdesc = tdesc_powerpc_32l;
+ current_process ()->tdesc = tdesc;
ppc_get_hwcap (&ppc_hwcap);
if (ppc_hwcap & PPC_FEATURE_CELL)
- init_registers_powerpc_cell32l ();
+ tdesc = tdesc_powerpc_cell32l;
else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
{
if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
- init_registers_powerpc_isa205_vsx32l ();
+ tdesc = tdesc_powerpc_isa205_vsx32l;
else
- init_registers_powerpc_vsx32l ();
+ tdesc = tdesc_powerpc_vsx32l;
}
else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
{
if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
- init_registers_powerpc_isa205_altivec32l ();
+ tdesc = tdesc_powerpc_isa205_altivec32l;
else
- init_registers_powerpc_altivec32l ();
+ tdesc = tdesc_powerpc_altivec32l;
}
/* On 32-bit machines, check for SPE registers.
Set the low target's regmap field as appropriately. */
#ifndef __powerpc64__
- the_low_target.regmap = ppc_regmap;
if (ppc_hwcap & PPC_FEATURE_HAS_SPE)
+ tdesc = tdesc_powerpc_e500l;
+
+ if (!ppc_regmap_adjusted)
{
- init_registers_powerpc_e500l ();
- the_low_target.regmap = ppc_regmap_e500;
- }
+ if (ppc_hwcap & PPC_FEATURE_HAS_SPE)
+ ppc_usrregs_info.regmap = ppc_regmap_e500;
- /* If the FPSCR is 64-bit wide, we need to fetch the whole 64-bit
- slot and not just its second word. The PT_FPSCR supplied in a
- 32-bit GDB compilation doesn't reflect this. */
- if (register_size (70) == 8)
- ppc_regmap[70] = (48 + 2*32) * sizeof (long);
+ /* If the FPSCR is 64-bit wide, we need to fetch the whole
+ 64-bit slot and not just its second word. The PT_FPSCR
+ supplied in a 32-bit GDB compilation doesn't reflect
+ this. */
+ if (register_size (tdesc, 70) == 8)
+ ppc_regmap[70] = (48 + 2*32) * sizeof (long);
+
+ ppc_regmap_adjusted = 1;
+ }
#endif
+ current_process ()->tdesc = tdesc;
}
/* Correct in either endianness.
@@ -484,7 +533,7 @@ ppc_fill_vsxregset (struct regcache *regcache, void *buf)
if (!(ppc_hwcap & PPC_FEATURE_HAS_VSX))
return;
- base = find_regno ("vs0h");
+ base = find_regno (regcache->tdesc, "vs0h");
for (i = 0; i < 32; i++)
collect_register (regcache, base + i, &regset[i * 8]);
}
@@ -498,7 +547,7 @@ ppc_store_vsxregset (struct regcache *regcache, const void *buf)
if (!(ppc_hwcap & PPC_FEATURE_HAS_VSX))
return;
- base = find_regno ("vs0h");
+ base = find_regno (regcache->tdesc, "vs0h");
for (i = 0; i < 32; i++)
supply_register (regcache, base + i, &regset[i * 8]);
}
@@ -519,7 +568,7 @@ ppc_fill_vrregset (struct regcache *regcache, void *buf)
if (!(ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC))
return;
- base = find_regno ("vr0");
+ base = find_regno (regcache->tdesc, "vr0");
for (i = 0; i < 32; i++)
collect_register (regcache, base + i, &regset[i * 16]);
@@ -536,7 +585,7 @@ ppc_store_vrregset (struct regcache *regcache, const void *buf)
if (!(ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC))
return;
- base = find_regno ("vr0");
+ base = find_regno (regcache->tdesc, "vr0");
for (i = 0; i < 32; i++)
supply_register (regcache, base + i, &regset[i * 16]);
@@ -565,7 +614,7 @@ ppc_fill_evrregset (struct regcache *regcache, void *buf)
if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE))
return;
- ev0 = find_regno ("ev0h");
+ ev0 = find_regno (regcache->tdesc, "ev0h");
for (i = 0; i < 32; i++)
collect_register (regcache, ev0 + i, &regset->evr[i]);
@@ -582,7 +631,7 @@ ppc_store_evrregset (struct regcache *regcache, const void *buf)
if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE))
return;
- ev0 = find_regno ("ev0h");
+ ev0 = find_regno (regcache->tdesc, "ev0h");
for (i = 0; i < 32; i++)
supply_register (regcache, ev0 + i, &regset->evr[i]);
@@ -590,7 +639,7 @@ ppc_store_evrregset (struct regcache *regcache, const void *buf)
supply_register_by_name (regcache, "spefscr", &regset->spefscr);
}
-struct regset_info target_regsets[] = {
+static struct regset_info ppc_regsets[] = {
/* List the extra register sets before GENERAL_REGS. That way we will
fetch them every time, but still fall back to PTRACE_PEEKUSER for the
general registers. Some kernels support these, but not the newer
@@ -605,11 +654,35 @@ struct regset_info target_regsets[] = {
{ 0, 0, 0, -1, -1, NULL, NULL }
};
+static struct usrregs_info ppc_usrregs_info =
+ {
+ ppc_num_regs,
+ ppc_regmap,
+ };
+
+static struct regsets_info ppc_regsets_info =
+ {
+ ppc_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &ppc_usrregs_info,
+ &ppc_regsets_info
+ };
+
+static const struct regs_info *
+ppc_regs_info (void)
+{
+ return &regs_info;
+}
+
struct linux_target_ops the_low_target = {
ppc_arch_setup,
- ppc_num_regs,
- ppc_regmap,
- NULL,
+ ppc_regs_info,
ppc_cannot_fetch_register,
ppc_cannot_store_register,
NULL, /* fetch_register */
@@ -627,3 +700,27 @@ struct linux_target_ops the_low_target = {
ppc_collect_ptrace_register,
ppc_supply_ptrace_register,
};
+
+void
+initialize_low_arch (void)
+{
+ /* Initialize the Linux target descriptions. */
+
+ init_registers_powerpc_32l ();
+ init_registers_powerpc_altivec32l ();
+ init_registers_powerpc_cell32l ();
+ init_registers_powerpc_vsx32l ();
+ init_registers_powerpc_isa205_32l ();
+ init_registers_powerpc_isa205_altivec32l ();
+ init_registers_powerpc_isa205_vsx32l ();
+ init_registers_powerpc_e500l ();
+ init_registers_powerpc_64l ();
+ init_registers_powerpc_altivec64l ();
+ init_registers_powerpc_cell64l ();
+ init_registers_powerpc_vsx64l ();
+ init_registers_powerpc_isa205_64l ();
+ init_registers_powerpc_isa205_altivec64l ();
+ init_registers_powerpc_isa205_vsx64l ();
+
+ initialize_regsets_info (&ppc_regsets_info);
+}
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 5d9fb80..18d6370 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -42,22 +42,39 @@
/* Defined in auto-generated file s390-linux32.c. */
void init_registers_s390_linux32 (void);
+extern const struct target_desc *tdesc_s390_linux32;
+
/* Defined in auto-generated file s390-linux32v1.c. */
void init_registers_s390_linux32v1 (void);
+extern const struct target_desc *tdesc_s390_linux32v1;
+
/* Defined in auto-generated file s390-linux32v2.c. */
void init_registers_s390_linux32v2 (void);
+extern const struct target_desc *tdesc_s390_linux32v2;
+
/* Defined in auto-generated file s390-linux64.c. */
void init_registers_s390_linux64 (void);
+extern const struct target_desc *tdesc_s390_linux64;
+
/* Defined in auto-generated file s390-linux64v1.c. */
void init_registers_s390_linux64v1 (void);
+extern const struct target_desc *tdesc_s390_linux64v1;
+
/* Defined in auto-generated file s390-linux64v2.c. */
void init_registers_s390_linux64v2 (void);
+extern const struct target_desc *tdesc_s390_linux64v2;
+
/* Defined in auto-generated file s390x-linux64.c. */
void init_registers_s390x_linux64 (void);
+extern const struct target_desc *tdesc_s390x_linux64;
+
/* Defined in auto-generated file s390x-linux64v1.c. */
void init_registers_s390x_linux64v1 (void);
+extern const struct target_desc *tdesc_s390x_linux64v1;
+
/* Defined in auto-generated file s390x-linux64v2.c. */
void init_registers_s390x_linux64v2 (void);
+extern const struct target_desc *tdesc_s390x_linux64v2;
#define s390_num_regs 52
@@ -138,15 +155,17 @@ s390_cannot_store_register (int regno)
static void
s390_collect_ptrace_register (struct regcache *regcache, int regno, char *buf)
{
- int size = register_size (regno);
+ int size = register_size (regcache->tdesc, regno);
if (size < sizeof (long))
{
- int regaddr = the_low_target.regmap[regno];
+ const struct regs_info *regs_info = (*the_low_target.regs_info) ();
+ struct usrregs_info *usr = regs_info->usrregs;
+ int regaddr = usr->regmap[regno];
memset (buf, 0, sizeof (long));
- if ((regno ^ 1) < the_low_target.num_regs
- && the_low_target.regmap[regno ^ 1] == regaddr)
+ if ((regno ^ 1) < usr->num_regs
+ && usr->regmap[regno ^ 1] == regaddr)
{
collect_register (regcache, regno & ~1, buf);
collect_register (regcache, (regno & ~1) + 1,
@@ -156,7 +175,7 @@ s390_collect_ptrace_register (struct regcache *regcache, int regno, char *buf)
{
/* Convert 4-byte PSW mask to 8 bytes by clearing bit 12 and copying
the basic addressing mode bit from the PSW address. */
- char *addr = alloca (register_size (regno ^ 1));
+ char *addr = alloca (register_size (regcache->tdesc, regno ^ 1));
collect_register (regcache, regno, buf);
collect_register (regcache, regno ^ 1, addr);
buf[1] &= ~0x8;
@@ -183,13 +202,15 @@ static void
s390_supply_ptrace_register (struct regcache *regcache,
int regno, const char *buf)
{
- int size = register_size (regno);
+ int size = register_size (regcache->tdesc, regno);
if (size < sizeof (long))
{
- int regaddr = the_low_target.regmap[regno];
+ const struct regs_info *regs_info = (*the_low_target.regs_info) ();
+ struct usrregs_info *usr = regs_info->usrregs;
+ int regaddr = usr->regmap[regno];
- if ((regno ^ 1) < the_low_target.num_regs
- && the_low_target.regmap[regno ^ 1] == regaddr)
+ if ((regno ^ 1) < usr->num_regs
+ && usr->regmap[regno ^ 1] == regaddr)
{
supply_register (regcache, regno & ~1, buf);
supply_register (regcache, (regno & ~1) + 1,
@@ -200,7 +221,7 @@ s390_supply_ptrace_register (struct regcache *regcache,
/* Convert 8-byte PSW mask to 4 bytes by setting bit 12 and copying
the basic addressing mode into the PSW address. */
char *mask = alloca (size);
- char *addr = alloca (register_size (regno ^ 1));
+ char *addr = alloca (register_size (regcache->tdesc, regno ^ 1));
memcpy (mask, buf, size);
mask[1] |= 0x8;
supply_register (regcache, regno, mask);
@@ -236,18 +257,21 @@ s390_supply_ptrace_register (struct regcache *regcache,
/* Provide only a fill function for the general register set. ps_lgetregs
will use this for NPTL support. */
-static void s390_fill_gregset (struct regcache *regcache, void *buf)
+static void
+s390_fill_gregset (struct regcache *regcache, void *buf)
{
int i;
+ const struct regs_info *regs_info = (*the_low_target.regs_info) ();
+ struct usrregs_info *usr = regs_info->usrregs;
- for (i = 0; i < the_low_target.num_regs; i++)
+ for (i = 0; i < usr->num_regs; i++)
{
- if (the_low_target.regmap[i] < PT_PSWMASK
- || the_low_target.regmap[i] > PT_ACR15)
+ if (usr->regmap[i] < PT_PSWMASK
+ || usr->regmap[i] > PT_ACR15)
continue;
- s390_collect_ptrace_register (regcache, i, (char *) buf
- + the_low_target.regmap[i]);
+ s390_collect_ptrace_register (regcache, i,
+ (char *) buf + usr->regmap[i]);
}
}
@@ -262,8 +286,10 @@ s390_fill_last_break (struct regcache *regcache, void *buf)
static void
s390_store_last_break (struct regcache *regcache, const void *buf)
{
- supply_register_by_name (regcache, "last_break",
- (const char *)buf + 8 - register_size (0));
+ const char *p;
+
+ p = (const char *) buf + 8 - register_size (regcache->tdesc, 0);
+ supply_register_by_name (regcache, "last_break", p);
}
static void
@@ -278,7 +304,7 @@ s390_store_system_call (struct regcache *regcache, const void *buf)
supply_register_by_name (regcache, "system_call", buf);
}
-struct regset_info target_regsets[] = {
+static struct regset_info s390_regsets[] = {
{ 0, 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
/* Last break address is read-only; do not attempt PTRACE_SETREGSET. */
{ PTRACE_GETREGSET, PTRACE_GETREGSET, NT_S390_LAST_BREAK, 0,
@@ -295,7 +321,7 @@ static const unsigned char s390_breakpoint[] = { 0, 1 };
static CORE_ADDR
s390_get_pc (struct regcache *regcache)
{
- if (register_size (0) == 4)
+ if (register_size (regcache->tdesc, 0) == 4)
{
unsigned int pswa;
collect_register_by_name (regcache, "pswa", &pswa);
@@ -312,7 +338,7 @@ s390_get_pc (struct regcache *regcache)
static void
s390_set_pc (struct regcache *regcache, CORE_ADDR newpc)
{
- if (register_size (0) == 4)
+ if (register_size (regcache->tdesc, 0) == 4)
{
unsigned int pswa;
collect_register_by_name (regcache, "pswa", &pswa);
@@ -328,9 +354,9 @@ s390_set_pc (struct regcache *regcache, CORE_ADDR newpc)
#ifdef __s390x__
static unsigned long
-s390_get_hwcap (void)
+s390_get_hwcap (const struct target_desc *tdesc)
{
- int wordsize = register_size (0);
+ int wordsize = register_size (tdesc, 0);
unsigned char *data = alloca (2 * wordsize);
int offset = 0;
@@ -371,9 +397,16 @@ s390_check_regset (int pid, int regset, int regsize)
return 1;
}
+#ifdef __s390x__
+/* For a 31-bit inferior, whether the kernel supports using the full
+ 64-bit GPRs. */
+static int have_hwcap_s390_high_gprs = 0;
+#endif
+
static void
s390_arch_setup (void)
{
+ const struct target_desc *tdesc;
struct regset_info *regset;
/* Check whether the kernel supports extra register sets. */
@@ -384,7 +417,7 @@ s390_arch_setup (void)
= s390_check_regset (pid, NT_S390_SYSTEM_CALL, 4);
/* Update target_regsets according to available register sets. */
- for (regset = target_regsets; regset->fill_function != NULL; regset++)
+ for (regset = s390_regsets; regset->fill_function != NULL; regset++)
if (regset->get_request == PTRACE_GETREGSET)
switch (regset->nt_type)
{
@@ -400,51 +433,48 @@ s390_arch_setup (void)
/* Assume 31-bit inferior process. */
if (have_regset_system_call)
- init_registers_s390_linux32v2 ();
+ tdesc = tdesc_s390_linux32v2;
else if (have_regset_last_break)
- init_registers_s390_linux32v1 ();
+ tdesc = tdesc_s390_linux32v1;
else
- init_registers_s390_linux32 ();
-
- the_low_target.num_regs = s390_num_regs;
- the_low_target.regmap = s390_regmap;
+ tdesc = tdesc_s390_linux32;
/* On a 64-bit host, check the low bit of the (31-bit) PSWM
-- if this is one, we actually have a 64-bit inferior. */
#ifdef __s390x__
{
unsigned int pswm;
- struct regcache *regcache = new_register_cache ();
- fetch_inferior_registers (regcache, find_regno ("pswm"));
+ struct regcache *regcache = new_register_cache (tdesc);
+ fetch_inferior_registers (regcache, find_regno (tdesc, "pswm"));
collect_register_by_name (regcache, "pswm", &pswm);
free_register_cache (regcache);
if (pswm & 1)
{
if (have_regset_system_call)
- init_registers_s390x_linux64v2 ();
+ tdesc = tdesc_s390x_linux64v2;
else if (have_regset_last_break)
- init_registers_s390x_linux64v1 ();
+ tdesc = tdesc_s390x_linux64v1;
else
- init_registers_s390x_linux64 ();
+ tdesc = tdesc_s390x_linux64;
}
/* For a 31-bit inferior, check whether the kernel supports
using the full 64-bit GPRs. */
- else if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
+ else if (s390_get_hwcap (tdesc) & HWCAP_S390_HIGH_GPRS)
{
+ have_hwcap_s390_high_gprs = 1;
+
if (have_regset_system_call)
- init_registers_s390_linux64v2 ();
+ tdesc = tdesc_s390_linux64v2;
else if (have_regset_last_break)
- init_registers_s390_linux64v1 ();
+ tdesc = tdesc_s390_linux64v1;
else
- init_registers_s390_linux64 ();
-
- the_low_target.num_regs = s390_num_regs_3264;
- the_low_target.regmap = s390_regmap_3264;
+ tdesc = tdesc_s390_linux64;
}
}
#endif
+ current_process ()->tdesc = tdesc;
}
@@ -456,12 +486,66 @@ s390_breakpoint_at (CORE_ADDR pc)
return memcmp (c, s390_breakpoint, s390_breakpoint_len) == 0;
}
+static struct usrregs_info s390_usrregs_info =
+ {
+ s390_num_regs,
+ s390_regmap,
+ };
+
+static struct regsets_info s390_regsets_info =
+ {
+ s390_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &s390_usrregs_info,
+ &s390_regsets_info
+ };
+
+#ifdef __s390x__
+static struct usrregs_info s390_usrregs_info_3264 =
+ {
+ s390_num_regs_3264,
+ s390_regmap_3264
+ };
+
+static struct regsets_info s390_regsets_info_3264 =
+ {
+ s390_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct regs_info regs_info_3264 =
+ {
+ NULL, /* regset_bitmap */
+ &s390_usrregs_info_3264,
+ &s390_regsets_info_3264
+ };
+#endif
+
+static const struct regs_info *
+s390_regs_info (void)
+{
+#ifdef __s390x__
+ if (have_hwcap_s390_high_gprs)
+ {
+ const struct target_desc *tdesc = current_process ()->tdesc;
+
+ if (register_size (tdesc, 0) == 4)
+ return &regs_info_3264;
+ }
+#endif
+ return &regs_info;
+}
struct linux_target_ops the_low_target = {
s390_arch_setup,
- s390_num_regs,
- s390_regmap,
- NULL,
+ s390_regs_info,
s390_cannot_fetch_register,
s390_cannot_store_register,
NULL, /* fetch_register */
@@ -479,3 +563,24 @@ struct linux_target_ops the_low_target = {
s390_collect_ptrace_register,
s390_supply_ptrace_register,
};
+
+void
+initialize_low_arch (void)
+{
+ /* Initialize the Linux target descriptions. */
+
+ init_registers_s390_linux32 ();
+ init_registers_s390_linux32v1 ();
+ init_registers_s390_linux32v2 ();
+ init_registers_s390_linux64 ();
+ init_registers_s390_linux64v1 ();
+ init_registers_s390_linux64v2 ();
+ init_registers_s390x_linux64 ();
+ init_registers_s390x_linux64v1 ();
+ init_registers_s390x_linux64v2 ();
+
+ initialize_regsets_info (&s390_regsets_info);
+#ifdef __s390x__
+ initialize_regsets_info (&s390_regsets_info_3264);
+#endif
+}
diff --git a/gdb/gdbserver/linux-sh-low.c b/gdb/gdbserver/linux-sh-low.c
index f268b55..e582a2b 100644
--- a/gdb/gdbserver/linux-sh-low.c
+++ b/gdb/gdbserver/linux-sh-low.c
@@ -21,6 +21,7 @@
/* Defined in auto-generated file reg-sh.c. */
void init_registers_sh (void);
+extern const struct target_desc *tdesc_sh;
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
@@ -102,16 +103,46 @@ static void sh_fill_gregset (struct regcache *regcache, void *buf)
collect_register (regcache, i, (char *) buf + sh_regmap[i]);
}
-struct regset_info target_regsets[] = {
+static struct regset_info sh_regsets[] = {
{ 0, 0, 0, 0, GENERAL_REGS, sh_fill_gregset, NULL },
{ 0, 0, 0, -1, -1, NULL, NULL }
};
+static struct regsets_info sh_regsets_info =
+ {
+ sh_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct usrregs_info sh_usrregs_info =
+ {
+ sh_num_regs,
+ sh_regmap,
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &sh_usrregs_info,
+ &sh_regsets_info
+ };
+
+static const struct regs_info *
+sh_regs_info (void)
+{
+ return &regs_info;
+}
+
+static void
+sh_arch_setup (void)
+{
+ current_process ()->tdesc = tdesc_sh;
+}
+
struct linux_target_ops the_low_target = {
- init_registers_sh,
- sh_num_regs,
- sh_regmap,
- NULL,
+ sh_arch_setup,
+ sh_regs_info,
sh_cannot_fetch_register,
sh_cannot_store_register,
NULL, /* fetch_register */
@@ -123,3 +154,11 @@ struct linux_target_ops the_low_target = {
0,
sh_breakpoint_at,
};
+
+void
+initialize_low_arch (void)
+{
+ init_registers_sh ();
+
+ initialize_regsets_info (&sh_regsets_info);
+}
diff --git a/gdb/gdbserver/linux-sparc-low.c b/gdb/gdbserver/linux-sparc-low.c
index 32590b2..444d446 100644
--- a/gdb/gdbserver/linux-sparc-low.c
+++ b/gdb/gdbserver/linux-sparc-low.c
@@ -100,6 +100,7 @@ static const struct regs_range_t fpregs_ranges[] = {
/* Defined in auto-generated file reg-sparc64.c. */
void init_registers_sparc64 (void);
+extern const struct target_desc *tdesc_sparc64;
static int
sparc_cannot_store_register (int regno)
@@ -119,12 +120,12 @@ sparc_fill_gregset_to_stack (struct regcache *regcache, const void *buf)
int i;
CORE_ADDR addr = 0;
unsigned char tmp_reg_buf[8];
- const int l0_regno = find_regno ("l0");
+ const int l0_regno = find_regno (regcache->tdesc, "l0");
const int i7_regno = l0_regno + 15;
/* These registers have to be stored in the stack. */
memcpy (&addr,
- ((char *) buf) + sparc_regmap[find_regno ("sp")],
+ ((char *) buf) + sparc_regmap[find_regno (regcache->tdesc, "sp")],
sizeof (addr));
addr += BIAS;
@@ -171,12 +172,12 @@ sparc_store_gregset_from_stack (struct regcache *regcache, const void *buf)
int i;
CORE_ADDR addr = 0;
unsigned char tmp_reg_buf[8];
- const int l0_regno = find_regno ("l0");
+ const int l0_regno = find_regno (regcache->tdesc, "l0");
const int i7_regno = l0_regno + 15;
/* These registers have to be obtained from the stack. */
memcpy (&addr,
- ((char *) buf) + sparc_regmap[find_regno ("sp")],
+ ((char *) buf) + sparc_regmap[find_regno (regcache->tdesc, "sp")],
sizeof (addr));
addr += BIAS;
@@ -269,8 +270,13 @@ sparc_reinsert_addr (void)
return lr;
}
+static void
+sparc_arch_setup (void)
+{
+ current_process ()->tdesc = tdesc_sparc64;
+}
-struct regset_info target_regsets[] = {
+static struct regset_info sparc_regsets[] = {
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
GENERAL_REGS,
sparc_fill_gregset, sparc_store_gregset },
@@ -280,12 +286,37 @@ struct regset_info target_regsets[] = {
{ 0, 0, 0, -1, -1, NULL, NULL }
};
+static struct regsets_info sparc_regsets_info =
+ {
+ sparc_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct usrregs_info sparc_usrregs_info =
+ {
+ sparc_num_regs,
+ /* No regmap needs to be provided since this impl. doesn't use
+ USRREGS. */
+ NULL
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &sparc_usrregs_info,
+ &sparc_regsets_info
+ };
+
+static const struct regs_info *
+sparc_regs_info (void)
+{
+ return &regs_info;
+}
+
struct linux_target_ops the_low_target = {
- init_registers_sparc64,
- sparc_num_regs,
- /* No regmap needs to be provided since this impl. doesn't use USRREGS. */
- NULL,
- NULL,
+ sparc_arch_setup,
+ sparc_regs_info,
sparc_cannot_fetch_register,
sparc_cannot_store_register,
NULL, /* fetch_register */
@@ -300,3 +331,12 @@ struct linux_target_ops the_low_target = {
NULL, NULL, NULL, NULL,
NULL, NULL
};
+
+void
+initialize_low_arch (void)
+{
+ /* Initialize the Linux target descriptions. */
+ init_registers_sparc64 ();
+
+ initialize_regsets_info (&sparc_regsets_info);
+}
diff --git a/gdb/gdbserver/linux-tic6x-low.c b/gdb/gdbserver/linux-tic6x-low.c
index 93a1e65..2367dea 100644
--- a/gdb/gdbserver/linux-tic6x-low.c
+++ b/gdb/gdbserver/linux-tic6x-low.c
@@ -38,10 +38,15 @@
/* Defined in auto-generated file tic6x-c64xp-linux.c. */
void init_registers_tic6x_c64xp_linux (void);
+extern const struct target_desc *tdesc_tic6x_c64xp_linux;
+
/* Defined in auto-generated file tic6x-c64x-linux.c. */
void init_registers_tic6x_c64x_linux (void);
+extern const struct target_desc *tdesc_tic6x_c64x_linux;
+
/* Defined in auto-generated file tic62x-c6xp-linux.c. */
void init_registers_tic6x_c62x_linux (void);
+extern const struct target_desc *tdesc_tic6x_c62x_linux;
union tic6x_register
{
@@ -167,11 +172,15 @@ extern struct linux_target_ops the_low_target;
static int *tic6x_regmap;
static unsigned int tic6x_breakpoint;
-static void
-tic6x_arch_setup (void)
+/* Forward definition. */
+static struct usrregs_info tic6x_usrregs_info;
+
+static const struct target_desc *
+tic6x_read_description (void)
{
register unsigned int csr asm ("B2");
unsigned int cpuid;
+ const struct target_desc *tdesc;
/* Determine the CPU we're running on to find the register order. */
__asm__ ("MVC .S2 CSR,%0" : "=r" (csr) :);
@@ -182,29 +191,30 @@ tic6x_arch_setup (void)
case 0x02: /* C67x */
tic6x_regmap = tic6x_regmap_c62x;
tic6x_breakpoint = 0x0000a122; /* BNOP .S2 0,5 */
- init_registers_tic6x_c62x_linux ();
+ tdesc = tdesc_tic6x_c62x_linux;
break;
case 0x03: /* C67x+ */
tic6x_regmap = tic6x_regmap_c64x;
tic6x_breakpoint = 0x0000a122; /* BNOP .S2 0,5 */
- init_registers_tic6x_c64x_linux ();
+ tdesc = tdesc_tic6x_c64x_linux;
break;
case 0x0c: /* C64x */
tic6x_regmap = tic6x_regmap_c64x;
tic6x_breakpoint = 0x0000a122; /* BNOP .S2 0,5 */
- init_registers_tic6x_c64x_linux ();
+ tdesc = tdesc_tic6x_c64x_linux;
break;
case 0x10: /* C64x+ */
case 0x14: /* C674x */
case 0x15: /* C66x */
tic6x_regmap = tic6x_regmap_c64xp;
tic6x_breakpoint = 0x56454314; /* illegal opcode */
- init_registers_tic6x_c64xp_linux ();
+ tdesc = tdesc_tic6x_c64xp_linux;
break;
default:
error ("Unknown CPU ID 0x%02x", cpuid);
}
- the_low_target.regmap = tic6x_regmap;
+ tic6x_usrregs_info.regmap = tic6x_regmap;
+ return tdesc;
}
static int
@@ -311,17 +321,47 @@ tic6x_store_gregset (struct regcache *regcache, const void *buf)
tic6x_supply_register (regcache, i, regset + tic6x_regmap[i]);
}
-struct regset_info target_regsets[] = {
+static struct regset_info tic6x_regsets[] = {
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, TIC6X_NUM_REGS * 4, GENERAL_REGS,
tic6x_fill_gregset, tic6x_store_gregset },
{ 0, 0, 0, -1, -1, NULL, NULL }
};
+static void
+tic6x_arch_setup (void)
+{
+ current_process ()->tdesc = tic6x_read_description ();
+}
+
+static struct regsets_info tic6x_regsets_info =
+ {
+ tic6x_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct usrregs_info tic6x_usrregs_info =
+ {
+ TIC6X_NUM_REGS,
+ NULL, /* Set in tic6x_read_description. */
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &tic6x_usrregs_info,
+ &tic6x_regsets_info
+ };
+
+static const struct regs_info *
+tic6x_regs_info (void)
+{
+ return &regs_info;
+}
+
struct linux_target_ops the_low_target = {
tic6x_arch_setup,
- TIC6X_NUM_REGS,
- 0,
- NULL,
+ tic6x_regs_info,
tic6x_cannot_fetch_register,
tic6x_cannot_store_register,
NULL, /* fetch_register */
@@ -333,3 +373,14 @@ struct linux_target_ops the_low_target = {
0,
tic6x_breakpoint_at,
};
+
+void
+initialize_low_arch (void)
+{
+ /* Initialize the Linux target descriptions. */
+ init_registers_tic6x_c64xp_linux ();
+ init_registers_tic6x_c64x_linux ();
+ init_registers_tic6x_c62x_linux ();
+
+ initialize_regsets_info (&tic6x_regsets_info);
+}
diff --git a/gdb/gdbserver/linux-tile-low.c b/gdb/gdbserver/linux-tile-low.c
index f242675..8963b9a 100644
--- a/gdb/gdbserver/linux-tile-low.c
+++ b/gdb/gdbserver/linux-tile-low.c
@@ -25,8 +25,11 @@
/* Defined in auto-generated file reg-tilegx.c. */
void init_registers_tilegx (void);
+extern const struct target_desc *tdesc_tilegx;
+
/* Defined in auto-generated file reg-tilegx32.c. */
void init_registers_tilegx32 (void);
+extern const struct target_desc *tdesc_tilegx32;
#define tile_num_regs 65
@@ -119,13 +122,39 @@ tile_store_gregset (struct regcache *regcache, const void *buf)
supply_register (regcache, i, ((uint_reg_t *) buf) + tile_regmap[i]);
}
-struct regset_info target_regsets[] =
+static struct regset_info tile_regsets[] =
{
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, tile_num_regs * 4,
GENERAL_REGS, tile_fill_gregset, tile_store_gregset },
{ 0, 0, 0, -1, -1, NULL, NULL }
};
+static struct regsets_info tile_regsets_info =
+ {
+ tile_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct usrregs_info tile_usrregs_info =
+ {
+ tile_num_regs,
+ tile_regmap,
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &tile_usrregs_info,
+ &tile_regsets_info,
+ };
+
+static const struct regs_info *
+tile_regs_info (void)
+{
+ return &regs_info;
+}
+
static void
tile_arch_setup (void)
{
@@ -138,18 +167,16 @@ tile_arch_setup (void)
error (_("Can't debug 64-bit process with 32-bit GDBserver"));
if (!is_elf64)
- init_registers_tilegx32();
+ current_process ()->tdesc = tdesc_tilegx32;
else
- init_registers_tilegx();
+ current_process ()->tdesc = tdesc_tilegx;
}
struct linux_target_ops the_low_target =
{
tile_arch_setup,
- tile_num_regs,
- tile_regmap,
- NULL,
+ tile_regs_info,
tile_cannot_fetch_register,
tile_cannot_store_register,
NULL,
@@ -161,3 +188,12 @@ struct linux_target_ops the_low_target =
0,
tile_breakpoint_at,
};
+
+void
+initialize_low_arch (void)
+{
+ init_registers_tilegx32();
+ init_registers_tilegx();
+
+ initialize_regsets_info (&tile_regsets_info);
+}
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index dfe78b1..a03f512 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -30,21 +30,43 @@
#include "gdb_proc_service.h"
#include "agent.h"
+#include "tdesc.h"
-/* Defined in auto-generated file i386-linux.c. */
-void init_registers_i386_linux (void);
+#ifdef __x86_64__
/* Defined in auto-generated file amd64-linux.c. */
void init_registers_amd64_linux (void);
-/* Defined in auto-generated file i386-avx-linux.c. */
-void init_registers_i386_avx_linux (void);
+extern const struct target_desc *tdesc_amd64_linux;
+
/* Defined in auto-generated file amd64-avx-linux.c. */
void init_registers_amd64_avx_linux (void);
-/* Defined in auto-generated file i386-mmx-linux.c. */
-void init_registers_i386_mmx_linux (void);
+extern const struct target_desc *tdesc_amd64_avx_linux;
+
/* Defined in auto-generated file x32-linux.c. */
void init_registers_x32_linux (void);
+extern const struct target_desc *tdesc_x32_linux;
+
/* Defined in auto-generated file x32-avx-linux.c. */
void init_registers_x32_avx_linux (void);
+extern const struct target_desc *tdesc_x32_avx_linux;
+#endif
+
+/* Defined in auto-generated file i386-linux.c. */
+void init_registers_i386_linux (void);
+extern const struct target_desc *tdesc_i386_linux;
+
+/* Defined in auto-generated file i386-mmx-linux.c. */
+void init_registers_i386_mmx_linux (void);
+extern const struct target_desc *tdesc_i386_mmx_linux;
+
+/* Defined in auto-generated file i386-avx-linux.c. */
+void init_registers_i386_avx_linux (void);
+extern const struct target_desc *tdesc_i386_avx_linux;
+
+#ifdef __x86_64__
+static struct target_desc *tdesc_amd64_linux_no_xml;
+#endif
+static struct target_desc *tdesc_i386_linux_no_xml;
+
static unsigned char jump_insn[] = { 0xe9, 0, 0, 0, 0 };
static unsigned char small_jump_insn[] = { 0x66, 0xe9, 0, 0 };
@@ -160,6 +182,22 @@ static /*const*/ int i386_regmap[] =
#define I386_NUM_REGS (sizeof (i386_regmap) / sizeof (i386_regmap[0]))
#endif
+
+#ifdef __x86_64__
+
+/* Returns true if the current inferior belongs to a x86-64 process,
+ per the tdesc. */
+
+static int
+is_64bit_tdesc (void)
+{
+ struct regcache *regcache = get_thread_regcache (current_inferior, 0);
+
+ return register_size (regcache->tdesc, 0) == 8;
+}
+
+#endif
+
/* Called by libthread_db. */
@@ -168,7 +206,7 @@ ps_get_thread_area (const struct ps_prochandle *ph,
lwpid_t lwpid, int idx, void **base)
{
#ifdef __x86_64__
- int use_64bit = register_size (0) == 8;
+ int use_64bit = is_64bit_tdesc ();
if (use_64bit)
{
@@ -211,7 +249,7 @@ static int
x86_get_thread_area (int lwpid, CORE_ADDR *addr)
{
#ifdef __x86_64__
- int use_64bit = register_size (0) == 8;
+ int use_64bit = is_64bit_tdesc ();
if (use_64bit)
{
@@ -251,14 +289,24 @@ x86_get_thread_area (int lwpid, CORE_ADDR *addr)
static int
-i386_cannot_store_register (int regno)
+x86_cannot_store_register (int regno)
{
+#ifdef __x86_64__
+ if (is_64bit_tdesc ())
+ return 0;
+#endif
+
return regno >= I386_NUM_REGS;
}
static int
-i386_cannot_fetch_register (int regno)
+x86_cannot_fetch_register (int regno)
{
+#ifdef __x86_64__
+ if (is_64bit_tdesc ())
+ return 0;
+#endif
+
return regno >= I386_NUM_REGS;
}
@@ -268,7 +316,7 @@ x86_fill_gregset (struct regcache *regcache, void *buf)
int i;
#ifdef __x86_64__
- if (register_size (0) == 8)
+ if (register_size (regcache->tdesc, 0) == 8)
{
for (i = 0; i < X86_64_NUM_REGS; i++)
if (x86_64_regmap[i] != -1)
@@ -290,7 +338,7 @@ x86_store_gregset (struct regcache *regcache, const void *buf)
int i;
#ifdef __x86_64__
- if (register_size (0) == 8)
+ if (register_size (regcache->tdesc, 0) == 8)
{
for (i = 0; i < X86_64_NUM_REGS; i++)
if (x86_64_regmap[i] != -1)
@@ -359,11 +407,9 @@ x86_store_xstateregset (struct regcache *regcache, const void *buf)
This is, presumably, to handle the case where PTRACE_[GS]ETFPXREGS
doesn't work. IWBN to avoid the duplication in the case where it
does work. Maybe the arch_setup routine could check whether it works
- and update target_regsets accordingly, maybe by moving target_regsets
- to linux_target_ops and set the right one there, rather than having to
- modify the target_regsets global. */
+ and update the supported regsets accordingly. */
-struct regset_info target_regsets[] =
+static struct regset_info x86_regsets[] =
{
#ifdef HAVE_PTRACE_GETREGS
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
@@ -388,7 +434,7 @@ struct regset_info target_regsets[] =
static CORE_ADDR
x86_get_pc (struct regcache *regcache)
{
- int use_64bit = register_size (0) == 8;
+ int use_64bit = register_size (regcache->tdesc, 0) == 8;
if (use_64bit)
{
@@ -407,7 +453,7 @@ x86_get_pc (struct regcache *regcache)
static void
x86_set_pc (struct regcache *regcache, CORE_ADDR pc)
{
- int use_64bit = register_size (0) == 8;
+ int use_64bit = register_size (regcache->tdesc, 0) == 8;
if (use_64bit)
{
@@ -1107,7 +1153,7 @@ x86_siginfo_fixup (siginfo_t *native, void *inf, int direction)
{
#ifdef __x86_64__
/* Is the inferior 32-bit? If so, then fixup the siginfo object. */
- if (register_size (0) == 4)
+ if (!is_64bit_tdesc ())
{
if (sizeof (siginfo_t) != sizeof (compat_siginfo_t))
fatal ("unexpected difference in siginfo");
@@ -1141,138 +1187,207 @@ x86_siginfo_fixup (siginfo_t *native, void *inf, int direction)
static int use_xml;
-/* Update gdbserver_xmltarget. */
+/* Format of XSAVE extended state is:
+ struct
+ {
+ fxsave_bytes[0..463]
+ sw_usable_bytes[464..511]
+ xstate_hdr_bytes[512..575]
+ avx_bytes[576..831]
+ future_state etc
+ };
+
+ Same memory layout will be used for the coredump NT_X86_XSTATE
+ representing the XSAVE extended state registers.
+
+ The first 8 bytes of the sw_usable_bytes[464..467] is the OS enabled
+ extended state mask, which is the same as the extended control register
+ 0 (the XFEATURE_ENABLED_MASK register), XCR0. We can use this mask
+ together with the mask saved in the xstate_hdr_bytes to determine what
+ states the processor/OS supports and what state, used or initialized,
+ the process/thread is in. */
+#define I386_LINUX_XSAVE_XCR0_OFFSET 464
+
+/* Does the current host support the GETFPXREGS request? The header
+ file may or may not define it, and even if it is defined, the
+ kernel will return EIO if it's running on a pre-SSE processor. */
+int have_ptrace_getfpxregs =
+#ifdef HAVE_PTRACE_GETFPXREGS
+ -1
+#else
+ 0
+#endif
+;
-static void
-x86_linux_update_xmltarget (void)
+/* Does the current host support PTRACE_GETREGSET? */
+static int have_ptrace_getregset = -1;
+
+/* Get Linux/x86 target description from running target. */
+
+static const struct target_desc *
+x86_linux_read_description (void)
{
- int pid;
+ unsigned int machine;
+ int is_elf64;
+ int avx;
+ int tid;
+ static uint64_t xcr0;
struct regset_info *regset;
- static unsigned long long xcr0;
- static int have_ptrace_getregset = -1;
-#if !defined(__x86_64__) && defined(HAVE_PTRACE_GETFPXREGS)
- static int have_ptrace_getfpxregs = -1;
-#endif
- if (!current_inferior)
- return;
+ tid = lwpid_of (get_thread_lwp (current_inferior));
- /* Before changing the register cache internal layout or the target
- regsets, flush the contents of the current valid caches back to
- the threads. */
- regcache_invalidate ();
+ is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine);
- pid = pid_of (get_thread_lwp (current_inferior));
-#ifdef __x86_64__
- if (num_xmm_registers == 8)
- init_registers_i386_linux ();
- else if (linux_is_elf64)
- init_registers_amd64_linux ();
- else
- init_registers_x32_linux ();
-#else
+ if (sizeof (void *) == 4)
{
-# ifdef HAVE_PTRACE_GETFPXREGS
- if (have_ptrace_getfpxregs == -1)
- {
- elf_fpxregset_t fpxregs;
+ if (is_elf64 > 0)
+ error (_("Can't debug 64-bit process with 32-bit GDBserver"));
+#ifndef __x86_64__
+ else if (machine == EM_X86_64)
+ error (_("Can't debug x86-64 process with 32-bit GDBserver"));
+#endif
+ }
- if (ptrace (PTRACE_GETFPXREGS, pid, 0, (int) &fpxregs) < 0)
- {
- have_ptrace_getfpxregs = 0;
- x86_xcr0 = I386_XSTATE_X87_MASK;
-
- /* Disable PTRACE_GETFPXREGS. */
- for (regset = target_regsets;
- regset->fill_function != NULL; regset++)
- if (regset->get_request == PTRACE_GETFPXREGS)
- {
- regset->size = 0;
- break;
- }
- }
- else
- have_ptrace_getfpxregs = 1;
- }
+#if !defined __x86_64__ && defined HAVE_PTRACE_GETFPXREGS
+ if (machine == EM_386 && have_ptrace_getfpxregs == -1)
+ {
+ elf_fpxregset_t fpxregs;
- if (!have_ptrace_getfpxregs)
+ if (ptrace (PTRACE_GETFPXREGS, tid, 0, (long) &fpxregs) < 0)
{
- init_registers_i386_mmx_linux ();
- return;
+ have_ptrace_getfpxregs = 0;
+ have_ptrace_getregset = 0;
+ return tdesc_i386_mmx_linux;
}
-# endif
- init_registers_i386_linux ();
+ else
+ have_ptrace_getfpxregs = 1;
}
#endif
if (!use_xml)
{
+ x86_xcr0 = I386_XSTATE_SSE_MASK;
+
/* Don't use XML. */
#ifdef __x86_64__
- if (num_xmm_registers == 8)
- gdbserver_xmltarget = xmltarget_i386_linux_no_xml;
+ if (machine == EM_X86_64)
+ return tdesc_amd64_linux_no_xml;
else
- gdbserver_xmltarget = xmltarget_amd64_linux_no_xml;
-#else
- gdbserver_xmltarget = xmltarget_i386_linux_no_xml;
#endif
-
- x86_xcr0 = I386_XSTATE_SSE_MASK;
-
- return;
+ return tdesc_i386_linux_no_xml;
}
- /* Check if XSAVE extended state is supported. */
if (have_ptrace_getregset == -1)
{
- unsigned long long xstateregs[I386_XSTATE_SSE_SIZE / sizeof (long long)];
+ uint64_t xstateregs[(I386_XSTATE_SSE_SIZE / sizeof (uint64_t))];
struct iovec iov;
iov.iov_base = xstateregs;
iov.iov_len = sizeof (xstateregs);
/* Check if PTRACE_GETREGSET works. */
- if (ptrace (PTRACE_GETREGSET, pid, (unsigned int) NT_X86_XSTATE,
- &iov) < 0)
+ if (ptrace (PTRACE_GETREGSET, tid,
+ (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
+ have_ptrace_getregset = 0;
+ else
{
- have_ptrace_getregset = 0;
- return;
+ have_ptrace_getregset = 1;
+
+ /* Get XCR0 from XSAVE extended state. */
+ xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
+ / sizeof (uint64_t))];
+
+ /* Use PTRACE_GETREGSET if it is available. */
+ for (regset = x86_regsets;
+ regset->fill_function != NULL; regset++)
+ if (regset->get_request == PTRACE_GETREGSET)
+ regset->size = I386_XSTATE_SIZE (xcr0);
+ else if (regset->type != GENERAL_REGS)
+ regset->size = 0;
}
- else
- have_ptrace_getregset = 1;
-
- /* Get XCR0 from XSAVE extended state at byte 464. */
- xcr0 = xstateregs[464 / sizeof (long long)];
-
- /* Use PTRACE_GETREGSET if it is available. */
- for (regset = target_regsets;
- regset->fill_function != NULL; regset++)
- if (regset->get_request == PTRACE_GETREGSET)
- regset->size = I386_XSTATE_SIZE (xcr0);
- else if (regset->type != GENERAL_REGS)
- regset->size = 0;
}
- if (have_ptrace_getregset)
- {
- /* AVX is the highest feature we support. */
- if ((xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK)
- {
- x86_xcr0 = xcr0;
+ /* Check the native XCR0 only if PTRACE_GETREGSET is available. */
+ avx = (have_ptrace_getregset
+ && (xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK);
+
+ /* AVX is the highest feature we support. */
+ if (avx)
+ x86_xcr0 = xcr0;
+ if (machine == EM_X86_64)
+ {
#ifdef __x86_64__
- /* I386 has 8 xmm regs. */
- if (num_xmm_registers == 8)
- init_registers_i386_avx_linux ();
- else if (linux_is_elf64)
- init_registers_amd64_avx_linux ();
+ if (avx)
+ {
+ if (!is_elf64)
+ return tdesc_x32_avx_linux;
else
- init_registers_x32_avx_linux ();
-#else
- init_registers_i386_avx_linux ();
-#endif
+ return tdesc_amd64_avx_linux;
+ }
+ else
+ {
+ if (!is_elf64)
+ return tdesc_x32_linux;
+ else
+ return tdesc_amd64_linux;
}
+#endif
}
+ else
+ {
+ if (avx)
+ return tdesc_i386_avx_linux;
+ else
+ return tdesc_i386_linux;
+ }
+
+ gdb_assert_not_reached ("failed to return tdesc");
+}
+
+/* Callback for find_inferior. Stops iteration when a thread with a
+ given PID is found. */
+
+static int
+same_process_callback (struct inferior_list_entry *entry, void *data)
+{
+ int pid = *(int *) data;
+
+ return (ptid_get_pid (entry->id) == pid);
+}
+
+/* Callback for for_each_inferior. Calls the arch_setup routine for
+ each process. */
+
+static void
+x86_arch_setup_process_callback (struct inferior_list_entry *entry)
+{
+ int pid = ptid_get_pid (entry->id);
+
+ /* Look up any thread of this processes. */
+ current_inferior
+ = (struct thread_info *) find_inferior (&all_threads,
+ same_process_callback, &pid);
+
+ the_low_target.arch_setup ();
+}
+
+/* Update all the target description of all processes; a new GDB
+ connected, and it may or not support xml target descriptions. */
+
+static void
+x86_linux_update_xmltarget (void)
+{
+ struct thread_info *save_inferior = current_inferior;
+
+ /* Before changing the register cache's internal layout, flush the
+ contents of the current valid caches back to the threads, and
+ release the current regcache objects. */
+ regcache_release ();
+
+ for_each_inferior (&all_processes, x86_arch_setup_process_callback);
+
+ current_inferior = save_inferior;
}
/* Process qSupported query, "xmlRegisters=". Update the buffer size for
@@ -1305,62 +1420,54 @@ x86_linux_process_qsupported (const char *query)
x86_linux_update_xmltarget ();
}
-/* Initialize gdbserver for the architecture of the inferior. */
+/* Common for x86/x86-64. */
-static void
-x86_arch_setup (void)
-{
- int pid = pid_of (get_thread_lwp (current_inferior));
- unsigned int machine;
- int is_elf64 = linux_pid_exe_is_elf_64_file (pid, &machine);
-
- if (sizeof (void *) == 4)
- {
- if (is_elf64 > 0)
- error (_("Can't debug 64-bit process with 32-bit GDBserver"));
-#ifndef __x86_64__
- else if (machine == EM_X86_64)
- error (_("Can't debug x86-64 process with 32-bit GDBserver"));
-#endif
- }
+static struct regsets_info x86_regsets_info =
+ {
+ x86_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
#ifdef __x86_64__
- if (is_elf64 < 0)
- {
- /* This can only happen if /proc/<pid>/exe is unreadable,
- but "that can't happen" if we've gotten this far.
- Fall through and assume this is a 32-bit program. */
- }
- else if (machine == EM_X86_64)
- {
- /* Amd64 doesn't have HAVE_LINUX_USRREGS. */
- the_low_target.num_regs = -1;
- the_low_target.regmap = NULL;
- the_low_target.cannot_fetch_register = NULL;
- the_low_target.cannot_store_register = NULL;
-
- /* Amd64 has 16 xmm regs. */
- num_xmm_registers = 16;
-
- linux_is_elf64 = is_elf64;
- x86_linux_update_xmltarget ();
- return;
- }
-
- linux_is_elf64 = 0;
+static struct regs_info amd64_linux_regs_info =
+ {
+ NULL, /* regset_bitmap */
+ NULL, /* usrregs_info */
+ &x86_regsets_info
+ };
#endif
+static struct usrregs_info i386_linux_usrregs_info =
+ {
+ I386_NUM_REGS,
+ i386_regmap,
+ };
- /* Ok we have a 32-bit inferior. */
+static struct regs_info i386_linux_regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &i386_linux_usrregs_info,
+ &x86_regsets_info
+ };
- the_low_target.num_regs = I386_NUM_REGS;
- the_low_target.regmap = i386_regmap;
- the_low_target.cannot_fetch_register = i386_cannot_fetch_register;
- the_low_target.cannot_store_register = i386_cannot_store_register;
+const struct regs_info *
+x86_linux_regs_info (void)
+{
+#ifdef __x86_64__
+ if (is_64bit_tdesc ())
+ return &amd64_linux_regs_info;
+ else
+#endif
+ return &i386_linux_regs_info;
+}
- /* I386 has 8 xmm regs. */
- num_xmm_registers = 8;
+/* Initialize the target description for the architecture of the
+ inferior. */
- x86_linux_update_xmltarget ();
+static void
+x86_arch_setup (void)
+{
+ current_process ()->tdesc = x86_linux_read_description ();
}
static int
@@ -1790,7 +1897,7 @@ x86_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr,
char *err)
{
#ifdef __x86_64__
- if (register_size (0) == 8)
+ if (is_64bit_tdesc ())
return amd64_install_fast_tracepoint_jump_pad (tpoint, tpaddr,
collector, lockaddr,
orig_size, jump_entry,
@@ -1824,7 +1931,7 @@ x86_get_min_fast_tracepoint_insn_len (void)
#ifdef __x86_64__
/* On x86-64, 5-byte jump instructions with a 4-byte offset are always
used for fast tracepoints. */
- if (register_size (0) == 8)
+ if (is_64bit_tdesc ())
return 5;
#endif
@@ -3167,9 +3274,7 @@ static struct emit_ops *
x86_emit_ops (void)
{
#ifdef __x86_64__
- int use_64bit = register_size (0) == 8;
-
- if (use_64bit)
+ if (is_64bit_tdesc ())
return &amd64_emit_ops;
else
#endif
@@ -3188,11 +3293,9 @@ x86_supports_range_stepping (void)
struct linux_target_ops the_low_target =
{
x86_arch_setup,
- -1,
- NULL,
- NULL,
- NULL,
- NULL,
+ x86_linux_regs_info,
+ x86_cannot_fetch_register,
+ x86_cannot_store_register,
NULL, /* fetch_register */
x86_get_pc,
x86_set_pc,
@@ -3223,3 +3326,27 @@ struct linux_target_ops the_low_target =
x86_get_min_fast_tracepoint_insn_len,
x86_supports_range_stepping,
};
+
+void
+initialize_low_arch (void)
+{
+ /* Initialize the Linux target descriptions. */
+#ifdef __x86_64__
+ init_registers_amd64_linux ();
+ init_registers_amd64_avx_linux ();
+ init_registers_x32_linux ();
+
+ tdesc_amd64_linux_no_xml = xmalloc (sizeof (struct target_desc));
+ copy_target_description (tdesc_amd64_linux_no_xml, tdesc_amd64_linux);
+ tdesc_amd64_linux_no_xml->xmltarget = xmltarget_amd64_linux_no_xml;
+#endif
+ init_registers_i386_linux ();
+ init_registers_i386_mmx_linux ();
+ init_registers_i386_avx_linux ();
+
+ tdesc_i386_linux_no_xml = xmalloc (sizeof (struct target_desc));
+ copy_target_description (tdesc_i386_linux_no_xml, tdesc_i386_linux);
+ tdesc_i386_linux_no_xml->xmltarget = xmltarget_i386_linux_no_xml;
+
+ initialize_regsets_info (&x86_regsets_info);
+}
diff --git a/gdb/gdbserver/linux-xtensa-low.c b/gdb/gdbserver/linux-xtensa-low.c
index d988a46..6083f33 100644
--- a/gdb/gdbserver/linux-xtensa-low.c
+++ b/gdb/gdbserver/linux-xtensa-low.c
@@ -22,6 +22,7 @@
/* Defined in auto-generated file reg-xtensa.c. */
void init_registers_xtensa (void);
+extern const struct target_desc *tdesc_xtensa;
#include <sys/ptrace.h>
#include <xtensa-config.h>
@@ -40,19 +41,20 @@ static void
xtensa_fill_gregset (struct regcache *regcache, void *buf)
{
elf_greg_t* rset = (elf_greg_t*)buf;
+ const struct target_desc *tdesc = regcache->tdesc;
int ar0_regnum;
char *ptr;
int i;
/* Take care of AR registers. */
- ar0_regnum = find_regno ("ar0");
+ ar0_regnum = find_regno (tdesc, "ar0");
ptr = (char*)&rset[R_A0];
for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++)
{
collect_register (regcache, i, ptr);
- ptr += register_size(i);
+ ptr += register_size (tdesc, i);
}
/* Loop registers, if hardware has it. */
@@ -74,19 +76,20 @@ static void
xtensa_store_gregset (struct regcache *regcache, const void *buf)
{
const elf_greg_t* rset = (const elf_greg_t*)buf;
+ const struct target_desc *tdesc = regcache->tdesc;
int ar0_regnum;
char *ptr;
int i;
/* Take care of AR registers. */
- ar0_regnum = find_regno ("ar0");
+ ar0_regnum = find_regno (tdesc, "ar0");
ptr = (char *)&rset[R_A0];
for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++)
{
supply_register (regcache, i, ptr);
- ptr += register_size(i);
+ ptr += register_size (tdesc, i);
}
/* Loop registers, if hardware has it. */
@@ -130,7 +133,7 @@ xtensa_store_xtregset (struct regcache *regcache, const void *buf)
}
}
-struct regset_info target_regsets[] = {
+static struct regset_info xtensa_regsets[] = {
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
GENERAL_REGS,
xtensa_fill_gregset, xtensa_store_gregset },
@@ -176,11 +179,41 @@ xtensa_breakpoint_at (CORE_ADDR where)
xtensa_breakpoint, xtensa_breakpoint_len) == 0;
}
+static struct regsets_info xtensa_regsets_info =
+ {
+ xtensa_regsets, /* regsets */
+ 0, /* num_regsets */
+ NULL, /* disabled_regsets */
+ };
+
+static struct usrregs_info xtensa_usrregs_info =
+ {
+ xtensa_num_regs,
+ xtensa_regmap,
+ };
+
+static struct regs_info regs_info =
+ {
+ NULL, /* regset_bitmap */
+ &xtensa_usrregs_info,
+ &xtensa_regsets_info
+ };
+
+static void
+xtensa_arch_setup (void)
+{
+ current_process ()->tdesc = tdesc_xtensa;
+}
+
+static const struct regs_info *
+xtensa_regs_info (void)
+{
+ return &regs_info;
+}
+
struct linux_target_ops the_low_target = {
- init_registers_xtensa,
- 0,
- 0,
- NULL,
+ xtensa_arch_setup,
+ xtensa_regs_info,
0,
0,
NULL, /* fetch_register */
@@ -192,3 +225,13 @@ struct linux_target_ops the_low_target = {
0,
xtensa_breakpoint_at,
};
+
+
+void
+initialize_low_arch (void)
+{
+ /* Initialize the Linux target descriptions. */
+ init_registers_xtensa ();
+
+ initialize_regsets_info (&xtensa_regsets_info);
+}
diff --git a/gdb/gdbserver/lynx-i386-low.c b/gdb/gdbserver/lynx-i386-low.c
index e461bb2..11b5f4c 100644
--- a/gdb/gdbserver/lynx-i386-low.c
+++ b/gdb/gdbserver/lynx-i386-low.c
@@ -122,6 +122,7 @@ enum lynx_i386_gdb_regnum
/* Defined in auto-generated file i386.c. */
extern void init_registers_i386 (void);
+extern const struct target_desc *tdesc_i386;
/* The fill_function for the general-purpose register set. */
@@ -297,6 +298,7 @@ static void
lynx_i386_arch_setup (void)
{
init_registers_i386 ();
+ lynx_tdesc = tdesc_i386;
}
/* Description of all the x86-lynx register sets. */
diff --git a/gdb/gdbserver/lynx-low.c b/gdb/gdbserver/lynx-low.c
index 3dbffa5..4cf8683 100644
--- a/gdb/gdbserver/lynx-low.c
+++ b/gdb/gdbserver/lynx-low.c
@@ -30,6 +30,8 @@
int using_threads = 1;
+const struct target_desc *lynx_tdesc;
+
/* Per-process private data. */
struct process_info_private
@@ -214,6 +216,7 @@ lynx_add_process (int pid, int attached)
struct process_info *proc;
proc = add_process (pid, attached);
+ proc->tdesc = lynx_tdesc;
proc->private = xcalloc (1, sizeof (*proc->private));
proc->private->last_wait_event_ptid = null_ptid;
diff --git a/gdb/gdbserver/lynx-low.h b/gdb/gdbserver/lynx-low.h
index 552c50f..47deaab 100644
--- a/gdb/gdbserver/lynx-low.h
+++ b/gdb/gdbserver/lynx-low.h
@@ -18,6 +18,7 @@
#include "server.h"
struct regcache;
+struct target_desc;
/* Some information relative to a given register set. */
@@ -50,3 +51,6 @@ struct lynx_target_ops
extern struct lynx_target_ops the_low_target;
+/* The inferior's target description. This is a global because the
+ LynxOS ports support neither bi-arch nor multi-process. */
+extern const struct target_desc *lynx_tdesc;
diff --git a/gdb/gdbserver/lynx-ppc-low.c b/gdb/gdbserver/lynx-ppc-low.c
index 5e5ac5d..dc5dd3c 100644
--- a/gdb/gdbserver/lynx-ppc-low.c
+++ b/gdb/gdbserver/lynx-ppc-low.c
@@ -69,6 +69,7 @@ typedef struct usr_fcontext_s
/* Defined in auto-generated file powerpc-32.c. */
extern void init_registers_powerpc_32 (void);
+extern const struct target_desc *tdesc_powerpc_32;
/* The fill_function for the general-purpose register set. */
@@ -164,6 +165,7 @@ static void
lynx_ppc_arch_setup (void)
{
init_registers_powerpc_32 ();
+ lynx_tdesc = tdesc_powerpc_32;
}
/* Description of all the powerpc-lynx register sets. */
diff --git a/gdb/gdbserver/nto-low.c b/gdb/gdbserver/nto-low.c
index 5e4c60d..3670133 100644
--- a/gdb/gdbserver/nto-low.c
+++ b/gdb/gdbserver/nto-low.c
@@ -35,6 +35,8 @@
extern int using_threads;
int using_threads = 1;
+const struct target_desc *nto_tdesc;
+
static void
nto_trace (const char *fmt, ...)
{
@@ -203,11 +205,13 @@ do_attach (pid_t pid)
&& (status.flags & _DEBUG_FLAG_STOPPED))
{
ptid_t ptid;
+ struct process_info *proc;
kill (pid, SIGCONT);
ptid = ptid_build (status.pid, status.tid, 0);
the_low_target.arch_setup ();
- add_process (status.pid, 1);
+ proc = add_process (status.pid, 1);
+ proc->tdesc = nto_tdesc;
TRACE ("Adding thread: pid=%d tid=%ld\n", status.pid,
ptid_get_lwp (ptid));
nto_find_new_threads (&nto_inferior);
diff --git a/gdb/gdbserver/nto-low.h b/gdb/gdbserver/nto-low.h
index 2c450b7..1cc8f22 100644
--- a/gdb/gdbserver/nto-low.h
+++ b/gdb/gdbserver/nto-low.h
@@ -19,6 +19,8 @@
#ifndef NTO_LOW_H
#define NTO_LOW_H
+struct target_desc;
+
enum regset_type
{
NTO_REG_GENERAL,
@@ -40,5 +42,9 @@ struct nto_target_ops
extern struct nto_target_ops the_low_target;
+/* The inferior's target description. This is a global because the
+ LynxOS ports support neither bi-arch nor multi-process. */
+extern const struct target_desc *nto_tdesc;
+
#endif
diff --git a/gdb/gdbserver/nto-x86-low.c b/gdb/gdbserver/nto-x86-low.c
index 9163880..c9cb004 100644
--- a/gdb/gdbserver/nto-x86-low.c
+++ b/gdb/gdbserver/nto-x86-low.c
@@ -28,6 +28,7 @@
/* Definition auto generated from reg-i386.dep. */
extern void init_registers_i386 ();
extern struct reg *regs_i386;
+extern const struct target_desc *tdesc_i386;
const unsigned char x86_breakpoint[] = { 0xCC };
#define x86_breakpoint_len 1
@@ -91,6 +92,7 @@ nto_x86_arch_setup (void)
{
init_registers_i386 ();
the_low_target.num_regs = 16;
+ nto_tdesc = tdesc_i386;
}
struct nto_target_ops the_low_target =
diff --git a/gdb/gdbserver/proc-service.c b/gdb/gdbserver/proc-service.c
index 235bab7..69b86f8 100644
--- a/gdb/gdbserver/proc-service.c
+++ b/gdb/gdbserver/proc-service.c
@@ -39,18 +39,20 @@ typedef size_t gdb_ps_size_t;
#ifdef HAVE_REGSETS
static struct regset_info *
-gregset_info(void)
+gregset_info (void)
{
int i = 0;
+ const struct regs_info *regs_info = (*the_low_target.regs_info) ();
+ struct regsets_info *regsets_info = regs_info->regsets_info;
- while (target_regsets[i].size != -1)
+ while (regsets_info->regsets[i].size != -1)
{
- if (target_regsets[i].type == GENERAL_REGS)
+ if (regsets_info->regsets[i].type == GENERAL_REGS)
break;
i++;
}
- return &target_regsets[i];
+ return &regsets_info->regsets[i];
}
#endif
diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c
index 778bd05..be47ed3 100644
--- a/gdb/gdbserver/regcache.c
+++ b/gdb/gdbserver/regcache.c
@@ -19,17 +19,11 @@
#include "server.h"
#include "regdef.h"
#include "gdbthread.h"
+#include "tdesc.h"
#include <stdlib.h>
#include <string.h>
-static int register_bytes;
-
-static struct reg *reg_defs;
-static int num_registers;
-
-const char **gdbserver_expedite_regs;
-
#ifndef IN_PROCESS_AGENT
struct regcache *
@@ -39,8 +33,23 @@ get_thread_regcache (struct thread_info *thread, int fetch)
regcache = (struct regcache *) inferior_regcache_data (thread);
+ /* Threads' regcaches are created lazily, because biarch targets add
+ the main thread/lwp before seeing it stop for the first time, and
+ it is only after the target sees the thread stop for the first
+ time that the target has a chance of determining the process's
+ architecture. IOW, when we first add the process's main thread
+ we don't know which architecture/tdesc its regcache should
+ have. */
if (regcache == NULL)
- fatal ("no register cache");
+ {
+ struct process_info *proc = get_thread_process (thread);
+
+ if (proc->tdesc == NULL)
+ fatal ("no target description");
+
+ regcache = new_register_cache (proc->tdesc);
+ set_inferior_regcache_data (thread, regcache);
+ }
if (fetch && regcache->registers_valid == 0)
{
@@ -56,9 +65,8 @@ get_thread_regcache (struct thread_info *thread, int fetch)
}
void
-regcache_invalidate_one (struct inferior_list_entry *entry)
+regcache_invalidate_thread (struct thread_info *thread)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct regcache *regcache;
regcache = (struct regcache *) inferior_regcache_data (thread);
@@ -78,16 +86,35 @@ regcache_invalidate_one (struct inferior_list_entry *entry)
regcache->registers_valid = 0;
}
+static int
+regcache_invalidate_one (struct inferior_list_entry *entry,
+ void *pid_p)
+{
+ struct thread_info *thread = (struct thread_info *) entry;
+ int pid = *(int *) pid_p;
+
+ /* Only invalidate the regcaches of threads of this process. */
+ if (ptid_get_pid (entry->id) == pid)
+ regcache_invalidate_thread (thread);
+
+ return 0;
+}
+
void
regcache_invalidate (void)
{
- for_each_inferior (&all_threads, regcache_invalidate_one);
+ /* Only update the threads of the current process. */
+ int pid = ptid_get_pid (current_inferior->entry.id);
+
+ find_inferior (&all_threads, regcache_invalidate_one, &pid);
}
#endif
struct regcache *
-init_register_cache (struct regcache *regcache, unsigned char *regbuf)
+init_register_cache (struct regcache *regcache,
+ const struct target_desc *tdesc,
+ unsigned char *regbuf)
{
#ifndef IN_PROCESS_AGENT
if (regbuf == NULL)
@@ -96,9 +123,10 @@ init_register_cache (struct regcache *regcache, unsigned char *regbuf)
created, in case there are registers the target never
fetches. This way they'll read as zero instead of
garbage. */
- regcache->registers = xcalloc (1, register_bytes);
+ regcache->tdesc = tdesc;
+ regcache->registers = xcalloc (1, tdesc->registers_size);
regcache->registers_owned = 1;
- regcache->register_status = xcalloc (1, num_registers);
+ regcache->register_status = xcalloc (1, tdesc->num_registers);
gdb_assert (REG_UNAVAILABLE == 0);
}
else
@@ -108,6 +136,7 @@ init_register_cache (struct regcache *regcache, unsigned char *regbuf)
else
#endif
{
+ regcache->tdesc = tdesc;
regcache->registers = regbuf;
regcache->registers_owned = 0;
#ifndef IN_PROCESS_AGENT
@@ -123,15 +152,14 @@ init_register_cache (struct regcache *regcache, unsigned char *regbuf)
#ifndef IN_PROCESS_AGENT
struct regcache *
-new_register_cache (void)
+new_register_cache (const struct target_desc *tdesc)
{
struct regcache *regcache;
- if (register_bytes == 0)
- return NULL; /* The architecture hasn't been initialized yet. */
+ gdb_assert (tdesc->registers_size != 0);
regcache = xmalloc (sizeof (*regcache));
- return init_register_cache (regcache, NULL);
+ return init_register_cache (regcache, tdesc, NULL);
}
void
@@ -151,67 +179,19 @@ free_register_cache (struct regcache *regcache)
void
regcache_cpy (struct regcache *dst, struct regcache *src)
{
- memcpy (dst->registers, src->registers, register_bytes);
+ gdb_assert (src != NULL && dst != NULL);
+ gdb_assert (src->tdesc == dst->tdesc);
+ gdb_assert (src != dst);
+
+ memcpy (dst->registers, src->registers, src->tdesc->registers_size);
#ifndef IN_PROCESS_AGENT
if (dst->register_status != NULL && src->register_status != NULL)
- memcpy (dst->register_status, src->register_status, num_registers);
+ memcpy (dst->register_status, src->register_status,
+ src->tdesc->num_registers);
#endif
dst->registers_valid = src->registers_valid;
}
-#ifndef IN_PROCESS_AGENT
-static void
-realloc_register_cache (struct inferior_list_entry *thread_p)
-{
- struct thread_info *thread = (struct thread_info *) thread_p;
- struct regcache *regcache
- = (struct regcache *) inferior_regcache_data (thread);
-
- if (regcache != NULL)
- regcache_invalidate_one (thread_p);
- free_register_cache (regcache);
- set_inferior_regcache_data (thread, new_register_cache ());
-}
-#endif
-
-void
-set_register_cache (struct reg *regs, int n)
-{
- int offset, i;
-
-#ifndef IN_PROCESS_AGENT
- /* Before changing the register cache internal layout, flush the
- contents of valid caches back to the threads. */
- regcache_invalidate ();
-#endif
-
- reg_defs = regs;
- num_registers = n;
-
- offset = 0;
- for (i = 0; i < n; i++)
- {
- regs[i].offset = offset;
- offset += regs[i].size;
- }
-
- register_bytes = offset / 8;
-
- /* Make sure PBUFSIZ is large enough to hold a full register packet. */
- if (2 * register_bytes + 32 > PBUFSIZ)
- fatal ("Register packet size exceeds PBUFSIZ.");
-
-#ifndef IN_PROCESS_AGENT
- /* Re-allocate all pre-existing register caches. */
- for_each_inferior (&all_threads, realloc_register_cache);
-#endif
-}
-
-int
-register_cache_size (void)
-{
- return register_bytes;
-}
#ifndef IN_PROCESS_AGENT
@@ -219,21 +199,23 @@ void
registers_to_string (struct regcache *regcache, char *buf)
{
unsigned char *registers = regcache->registers;
+ const struct target_desc *tdesc = regcache->tdesc;
int i;
- for (i = 0; i < num_registers; i++)
+ for (i = 0; i < tdesc->num_registers; i++)
{
if (regcache->register_status[i] == REG_VALID)
{
- convert_int_to_ascii (registers, buf, register_size (i));
- buf += register_size (i) * 2;
+ convert_int_to_ascii (registers, buf,
+ register_size (tdesc, i));
+ buf += register_size (tdesc, i) * 2;
}
else
{
- memset (buf, 'x', register_size (i) * 2);
- buf += register_size (i) * 2;
+ memset (buf, 'x', register_size (tdesc, i) * 2);
+ buf += register_size (tdesc, i) * 2;
}
- registers += register_size (i);
+ registers += register_size (tdesc, i);
}
*buf = '\0';
}
@@ -243,59 +225,97 @@ registers_from_string (struct regcache *regcache, char *buf)
{
int len = strlen (buf);
unsigned char *registers = regcache->registers;
+ const struct target_desc *tdesc = regcache->tdesc;
- if (len != register_bytes * 2)
+ if (len != tdesc->registers_size * 2)
{
warning ("Wrong sized register packet (expected %d bytes, got %d)",
- 2*register_bytes, len);
- if (len > register_bytes * 2)
- len = register_bytes * 2;
+ 2 * tdesc->registers_size, len);
+ if (len > tdesc->registers_size * 2)
+ len = tdesc->registers_size * 2;
}
convert_ascii_to_int (buf, registers, len / 2);
}
struct reg *
-find_register_by_name (const char *name)
+find_register_by_name (const struct target_desc *tdesc, const char *name)
{
int i;
- for (i = 0; i < num_registers; i++)
- if (!strcmp (name, reg_defs[i].name))
- return &reg_defs[i];
+ for (i = 0; i < tdesc->num_registers; i++)
+ if (strcmp (name, tdesc->reg_defs[i].name) == 0)
+ return &tdesc->reg_defs[i];
fatal ("Unknown register %s requested", name);
return 0;
}
int
-find_regno (const char *name)
+find_regno (const struct target_desc *tdesc, const char *name)
{
int i;
- for (i = 0; i < num_registers; i++)
- if (!strcmp (name, reg_defs[i].name))
+ for (i = 0; i < tdesc->num_registers; i++)
+ if (strcmp (name, tdesc->reg_defs[i].name) == 0)
return i;
fatal ("Unknown register %s requested", name);
return -1;
}
struct reg *
-find_register_by_number (int n)
+find_register_by_number (const struct target_desc *tdesc, int n)
{
- return &reg_defs[n];
+ return &tdesc->reg_defs[n];
}
#endif
+#ifndef IN_PROCESS_AGENT
+static void
+free_register_cache_thread (struct thread_info *thread)
+{
+ struct regcache *regcache
+ = (struct regcache *) inferior_regcache_data (thread);
+
+ if (regcache != NULL)
+ {
+ regcache_invalidate_thread (thread);
+ free_register_cache (regcache);
+ set_inferior_regcache_data (thread, NULL);
+ }
+}
+
+static void
+free_register_cache_thread_one (struct inferior_list_entry *entry)
+{
+ struct thread_info *thread = (struct thread_info *) entry;
+
+ free_register_cache_thread (thread);
+}
+
+void
+regcache_release (void)
+{
+ /* Flush and release all pre-existing register caches. */
+ for_each_inferior (&all_threads, free_register_cache_thread_one);
+}
+#endif
+
int
-register_size (int n)
+register_cache_size (const struct target_desc *tdesc)
{
- return reg_defs[n].size / 8;
+ return tdesc->registers_size;
+}
+
+int
+register_size (const struct target_desc *tdesc, int n)
+{
+ return tdesc->reg_defs[n].size / 8;
}
static unsigned char *
register_data (struct regcache *regcache, int n, int fetch)
{
- return regcache->registers + (reg_defs[n].offset / 8);
+ return regcache->registers + regcache->tdesc->reg_defs[n].offset / 8;
}
/* Supply register N, whose contents are stored in BUF, to REGCACHE.
@@ -307,7 +327,8 @@ supply_register (struct regcache *regcache, int n, const void *buf)
{
if (buf)
{
- memcpy (register_data (regcache, n, 0), buf, register_size (n));
+ memcpy (register_data (regcache, n, 0), buf,
+ register_size (regcache->tdesc, n));
#ifndef IN_PROCESS_AGENT
if (regcache->register_status != NULL)
regcache->register_status[n] = REG_VALID;
@@ -315,7 +336,8 @@ supply_register (struct regcache *regcache, int n, const void *buf)
}
else
{
- memset (register_data (regcache, n, 0), 0, register_size (n));
+ memset (register_data (regcache, n, 0), 0,
+ register_size (regcache->tdesc, n));
#ifndef IN_PROCESS_AGENT
if (regcache->register_status != NULL)
regcache->register_status[n] = REG_UNAVAILABLE;
@@ -328,7 +350,8 @@ supply_register (struct regcache *regcache, int n, const void *buf)
void
supply_register_zeroed (struct regcache *regcache, int n)
{
- memset (register_data (regcache, n, 0), 0, register_size (n));
+ memset (register_data (regcache, n, 0), 0,
+ register_size (regcache->tdesc, n));
#ifndef IN_PROCESS_AGENT
if (regcache->register_status != NULL)
regcache->register_status[n] = REG_VALID;
@@ -344,24 +367,28 @@ supply_regblock (struct regcache *regcache, const void *buf)
{
if (buf)
{
- memcpy (regcache->registers, buf, register_bytes);
+ const struct target_desc *tdesc = regcache->tdesc;
+
+ memcpy (regcache->registers, buf, tdesc->registers_size);
#ifndef IN_PROCESS_AGENT
{
int i;
- for (i = 0; i < num_registers; i++)
+ for (i = 0; i < tdesc->num_registers; i++)
regcache->register_status[i] = REG_VALID;
}
#endif
}
else
{
- memset (regcache->registers, 0, register_bytes);
+ const struct target_desc *tdesc = regcache->tdesc;
+
+ memset (regcache->registers, 0, tdesc->registers_size);
#ifndef IN_PROCESS_AGENT
{
int i;
- for (i = 0; i < num_registers; i++)
+ for (i = 0; i < tdesc->num_registers; i++)
regcache->register_status[i] = REG_UNAVAILABLE;
}
#endif
@@ -374,7 +401,7 @@ void
supply_register_by_name (struct regcache *regcache,
const char *name, const void *buf)
{
- supply_register (regcache, find_regno (name), buf);
+ supply_register (regcache, find_regno (regcache->tdesc, name), buf);
}
#endif
@@ -382,7 +409,8 @@ supply_register_by_name (struct regcache *regcache,
void
collect_register (struct regcache *regcache, int n, void *buf)
{
- memcpy (buf, register_data (regcache, n, 1), register_size (n));
+ memcpy (buf, register_data (regcache, n, 1),
+ register_size (regcache->tdesc, n));
}
#ifndef IN_PROCESS_AGENT
@@ -390,15 +418,15 @@ collect_register (struct regcache *regcache, int n, void *buf)
void
collect_register_as_string (struct regcache *regcache, int n, char *buf)
{
- convert_int_to_ascii (register_data (regcache, n, 1),
- buf, register_size (n));
+ convert_int_to_ascii (register_data (regcache, n, 1), buf,
+ register_size (regcache->tdesc, n));
}
void
collect_register_by_name (struct regcache *regcache,
const char *name, void *buf)
{
- collect_register (regcache, find_regno (name), buf);
+ collect_register (regcache, find_regno (regcache->tdesc, name), buf);
}
/* Special handling for register PC. */
diff --git a/gdb/gdbserver/regcache.h b/gdb/gdbserver/regcache.h
index ce86322..48c57a2 100644
--- a/gdb/gdbserver/regcache.h
+++ b/gdb/gdbserver/regcache.h
@@ -21,6 +21,7 @@
struct inferior_list_entry;
struct thread_info;
+struct target_desc;
/* The register exists, it has a value, but we don't know what it is.
Used when inspecting traceframes. */
@@ -35,6 +36,9 @@ struct thread_info;
struct regcache
{
+ /* The regcache's target description. */
+ const struct target_desc *tdesc;
+
/* Whether the REGISTERS buffer's contents are valid. If false, we
haven't fetched the registers from the target yet. Not that this
register cache is _not_ pass-through, unlike GDB's. Note that
@@ -50,13 +54,14 @@ struct regcache
};
struct regcache *init_register_cache (struct regcache *regcache,
+ const struct target_desc *tdesc,
unsigned char *regbuf);
void regcache_cpy (struct regcache *dst, struct regcache *src);
/* Create a new register cache for INFERIOR. */
-struct regcache *new_register_cache (void);
+struct regcache *new_register_cache (const struct target_desc *tdesc);
struct regcache *get_thread_regcache (struct thread_info *thread, int fetch);
@@ -64,11 +69,20 @@ struct regcache *get_thread_regcache (struct thread_info *thread, int fetch);
void free_register_cache (struct regcache *regcache);
-/* Invalidate cached registers for one or all threads. */
+/* Invalidate cached registers for one thread. */
+
+void regcache_invalidate_thread (struct thread_info *);
+
+/* Invalidate cached registers for all threads of the current
+ process. */
-void regcache_invalidate_one (struct inferior_list_entry *);
void regcache_invalidate (void);
+/* Invalidate and release the register cache of all threads of the
+ current process. */
+
+void regcache_release (void);
+
/* Convert all registers to a string in the currently specified remote
format. */
@@ -84,18 +98,13 @@ void regcache_write_pc (struct regcache *regcache, CORE_ADDR pc);
/* Return a pointer to the description of register ``n''. */
-struct reg *find_register_by_number (int n);
-
-int register_size (int n);
+struct reg *find_register_by_number (const struct target_desc *tdesc, int n);
-int register_cache_size (void);
+int register_cache_size (const struct target_desc *tdesc);
-int find_regno (const char *name);
+int register_size (const struct target_desc *tdesc, int n);
-/* The following two variables are set by auto-generated
- code in the init_registers_... routines. */
-extern const char **gdbserver_expedite_regs;
-extern const char *gdbserver_xmltarget;
+int find_regno (const struct target_desc *tdesc, const char *name);
void supply_register (struct regcache *regcache, int n, const void *buf);
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index 42c6a54..3f055cf 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -20,6 +20,7 @@
#include "terminal.h"
#include "target.h"
#include "gdbthread.h"
+#include "tdesc.h"
#include <stdio.h>
#include <string.h>
#if HAVE_SYS_IOCTL_H
@@ -1270,7 +1271,7 @@ outreg (struct regcache *regcache, int regno, char *buf)
*buf++ = tohex (regno & 0xf);
*buf++ = ':';
collect_register_as_string (regcache, regno, buf);
- buf += 2 * register_size (regno);
+ buf += 2 * register_size (regcache->tdesc, regno);
*buf++ = ';';
return buf;
@@ -1328,12 +1329,12 @@ prepare_resume_reply (char *buf, ptid_t ptid,
sprintf (buf, "T%02x", status->value.sig);
buf += strlen (buf);
- regp = gdbserver_expedite_regs;
-
saved_inferior = current_inferior;
current_inferior = find_thread_ptid (ptid);
+ regp = current_target_desc ()->expedite_regs;
+
regcache = get_thread_regcache (current_inferior, 1);
if (the_target->stopped_by_watchpoint != NULL
@@ -1358,7 +1359,7 @@ prepare_resume_reply (char *buf, ptid_t ptid,
while (*regp)
{
- buf = outreg (regcache, find_regno (*regp), buf);
+ buf = outreg (regcache, find_regno (regcache->tdesc, *regp), buf);
regp ++;
}
*buf = '\0';
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 1d1e7b4..4a1d1dc 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -20,6 +20,7 @@
#include "gdbthread.h"
#include "agent.h"
#include "notif.h"
+#include "tdesc.h"
#if HAVE_UNISTD_H
#include <unistd.h>
@@ -76,8 +77,6 @@ int program_signals_p;
jmp_buf toplevel;
-const char *gdbserver_xmltarget;
-
/* The PID of the originally created or attached inferior. Used to
send signals to the process when GDB sends us an asynchronous interrupt
(user hitting Control-C in the client), and to wait for the child to exit
@@ -646,21 +645,22 @@ handle_general_set (char *own_buf)
static const char *
get_features_xml (const char *annex)
{
- /* gdbserver_xmltarget defines what to return when looking
- for the "target.xml" file. Its contents can either be
- verbatim XML code (prefixed with a '@') or else the name
- of the actual XML file to be used in place of "target.xml".
+ const struct target_desc *desc = current_target_desc ();
+
+ /* `desc->xmltarget' defines what to return when looking for the
+ "target.xml" file. Its contents can either be verbatim XML code
+ (prefixed with a '@') or else the name of the actual XML file to
+ be used in place of "target.xml".
This variable is set up from the auto-generated
init_registers_... routine for the current target. */
- if (gdbserver_xmltarget
- && strcmp (annex, "target.xml") == 0)
+ if (desc->xmltarget != NULL && strcmp (annex, "target.xml") == 0)
{
- if (*gdbserver_xmltarget == '@')
- return gdbserver_xmltarget + 1;
+ if (*desc->xmltarget == '@')
+ return desc->xmltarget + 1;
else
- annex = gdbserver_xmltarget;
+ annex = desc->xmltarget;
}
#ifdef USE_XML
@@ -3294,7 +3294,8 @@ process_serial_event (void)
require_running (own_buf);
if (current_traceframe >= 0)
{
- struct regcache *regcache = new_register_cache ();
+ struct regcache *regcache
+ = new_register_cache (current_target_desc ());
if (fetch_traceframe_registers (current_traceframe,
regcache, -1) == 0)
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index 139cd49..18d060c 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -112,6 +112,7 @@ struct inferior_list_entry
struct thread_info;
struct process_info;
struct regcache;
+struct target_desc;
#include "regcache.h"
#include "gdb/signals.h"
@@ -157,6 +158,8 @@ struct process_info
/* The list of installed fast tracepoints. */
struct fast_tracepoint_jump *fast_tracepoint_jumps;
+ const struct target_desc *tdesc;
+
/* Private target data. */
struct process_info_private *private;
};
@@ -431,6 +434,9 @@ void supply_static_tracepoint_registers (struct regcache *regcache,
CORE_ADDR pc);
void set_trampoline_buffer_space (CORE_ADDR begin, CORE_ADDR end,
char *errmsg);
+
+extern const struct target_desc *ipa_tdesc;
+
#else
void stop_tracing (void);
diff --git a/gdb/gdbserver/spu-low.c b/gdb/gdbserver/spu-low.c
index deaa115..6e3974a 100644
--- a/gdb/gdbserver/spu-low.c
+++ b/gdb/gdbserver/spu-low.c
@@ -56,7 +56,7 @@ int using_threads = 0;
/* Defined in auto-generated file reg-spu.c. */
void init_registers_spu (void);
-
+extern const struct target_desc *tdesc_spu;
/* Fetch PPU register REGNO. */
static CORE_ADDR
@@ -266,6 +266,7 @@ spu_create_inferior (char *program, char **allargs)
{
int pid;
ptid_t ptid;
+ struct process_info *proc;
pid = fork ();
if (pid < 0)
@@ -287,7 +288,8 @@ spu_create_inferior (char *program, char **allargs)
_exit (0177);
}
- add_process (pid, 0);
+ proc = add_process (pid, 0);
+ proc->tdesc = tdesc_spu;
ptid = ptid_build (pid, pid, 0);
add_thread (ptid, NULL);
@@ -299,6 +301,7 @@ int
spu_attach (unsigned long pid)
{
ptid_t ptid;
+ struct process_info *proc;
if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
{
@@ -308,7 +311,8 @@ spu_attach (unsigned long pid)
_exit (0177);
}
- add_process (pid, 1);
+ proc = add_process (pid, 1);
+ proc->tdesc = tdesc_spu;
ptid = ptid_build (pid, pid, 0);
add_thread (ptid, NULL);
return 0;
diff --git a/gdb/gdbserver/tdesc.c b/gdb/gdbserver/tdesc.c
new file mode 100644
index 0000000..ac3c14a
--- /dev/null
+++ b/gdb/gdbserver/tdesc.c
@@ -0,0 +1,66 @@
+/* Copyright (C) 2012-2013 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "server.h"
+#include "tdesc.h"
+#include "regdef.h"
+
+void
+init_target_desc (struct target_desc *tdesc)
+{
+ int offset, i;
+
+ offset = 0;
+ for (i = 0; i < tdesc->num_registers; i++)
+ {
+ tdesc->reg_defs[i].offset = offset;
+ offset += tdesc->reg_defs[i].size;
+ }
+
+ tdesc->registers_size = offset / 8;
+
+ /* Make sure PBUFSIZ is large enough to hold a full register
+ packet. */
+ if (2 * tdesc->registers_size + 32 > PBUFSIZ)
+ fatal ("Register packet size exceeds PBUFSIZ.");
+}
+
+#ifndef IN_PROCESS_AGENT
+
+static const struct target_desc default_description;
+
+void
+copy_target_description (struct target_desc *dest,
+ const struct target_desc *src)
+{
+ dest->reg_defs = src->reg_defs;
+ dest->num_registers = src->num_registers;
+ dest->expedite_regs = src->expedite_regs;
+ dest->registers_size = src->registers_size;
+ dest->xmltarget = src->xmltarget;
+}
+
+const struct target_desc *
+current_target_desc (void)
+{
+ if (current_inferior == NULL)
+ return &default_description;
+
+ return current_process ()->tdesc;
+}
+
+#endif
diff --git a/gdb/gdbserver/tdesc.h b/gdb/gdbserver/tdesc.h
new file mode 100644
index 0000000..f3d018d
--- /dev/null
+++ b/gdb/gdbserver/tdesc.h
@@ -0,0 +1,64 @@
+/* Target description definitions for remote server for GDB.
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef TDESC_H
+#define TDESC_H
+
+struct reg;
+
+/* A target description. */
+
+struct target_desc
+{
+ /* An array of NUM_REGISTERS elements of register definitions that
+ describe the inferior's register set. */
+ struct reg *reg_defs;
+
+ /* The number of registers in inferior's register set (and thus in
+ the regcache). */
+ int num_registers;
+
+ /* The register cache size, in bytes. */
+ int registers_size;
+
+ /* An array of register names. These are the "expedite" registers:
+ registers whose values are sent along with stop replies. */
+ const char **expedite_regs;
+
+ /* Defines what to return when looking for the "target.xml" file in
+ response to qXfer:features:read. Its contents can either be
+ verbatim XML code (prefixed with a '@') or else the name of the
+ actual XML file to be used in place of "target.xml". */
+ const char *xmltarget;
+};
+
+/* Copy target description SRC to DEST. */
+
+void copy_target_description (struct target_desc *dest,
+ const struct target_desc *src);
+
+/* Initialize TDESC. */
+
+void init_target_desc (struct target_desc *tdesc);
+
+/* Return the current inferior's target description. Never returns
+ NULL. */
+
+const struct target_desc *current_target_desc (void);
+
+#endif /* TDESC_H */
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index 1ff6114..d237e7f 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -29,6 +29,7 @@
#include <stdint.h>
#include "ax.h"
+#include "tdesc.h"
#define DEFAULT_TRACE_BUFFER_SIZE 5242880 /* 5*1024*1024 */
@@ -4675,6 +4676,14 @@ collect_data_at_step (struct tracepoint_hit_ctx *ctx,
#endif
+#ifdef IN_PROCESS_AGENT
+/* The target description used by the IPA. Given that the IPA library
+ is built for a specific architecture that is loaded into the
+ inferior, there only needs to be one such description per
+ build. */
+const struct target_desc *ipa_tdesc;
+#endif
+
static struct regcache *
get_context_regcache (struct tracepoint_hit_ctx *ctx)
{
@@ -4687,7 +4696,7 @@ get_context_regcache (struct tracepoint_hit_ctx *ctx)
if (!fctx->regcache_initted)
{
fctx->regcache_initted = 1;
- init_register_cache (&fctx->regcache, fctx->regspace);
+ init_register_cache (&fctx->regcache, ipa_tdesc, fctx->regspace);
supply_regblock (&fctx->regcache, NULL);
supply_fast_tracepoint_registers (&fctx->regcache, fctx->regs);
}
@@ -4702,7 +4711,7 @@ get_context_regcache (struct tracepoint_hit_ctx *ctx)
if (!sctx->regcache_initted)
{
sctx->regcache_initted = 1;
- init_register_cache (&sctx->regcache, sctx->regspace);
+ init_register_cache (&sctx->regcache, ipa_tdesc, sctx->regspace);
supply_regblock (&sctx->regcache, NULL);
/* Pass down the tracepoint address, because REGS doesn't
include the PC, but we know what it must have been. */
@@ -4761,13 +4770,15 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
unsigned char *regspace;
struct regcache tregcache;
struct regcache *context_regcache;
-
+ int regcache_size;
trace_debug ("Want to collect registers");
+ context_regcache = get_context_regcache (ctx);
+ regcache_size = register_cache_size (context_regcache->tdesc);
+
/* Collect all registers for now. */
- regspace = add_traceframe_block (tframe, tpoint,
- 1 + register_cache_size ());
+ regspace = add_traceframe_block (tframe, tpoint, 1 + regcache_size);
if (regspace == NULL)
{
trace_debug ("Trace buffer block allocation failed, skipping");
@@ -4776,11 +4787,10 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
/* Identify a register block. */
*regspace = 'R';
- context_regcache = get_context_regcache (ctx);
-
/* Wrap the regblock in a register cache (in the stack, we
don't want to malloc here). */
- init_register_cache (&tregcache, regspace + 1);
+ init_register_cache (&tregcache, context_regcache->tdesc,
+ regspace + 1);
/* Copy the register data to the regblock. */
regcache_cpy (&tregcache, context_regcache);
@@ -5083,7 +5093,7 @@ traceframe_walk_blocks (unsigned char *database, unsigned int datasize,
{
case 'R':
/* Skip over the registers block. */
- dataptr += register_cache_size ();
+ dataptr += current_target_desc ()->registers_size;
break;
case 'M':
/* Skip over the memory block. */
@@ -5178,12 +5188,13 @@ traceframe_get_pc (struct traceframe *tframe)
{
struct regcache regcache;
unsigned char *dataptr;
+ const struct target_desc *tdesc = current_target_desc ();
dataptr = traceframe_find_regblock (tframe, -1);
if (dataptr == NULL)
return 0;
- init_register_cache (&regcache, dataptr);
+ init_register_cache (&regcache, tdesc, dataptr);
return regcache_read_pc (&regcache);
}
@@ -5737,7 +5748,7 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs)
ctx.regcache_initted = 0;
/* Wrap the regblock in a register cache (in the stack, we don't
want to malloc here). */
- ctx.regspace = alloca (register_cache_size ());
+ ctx.regspace = alloca (ipa_tdesc->registers_size);
if (ctx.regspace == NULL)
{
trace_debug ("Trace buffer block allocation failed, skipping");
@@ -6597,7 +6608,7 @@ gdb_probe (const struct marker *mdata, void *probe_private,
/* Wrap the regblock in a register cache (in the stack, we don't
want to malloc here). */
- ctx.regspace = alloca (register_cache_size ());
+ ctx.regspace = alloca (ipa_tdesc->registers_size);
if (ctx.regspace == NULL)
{
trace_debug ("Trace buffer block allocation failed, skipping");
diff --git a/gdb/gdbserver/win32-arm-low.c b/gdb/gdbserver/win32-arm-low.c
index 09ac1da..0f93ef0 100644
--- a/gdb/gdbserver/win32-arm-low.c
+++ b/gdb/gdbserver/win32-arm-low.c
@@ -24,7 +24,7 @@
/* Defined in auto-generated file reg-arm.c. */
void init_registers_arm (void);
-
+extern const struct target_desc *tdesc_arm;
static void
arm_get_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event)
@@ -108,12 +108,19 @@ arm_store_inferior_register (struct regcache *regcache,
collect_register (regcache, r, regptr (&th->context, r));
}
+static void
+arm_arch_setup (void)
+{
+ init_registers_arm ();
+ win32_tdesc = tdesc_arm;
+}
+
/* Correct in either endianness. We do not support Thumb yet. */
static const unsigned long arm_wince_breakpoint = 0xe6000010;
#define arm_wince_breakpoint_len 4
struct win32_target_ops the_low_target = {
- init_registers_arm,
+ arm_arch_setup,
sizeof (mappings) / sizeof (mappings[0]),
NULL, /* initial_stuff */
arm_get_thread_context,
diff --git a/gdb/gdbserver/win32-i386-low.c b/gdb/gdbserver/win32-i386-low.c
index 1db9393..049e8a2 100644
--- a/gdb/gdbserver/win32-i386-low.c
+++ b/gdb/gdbserver/win32-i386-low.c
@@ -31,9 +31,11 @@
#ifdef __x86_64__
/* Defined in auto-generated file reg-amd64.c. */
void init_registers_amd64 (void);
+extern const struct target_desc *tdesc_amd64;
#else
/* Defined in auto-generated file reg-i386.c. */
void init_registers_i386 (void);
+extern const struct target_desc *tdesc_i386;
#endif
static struct i386_debug_reg_state debug_reg_state;
@@ -399,17 +401,19 @@ static const unsigned char i386_win32_breakpoint = 0xcc;
#define i386_win32_breakpoint_len 1
static void
-init_windows_x86 (void)
+i386_arch_setup (void)
{
#ifdef __x86_64__
init_registers_amd64 ();
+ win32_tdesc = tdesc_amd64;
#else
init_registers_i386 ();
+ win32_tdesc = tdesc_i386;
#endif
}
struct win32_target_ops the_low_target = {
- init_windows_x86,
+ i386_arch_setup,
sizeof (mappings) / sizeof (mappings[0]),
i386_initial_stuff,
i386_get_thread_context,
diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index 2cb5465..d1caa73 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -87,6 +87,8 @@ static int soft_interrupt_requested = 0;
by suspending all the threads. */
static int faked_breakpoint = 0;
+const struct target_desc *win32_tdesc;
+
#define NUM_REGS (the_low_target.num_regs)
typedef BOOL WINAPI (*winapi_DebugActiveProcessStop) (DWORD dwProcessId);
@@ -193,9 +195,6 @@ child_add_thread (DWORD pid, DWORD tid, HANDLE h, void *tlb)
th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
add_thread (ptid, th);
- set_inferior_regcache_data ((struct thread_info *)
- find_inferior_id (&all_threads, ptid),
- new_register_cache ());
if (the_low_target.thread_added != NULL)
(*the_low_target.thread_added) (th);
@@ -308,6 +307,8 @@ child_init_thread_list (void)
static void
do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
{
+ struct process_info *proc;
+
last_sig = GDB_SIGNAL_0;
current_process_handle = proch;
@@ -319,7 +320,8 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
memset (&current_event, 0, sizeof (current_event));
- add_process (pid, attached);
+ proc = add_process (pid, attached);
+ proc->tdesc = win32_tdesc;
child_init_thread_list ();
if (the_low_target.initial_stuff != NULL)
diff --git a/gdb/gdbserver/win32-low.h b/gdb/gdbserver/win32-low.h
index 4f262c2..718362e 100644
--- a/gdb/gdbserver/win32-low.h
+++ b/gdb/gdbserver/win32-low.h
@@ -18,6 +18,12 @@
#include <windows.h>
+struct target_desc;
+
+/* The inferior's target description. This is a global because the
+ Windows ports support neither bi-arch nor multi-process. */
+extern const struct target_desc *win32_tdesc;
+
/* Thread information structure used to track extra information about
each thread. */
typedef struct win32_thread_info
diff --git a/gdb/regformats/regdat.sh b/gdb/regformats/regdat.sh
index be4e01e..6256125 100755
--- a/gdb/regformats/regdat.sh
+++ b/gdb/regformats/regdat.sh
@@ -121,6 +121,7 @@ exec > new-$2
copyright $1
echo '#include "server.h"'
echo '#include "regdef.h"'
+echo '#include "tdesc.h"'
echo
offset=0
i=0
@@ -134,7 +135,7 @@ while do_read
do
if test "${type}" = "name"; then
name="${entry}"
- echo "struct reg regs_${name}[] = {"
+ echo "static struct reg regs_${name}[] = {"
continue
elif test "${type}" = "xmltarget"; then
xmltarget="${entry}"
@@ -160,12 +161,12 @@ done
echo "};"
echo
-echo "const char *expedite_regs_${name}[] = { \"`echo ${expedite} | sed 's/,/", "/g'`\", 0 };"
+echo "static const char *expedite_regs_${name}[] = { \"`echo ${expedite} | sed 's/,/", "/g'`\", 0 };"
if test "${xmltarget}" = x; then
if test "${xmlarch}" = x && test "${xmlosabi}" = x; then
- echo "const char *xmltarget_${name} = 0;"
+ echo "static const char *xmltarget_${name} = 0;"
else
- echo "const char *xmltarget_${name} = \"@<target>\\"
+ echo "static const char *xmltarget_${name} = \"@<target>\\"
if test "${xmlarch}" != x; then
echo "<architecture>${xmlarch}</architecture>\\"
fi
@@ -175,18 +176,27 @@ if test "${xmltarget}" = x; then
echo "</target>\";"
fi
else
- echo "const char *xmltarget_${name} = \"${xmltarget}\";"
+ echo "static const char *xmltarget_${name} = \"${xmltarget}\";"
fi
echo
cat <<EOF
+const struct target_desc *tdesc_${name};
+
void
-init_registers_${name} ()
+init_registers_${name} (void)
{
- set_register_cache (regs_${name},
- sizeof (regs_${name}) / sizeof (regs_${name}[0]));
- gdbserver_expedite_regs = expedite_regs_${name};
- gdbserver_xmltarget = xmltarget_${name};
+ static struct target_desc tdesc_${name}_s;
+ struct target_desc *result = &tdesc_${name}_s;
+
+ result->reg_defs = regs_${name};
+ result->num_registers = sizeof (regs_${name}) / sizeof (regs_${name}[0]);
+ result->expedite_regs = expedite_regs_${name};
+ result->xmltarget = xmltarget_${name};
+
+ init_target_desc (result);
+
+ tdesc_${name} = result;
}
EOF