[GDBserver] Multi-process + multi-arch

This patch makes GDBserver support multi-process + biarch.

Currently, if you're debugging more than one process at once with a
single gdbserver (in extended-remote mode), then all processes must
have the same architecture (e.g., 64-bit vs 32-bit).  Otherwise, you
see this:

Added inferior 2
[Switching to inferior 2 [<null>] (<noexec>)]
Reading symbols from /home/pedro/gdb/tests/main32...done.
Temporary breakpoint 2 at 0x4004cf: main. (2 locations)
Starting program: /home/pedro/gdb/tests/main32
warning: Selected architecture i386 is not compatible with reported target architecture i386:x86-64
warning: Architecture rejected target-supplied description
Remote 'g' packet reply is too long: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090cfffff0000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000b042f7460000000000020000230000002b0000002b0000002b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f03000000000000ffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f00003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
... etc, etc ...

Even though the process was running a 32-bit program, GDBserver sent
back to GDB a register set in 64-bit layout.

A patch (http://sourceware.org/ml/gdb-patches/2012-11/msg00228.html) a
while ago made GDB track a target_gdbarch per inferior, and as
consequence, fetch a target description per-inferior.  This patch is
the GDBserver counterpart, that makes GDBserver keep track of each
process'es XML target description and register layout.  So in the
example above, GDBserver will send the correct register set in 32-bit
layout to GDB.

A new "struct target_desc" object (tdesc for short) is added, that
holds the target description and register layout information about
each process.  Each `struct process_info' holds a pointer to a target
description.  The regcache also gains a pointer to a target
description, mainly for convenience, and parallel with GDB (and
possible future support for programs that flip processor modes).

The low target's arch_setup routines are responsible for setting the
process'es correct tdesc.  This isn't that much different to how
things were done before, except that instead of detecting the inferior
process'es architecture and calling the corresponding
init_registers_FOO routine, which would change the regcache layout
globals and recreate the threads' regcaches, the regcache.c globals
are gone, and the init_registers_$BAR routines now each initialize a
separate global struct target_desc object (one for each arch variant
GDBserver supports), and so all the init_registers_$BAR routines that
are built into GDBserver are called early at GDBserver startup time
(similarly to how GDB handles its built-in target descriptions), and
then the arch_setup routine is responsible for making
process_info->tdesc point to one of these target description globals.
The regcache module is all parameterized to get the regcache's layout
from the tdesc object instead of the old register_bytes, etc. globals.

The threads' regcaches are now created lazily.  The old scheme where
we created each of them when we added a new thread doesn't work
anymore, because we add the main thread/lwp before we see it stop for
the first time, and it is only when we see the thread stop for the
first time that we have a chance of determining the inferior's
architecture (through the_low_target.arch_setup).  Therefore when we
add the main thread we don't know which architecture/tdesc its
regcache should have.

This patch makes the gdb.multi/multi-arch.exp test now pass against
(extended-remote) GDBserver.  It currently fails, without this patch.

The IPA also uses the regcache, so it gains a new global struct
target_desc pointer, which points at the description of the process it
is loaded in.

Re. the linux-low.c & friends changes.  Since the register map
etc. may differ between processes (64-bit vs 32-bit) etc., the
linux_target_ops num_regs, regmap and regset_bitmap data fields are no
longer sufficient.  A new method is added in their place that returns
a pointer to a new struct that includes all info linux-low.c needs to
access registers of the current inferior.

The patch/discussion that originally introduced
linux-low.c:disabled_regsets mentions that the disabled_regsets set
may be different per mode (in a biarch setup), and indeed that is
cleared whenever we start a new (first) inferior, so that global is
moved as well behind the new `struct regs_info'.

On the x86 side:

I simply replaced the i387-fp.c:num_xmm_registers global with a check
for 64-bit or 32-bit process, which is equivalent to how the global
was set.  This avoided coming up with some more general mechanism that
would work for all targets that use this module (GNU/Linux, Windows,
etc.).

Tested:

  GNU/Linux IA64
  GNU/Linux MIPS64
  GNU/Linux PowerPC (Fedora 16)
  GNU/Linux s390x (Fedora 16)
  GNU/Linux sparc64 (Debian)
  GNU/Linux x86_64, -m64 and -m32 (Fedora 17)

Cross built, and smoke tested:

  i686-w64-mingw32, under Wine.
  GNU/Linux TI C6x, by Yao Qi.

Cross built but otherwise not tested:

  aarch64-linux-gnu
  arm-linux-gnu
  m68k-linux
  nios2-linux-gnu
  sh-linux-gnu
  spu
  tilegx-unknown-linux-gnu

Completely untested:

  GNU/Linux Blackfin
  GNU/Linux CRIS
  GNU/Linux CRISv32
  GNU/Linux TI Xtensa
  GNU/Linux M32R
  LynxOS
  QNX NTO

gdb/gdbserver/
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'.

gdb/
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.
This commit is contained in:
Pedro Alves 2013-06-07 10:46:59 +00:00
parent 88ab56844a
commit 3aee891821
51 changed files with 2363 additions and 731 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -46,9 +46,59 @@ 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
{
/* Arch-specific additions. */
@ -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 *);

View File

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

View File

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

View File

@ -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 ("status"), regset + 36);
find_regno (regcache->tdesc, "hi"), regset + 33);
mips_supply_register (regcache, use_64bit,
find_regno ("cause"), regset + 37);
find_regno (regcache->tdesc, "pc"), regset + 34);
mips_supply_register (regcache, use_64bit,
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);
}

View File

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

View File

@ -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)
{
init_registers_powerpc_e500l ();
the_low_target.regmap = ppc_regmap_e500;
}
tdesc = tdesc_powerpc_e500l;
/* 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 (!ppc_regmap_adjusted)
{
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 (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);
}

View File

@ -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)
{
if (have_regset_system_call)
init_registers_s390_linux64v2 ();
else if (have_regset_last_break)
init_registers_s390_linux64v1 ();
else
init_registers_s390_linux64 ();
have_hwcap_s390_high_gprs = 1;
the_low_target.num_regs = s390_num_regs_3264;
the_low_target.regmap = s390_regmap_3264;
if (have_regset_system_call)
tdesc = tdesc_s390_linux64v2;
else if (have_regset_last_break)
tdesc = tdesc_s390_linux64v1;
else
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
}

View File

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

View File

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

View File

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

View File

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

View File

@ -30,21 +30,43 @@
#include "gdb_proc_service.h"
#include "agent.h"
#include "tdesc.h"
#ifdef __x86_64__
/* Defined in auto-generated file amd64-linux.c. */
void init_registers_amd64_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);
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);
/* 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);
/* Defined in auto-generated file amd64-avx-linux.c. */
void init_registers_amd64_avx_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);
/* Defined in auto-generated file x32-linux.c. */
void init_registers_x32_linux (void);
/* Defined in auto-generated file x32-avx-linux.c. */
void init_registers_x32_avx_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
};
static void
x86_linux_update_xmltarget (void)
{
int pid;
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
Same memory layout will be used for the coredump NT_X86_XSTATE
representing the XSAVE extended state registers.
if (!current_inferior)
return;
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
/* 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 ();
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 ();
/* 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
;
/* 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)
{
unsigned int machine;
int is_elf64;
int avx;
int tid;
static uint64_t xcr0;
struct regset_info *regset;
tid = lwpid_of (get_thread_lwp (current_inferior));
is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine);
if (sizeof (void *) == 4)
{
# ifdef HAVE_PTRACE_GETFPXREGS
if (have_ptrace_getfpxregs == -1)
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 !defined __x86_64__ && defined HAVE_PTRACE_GETFPXREGS
if (machine == EM_386 && have_ptrace_getfpxregs == -1)
{
elf_fpxregset_t fpxregs;
if (ptrace (PTRACE_GETFPXREGS, tid, 0, (long) &fpxregs) < 0)
{
elf_fpxregset_t fpxregs;
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;
have_ptrace_getfpxregs = 0;
have_ptrace_getregset = 0;
return tdesc_i386_mmx_linux;
}
if (!have_ptrace_getfpxregs)
{
init_registers_i386_mmx_linux ();
return;
}
# endif
init_registers_i386_linux ();
else
have_ptrace_getfpxregs = 1;
}
#endif
if (!use_xml)
{
/* Don't use XML. */
#ifdef __x86_64__
if (num_xmm_registers == 8)
gdbserver_xmltarget = xmltarget_i386_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;
/* Don't use XML. */
#ifdef __x86_64__
if (machine == EM_X86_64)
return tdesc_amd64_linux_no_xml;
else
#endif
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;
}
}
/* 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__
if (avx)
{
if (!is_elf64)
return tdesc_x32_avx_linux;
else
return tdesc_amd64_avx_linux;
}
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;
#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 (!is_elf64)
return tdesc_x32_linux;
else
init_registers_x32_avx_linux ();
#else
init_registers_i386_avx_linux ();
#endif
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 struct regsets_info x86_regsets_info =
{
x86_regsets, /* regsets */
0, /* num_regsets */
NULL, /* disabled_regsets */
};
#ifdef __x86_64__
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,
};
static struct regs_info i386_linux_regs_info =
{
NULL, /* regset_bitmap */
&i386_linux_usrregs_info,
&x86_regsets_info
};
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;
}
/* Initialize the target description for the architecture of the
inferior. */
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
}
#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;
#endif
/* Ok we have a 32-bit inferior. */
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;
/* I386 has 8 xmm regs. */
num_xmm_registers = 8;
x86_linux_update_xmltarget ();
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);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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
int
register_size (int n)
#ifndef IN_PROCESS_AGENT
static void
free_register_cache_thread (struct thread_info *thread)
{
return reg_defs[n].size / 8;
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_cache_size (const struct target_desc *tdesc)
{
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. */

View File

@ -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);
struct reg *find_register_by_number (const struct target_desc *tdesc, int n);
int register_size (int n);
int register_cache_size (const struct target_desc *tdesc);
int register_cache_size (void);
int register_size (const struct target_desc *tdesc, int n);
int find_regno (const char *name);
/* 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);

View File

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

View File

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

View File

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

View File

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

66
gdb/gdbserver/tdesc.c Normal file
View File

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

64
gdb/gdbserver/tdesc.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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